diff options
author | Ilya Smirnov <ismirno@us.ibm.com> | 2018-04-10 17:37:13 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2018-05-02 16:03:48 -0400 |
commit | b013c352cce4f0f7da2a59020b782a67732e5259 (patch) | |
tree | 22174144e2db1f47a5667f049b4d0936b58e954a /src/usr | |
parent | 18cd3bf4c1eb67ddf2ebef3bcba88761c7618c9e (diff) | |
download | talos-hostboot-b013c352cce4f0f7da2a59020b782a67732e5259.tar.gz talos-hostboot-b013c352cce4f0f7da2a59020b782a67732e5259.zip |
Secure Boot: Basic Support For Redundant TPM
This change implements the detection and initialization of the backup
TPM in istep 10.14. The backup TPM is presence-detected and initialized;
the logs of the primary TPM are extended into the secondary TPM in istep
10.14. After the initialization of the secondary TPM, all events are
extended into both TPMs. A test was created to test whether the backup
TPM is initialized correctly.
Change-Id: I305500c9f680115e684ab153fc882b8d5364b0d4
RTC: 134912
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/57374
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r-- | src/usr/isteps/istep10/call_host_update_redundant_tpm.C | 24 | ||||
-rw-r--r-- | src/usr/secureboot/trusted/base/trustedbootMsg.H | 5 | ||||
-rw-r--r-- | src/usr/secureboot/trusted/base/trustedboot_base.C | 307 | ||||
-rw-r--r-- | src/usr/secureboot/trusted/trustedboot.C | 198 | ||||
-rw-r--r-- | src/usr/secureboot/trusted/trustedboot.H | 15 |
5 files changed, 496 insertions, 53 deletions
diff --git a/src/usr/isteps/istep10/call_host_update_redundant_tpm.C b/src/usr/isteps/istep10/call_host_update_redundant_tpm.C index af6030891..878b1b1e3 100644 --- a/src/usr/isteps/istep10/call_host_update_redundant_tpm.C +++ b/src/usr/isteps/istep10/call_host_update_redundant_tpm.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -22,6 +22,7 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +#include <isteps/hwpisteperror.H> #include <errl/errlentry.H> #include <errl/errlmanager.H> #include <isteps/istep_reasoncodes.H> @@ -38,6 +39,7 @@ #include <util/align.H> #include <util/algorithm.H> #include <istepHelperFuncs.H> +#include <secureboot/trustedbootif.H> namespace ISTEP_10 { @@ -47,10 +49,28 @@ void* call_host_update_redundant_tpm (void *io_pArgs) TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, ENTER_MRK"call_host_update_redundant_tpm"); + ISTEP_ERROR::IStepError l_istepError; +#ifdef CONFIG_TPMDD + TARGETING::Target* l_backupTpm = nullptr; + + do{ + TRUSTEDBOOT::getBackupTpm(l_backupTpm); + if(!l_backupTpm) + { + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, + "call_host_update_redundant_tpm: Backup TPM not found."); + break; + } + + TRUSTEDBOOT::initBackupTpm(); + + } while(0); +#endif + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, EXIT_MRK"call_host_update_redundant_tpm"); - return nullptr; + return l_istepError.getErrorHandle(); } }; diff --git a/src/usr/secureboot/trusted/base/trustedbootMsg.H b/src/usr/secureboot/trusted/base/trustedbootMsg.H index 79edde42e..45821f9f4 100644 --- a/src/usr/secureboot/trusted/base/trustedbootMsg.H +++ b/src/usr/secureboot/trusted/base/trustedbootMsg.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -54,7 +54,8 @@ namespace TRUSTEDBOOT MSG_TYPE_PCREXTEND, MSG_TYPE_SEPARATOR, MSG_TYPE_SHUTDOWN, - MSG_TYPE_LAST = MSG_TYPE_SHUTDOWN + MSG_TYPE_INIT_BACKUP_TPM, + MSG_TYPE_LAST = MSG_TYPE_INIT_BACKUP_TPM }; /// PCREXTEND message data diff --git a/src/usr/secureboot/trusted/base/trustedboot_base.C b/src/usr/secureboot/trusted/base/trustedboot_base.C index 801869439..c4929faef 100644 --- a/src/usr/secureboot/trusted/base/trustedboot_base.C +++ b/src/usr/secureboot/trusted/base/trustedboot_base.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -51,6 +51,8 @@ #include "../trustedbootUtils.H" #include "../../pnor/pnor_utils.H" #include "trustedbootMsg.H" +#include "../tpmLogMgr.H" +#include <algorithm> // ---------------------------------------------- // Trace definitions @@ -489,4 +491,307 @@ errlHndl_t extendBaseImage() return pError; } +void initBackupTpm() +{ + errlHndl_t l_errl = nullptr; +#ifdef CONFIG_TPMDD + Message* l_msg = Message::factory(MSG_TYPE_INIT_BACKUP_TPM, + 0, + nullptr, + MSG_MODE_SYNC); + int l_rc = msg_sendrecv(systemData.msgQ, l_msg->iv_msg); + if(l_rc == 0) + { + l_errl = l_msg->iv_errl; + l_msg->iv_errl = nullptr; + } + else + { + TRACFCOMP(g_trac_trustedboot, "Error occurred while sending message to" + " the TPM daemon. RC = %d", l_rc); + /*@ + * @errortype ERRL_SEV_UNRECOVERABLE + * @reasoncode RC_SENDRECV_FAIL + * @moduleid MOD_INIT_BACKUP_TPM + * @userdata1 rc from msq_sendrecv() + * @devdesc msg_sendrecv() failed + * @custdesc Trusted Boot failure + */ + l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_INIT_BACKUP_TPM, + RC_SENDRECV_FAIL, + l_rc, + 0, + true); + l_errl->collectTrace(SECURE_COMP_NAME); + l_errl->collectTrace(TRBOOT_COMP_NAME); + } + delete l_msg; + l_msg = nullptr; + + if(l_errl) + { + TARGETING::Target* l_backupTpm = nullptr; + getBackupTpm(l_backupTpm); + if(l_backupTpm) + { + tpmMarkFailed(l_backupTpm, l_errl); + } + } +#endif +} + +errlHndl_t testCmpPrimaryAndBackupTpm() +{ + errlHndl_t l_err = nullptr; +#ifdef CONFIG_TPMDD + TARGETING::Target* l_primaryTpm = nullptr; + TARGETING::Target* l_backupTpm = nullptr; + bool l_errorOccurred = false; + BackupTpmTestFailures l_rc = TPM_TEST_NO_ERROR; + + do { + + getPrimaryTpm(l_primaryTpm); + if(!l_primaryTpm) + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: primary TPM not found;" + "skipping test"); + break; + } + getBackupTpm(l_backupTpm); + if(!l_backupTpm) + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: backup TPM not found;" + "skipping test"); + break; + } + + auto l_primaryHwasState = l_primaryTpm->getAttr< + TARGETING::ATTR_HWAS_STATE>(); + if(!(l_primaryHwasState.present && l_primaryHwasState.functional)) + { + TRACFCOMP(g_trac_trustedboot, "testCmpPrimaryAndBackupTpm: primary TPM" + "is not present or not functional;" + "skipping the test."); + break; + } + + auto l_backupHwasState = l_backupTpm->getAttr<TARGETING::ATTR_HWAS_STATE>(); + if(!(l_backupHwasState.present && l_backupHwasState.functional)) + { + TRACFCOMP(g_trac_trustedboot, "testCmpPrimaryAndBackupTpm: backup TPM" + "is not present or not functional;" + "skipping the test."); + break; + } + + auto * const pTpmLogMgr = getTpmLogMgr(l_primaryTpm); + auto * const bTpmLogMgr = getTpmLogMgr(l_backupTpm); + + if(!pTpmLogMgr || !bTpmLogMgr) + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: TPM log manager(s)" + " is(are) uninitialized"); + l_errorOccurred = true; + l_rc = TPM_TEST_LOGS_NOT_INITIALIZED; + break; + } + + if(TpmLogMgr_getLogSize(bTpmLogMgr) == TpmLogMgr_getLogSize(pTpmLogMgr)) + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: the sizes of TPM logs match"); + } + else + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: log size mismatch." + " Primary log size: %d; backup log size: %d.", + TpmLogMgr_getLogSize(pTpmLogMgr), + TpmLogMgr_getLogSize(bTpmLogMgr)); + l_errorOccurred = true; + l_rc = TPM_TEST_LOG_SIZE_MISMATCH; + break; + } + + int l_count = 0; + TCG_PCR_EVENT2 l_pEventLog = {0}; + TCG_PCR_EVENT2 l_bEventLog = {0}; + // Skip the first entry which is the header + const uint8_t* l_pEventHdl = TpmLogMgr_getFirstEvent(pTpmLogMgr); + const uint8_t* l_bEventHdl = TpmLogMgr_getFirstEvent(bTpmLogMgr); + + // Match the logs + while(l_pEventHdl != nullptr && l_bEventHdl != nullptr) + { + // Other (than the header) events need to be processed + l_pEventHdl = TpmLogMgr_getNextEvent(pTpmLogMgr, l_pEventHdl, + &l_pEventLog, &l_errorOccurred); + if(l_errorOccurred) + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: Unmarshaling error occurred."); + l_rc = TPM_TEST_UNMARSHAL_ERROR; + break; + } + + l_bEventHdl = TpmLogMgr_getNextEvent(bTpmLogMgr, l_bEventHdl, + &l_bEventLog, &l_errorOccurred); + if(l_errorOccurred) + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: Unmarshaling error occurred."); + l_rc = TPM_TEST_UNMARSHAL_ERROR; + break; + } + + if(memcmp(&l_pEventLog, &l_bEventLog, sizeof(TCG_PCR_EVENT2))) + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: log #%d does not match", + l_count); + TRACFBIN(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: primary TPM's log:", + &l_pEventLog, sizeof(TCG_PCR_EVENT2)); + TRACFBIN(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: backup TPM's log:", + &l_bEventLog, sizeof(TCG_PCR_EVENT2)); + l_errorOccurred = true; + l_rc = TPM_TEST_LOG_MISMATCH; + break; + } + else + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: log #%d matches", + l_count); + } + + l_count++; + } //while + + if(l_err || l_errorOccurred) + { + break; + } + + TPM_Pcr l_pcrRegs[8] = {PCR_0, PCR_1, PCR_2, PCR_3, + PCR_4, PCR_5, PCR_6, PCR_7}; + TPM_Alg_Id l_algIds[2] = {TPM_ALG_SHA1, TPM_ALG_SHA256}; + + size_t l_sizeToAllocate = std::max(getDigestSize(TPM_ALG_SHA1), + getDigestSize(TPM_ALG_SHA256)); + + uint8_t* l_pDigest = new uint8_t[l_sizeToAllocate](); + uint8_t* l_bDigest = new uint8_t[l_sizeToAllocate](); + size_t l_digestSize = 0; + + // Match the contents of the PCR regs + for(const auto l_algId : l_algIds) + { + l_digestSize = getDigestSize(l_algId); + + for(const auto l_pcrReg : l_pcrRegs) + { + l_err = tpmCmdPcrRead(l_primaryTpm, + l_pcrReg, + l_algId, + l_pDigest, + l_digestSize); + if(l_err) + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: failed to read PCR %d" + " of primary TPM; algId = 0x%.04x", + l_pcrReg, + l_algId); + break; + } + + l_err = tpmCmdPcrRead(l_backupTpm, + l_pcrReg, + l_algId, + l_bDigest, + l_digestSize); + if(l_err) + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: failed to read PCR %d" + " of backup TPM; algId = 0x%.04x", + l_pcrReg, + l_algId); + break; + } + + if(memcmp(l_pDigest, l_bDigest, l_digestSize)) + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: digests of PCR %d" + " algId 0x%.04x do not match!", + l_pcrReg, + l_algId); + TRACFBIN(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: contents of primary TPM's" + " PCR:", + l_pDigest, l_digestSize); + TRACFBIN(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: contents of backup TPM's" + " PCR:", + l_bDigest, l_digestSize); + l_rc = TPM_TEST_DIGEST_MISMATCH; + l_errorOccurred = true; + break; + } + else + { + TRACFCOMP(g_trac_trustedboot, + "testCmpPrimaryAndBackupTpm: digests of PCR %d, algId" + " 0x%.04x match", + l_pcrReg, + l_algId); + } + } // pcrReg + + if(l_err || l_errorOccurred) + { + break; + } + } // algId + + delete l_pDigest; + delete l_bDigest; + l_pDigest = l_bDigest = nullptr; + + } while(0); + + if(!l_err && l_errorOccurred) + { + /*@ + * @errortype + * @reasoncode RC_BACKUP_TPM_TEST_FAIL + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_TEST_CMP_PRIMARY_AND_BACKUP_TPM + * @userdata1 return code + * @userdata2 0 + * @devdesc TPM testcase error. See the return code for details. + * @custdesc Trusted Boot failure. + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_TEST_CMP_PRIMARY_AND_BACKUP_TPM, + RC_BACKUP_TPM_TEST_FAIL, + l_rc, + 0, + true /*Add HB SW Callout*/); + + l_err->collectTrace(SECURE_COMP_NAME); + l_err->collectTrace(TRBOOT_COMP_NAME); + } +#endif + return l_err; +} + } // end TRUSTEDBOOT diff --git a/src/usr/secureboot/trusted/trustedboot.C b/src/usr/secureboot/trusted/trustedboot.C index 2f27064ca..75f7208a5 100644 --- a/src/usr/secureboot/trusted/trustedboot.C +++ b/src/usr/secureboot/trusted/trustedboot.C @@ -45,6 +45,7 @@ #include <secureboot/trustedboot_reasoncodes.H> #include <sys/mmio.h> #include <sys/task.h> +#include <sys/sync.h> #include <initservice/initserviceif.H> #ifdef CONFIG_BMC_IPMI #include <ipmi/ipmisensor.H> @@ -68,6 +69,7 @@ #include <targeting/common/commontargeting.H> #include <algorithm> #include <util/misc.H> +#include <hwas/common/hwasCommon.H> namespace TRUSTEDBOOT { @@ -323,8 +325,6 @@ void* host_update_master_tpm( void *io_pArgs ) if(!primaryTpmAvail) { - /// @todo RTC:134913 Switch to backup chip if backup TPM avail - // Primary TPM not available TRACFCOMP( g_trac_trustedboot, "Primary TPM Existence Fail"); @@ -341,28 +341,28 @@ void* host_update_master_tpm( void *io_pArgs ) } else { + auto l_backupHwasState = pBackupTpm->getAttr< + TARGETING::ATTR_HWAS_STATE>(); TPMDD::tpm_info_t tpmInfo; memset(&tpmInfo, 0, sizeof(tpmInfo)); errlHndl_t tmpErr = TPMDD::tpmReadAttributes( pBackupTpm, tpmInfo, TPM_LOCALITY_0); - if (nullptr != tmpErr || !tpmInfo.tpmEnabled) + if (nullptr != tmpErr || !tpmInfo.tpmEnabled || + (l_backupHwasState.functional && l_backupHwasState.present)) + // If the backup state is functional and present then we are + // in MPIPL scenario and we need to reset the states { TRACUCOMP( g_trac_trustedboot, "host_update_master_tpm() " "Marking backup TPM unavailable"); - auto backupHwasState = pBackupTpm->getAttr< - TARGETING::ATTR_HWAS_STATE>(); - backupHwasState.present = false; - backupHwasState.functional = false; + l_backupHwasState.present = false; + l_backupHwasState.functional = false; pBackupTpm->setAttr< - TARGETING::ATTR_HWAS_STATE>(backupHwasState); - + TARGETING::ATTR_HWAS_STATE>(l_backupHwasState); - pBackupTpm->setAttr<TARGETING::ATTR_HB_TPM_INIT_ATTEMPTED>( - true); if (nullptr != tmpErr) { // Ignore attribute read failure @@ -425,7 +425,8 @@ void* host_update_master_tpm( void *io_pArgs ) { TRACUCOMP( g_trac_trustedboot, "host_update_master_tpm() - " - "Backup TPM Present:%d Functional:%d Init Attempted:%d", + "Backup TPM Present:%d Functional:%d Init Attempted:%d. " + "Backup TPM initialization is deferred to istep 10.14.", pBackupTpm->getAttr<TARGETING::ATTR_HWAS_STATE>(). present, pBackupTpm->getAttr<TARGETING::ATTR_HWAS_STATE>(). @@ -541,14 +542,24 @@ void tpmInitialize(TRUSTEDBOOT::TpmTarget* const i_pTpm) EXIT_MRK"tpmInitialize()"); } -void tpmReplayLog(TRUSTEDBOOT::TpmTarget* const i_pTpm) +void tpmReplayLog(TRUSTEDBOOT::TpmTarget* const i_primaryTpm, + TRUSTEDBOOT::TpmTarget* const i_backupTpm) { - assert(i_pTpm != nullptr,"tpmReplayLog: BUG! i_pTpm was nullptr"); - assert(i_pTpm->getAttr<TARGETING::ATTR_TYPE>() == TARGETING::TYPE_TPM, - "tpmReplayLog: BUG! Expected target to be of TPM type, but " - "it was of type 0x%08X",i_pTpm->getAttr<TARGETING::ATTR_TYPE>()); - + assert(i_primaryTpm != nullptr, + "tpmReplayLog: BUG! i_primaryTpm was nullptr"); + assert(i_backupTpm != nullptr, + "tpmReplayLog: BUG! i_backupTpm was nullptr"); + assert(i_primaryTpm->getAttr<TARGETING::ATTR_TYPE>() == TARGETING::TYPE_TPM, + "tpmReplayLog: BUG! Expected primary target to be of TPM type, but " + "it was of type 0x%08X", + i_primaryTpm->getAttr<TARGETING::ATTR_TYPE>()); + assert(i_backupTpm->getAttr<TARGETING::ATTR_TYPE>() + == TARGETING::TYPE_TPM, + "tpmReplayLog: BUG! Expected secondary target to be of TPM type, but" + " it was of type 0x%08X", + i_backupTpm->getAttr<TARGETING::ATTR_TYPE>()); TRACUCOMP(g_trac_trustedboot, ENTER_MRK"tpmReplayLog()"); + errlHndl_t err = nullptr; bool unMarshalError = false; @@ -557,7 +568,12 @@ void tpmReplayLog(TRUSTEDBOOT::TpmTarget* const i_pTpm) TCG_PCR_EVENT2 l_eventLog = {0}; // Move past header event to get a pointer to the first event // If there are no events besides the header, l_eventHndl = nullptr - auto * const pTpmLogMgr = getTpmLogMgr(i_pTpm); + auto * const pTpmLogMgr = getTpmLogMgr(i_primaryTpm); + auto * const bTpmLogMgr = getTpmLogMgr(i_backupTpm); + assert(pTpmLogMgr != nullptr, "tpmReplayLog: BUG! Primary TPM's log manager" + " is nullptr!"); + assert(bTpmLogMgr != nullptr, "tpmReplayLog: BUG! Backup TPM's log manager" + " is nullptr!"); const uint8_t* l_eventHndl = TpmLogMgr_getFirstEvent(pTpmLogMgr); while ( l_eventHndl != nullptr ) { @@ -585,43 +601,42 @@ void tpmReplayLog(TRUSTEDBOOT::TpmTarget* const i_pTpm) err->collectTrace( SECURE_COMP_NAME ); err->collectTrace(TRBOOT_COMP_NAME); + tpmMarkFailed(i_primaryTpm, err); break; } - // Extend to tpm - if (EV_ACTION == l_eventLog.eventType) + err = TpmLogMgr_addEvent(bTpmLogMgr, &l_eventLog); + if(err) { - TRACUBIN(g_trac_trustedboot, "tpmReplayLog: Extending event:", - &l_eventLog, sizeof(TCG_PCR_EVENT2)); - for (size_t i = 0; i < l_eventLog.digests.count; i++) - { + tpmMarkFailed(i_backupTpm, err); + break; + } - TPM_Alg_Id l_algId = (TPM_Alg_Id)l_eventLog.digests.digests[i] - .algorithmId; - err = tpmCmdPcrExtend(i_pTpm, - (TPM_Pcr)l_eventLog.pcrIndex, - l_algId, - reinterpret_cast<uint8_t*> + TRACUBIN(g_trac_trustedboot, "tpmReplayLog: Extending event:", + &l_eventLog, sizeof(TCG_PCR_EVENT2)); + for (size_t i = 0; i < l_eventLog.digests.count; i++) + { + TPM_Alg_Id l_algId = (TPM_Alg_Id)l_eventLog.digests.digests[i] + .algorithmId; + err = tpmCmdPcrExtend(i_backupTpm, + (TPM_Pcr)l_eventLog.pcrIndex, + l_algId, + reinterpret_cast<uint8_t*> (&(l_eventLog.digests.digests[i].digest)), - getDigestSize(l_algId)); - if (err) - { - break; - } - } + getDigestSize(l_algId)); if (err) { + tpmMarkFailed(i_backupTpm, err); break; } } + if (err) + { + break; + } } - // If the TPM failed we will mark it not functional and commit errl - if (err) - { - // err will be committed and set to nullptr - tpmMarkFailed(i_pTpm, err); - } + TRACUCOMP(g_trac_trustedboot, EXIT_MRK"tpmReplayLog()"); } errlHndl_t tpmLogConfigEntries(TRUSTEDBOOT::TpmTarget* const i_pTpm) @@ -1262,6 +1277,97 @@ void tpmVerifyFunctionalTpmExists( return; } +void doInitBackupTpm() +{ + TARGETING::Target* l_backupTpm = nullptr; + errlHndl_t l_errl = nullptr; + TRUSTEDBOOT::getBackupTpm(l_backupTpm); + + do { + if(l_backupTpm) + { + auto l_backupHwasState = l_backupTpm->getAttr< + TARGETING::ATTR_HWAS_STATE>(); + // Presence-detect the secondary TPM + TARGETING::TargetHandleList l_targetList; + l_targetList.push_back(l_backupTpm); + l_errl = HWAS::platPresenceDetect(l_targetList); + if(l_errl) + { + errlCommit(l_errl, SECURE_COMP_ID); + break; + } + + // The TPM target would have been deleted from the list if it's + // not present. + if(l_targetList.size()) + { + l_backupHwasState.present = true; + l_backupTpm->setAttr<TARGETING::ATTR_HWAS_STATE>(l_backupHwasState); + } + else + { + l_backupHwasState.present = false; + l_backupTpm->setAttr<TARGETING::ATTR_HWAS_STATE>(l_backupHwasState); + break; + } + + mutex_lock(l_backupTpm->getHbMutexAttr<TARGETING::ATTR_HB_TPM_MUTEX>()); + tpmInitialize(l_backupTpm); + TpmLogMgr* l_tpmLogMgr = getTpmLogMgr(l_backupTpm); + if(!l_tpmLogMgr) + { + l_tpmLogMgr = new TpmLogMgr; + setTpmLogMgr(l_backupTpm, l_tpmLogMgr); + l_errl = TpmLogMgr_initialize(l_tpmLogMgr); + if(l_errl) + { + l_backupHwasState.functional = false; + l_backupTpm->setAttr<TARGETING::ATTR_HWAS_STATE> + (l_backupHwasState); + errlCommit(l_errl, SECURE_COMP_ID); + mutex_unlock(l_backupTpm-> + getHbMutexAttr<TARGETING::ATTR_HB_TPM_MUTEX>()); + break; + } + } + mutex_unlock(l_backupTpm-> + getHbMutexAttr<TARGETING::ATTR_HB_TPM_MUTEX>()); + + TARGETING::Target* l_primaryTpm = nullptr; + getPrimaryTpm(l_primaryTpm); + if(l_primaryTpm) + { + auto l_primaryHwasState = l_primaryTpm->getAttr< + TARGETING::ATTR_HWAS_STATE>(); + if(l_primaryHwasState.functional && l_primaryHwasState.present) + { + tpmReplayLog(l_primaryTpm, l_backupTpm); + } + } + + l_errl = TRUSTEDBOOT::testCmpPrimaryAndBackupTpm(); + if(l_errl) + { + errlCommit(l_errl, SECURE_COMP_ID); + break; + } + } + else + { + TRACFCOMP(g_trac_trustedboot, "tpmDaemon: Backup TPM init message was" + " received but the backup TPM cannot be found."); + } + + } while(0); + + // Init was attempted even if it didn't succeed + if(l_backupTpm) + { + l_backupTpm->setAttr<TARGETING::ATTR_HB_TPM_INIT_ATTEMPTED>(true); + } +} + void* tpmDaemon(void* unused) { bool shutdownPending = false; @@ -1356,7 +1462,11 @@ void* tpmDaemon(void* unused) NoTpmShutdownPolicy::BACKGROUND_SHUTDOWN); } break; - + case TRUSTEDBOOT::MSG_TYPE_INIT_BACKUP_TPM: + { + doInitBackupTpm(); + } + break; default: assert(false, "Invalid msg command"); break; diff --git a/src/usr/secureboot/trusted/trustedboot.H b/src/usr/secureboot/trusted/trustedboot.H index 220f9f599..d35c8a63e 100644 --- a/src/usr/secureboot/trusted/trustedboot.H +++ b/src/usr/secureboot/trusted/trustedboot.H @@ -115,12 +115,19 @@ void tpmVerifyFunctionalTpmExists( NoTpmShutdownPolicy::SYNC_SHUTDOWN); /** - * @brief Replay the entries that exist in the log into the TPM as needed + * @brief Replay (extend) the entries that exist in the log of the primary TPM + * into the secondary TPM. + * + * @param[in] i_primaryTpm TPM targeting target handle indicating TPM to + * replay the log from. Function will assert if the value is nullptr + * or is not of TPM type. + * @param[in] i_backupTpm TPM targeting target handle indicating TPM to replay + * the log to. Function will assert if the value is nullptr or is not + * of TPM type. * - * @param[in] i_pTpm TPM targeting target handle indicating TPM to replay log. - * Function will assert if value is nullptr or is not of TPM type */ -void tpmReplayLog(TRUSTEDBOOT::TpmTarget* i_pTpm); +void tpmReplayLog(TRUSTEDBOOT::TpmTarget* i_primaryTpm, + TRUSTEDBOOT::TpmTarget* i_backupTpm); /** * @brief Send config entries to TPM |