summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorIlya Smirnov <ismirno@us.ibm.com>2018-04-10 17:37:13 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-05-02 16:03:48 -0400
commitb013c352cce4f0f7da2a59020b782a67732e5259 (patch)
tree22174144e2db1f47a5667f049b4d0936b58e954a /src/usr
parent18cd3bf4c1eb67ddf2ebef3bcba88761c7618c9e (diff)
downloadtalos-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.C24
-rw-r--r--src/usr/secureboot/trusted/base/trustedbootMsg.H5
-rw-r--r--src/usr/secureboot/trusted/base/trustedboot_base.C307
-rw-r--r--src/usr/secureboot/trusted/trustedboot.C198
-rw-r--r--src/usr/secureboot/trusted/trustedboot.H15
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
OpenPOWER on IntegriCloud