summaryrefslogtreecommitdiffstats
path: root/src/usr/secureboot/trusted/trustedboot.C
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/trustedboot.C
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/trustedboot.C')
-rw-r--r--src/usr/secureboot/trusted/trustedboot.C198
1 files changed, 154 insertions, 44 deletions
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;
OpenPOWER on IntegriCloud