TSS2_RC LocalTpmSendTpmCommand( TSS2_TCTI_CONTEXT *tctiContext, /* in */ size_t command_size, /* in */ uint8_t *command_buffer /* in */ ) { TSS2_RC rval = TSS2_RC_SUCCESS; ssize_t size; #ifdef DEBUG UINT32 commandCode = CHANGE_ENDIAN_DWORD( ( (TPM20_Header_In *)command_buffer )->commandCode ); UINT32 cnt = CHANGE_ENDIAN_DWORD(((TPM20_Header_In *) command_buffer)->commandSize); if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { (*tpmLocalTpmPrintf)( rmDebugPrefix, "\n" ); (*tpmLocalTpmPrintf)(rmDebugPrefix, "Cmd sent: %s\n", commandCodeStrings[ commandCode - TPM_CC_FIRST ] ); DEBUG_PRINT_BUFFER( command_buffer, cnt ); } #endif size = write( ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->devFile, command_buffer, command_size ); if( size < 0 ) { (*tpmLocalTpmPrintf)(NO_PREFIX, "send failed with error: %d\n", errno ); rval = TSS2_TCTI_RC_IO_ERROR; } else if( (size_t)size != command_size ) { rval = TSS2_TCTI_RC_IO_ERROR; } return rval; }
// // Copy session data for commands that require it. // // Inputs: // // pointer to pointer to sessionData area of command // // pointer to session data to be copied into command buffer // // Outputs: // // sessionDataPtr points to end byte past command buffer. This allows // caller to set the commandSize field for the command. // TSS2_RC CopySessionDataIn( void **otherData, TPMS_AUTH_COMMAND const *sessionData, UINT32 *sessionSizePtr ) { TSS2_RC rval = TSS2_RC_SUCCESS; UINT8 *inBuffPtr = *otherData; TPMS_AUTH_COMMAND *sessionDataCopy = (TPMS_AUTH_COMMAND *)sessionData; if( sessionData == 0 ) { rval = TSS2_SYS_RC_BAD_VALUE; goto exitCopySessionDataIn; } // Size of session data *sessionSizePtr += CHANGE_ENDIAN_DWORD( sizeof( TPMI_SH_AUTH_SESSION ) + sizeof( UINT16 ) + sessionData->nonce.t.size + sizeof( UINT8 ) + sizeof( UINT16 ) + sessionData->hmac.t.size ); // copy session handle SESSION_MARSHAL_UINT32( inBuffPtr, *sessionSizePtr, (UINT8 **)otherData, sessionDataCopy->sessionHandle, &rval, exitCopySessionDataIn ); // Copy nonce SESSION_MARSHAL_SIMPLE_TPM2B( inBuffPtr, *sessionSizePtr, (UINT8 **)otherData, &( sessionDataCopy->nonce.b ), &rval, exitCopySessionDataIn ); // Copy attributes SESSION_MARSHAL_UINT8( inBuffPtr, *sessionSizePtr, (UINT8 **)otherData, (UINT8)( sessionDataCopy->sessionAttributes.val ), &rval, exitCopySessionDataIn ); // Copy hmac data. SESSION_MARSHAL_SIMPLE_TPM2B( inBuffPtr, *sessionSizePtr, (UINT8 **)otherData, &( sessionDataCopy->hmac.b ), &rval, exitCopySessionDataIn ); exitCopySessionDataIn: return rval; }
TSS2_RC Tss2_Sys_ExecuteAsync( TSS2_SYS_CONTEXT *sysContext ) { TSS2_RC rval = TSS2_RC_SUCCESS; if( sysContext == 0 ) { rval = TSS2_SYS_RC_BAD_REFERENCE; } else if( SYS_CONTEXT->previousStage != CMD_STAGE_PREPARE ) { rval = TSS2_SYS_RC_BAD_SEQUENCE; } else { rval = (*( TCTI_CONTEXT )->transmit)( SYS_CONTEXT->tctiContext, CHANGE_ENDIAN_DWORD( ((TPM20_Header_In *)SYS_CONTEXT->tpmInBuffPtr )->commandSize), SYS_CONTEXT->tpmInBuffPtr ); } if( rval == TSS2_RC_SUCCESS ) { SYS_CONTEXT->previousStage = CMD_STAGE_SEND_COMMAND; } return rval; }
void CopyCommandHeader( _TSS2_SYS_CONTEXT_BLOB *sysContext, TPM_CC commandCode ) { SYS_CONTEXT->rval = TSS2_RC_SUCCESS; ((TPM20_Header_In *) sysContext->tpmInBuffPtr)->tag = CHANGE_ENDIAN_WORD( TPM_ST_NO_SESSIONS ); ((TPM20_Header_In *) sysContext->tpmInBuffPtr)->commandCode = CHANGE_ENDIAN_DWORD( commandCode ); SYS_CONTEXT->rval = TSS2_RC_SUCCESS; SYS_CONTEXT->nextData = SYS_CONTEXT->tpmInBuffPtr + sizeof( TPM20_Header_In ); }
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 ); } }
void Marshal_UINT32( UINT8 *inBuffPtr, UINT32 maxCommandSize, UINT8 **nextData, UINT32 value, TSS2_RC *rval ) { if( *rval != TSS2_RC_SUCCESS ) return; *rval = CheckDataPointers( inBuffPtr, nextData ); if( *rval != TSS2_RC_SUCCESS ) return; *rval = CheckOverflow( inBuffPtr, maxCommandSize, *nextData, sizeof(UINT32) ); if( *rval != TSS2_RC_SUCCESS ) return; *( (UINT32 *)*nextData ) = CHANGE_ENDIAN_DWORD( value ); *nextData = *nextData + sizeof( UINT32 ); }
// Common to all _Prepare TSS2_RC CommonPrepareEpilogue( TSS2_SYS_CONTEXT *sysContext ) { if( SYS_CONTEXT->rval != TSS2_RC_SUCCESS ) { return SYS_CONTEXT->rval; } SYS_CONTEXT->cpBufferUsedSize = SYS_CONTEXT->nextData - SYS_CONTEXT->cpBuffer; // Set current command size. ((TPM20_Header_In *) SYS_CONTEXT->tpmInBuffPtr)->commandSize = CHANGE_ENDIAN_DWORD( SYS_CONTEXT->nextData - SYS_CONTEXT->tpmInBuffPtr ); SYS_CONTEXT->previousStage = CMD_STAGE_PREPARE; return SYS_CONTEXT->rval; }
TSS2_RC SocketSendSessionEnd( TSS2_TCTI_CONTEXT *tctiContext, /* in */ UINT8 tpmCmdServer ) { UINT32 tpmSendCommand = TPM_SESSION_END; // Value for "send command" to MS simulator. SOCKET sock; if( tpmCmdServer ) { sock = TCTI_CONTEXT_INTEL->tpmSock; } else { sock = TCTI_CONTEXT_INTEL->otherSock; } tpmSendCommand = CHANGE_ENDIAN_DWORD(tpmSendCommand); sendBytes( sock, (char *)&tpmSendCommand, 4 ); return( TSS2_RC_SUCCESS ); }
// Common to all _Prepare TSS2_RC CommonPreparePrologue( TSS2_SYS_CONTEXT *sysContext, TPM_CC commandCode ) { int numCommandHandles; if( sysContext == NULL ) { return SYS_CONTEXT->rval = TSS2_SYS_RC_BAD_REFERENCE; } InitSysContextFields( sysContext ); // Need to check stage here. if( SYS_CONTEXT->previousStage != CMD_STAGE_INITIALIZE && SYS_CONTEXT->previousStage != CMD_STAGE_RECEIVE_RESPONSE && SYS_CONTEXT->previousStage != CMD_STAGE_PREPARE ) { SYS_CONTEXT->rval = TSS2_SYS_RC_BAD_SEQUENCE; } else { CopyCommandHeader( SYS_CONTEXT, commandCode ); SYS_CONTEXT->numResponseHandles = GetNumResponseHandles( commandCode ); SYS_CONTEXT->commandCodeSwapped = CHANGE_ENDIAN_DWORD( commandCode ); SYS_CONTEXT->paramsSize = (UINT32 *)&(((TPM20_Header_Out *)( SYS_CONTEXT->tpmOutBuffPtr ) )->otherData ) + GetNumResponseHandles( commandCode ); numCommandHandles = GetNumCommandHandles( commandCode ); SYS_CONTEXT->cpBuffer = SYS_CONTEXT->nextData + numCommandHandles * sizeof(UINT32); } return SYS_CONTEXT->rval; }
TSS2_RC LocalTpmReceiveTpmResponse( TSS2_TCTI_CONTEXT *tctiContext, /* in */ size_t *response_size, /* out */ unsigned char *response_buffer, /* in */ int32_t timeout ) { TSS2_RC rval = TSS2_RC_SUCCESS; ssize_t size; size = read( ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->devFile, response_buffer, *response_size ); if( size < 0 ) { (*tpmLocalTpmPrintf)(NO_PREFIX, "send failed with error: %d\n", errno ); rval = TSS2_TCTI_RC_IO_ERROR; *response_size = 0; } else { #ifdef DEBUG UINT32 cnt = CHANGE_ENDIAN_DWORD(((TPM20_Header_Out *) response_buffer)->responseSize); if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { (*tpmLocalTpmPrintf)( rmDebugPrefix, "\n" ); (*tpmLocalTpmPrintf)( rmDebugPrefix, "Response Received: " ); DEBUG_PRINT_BUFFER( response_buffer, cnt ); } #endif *response_size = size; } return rval; }
TSS2_RC Tss2_Sys_SetCmdAuths( TSS2_SYS_CONTEXT *sysContext, const TSS2_SYS_CMD_AUTHS *cmdAuthsArray ) { TSS2_RC rval = TSS2_RC_SUCCESS; if( sysContext == NULL || cmdAuthsArray == 0 ) { rval = TSS2_SYS_RC_BAD_REFERENCE; } else { SYS_CONTEXT->authsCount = 0; if( cmdAuthsArray->cmdAuthsCount > MAX_SESSION_NUM ) { rval = TSS2_SYS_RC_BAD_VALUE; } else if( SYS_CONTEXT->previousStage != CMD_STAGE_PREPARE ) { rval = TSS2_SYS_RC_BAD_SEQUENCE; } else if( SYS_CONTEXT->authAllowed != 1 ) { // Don't do anything. Let the TPM return an error code. } else { uint8_t i; UINT32 authSize = 0; UINT64 newCmdSize = 0; if( cmdAuthsArray->cmdAuthsCount > 0 ) { // Change command tag. ( (TPM20_Header_In *)( SYS_CONTEXT->tpmInBuffPtr ) )->tag = CHANGE_ENDIAN_WORD( TPM_ST_SESSIONS ); // Calculate size needed for authorization area // and check for any null pointers. // Also check for decrypt/encrypt sessions. for( i = 0; i < cmdAuthsArray->cmdAuthsCount; i++ ) { // Check for null pointer. if( cmdAuthsArray->cmdAuths[i] == 0 ) { rval = TSS2_SYS_RC_BAD_VALUE; break; } authSize += sizeof( TPMI_SH_AUTH_SESSION ); // Handle authSize += sizeof( UINT16 ) + cmdAuthsArray->cmdAuths[i]->nonce.t.size; // nonce authSize += sizeof( UINT8 ); // sessionAttribues authSize += sizeof( UINT16 ) + cmdAuthsArray->cmdAuths[i]->hmac.t.size; // hmac // Check for decrypt/encrypt sessions and set flags. This is // done to support the one-call function. if( cmdAuthsArray->cmdAuths[i]->sessionAttributes.decrypt ) SYS_CONTEXT->decryptSession = 1; if( cmdAuthsArray->cmdAuths[i]->sessionAttributes.encrypt ) SYS_CONTEXT->encryptSession = 1; } if( rval == TSS2_RC_SUCCESS ) { authSize += sizeof( UINT32 ); // authorization size field newCmdSize = (UINT64)authSize + (UINT64)CHANGE_ENDIAN_DWORD( ( (TPM20_Header_In *)( SYS_CONTEXT->tpmInBuffPtr ) )->commandSize ); if( newCmdSize > (UINT64)( SYS_CONTEXT->maxCommandSize ) ) { rval = TSS2_SYS_RC_INSUFFICIENT_BUFFER; } else { void *otherData; // We're going to have to move stuff around. // First move current cpBuffer down. rval = CopyMemReverse( SYS_CONTEXT->cpBuffer + authSize, SYS_CONTEXT->cpBuffer, SYS_CONTEXT->cpBufferUsedSize, SYS_CONTEXT->tpmInBuffPtr + SYS_CONTEXT->maxCommandSize ); if( rval == TSS2_RC_SUCCESS ) { // Now copy in the authorization area. otherData = SYS_CONTEXT->cpBuffer; rval = CopySessionsDataIn( &otherData, cmdAuthsArray ); // Update cpBuffer SYS_CONTEXT->cpBuffer += authSize; // Now update the command size. ( (TPM20_Header_In *)( SYS_CONTEXT->tpmInBuffPtr ) )->commandSize = CHANGE_ENDIAN_DWORD( (UINT32)newCmdSize ); SYS_CONTEXT->authsCount = cmdAuthsArray->cmdAuthsCount; } } } } } } return rval; }
TSS2_RC SocketReceiveTpmResponse( TSS2_TCTI_CONTEXT *tctiContext, /* in */ size_t *response_size, /* out */ unsigned char *response_buffer, /* in */ int32_t timeout ) { UINT32 trash; size_t responseSize = 0; TSS2_RC rval = TSS2_RC_SUCCESS; fd_set readFds; struct timeval tv, *tvPtr; int32_t timeoutMsecs = timeout % 1000; int iResult; if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { #ifdef DEBUG (*printfFunction)( rmDebugPrefix, "Response Received: " ); #endif #ifdef DEBUG_SOCKETS (*printfFunction)( rmDebugPrefix, "from socket #0x%x:\n", TCTI_CONTEXT_INTEL->tpmSock ); #endif } if( *response_size > 0 ) { if( timeout == TSS2_TCTI_TIMEOUT_BLOCK ) { tvPtr = 0; } else { tv.tv_sec = timeout / 1000; tv.tv_usec = timeoutMsecs * 1000; tvPtr = &tv; } FD_ZERO( &readFds ); FD_SET( TCTI_CONTEXT_INTEL->tpmSock, &readFds ); iResult = select( TCTI_CONTEXT_INTEL->tpmSock+1, &readFds, 0, 0, tvPtr ); if( iResult == 0 ) { (*printfFunction)(NO_PREFIX, "select failed due to timeout, socket #: 0x%x\n", TCTI_CONTEXT_INTEL->tpmSock ); rval = TSS2_TCTI_RC_TRY_AGAIN; goto retSocketReceiveTpmResponse; } else if( iResult == SOCKET_ERROR ) { (*printfFunction)(NO_PREFIX, "select failed with socket error: %d\n", WSAGetLastError() ); rval = TSS2_TCTI_RC_IO_ERROR; goto retSocketReceiveTpmResponse; } else if ( iResult != 1 ) { (*printfFunction)(NO_PREFIX, "select failed, read the wrong # of bytes: %d\n", iResult ); rval = TSS2_TCTI_RC_IO_ERROR; goto retSocketReceiveTpmResponse; } // Receive the size of the response. recvBytes( TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)&responseSize, 4 ); responseSize = CHANGE_ENDIAN_DWORD( responseSize ); // Receive the TPM response. recvBytes( TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)response_buffer, responseSize ); #ifdef DEBUG if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { DEBUG_PRINT_BUFFER( response_buffer, responseSize ); } #endif // Receive the appended four bytes of 0's recvBytes( TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)&trash, 4 ); } if( responseSize < *response_size ) { *response_size = responseSize; } ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.commandSent = 0; // Turn cancel off. rval = (TSS2_RC)PlatformCommand( tctiContext, MS_SIM_CANCEL_OFF ); if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { // (*printfFunction)(NO_PREFIX, "%s sent cancel OFF command:\n", interfaceName ); } retSocketReceiveTpmResponse: return rval; }
TSS2_RC SocketSendTpmCommand( TSS2_TCTI_CONTEXT *tctiContext, /* in */ size_t command_size, /* in */ uint8_t *command_buffer /* in */ ) { UINT32 tpmSendCommand = MS_SIM_TPM_SEND_COMMAND; // Value for "send command" to MS simulator. UINT32 cnt, cnt1; UINT8 locality; #ifdef SAPI_CLIENT UINT8 debugMsgLevel, statusBits; #endif UINT32 commandCode = CHANGE_ENDIAN_DWORD( ( (TPM20_Header_In *)command_buffer )->commandCode ); if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { #ifdef DEBUG (*printfFunction)(NO_PREFIX, "\n" ); if( commandCode >= TPM_CC_NV_UndefineSpaceSpecial && commandCode <= TPM_CC_PolicyNvWritten ) (*printfFunction)(rmDebugPrefix, "Cmd sent: %s\n", commandCodeStrings[ commandCode - TPM_CC_FIRST ] ); else (*printfFunction)(rmDebugPrefix, "Cmd sent: 0x%4.4x\n", CHANGE_ENDIAN_DWORD(commandCode ) ); #endif #ifdef DEBUG_SOCKETS (*printfFunction)(rmDebugPrefix, "Command sent on socket #0x%x: %s\n", TCTI_CONTEXT_INTEL->tpmSock, commandCodeStrings[ commandCode - TPM_CC_FIRST ] ); #endif } // Size TPM 1.2 and TPM 2.0 headers overlap exactly, we can use // either 1.2 or 2.0 header to get the size. cnt = CHANGE_ENDIAN_DWORD(((TPM20_Header_In *) command_buffer)->commandSize); // Send TPM_SEND_COMMAND tpmSendCommand = CHANGE_ENDIAN_DWORD(tpmSendCommand); sendBytes( TCTI_CONTEXT_INTEL->tpmSock, (char *)&tpmSendCommand, 4 ); // Send the locality locality = (UINT8)( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.locality; sendBytes( TCTI_CONTEXT_INTEL->tpmSock, (char *)&locality, 1 ); #ifdef SAPI_CLIENT // Send the debug level debugMsgLevel = (UINT8)( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.debugMsgLevel; sendBytes( TCTI_CONTEXT_INTEL->tpmSock, (char *)&debugMsgLevel, 1 ); // Send status bits statusBits = (UINT8)( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.commandSent; statusBits |= ( (UINT8)( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.rmDebugPrefix ) << 1; sendBytes( TCTI_CONTEXT_INTEL->tpmSock, (char *)&statusBits, 1 ); #endif #ifdef DEBUG if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { (*printfFunction)(rmDebugPrefix, "Locality = %d", ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.locality ); } #endif // Send number of bytes. cnt1 = cnt; cnt = CHANGE_ENDIAN_DWORD(cnt); sendBytes( TCTI_CONTEXT_INTEL->tpmSock, (char *)&cnt, 4 ); // Send the TPM command buffer sendBytes( TCTI_CONTEXT_INTEL->tpmSock, (char *)command_buffer, cnt1 ); #ifdef DEBUG if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { DEBUG_PRINT_BUFFER( command_buffer, cnt1 ); } #endif ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.commandSent = 1; return TSS2_RC_SUCCESS; }
UINT32 GetCommandSize( TSS2_SYS_CONTEXT *sysContext ) { return( CHANGE_ENDIAN_DWORD( ((TPM20_Header_In *) SYS_CONTEXT->tpmInBuffPtr)->commandSize ) ); }
// // 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; }
TSS2_RC Tss2_Sys_GetRspAuths( TSS2_SYS_CONTEXT *sysContext, TSS2_SYS_RSP_AUTHS *rspAuthsArray ) { TSS2_RC rval = TSS2_RC_SUCCESS; void *otherData, *otherDataSaved; if( sysContext == NULL || rspAuthsArray == NULL ) { rval = TSS2_SYS_RC_BAD_REFERENCE; } else if( SYS_CONTEXT->previousStage != CMD_STAGE_RECEIVE_RESPONSE || CHANGE_ENDIAN_DWORD( ( (TPM20_Header_Out *)( SYS_CONTEXT->tpmOutBuffPtr ) )->responseCode ) != TPM_RC_SUCCESS || SYS_CONTEXT->authAllowed == 0 ) { rval = TSS2_SYS_RC_BAD_SEQUENCE; } else { int i = 0; if( rspAuthsArray->rspAuthsCount == 0 ) { rval = TSS2_SYS_RC_BAD_VALUE; } else { if( rspAuthsArray->rspAuthsCount != SYS_CONTEXT->authsCount ) { rval = TSS2_SYS_RC_INVALID_SESSIONS; } else { // Get start of authorization area. otherData = SYS_CONTEXT->tpmOutBuffPtr; otherData = (UINT8 *)otherData + sizeof( TPM20_Header_Out ) - 1; otherData = (UINT8 *)otherData + SYS_CONTEXT->numResponseHandles * sizeof( TPM_HANDLE ); otherData = (UINT8 *)otherData + CHANGE_ENDIAN_DWORD( *( SYS_CONTEXT->paramsSize ) ); otherData = (UINT8 *)otherData + sizeof( UINT32 ); otherDataSaved = otherData; if( TPM_ST_SESSIONS == CHANGE_ENDIAN_WORD( ( (TPM20_Header_Out *)( SYS_CONTEXT->tpmOutBuffPtr ) )->tag ) ) { for( i = 0; i < rspAuthsArray->rspAuthsCount; i++ ) { // Before copying, make sure that we aren't going to go past the output buffer + the response size. if( (UINT8 *)otherData > ( SYS_CONTEXT->tpmOutBuffPtr + CHANGE_ENDIAN_DWORD( ( (TPM20_Header_Out *)( SYS_CONTEXT->tpmOutBuffPtr ) )->responseSize ) ) ) { rval = TSS2_SYS_RC_MALFORMED_RESPONSE; break; } otherData = (UINT8 *)otherData + sizeof( UINT16 ) + CHANGE_ENDIAN_WORD( *(UINT16 *)otherData ); // Nonce if( (UINT8 *)otherData > ( SYS_CONTEXT->tpmOutBuffPtr + CHANGE_ENDIAN_DWORD( ( (TPM20_Header_Out *)( SYS_CONTEXT->tpmOutBuffPtr ) )->responseSize ) ) ) { rval = TSS2_SYS_RC_MALFORMED_RESPONSE; break; } otherData = (UINT8 *)otherData + 1; // session attributes. if( (UINT8 *)otherData > ( SYS_CONTEXT->tpmOutBuffPtr + CHANGE_ENDIAN_DWORD( ( (TPM20_Header_Out *)( SYS_CONTEXT->tpmOutBuffPtr ) )->responseSize ) ) ) { rval = TSS2_SYS_RC_MALFORMED_RESPONSE; break; } otherData = (UINT8 *)otherData + sizeof( UINT16 ) + CHANGE_ENDIAN_WORD( *(UINT16 *)otherData ); // hmac if( (UINT8 *)otherData > ( SYS_CONTEXT->tpmOutBuffPtr + CHANGE_ENDIAN_DWORD( ( (TPM20_Header_Out *)( SYS_CONTEXT->tpmOutBuffPtr ) )->responseSize ) ) ) { rval = TSS2_SYS_RC_MALFORMED_RESPONSE; break; } // Make sure that we don't run past the valid authorizations. if( ( i + 1 ) > rspAuthsArray->rspAuthsCount ) { rval = TSS2_SYS_RC_INVALID_SESSIONS; break; } } if( rval == TSS2_RC_SUCCESS ) { // Check that number of auths is equal to the number asked for. // Can't see how this would actually happen, but left it in as a failsafe against // future code modifications. if( i != rspAuthsArray->rspAuthsCount ) { rval = TSS2_SYS_RC_INVALID_SESSIONS; } else { // Get start of authorization area. otherData = otherDataSaved; rval = CopySessionsDataOut( rspAuthsArray, otherData, CHANGE_ENDIAN_WORD( ( (TPM20_Header_Out *)( SYS_CONTEXT->tpmOutBuffPtr ) )->tag ), SYS_CONTEXT->tpmOutBuffPtr, SYS_CONTEXT->maxResponseSize ); } } } } } } return rval; }
TSS2_RC SocketReceiveTpmResponse( TSS2_TCTI_CONTEXT *tctiContext, /* in */ size_t *response_size, /* out */ unsigned char *response_buffer, /* in */ int32_t timeout ) { UINT32 trash; TSS2_RC rval = TSS2_RC_SUCCESS; fd_set readFds; struct timeval tv, *tvPtr; int32_t timeoutMsecs = timeout % 1000; int iResult; unsigned char responseSizeDelta = 0; rval = CommonReceiveChecks( tctiContext, response_size, response_buffer ); if( rval != TSS2_RC_SUCCESS ) { goto retSocketReceiveTpmResponse; } if( timeout == TSS2_TCTI_TIMEOUT_BLOCK ) { tvPtr = 0; } else { tv.tv_sec = timeout / 1000; tv.tv_usec = timeoutMsecs * 1000; tvPtr = &tv; } FD_ZERO( &readFds ); FD_SET( TCTI_CONTEXT_INTEL->tpmSock, &readFds ); iResult = select( TCTI_CONTEXT_INTEL->tpmSock+1, &readFds, 0, 0, tvPtr ); if( iResult == 0 ) { TCTI_LOG( tctiContext, NO_PREFIX, "select failed due to timeout, socket #: 0x%x\n", TCTI_CONTEXT_INTEL->tpmSock ); rval = TSS2_TCTI_RC_TRY_AGAIN; goto retSocketReceiveTpmResponse; } else if( iResult == SOCKET_ERROR ) { TCTI_LOG( tctiContext, NO_PREFIX, "select failed with socket error: %d\n", WSAGetLastError() ); rval = TSS2_TCTI_RC_IO_ERROR; goto retSocketReceiveTpmResponse; } else if ( iResult != 1 ) { TCTI_LOG( tctiContext, NO_PREFIX, "select failed, read the wrong # of bytes: %d\n", iResult ); rval = TSS2_TCTI_RC_IO_ERROR; goto retSocketReceiveTpmResponse; } if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.protocolResponseSizeReceived != 1 ) { // Receive the size of the response. rval = tctiRecvBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)& (((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize ), 4 ); if( rval != TSS2_RC_SUCCESS ) goto retSocketReceiveTpmResponse; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize = CHANGE_ENDIAN_DWORD( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize ); ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.protocolResponseSizeReceived = 1; } if( response_buffer == NULL ) { // In this case, just return the size *response_size = ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.protocolResponseSizeReceived = 1; goto retSocketReceiveTpmResponse; } if( *response_size < ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize ) { *response_size = ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize; rval = TSS2_TCTI_RC_INSUFFICIENT_BUFFER; // If possible, receive tag from TPM. if( *response_size >= sizeof( TPM_ST ) && ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.tagReceived == 0 ) { if( TSS2_RC_SUCCESS != tctiRecvBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)&( ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->tag ), 2 ) ) { goto retSocketReceiveTpmResponse; } else { ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.tagReceived = 1; } } // If possible, receive response size from TPM if( *response_size >= ( sizeof( TPM_ST ) + sizeof( TPM_RC ) ) && ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.responseSizeReceived == 0 ) { if( TSS2_RC_SUCCESS != tctiRecvBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)&( ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->responseSize ), 4 ) ) { goto retSocketReceiveTpmResponse; } else { ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize = CHANGE_ENDIAN_DWORD( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize ); ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.responseSizeReceived = 1; } } } else { if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED && ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize > 0 ) { #ifdef DEBUG TCTI_LOG( tctiContext, NO_PREFIX, "Response Received: " ); #endif #ifdef DEBUG_SOCKETS TCTI_LOG( tctiContext, NO_PREFIX, "from socket #0x%x:\n", TCTI_CONTEXT_INTEL->tpmSock ); #endif } if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.tagReceived == 1 ) { *(TPM_ST *)response_buffer = ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->tag; responseSizeDelta += sizeof( TPM_ST ); response_buffer += sizeof( TPM_ST ); } if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.responseSizeReceived == 1 ) { *(TPM_RC *)response_buffer = CHANGE_ENDIAN_DWORD( ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->responseSize ); responseSizeDelta += sizeof( TPM_RC ); response_buffer += sizeof( TPM_RC ); } // Receive the TPM response. rval = tctiRecvBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)response_buffer, ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize - responseSizeDelta ); if( rval != TSS2_RC_SUCCESS ) goto retSocketReceiveTpmResponse; #ifdef DEBUG if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { DEBUG_PRINT_BUFFER( NO_PREFIX, response_buffer, ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize ); } #endif // Receive the appended four bytes of 0's rval = tctiRecvBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)&trash, 4 ); if( rval != TSS2_RC_SUCCESS ) goto retSocketReceiveTpmResponse; } if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize < *response_size ) { *response_size = ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->responseSize; } ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.commandSent = 0; // Turn cancel off. if( rval == TSS2_RC_SUCCESS ) { rval = (TSS2_RC)PlatformCommand( tctiContext, MS_SIM_CANCEL_OFF ); } else { // Ignore return value so earlier error code is preserved. PlatformCommand( tctiContext, MS_SIM_CANCEL_OFF ); } if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { // TCTI_LOG( tctiContext, NO_PREFIX, "%s sent cancel OFF command:\n", interfaceName ); } retSocketReceiveTpmResponse: if( rval == TSS2_RC_SUCCESS && response_buffer != NULL ) { ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->previousStage = TCTI_STAGE_RECEIVE_RESPONSE; } return rval; }
TSS2_RC SocketSendTpmCommand( TSS2_TCTI_CONTEXT *tctiContext, /* in */ size_t command_size, /* in */ uint8_t *command_buffer /* in */ ) { UINT32 tpmSendCommand = MS_SIM_TPM_SEND_COMMAND; // Value for "send command" to MS simulator. UINT32 cnt, cnt1; UINT8 locality; TSS2_RC rval = TSS2_RC_SUCCESS; #ifdef DEBUG UINT32 commandCode ; #endif #ifdef SAPI_CLIENT UINT8 debugMsgLevel, statusBits; #endif rval = CommonSendChecks( tctiContext, command_buffer ); if( rval != TSS2_RC_SUCCESS ) { goto returnFromSocketSendTpmCommand; } if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { #ifdef DEBUG TCTI_LOG( tctiContext, NO_PREFIX, "\n" ); commandCode = CHANGE_ENDIAN_DWORD( ( (TPM20_Header_In *)command_buffer )->commandCode ); if( commandCode >= TPM_CC_NV_UndefineSpaceSpecial && commandCode <= TPM_CC_PolicyNvWritten ) TCTI_LOG( tctiContext, NO_PREFIX, "Cmd sent: %s\n", strTpmCommandCode( commandCode ) ); else TCTI_LOG( tctiContext, NO_PREFIX, "Cmd sent: 0x%4.4x\n", CHANGE_ENDIAN_DWORD(commandCode ) ); #endif #ifdef DEBUG_SOCKETS TCTI_LOG( tctiContext, NO_PREFIX, "Command sent on socket #0x%x: %s\n", TCTI_CONTEXT_INTEL->tpmSock, strTpmCommandCode( commandCode ) ); #endif } // Size TPM 1.2 and TPM 2.0 headers overlap exactly, we can use // either 1.2 or 2.0 header to get the size. cnt = CHANGE_ENDIAN_DWORD(((TPM20_Header_In *) command_buffer)->commandSize); // Send TPM_SEND_COMMAND tpmSendCommand = CHANGE_ENDIAN_DWORD(tpmSendCommand); rval = tctiSendBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)&tpmSendCommand, 4 ); if( rval != TSS2_RC_SUCCESS ) goto returnFromSocketSendTpmCommand; // Send the locality locality = (UINT8)( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.locality; rval = tctiSendBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)&locality, 1 ); if( rval != TSS2_RC_SUCCESS ) goto returnFromSocketSendTpmCommand; #ifdef SAPI_CLIENT // Send the debug level debugMsgLevel = (UINT8)( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.debugMsgLevel; rval = tctiSendBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)&debugMsgLevel, 1 ); if( rval != TSS2_RC_SUCCESS ) goto returnFromSocketSendTpmCommand; // Send status bits statusBits = (UINT8)( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.commandSent; statusBits |= ( (UINT8)( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.rmDebugPrefix ) << 1; rval = tctiSendBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)&statusBits, 1 ); if( rval != TSS2_RC_SUCCESS ) goto returnFromSocketSendTpmCommand; #endif #ifdef DEBUG if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { TCTI_LOG( tctiContext, NO_PREFIX, "Locality = %d", ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.locality ); } #endif // Send number of bytes. cnt1 = cnt; cnt = CHANGE_ENDIAN_DWORD(cnt); rval = tctiSendBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)&cnt, 4 ); if( rval != TSS2_RC_SUCCESS ) goto returnFromSocketSendTpmCommand; // Send the TPM command buffer rval = tctiSendBytes( tctiContext, TCTI_CONTEXT_INTEL->tpmSock, (unsigned char *)command_buffer, cnt1 ); if( rval != TSS2_RC_SUCCESS ) goto returnFromSocketSendTpmCommand; #ifdef DEBUG if( ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext )->status.debugMsgLevel == TSS2_TCTI_DEBUG_MSG_ENABLED ) { DEBUG_PRINT_BUFFER( NO_PREFIX, command_buffer, cnt1 ); } #endif ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.commandSent = 1; returnFromSocketSendTpmCommand: if( rval == TSS2_RC_SUCCESS ) { ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->previousStage = TCTI_STAGE_SEND_COMMAND; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.tagReceived = 0; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.responseSizeReceived = 0; ((TSS2_TCTI_CONTEXT_INTEL *)tctiContext)->status.protocolResponseSizeReceived = 0; } return rval; }