TCG TIS 1.3 compliant TPM driver to use the TPM as hardware crypto library.
The TPM 2.0 architecture, commands and structures are defined in the set of 4 Trusted Platform Module Library Specification, Family "2.0" specifications that that can be found at http://www.trustedcomputinggroup.org/resources/tpm_library_specification
The "PC Client Specific TPM Interface Specification (TIS), Version 1.3" that was used for this implementation can be found at http://www.trustedcomputinggroup.org/resources/pc_client_work_group_pc_client_specific_tpm_interface_specification_tis
All the information to get going is in SPITIS_TPM20.h!
TPMCommands.cpp
- Committer:
- LordOfDorks
- Date:
- 2015-04-11
- Revision:
- 4:77fecfe49437
- Parent:
- 3:4b9ad18eae02
File content as of revision 4:77fecfe49437:
/* mbed TCG SPI TPM 2.0 TIS 1.3 driver, * Copyright (c) 2015, Microsoft Coprporation Inc. * by Stefan Thom (LordOfDorks) StefanTh@Microsoft.com, Stefan@ThomsR.Us * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ #include "SPITIS_TPM20.h" #include "TPM20Tables.h" TPM_RC TIS_TPM20::ParseResponseHeader(TPM_ST* tag, UINT32* rspSize, uint8_t** buffer, int32_t* size) { TPM_RC tpmRC = TPM_RC_SUCCESS; if((TPM_ST_Unmarshal(tag, buffer, size) != TPM_RC_SUCCESS) || (UINT32_Unmarshal(rspSize, buffer, size) != TPM_RC_SUCCESS) || (TPM_RC_Unmarshal(&tpmRC, buffer, size) != TPM_RC_SUCCESS) || ((*tag != TPM_ST_SESSIONS) && (*tag != TPM_ST_NO_SESSIONS))) { tpmRC = TPM_RC_FAILURE; } return tpmRC; } #ifndef TPM_TPM_TIS_NO_COMMAND_FILTERING TIS_TPM20::TIS_RESULT TIS_TPM20::ApplyFilter(TIS_TPM20::TIS_LOCALITY locality, uint8_t* pbCmd, uint32_t cbCmd) { uint8_t* buffer = pbCmd; int32_t size = (int32_t)cbCmd; TPM_ST tag = 0; UINT32 cmdSize = 0; TPM_CC ordinal = 0; int32_t handleCount = -1; // Read the header if((TPM_ST_Unmarshal(&tag, &buffer, &size) != TPM_RC_SUCCESS) || (UINT32_Unmarshal(&cmdSize, &buffer, &size) != TPM_RC_SUCCESS) || (TPM_CC_Unmarshal(&ordinal, &buffer, &size) != TPM_RC_SUCCESS) || ((tag != TPM_ST_SESSIONS) && (tag != TPM_ST_NO_SESSIONS))) { return TIS_SESSION_RESULT_FILTERED; } // First filter ordinals based on locality if(locality == TIS_LOCALITY_0) { switch(ordinal) { // We will not allow certain commands from locality 0 - aka externally exposed TPM access case TPM_CC_ChangeEPS: case TPM_CC_ChangePPS: case TPM_CC_Clear: case TPM_CC_ClearControl: case TPM_CC_ClockSet: case TPM_CC_PCR_Allocate: case TPM_CC_PCR_SetAuthPolicy: case TPM_CC_Shutdown: return TIS_SESSION_RESULT_FILTERED; default: break; } } // Lookup the number of handles in the command for(uint32_t n = 0; s_ccAttr[n].commandIndex != 0x0000 ;n++) { if(s_ccAttr[n].commandIndex == ordinal) { handleCount = s_ccAttr[n].cHandles; break; } } // Easy elimination of invalid cases if((handleCount < 0) || (handleCount > 3)) { return TIS_SESSION_RESULT_FILTERED; } // Read the handles from the command and see if they are allowed for(uint32_t n = 0 ;n < handleCount; n++) { TPM_HANDLE handle = TPM_RH_NULL; if(TPM_HANDLE_Unmarshal(&handle, &buffer, &size) != TPM_RC_SUCCESS) { return TIS_SESSION_RESULT_FILTERED; } if(locality == TIS_LOCALITY_0) { switch(handle) { // We will not allow the platform entity to be used from locality 0 case TPM_RH_PLATFORM: return TIS_SESSION_RESULT_FILTERED; default: break; } } } return TIS_SESSION_RESULT_COMPLETE; } #endif TPM_RC TIS_TPM20::TPM2_Startup( TPM_SU startupType ) { TIS_TPM20::TIS_RESULT result = TIS_TPM20::TIS_SESSION_RESULT_COMPLETE; const uint32_t maxSize = 100; // Educated guess uint8_t* pbBuffer = NULL; uint32_t cbRsp = 0; uint8_t* buffer = NULL; int32_t size = 0; uint32_t cursor = 0; TPM_ST tag = TPM_ST_NO_SESSIONS; TPM_CC commandCode = TPM_CC_Startup; TPM_RC tpmRC = TPM_RC_SUCCESS; if((pbBuffer = new uint8_t[maxSize]) == NULL) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } size = maxSize; buffer = pbBuffer; // Marshal the command cursor += TPM_ST_Marshal(&tag, &buffer, &size); cursor += UINT32_Marshal(&cursor, &buffer, &size); cursor += TPM_CC_Marshal(&commandCode, &buffer, &size); cursor += TPM_SU_Marshal(&startupType, &buffer, &size); if(size < 0) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Fill in the command size buffer = &pbBuffer[sizeof(TPM_ST)]; size = sizeof(UINT32); UINT32_Marshal(&cursor, &buffer, &size); // Send the command if(SendCommand(pbBuffer, cursor) != TIS_SESSION_RESULT_COMPLETE) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Wait for response while((result = RetrieveResponse(pbBuffer, maxSize, &cbRsp)) == TIS_SESSION_RESULT_PENDING) { wait_us(1000); } // Look at the result buffer = pbBuffer; size = (int32_t)cbRsp; tpmRC = TPM_RC_FAILURE; if((result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) || ((tpmRC = ParseResponseHeader(&tag, &cursor, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } Cleanup: #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_Startup.ResponseCode = 0x%08x\n\r", tpmRC); #endif if(pbBuffer != NULL) { delete[] pbBuffer; pbBuffer = NULL; } return tpmRC; } uint32_t TIS_TPM20::TPM2_Shutdown( uint16_t shutdownType ) { TIS_TPM20::TIS_RESULT result = TIS_TPM20::TIS_SESSION_RESULT_COMPLETE; const uint32_t maxSize = 100; // Educated guess uint8_t* pbBuffer = NULL; uint32_t cbRsp = 0; uint8_t* buffer = NULL; int32_t size = 0; uint32_t cursor = 0; TPM_ST tag = TPM_ST_NO_SESSIONS; TPM_CC commandCode = TPM_CC_Shutdown; TPM_RC tpmRC = TPM_RC_SUCCESS; if((pbBuffer = new uint8_t[maxSize]) == NULL) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } size = maxSize; buffer = pbBuffer; // Marshal the command cursor += TPM_ST_Marshal(&tag, &buffer, &size); cursor += UINT32_Marshal(&cursor, &buffer, &size); cursor += TPM_CC_Marshal(&commandCode, &buffer, &size); cursor += TPM_SU_Marshal(&shutdownType, &buffer, &size); if(size < 0) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Fill in the command size buffer = &pbBuffer[sizeof(TPM_ST)]; size = sizeof(UINT32); UINT32_Marshal(&cursor, &buffer, &size); if(SendCommand(pbBuffer, cursor) != TIS_SESSION_RESULT_COMPLETE) { return TPM_RC_FAILURE; } while((result = RetrieveResponse(pbBuffer, maxSize, &cbRsp)) == TIS_SESSION_RESULT_PENDING) { wait_us(1000); } // Look at the result buffer = pbBuffer; size = (int32_t)cbRsp; tpmRC = TPM_RC_FAILURE; if((result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) || ((tpmRC = ParseResponseHeader(&tag, &cursor, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } Cleanup: #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_Shutdown.ResponseCode = 0x%08x\n\r", tpmRC); #endif if(pbBuffer != NULL) { delete[] pbBuffer; pbBuffer = NULL; } return tpmRC; } uint32_t TIS_TPM20::TPM2_GetRandom( TPM2B_DIGEST* random ) { TIS_TPM20::TIS_RESULT result = TIS_TPM20::TIS_SESSION_RESULT_COMPLETE; const uint32_t maxSize = 100; // Educated guess uint8_t* pbBuffer = NULL; uint32_t cbRsp = 0; uint8_t* buffer = NULL; int32_t size = 0; uint32_t cursor = 0; TPM_ST tag = TPM_ST_NO_SESSIONS; TPM_CC commandCode = TPM_CC_GetRandom; TPM_RC tpmRC = TPM_RC_SUCCESS; if((pbBuffer = new uint8_t[maxSize]) == NULL) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } size = maxSize; buffer = pbBuffer; // Marshal the command cursor += TPM_ST_Marshal(&tag, &buffer, &size); cursor += UINT32_Marshal(&cursor, &buffer, &size); cursor += TPM_CC_Marshal(&commandCode, &buffer, &size); cursor += UINT16_Marshal(&random->t.size, &buffer, &size); if(size < 0) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Fill in the command size buffer = &pbBuffer[sizeof(TPM_ST)]; size = sizeof(UINT32); UINT32_Marshal(&cursor, &buffer, &size); if((result = SendCommand(pbBuffer, cursor)) != TIS_SESSION_RESULT_COMPLETE) { return TPM_RC_FAILURE; } while((result = RetrieveResponse(pbBuffer, maxSize, &cbRsp)) == TIS_SESSION_RESULT_PENDING) { wait_us(1000); } if(result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Look at the result buffer = pbBuffer; size = (int32_t)cbRsp; tpmRC = TPM_RC_FAILURE; if((result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) || ((tpmRC = ParseResponseHeader(&tag, &cursor, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } // Copy the parameters out if((tpmRC = TPM2B_DIGEST_Unmarshal(random, &buffer, &size)) != TPM_RC_SUCCESS) { goto Cleanup; } Cleanup: #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_GetRandom.ResponseCode = 0x%08x\n\r", tpmRC); #endif if(pbBuffer != NULL) { delete[] pbBuffer; pbBuffer = NULL; } return tpmRC; } uint32_t TIS_TPM20::TPM2_StirRandom( TPM2B_DIGEST* seed ) { TIS_TPM20::TIS_RESULT result = TIS_TPM20::TIS_SESSION_RESULT_COMPLETE; const uint32_t maxSize = 100; // Educated guess uint8_t* pbBuffer = NULL; uint32_t cbRsp = 0; uint8_t* buffer = NULL; int32_t size = 0; uint32_t cursor = 0; TPM_ST tag = TPM_ST_NO_SESSIONS; TPM_CC commandCode = TPM_CC_StirRandom; TPM_RC tpmRC = TPM_RC_SUCCESS; if((pbBuffer = new uint8_t[maxSize]) == NULL) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } size = maxSize; buffer = pbBuffer; // Marshal the command cursor += TPM_ST_Marshal(&tag, &buffer, &size); cursor += UINT32_Marshal(&cursor, &buffer, &size); cursor += TPM_CC_Marshal(&commandCode, &buffer, &size); cursor += TPM2B_DIGEST_Marshal(seed, &buffer, &size); if(size < 0) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Fill in the command size buffer = &pbBuffer[sizeof(TPM_ST)]; size = sizeof(UINT32); UINT32_Marshal(&cursor, &buffer, &size); if((result = SendCommand(pbBuffer, cursor)) != TIS_SESSION_RESULT_COMPLETE) { return TPM_RC_FAILURE; } while((result = RetrieveResponse(pbBuffer, maxSize, &cbRsp)) == TIS_SESSION_RESULT_PENDING) { wait_us(1000); } if(result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Look at the result buffer = pbBuffer; size = (int32_t)cbRsp; tpmRC = TPM_RC_FAILURE; if((result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) || ((tpmRC = ParseResponseHeader(&tag, &cursor, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } Cleanup: #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_StirRandom.ResponseCode = 0x%08x\n\r", tpmRC); #endif if(pbBuffer != NULL) { delete[] pbBuffer; pbBuffer = NULL; } return tpmRC; } TPM_RC TIS_TPM20::TPM2_HMAC_Start( TPMI_DH_OBJECT handle, TPM2B_AUTH* handleAuth, TPM2B_AUTH* auth, TPMI_ALG_HASH hashAlg, TPMI_DH_OBJECT* sequenceHandle ) { TIS_TPM20::TIS_RESULT result = TIS_TPM20::TIS_SESSION_RESULT_COMPLETE; const uint32_t maxSize = 100; // Educated guess uint8_t* pbBuffer = NULL; uint32_t cbRsp = 0; uint8_t* buffer = NULL; int32_t size = 0; uint32_t cursor = 0; TPM_ST tag = TPM_ST_SESSIONS; TPM_CC commandCode = TPM_CC_HMAC_Start; TPM_RC tpmRC = TPM_RC_SUCCESS; TPM_HANDLE sessionHandle = TPM_RS_PW; TPMA_SESSION sessionAttributes = {0}; UINT16 nonce = 0; UINT32 paramStart = sizeof(sessionHandle) + sizeof(nonce) + sizeof(sessionAttributes) + sizeof(handleAuth->t.size) + handleAuth->t.size; if((pbBuffer = new uint8_t[maxSize]) == NULL) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } size = maxSize; buffer = pbBuffer; // Marshal the command cursor += TPM_ST_Marshal(&tag, &buffer, &size); cursor += UINT32_Marshal(&cursor, &buffer, &size); cursor += TPM_CC_Marshal(&commandCode, &buffer, &size); // Object handles cursor += TPM_HANDLE_Marshal(&handle, &buffer, &size); // Authorization session sessionAttributes.continueSession = YES; cursor += UINT32_Marshal(¶mStart, &buffer, &size); cursor += TPM_HANDLE_Marshal(&sessionHandle, &buffer, &size); cursor += UINT16_Marshal(&nonce, &buffer, &size); cursor += TPMA_SESSION_Marshal(&sessionAttributes, &buffer, &size); cursor += TPM2B_AUTH_Marshal(handleAuth, &buffer, &size); // Parameters cursor += TPM2B_AUTH_Marshal(auth, &buffer, &size); cursor += TPM_ALG_ID_Marshal(&hashAlg, &buffer, &size); if(size < 0) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Fill in the command size buffer = &pbBuffer[sizeof(TPM_ST)]; size = sizeof(UINT32); UINT32_Marshal(&cursor, &buffer, &size); if((result = SendCommand(pbBuffer, cursor)) != TIS_SESSION_RESULT_COMPLETE) { return TPM_RC_FAILURE; } while((result = RetrieveResponse(pbBuffer, maxSize, &cbRsp)) == TIS_SESSION_RESULT_PENDING) { wait_us(1000); } if(result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Look at the result buffer = pbBuffer; size = (int32_t)cbRsp; tpmRC = TPM_RC_FAILURE; if((result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) || ((tpmRC = ParseResponseHeader(&tag, &cursor, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } // Copy the parameters out if((tpmRC = TPM_HANDLE_Unmarshal(sequenceHandle, &buffer, &size)) != TPM_RC_SUCCESS) { goto Cleanup; } // Ignore the return session Cleanup: #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_HMAC_Start.ResponseCode = 0x%08x\n\r", tpmRC); #endif if(pbBuffer != NULL) { delete[] pbBuffer; pbBuffer = NULL; } return tpmRC; } TPM_RC TIS_TPM20::TPM2_HashSequenceStart( TPM2B_AUTH* auth, TPMI_ALG_HASH hashAlg, TPMI_DH_OBJECT* sequenceHandle ) { TIS_TPM20::TIS_RESULT result = TIS_TPM20::TIS_SESSION_RESULT_COMPLETE; const uint32_t maxSize = 100; // Educated guess uint8_t* pbBuffer = NULL; uint32_t cbRsp = 0; uint8_t* buffer = NULL; int32_t size = 0; uint32_t cursor = 0; TPM_ST tag = TPM_ST_NO_SESSIONS; TPM_CC commandCode = TPM_CC_HashSequenceStart; TPM_RC tpmRC = TPM_RC_SUCCESS; if((pbBuffer = new uint8_t[maxSize]) == NULL) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } size = maxSize; buffer = pbBuffer; // Marshal the command cursor += TPM_ST_Marshal(&tag, &buffer, &size); cursor += UINT32_Marshal(&cursor, &buffer, &size); cursor += TPM_CC_Marshal(&commandCode, &buffer, &size); cursor += TPM2B_AUTH_Marshal(auth, &buffer, &size); cursor += TPM_ALG_ID_Marshal(&hashAlg, &buffer, &size); if(size < 0) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Fill in the command size buffer = &pbBuffer[sizeof(TPM_ST)]; size = sizeof(UINT32); UINT32_Marshal(&cursor, &buffer, &size); if((result = SendCommand(pbBuffer, cursor)) != TIS_SESSION_RESULT_COMPLETE) { return TPM_RC_FAILURE; } while((result = RetrieveResponse(pbBuffer, maxSize, &cbRsp)) == TIS_SESSION_RESULT_PENDING) { wait_us(1000); } if(result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Look at the result buffer = pbBuffer; size = (int32_t)cbRsp; tpmRC = TPM_RC_FAILURE; if((result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) || ((tpmRC = ParseResponseHeader(&tag, &cursor, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } // Copy the parameters out if((tpmRC = TPM_HANDLE_Unmarshal(sequenceHandle, &buffer, &size)) != TPM_RC_SUCCESS) { goto Cleanup; } Cleanup: #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_HashSequenceStart.ResponseCode = 0x%08x\n\r", tpmRC); #endif if(pbBuffer != NULL) { delete[] pbBuffer; pbBuffer = NULL; } return tpmRC; } TPM_RC TIS_TPM20::TPM2_SequenceUpdate( TPMI_DH_OBJECT sequenceHandle, TPM2B_AUTH* sequenceHandleAuth, uint8_t* pbData, uint16_t cbData ) { TIS_TPM20::TIS_RESULT result = TIS_TPM20::TIS_SESSION_RESULT_COMPLETE; const uint32_t maxSize = 100; // Educated guess uint8_t* pbBuffer = NULL; uint32_t cbRsp = 0; uint8_t* buffer = NULL; int32_t size = 0; uint32_t cursor = 0; TPM_ST tag = TPM_ST_SESSIONS; TPM_CC commandCode = TPM_CC_SequenceUpdate; TPM_RC tpmRC = TPM_RC_SUCCESS; TPM_HANDLE sessionHandle = TPM_RS_PW; TPMA_SESSION sessionAttributes = {0}; UINT16 nonce = 0; UINT32 paramStart = sizeof(TPM_HANDLE) + sizeof(UINT16) + sizeof(UINT8) + sizeof(sequenceHandleAuth->t.size) + sequenceHandleAuth->t.size; if((pbBuffer = new uint8_t[maxSize]) == NULL) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } size = maxSize; buffer = pbBuffer; // Marshal the command cursor += TPM_ST_Marshal(&tag, &buffer, &size); cursor += UINT32_Marshal(&cursor, &buffer, &size); cursor += TPM_CC_Marshal(&commandCode, &buffer, &size); // Object handles cursor += TPM_HANDLE_Marshal(&sequenceHandle, &buffer, &size); // Authorization session sessionAttributes.continueSession = YES; cursor += UINT32_Marshal(¶mStart, &buffer, &size); cursor += TPM_HANDLE_Marshal(&sessionHandle, &buffer, &size); cursor += UINT16_Marshal(&nonce, &buffer, &size); cursor += TPMA_SESSION_Marshal(&sessionAttributes, &buffer, &size); cursor += TPM2B_AUTH_Marshal(sequenceHandleAuth, &buffer, &size); // Parameter cursor += UINT16_Marshal(&cbData, &buffer, &size); if(size < 0) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Fill in the command size cursor += cbData; // Add the trailing data! buffer = &pbBuffer[sizeof(TPM_ST)]; size = sizeof(UINT32); UINT32_Marshal(&cursor, &buffer, &size); if((result = SendCommand(pbBuffer, cursor - cbData, pbData, cbData)) != TIS_SESSION_RESULT_COMPLETE) { return TPM_RC_FAILURE; } while((result = RetrieveResponse(pbBuffer, maxSize, &cbRsp)) == TIS_SESSION_RESULT_PENDING) { wait_us(1000); } if(result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Look at the result buffer = pbBuffer; size = (int32_t)cbRsp; tpmRC = TPM_RC_FAILURE; if((result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) || ((tpmRC = ParseResponseHeader(&tag, &cursor, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } // Ignore the return session Cleanup: #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_SequenceUpdate.ResponseCode = 0x%08x\n\r", tpmRC); #endif if(pbBuffer != NULL) { delete[] pbBuffer; pbBuffer = NULL; } return tpmRC; } TPM_RC TIS_TPM20::TPM2_SequenceComplete( TPMI_DH_OBJECT sequenceHandle, TPM2B_AUTH* sequenceHandleAuth, TPMI_RH_HIERARCHY hierarchy, TPM2B_DIGEST* digest, TPMT_TK_HASHCHECK* validation ) { TIS_TPM20::TIS_RESULT result = TIS_TPM20::TIS_SESSION_RESULT_COMPLETE; const uint32_t maxSize = 100; // Educated guess uint8_t* pbBuffer = NULL; uint32_t cbRsp = 0; uint8_t* buffer = NULL; int32_t size = 0; uint32_t cursor = 0; TPM_ST tag = TPM_ST_SESSIONS; TPM_CC commandCode = TPM_CC_SequenceComplete; TPM_RC tpmRC = TPM_RC_SUCCESS; TPM_HANDLE sessionHandle = TPM_RS_PW; TPMA_SESSION sessionAttributes = {0}; UINT16 nonce = 0; UINT32 paramStart = sizeof(sessionHandle) + sizeof(nonce) + sizeof(UINT8) + sizeof(sequenceHandleAuth->t.size) + sequenceHandleAuth->t.size; if((pbBuffer = new uint8_t[maxSize]) == NULL) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } size = maxSize; buffer = pbBuffer; // Marshal the command cursor += TPM_ST_Marshal(&tag, &buffer, &size); cursor += UINT32_Marshal(&cursor, &buffer, &size); cursor += TPM_CC_Marshal(&commandCode, &buffer, &size); // Object handles cursor += TPM_HANDLE_Marshal(&sequenceHandle, &buffer, &size); // Authorization session sessionAttributes.continueSession = YES; cursor += UINT32_Marshal(¶mStart, &buffer, &size); cursor += TPM_HANDLE_Marshal(&sessionHandle, &buffer, &size); cursor += UINT16_Marshal(&nonce, &buffer, &size); cursor += TPMA_SESSION_Marshal(&sessionAttributes, &buffer, &size); cursor += TPM2B_AUTH_Marshal(sequenceHandleAuth, &buffer, &size); // Parameters cursor += UINT16_Marshal(&nonce, &buffer, &size); cursor += TPM_HANDLE_Marshal(&hierarchy, &buffer, &size); if(size < 0) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Fill in the command size buffer = &pbBuffer[sizeof(TPM_ST)]; size = sizeof(UINT32); UINT32_Marshal(&cursor, &buffer, &size); if((result = SendCommand(pbBuffer, cursor)) != TIS_SESSION_RESULT_COMPLETE) { return TPM_RC_FAILURE; } while((result = RetrieveResponse(pbBuffer, maxSize, &cbRsp)) == TIS_SESSION_RESULT_PENDING) { wait_us(1000); } if(result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Look at the result buffer = pbBuffer; size = (int32_t)cbRsp; tpmRC = TPM_RC_FAILURE; if((result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) || ((tpmRC = ParseResponseHeader(&tag, &cursor, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } // Read the parameter Size if((tpmRC = UINT32_Unmarshal(¶mStart, &buffer, &size)) != TPM_RC_SUCCESS) { goto Cleanup; } // Copy the parameters out if(((tpmRC = TPM2B_DIGEST_Unmarshal(digest, &buffer, &size)) != TPM_RC_SUCCESS) || ((tpmRC = TPMT_TK_HASHCHECK_Unmarshal(validation, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } // Ignore the return session Cleanup: #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_SequenceComplete.ResponseCode = 0x%08x\n\r", tpmRC); #endif if(pbBuffer != NULL) { delete[] pbBuffer; pbBuffer = NULL; } return tpmRC; } TPM_RC TIS_TPM20::TPM2_EventSequenceComplete( TPMI_DH_PCR pcrHandle, TPM2B_AUTH* pcrAuth, TPMI_DH_OBJECT sequenceHandle, TPM2B_AUTH* sequenceHandleAuth, TPML_DIGEST_VALUES* results ) { TIS_TPM20::TIS_RESULT result = TIS_TPM20::TIS_SESSION_RESULT_COMPLETE; const uint32_t maxSize = 100; // Educated guess uint8_t* pbBuffer = NULL; uint32_t cbRsp = 0; uint8_t* buffer = NULL; int32_t size = 0; uint32_t cursor = 0; TPM_ST tag = TPM_ST_SESSIONS; TPM_CC commandCode = TPM_CC_EventSequenceComplete; TPM_RC tpmRC = TPM_RC_SUCCESS; TPM_HANDLE sessionHandle = TPM_RS_PW; TPMA_SESSION sessionAttributes = {0}; UINT16 nonce = 0; UINT32 paramStart = sizeof(sessionHandle) + sizeof(nonce) + sizeof(UINT8) + sizeof(pcrAuth->t.size) + pcrAuth->t.size + sizeof(sessionHandle) + sizeof(nonce) + sizeof(UINT8) + sizeof(sequenceHandleAuth->t.size) + sequenceHandleAuth->t.size; if((pbBuffer = new uint8_t[maxSize]) == NULL) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } size = maxSize; buffer = pbBuffer; // Marshal the command cursor += TPM_ST_Marshal(&tag, &buffer, &size); cursor += UINT32_Marshal(&cursor, &buffer, &size); cursor += TPM_CC_Marshal(&commandCode, &buffer, &size); // Object handles cursor += TPM_HANDLE_Marshal(&pcrHandle, &buffer, &size); cursor += TPM_HANDLE_Marshal(&sequenceHandle, &buffer, &size); // Authorization sessions sessionAttributes.continueSession = YES; cursor += UINT32_Marshal(¶mStart, &buffer, &size); cursor += TPM_HANDLE_Marshal(&sessionHandle, &buffer, &size); cursor += UINT16_Marshal(&nonce, &buffer, &size); cursor += TPMA_SESSION_Marshal(&sessionAttributes, &buffer, &size); cursor += TPM2B_AUTH_Marshal(pcrAuth, &buffer, &size); cursor += TPM_HANDLE_Marshal(&sessionHandle, &buffer, &size); cursor += UINT16_Marshal(&nonce, &buffer, &size); cursor += TPMA_SESSION_Marshal(&sessionAttributes, &buffer, &size); cursor += TPM2B_AUTH_Marshal(sequenceHandleAuth, &buffer, &size); // Parameters cursor += UINT16_Marshal(&nonce, &buffer, &size); if(size < 0) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Fill in the command size buffer = &pbBuffer[sizeof(TPM_ST)]; size = sizeof(UINT32); UINT32_Marshal(&cursor, &buffer, &size); if((result = SendCommand(pbBuffer, cursor)) != TIS_SESSION_RESULT_COMPLETE) { return TPM_RC_FAILURE; } while((result = RetrieveResponse(pbBuffer, maxSize, &cbRsp)) == TIS_SESSION_RESULT_PENDING) { wait_us(1000); } if(result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Look at the result buffer = pbBuffer; size = (int32_t)cbRsp; tpmRC = TPM_RC_FAILURE; if((result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) || ((tpmRC = ParseResponseHeader(&tag, &cursor, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } // Read the parameter Size if((tpmRC = UINT32_Unmarshal(¶mStart, &buffer, &size)) != TPM_RC_SUCCESS) { goto Cleanup; } // Copy the parameters out if((tpmRC = TPML_DIGEST_VALUES_Unmarshal(results, &buffer, &size)) != TPM_RC_SUCCESS) { goto Cleanup; } // Ignore return sessions Cleanup: #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_EventSequenceComplete.ResponseCode = 0x%08x\n\r", tpmRC); #endif if(pbBuffer != NULL) { delete[] pbBuffer; pbBuffer = NULL; } return tpmRC; } TPM_RC TIS_TPM20::TPM2_PCR_Read( TPML_PCR_SELECTION* pcrSelectionIn, uint32_t* pcrUpdateCounter, TPML_PCR_SELECTION* pcrSelectionOut, TPML_DIGEST* pcrValues) { TIS_TPM20::TIS_RESULT result = TIS_TPM20::TIS_SESSION_RESULT_COMPLETE; const uint32_t maxSize = 100; // Educated guess uint8_t* pbBuffer = NULL; uint32_t cbRsp = 0; uint8_t* buffer = NULL; int32_t size = 0; uint32_t cursor = 0; TPM_ST tag = TPM_ST_NO_SESSIONS; TPM_CC commandCode = TPM_CC_PCR_Read; TPM_RC tpmRC = TPM_RC_SUCCESS; if((pbBuffer = new uint8_t[maxSize]) == NULL) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } size = maxSize; buffer = pbBuffer; // Marshal the command cursor += TPM_ST_Marshal(&tag, &buffer, &size); cursor += UINT32_Marshal(&cursor, &buffer, &size); cursor += TPM_CC_Marshal(&commandCode, &buffer, &size); cursor += TPML_PCR_SELECTION_Marshal(pcrSelectionIn, &buffer, &size); if(size < 0) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Fill in the command size buffer = &pbBuffer[sizeof(TPM_ST)]; size = sizeof(UINT32); UINT32_Marshal(&cursor, &buffer, &size); #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_PCR_Read()\n\r"); #endif if((result = SendCommand(pbBuffer, cursor)) != TIS_SESSION_RESULT_COMPLETE) { return TPM_RC_FAILURE; } while((result = RetrieveResponse(pbBuffer, maxSize, &cbRsp)) == TIS_SESSION_RESULT_PENDING) { wait_us(1000); } if((result != TIS_TPM20::TIS_SESSION_RESULT_COMPLETE) || (cbRsp < 10)) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } // Look at the response header buffer = pbBuffer; size = (INT32)cbRsp; if((TPM_ST_Unmarshal(&tag, &buffer, &size) != TPM_RC_SUCCESS) || (UINT32_Unmarshal(&cursor, &buffer, &size) != TPM_RC_SUCCESS) || (TPM_RC_Unmarshal(&tpmRC, &buffer, &size) != TPM_RC_SUCCESS) || ((tag != TPM_ST_SESSIONS) && (tag != TPM_ST_NO_SESSIONS)) || (cursor != cbRsp)) { tpmRC = TPM_RC_FAILURE; goto Cleanup; } if(tpmRC != TPM_RC_SUCCESS) { goto Cleanup; } // Unmarshal the rest if(((tpmRC = UINT32_Unmarshal(pcrUpdateCounter, &buffer, &size)) != TPM_RC_SUCCESS) || ((tpmRC = TPML_PCR_SELECTION_Unmarshal(pcrSelectionOut, &buffer, &size)) != TPM_RC_SUCCESS) || ((tpmRC = TPML_DIGEST_Unmarshal(pcrValues, &buffer, &size)) != TPM_RC_SUCCESS)) { goto Cleanup; } // If there is trailing data if(size > 0) { tpmRC = TPM_RC_SIZE; goto Cleanup; } Cleanup: #ifdef TPM_TIS_DEBUG_OUTPUT printf("TIS.TPM2_PCR_Read.ResponseCode = 0x%08x\n\r", tpmRC); #endif if(pbBuffer != NULL) { delete[] pbBuffer; pbBuffer = NULL; } return tpmRC; }