TPM_RC GetSessionStruct( TPMI_SH_AUTH_SESSION sessionHandle, SESSION **session ) { TPM_RC rval = TSS2_APP_RC_GET_SESSION_STRUCT_FAILED; SESSION_LIST_ENTRY *sessionEntry; TpmClientPrintf( 0, "In GetSessionStruct\n" ); if( session != 0 ) { // // Get pointer to session structure using the sessionHandle // for( sessionEntry = sessionsList; sessionEntry != 0 && sessionEntry->session.sessionHandle != sessionHandle; sessionEntry = sessionEntry->nextEntry ) ; if( sessionEntry != 0 ) { *session = &sessionEntry->session; rval = TSS2_RC_SUCCESS; } } return rval; }
TPM_RC GetSessionAlgId( TPMI_SH_AUTH_SESSION sessionHandle, TPMI_ALG_HASH *sessionAlgId ) { TPM_RC rval = TSS2_APP_RC_GET_SESSION_ALG_ID_FAILED; SESSION *session; TpmClientPrintf( 0, "In GetSessionAlgId\n" ); rval = GetSessionStruct( sessionHandle, &session ); if( rval == TSS2_RC_SUCCESS ) { *sessionAlgId = session->authHash; rval = TSS2_RC_SUCCESS; } return rval; }
// // This function is a helper function used to calculate cpHash and rpHash. // // NOTE: for calculating cpHash, set responseCode to TPM_RC_NO_RESPONSE; this // tells the function to leave it out of the calculation. // TPM_RC TpmCalcPHash( TSS2_SYS_CONTEXT *sysContext, TPM_HANDLE handle1, TPM_HANDLE handle2, TPMI_ALG_HASH authHash, TPM_RC responseCode, TPM2B_DIGEST *pHash ) { TPM_RC rval = TPM_RC_SUCCESS; UINT32 i; TPM2B_NAME name1; TPM2B_NAME name2; TPM2B_MAX_BUFFER hashInput; // Byte stream to be hashed to create pHash UINT8 *hashInputPtr; size_t parametersSize; const uint8_t *startParams; UINT8 cmdCode[4] = {0,0,0,0}; UINT8 *cmdCodePtr = &cmdCode[0]; name1.b.size = name2.b.size = 0; // Calculate pHash // // Only get names for commands if( responseCode == TPM_RC_NO_RESPONSE ) { // Get names for the handles rval = TpmHandleToName( handle1, &name1 ); if( rval != TPM_RC_SUCCESS ) return rval; } #ifdef DEBUG OpenOutFile( &outFp ); TpmClientPrintf( 0, "\n\nNAME1 = \n" ); PrintSizedBuffer( &(name1.b) ); CloseOutFile( &outFp ); #endif // Only get names for commands if( responseCode == TPM_RC_NO_RESPONSE ) { rval = Tss2_Sys_GetCpBuffer( sysContext, ¶metersSize, &startParams); if( rval != TPM_RC_SUCCESS ) return rval; rval = TpmHandleToName( handle2, &name2 ); if( rval != TPM_RC_SUCCESS ) return rval; } else { rval = Tss2_Sys_GetRpBuffer( sysContext, ¶metersSize, &startParams); if( rval != TPM_RC_SUCCESS ) return rval; } #ifdef DEBUG OpenOutFile( &outFp ); TpmClientPrintf( 0, "\n\nNAME2 = \n" ); PrintSizedBuffer( &(name2.b) ); CloseOutFile( &outFp ); #endif // Create pHash input byte stream: first add response code, if any. hashInput.b.size = 0; if( responseCode != TPM_RC_NO_RESPONSE ) { hashInputPtr = &( hashInput.t.buffer[hashInput.b.size] ); *(UINT32 *)hashInputPtr = CHANGE_ENDIAN_DWORD( responseCode ); hashInput.b.size += 4; hashInputPtr += 4; } // Create pHash input byte stream: now add command code. rval = Tss2_Sys_GetCommandCode( sysContext, &cmdCode ); if( rval != TPM_RC_SUCCESS ) return rval; hashInputPtr = &( hashInput.t.buffer[hashInput.b.size] ); *(UINT32 *)hashInputPtr = CHANGE_ENDIAN_DWORD( *(UINT32 *)cmdCodePtr ); hashInput.t.size += 4; // Create pHash input byte stream: now add in names for the handles. rval = ConcatSizedByteBuffer( &hashInput, &( name1.b ) ); if( rval != TPM_RC_SUCCESS ) return rval; rval = ConcatSizedByteBuffer( &hashInput, &( name2.b ) ); if( rval != TPM_RC_SUCCESS ) return rval; if( ( hashInput.t.size + parametersSize ) <= sizeof( hashInput.t.buffer ) ) { // Create pHash input byte stream: now add in parameters byte stream for( i = 0; i < parametersSize; i++ ) hashInput.t.buffer[hashInput.t.size + i ] = startParams[i]; hashInput.t.size += (UINT16)parametersSize; } else { return( APPLICATION_ERROR( TSS2_BASE_RC_INSUFFICIENT_BUFFER ) ); } #ifdef DEBUG OpenOutFile( &outFp ); TpmClientPrintf( 0, "\n\nPHASH input bytes= \n" ); PrintSizedBuffer( &(hashInput.b) ); CloseOutFile( &outFp ); #endif // Now hash the whole mess. if( hashInput.t.size > sizeof( hashInput.t.buffer ) ) { rval = APPLICATION_ERROR( TSS2_BASE_RC_INSUFFICIENT_BUFFER ); } else { rval = TpmHash( authHash, hashInput.t.size, &( hashInput.t.buffer[0] ), pHash ); if( rval != TPM_RC_SUCCESS ) return rval; #ifdef DEBUG OpenOutFile( &outFp ); TpmClientPrintf( 0, "\n\nPHASH = " ); PrintSizedBuffer( &(pHash->b) ); CloseOutFile( &outFp ); #endif } return rval; }
// // This function calculates the session HMAC and updates session state. // UINT32 TpmComputeSessionHmac( TSS2_SYS_CONTEXT *sysContext, TPMS_AUTH_COMMAND *pSessionDataIn, // Pointer to session input struct TPM_HANDLE entityHandle, // Used to determine if we're accessing a different // resource than the bound resoure. TPM_RC responseCode, // Response code for the command, 0xffff for "none" is // used to indicate that no response code is present // (used for calculating command HMACs vs response HMACs). TPM_HANDLE handle1, // First handle == 0xff000000 indicates no handle TPM_HANDLE handle2, // Second handle == 0xff000000 indicates no handle TPMA_SESSION sessionAttributes, // Current session attributes TPM2B_DIGEST *result, // Where the result hash is saved. TPM_RC sessionCmdRval ) { TPM2B_MAX_BUFFER hmacKey; TPM2B *bufferList[7]; TPM2B_DIGEST pHash; SESSION *pSession = 0; TPM2B_AUTH authValue; TPM2B sessionAttributesByteBuffer; UINT16 i; TPM_RC rval; UINT8 nvNameChanged = 0; ENTITY *nvEntity; UINT8 commandCode[4] = { 0, 0, 0, 0 }; UINT32 *cmdCodePtr; UINT32 cmdCode; hmacKey.b.size = 0; rval = GetSessionStruct( pSessionDataIn->sessionHandle, &pSession ); if( rval != TPM_RC_SUCCESS ) { return rval; } pHash.t.size = sizeof( TPM2B_DIGEST ) - 2; rval = ( *CalcPHash )( sysContext, handle1, handle2, pSession->authHash, responseCode, &pHash ); if( rval != TPM_RC_SUCCESS ) return rval; // Use entityHandle to get authValue, if any. if( ( pSession->bind == TPM_RH_NULL ) || ( ( pSession->bind != TPM_RH_NULL ) && ( pSession->bind == entityHandle ) ) ) { rval = GetEntityAuth( entityHandle, &authValue ); if( rval != TPM_RC_SUCCESS ) authValue.t.size = 0; } else { authValue.t.size = 0; } rval = Tss2_Sys_GetCommandCode( sysContext, &commandCode ); if( rval != TPM_RC_SUCCESS ) return rval; if( ( entityHandle >> HR_SHIFT ) == TPM_HT_NV_INDEX ) { // If NV index, get status wrt to name change. If name has changed, // we have to treat it as if its not the bound entity, even if it was // the bound entity. nvNameChanged = pSession->nvNameChanged; } rval = ConcatSizedByteBuffer( (TPM2B_MAX_BUFFER *)&hmacKey, &( pSession->sessionKey.b ) ); if( ( pSession->bind == TPM_RH_NULL ) || ( pSession->bind != entityHandle ) || nvNameChanged ) { rval = ConcatSizedByteBuffer( (TPM2B_MAX_BUFFER *)&hmacKey, &( authValue.b ) ); } #ifdef DEBUG OpenOutFile( &outFp ); TpmClientPrintf( 0, "\n\nhmacKey = " ); PrintSizedBuffer( &(hmacKey.b) ); CloseOutFile( &outFp ); #endif // Create buffer list i = 0; bufferList[i++] = &pHash.b; bufferList[i++] = &( pSession->nonceNewer.b ); bufferList[i++] = &( pSession->nonceOlder.b ); bufferList[i++] = &( pSession->nonceTpmDecrypt.b ); bufferList[i++] = &( pSession->nonceTpmEncrypt.b ); sessionAttributesByteBuffer.size = 1; sessionAttributesByteBuffer.buffer[0] = *(UINT8 *)&sessionAttributes; bufferList[i++] = &( sessionAttributesByteBuffer ); bufferList[i++] = 0; cmdCodePtr = (UINT32 *)&commandCode[0]; cmdCode = *cmdCodePtr; #ifdef DEBUG OpenOutFile( &outFp ); for( i = 0; bufferList[i] != 0; i++ ) { TpmClientPrintf( 0, "\n\nbufferlist[%d]:\n", i ); PrintSizedBuffer( bufferList[i] ); } CloseOutFile( &outFp ); #endif rval = (*HmacFunctionPtr)( pSession->authHash, &hmacKey.b, &( bufferList[0] ), result ); if( rval != TPM_RC_SUCCESS ) return rval; if( ( responseCode != TPM_RC_NO_RESPONSE ) && ( cmdCode == TPM_CC_NV_Write || cmdCode == TPM_CC_NV_Increment || cmdCode == TPM_CC_NV_SetBits ) ) { rval = GetEntity( entityHandle, &nvEntity ); if( rval != TPM_RC_SUCCESS ) { return rval; } else { // Only change session's nvNameChanged parameter when // the NV index's name changes due to a write. if( nvEntity->nvNameChanged == 0 ) { pSession->nvNameChanged = 1; nvEntity->nvNameChanged = 1; } } } return rval; }