summaryrefslogtreecommitdiffstats
path: root/src/usr/secureboot/trusted/base
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/secureboot/trusted/base
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/secureboot/trusted/base')
-rw-r--r--src/usr/secureboot/trusted/base/trustedbootMsg.H5
-rw-r--r--src/usr/secureboot/trusted/base/trustedboot_base.C307
2 files changed, 309 insertions, 3 deletions
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
OpenPOWER on IntegriCloud