Public key encryption on TPM2 using TSS.NET

Viewed 967

Is it possible to implement public key encryption in a .Net application using a TPM2 and the TSS.NET library by microsoft? To be more specific, the part that should be done in the TPM is the decryption using the private key and therefore the public key should be able to be exported to other machines. Additionally the keys should be stored in the TPM2 module.

I studied/worked through the examples by Microsoft and read the documentation, but I did not find information on that topic or or I missed it somehow.

To store data in the TPM2, I found nv memory, but as far as I understand, this is used to store data from outside the TPM2 module in it, but I don't know if/how it is possible to store some kind of keys from inside the TPM2 module in its nv memory to be used at next boot again.

1 Answers

There does not seem to exist sample code for C# (yet) however there is some sample C++ code that demonstrates what you want:

void Samples::RsaEncryptDecrypt()
{
    Announce("RsaEncryptDecrypt");

    // This sample demostrates the use of the TPM for RSA operations.

    // We will make a key in the "null hierarchy".
    TPMT_PUBLIC primTempl(TPM_ALG_ID::SHA1,
                          TPMA_OBJECT::decrypt | TPMA_OBJECT::userWithAuth | TPMA_OBJECT::sensitiveDataOrigin,
                          null,  // No policy
                          TPMS_RSA_PARMS(null, TPMS_SCHEME_OAEP(TPM_ALG_ID::SHA1), 2048, 65537),
                          TPM2B_PUBLIC_KEY_RSA());

    // Create the key
    auto storagePrimary = tpm.CreatePrimary(TPM_RH_NULL, null, primTempl, null, null);

    TPM_HANDLE& keyHandle = storagePrimary.handle;

    ByteVec dataToEncrypt = TPM_HASH::FromHashOfString(TPM_ALG_ID::SHA1, "secret");
    cout << "Data to encrypt: " << dataToEncrypt << endl;

    auto enc = tpm.RSA_Encrypt(keyHandle, dataToEncrypt, TPMS_NULL_ASYM_SCHEME(), null);
    cout << "RSA-encrypted data: " << enc << endl;

    auto dec = tpm.RSA_Decrypt(keyHandle, enc, TPMS_NULL_ASYM_SCHEME(), null);
    cout << "decrypted data: " << dec << endl;
    if (dec == dataToEncrypt)
        cout << "Decryption worked" << endl;
    _ASSERT(dataToEncrypt == dec);

    // Now encrypt using TSS.C++ library functions
    ByteVec mySecret = tpm._GetRandLocal(20);
    enc = storagePrimary.outPublic.Encrypt(mySecret, null);
    dec = tpm.RSA_Decrypt(keyHandle, enc, TPMS_NULL_ASYM_SCHEME(), null);
    cout << "My           secret: " << mySecret << endl;
    cout << "My decrypted secret: " << dec << endl;
    _ASSERT(mySecret == dec);

    // Now with padding
    ByteVec pad { 1, 2, 3, 4, 5, 6, 0 };
    enc = storagePrimary.outPublic.Encrypt(mySecret, pad);
    dec = tpm.RSA_Decrypt(keyHandle, enc, TPMS_NULL_ASYM_SCHEME(), pad);
    cout << "My           secret: " << mySecret << endl;
    cout << "My decrypted secret: " << dec << endl;
    _ASSERT(mySecret == dec);

    tpm.FlushContext(keyHandle);
} // RsaEncryptDecrypt()

Of course instead of creating a new primary key you would probably want to use the SRK or a child key.

Related