summaryrefslogtreecommitdiffstats
path: root/src/usr/secureboot
diff options
context:
space:
mode:
authorNick Bofferding <bofferdn@us.ibm.com>2017-01-30 13:52:49 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-03-03 13:51:19 -0500
commita9eefaa1086c7a3cc51e374c52a7c04397968fd5 (patch)
treeb0f15275d1fab88785d6efe8c47d3ad6ea3bc377 /src/usr/secureboot
parenta0437b216feaa77f81cfa3738844a0b761a9e99d (diff)
downloadtalos-hostboot-a9eefaa1086c7a3cc51e374c52a7c04397968fd5.tar.gz
talos-hostboot-a9eefaa1086c7a3cc51e374c52a7c04397968fd5.zip
Support DRTM RIT protection
- Added mailbox scratch register 7 definition - Added DRTM functions - Added set/clear security switch register functions - Added additional security switch bit definitions - Added secureboot extended library to host DRTM functions - Inhibited TPM start command in DRTM flow - Added new config options for DRTM and DRTM RIT protection - Added new DRTM attribute to indicate if DRTM is active - Added new DRTM attribute to hold DRTM payload address - Added new DRTM attribute to initiate DRTM in lieu of loading payload - Updated target service init to determine DRTM settings - Updated host start payload step to initiate DRTM if conditions are met - Updated host MPIPL service to verify DRTM payload and clean up DRTM HW state - Updated host gard step to verify DRTM HW state - Rerouted PCR extensions to PCR 17 in DRTM boot - Use locality 2 for all PCR extensions in DRTM boot - Inhibit extension logging (for now) in DRTM boot - Only extend seperator to PCR 17 in DRTM boot Change-Id: Id52c36c3a64ca002571396d605caa308d9dc0199 RTC: 157140 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35633 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com> Reviewed-by: Stephen M. Cprek <smcprek@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Timothy R. Block <block@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/secureboot')
-rw-r--r--src/usr/secureboot/HBconfig14
-rw-r--r--src/usr/secureboot/base/service.C16
-rw-r--r--src/usr/secureboot/base/settings.C135
-rw-r--r--src/usr/secureboot/common/securetrace.H8
-rw-r--r--src/usr/secureboot/ext/drtm.C723
-rw-r--r--src/usr/secureboot/ext/makefile6
-rw-r--r--src/usr/secureboot/trusted/trustedboot.C103
-rw-r--r--src/usr/secureboot/trusted/trustedbootCmds.C24
8 files changed, 1007 insertions, 22 deletions
diff --git a/src/usr/secureboot/HBconfig b/src/usr/secureboot/HBconfig
index ac092ad73..0ef8bc748 100644
--- a/src/usr/secureboot/HBconfig
+++ b/src/usr/secureboot/HBconfig
@@ -3,3 +3,17 @@ config SECUREBOOT
default y
help
Enable secure boot
+
+config DRTM #TODO RTC: 170487 Disable for relevant platforms
+ default y if (SECUREBOOT && TPMDD)
+ depends on (SECUREBOOT && TPMDD)
+ help
+ Enable DRTM support
+
+config DRTM_TRIGGERING #TODO RTC: 170487 Disable for relevant platforms
+ default y if DRTM
+ depends on DRTM
+ help
+ Enable triggering DRTM from Hostboot when the
+ ATTR_FORCE_PRE_PAYLOAD_DRTM attribute is overridden
+
diff --git a/src/usr/secureboot/base/service.C b/src/usr/secureboot/base/service.C
index a381c4fd2..54b7d7fb7 100644
--- a/src/usr/secureboot/base/service.C
+++ b/src/usr/secureboot/base/service.C
@@ -109,6 +109,22 @@ errlHndl_t getJumperState(SecureJumperState& o_state, TARGETING::Target* i_targ)
return Singleton<Settings>::instance().getJumperState(o_state, i_targ);
}
+errlHndl_t clearSecuritySwitchBits(
+ const std::vector<SECUREBOOT::ProcSecurity>& i_bits,
+ TARGETING::Target* const i_pTarget)
+{
+ return Singleton<Settings>::instance().clearSecuritySwitchBits(
+ i_bits, i_pTarget);
+}
+
+errlHndl_t setSecuritySwitchBits(
+ const std::vector<SECUREBOOT::ProcSecurity>& i_bits,
+ TARGETING::Target* const i_pTarget)
+{
+ return Singleton<Settings>::instance().setSecuritySwitchBits(
+ i_bits, i_pTarget);
+}
+
void handleSecurebootFailure(errlHndl_t &io_err, bool i_waitForShutdown)
{
TRACFCOMP( g_trac_secure, ENTER_MRK"handleSecurebootFailure()");
diff --git a/src/usr/secureboot/base/settings.C b/src/usr/secureboot/base/settings.C
index bd8f129f0..83e5365e3 100644
--- a/src/usr/secureboot/base/settings.C
+++ b/src/usr/secureboot/base/settings.C
@@ -129,6 +129,141 @@ namespace SECUREBOOT
return l_errl;
}
+ errlHndl_t Settings::clearSecuritySwitchBits(
+ const std::vector<SECUREBOOT::ProcSecurity>& i_bits,
+ TARGETING::Target* const i_pTarget) const
+ {
+ uint64_t bitsToClear = 0;
+ for(const auto &bit : i_bits)
+ {
+ bitsToClear |= static_cast<uint64_t>(bit);
+ }
+
+ auto pError = writeSecurityRegister(
+ i_pTarget,
+ static_cast<uint64_t>(ProcSecurity::SwitchRegisterClear),
+ bitsToClear);
+
+ if(pError)
+ {
+ SB_ERR("clearSecuritySwitchBits: writeSecurityRegister "
+ "(SwitchRegisterClear) failed. Target HUID = 0x%08X, data = "
+ "0x%016llX.",
+ get_huid(i_pTarget),bitsToClear);
+ SB_ERR("clearSecuritySwitchBits: plid=0x%08X, eid=0x%08X, "
+ "reason=0x%04X",
+ ERRL_GETPLID_SAFE(pError),
+ ERRL_GETEID_SAFE(pError),
+ ERRL_GETRC_SAFE(pError));
+ }
+
+ return pError;
+ }
+
+ errlHndl_t Settings::setSecuritySwitchBits(
+ const std::vector<SECUREBOOT::ProcSecurity>& i_bits,
+ TARGETING::Target* const i_pTarget) const
+ {
+ uint64_t bitsToSet = 0;
+ for(const auto &bit : i_bits)
+ {
+ bitsToSet |= static_cast<uint64_t>(bit);
+ }
+
+ auto pError = writeSecurityRegister(
+ i_pTarget,
+ static_cast<uint64_t>(ProcSecurity::SwitchRegister),
+ bitsToSet);
+
+ if(pError)
+ {
+ SB_ERR("setSecuritySwitchBits: writeSecurityRegister "
+ "(SwitchRegister) failed. Target HUID = 0x%08X, data = "
+ "0x%016llX.",
+ get_huid(i_pTarget),bitsToSet);
+ SB_ERR("setSecuritySwitchBits: plid=0x%08X, eid=0x%08X, "
+ "reason=0x%04X",
+ ERRL_GETPLID_SAFE(pError),
+ ERRL_GETEID_SAFE(pError),
+ ERRL_GETRC_SAFE(pError));
+ }
+
+ return pError;
+ }
+
+ errlHndl_t Settings::writeSecurityRegister(
+ TARGETING::Target* const i_pTarget,
+ const uint64_t i_scomAddress,
+ const uint64_t i_data) const
+ {
+ errlHndl_t pError = nullptr;
+
+ do
+ {
+
+ // Target must be the sentinel or some other non-NULL proc value
+ if ( (i_pTarget != TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL)
+ && ( (i_pTarget == nullptr)
+ || ( (i_pTarget->getAttr<TARGETING::ATTR_TYPE>())
+ != (TARGETING::TYPE_PROC) ) ) )
+ {
+ SB_ERR("writeSecurityRegister: Caller invoked API with bad target; "
+ "Target HUID = 0x%08X.",get_huid(i_pTarget));
+ /*@
+ * @errortype
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid SECUREBOOT::MOD_SECURE_WRITE_REG
+ * @reasoncode SECUREBOOT::RC_SECURE_BAD_TARGET
+ * @userdata1 Target pointer value
+ * @userdata2 Target's HUID or 0 if NULL target pointer
+ * @devdesc Invalid target used to write security
+ * register.
+ * @custdesc Unexpected internal firmware error.
+ */
+ pError = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SECUREBOOT::MOD_SECURE_WRITE_REG,
+ SECUREBOOT::RC_SECURE_BAD_TARGET,
+ reinterpret_cast<uint64_t>(i_pTarget),
+ TO_UINT64(get_huid(i_pTarget)),
+ true);
+ pError->collectTrace(SECURE_COMP_NAME, ERROR_TRACE_SIZE);
+ break;
+ }
+
+ // Write security switch settings to processor
+ const size_t expSize = sizeof(i_data);
+ size_t actSize = expSize;
+ pError = deviceWrite(
+ i_pTarget,
+ const_cast<uint64_t*>(&i_data), actSize,
+ DEVICE_SCOM_ADDRESS(i_scomAddress));
+ if (nullptr != pError)
+ {
+ SB_ERR("writeSecurityRegister: deviceWrite failed; target HUID = "
+ "0x%08X, SCOM addr = 0x%016llX, data = 0x%016llX.",
+ get_huid(i_pTarget),i_scomAddress,i_data);
+ break;
+ }
+
+ assert(actSize == expSize,
+ "writeSecurityRegister: BUG! size returned from device write (%d) "
+ "is not the expected size of %d",actSize,expSize);
+
+ } while(0);
+
+ if(pError)
+ {
+ SB_ERR("writeSecurityRegister: plid=0x%08X, eid=0x%08X, "
+ "reason=0x%04X",
+ ERRL_GETPLID_SAFE(pError),
+ ERRL_GETEID_SAFE(pError),
+ ERRL_GETRC_SAFE(pError));
+ }
+
+ return pError;
+ }
+
errlHndl_t Settings::readSecurityRegister(Target* i_targ,
const uint64_t i_scomAddress,
uint64_t& o_regValue) const
diff --git a/src/usr/secureboot/common/securetrace.H b/src/usr/secureboot/common/securetrace.H
index 17c6988c7..06d3bc6b5 100644
--- a/src/usr/secureboot/common/securetrace.H
+++ b/src/usr/secureboot/common/securetrace.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016 */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -61,4 +61,10 @@ extern trace_desc_t* g_trac_secure;
#define SB_DBG_BIN(args...) \
TRACDBIN(SECUREBOOT::g_trac_secure,args)
+#define SB_UNIT(args...) \
+ TRACUCOMP(SECUREBOOT::g_trac_secure,"U> " args)
+
+#define SB_UNIT_BIN(args...) \
+ TRACUBIN(SECUREBOOT::g_trac_secure,args)
+
#endif
diff --git a/src/usr/secureboot/ext/drtm.C b/src/usr/secureboot/ext/drtm.C
new file mode 100644
index 000000000..1497e35e3
--- /dev/null
+++ b/src/usr/secureboot/ext/drtm.C
@@ -0,0 +1,723 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/secureboot/ext/drtm.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2013,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include <stdint.h>
+#include <config.h>
+#include <builtins.h>
+#include <limits.h>
+#include <string.h>
+#include <vector>
+#include <algorithm>
+
+#include <sys/mm.h>
+#include <sys/task.h>
+#include <util/align.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <targeting/common/util.H>
+#include <targeting/common/utilFilter.H>
+#include <targeting/common/commontargeting.H>
+#include <arch/pirformat.H>
+#include <initservice/mboxRegs.H>
+#include <util/utilmbox_scratch.H>
+#include <secureboot/settings.H>
+#include <secureboot/service.H>
+#include <secureboot/secure_reasoncodes.H>
+#include <secureboot/trustedbootif.H>
+#include <secureboot/drtm.H>
+
+#include "../common/securetrace.H"
+
+// Set to "1" to enable unit tracing
+#if 0
+ // Enable SB_UNIT
+ #define TRACUCOMP(args...) TRACFCOMP(args)
+ // Enable SB_UNIT_BIN
+ #define TRACUBIN(args...) TRACFBIN(args)
+#else
+ #define TRACUCOMP(args...)
+ #define TRACUBIN(args...)
+#endif
+
+// Makes the math more intuitive
+#define BYTES_PER_MEGABYTE MEGABYTE
+
+namespace SECUREBOOT
+{
+
+namespace DRTM
+{
+
+#ifdef CONFIG_DRTM_TRIGGERING
+
+// RIT protection DRTM payload address in megabytes
+// Use reserved area immediately before payload base
+const uint32_t DRTM_RIT_PAYLOAD_PHYS_ADDR_MB = 256-1;
+
+// RIT protection payload
+const char DRTM_RIT_PAYLOAD[] = {'D','R','T','M'};
+
+const char* const DRTM_RIT_LOG_TEXT = "DrtmPayload";
+
+#endif
+
+errlHndl_t discoverDrtmState(
+ const INITSERVICE::SPLESS::MboxScratch7_t& i_scratchReg7,
+ const INITSERVICE::SPLESS::MboxScratch8_t& i_scratchReg8)
+{
+ SB_ENTER("discoverDrtmState: i_scratchReg7=0x%08X, "
+ "i_scratchReg8 = 0x%08X",
+ i_scratchReg7.data32,i_scratchReg8.data32);
+
+ errlHndl_t pError = nullptr;
+
+ do
+ {
+
+ TARGETING::Target* pSysTarget = nullptr;
+ TARGETING::targetService().getTopLevelTarget(pSysTarget);
+
+ if(pSysTarget == nullptr)
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false,"discoverDrtmState: BUG! nullptr system target detected.");
+ break;
+ }
+
+ TARGETING::Target* pMasterProc = nullptr;
+ pError = TARGETING::targetService().queryMasterProcChipTargetHandle(
+ pMasterProc);
+ if(pError)
+ {
+ SB_ERR("discoverDrtmState: Failed in call to "
+ "queryMasterProcChipTargetHandle().");
+ break;
+ }
+
+ uint64_t securitySwitches = 0;
+ pError = SECUREBOOT::getSecuritySwitch(securitySwitches,
+ pMasterProc);
+ if(pError)
+ {
+ SB_ERR("discoverDrtmState: Failed in call to getSecuritySwitch() for "
+ "proc = 0x%08X.",
+ get_huid(pMasterProc));
+ break;
+ }
+
+ const bool masterProcL4A = securitySwitches
+ & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::L4ABit);
+ const bool masterProcLQA = securitySwitches
+ & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::LQABit);
+ const bool masterProcLLP = securitySwitches
+ & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::LLPBit);
+
+ const bool drtmPayloadValid = i_scratchReg8.validDrtmPayloadAddr;
+ const bool isMpiplBoot = pSysTarget->getAttr<TARGETING::ATTR_IS_MPIPL_HB>();
+ const bool securebootEnabled = SECUREBOOT::enabled();
+
+ SB_INF("discoverDrtmState: masterProcL4A = %d, drtmPayloadValid = %d, "
+ "isMpiplBoot = %d, securebootEnabled = %d, "
+ "masterProcLQA = %d, i_scratchReg7 = 0x%08X, "
+ "masterProcLLP = %d.",
+ masterProcL4A,drtmPayloadValid,isMpiplBoot,
+ securebootEnabled,masterProcLQA,i_scratchReg7.drtmPayloadAddrMb,
+ masterProcLLP);
+
+ TARGETING::ATTR_IS_DRTM_MPIPL_HB_type drtmMpIpl = false;
+ if(masterProcL4A || drtmPayloadValid)
+ {
+ // Note: We don't care if trusted boot is not enabled, if not, the
+ // measurement will simply be ignored later
+ if( !masterProcL4A
+ || !drtmPayloadValid
+ || !isMpiplBoot
+ || !securebootEnabled
+ || !masterProcLQA
+ || masterProcLLP)
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false,"discoverDrtmState: BUG! Inconsistent DRTM state "
+ "detected. masterProcL4A = %d, drtmPayloadValid = %d, "
+ "isMpiplBoot = %d, securebootEnabled = %d, "
+ "masterProcLQA = %d, masterProcLLP = %d.",
+ masterProcL4A,drtmPayloadValid,isMpiplBoot,
+ securebootEnabled,masterProcLQA,masterProcLLP);
+ break;
+ }
+ else
+ {
+ drtmMpIpl = true;
+ }
+ }
+
+ if( drtmMpIpl
+ && (i_scratchReg7.drtmPayloadAddrMb == 0))
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false,"discoverDrtmState: BUG! DRTM payload address "
+ "should not be 0 on a DRTM boot.");
+ break;
+ }
+
+ const auto drtmPayloadAddrMb = drtmMpIpl ?
+ i_scratchReg7.drtmPayloadAddrMb : 0;
+
+ pSysTarget->setAttr<TARGETING::ATTR_IS_DRTM_MPIPL_HB>(drtmMpIpl);
+ pSysTarget->setAttr<TARGETING::ATTR_DRTM_PAYLOAD_ADDR_MB_HB>(
+ drtmPayloadAddrMb);
+
+ // NOTE: It should be SBE job to clear the DRTM scratch regs
+ // on any given non-DRTM boot flow, hence Hostboot never has to clear them.
+
+ } while(0);
+
+ if(pError)
+ {
+ SB_ERR("discoverDrtmState: plid=0x%08X, eid=0x%08X, reason=0x%04X",
+ ERRL_GETPLID_SAFE(pError),
+ ERRL_GETEID_SAFE(pError),
+ ERRL_GETRC_SAFE(pError));
+ }
+
+ SB_EXIT("discoverDrtmState");
+
+ return pError;
+}
+
+void isDrtmMpipl(bool& o_isDrtmMpipl)
+{
+ TARGETING::Target* pSysTarget = nullptr;
+ TARGETING::targetService().getTopLevelTarget(pSysTarget);
+
+ if(pSysTarget == nullptr)
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false,"isDrtmMpipl: BUG! nullptr system target detected");
+ }
+
+ o_isDrtmMpipl = pSysTarget->getAttr<TARGETING::ATTR_IS_DRTM_MPIPL_HB>();
+}
+
+errlHndl_t validateDrtmHwSignature()
+{
+ SB_ENTER("validateDrtmHwSignature");
+
+ errlHndl_t pError = nullptr;
+
+ do
+ {
+ bool drtmMpIpl = false;
+ isDrtmMpipl(drtmMpIpl);
+
+ if(drtmMpIpl)
+ {
+ SB_DBG("validateDrtmHwSignature: DRTM active, checking L4A, LQA, "
+ "SUL, LLS and LLP on node's functional proc chips.");
+
+ TARGETING::TargetHandleList funcProcChips;
+ TARGETING::getAllChips(funcProcChips,
+ TARGETING::TYPE_PROC);
+ for(auto &pFuncProc :funcProcChips)
+ {
+ uint64_t securitySwitches = 0;
+ pError = SECUREBOOT::getSecuritySwitch(securitySwitches,
+ pFuncProc);
+ if(pError)
+ {
+ SB_ERR("validateDrtmHwSignature: getSecuritySwitch() "
+ "failed for proc = 0x%08X.",
+ get_huid(pFuncProc));
+ break;
+ }
+
+ const bool L4A = securitySwitches
+ & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::L4ABit);
+ const bool LQA = securitySwitches
+ & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::LQABit);
+ const bool SUL = securitySwitches
+ & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::SULBit);
+ const bool LLP = securitySwitches
+ & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::LLPBit);
+ const bool LLS = securitySwitches
+ & static_cast<uint64_t>(SECUREBOOT::ProcSecurity::LLSBit);
+
+ SB_INF("validateDrtmHwSignature: Proc 0x%08X has L4A = %d, "
+ "LQA = %d, SUL = %d, LLP = %d, LLS = %d.",
+ get_huid(pFuncProc),L4A,LQA,SUL,LLP,LLS);
+
+ if(!L4A || !LQA || !SUL || LLP || LLS)
+ {
+ // TODO: RTC 167205: GA error handling, including whether
+ // to attempt on every processor
+ assert(false,"validateDrtmHwSignature: BUG! In DRTM flow, "
+ "all functional proc chips should have L4A, LQA, and "
+ "SUL set + LLP and LLS clear, however proc 0x%08X has "
+ "L4A = %d, LQA = %d, SUL = %d, LLP = %d, LLS = %d.",
+ get_huid(pFuncProc),L4A,LQA,SUL,LLP,LLS);
+ break;
+ }
+ }
+
+ if(pError)
+ {
+ break;
+ }
+ }
+ else
+ {
+ SB_INF("validateDrtmHwSignature: DRTM not active, skipping check "
+ "for L4A, LQA, SUL, LLP and LLS on node's functional procs");
+ }
+
+ } while(0);
+
+ if(pError)
+ {
+ SB_ERR("validateDrtmHwSignature: plid=0x%08X, eid=0x%08X, "
+ "reason=0x%04X",
+ ERRL_GETPLID_SAFE(pError),
+ ERRL_GETEID_SAFE(pError),
+ ERRL_GETRC_SAFE(pError));
+ }
+
+ SB_EXIT("validateDrtmHwSignature");
+
+ return pError;
+}
+
+errlHndl_t validateDrtmPayload()
+{
+ SB_ENTER("validateDrtmPayload");
+
+ errlHndl_t pError = nullptr;
+ const void* drtmPayloadVirtAddr = nullptr;
+
+ do
+ {
+ bool drtmMpIpl = false;
+ isDrtmMpipl(drtmMpIpl);
+
+ if(drtmMpIpl)
+ {
+ SB_DBG("validateDrtmPayload: DRTM active, validating DRTM payload."
+ "proc chips.");
+
+ TARGETING::Target* pSysTarget = nullptr;
+ TARGETING::targetService().getTopLevelTarget(pSysTarget);
+
+ if(pSysTarget == nullptr)
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false,"validateDrtmPayload: BUG! nullptr system target "
+ "detected");
+ break;
+ }
+
+ const auto drtmPayloadPhysAddrMb = pSysTarget->getAttr<
+ TARGETING::ATTR_DRTM_PAYLOAD_ADDR_MB_HB>();
+
+ if(drtmPayloadPhysAddrMb == 0)
+ {
+ assert(false,"validateDrtmPayload: BUG! DRTM payload physical "
+ "address should not be 0.");
+ break;
+ }
+
+ const uint64_t drtmPayloadPhysAddr =
+ drtmPayloadPhysAddrMb*BYTES_PER_MEGABYTE;
+
+ SB_INF("validateDrtmPayload: DRTM payload available at physical "
+ "address of %d MB (0x%16llX).",
+ drtmPayloadPhysAddrMb,drtmPayloadPhysAddr);
+
+ // Compute DRTM payload size
+ // TODO: RTC 167205: Once the DRTM save area is known/defined,
+ // need to figure out a better initial size to map. For example,
+ // perhaps we map just one page to begin with, in order to read out
+ // the actual total size. Also, a size is available, assert if the
+ // size is 0.
+ uint64_t drtmPayloadSize = 0;
+ #ifdef CONFIG_DRTM_TRIGGERING
+ drtmPayloadSize = ALIGN_PAGE(sizeof(DRTM_RIT_PAYLOAD));
+ #endif
+
+ // Map in the physical memory to virtual memory
+ drtmPayloadVirtAddr = mm_block_map (
+ reinterpret_cast<void*>(drtmPayloadPhysAddr),drtmPayloadSize);
+ if(drtmPayloadVirtAddr == nullptr)
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false,"validateDrtmPayload: BUG! mm_block_map returned "
+ "nullptr for physical address 0x%016llX and size "
+ "0x%016llX.",
+ drtmPayloadPhysAddr,drtmPayloadSize);
+ break;
+ }
+
+ #ifdef CONFIG_DRTM_TRIGGERING
+
+ // Verify the payload matches expected result
+ if(memcmp(drtmPayloadVirtAddr,DRTM_RIT_PAYLOAD,
+ sizeof(DRTM_RIT_PAYLOAD) != 0))
+ {
+ const uint32_t* pAddrAct = reinterpret_cast<const uint32_t*>(
+ drtmPayloadVirtAddr);
+ const uint32_t* pAddrExp = reinterpret_cast<const uint32_t*>(
+ &DRTM_RIT_PAYLOAD);
+
+ SB_ERR("validateDrtmPayload: DRTM RIT: payload content at "
+ "0x%16llX was not as expected. Expected value = 0x%08X, "
+ "actual = 0x%08X",
+ drtmPayloadVirtAddr,
+ *pAddrAct,
+ *pAddrExp);
+
+ // TODO: RTC 167205: GA error handling
+ assert(false,"validateDrtmPayload: BUG: DRTM payload content "
+ "at 0x%16llX was not as expected. Expected value = "
+ "0x%08X, actual = 0x%08X",
+ drtmPayloadVirtAddr,
+ *pAddrAct,
+ *pAddrExp);
+ break;
+ }
+
+ // Extend (arbitrary) measurement to PCR17
+ SHA512_t hash = {0};
+ memcpy(hash,DRTM_RIT_PAYLOAD,sizeof(DRTM_RIT_PAYLOAD));
+ pError = TRUSTEDBOOT::pcrExtend(TRUSTEDBOOT::PCR_DRTM_17, hash,
+ sizeof(SHA512_t),DRTM_RIT_LOG_TEXT);
+ if(pError)
+ {
+ SB_ERR("validateDrtmPayload: Failed in pcrExtend() for PCR 17");
+ break;
+ }
+
+ #else
+
+ // TODO: RTC 167205: Securely verify the measured launch environment
+ // TODO: RTC 167205: Really measure+extend the payload
+
+ #endif
+ }
+ else
+ {
+ SB_INF("validateDrtmPayload: DRTM not active, skipping DRTM "
+ "payload verification ");
+ }
+
+ } while(0);
+
+ if(drtmPayloadVirtAddr)
+ {
+ auto rc = mm_block_unmap(const_cast<void*>(drtmPayloadVirtAddr));
+ if(rc != 0)
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false,"validateDrtmPayload: BUG! mm_block_unmap failed for "
+ "virtual address 0x%16llX.",
+ drtmPayloadVirtAddr);
+
+ }
+ }
+
+ if(pError)
+ {
+ SB_ERR("validateDrtmPayload: plid=0x%08X, eid=0x%08X, reason=0x%04X",
+ ERRL_GETPLID_SAFE(pError),
+ ERRL_GETEID_SAFE(pError),
+ ERRL_GETRC_SAFE(pError));
+ }
+
+ SB_EXIT("validateDrtmPayload");
+
+ return pError;
+}
+
+errlHndl_t completeDrtm()
+{
+ SB_ENTER("completeDrtm");
+
+ errlHndl_t pError = nullptr;
+
+ do
+ {
+ bool drtmMpIpl = false;
+ isDrtmMpipl(drtmMpIpl);
+
+ if(drtmMpIpl)
+ {
+ SB_INF("completeDrtm: Clearing L4A and LQA on node's functional "
+ "proc chips.");
+
+ const std::vector<SECUREBOOT::ProcSecurity> bitsToClear {
+ SECUREBOOT::ProcSecurity::L4ABit,
+ SECUREBOOT::ProcSecurity::LQABit
+ };
+
+ TARGETING::TargetHandleList funcProcChips;
+ TARGETING::getAllChips(funcProcChips,
+ TARGETING::TYPE_PROC);
+
+ for(auto &pFuncProc :funcProcChips)
+ {
+ pError = SECUREBOOT::clearSecuritySwitchBits(bitsToClear,
+ pFuncProc);
+ if(pError)
+ {
+ // TODO: RTC 167205: GA error handling to attempt on every
+ // processor
+ SB_ERR("completeDrtm: clearSecuritySwitchBits() failed for "
+ "proc = 0x%08X. Tried to clear LQA + L4A.",
+ get_huid(pFuncProc));
+ break;
+ }
+ }
+
+ if(pError)
+ {
+ break;
+ }
+
+ }
+ else
+ {
+ SB_INF("completeDrtm: DRTM not active, not clearing LQA or L4A "
+ "bits.");
+ }
+
+ } while(0);
+
+ if(pError)
+ {
+ SB_ERR("completeDrtm: plid=0x%08X, eid=0x%08X, reason=0x%04X",
+ ERRL_GETPLID_SAFE(pError),
+ ERRL_GETEID_SAFE(pError),
+ ERRL_GETRC_SAFE(pError));
+ }
+
+ SB_EXIT("completeDrtm");
+
+ return pError;
+}
+
+#ifdef CONFIG_DRTM_TRIGGERING
+
+errlHndl_t initiateDrtm()
+{
+ SB_ENTER("initiateDrtm");
+
+ errlHndl_t pError = nullptr;
+
+ // For DRTM, the thread has to be pinned to a core (and therefore pinned to
+ // a chip)
+ task_affinity_pin();
+
+ void* drtmPayloadVirtAddr = nullptr;
+
+ do
+ {
+ const std::vector<SECUREBOOT::ProcSecurity> LLP {
+ SECUREBOOT::ProcSecurity::LLPBit,
+ };
+
+ const std::vector<SECUREBOOT::ProcSecurity> LLS {
+ SECUREBOOT::ProcSecurity::LLSBit,
+ };
+
+ // Determine which fabric group and chip this task is executing on and
+ // create a filter to find the matching chip target
+ auto cpuId = task_getcpuid();
+ auto groupId = PIR_t::groupFromPir(cpuId);
+ auto chipId = PIR_t::chipFromPir(cpuId);
+ TARGETING::PredicateAttrVal<TARGETING::ATTR_FABRIC_GROUP_ID>
+ matchesGroup(groupId);
+ TARGETING::PredicateAttrVal<TARGETING::ATTR_FABRIC_CHIP_ID>
+ matchesChip(chipId);
+ TARGETING::PredicatePostfixExpr matchesGroupAndChip;
+ matchesGroupAndChip.push(&matchesGroup).push(&matchesChip).And();
+
+ // Get all the functional proc chips and find the chip we're running on
+ TARGETING::TargetHandleList funcProcChips;
+ TARGETING::getAllChips(funcProcChips,
+ TARGETING::TYPE_PROC);
+ if(funcProcChips.empty())
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false,"initiateDrtm: BUG! Functional proc chips is empty, "
+ "yet this code is running on a functional chip!");
+ break;
+ }
+
+ // NOTE: std::find_if requires predicates to be copy constructable, but
+ // predicates are not; hence use a wrapper lambda function to bypass
+ // that limitation
+ auto pMatch =
+ std::find_if(funcProcChips.begin(),funcProcChips.end(),
+ [&matchesGroupAndChip] ( TARGETING::Target* pTarget )
+ {
+ return matchesGroupAndChip(pTarget);
+ } );
+
+ if(pMatch == funcProcChips.end())
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false, "initiateDrtm: BUG! No functional chip found "
+ "to be running this code");
+ break;
+ }
+
+ // Move the matching target to the end of the list.
+ // NOTE: If reverse iterators were supported, we could have verified the
+ // last element of the container is not the match, and done a
+ // std::iter_swap of the match and the last element
+ TARGETING::Target* const pMatchTarget = *pMatch;
+ funcProcChips.erase(pMatch);
+ funcProcChips.push_back(pMatchTarget);
+
+ // Map to the DRTM payload area in mainstore
+ const uint32_t drtmPayloadPhysAddrMb = DRTM_RIT_PAYLOAD_PHYS_ADDR_MB;
+ drtmPayloadVirtAddr = mm_block_map(
+ reinterpret_cast<void*>(drtmPayloadPhysAddrMb*BYTES_PER_MEGABYTE),
+ PAGESIZE);
+ if(drtmPayloadVirtAddr == nullptr)
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false, "initiateDrtm: BUG! Failed in call to mm_block_map "
+ "to map the DRTM payload.");
+ break;
+ }
+
+ // Copy the DRTM payload to the DRTM payload area
+ memcpy(
+ reinterpret_cast<uint32_t*>(drtmPayloadVirtAddr),
+ DRTM_RIT_PAYLOAD,
+ sizeof(DRTM_RIT_PAYLOAD));
+
+ // The required generic sequencing to initiate DRTM is as follows:
+ // 1) Initiating task must pin itself to a core (to ensure it
+ // will not be accidentally queisced by SBE)
+ // 2) It must set the DRTM payload information in the master processor
+ // mailbox scratch registers (registers 7 and 8) before it goes
+ // offline
+ // 3) It must determine the processor it's currently running on
+ // 4) It must set the late launch bit (LL) on all other processors
+ // 4a) If the given processor is an active master, it must set
+ // late launch primary (LLP) bit
+ // 4b) Otherwise it must set late launch secondary (LLS) bit
+ // 5) Finally, it must its own processor's LL bit last, according to the
+ // rules of step 4.
+ for(auto &pFuncProc :funcProcChips)
+ {
+ const auto procMasterType = pFuncProc->getAttr<
+ TARGETING::ATTR_PROC_MASTER_TYPE>();
+
+ // If master chip, set the DRTM payload address and validity
+ if(procMasterType == TARGETING::PROC_MASTER_TYPE_ACTING_MASTER)
+ {
+ (void)setDrtmPayloadPhysAddrMb(drtmPayloadPhysAddrMb);
+ }
+
+ pError = SECUREBOOT::setSecuritySwitchBits(procMasterType ==
+ TARGETING::PROC_MASTER_TYPE_ACTING_MASTER ?
+ LLP : LLS,
+ pFuncProc);
+ if(pError)
+ {
+ SB_ERR("initiateDrtm: setSecuritySwitchBits() failed for proc "
+ "= 0x%08X. Tried to set LLP or LLS.",
+ get_huid(pFuncProc));
+ break;
+ }
+ }
+
+ if(pError)
+ {
+ break;
+ }
+
+
+ SB_INF("initiateDrtm: SBE should eventually quiesce all cores; until "
+ "then, endlessly yield the task");
+ while(1)
+ {
+ task_yield();
+ }
+
+ } while(0);
+
+ // If we -do- come back from this function (on error path only), then we
+ // should unpin
+ task_affinity_unpin();
+
+ if(drtmPayloadVirtAddr)
+ {
+ auto rc = mm_block_unmap(const_cast<void*>(drtmPayloadVirtAddr));
+ if(rc != 0)
+ {
+ // TODO: RTC 167205: GA error handling
+ assert(false,"initiateDrtm: BUG! mm_block_unmap failed for virtual "
+ "address 0x%16llX.",
+ drtmPayloadVirtAddr);
+ }
+ }
+
+ if(pError)
+ {
+ SB_ERR("initiateDrtm: plid=0x%08X, eid=0x%08X, reason=0x%04X",
+ ERRL_GETPLID_SAFE(pError),
+ ERRL_GETEID_SAFE(pError),
+ ERRL_GETRC_SAFE(pError));
+ }
+
+ SB_EXIT("initiateDrtm");
+
+ return pError;
+}
+
+void setDrtmPayloadPhysAddrMb(
+ const uint32_t i_drtmPayloadPhysAddrMb)
+{
+ // Set the address
+ Util::writeScratchReg(
+ INITSERVICE::SPLESS::MBOX_SCRATCH_REG7,i_drtmPayloadPhysAddrMb);
+
+ // Mark as valid if non-0, else invalid
+ INITSERVICE::SPLESS::MboxScratch8_t scratch8 =
+ { .data32 = Util::readScratchReg(
+ INITSERVICE::SPLESS::MBOX_SCRATCH_REG8) };
+ scratch8.validDrtmPayloadAddr =
+ i_drtmPayloadPhysAddrMb ? true : false;
+ Util::writeScratchReg(
+ INITSERVICE::SPLESS::MBOX_SCRATCH_REG8,scratch8.data32);
+}
+
+#endif // CONFIG_DRTM_TRIGGERING
+
+} // End DRTM namespace
+
+} // End SECUREBOOT namespace
+
diff --git a/src/usr/secureboot/ext/makefile b/src/usr/secureboot/ext/makefile
index ddc0261cc..952a8cc56 100644
--- a/src/usr/secureboot/ext/makefile
+++ b/src/usr/secureboot/ext/makefile
@@ -5,7 +5,9 @@
#
# OpenPOWER HostBoot Project
#
-# COPYRIGHT International Business Machines Corp. 2013,2014
+# Contributors Listed Below - COPYRIGHT 2013,2017
+# [+] International Business Machines Corp.
+#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,7 +26,7 @@ ROOTPATH = ../../../..
MODULE = secureboot_ext
SUBDIRS +=
-OBJS +=
+OBJS += $(if $(CONFIG_DRTM),drtm.o)
CFLAGS += -iquote ../
include ${ROOTPATH}/config.mk
diff --git a/src/usr/secureboot/trusted/trustedboot.C b/src/usr/secureboot/trusted/trustedboot.C
index b6bbd313b..2009ab07a 100644
--- a/src/usr/secureboot/trusted/trustedboot.C
+++ b/src/usr/secureboot/trusted/trustedboot.C
@@ -56,6 +56,9 @@
#include "tpmLogMgr.H"
#include "base/trustedbootMsg.H"
#include <secureboot/settings.H>
+#ifdef CONFIG_DRTM
+#include <secureboot/drtm.H>
+#endif
namespace TRUSTEDBOOT
{
@@ -375,10 +378,18 @@ void tpmInitialize(TRUSTEDBOOT::TpmTarget & io_target)
io_target.initAttempted = true;
io_target.failed = false;
- bool drtm = false;
- /// @todo #157140 Add ability to check for DRTM
+ bool sendStartup = true;
+
+#ifdef CONFIG_DRTM
+ bool drtmMpipl = false;
+ (void)SECUREBOOT::DRTM::isDrtmMpipl(drtmMpipl);
+ if(drtmMpipl)
+ {
+ sendStartup = false;
+ }
+#endif
// Don't run STARTUP during DRTM
- if (!drtm)
+ if (sendStartup)
{
// TPM_STARTUP
err = tpmCmdStartup(&io_target);
@@ -395,11 +406,13 @@ void tpmInitialize(TRUSTEDBOOT::TpmTarget & io_target)
break;
}
+#ifdef CONFIG_DRTM
// For a DRTM we need to reset PCRs 17-22
- if (drtm)
+ if (drtmMpipl)
{
- /// @todo Implement PCR reset
+ /// @TODO RTC 167667 Implement PCR reset
}
+#endif
} while ( 0 );
@@ -596,7 +609,7 @@ errlHndl_t tpmLogConfigEntries(TRUSTEDBOOT::TpmTarget & io_target)
}
void pcrExtendSingleTpm(TpmTarget & io_target,
- TPM_Pcr i_pcr,
+ const TPM_Pcr i_pcr,
TPM_Alg_Id i_algId,
const uint8_t* i_digest,
size_t i_digestSize,
@@ -606,6 +619,26 @@ void pcrExtendSingleTpm(TpmTarget & io_target,
TCG_PCR_EVENT2 eventLog;
bool unlock = false;
+ TPM_Pcr pcr = i_pcr;
+ bool useStaticLog = true;
+
+#ifdef CONFIG_DRTM
+ // In a DRTM flow, all extensions must be re-rerouted to PCR 17
+ // (which will end up using locality 2).
+ bool drtmMpipl = false;
+ (void)SECUREBOOT::DRTM::isDrtmMpipl(drtmMpipl);
+ if(drtmMpipl)
+ {
+ TRACFCOMP(g_trac_trustedboot,
+ INFO_MRK " pcrExtendSingleTpm(): DRTM active; re-routing PCR %d "
+ "extend to PCR 17",
+ i_pcr);
+
+ pcr = PCR_DRTM_17;
+ useStaticLog = false;
+ }
+#endif
+
memset(&eventLog, 0, sizeof(eventLog));
do
{
@@ -617,22 +650,29 @@ void pcrExtendSingleTpm(TpmTarget & io_target,
!io_target.failed)
{
// Fill in TCG_PCR_EVENT2 and add to log
- eventLog = TpmLogMgr_genLogEventPcrExtend(i_pcr,
+ eventLog = TpmLogMgr_genLogEventPcrExtend(pcr,
i_algId, i_digest,
i_digestSize,
TPM_ALG_SHA1, i_digest,
i_digestSize,
i_logMsg);
- err = TpmLogMgr_addEvent(io_target.logMgr,&eventLog);
- if (NULL != err)
+ if(useStaticLog)
{
- break;
+ err = TpmLogMgr_addEvent(io_target.logMgr,&eventLog);
+ if (NULL != err)
+ {
+ break;
+ }
}
+ // TODO: RTC 145689: Add DRTM support for using dynamic
+ // log instead of static log; until then, inhibit DRTM logging
+ // entirely
+
// Perform the requested extension and also force into the
// SHA1 bank
err = tpmCmdPcrExtend2Hash(&io_target,
- i_pcr,
+ pcr,
i_algId,
i_digest,
i_digestSize,
@@ -685,16 +725,34 @@ void pcrExtendSeparator(TpmTarget & io_target)
mutex_lock( &io_target.tpmMutex );
unlock = true;
- for (TPM_Pcr curPcr = PCR_0; curPcr <= PCR_7;
- curPcr = static_cast<TPM_Pcr>(curPcr + 1))
+ std::vector<TPM_Pcr> pcrs =
+ {PCR_0,PCR_1,PCR_2,PCR_3,PCR_4,PCR_5,PCR_6,PCR_7};
+ bool useStaticLog = true;
+
+#ifdef CONFIG_DRTM
+ // In a DRTM flow, all extensions must be re-rerouted to PCR 17
+ // (which will end up using locality 2).
+ bool drtmMpipl = false;
+ (void)SECUREBOOT::DRTM::isDrtmMpipl(drtmMpipl);
+ if(drtmMpipl)
{
+ TRACFCOMP(g_trac_trustedboot,
+ INFO_MRK " pcrExtendSeparator(): DRTM active; extending "
+ "separator to PCR 17 instead of PCR 0..7.");
+
+ pcrs = { PCR_DRTM_17 };
+ useStaticLog = false;
+ }
+#endif
+ for (const auto &pcr : pcrs)
+ {
// Log the separator
if (io_target.available &&
!io_target.failed)
{
// Fill in TCG_PCR_EVENT2 and add to log
- eventLog = TpmLogMgr_genLogEventPcrExtend(curPcr,
+ eventLog = TpmLogMgr_genLogEventPcrExtend(pcr,
TPM_ALG_SHA1,
sha1_digest,
sizeof(sha1_digest),
@@ -702,15 +760,24 @@ void pcrExtendSeparator(TpmTarget & io_target)
sha256_digest,
sizeof(sha256_digest),
logMsg);
- err = TpmLogMgr_addEvent(io_target.logMgr,&eventLog);
- if (NULL != err)
+
+ if(useStaticLog)
{
- break;
+ err = TpmLogMgr_addEvent(io_target.logMgr,&eventLog);
+ if (NULL != err)
+ {
+ break;
+ }
}
+ // TODO: RTC 145689: Add DRTM support for using dynamic
+ // log (which will happen any time useStaticLog is false).
+ // Until then, we cannot log DRTM events, since they are only
+ // allowed to go to the dynamic log
+
// Perform the requested extension
err = tpmCmdPcrExtend2Hash(&io_target,
- curPcr,
+ pcr,
TPM_ALG_SHA1,
sha1_digest,
sizeof(sha1_digest),
diff --git a/src/usr/secureboot/trusted/trustedbootCmds.C b/src/usr/secureboot/trusted/trustedbootCmds.C
index 9e5875933..a052c0571 100644
--- a/src/usr/secureboot/trusted/trustedbootCmds.C
+++ b/src/usr/secureboot/trusted/trustedbootCmds.C
@@ -37,6 +37,8 @@
// ----------------------------------------------
#include <string.h>
#include <stdlib.h>
+#include <config.h>
+
#ifdef __HOSTBOOT_MODULE
#include <secureboot/trustedboot_reasoncodes.H>
#else
@@ -47,6 +49,10 @@
#include "trustedboot.H"
#include "trustedTypes.H"
+#ifdef CONFIG_DRTM
+#include <secureboot/drtm.H>
+#endif
+
#ifdef __cplusplus
namespace TRUSTEDBOOT
{
@@ -844,10 +850,26 @@ errlHndl_t tpmCmdPcrExtend2Hash(TpmTarget * io_target,
i_digestSize_2 : fullDigestSize_2));
}
+ tpm_locality_t tpmLocality = TPM_LOCALITY_0;
+#ifdef CONFIG_DRTM
+ bool drtmMpipl = false;
+ SECUREBOOT::DRTM::isDrtmMpipl(drtmMpipl);
+ if(drtmMpipl)
+ {
+ assert(i_pcr == TRUSTEDBOOT::PCR_DRTM_17,
+ "BUG! All DRTM extensions must be to PCR 17 (instead of %d)",
+ i_pcr);
+
+ TRACFCOMP(g_trac_trustedboot,
+ INFO_MRK " tpmCmdPcrExtend2Hash(): DRTM active, redirecting "
+ "PCR extend request from locality 0 to locality 2.");
+ tpmLocality = TPM_LOCALITY_2;
+ }
+#endif
err = tpmTransmitCommand(io_target,
dataBuf,
sizeof(dataBuf),
- TPM_LOCALITY_0);
+ tpmLocality);
if (TB_SUCCESS != err)
{
OpenPOWER on IntegriCloud