From 6c5ba7c0b4d3d1694a2cdf2d6c5365027534ef5a Mon Sep 17 00:00:00 2001 From: Chris Engel Date: Fri, 28 Aug 2015 10:46:52 -0500 Subject: Trustedboot add support for PCR Extend Change-Id: I05614ef6c3e5d68e0b512ec6b69a0b6054a9d7b4 RTC: 125288 ForwardPort: yes Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/790 Reviewed-by: Stephen M. Cprek Reviewed-by: Timothy R. Block Reviewed-by: Daniel M. Crowell Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22366 Tested-by: Jenkins Server Reviewed-by: Christopher J. Engel Tested-by: FSP CI Jenkins --- .../usr/secureboot/trustedboot_reasoncodes.H | 3 + src/usr/secureboot/trusted/base/trustedboot_base.C | 33 ++-- src/usr/secureboot/trusted/test/trustedbootTest.H | 167 ++++++++++++++++++- src/usr/secureboot/trusted/trustedTypes.C | 85 ++++++++++ src/usr/secureboot/trusted/trustedTypes.H | 41 +++++ src/usr/secureboot/trusted/trustedboot.C | 20 +++ src/usr/secureboot/trusted/trustedboot.H | 15 +- src/usr/secureboot/trusted/trustedbootCmds.C | 182 ++++++++++++++++++++- src/usr/secureboot/trusted/trustedbootCmds.H | 14 ++ 9 files changed, 539 insertions(+), 21 deletions(-) diff --git a/src/include/usr/secureboot/trustedboot_reasoncodes.H b/src/include/usr/secureboot/trustedboot_reasoncodes.H index 77d237012..6cad6ebd7 100644 --- a/src/include/usr/secureboot/trustedboot_reasoncodes.H +++ b/src/include/usr/secureboot/trustedboot_reasoncodes.H @@ -50,6 +50,7 @@ namespace TRUSTEDBOOT MOD_TPM_MARSHALCMDDATA = 0x04, MOD_TPM_UNMARSHALRESPDATA = 0x05, MOD_TPM_VERIFYFUNCTIONAL = 0x06, + MOD_TPM_CMD_PCREXTEND = 0x07, MOD_TPMLOGMGR_INITIALIZE = 0x10, MOD_TPMLOGMGR_ADDEVENT = 0x11, @@ -73,6 +74,8 @@ namespace TRUSTEDBOOT RC_TPMLOGMGR_ADDEVENTMARSH_FAIL = SECURE_COMP_ID | 0xAB, RC_TPMLOGMGR_INIT_FAIL = SECURE_COMP_ID | 0xAC, RC_TPM_NOFUNCTIONALTPM_FAIL = SECURE_COMP_ID | 0xAD, + RC_TPM_COMMAND_FAIL = SECURE_COMP_ID | 0xAE, + RC_TPM_INVALID_ARGS = SECURE_COMP_ID | 0xAF, }; #ifdef __cplusplus } diff --git a/src/usr/secureboot/trusted/base/trustedboot_base.C b/src/usr/secureboot/trusted/base/trustedboot_base.C index e9f20db59..dcd5a3191 100644 --- a/src/usr/secureboot/trusted/base/trustedboot_base.C +++ b/src/usr/secureboot/trusted/base/trustedboot_base.C @@ -43,6 +43,7 @@ #include #include "trustedboot_base.H" #include "../trustedboot.H" +#include "../trustedbootCmds.H" #include "../trustedbootUtils.H" #include "tpmLogMgr.H" @@ -165,19 +166,7 @@ void pcrExtendSingleTpm(TpmTarget & io_target, } } - - - // If the TPM init has occurred and it is currently - // functional we will do our extension - if (io_target.available && - io_target.initAttempted && - !io_target.failed) - { - - /// @todo RTC:125288 Add call to extend the PCR - } - - // Now we log the event, we will do this in two scenarios + // Log the event, we will do this in two scenarios // - !initAttempted - prior to IPL of the TPM we log for replay // - initAttempted && !failed - TPM is functional so we log if ((io_target.available && @@ -209,6 +198,24 @@ void pcrExtendSingleTpm(TpmTarget & io_target, } } + // If the TPM init has occurred and it is currently + // functional we will do our extension + if (io_target.available && + io_target.initAttempted && + !io_target.failed) + { + + err = tpmCmdPcrExtend(&io_target, + i_pcr, + i_algId, + i_digest, + i_digestSize); + if (NULL != err) + { + break; + } + } + } while ( 0 ); if (NULL != err) diff --git a/src/usr/secureboot/trusted/test/trustedbootTest.H b/src/usr/secureboot/trusted/test/trustedbootTest.H index 7b008ca5d..476b7e4c0 100755 --- a/src/usr/secureboot/trusted/test/trustedbootTest.H +++ b/src/usr/secureboot/trusted/test/trustedbootTest.H @@ -41,6 +41,8 @@ #include "../trustedTypes.H" #include "../trustedboot.H" #include "../trustedbootCmds.H" +#include "../base/trustedboot_base.H" +#include "../base/tpmLogMgr.H" extern trace_desc_t* g_trac_trustedboot; @@ -58,7 +60,6 @@ class TrustedBootTest: public CxxTest::TestSuite { public: - /** * @brief Helper to run failing marshal tests */ @@ -378,6 +379,8 @@ class TrustedBootTest: public CxxTest::TestSuite // Unsupported command { + TRACUCOMP( g_trac_trustedboot, + "testCommandMarshal - Unsupported Command" ); memset(dataBufIn, 0, sizeof(dataBufIn)); memset(dataBufOut, 0, sizeof(dataBufOut)); baseCmd->commandCode = 0x12345; @@ -393,6 +396,8 @@ class TrustedBootTest: public CxxTest::TestSuite // Test 2ByteIn with Startup command { + TRACUCOMP( g_trac_trustedboot, + "testCommandMarshal - 2ByteIn" ); memset(dataBufIn, 0, sizeof(dataBufIn)); memset(dataBufOut, 0, sizeof(dataBufOut)); TRUSTEDBOOT::TPM2_2ByteIn* cmdPtr = @@ -411,6 +416,8 @@ class TrustedBootTest: public CxxTest::TestSuite // Test GetCapabilityIn { + TRACUCOMP( g_trac_trustedboot, + "testCommandMarshal - GetCapabilityIn" ); memset(dataBufIn, 0, sizeof(dataBufIn)); memset(dataBufOut, 0, sizeof(dataBufOut)); TRUSTEDBOOT::TPM2_GetCapabilityIn* cmdPtr = @@ -428,6 +435,45 @@ class TrustedBootTest: public CxxTest::TestSuite sizeof(TPM2_GetCapabilityIn)); } + // Test ExtendIn + { + TRACUCOMP( g_trac_trustedboot, + "testCommandMarshal - ExtendIn" ); + memset(dataBufIn, 0, sizeof(dataBufIn)); + memset(dataBufOut, 0, sizeof(dataBufOut)); + TRUSTEDBOOT::TPM2_ExtendIn* cmdPtr = + reinterpret_cast + (dataBufIn); + cmdPtr->base.tag = TPM_ST_SESSIONS; + cmdPtr->base.commandCode = TPM_CC_PCR_Extend; + cmdPtr->digests.count = 1; + cmdPtr->digests.digests[0].algorithmId = TPM_ALG_SHA256; + + runTpmMarshalTest(baseCmd, + dataBufOut, + sizeof(dataBufOut), + cmdSize, + "ExtendIn", + num_ops, + fails, + sizeof(TPM2_ExtendIn) + + sizeof(TPMS_AUTH_COMMAND) + + 4); //auth size field + + // Invalid number of digests + memset(dataBufIn, 0, sizeof(dataBufIn)); + memset(dataBufOut, 0, sizeof(dataBufOut)); + cmdPtr->base.commandCode = TRUSTEDBOOT::TPM_CC_PCR_Extend; + cmdPtr->digests.count = HASH_COUNT+1; + runTpmMarshalFailTest(baseCmd, + dataBufOut, + sizeof(dataBufOut), + cmdSize, + "ExtendIn - invalid #digests", + num_ops, + fails); + + } } while( 0 ); @@ -455,6 +501,8 @@ class TrustedBootTest: public CxxTest::TestSuite // Unsupported command { + TRACUCOMP( g_trac_trustedboot, + "testCommandUnmarshal - Unsupported command" ); memset(dataBufIn, 0, sizeof(dataBufIn)); memset(dataBufOut, 0, sizeof(dataBufOut)); @@ -470,6 +518,8 @@ class TrustedBootTest: public CxxTest::TestSuite // Test BaseOut with Startup command { + TRACUCOMP( g_trac_trustedboot, + "testCommandUnmarshal - BaseOut" ); memset(dataBufIn, 0, sizeof(dataBufIn)); memset(dataBufOut, 0, sizeof(dataBufOut)); @@ -485,6 +535,8 @@ class TrustedBootTest: public CxxTest::TestSuite // Test GetCapabilityOut { + TRACUCOMP( g_trac_trustedboot, + "testCommandUnmarshal - GetCapabilityOut" ); memset(dataBufIn, 0, sizeof(dataBufIn)); memset(dataBufOut, 0, sizeof(dataBufOut)); @@ -517,6 +569,7 @@ class TrustedBootTest: public CxxTest::TestSuite + } while( 0 ); TRACFCOMP( g_trac_trustedboot, "testCommandUnmarshal - End: %d/%d fails", @@ -524,6 +577,118 @@ class TrustedBootTest: public CxxTest::TestSuite } + /** + * @brief Retrieve a node target to test with + */ + TRUSTEDBOOT::TpmTarget getTestTarget() + { + TARGETING::TargetService& tS = TARGETING::targetService(); + TRUSTEDBOOT::TpmTarget target; + TPMDD::tpm_info_t tpmInfo; + + target.available = true; + target.initAttempted = true; + target.failed = false; + + tS.getMasterNodeTarget( target.nodeTarget ); + + assert(target.nodeTarget != NULL); + + TRACFCOMP( g_trac_trustedboot, + "getTestTarget node tgt=0x%X chip=%d", + TARGETING::get_huid(target.nodeTarget)); + + // Let's see if the requested chip is functional + target.chip = TPMDD::TPM_PRIMARY; + tpmInfo.chip = TPMDD::TPM_PRIMARY; + errlHndl_t err = tpmReadAttributes (target.nodeTarget, + tpmInfo); + + if (NULL != err) + { + target.failed = true; + delete err; + } + else if (!tpmInfo.tpmEnabled) + { + TRACFCOMP(g_trac_trustedboot, "getTestTarget - " + "Chip %d not enabled", + tpmInfo.chip); + target.failed = true; + } + else + { + TRACFCOMP(g_trac_trustedboot, "getTestTarget - " + "Chip %d enabled", + target.chip); + } + + return target; + } + + + + /** + * @brief TPM Extend PCR + */ + void testExtendPCR ( void ) + { + int64_t fails = 0, num_ops = 0; + uint8_t digest[TPM_ALG_SHA256_SIZE]; + + TRACFCOMP( g_trac_trustedboot, + "testExtendPCR - Start" ); + TpmTarget target = getTestTarget(); + + do + { + + if (target.failed) + { + TS_FAIL( "testExtendPCR - Master TPM not functional" ); + break; + } + + for (size_t idx = 0; idx < sizeof(digest); idx++) + { + digest[idx] = idx+1; + } + + for (size_t i = 0; i < 5; i ++) { + + num_ops++; + pcrExtendSingleTpm(target, + PCR_DEBUG, + TPM_ALG_SHA256, + digest, + TPM_ALG_SHA256_SIZE, + "testExtendPCR - test 1"); + if( target.failed ) + { + fails++; + TS_FAIL( "testExtendPCR - Extend Error detected" ); + break; + } + else + { + TRACUCOMP(g_trac_trustedboot, "testExtendPCR - " + "Extend returned as expected."); + } + } + + + + } while( 0 ); + TRACFCOMP( g_trac_trustedboot, + "testExtendPCR - End: %d/%d fails", + fails, num_ops ); + + if (NULL != target.logMgr) + { + delete target.logMgr; + } + } + }; diff --git a/src/usr/secureboot/trusted/trustedTypes.C b/src/usr/secureboot/trusted/trustedTypes.C index f9ae71165..555efc141 100644 --- a/src/usr/secureboot/trusted/trustedTypes.C +++ b/src/usr/secureboot/trusted/trustedTypes.C @@ -136,6 +136,23 @@ namespace TRUSTEDBOOT return NULL; } + uint8_t* TPMT_HA_marshal(TPMT_HA* val, + uint8_t* o_tpmBuf, + size_t i_tpmBufSize, + size_t * io_cmdSize) + { + o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + &(val->algorithmId), sizeof(val->algorithmId)); + if (getDigestSize((TPM_Alg_Id)val->algorithmId) == 0) + { + return NULL; + } + o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + &(val->digest.bytes), + getDigestSize((TPM_Alg_Id)val->algorithmId)); + return o_tpmBuf; + } + size_t TCG_PCR_EVENT_marshalSize(TCG_PCR_EVENT* val) { return (sizeof(TCG_PCR_EVENT) + val->eventSize - MAX_TPM_LOG_MSG); @@ -152,6 +169,35 @@ namespace TRUSTEDBOOT return (sizeof(val->eventSize) + val->eventSize); } + + uint8_t* TPML_DIGEST_VALUES_marshal(TPML_DIGEST_VALUES* val, + uint8_t* o_tpmBuf, + size_t i_tpmBufSize, + size_t * io_cmdSize) + { + o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + &(val->count), sizeof(val->count)); + if (NULL != o_tpmBuf && HASH_COUNT < val->count) + { + o_tpmBuf = NULL; + } + else + { + for (size_t idx = 0; idx < val->count; idx++) + { + o_tpmBuf = TPMT_HA_marshal(&(val->digests[idx]), + o_tpmBuf, + i_tpmBufSize, + io_cmdSize); + if (NULL == o_tpmBuf) + { + break; + } + } + } + return o_tpmBuf; + } + uint8_t* TPM2_BaseIn_marshal(TPM2_BaseIn* val, uint8_t* o_tpmBuf, size_t i_tpmBufSize, size_t* io_cmdSize) { @@ -180,6 +226,15 @@ namespace TRUSTEDBOOT &(val->param), sizeof(val->param)); } + uint8_t* TPM2_4ByteIn_marshal(TPM2_4ByteIn* val, + uint8_t* o_tpmBuf, + size_t i_tpmBufSize, + size_t* io_cmdSize) + { + // Base has already been marshaled + return marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + &(val->param), sizeof(val->param)); + } uint8_t* TPM2_GetCapabilityIn_marshal(TPM2_GetCapabilityIn* val, uint8_t* o_tpmBuf, @@ -218,6 +273,36 @@ namespace TRUSTEDBOOT } + uint8_t* TPM2_ExtendIn_marshalHandle(TPM2_ExtendIn* val, + uint8_t* o_tpmBuf, + size_t i_tpmBufSize, + size_t* io_cmdSize) + { + // Base has already been marshaled + // only marshal the pcr handle in this stage + return marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + &(val->pcrHandle), sizeof(val->pcrHandle)); + } + + uint8_t* TPM2_ExtendIn_marshalParms(TPM2_ExtendIn* val, + uint8_t* o_tpmBuf, + size_t i_tpmBufSize, + size_t* io_cmdSize) + { + // Base and handle has already been marshaled + return (TPML_DIGEST_VALUES_marshal(&(val->digests), o_tpmBuf, + i_tpmBufSize, io_cmdSize)); + } + + + uint8_t* TPMS_AUTH_COMMAND_marshal(TPMS_AUTH_COMMAND* val, + uint8_t* o_tpmBuf, + size_t i_tpmBufSize, + size_t* io_cmdSize) + { + return marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + val, sizeof(TPMS_AUTH_COMMAND)); + } #ifdef __cplusplus } // end TRUSTEDBOOT diff --git a/src/usr/secureboot/trusted/trustedTypes.H b/src/usr/secureboot/trusted/trustedTypes.H index f6348f6bb..d3f98dec0 100644 --- a/src/usr/secureboot/trusted/trustedTypes.H +++ b/src/usr/secureboot/trusted/trustedTypes.H @@ -41,6 +41,7 @@ #include #ifdef __HOSTBOOT_MODULE #include +#include #else #include "trustedboot.H" #define PACKED __attribute__((__packed__)) @@ -77,6 +78,7 @@ namespace TRUSTEDBOOT MAX_TPM_LOG_MSG = 128, ///< Maximum log message size HASH_COUNT = 1, ///< Maximum # of digests + PCR_SELECT_MAX = ((PCR_MAX+7)/8), ///< PCR selection octet max }; typedef enum @@ -134,6 +136,10 @@ namespace TRUSTEDBOOT TPM_RC_INITIALIZE = 0x100, + + // TPM Authorization types + TPM_RS_PW = 0x40000009, + }; @@ -208,6 +214,8 @@ namespace TRUSTEDBOOT typedef struct _TPMT_HA TPMT_HA; size_t TPMT_HA_marshalSize(TPMT_HA* val); uint8_t* TPMT_HA_logMarshal(TPMT_HA* val, uint8_t* i_logBuf); + uint8_t* TPMT_HA_marshal(TPMT_HA* val, uint8_t* o_tpmBuf, + size_t i_tpmBufSize, size_t * io_cmdSize); /// Crypto agile digests list @@ -220,6 +228,9 @@ namespace TRUSTEDBOOT size_t TPML_DIGEST_VALUES_marshalSize(TPML_DIGEST_VALUES* val); uint8_t* TPML_DIGEST_VALUES_logMarshal(TPML_DIGEST_VALUES* val, uint8_t* i_logBuf); + uint8_t* TPML_DIGEST_VALUES_marshal(TPML_DIGEST_VALUES* val, + uint8_t* o_tpmBuf, size_t i_tpmBufSize, + size_t * io_cmdSize); /// Event field structure struct _TPM_EVENT_FIELD @@ -276,6 +287,16 @@ namespace TRUSTEDBOOT uint8_t* TPM2_2ByteIn_marshal(TPM2_2ByteIn* val, uint8_t* o_tpmBuf, size_t i_tpmBufSize, size_t* io_cmdSize); + /// Generic TPM Input Command structure with a 4 byte param + struct _TPM2_4ByteIn + { + TPM2_BaseIn base; + uint32_t param; + } PACKED; + typedef struct _TPM2_4ByteIn TPM2_4ByteIn; + uint8_t* TPM2_4ByteIn_marshal(TPM2_4ByteIn* val, uint8_t* o_tpmBuf, + size_t i_tpmBufSize, size_t* io_cmdSize); + /// Generic TPM Output Command structure with a 4 byte return data struct _TPM2_4ByteOut @@ -320,6 +341,26 @@ namespace TRUSTEDBOOT TPML_DIGEST_VALUES digests; ///< Values to be extended } PACKED; typedef struct _TPM2_ExtendIn TPM2_ExtendIn; + uint8_t* TPM2_ExtendIn_marshalHandle(TPM2_ExtendIn* val, + uint8_t* o_tpmBuf, size_t i_tpmBufSize, + size_t* io_cmdSize); + uint8_t* TPM2_ExtendIn_marshalParms(TPM2_ExtendIn* val, + uint8_t* o_tpmBuf, size_t i_tpmBufSize, + size_t* io_cmdSize); + + /// TPM Authorization structure + /// This is not the full structure and only works for PW auth with NULL PW + struct _TPMS_AUTH_COMMAND + { + uint32_t sessionHandle; + uint16_t nonceSize; ///< Size of nonce structure, currently 0 + uint8_t sessionAttributes; ///< Session attributes + uint16_t hmacSize; ///< Size of hmac structure, currently 0 + } PACKED; + typedef struct _TPMS_AUTH_COMMAND TPMS_AUTH_COMMAND; + uint8_t* TPMS_AUTH_COMMAND_marshal(TPMS_AUTH_COMMAND* val, + uint8_t* o_tpmBuf, size_t i_tpmBufSize, + size_t* io_cmdSize); #ifdef __cplusplus } // end TRUSTEDBOOT namespace diff --git a/src/usr/secureboot/trusted/trustedboot.C b/src/usr/secureboot/trusted/trustedboot.C index ad596648c..d51c9e031 100644 --- a/src/usr/secureboot/trusted/trustedboot.C +++ b/src/usr/secureboot/trusted/trustedboot.C @@ -112,6 +112,9 @@ void* host_update_master_tpm( void *io_pArgs ) } } + // Now we need to replay any existing entries in the log into the TPM + tpmReplayLog(systemTpms.tpm[TPM_MASTER_INDEX]); + if (systemTpms.tpm[TPM_MASTER_INDEX].failed || !systemTpms.tpm[TPM_MASTER_INDEX].available) { @@ -150,6 +153,15 @@ void* host_update_master_tpm( void *io_pArgs ) err = TPMDD::tpmReadAttributes(nodeTarget, tpmInfo); if (NULL != err) { + // We don't want to log this error we will just assume + // the backup doesn't exist + delete err; + err = NULL; + TRACUCOMP( g_trac_trustedboot, + "host_update_master_tpm() tgt=0x%X " + "Marking backup TPM unavailable due to attribute fail", + TARGETING::get_huid(nodeTarget)); + systemTpms.tpm[TPM_BACKUP_INDEX].available = false; break; } else if (!tpmInfo.tpmEnabled) @@ -228,7 +240,15 @@ void tpmInitialize(TRUSTEDBOOT::TpmTarget & io_target, TRACDCOMP( g_trac_trustedboot, EXIT_MRK"tpmInitialize()"); +} +void tpmReplayLog(TRUSTEDBOOT::TpmTarget & io_target) +{ + ///@todo RTC:125288 Implement replay + // Function will walk existing entries in the TPM log and call + // tpmCmdPcrExtend as required + // This function must commit any errors and call tpmMarkFailed if errors + // are found } diff --git a/src/usr/secureboot/trusted/trustedboot.H b/src/usr/secureboot/trusted/trustedboot.H index eaf950759..2569de487 100644 --- a/src/usr/secureboot/trusted/trustedboot.H +++ b/src/usr/secureboot/trusted/trustedboot.H @@ -65,7 +65,7 @@ public: /** - * @brief Initialize the targetted TPM + * @brief Initialize the targeted TPM * @param[in/out] io_target Current TPM target structure * @param[in] i_nodeTarget Node Target * @param[in] i_chip Chip to initialize @@ -74,6 +74,19 @@ void tpmInitialize(TRUSTEDBOOT::TpmTarget & io_target, TARGETING::Target* i_nodeTarget, TPMDD::tpm_chip_types_t i_chip); +/** + * @brief Verify a functional TPM still exists in the system + * @return errlHndl_t NULL if TPM available, otherwise a pointer to the + * error log. +*/ +errlHndl_t tpmVerifyFunctionalTpmExists(); + +/** + * @brief Replay the entries that exist in the log into the TPM as needed + * @param[in/out] io_target Current TPM target structure + */ +void tpmReplayLog(TRUSTEDBOOT::TpmTarget & io_target); + } // end TRUSTEDBOOT namespace #endif diff --git a/src/usr/secureboot/trusted/trustedbootCmds.C b/src/usr/secureboot/trusted/trustedbootCmds.C index aa5d713fa..611708c2e 100644 --- a/src/usr/secureboot/trusted/trustedbootCmds.C +++ b/src/usr/secureboot/trusted/trustedbootCmds.C @@ -120,9 +120,13 @@ errlHndl_t tpmMarshalCommandData(TPM2_BaseIn* i_cmd, { errlHndl_t err = TB_SUCCESS; uint8_t* sBuf = o_outbuf; + uint32_t* sSizePtr = NULL; + size_t curSize = 0; int stage = 0; TPM2_BaseIn* baseCmd = (TPM2_BaseIn*)o_outbuf; + TPMS_AUTH_COMMAND cmdAuth; + *o_cmdSize = 0; TRACDCOMP( g_trac_trustedboot, @@ -142,19 +146,55 @@ errlHndl_t tpmMarshalCommandData(TPM2_BaseIn* i_cmd, break; } - // Marshal the handles stage = 1; - + if (TPM_CC_PCR_Extend == i_cmd->commandCode) + { + TPM2_ExtendIn* cmdPtr = (TPM2_ExtendIn*)i_cmd; + sBuf = TPM2_ExtendIn_marshalHandle(cmdPtr, + sBuf, + i_bufsize, + o_cmdSize); + if (NULL == sBuf) + { + break; + } + } // Marshal the authorizations stage = 2; + if (TPM_CC_PCR_Extend == i_cmd->commandCode) + { + // Insert a password authorization with a null pw + // Make room for the 4 byte size field at the beginning + sSizePtr = (uint32_t*)sBuf; + sBuf += sizeof(uint32_t); + *o_cmdSize += sizeof(uint32_t); + i_bufsize -= sizeof(uint32_t); + curSize = *o_cmdSize; + + cmdAuth.sessionHandle = TPM_RS_PW; + cmdAuth.nonceSize = 0; + cmdAuth.sessionAttributes = 0; + cmdAuth.hmacSize = 0; + + sBuf = TPMS_AUTH_COMMAND_marshal(&cmdAuth, sBuf, i_bufsize, + o_cmdSize); + + if (NULL == sBuf) + { + break; + } + // Put in the size of the auth area + *sSizePtr = (*o_cmdSize - curSize); - // Marshal the parameters + } + + // Marshal the command parameters stage = 3; switch (i_cmd->commandCode) { - // Two byte parm fields + // Two byte parm fields case TPM_CC_Startup: { TPM2_2ByteIn* cmdPtr = @@ -172,6 +212,13 @@ errlHndl_t tpmMarshalCommandData(TPM2_BaseIn* i_cmd, i_bufsize, o_cmdSize); } break; + case TPM_CC_PCR_Extend: + { + TPM2_ExtendIn* cmdPtr = (TPM2_ExtendIn*)i_cmd; + sBuf = TPM2_ExtendIn_marshalParms(cmdPtr, sBuf, + i_bufsize, o_cmdSize); + } + break; default: { @@ -197,11 +244,19 @@ errlHndl_t tpmMarshalCommandData(TPM2_BaseIn* i_cmd, break; }; - if (TB_SUCCESS != err) + if (TB_SUCCESS != err || NULL == sBuf) { break; } + // Do a verification that the cmdSize equals what we used + if (((size_t)(sBuf - o_outbuf)) != *o_cmdSize) + { + TRACFCOMP( g_trac_trustedboot, + "TPM MARSHAL MARSHAL SIZE MISMATCH : %d %d", + (sBuf - o_outbuf), *o_cmdSize ); + sBuf = NULL; + } // Lastly now that we know the size update the byte stream baseCmd->commandSize = *o_cmdSize; @@ -285,8 +340,9 @@ errlHndl_t tpmUnmarshalResponseData(uint32_t i_commandCode, stage = 2; switch (i_commandCode) { - // Empty response commands + // Empty response commands case TPM_CC_Startup: + case TPM_CC_PCR_Extend: // Nothing to do break; @@ -645,6 +701,120 @@ errlHndl_t tpmCmdGetCapFwVersion(TpmTarget* io_target) } +errlHndl_t tpmCmdPcrExtend(TpmTarget * io_target, + TPM_Pcr i_pcr, + TPM_Alg_Id i_algId, + uint8_t* i_digest, + size_t i_digestSize) +{ + errlHndl_t err = NULL; + uint8_t dataBuf[sizeof(TPM2_ExtendIn)]; + size_t dataSize = sizeof(dataBuf); + size_t fullDigestSize = 0; + TPM2_BaseOut* resp = (TPM2_BaseOut*)dataBuf; + TPM2_ExtendIn* cmd = (TPM2_ExtendIn*)dataBuf; + + + TRACDCOMP( g_trac_trustedboot, + ">>tpmCmdPcrExtend()" ); + TRACUCOMP( g_trac_trustedboot, + ">>tpmCmdPcrExtend() Pcr(%d) Alg(%X) DS(%d)", + i_pcr, i_algId, (int)i_digestSize); + + do + { + + fullDigestSize = getDigestSize(i_algId); + + // Build our command block + memset(dataBuf, 0, sizeof(dataBuf)); + + // Argument verification + if (fullDigestSize == 0 || + fullDigestSize != i_digestSize || + NULL == i_digest || + PCR_MAX < i_pcr + ) + { + TRACFCOMP( g_trac_trustedboot, + "TPM PCR EXTEND ARG FAILURE FDS(%d) DS(%d) PCR(%d)", + (int)fullDigestSize, (int)i_digestSize, i_pcr); + /*@ + * @errortype + * @reasoncode RC_TPM_INVALID_ARGS + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_TPM_CMD_PCREXTEND + * @userdata1 Digest Ptr + * @userdata2[0:31] Full Digest Size + * @userdata2[32:63] PCR + * @devdesc Unmarshaling error detected + */ + err = tpmCreateErrorLog(MOD_TPM_CMD_PCREXTEND, + RC_TPM_INVALID_ARGS, + (uint64_t)i_digest, + (fullDigestSize << 32) | + i_pcr); + break; + } + + // Log the input PCR value + TRACUBIN(g_trac_trustedboot, "PCR In", + i_digest, fullDigestSize); + + cmd->base.tag = TPM_ST_SESSIONS; + cmd->base.commandCode = TPM_CC_PCR_Extend; + cmd->pcrHandle = i_pcr; + cmd->digests.count = 1; + cmd->digests.digests[0].algorithmId = i_algId; + memcpy(cmd->digests.digests[0].digest.bytes, i_digest, fullDigestSize); + + err = tpmTransmitCommand(io_target, + dataBuf, + sizeof(dataBuf)); + + if (TB_SUCCESS != err) + { + TRACFCOMP( g_trac_trustedboot, + "TPM PCRExtend Transmit Fail"); + break; + + } + else if ((sizeof(TPM2_BaseOut) > dataSize) + || (TPM_SUCCESS != resp->responseCode)) + { + TRACFCOMP( g_trac_trustedboot, + "TPM PCRExtend OP Fail Ret(%X) ExSize(%d) Size(%d) ", + resp->responseCode, + (int)sizeof(TPM2_BaseOut), + (int)dataSize); + + /*@ + * @errortype + * @reasoncode RC_TPM_COMMAND_FAIL + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_TPM_CMD_PCREXTEND + * @userdata1 responseCode + * @userdata2 dataSize + * @devdesc Command failure reading TPM FW version. + */ + err = tpmCreateErrorLog(MOD_TPM_CMD_PCREXTEND, + RC_TPM_COMMAND_FAIL, + resp->responseCode, + dataSize); + break; + + } + + } while ( 0 ); + + + TRACUCOMP( g_trac_trustedboot, + "<