From a0e8246b27da999d4d8beba64994daef6333a442 Mon Sep 17 00:00:00 2001 From: Chris Engel Date: Thu, 6 Jul 2017 22:04:32 -0500 Subject: MFG support to validate TPM provisioning Change-Id: I137b6f6c81cbcd3c2379e4ef34ddff021c3cd576 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/42835 Reviewed-by: Nicholas E. Bofferding Tested-by: Jenkins Server Reviewed-by: Timothy R. Block Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Stephen M. Cprek Tested-by: FSP CI Jenkins Reviewed-by: Michael Baiocchi Reviewed-by: Daniel M. Crowell --- src/usr/secureboot/HBconfig | 5 + src/usr/secureboot/trusted/trustedTypes.C | 29 ++++- src/usr/secureboot/trusted/trustedTypes.H | 19 +++- src/usr/secureboot/trusted/trustedboot.C | 22 ++++ src/usr/secureboot/trusted/trustedbootCmds.C | 159 +++++++++++++++++++++++++++ src/usr/secureboot/trusted/trustedbootCmds.H | 10 ++ 6 files changed, 242 insertions(+), 2 deletions(-) (limited to 'src/usr/secureboot') diff --git a/src/usr/secureboot/HBconfig b/src/usr/secureboot/HBconfig index 867bee67c..425593e74 100644 --- a/src/usr/secureboot/HBconfig +++ b/src/usr/secureboot/HBconfig @@ -25,3 +25,8 @@ config DRTM_TRIGGERING #TODO RTC: 170487 Disable for relevant platforms Enable triggering DRTM from Hostboot when the ATTR_FORCE_PRE_PAYLOAD_DRTM attribute is overridden +config TPM_NVIDX_VALIDATE + default y if TPMDD + depends on TPMDD + help + Validate TPM MFG NV Index Provisioning during IPL diff --git a/src/usr/secureboot/trusted/trustedTypes.C b/src/usr/secureboot/trusted/trustedTypes.C index 9e2581ef6..fe8112151 100644 --- a/src/usr/secureboot/trusted/trustedTypes.C +++ b/src/usr/secureboot/trusted/trustedTypes.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* Contributors Listed Below - COPYRIGHT 2015,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -127,6 +127,26 @@ namespace TRUSTEDBOOT return i_tpmBuf; } + const uint8_t* TPML_HANDLE_unmarshal(TPML_HANDLE* val, + const uint8_t* i_tpmBuf, + size_t* io_tpmBufSize) + { + i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize, + &(val->count), sizeof(val->count)); + + // Now we know the count as well + if (val->count <= MAX_TPML_HANDLES) { + i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize, + &(val->handles[0]), + sizeof(uint32_t) * val->count); + } + else + { + return NULL; + } + + return i_tpmBuf; + } const uint8_t* TPMS_CAPABILITY_DATA_unmarshal(TPMS_CAPABILITY_DATA* val, const uint8_t* i_tpmBuf, @@ -138,6 +158,13 @@ namespace TRUSTEDBOOT switch (val->capability) { + case TPM_CAP_HANDLES: + { + return TPML_HANDLE_unmarshal( + &(val->data.tpmHandles), i_tpmBuf, + io_tpmBufSize); + } + break; case TPM_CAP_TPM_PROPERTIES: { return TPML_TAGGED_TPM_PROPERTY_unmarshal( diff --git a/src/usr/secureboot/trusted/trustedTypes.H b/src/usr/secureboot/trusted/trustedTypes.H index ee19a7200..0798295c5 100644 --- a/src/usr/secureboot/trusted/trustedTypes.H +++ b/src/usr/secureboot/trusted/trustedTypes.H @@ -75,6 +75,10 @@ namespace TRUSTEDBOOT HASH_COUNT = 2, ///< Maximum # of digests PCR_SELECT_MAX = (IMPLEMENTATION_PCR+7)/8, ///< PCR selection octet max + + NVIDX_RSAEKCERT = 0x01C00002, ///< RSA EK certificate NV index + NVIDX_ECCEKCERT = 0x01C0000A, ///< ECC EK certificate NV index + NVIDX_IBMPLATCERT = 0x01C10180, ///< IBM Platform certificate index }; /** @@ -110,9 +114,13 @@ namespace TRUSTEDBOOT TPM_SU_STATE = 0x0001,///< TPM perform restore saved state // Capability + MAX_TPML_HANDLES = 20, + TPM_CAP_HANDLES = 1, MAX_TPM_PROPERTIES = 2, TPM_CAP_TPM_PROPERTIES = 0x00000006, ///< Pull TPM Properties + // TPM Handles + TPM_HT_NV_INDEX = 0x01000000, // TPM Properties TPM_PT_MANUFACTURER = 0x00000105, TPM_PT_FIRMWARE_VERSION_1 = 0x0000010B, @@ -152,10 +160,19 @@ namespace TRUSTEDBOOT TPML_TAGGED_TPM_PROPERTY* val, const uint8_t* i_tpmBuf, size_t* io_tpmBufSize); + struct _TPML_HANDLE + { + uint32_t count; ///< Number of handles + uint32_t handles[MAX_TPML_HANDLES]; + } PACKED; + typedef struct _TPML_HANDLE TPML_HANDLE; + const uint8_t* TPML_HANDLE_unmarshal(TPML_HANDLE* val, + const uint8_t* i_tpmBuf, + size_t* io_tpmBufSize); union _TPMU_CAPABILITIES { - // Currently only TPM properties supported + TPML_HANDLE tpmHandles; TPML_TAGGED_TPM_PROPERTY tpmProperties; } PACKED; typedef union _TPMU_CAPABILITIES TPMU_CAPABILITIES; diff --git a/src/usr/secureboot/trusted/trustedboot.C b/src/usr/secureboot/trusted/trustedboot.C index 6682bf829..083fc0859 100644 --- a/src/usr/secureboot/trusted/trustedboot.C +++ b/src/usr/secureboot/trusted/trustedboot.C @@ -67,6 +67,7 @@ #include #include #include +#include namespace TRUSTEDBOOT { @@ -493,6 +494,27 @@ void tpmInitialize(TRUSTEDBOOT::TpmTarget* const i_pTpm) break; } +#ifdef CONFIG_TPM_NVIDX_VALIDATE + // Find out if in manufacturing mode + TARGETING::Target* pTopLevel = nullptr; + TARGETING::targetService().getTopLevelTarget(pTopLevel); + assert(pTopLevel != nullptr,"Top level target was nullptr"); + + auto mnfgFlags = + pTopLevel->getAttr(); + + // Only validate during MFG IPL + if (mnfgFlags & TARGETING::MNFG_FLAG_SRC_TERM && + !Util::isSimicsRunning()) { + // TPM_GETCAPABILITY to validate NV Indexes + err = tpmCmdGetCapNvIndexValidate(i_pTpm); + if (nullptr != err) + { + break; + } + } +#endif + #ifdef CONFIG_DRTM // For a DRTM we need to reset PCRs 17-22 if (drtmMpipl) diff --git a/src/usr/secureboot/trusted/trustedbootCmds.C b/src/usr/secureboot/trusted/trustedbootCmds.C index a052c0571..709675c2d 100644 --- a/src/usr/secureboot/trusted/trustedbootCmds.C +++ b/src/usr/secureboot/trusted/trustedbootCmds.C @@ -447,6 +447,7 @@ errlHndl_t tpmUnmarshalResponseData(uint32_t i_commandCode, return err; } +#ifdef __HOSTBOOT_MODULE errlHndl_t tpmCmdStartup(TpmTarget* io_target) { errlHndl_t err = TB_SUCCESS; @@ -738,6 +739,164 @@ errlHndl_t tpmCmdGetCapFwVersion(TpmTarget* io_target) return err; } +errlHndl_t tpmCmdGetCapNvIndexValidate(TpmTarget* io_target) +{ + errlHndl_t err = TB_SUCCESS; + uint8_t dataBuf[BUFSIZE]; + size_t dataSize = BUFSIZE; + TPM2_GetCapabilityOut* resp = + (TPM2_GetCapabilityOut*)dataBuf; + TPM2_GetCapabilityIn* cmd = + (TPM2_GetCapabilityIn*)dataBuf; + bool foundRSAEKCert = false; + bool foundECCEKCert = false; + bool foundPlatCert = false; + bool moreData = false; + + TRACUCOMP( g_trac_trustedboot, + ">>tpmCmdGetCapNvIndexValidate()" ); + + do + { + + // Build our command block for a get capability of the FW version + memset(dataBuf, 0, dataSize); + + cmd->base.tag = TPM_ST_NO_SESSIONS; + cmd->base.commandCode = TPM_CC_GetCapability; + cmd->capability = TPM_CAP_HANDLES; + cmd->property = TPM_HT_NV_INDEX; + cmd->propertyCount = MAX_TPML_HANDLES; + + err = tpmTransmitCommand(io_target, + dataBuf, + sizeof(dataBuf), + TPM_LOCALITY_0); + + if (TB_SUCCESS != err) + { + TRACFCOMP( g_trac_trustedboot, + "TPM GETCAP Transmit Fail"); + break; + + } + + if (TPM_SUCCESS != resp->base.responseCode) + { + TRACFCOMP( g_trac_trustedboot, + "TPM GETCAP OP Fail Ret(0x%X) Size(%d) ", + resp->base.responseCode, + (int)dataSize); + + /*@ + * @errortype + * @reasoncode RC_TPM_GETCAP_FAIL + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_TPM_CMD_GETCAPNVINDEX + * @userdata1 responseCode + * @userdata2 0 + * @devdesc Command failure reading TPM capability. + * @custdesc Failure detected in security subsystem + */ + err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPNVINDEX, + RC_TPM_GETCAP_FAIL, + resp->base.responseCode, + 0); + + break; + } + + // Walk the reponse data to pull the high order bytes out + + if (resp->capData.capability != TPM_CAP_HANDLES) { + + TRACFCOMP( g_trac_trustedboot, + "TPM GETCAP NVINDEX INVALID DATA " + "Cap(0x%X) Cnt(0x%X) ", + resp->capData.capability, + resp->capData.data.tpmHandles.count); + + /*@ + * @errortype + * @reasoncode RC_TPM_GETCAP_FW_INVALID_RESP + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_TPM_CMD_GETCAPNVINDEX + * @userdata1 capability + * @userdata2 0 + * @devdesc Command failure reading TPM NV indexes. + * @custdesc Failure detected in security subsystem + */ + err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPNVINDEX, + RC_TPM_GETCAP_FW_INVALID_RESP, + resp->capData.capability, 0); + + break; + } + + for (size_t idx = 0; idx < resp->capData.data.tpmHandles.count; + ++idx) + { + // Check for specific handles we expect to be setup + // by manufacturing provisioning + switch (resp->capData.data.tpmHandles.handles[idx]) + { + case NVIDX_RSAEKCERT: + foundRSAEKCert = true; + break; + case NVIDX_ECCEKCERT: + foundECCEKCert = true; + break; + case NVIDX_IBMPLATCERT: + foundPlatCert = true; + break; + // Ignore any other handles + } + } + // More Data implies the TPM could have returned more then + // we asked for + moreData = resp->moreData; + + } while ( 0 ); + + // Validate we found all we needed + if (NULL == err && + (foundRSAEKCert == false || foundECCEKCert == false || + foundPlatCert == false || moreData == true)) + { + TRACFCOMP( g_trac_trustedboot, + "TPM GETCAP NVINDEX MISSING INDEX " + "RSAEK(%d) ECCEK(%d) PLAT(%d) MD(%d)", + foundRSAEKCert, foundECCEKCert, foundPlatCert, + moreData); + + /*@ + * @errortype + * @reasoncode RC_TPM_NVINDEX_VALIDATE_FAIL + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_TPM_CMD_GETCAPNVINDEX + * @userdata1[0:3] foundRSAEKCert + * @userdata1[4:7] foundECCEKCert + * @userdata1[8:11] foundPlatCert + * @userdata1[12:31] 0 + * @userdata2[0:3] moreData + * @userdata2[4:31] 0 + * @devdesc Command failure reading TPM NV indexes. + * @custdesc Failure detected in security subsystem + */ + err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPNVINDEX, + RC_TPM_NVINDEX_VALIDATE_FAIL, + (uint32_t)foundRSAEKCert << 28 | + (uint32_t)foundECCEKCert << 14 | + (uint32_t)foundPlatCert << 20, + (uint32_t)moreData << 28); + } + + TRACDCOMP( g_trac_trustedboot, + "<