UINT32 TpmHandleToName( TPM_HANDLE handle, TPM2B_NAME *name ) { TPM_RC rval; TPM2B_NAME qualifiedName; TPM2B_PUBLIC public; TPM2B_NV_PUBLIC nvPublic; TSS2_SYS_CONTEXT *sysContext; UINT8 *namePtr = &( name->t.name[0] ); // Initialize name to zero length in case of failure. qualifiedName.b.size = sizeof( TPM2B_NAME ) - 2; name->b.size = sizeof( TPM2B_NAME ) - 2; if( handle == ( TPM_HT_NO_HANDLE ) ) { name->b.size = 0; rval = TPM_RC_SUCCESS; } else { switch( handle >> HR_SHIFT ) { case TPM_HT_NV_INDEX: sysContext = InitSysContext( 1000, resMgrTctiContext, &abiVersion ); if( sysContext == 0 ) return TSS2_APP_RC_INIT_SYS_CONTEXT_FAILED; nvPublic.t.size = 0; rval = Tss2_Sys_NV_ReadPublic( sysContext, handle, 0, &nvPublic, name, 0 ); TeardownSysContext( &sysContext ); break; case TPM_HT_TRANSIENT: case TPM_HT_PERSISTENT: sysContext = InitSysContext( 1000, resMgrTctiContext, &abiVersion ); if( sysContext == 0 ) return TSS2_APP_RC_INIT_SYS_CONTEXT_FAILED; public.t.size = 0; rval = Tss2_Sys_ReadPublic( sysContext, handle, 0, &public, name, &qualifiedName, 0 ); TeardownSysContext( &sysContext ); break; default: rval = TPM_RC_SUCCESS; name->b.size = sizeof( TPM_HANDLE ); *(TPM_HANDLE *)namePtr = CHANGE_ENDIAN_DWORD( handle ); } }
// // This function does a hash on an array of data strings. // UINT32 TpmHashSequence( TPMI_ALG_HASH hashAlg, UINT8 numBuffers, TPM2B_DIGEST *bufferList, TPM2B_DIGEST *result ) { UINT32 rval; TSS2_SYS_CONTEXT *sysContext; TPM2B_AUTH nullAuth; TPMI_DH_OBJECT sequenceHandle; int i; TPM2B emptyBuffer; TPMT_TK_HASHCHECK validation; TPMS_AUTH_COMMAND cmdAuth; TPMS_AUTH_COMMAND *cmdSessionArray[1] = { &cmdAuth }; TSS2_SYS_CMD_AUTHS cmdAuthArray = { 1, &cmdSessionArray[0] }; nullAuth.t.size = 0; emptyBuffer.size = 0; // Set result size to 0, in case any errors occur result->b.size = 0; // Init input sessions struct cmdAuth.sessionHandle = TPM_RS_PW; cmdAuth.nonce.t.size = 0; *( (UINT8 *)((void *)&cmdAuth.sessionAttributes ) ) = 0; cmdAuth.hmac.t.size = 0; sysContext = InitSysContext( 3000, resMgrTctiContext, &abiVersion ); if( sysContext == 0 ) return TSS2_APP_RC_INIT_SYS_CONTEXT_FAILED; rval = Tss2_Sys_HashSequenceStart( sysContext, 0, &nullAuth, hashAlg, &sequenceHandle, 0 ); if( rval != TPM_RC_SUCCESS ) return( rval ); for( i = 0; i < numBuffers; i++ ) { rval = Tss2_Sys_SequenceUpdate ( sysContext, sequenceHandle, &cmdAuthArray, (TPM2B_MAX_BUFFER *)&bufferList[i], 0 ); if( rval != TPM_RC_SUCCESS ) return( rval ); } INIT_SIMPLE_TPM2B_SIZE( *result ); rval = Tss2_Sys_SequenceComplete ( sysContext, sequenceHandle, &cmdAuthArray, ( TPM2B_MAX_BUFFER *)&emptyBuffer, TPM_RH_PLATFORM, result, &validation, 0 ); if( rval != TPM_RC_SUCCESS ) return( rval ); TeardownSysContext( &sysContext ); return rval; }
TSS2_RC EncryptCFB( SESSION *session, TPM2B_MAX_BUFFER *encryptedData, TPM2B_MAX_BUFFER *clearData, TPM2B_AUTH *authValue ) { TSS2_RC rval = TSS2_RC_SUCCESS; TPM2B_MAX_BUFFER encryptKey; TPM2B_IV ivIn, ivOut; TPM_HANDLE keyHandle; TPM2B_NAME keyName; TSS2_SYS_CONTEXT *sysContext; // Authorization structure for command. TPMS_AUTH_COMMAND sessionData; // Create and init authorization area for command: // only 1 authorization area. TPMS_AUTH_COMMAND *sessionDataArray[1] = { &sessionData }; // Authorization array for command (only has one auth structure). TSS2_SYS_CMD_AUTHS sessionsData = { 1, &sessionDataArray[0] }; sysContext = InitSysContext( 1000, resMgrTctiContext, &abiVersion ); if( sysContext == 0 ) { TeardownSysContext( &sysContext ); return TSS2_APP_RC_TEARDOWN_SYS_CONTEXT_FAILED; } rval = GenerateSessionEncryptDecryptKey( session, &encryptKey, &ivIn, authValue ); if( rval == TSS2_RC_SUCCESS ) { rval = LoadSessionEncryptDecryptKey( &session->symmetric, &encryptKey, &keyHandle, &keyName ); if( rval == TSS2_RC_SUCCESS ) { // Encrypt the data. sessionData.sessionHandle = TPM_RS_PW; sessionData.nonce.t.size = 0; *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0; sessionData.hmac.t.size = 0; encryptedData->t.size = sizeof( *encryptedData ) - 1; ivOut.t.size = sizeof( ivOut ) - 2; rval = Tss2_Sys_EncryptDecrypt( sysContext, keyHandle, &sessionsData, NO, TPM_ALG_CFB, &ivIn, clearData, encryptedData, &ivOut, 0 ); if( rval == TSS2_RC_SUCCESS ) { rval = Tss2_Sys_FlushContext( sysContext, keyHandle ); } } } TeardownSysContext( &sysContext ); return rval; }
UINT32 LoadSessionEncryptDecryptKey( TPMT_SYM_DEF *symmetric, TPM2B_MAX_BUFFER *key, TPM_HANDLE *keyHandle, TPM2B_NAME *keyName ) { TPM2B keyAuth; TPM2B_SENSITIVE inPrivate; TPM2B_PUBLIC inPublic; UINT32 rval; TSS2_SYS_CONTEXT *sysContext; keyAuth.size = 0; inPrivate.t.sensitiveArea.sensitiveType = TPM_ALG_SYMCIPHER; inPrivate.t.size = CopySizedByteBuffer( &(inPrivate.t.sensitiveArea.authValue.b), &keyAuth); inPrivate.t.sensitiveArea.seedValue.b.size = 0; inPrivate.t.size += CopySizedByteBuffer( &inPrivate.t.sensitiveArea.sensitive.bits.b, &key->b ); inPrivate.t.size += 2 * sizeof( UINT16 ); inPublic.t.publicArea.type = TPM_ALG_SYMCIPHER; inPublic.t.publicArea.nameAlg = TPM_ALG_NULL; *( UINT32 *)&( inPublic.t.publicArea.objectAttributes )= 0; inPublic.t.publicArea.objectAttributes.decrypt = 1; inPublic.t.publicArea.objectAttributes.sign = 1; inPublic.t.publicArea.objectAttributes.userWithAuth = 1; inPublic.t.publicArea.authPolicy.t.size = 0; inPublic.t.publicArea.parameters.symDetail.sym.algorithm = symmetric->algorithm; inPublic.t.publicArea.parameters.symDetail.sym.keyBits = symmetric->keyBits; inPublic.t.publicArea.parameters.symDetail.sym.mode = symmetric->mode; inPublic.t.publicArea.unique.sym.t.size = 0; sysContext = InitSysContext( 1000, resMgrTctiContext, &abiVersion ); if( sysContext == 0 ) { return TSS2_APP_RC_INIT_SYS_CONTEXT_FAILED; } keyName->t.size = sizeof( *keyName ) - 2; rval = Tss2_Sys_LoadExternal( sysContext, 0, &inPrivate, &inPublic, TPM_RH_NULL, keyHandle, keyName, 0 ); TeardownSysContext( &sysContext ); return rval; }
// // This function does a hash on a string of data. // UINT32 TpmHash( TPMI_ALG_HASH hashAlg, UINT16 size, BYTE *data, TPM2B_DIGEST *result ) { TPM_RC rval; TPM2B_MAX_BUFFER dataSizedBuffer; UINT16 i; TSS2_SYS_CONTEXT *sysContext; dataSizedBuffer.t.size = size; for( i = 0; i < size; i++ ) dataSizedBuffer.t.buffer[i] = data[i]; sysContext = InitSysContext( 3000, resMgrTctiContext, &abiVersion ); if( sysContext == 0 ) return TSS2_APP_RC_INIT_SYS_CONTEXT_FAILED; rval = Tss2_Sys_Hash ( sysContext, 0, &dataSizedBuffer, hashAlg, TPM_RH_NULL, result, 0, 0); TeardownSysContext( &sysContext ); return rval; }
UINT32 LoadExternalHMACKey( TPMI_ALG_HASH hashAlg, TPM2B *key, TPM_HANDLE *keyHandle, TPM2B_NAME *keyName ) { TPM2B keyAuth; TPM2B_SENSITIVE inPrivate; TPM2B_PUBLIC inPublic; UINT32 rval; TSS2_SYS_CONTEXT *sysContext; keyAuth.size = 0; inPrivate.t.sensitiveArea.sensitiveType = TPM_ALG_KEYEDHASH; inPrivate.t.size = CopySizedByteBuffer( &(inPrivate.t.sensitiveArea.authValue.b), &keyAuth); inPrivate.t.sensitiveArea.seedValue.b.size = 0; inPrivate.t.size += CopySizedByteBuffer( &inPrivate.t.sensitiveArea.sensitive.bits.b, key); inPrivate.t.size += 2 * sizeof( UINT16 ); inPublic.t.publicArea.type = TPM_ALG_KEYEDHASH; inPublic.t.publicArea.nameAlg = TPM_ALG_NULL; *( UINT32 *)&( inPublic.t.publicArea.objectAttributes )= 0; inPublic.t.publicArea.objectAttributes.sign = 1; inPublic.t.publicArea.objectAttributes.userWithAuth = 1; inPublic.t.publicArea.authPolicy.t.size = 0; inPublic.t.publicArea.parameters.keyedHashDetail.scheme.scheme = TPM_ALG_HMAC; inPublic.t.publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg = hashAlg; inPublic.t.publicArea.unique.keyedHash.t.size = 0; sysContext = InitSysContext( 1000, resMgrTctiContext, &abiVersion ); if( sysContext == 0 ) { TeardownSysContext( &sysContext ); return TSS2_APP_ERROR_LEVEL + TPM_RC_FAILURE; } rval = Tss2_Sys_LoadExternal( sysContext, 0, &inPrivate, &inPublic, TPM_RH_NULL, keyHandle, keyName, 0 ); TeardownSysContext( &sysContext ); return rval; }
// // This is a wrapper function around the TPM2_StartAuthSession command. // It performs the command, calculates the session key, and updates a // SESSION structure. // TPM_RC StartAuthSession( SESSION *session ) { TPM_RC rval; TPM2B_ENCRYPTED_SECRET key; char label[] = "ATH"; TSS2_SYS_CONTEXT *tmpSysContext; UINT16 bytes; int i; key.t.size = 0; tmpSysContext = InitSysContext( 1000, resMgrTctiContext, &abiVersion ); if( tmpSysContext == 0 ) return TSS2_APP_RC_INIT_SYS_CONTEXT_FAILED; if( session->nonceOlder.t.size == 0 ) { session->nonceOlder.t.size = GetDigestSize( TPM_ALG_SHA1 ); for( i = 0; i < session->nonceOlder.t.size; i++ ) session->nonceOlder.t.buffer[i] = 0; } session->nonceNewer.t.size = session->nonceOlder.t.size; rval = Tss2_Sys_StartAuthSession( tmpSysContext, session->tpmKey, session->bind, 0, &( session->nonceOlder ), &( session->encryptedSalt ), session->sessionType, &( session->symmetric ), session->authHash, &( session->sessionHandle ), &( session->nonceNewer ), 0 ); if( rval == TPM_RC_SUCCESS ) { if( session->tpmKey == TPM_RH_NULL ) session->salt.t.size = 0; if( session->bind == TPM_RH_NULL ) session->authValueBind.t.size = 0; if( session->tpmKey == TPM_RH_NULL && session->bind == TPM_RH_NULL ) { session->sessionKey.b.size = 0; } else { // Generate the key used as input to the KDF. rval = ConcatSizedByteBuffer( (TPM2B_MAX_BUFFER *)&key, &( session->authValueBind.b ) ); if( rval != TPM_RC_SUCCESS ) { TeardownSysContext( &tmpSysContext ); return( rval ); } rval = ConcatSizedByteBuffer( (TPM2B_MAX_BUFFER *)&key, &( session->salt.b ) ); if( rval != TPM_RC_SUCCESS ) { TeardownSysContext( &tmpSysContext ); return( rval ); } bytes = GetDigestSize( session->authHash ); if( key.t.size == 0 ) { session->sessionKey.t.size = 0; } else { rval = KDFa( session->authHash, &(key.b), label, &( session->nonceNewer.b ), &( session->nonceOlder.b ), bytes * 8, (TPM2B_MAX_BUFFER *)&( session->sessionKey ) ); } if( rval != TPM_RC_SUCCESS ) { TeardownSysContext( &tmpSysContext ); return( TSS2_APP_RC_CREATE_SESSION_KEY_FAILED ); } } session->nonceTpmDecrypt.b.size = 0; session->nonceTpmEncrypt.b.size = 0; session->nvNameChanged = 0; } TeardownSysContext( &tmpSysContext ); return rval; }
// // This function does an HMAC on a null-terminated list of input buffers. // UINT32 TpmHmac( TPMI_ALG_HASH hashAlg, TPM2B *key, TPM2B **bufferList, TPM2B_DIGEST *result ) { TPM2B_AUTH nullAuth; TPMI_DH_OBJECT sequenceHandle; int i; TPM2B emptyBuffer; TPMT_TK_HASHCHECK validation; TPMS_AUTH_COMMAND *sessionDataArray[1]; TPMS_AUTH_COMMAND sessionData; TSS2_SYS_CMD_AUTHS sessionsData; TPM2B_AUTH hmac; TPM2B_NONCE nonce; TPMS_AUTH_RESPONSE *sessionDataOutArray[1]; TPMS_AUTH_RESPONSE sessionDataOut; TSS2_SYS_RSP_AUTHS sessionsDataOut; UINT32 rval; TPM_HANDLE keyHandle; TPM2B_NAME keyName; TPM2B keyAuth; TSS2_SYS_CONTEXT *sysContext; sessionDataArray[0] = &sessionData; sessionDataOutArray[0] = &sessionDataOut; // Set result size to 0, in case any errors occur result->b.size = 0; keyAuth.size = 0; nullAuth.t.size = 0; rval = LoadExternalHMACKey( hashAlg, key, &keyHandle, &keyName ); if( rval != TPM_RC_SUCCESS ) { return( rval ); } // Init input sessions struct sessionData.sessionHandle = TPM_RS_PW; nonce.t.size = 0; sessionData.nonce = nonce; CopySizedByteBuffer( &(hmac.b), &keyAuth ); sessionData.hmac = hmac; *( (UINT8 *)((void *)&( sessionData.sessionAttributes ) ) ) = 0; sessionsData.cmdAuthsCount = 1; sessionsData.cmdAuths = &sessionDataArray[0]; // Init sessions out struct sessionsDataOut.rspAuthsCount = 1; sessionsDataOut.rspAuths = &sessionDataOutArray[0]; emptyBuffer.size = 0; sysContext = InitSysContext( 3000, resMgrTctiContext, &abiVersion ); if( sysContext == 0 ) return TSS2_APP_ERROR_LEVEL + TPM_RC_FAILURE; rval = Tss2_Sys_HMAC_Start( sysContext, keyHandle, &sessionsData, &nullAuth, hashAlg, &sequenceHandle, 0 ); if( rval != TPM_RC_SUCCESS ) return( rval ); hmac.t.size = 0; sessionData.hmac = hmac; for( i = 0; bufferList[i] != 0; i++ ) { rval = Tss2_Sys_SequenceUpdate ( sysContext, sequenceHandle, &sessionsData, (TPM2B_MAX_BUFFER *)( bufferList[i] ), &sessionsDataOut ); if( rval != TPM_RC_SUCCESS ) return( rval ); } result->t.size = sizeof( TPM2B_DIGEST ) - 2; rval = Tss2_Sys_SequenceComplete ( sysContext, sequenceHandle, &sessionsData, ( TPM2B_MAX_BUFFER *)&emptyBuffer, TPM_RH_PLATFORM, result, &validation, &sessionsDataOut ); if( rval != TPM_RC_SUCCESS ) return( rval ); rval = Tss2_Sys_FlushContext( sysContext, keyHandle ); TeardownSysContext( &sysContext ); return rval; }