TSS2_RC PlatformCommand( TSS2_TCTI_CONTEXT *tctiContext, /* in */ char cmd ) { int iResult = 0; // used to return function results char sendbuf[] = { 0x0,0x0,0x0,0x0 }; char recvbuf[] = { 0x0, 0x0, 0x0, 0x0 }; TSS2_RC rval = TSS2_RC_SUCCESS; if( simulator ) { sendbuf[3] = cmd; OpenOutFile( &outFp ); // Send the command iResult = send( TCTI_CONTEXT_INTEL->otherSock, sendbuf, 4, 0 ); if (iResult == SOCKET_ERROR) { (*printfFunction)(NO_PREFIX, "send failed with error: %d\n", WSAGetLastError() ); closesocket(TCTI_CONTEXT_INTEL->otherSock); WSACleanup(); rval = TSS2_TCTI_RC_IO_ERROR; } else { #ifdef DEBUG_SOCKETS (*printfFunction)( rmDebugPrefix, "Send Bytes to socket #0x%x: \n", TCTI_CONTEXT_INTEL->otherSock ); DebugPrintBuffer( (UINT8 *)sendbuf, 4 ); #endif // Read result iResult = recv( TCTI_CONTEXT_INTEL->otherSock, recvbuf, 4, 0); if (iResult == SOCKET_ERROR) { (*printfFunction)(NO_PREFIX, "In PlatformCommand, recv failed (socket: 0x%x) with error: %d\n", TCTI_CONTEXT_INTEL->otherSock, WSAGetLastError() ); closesocket(TCTI_CONTEXT_INTEL->otherSock); WSACleanup(); rval = TSS2_TCTI_RC_IO_ERROR; } else if( recvbuf[0] != 0 || recvbuf[1] != 0 || recvbuf[2] != 0 || recvbuf[3] != 0 ) { (*printfFunction)(NO_PREFIX, "PlatformCommand failed with error: %d\n", recvbuf[3] ); closesocket(TCTI_CONTEXT_INTEL->otherSock); WSACleanup(); rval = TSS2_TCTI_RC_IO_ERROR; } else { #ifdef DEBUG_SOCKETS (*printfFunction)(NO_PREFIX, "Receive bytes from socket #0x%x: \n", TCTI_CONTEXT_INTEL->otherSock ); DebugPrintBuffer( (UINT8 *)recvbuf, 4 ); #endif } } CloseOutFile( &outFp ); } return rval; }
TSS2_RC TeardownSocketsTcti ( TSS2_TCTI_CONTEXT *tctiContext, // OUT const char *config, // IN const char *interfaceName ) { OpenOutFile( &outFp ); (*printfFunction)(NO_PREFIX, "Tearing down %s Interface\n", interfaceName ); CloseOutFile( &outFp ); ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->finalize( tctiContext ); return TSS2_RC_SUCCESS; }
TSS2_RC InitSocketsTcti ( TSS2_TCTI_CONTEXT *tctiContext, // OUT size_t *contextSize, // IN/OUT const char *config, // IN const uint64_t magic, const uint32_t version, const char *interfaceName, const uint8_t serverSockets ) { TSS2_RC rval = TSS2_RC_SUCCESS; char hostName[200]; int port; SOCKET otherSock; SOCKET tpmSock; if( tctiContext == NULL ) { *contextSize = sizeof( TSS2_TCTI_CONTEXT_INTEL ); return TSS2_RC_SUCCESS; } else { OpenOutFile( &outFp ); (*printfFunction)(NO_PREFIX, "Initializing %s Interface\n", interfaceName ); // Init TCTI context. ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->magic = magic; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->version = version; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->transmit = SocketSendTpmCommand; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->receive = SocketReceiveTpmResponse; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->finalize = SocketFinalize; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->cancel = SocketCancel; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->getPollHandles = 0; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->setLocality = SocketSetLocality; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.locality = 3; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.commandSent = 0; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.rmDebugPrefix = 0; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->currentTctiContext = 0; // Get hostname and port. if( ( strlen( config ) + 2 ) <= ( HOSTNAME_LENGTH ) ) { if( 1 == sscanf( config, "%199s", hostName ) ) { if( strlen( config) - ( strlen( hostName ) + 2 ) <= PORT_LENGTH ) { if( 1 != sscanf( &config[strlen( hostName )], "%d", &port ) ) { return( TSS2_TCTI_RC_BAD_VALUE ); } } else { return( TSS2_TCTI_RC_BAD_VALUE ); } } else { return( TSS2_TCTI_RC_BAD_VALUE ); } } else { return( TSS2_TCTI_RC_INSUFFICIENT_BUFFER ); } rval = (TSS2_RC) InitSockets( &hostName[0], port, serverSockets, &otherSock, &tpmSock ); if( rval == TSS2_RC_SUCCESS ) { ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->otherSock = otherSock; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->tpmSock = tpmSock; } else { CloseSockets( otherSock, tpmSock); } CloseOutFile( &outFp ); } return rval; }
TSS2_RC InitLocalTpmTcti ( TSS2_TCTI_CONTEXT *tctiContext, // OUT size_t *contextSize, // IN/OUT const char *config, // IN const uint64_t magic, const uint32_t version, const char *interfaceName, const uint8_t serverSockets // Unused for local TPM. ) { TSS2_RC rval = TSS2_RC_SUCCESS; char fileName[200]; if( tctiContext == NULL ) { *contextSize = sizeof( TSS2_TCTI_CONTEXT_INTEL ); return TSS2_RC_SUCCESS; } else { OpenOutFile( &outFp ); (*tpmLocalTpmPrintf)(NO_PREFIX, "Initializing %s Interface\n", interfaceName ); // Init TCTI context. ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->magic = magic; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->version = version; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->transmit = LocalTpmSendTpmCommand; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->receive = LocalTpmReceiveTpmResponse; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->finalize = LocalTpmFinalize; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->cancel = LocalTpmCancel; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->getPollHandles = 0; ((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->setLocality = LocalTpmSetLocality; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.locality = 3; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.commandSent = 0; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.rmDebugPrefix = 0; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->currentTctiContext = 0; // Get hostname and port. if( ( strlen( config ) + 2 ) <= ( HOSTNAME_LENGTH ) ) { if( 1 != sscanf( config, "%199s", fileName ) ) { return( TSS2_TCTI_RC_BAD_VALUE ); } } else { return( TSS2_TCTI_RC_INSUFFICIENT_BUFFER ); } ( ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->devFile ) = open( fileName, O_RDWR ); if( ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->devFile < 0 ) { return( TSS2_TCTI_RC_IO_ERROR ); } CloseOutFile( &outFp ); } 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; }