Prakhar314 / TPM-Timing-Analysis

1 stars 2 forks source link

Can't perform AES encryption in context of session #2

Open alexey3nemckovich opened 2 years ago

alexey3nemckovich commented 2 years ago

Hello, @Prakhar314 and @sicario001 . Your project is really useful to dive into TPM2 API, it has a really lot of nice samples. But maybe you could help to understand what i am doing wrong here. I want to create a session for encrypting/decrypting tpm commands and responses. And in context of this session create aes key, make it persistent and perform some encryption/decryption with it. But unfortunately that doesn't work. Could you help me to figure it out? Here is sample code of how I am trying to do it.

// Session encryption is essentially transparent to the application programmer.
// All that is needed is to create a session with the necessary characteristics and
// TSS.C++ adds all necessary parameter encryption and decryption.

// At the time of writing only unseeded and unbound session enc and dec are supported.
// First set up a session that encrypts communications TO the TPM. To do this
// we tell the TPM to decrypt via TPMA_SESSION::decrypt.
AUTH_SESSION sess = tpm.StartAuthSession(TPM_SE::HMAC, TPM_ALG_ID::SHA1,
    TPMA_SESSION::continueSession | TPMA_SESSION::decrypt,
    TPMT_SYM_DEF(TPM_ALG_ID::AES, 128, TPM_ALG_ID::CFB));

Announce("EncryptDecryptSample");

TPM_HANDLE prim = MakeStoragePrimary(&sess);

// Make an AES key
TPMT_PUBLIC inPublic(TPM_ALG_ID::SHA256,
    TPMA_OBJECT::decrypt | TPMA_OBJECT::sign | TPMA_OBJECT::userWithAuth
    | TPMA_OBJECT::sensitiveDataOrigin,
    null,
    TPMS_SYMCIPHER_PARMS(Aes256Cfb),
    TPM2B_DIGEST_SYMCIPHER());

// Set the use-auth for the nex 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);

auto aesKey = tpm[sess].Create(prim, sensCreate, inPublic, null, null);

TPM_HANDLE aesHandle = tpm[sess].Load(prim, aesKey.outPrivate, aesKey.outPublic);

TPM_HANDLE& keyHandle = aesHandle;

// We can put the primary key into NV with EvictControl
TPM_HANDLE persistentHandle = TPM_HANDLE::Persistent(1001);

// First delete anything that might already be there
tpm._AllowErrors()[sess].EvictControl(TPM_RH::OWNER, persistentHandle, persistentHandle);

// Make our primary persistent
tpm[sess].EvictControl(TPM_RH::OWNER, aesHandle, persistentHandle);

//// Flush the old one
tpm[sess].FlushContext(aesHandle);

ByteVec toEncrypt{ 1, 2, 3, 4, 5, 4, 3, 2, 12, 3, 4, 5 };
ByteVec iv(16);

persistentHandle.SetAuth(userAuth);

auto encrypted = tpm[sess].EncryptDecrypt(persistentHandle, (BYTE)0, TPM_ALG_ID::CFB, iv, toEncrypt);
auto decrypted = tpm[sess].EncryptDecrypt(persistentHandle, (BYTE)1, TPM_ALG_ID::CFB, iv, encrypted.outData);

cout << "AES encryption" << endl <<
    "in:  " << toEncrypt << endl <<
    "enc: " << encrypted.outData << endl <<
    "dec: " << decrypted.outData << endl;

_ASSERT(decrypted.outData == toEncrypt);

tpm.FlushContext(prim);
tpm.FlushContext(aesHandle);`
alexey3nemckovich commented 2 years ago

It fails on attempt to load created key with error = TPM_RC::SIZE TPM_HANDLE aesHandle = tpm[sess].Load(prim, aesKey.outPrivate, aesKey.outPublic); If do this actions (key creation, making it persistent, encryption/decryption) without session everything works fine. But I need somehow to encrypt parameters passed to TPM.

alexey3nemckovich commented 2 years ago

I realised, that EncryptDecrypt command can't be crypted, because it doesn't have TPM2B parameter first. So, I tried to use RSA encryption instread. It supports encryption session. But unfortunately I got another error Sample of my code `

// At the time of writing only unseeded and unbound session enc and dec are supported.
// First set up a session that encrypts communications TO the TPM. To do this
// we tell the TPM to decrypt via TPMA_SESSION::decrypt.
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));

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

// Set the use-auth for the nex 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
auto storagePrimary = tpm[sess].CreatePrimary(TPM_RH::OWNER, sensCreate, primTempl, null, null);

TPM_HANDLE& keyHandle = storagePrimary.handle;

// We can put the primary key into NV with EvictControl
TPM_HANDLE persistentHandle = TPM_HANDLE::Persistent(1000);

persistentHandle.SetName(userAuth);
persistentHandle.SetAuth(userAuth);

// 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, storagePrimary.handle, persistentHandle);

//// Flush the old one
tpm.FlushContext(storagePrimary.handle);

// ReadPublic of the new persistent one
auto persistentPub = tpm.ReadPublic(persistentHandle);
cout << "Public part of persistent primary" << endl << persistentPub.ToString(false);

ByteVec dataToEncrypt = { '1', '2', '3', '\0' };//TPM_HASH::FromHashOfString(TPM_ALG_ID::SHA1, "secret");
cout << "Data to encrypt: " << dataToEncrypt << endl;

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

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

tpm.FlushContext(keyHandle);`

Here program fails on RSA_Encrypt command with code BAD_AUTH.