TPM: I can't perform RSA encryption/decryption with persistent key, using encryption session

621 views Asked by At

Description of the situation by steps:

  1. I start encryption/decryption sessions
  2. I create primary RSA key
  3. I make key object persistent
  4. I try to encrypt data, using persistent key handle

Sample of my code below:

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

// 1) Starting decryption / encryption sessions

AUTH_SESSION sess = tpm.StartAuthSession(TPM_SE::HMAC, TPM_ALG_ID::SHA256,
    TPMA_SESSION::continueSession | TPMA_SESSION::decrypt,
    TPMT_SYM_DEF(TPM_ALG_ID::AES, 128, TPM_ALG_ID::CFB));

AUTH_SESSION encSess = tpm.StartAuthSession(TPM_SE::HMAC, TPM_ALG_ID::SHA1,
    TPMA_SESSION::continueSession | TPMA_SESSION::encrypt,
    TPMT_SYM_DEF(TPM_ALG_ID::AES, 128, TPM_ALG_ID::CFB));

// 2) Creating primary RSA key

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());

auto storagePrimary = tpm[sess].CreatePrimary(TPM_RH::OWNER, null, primTempl, null, null);

// 3) Making this key object persistent

TPM_HANDLE& keyHandle = storagePrimary.handle;

TPM_HANDLE persistentHandle = TPM_HANDLE::Persistent(1000);

ByteVec name = { 1, 2, 3, 4 };
persistentHandle.SetName(name);

tpm._AllowErrors().EvictControl(TPM_RH::OWNER, persistentHandle, persistentHandle);

tpm.EvictControl(TPM_RH::OWNER, storagePrimary.handle, persistentHandle);

tpm.FlushContext(storagePrimary.handle);

// 4) Trying to encrypt data with persistent RSA key

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

This row leads to error TPM_RC::BAD_AUTH. What am I doing wrong?

auto enc = tpm[sess].RSA_Encrypt(persistentHandle, dataToEncrypt, TPMS_NULL_ASYM_SCHEME(), null);

When I perform encryption with not persistent key handle, using encryption session, everything works fine.

auto enc = tpm[sess].RSA_Encrypt(keyHandle, dataToEncrypt, TPMS_NULL_ASYM_SCHEME(), null);
1

There are 1 answers

0
帅是理 On

I Think ,you maybe not set auth.

maybe try to set the auth: like follow this:

  void Samples::Test_PransentKeyIntoNv()
{
    TPMT_PUBLIC stParentPublicTmp(TPM_ALG_ID::SHA1,          // Key nameAlg
                                  TPMA_OBJECT::decrypt | TPMA_OBJECT::restricted | TPMA_OBJECT::userWithAuth
                                  | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM | TPMA_OBJECT::sensitiveDataOrigin,
                                  null,                   // No policy
                                  // Key-parms: How child keys should be protected
                                  TPMS_RSA_PARMS(Aes128Cfb,
                                          TPMS_NULL_ASYM_SCHEME(),
                                          2048,
                                          65537),
                                  TPM2B_PUBLIC_KEY_RSA());

    // Set the use-auth for the next key. Note the second parameter is
    // NULL because we are asking the TPM to create a new key.
    ByteVec userAuth = { 1, 2, 3, 4 };
    TPMS_SENSITIVE_CREATE sensCreate(userAuth, null);

    // Create the key (no PCR-state captured)
    auto storagePrimary = tpm.CreatePrimary(TPM_RH::OWNER, sensCreate, stParentPublicTmp, null, null);

    // Note that if we want to use the storage key handle we need the userAuth, as specified above.
    // TSS.C++ sets this when it can, but this is what you have to do if it has not been auto-set.
    storagePrimary.handle.SetAuth(userAuth);


    TPMT_PUBLIC stChildKeyPublicTmp(TPM_ALG_ID::SHA1,
                                    TPMA_OBJECT::decrypt | TPMA_OBJECT::sign | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM
                                    | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth,
                                    null,                                   // No policy
                                    TPMS_RSA_PARMS(null,
                                            TPMS_NULL_ASYM_SCHEME(),
                                            2048,
                                            65537),
                                    TPM2B_PUBLIC_KEY_RSA());
    auto newSigKey = tpm.Create(storagePrimary.handle, sensCreate, stChildKeyPublicTmp, null, null);

    TPM_HANDLE signKey = tpm.Load(storagePrimary.handle, newSigKey.outPrivate, newSigKey.outPublic);
    signKey.SetAuth(userAuth);


    // We can put the primary key into NV with EvictControl
    TPM_HANDLE persistentHandle = TPM_HANDLE::Persistent(0);
    // First delete anything that might already be there
    tpm._AllowErrors().EvictControl(TPM_RH::OWNER, persistentHandle, persistentHandle);
    // Make our primary persistent
    tpm.EvictControl(TPM_RH::OWNER, signKey, persistentHandle);
    // Flush the old one
    tpm.FlushContext(signKey);
    if (tpm._LastCommandSucceeded())
    {
        cout << "Success, handle: " << persistentHandle.ToString().c_str();
    }
    // ReadPublic of the new persistent one
    auto persistentPub = tpm.ReadPublic(persistentHandle);
    cout << "Public part of persistent primary" << endl << persistentPub.ToString(false);
}

void Samples::Test_UsingExistKeyFromNv()
{
    TPM_HANDLE keyHandle = TPM_HANDLE::Persistent(0);
    ByteVec userAuth = { 1, 2, 3, 4 };
    keyHandle.SetAuth(userAuth);

    auto key = tpm.ReadPublic(keyHandle);
    cout << "Public part of persistent primary" << endl << key.ToString(false);

    TPMT_PUBLIC stPublic = key.outPublic;

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

    auto enc = tpm._AllowErrors().RSA_Encrypt(keyHandle, dataToEncrypt, TPMS_SCHEME_OAEP(TPM_ALG_ID::SHA256), null);
    if (tpm._LastCommandSucceeded())
    {
        cout << "RSA-encrypted data: " << enc << "\n" << endl;
    }
    else
    {
        cout << "RSA-encrypted data: " << tpm._GetLastResponseCode() << "\n" << endl;
    }

    auto dec = tpm._AllowErrors().RSA_Decrypt(keyHandle, enc, TPMS_SCHEME_OAEP(TPM_ALG_ID::SHA256), null);
    if (tpm._LastCommandSucceeded())
    {
        cout << "decrypted data: " << dec << "\n" << endl;
    }
    else
    {
        cout << "RSA-encrypted data: error code =" << tpm._GetLastResponseCode() << "\n" << endl;
    }
}