summaryrefslogtreecommitdiffstats
path: root/src/usr/secureboot
diff options
context:
space:
mode:
authorIlya Smirnov <ismirno@us.ibm.com>2019-01-15 16:08:48 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2019-02-19 16:56:50 -0600
commit00325c6de8baa143c8e06e9324d6ba997465aa1f (patch)
tree819430f83cbfdb317e99878b05a6991734bd1852 /src/usr/secureboot
parent6781c16acf6de4b08cbc55f2569062ba1c655592 (diff)
downloadtalos-hostboot-00325c6de8baa143c8e06e9324d6ba997465aa1f.tar.gz
talos-hostboot-00325c6de8baa143c8e06e9324d6ba997465aa1f.zip
Secureboot: Enhanced Multinode Comm: Slave Node
This commit introduces the logic to create the slave response for the new enhanced multinode comm protocol. The slave response consists of an eye catcher, node ID, quote and signature data from TPM, PCR contents of the slave node TPM, Attestation Key Certificate, and the TPM log. All of the above data is packaged into a binary blob to be sent back to the master node. Change-Id: I927c6ca937e6c07af4185cf54c782697c5d822f6 RTC: 203643 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/70791 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: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com> Reviewed-by: Marshall J. Wilks <mjwilks@us.ibm.com> Reviewed-by: Christopher J. Engel <cjengel@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-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/node_comm/node_comm.H5
-rw-r--r--src/usr/secureboot/node_comm/node_comm_exchange.C335
-rw-r--r--src/usr/secureboot/trusted/base/trustedbootMsg.H33
-rw-r--r--src/usr/secureboot/trusted/base/trustedboot_base.C64
-rw-r--r--src/usr/secureboot/trusted/trustedTypes.C6
-rw-r--r--src/usr/secureboot/trusted/trustedTypes.H53
-rw-r--r--src/usr/secureboot/trusted/trustedboot.C68
-rw-r--r--src/usr/secureboot/trusted/trustedboot.H4
-rw-r--r--src/usr/secureboot/trusted/trustedbootCmds.C23
-rw-r--r--src/usr/secureboot/trusted/trustedbootCmds.H5
10 files changed, 554 insertions, 42 deletions
diff --git a/src/usr/secureboot/node_comm/node_comm.H b/src/usr/secureboot/node_comm/node_comm.H
index 67bf10fb5..d7b843a3e 100644
--- a/src/usr/secureboot/node_comm/node_comm.H
+++ b/src/usr/secureboot/node_comm/node_comm.H
@@ -34,15 +34,14 @@
#include <trace/interface.H>
#include <scom/centaurScomCache.H> // for TRACE_ERR_FMT, TRACE_ERR_ARGS
#include <secureboot/nodecommif.H>
+#include "../trusted/trustedboot.H"
+
// ----------------------------------------------
// Defines
// ----------------------------------------------
#define NODECOMM_TRACE_NAME "NODECOMM"
extern trace_desc_t* g_trac_nc;
-// Easy macro replace for unit testing - TRACD vs TRACF
-#define TRACUCOMP(args...) TRACDCOMP(args)
-
namespace SECUREBOOT
{
diff --git a/src/usr/secureboot/node_comm/node_comm_exchange.C b/src/usr/secureboot/node_comm/node_comm_exchange.C
index 5383056b6..a7efd6129 100644
--- a/src/usr/secureboot/node_comm/node_comm_exchange.C
+++ b/src/usr/secureboot/node_comm/node_comm_exchange.C
@@ -56,6 +56,12 @@
#include "node_comm.H"
#include "node_comm_transfer.H"
+#include <secureboot/service.H>
+#include <securerom/contrib/sha512.H>
+
+#include "../trusted/trustedTypes.H"
+#include "../trusted/tpmLogMgr.H"
+
// ----------------------------------------------
// Defines
// ----------------------------------------------
@@ -264,6 +270,335 @@ errlHndl_t nodeCommAbusLogNonce(uint64_t & i_nonce)
} // end of nodeCommAbusLogNonce
+/**
+ * @brief A function to create the slave node response quote that consists of
+ * eye catcher, slave node ID, quote and signature data (represented by
+ * the QuoteDataOut structure), the contents of PCRs 0-7, the
+ * Attestation Key Certificate returned from TPM, the size
+ * and the contents of the TPM log
+ * @param[in] i_masterEyeCatcher the eye catcher from master node that indicates
+ * the state of master node's TPM. (If master node's TPM is in bad
+ * state, the slave node won't generate the full quote, as remote
+ * attestation is not possible)
+ * @param[in] i_nonce the 32-byte nonce generated by the master node
+ * @param[in] i_pcrSelect the PCR selection structure
+ * @param[out] o_size the size of the slave quote
+ * @param[out] o_resp the slave quote in binary format
+ * @note Assuming CONFIG_TPMDD is compiled in, o_resp is always allocated
+ * dynamically in this function, and it is the responsibility of the
+ * calller to delete it after the function returns. If an error occurs
+ * within the function, the o_resp will only have an eye catcher
+ * indicating that the slave quote is bad.
+ * @return nullptr on success; non-nullptr on error
+ */
+errlHndl_t nodeCommGenSlaveResponseQuote(const SECUREBOOT::NODECOMM::NCEyeCatcher_t i_masterEyeCatch,
+ const TRUSTEDBOOT::MasterTpmNonce_t* const i_nonce,
+ const TRUSTEDBOOT::TPML_PCR_SELECTION* const i_pcrSelect,
+ size_t& o_size,
+ uint8_t*& o_resp)
+{
+ errlHndl_t l_errl = nullptr;
+#ifdef CONFIG_TPMDD
+ TRACFCOMP(g_trac_nc, ENTER_MRK"nodeCommGenSlaveResponseQuote");
+ bool l_tpmRequired = TRUSTEDBOOT::isTpmRequired();
+ bool l_errorOccurred = false;
+
+ TRUSTEDBOOT::QuoteDataOut l_quoteData;
+ uint32_t l_nodeId = TARGETING::UTIL::getCurrentNodePhysId();
+ do {
+
+ o_resp = nullptr;
+
+ TARGETING::Target* l_primaryTpm = nullptr;
+ TRUSTEDBOOT::getPrimaryTpm(l_primaryTpm);
+ if(!l_primaryTpm ||
+ !l_primaryTpm->getAttr<TARGETING::ATTR_HWAS_STATE>().functional ||
+ !l_primaryTpm->getAttr<TARGETING::ATTR_HWAS_STATE>().present)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommGenSlaveResponseQuote: primary TPM not found or not functional");
+ l_errorOccurred = true;
+ break;
+ }
+
+
+ // If Master indicated that there is an issue with its TPM: Case 1: If the
+ // TPM Required policy is on, terminate the boot; Case 2: If TPM required
+ // policy is off, send back a token indicating that no nodecomm TPM commands
+ // have been performed (remote attestation is not possible with bad master
+ // TPM); do not fail the boot.
+ if(i_masterEyeCatch == SECUREBOOT::NODECOMM::MSTNOTPM)
+ {
+ l_errorOccurred = true;
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommGenSlaveResponseQuote: Master indicated an issue with secure nodecomm (master eye catcher is MSTNOTPM)");
+ // Case 1
+ if(l_tpmRequired)
+ {
+ /* @
+ * @errortype
+ * @reasoncode RC_NC_BAD_MASTER_TPM
+ * @moduleid MOD_NC_GEN_SLAVE_RESPONSE
+ * @userdata1 <unused>
+ * @userdata2 <unused>
+ * @devdesc The system policy is set to not allow boot without a
+ * functioning TPM, but the system's master node
+ * indicated that its TPM is compromised. This slave
+ * node must terminate the boot process.
+ * @custdesc Trustedboot failure
+ */
+ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_NC_GEN_SLAVE_RESPONSE,
+ RC_NC_BAD_MASTER_TPM);
+ // It is unlikely that there is an issue with this node, but collect
+ // the logs anyway for ease of debug.
+ l_errl->collectTrace(SECURE_COMP_NAME);
+ l_errl->collectTrace(TRBOOT_COMP_NAME);
+ l_errl->collectTrace(NODECOMM_TRACE_NAME);
+
+
+ break;
+ }
+ // Case 2
+ // The error condition will be handled below in the if branch that
+ // checks l_errorOccurred
+ }
+ else if(i_masterEyeCatch != SECUREBOOT::NODECOMM::MASTERQ_)
+ {
+ l_errorOccurred = true;
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommGenSlaveResponseQuote: Invalid master eye catcher received: 0x%x", i_masterEyeCatch);
+ if(l_tpmRequired)
+ {
+ /* @
+ * @errortype
+ * @reasoncode RC_NC_BAD_MASTER_EYE_CATCH
+ * @moduleid MOD_NC_GEN_SLAVE_RESPONSE
+ * @userdata1 Eye catcher received from master
+ * @devdesc Master node sent an unrecognized eye catcher
+ * @custdesc Trustedboot failure
+ */
+ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_NC_GEN_SLAVE_RESPONSE,
+ RC_NC_BAD_MASTER_EYE_CATCH,
+ i_masterEyeCatch);
+ // It is unlikely that there is an issue with this node, but collect
+ // the logs anyway for ease of debug.
+ l_errl->collectTrace(NODECOMM_TRACE_NAME);
+ l_errl->collectTrace(TRBOOT_COMP_NAME);
+ l_errl->collectTrace(SECURE_COMP_NAME);
+ }
+ break;
+ }
+
+ // Step 1: Recreate node Attestation Key (AK)
+ l_errl = TRUSTEDBOOT::createAttestationKeys(l_primaryTpm);
+ if(l_errl)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommGenSlaveResponseQuote: could not create attestation keys");
+ break;
+ }
+
+ TRUSTEDBOOT::TPM2B_MAX_NV_BUFFER l_AKCert;
+ // Step 2: Read the AK Certificate
+ l_errl = TRUSTEDBOOT::readAKCertificate(l_primaryTpm, &l_AKCert);
+ if(l_errl)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommGenSlaveResponseQuote: could not read AK certificate");
+ break;
+ }
+
+ // Hash the AK Certificate and extend the hash into PCR1
+ SHA512_t l_AKCertHash = {0};
+ hashBlob(l_AKCert.buffer,
+ sizeof(l_AKCert.buffer),
+ l_AKCertHash);
+
+ l_errl = TRUSTEDBOOT::pcrExtend(TRUSTEDBOOT::PCR_1,
+ TRUSTEDBOOT::EV_PLATFORM_CONFIG_FLAGS,
+ l_AKCertHash,
+ sizeof(l_AKCertHash),
+ "AK Certificate Hash"); // @TODO RTC 203644 this should be a full AK certificate in binary
+ if(l_errl)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommGenSlaveResponseQuote: could not extend AK Certificate hash to TPM");
+ break;
+ }
+
+ l_quoteData.data = new uint8_t[1 * KILOBYTE]{};// the actual data size will
+ // be smaller than 1KB
+ // Step 3: Generate quote and signature data (presented as binary data in
+ // the QuoteDataOut structure)
+ l_errl = TRUSTEDBOOT::generateQuote(l_primaryTpm,
+ i_nonce,
+ &l_quoteData);
+ if(l_errl)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommGenSlaveResponseQuote: could not generate TPM quote");
+ break;
+ }
+
+ // Step 4: Flush the AK from the TPM
+ l_errl = TRUSTEDBOOT::flushContext(l_primaryTpm);
+ if(l_errl)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommGenSlaveResponseQuote: could not flush TPM context");
+ break;
+ }
+
+ // @TODO RTC 203645 use the i_pcrSelect to read selected PCRs
+ // Step 5: Read PCRs 0-7
+ uint32_t l_pcrCount = TRUSTEDBOOT::FW_USED_PCR_COUNT;
+ TRUSTEDBOOT::TPM_Pcr l_pcrRegs[l_pcrCount] = {
+ TRUSTEDBOOT::PCR_0,
+ TRUSTEDBOOT::PCR_1,
+ TRUSTEDBOOT::PCR_2,
+ TRUSTEDBOOT::PCR_3,
+ TRUSTEDBOOT::PCR_4,
+ TRUSTEDBOOT::PCR_5,
+ TRUSTEDBOOT::PCR_6,
+ TRUSTEDBOOT::PCR_7
+ };
+ size_t l_digestSize =
+ TRUSTEDBOOT::getDigestSize(TRUSTEDBOOT::TPM_ALG_SHA256);
+
+ // An array of PCR Digest structures to hold the contents of PCRs 0-7
+ TRUSTEDBOOT::TPM2B_DIGEST l_pcrDigests[l_pcrCount];
+ for(const auto l_pcr : l_pcrRegs)
+ {
+ l_pcrDigests[l_pcr].size = l_digestSize;
+ l_errl = TRUSTEDBOOT::pcrRead(l_primaryTpm,
+ l_pcr,
+ TRUSTEDBOOT::TPM_ALG_SHA256,
+ l_digestSize,
+ l_pcrDigests[l_pcr].buffer);
+ if(l_errl)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommGenSlaveResponseQuote: could not read PCR%d", l_pcr);
+ break;
+ }
+ }
+ if(l_errl)
+ {
+ break;
+ }
+
+ // Step 6: Read out the primary TPM's Log and copy it into the quote
+ TRUSTEDBOOT::TpmLogMgr* l_primaryLogMgr =
+ TRUSTEDBOOT::getTpmLogMgr(l_primaryTpm);
+ if(!l_primaryLogMgr)
+ {
+ TRACFCOMP(g_trac_nc,ERR_MRK"nodeCommGenSlaveResponseQuote: could not fetch primary TPM's log");
+ /*@
+ * @errortype
+ * @reasoncode RC_NC_NO_PRIMARY_TPM_LOG
+ * @moduleid MOD_NC_GEN_SLAVE_RESPONSE
+ * @userdata1 Primary TPM HUID
+ * @devdesc Could not fetch primary TPM's Log
+ * @custdes Trustedboot failure
+ */
+ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_NC_GEN_SLAVE_RESPONSE,
+ RC_NC_NO_PRIMARY_TPM_LOG,
+ get_huid(l_primaryTpm));
+ l_errl->collectTrace(NODECOMM_TRACE_NAME);
+ l_errl->collectTrace(SECURE_COMP_NAME);
+ l_errl->collectTrace(TRBOOT_COMP_NAME);
+ break;
+ }
+ uint32_t l_logSize = TRUSTEDBOOT::TpmLogMgr_getLogSize(l_primaryLogMgr);
+ const uint8_t* l_logPtr =
+ TRUSTEDBOOT::TpmLogMgr_getLogStartPtr(l_primaryLogMgr);
+
+ SECUREBOOT::NODECOMM::NCEyeCatcher_t l_goodEyeCatch =
+ SECUREBOOT::NODECOMM::NODEQUOT;
+
+ // Figure out the size of the slave quote
+ o_size = sizeof(l_goodEyeCatch) +
+ sizeof(l_nodeId) +
+ l_quoteData.size +
+ sizeof(l_pcrCount) +
+ sizeof(l_pcrDigests) +
+ sizeof(l_AKCert) +
+ sizeof(l_logSize) +
+ l_logSize;
+
+ // Allocate the output
+ o_resp = new uint8_t[o_size] {};
+ // Now populate the output
+ size_t l_currentOffset = 0;
+
+ // First the good eye catcher
+ memcpy(o_resp, &l_goodEyeCatch, sizeof(l_goodEyeCatch));
+ l_currentOffset += sizeof(l_goodEyeCatch);
+ // Now the node ID
+ memcpy(o_resp + l_currentOffset, &l_nodeId, sizeof(l_nodeId));
+ l_currentOffset += sizeof(l_nodeId);
+ // The TPM quote & signature information (both are included in the TPM
+ // quote blob)
+ memcpy(o_resp + l_currentOffset, l_quoteData.data, l_quoteData.size);
+ l_currentOffset += l_quoteData.size;
+ // The number of PCRs read
+ memcpy(o_resp + l_currentOffset, &l_pcrCount, sizeof(l_pcrCount));
+ l_currentOffset += sizeof(l_pcrCount);
+ // PCR0-7 contents
+ memcpy(o_resp + l_currentOffset,
+ reinterpret_cast<uint8_t*>(&l_pcrDigests),
+ sizeof(l_pcrDigests));
+ l_currentOffset += sizeof(l_pcrDigests);
+ // AK certificate size
+ memcpy(o_resp + l_currentOffset, &l_AKCert.size, sizeof(l_AKCert.size));
+ l_currentOffset += sizeof(l_AKCert.size);
+ // Actual AK certificate
+ memcpy(o_resp + l_currentOffset, l_AKCert.buffer, sizeof(l_AKCert.buffer));
+ l_currentOffset += sizeof(l_AKCert.buffer);
+ // The length of the TPM log
+ memcpy(o_resp + l_currentOffset, &l_logSize, sizeof(l_logSize));
+ l_currentOffset += sizeof(l_logSize);
+ // The actual TPM log
+ memcpy(o_resp + l_currentOffset, l_logPtr, l_logSize);
+
+ } while(0);
+
+ if(l_quoteData.data)
+ {
+ delete[](l_quoteData.data);
+ l_quoteData.data = nullptr;
+ }
+
+ if(l_errl || l_errorOccurred)
+ {
+ // There was some error; allocate the output buffer just big enough
+ // for an eye catcher and node ID
+ SECUREBOOT::NODECOMM::NCEyeCatcher_t l_badEyeCatcher =
+ SECUREBOOT::NODECOMM::NDNOTPM_;
+ o_resp = new uint8_t[sizeof(l_badEyeCatcher) + sizeof(l_nodeId)]{};
+ memcpy(o_resp, &l_badEyeCatcher, sizeof(l_badEyeCatcher));
+ memcpy(o_resp + sizeof(l_badEyeCatcher), &l_nodeId, sizeof(l_nodeId));
+ o_size = sizeof(l_badEyeCatcher) + sizeof(l_nodeId);
+
+ errlHndl_t l_poisonTpmErr = TRUSTEDBOOT::poisonAllTpms();
+ if(l_poisonTpmErr)
+ {
+ if(l_errl)
+ {
+ l_poisonTpmErr->plid(l_errl->plid());
+ }
+ errlCommit(l_poisonTpmErr, SECURE_COMP_ID);
+ }
+ }
+
+ if(l_errl)
+ {
+ if(!l_tpmRequired)
+ {
+ // TPM is not required, so no need to propagate the error up and
+ // fail the boot.
+ errlCommit(l_errl, SECURE_COMP_ID);
+ }
+ }
+
+ TRACFCOMP(g_trac_nc, EXIT_MRK"nodeCommGenSlaveResponseQuote: " TRACE_ERR_FMT, TRACE_ERR_ARGS(l_errl));
+#endif
+ return l_errl;
+} //nodeCommGenSlaveResponseQuote
/**
* @brief This function runs the procedure for the master processor on the
diff --git a/src/usr/secureboot/trusted/base/trustedbootMsg.H b/src/usr/secureboot/trusted/base/trustedbootMsg.H
index 9789c4fed..929233111 100644
--- a/src/usr/secureboot/trusted/base/trustedbootMsg.H
+++ b/src/usr/secureboot/trusted/base/trustedbootMsg.H
@@ -62,7 +62,8 @@ namespace TRUSTEDBOOT
MSG_TYPE_READ_AK_CERT,
MSG_TYPE_GEN_QUOTE,
MSG_TYPE_FLUSH_CONTEXT,
- MSG_TYPE_LAST = MSG_TYPE_FLUSH_CONTEXT,
+ MSG_TYPE_PCR_READ,
+ MSG_TYPE_LAST = MSG_TYPE_PCR_READ,
};
/// PCREXTEND message data
@@ -103,8 +104,8 @@ namespace TRUSTEDBOOT
struct ReadAKCertData
{
TpmTarget* tpm;
- AKCertificate_t* data; // The output of NVRAM read
- ReadAKCertData(TpmTarget* i_tpm, AKCertificate_t* i_data) :
+ TPM2B_MAX_NV_BUFFER* data; // The output of NVRAM read
+ ReadAKCertData(TpmTarget* i_tpm, TPM2B_MAX_NV_BUFFER* i_data) :
tpm(i_tpm), data(i_data)
{
}
@@ -114,10 +115,10 @@ namespace TRUSTEDBOOT
struct GenQuoteData
{
TpmTarget* tpm;
- MasterTpmNonce_t* masterNonce; // 32-byte nonce value
+ const MasterTpmNonce_t* const masterNonce; // 32-byte nonce value
QuoteDataOut* data; // Output - the quote and signature fields
GenQuoteData(TpmTarget* i_tpm,
- MasterTpmNonce_t* i_masterNonce,
+ const MasterTpmNonce_t* const i_masterNonce,
QuoteDataOut* o_data) :
tpm(i_tpm),
masterNonce(i_masterNonce),
@@ -126,6 +127,28 @@ namespace TRUSTEDBOOT
}
};
+ // The struct used to read a PCR from TPM
+ struct PcrReadData
+ {
+ TpmTarget* tpm; // TPM target whose PCRs are to be read
+ TPM_Pcr pcr; // The PCR to read
+ TPM_Alg_Id alg; // The PCR bank to read
+ uint8_t* digest; // The buffer to hold the PCR contents
+ size_t digestSize; // The size of the digest buffer
+ PcrReadData(TpmTarget* i_tpm,
+ TPM_Pcr i_pcr,
+ TPM_Alg_Id i_alg,
+ uint8_t* o_digest,
+ size_t i_digestSize) :
+ tpm(i_tpm),
+ pcr(i_pcr),
+ alg(i_alg),
+ digest(o_digest),
+ digestSize(i_digestSize)
+ {
+ }
+ };
+
// Trustedboot message class
class Message
{
diff --git a/src/usr/secureboot/trusted/base/trustedboot_base.C b/src/usr/secureboot/trusted/base/trustedboot_base.C
index 5c68e3c2f..e0170b164 100644
--- a/src/usr/secureboot/trusted/base/trustedboot_base.C
+++ b/src/usr/secureboot/trusted/base/trustedboot_base.C
@@ -902,7 +902,7 @@ errlHndl_t createAttestationKeys(TpmTarget* i_target)
return l_errl;
}
-errlHndl_t readAKCertificate(TpmTarget* i_target, AKCertificate_t* o_data)
+errlHndl_t readAKCertificate(TpmTarget* i_target, TPM2B_MAX_NV_BUFFER* o_data)
{
errlHndl_t l_errl = nullptr;
#ifdef CONFIG_TPMDD
@@ -955,7 +955,7 @@ errlHndl_t readAKCertificate(TpmTarget* i_target, AKCertificate_t* o_data)
}
errlHndl_t generateQuote(TpmTarget* i_target,
- MasterTpmNonce_t* i_masterNonce,
+ const MasterTpmNonce_t* const i_masterNonce,
QuoteDataOut* o_data)
{
errlHndl_t l_errl = nullptr;
@@ -1060,4 +1060,64 @@ errlHndl_t flushContext(TpmTarget* i_target)
return l_errl;
}
+errlHndl_t pcrRead(TpmTarget* i_target,
+ const TPM_Pcr i_pcr,
+ const TPM_Alg_Id i_algId,
+ const size_t i_digestSize,
+ uint8_t* const o_digest)
+{
+ errlHndl_t l_errl = nullptr;
+#ifdef CONFIG_TPMDD
+ Message* l_msg = nullptr;
+
+ PcrReadData* l_data = new PcrReadData{i_target,
+ i_pcr,
+ i_algId,
+ o_digest,
+ i_digestSize};
+
+ l_msg = Message::factory(MSG_TYPE_PCR_READ,
+ sizeof(*l_data),
+ reinterpret_cast<uint8_t*>(l_data),
+ MSG_MODE_SYNC);
+ assert(l_msg != nullptr, "pcrRead: l_msg is nullptr");
+ l_data = nullptr; //l_msg now owns l_data
+
+ int l_rc = msg_sendrecv(systemData.msgQ, l_msg->iv_msg);
+ if(l_rc)
+ {
+ /*@
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_PCR_READ
+ * @reasoncode RC_SENDRECV_FAIL
+ * @userdata1 rc from msg_sendrecv
+ * @userdata2 TPM HUID
+ * @devdesc msg_sendrecv failed for pcrRead
+ * @custdesc trustedboot failure
+ */
+ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_PCR_READ,
+ RC_SENDRECV_FAIL,
+ l_rc,
+ TARGETING::get_huid(i_target),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ l_errl->collectTrace(SECURE_COMP_NAME);
+ l_errl->collectTrace(TRBOOT_COMP_NAME);
+ }
+ else
+ {
+ l_errl = l_msg->iv_errl;
+ l_msg->iv_errl = nullptr;
+ }
+
+ if(l_msg)
+ {
+ delete l_msg;
+ l_msg = nullptr;
+ }
+
+#endif
+ return l_errl;
+}
+
} // end TRUSTEDBOOT
diff --git a/src/usr/secureboot/trusted/trustedTypes.C b/src/usr/secureboot/trusted/trustedTypes.C
index fe8112151..f78b7411a 100644
--- a/src/usr/secureboot/trusted/trustedTypes.C
+++ b/src/usr/secureboot/trusted/trustedTypes.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -378,7 +378,7 @@ namespace TRUSTEDBOOT
sizeof(TPMU_HA) < val->size)
{
TRACUCOMP( g_trac_trustedboot,
- "TPM2B_DIGEST::unmarshal invalid size");
+ "TPM2B_DIGEST::unmarshal invalid size (%d)", val->size);
return NULL;
}
i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
@@ -393,7 +393,7 @@ namespace TRUSTEDBOOT
{
i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
&(val->count), sizeof(val->count));
- if (NULL != i_tpmBuf && HASH_COUNT < val->count)
+ if (NULL != i_tpmBuf && FW_USED_PCR_COUNT < val->count)
{
TRACUCOMP( g_trac_trustedboot,
"TPML_DIGEST::unmarshal invalid count %d", val->count);
diff --git a/src/usr/secureboot/trusted/trustedTypes.H b/src/usr/secureboot/trusted/trustedTypes.H
index 7efa1d901..ae3f3e233 100644
--- a/src/usr/secureboot/trusted/trustedTypes.H
+++ b/src/usr/secureboot/trusted/trustedTypes.H
@@ -59,14 +59,6 @@ namespace TRUSTEDBOOT
MAX_TRANSMIT_SIZE = 1024, ///< Maximum send/receive transmit size
};
- /// TPM Algorithm defines
- typedef enum
- {
- TPM_ALG_SHA1 = 0x0004, ///< SHA1 Id
- TPM_ALG_SHA256 = 0x000B, ///< SHA256 Id
- TPM_ALG_INVALID_ID ///< Used for error checking
- } TPM_Alg_Id;
-
typedef enum
{
TPM_ALG_SHA1_SIZE = 20, ///< SHA1 digest byte size
@@ -164,6 +156,39 @@ namespace TRUSTEDBOOT
// Command structures taken from Trusted Platform Module Library Part 3:
// Commands Family "2.0"
+ /* TPM data structures naming conventions
+ (taken from the TCG TPM spec v2)
+
+ _TPM_ an indication/signal from the TPM’s system interface
+ TPM_ a constant or an enumerated type
+ TPM2_ a command defined by this specification
+ TPM2B_ a structure that is a sized buffer where the size of the buffer is
+ contained in a 16-bit, unsigned value. The first parameter is the
+ size in octets of the second parameter. The second parameter may be
+ any type.
+ TPMA_ a structure where each of the fields defines an attribute and each
+ field is usually a single bit. All the attributes in an attribute
+ structure are packed with the overall size of the structure
+ indicated in the heading of the attribute description
+ (UINT8, UINT16, or UINT32).
+ TPM_ALG_ an enumerated type that indicates an algorithm
+ A TPM_ALG_ is often used as a selector for a union.
+ TPMI_ an interface type. The value is specified for purposes of dynamic
+ type checking when unmarshaled.
+ TPML_ a list length followed by the indicated number of entries of the
+ indicated type. This is an array with a length field.
+ TPMS_ a structure that is not a size buffer or a tagged buffer or a
+ list
+ TPMT_ a structure with the first parameter being a structure tag,
+ indicating the type of the structure that follows. A structure tag
+ may be either a TPMT_ST_ or TPM_ALG_ depending on context.
+ TPMU_ a union of structures, lists, or unions. If a union exists, there
+ will normally be a companion TPMT_ that is the expression of the
+ union in a tagged structure, where the tag is the selector
+ indicating which member of the union is present.
+ */
+
+
/// TPM capability response structure
struct _TPMS_TAGGED_PROPERTY
{
@@ -419,8 +444,9 @@ namespace TRUSTEDBOOT
struct _TPM2B_DIGEST
{
- uint16_t size;
- uint8_t buffer[sizeof(TPMU_HA)];
+ uint16_t size; // size in octets of the buffer field; may be 0
+ uint8_t buffer[sizeof(TPMU_HA)]; // the buffer area that can be no
+ // larger than a digest
} PACKED;
typedef struct _TPM2B_DIGEST TPM2B_DIGEST;
const uint8_t* TPM2B_DIGEST_unmarshal(TPM2B_DIGEST* val,
@@ -439,8 +465,9 @@ namespace TRUSTEDBOOT
struct _TPML_PCR_SELECTION
{
- uint32_t count;
- TPMS_PCR_SELECTION pcrSelections[HASH_COUNT];
+ uint32_t count; //number of selection structures;
+ // a value of zero is allowed.
+ TPMS_PCR_SELECTION pcrSelections[HASH_COUNT]; // list of selections
} PACKED;
typedef struct _TPML_PCR_SELECTION TPML_PCR_SELECTION;
uint8_t* TPML_PCR_SELECTION_marshal(const TPML_PCR_SELECTION* val,
@@ -541,7 +568,7 @@ namespace TRUSTEDBOOT
struct _TPM2_NVReadOut
{
TPM2_BaseOut base;
- uint8_t NVData[TPM_NV_DATA_SIZE];
+ TPM2B_MAX_NV_BUFFER data;
} PACKED;
typedef struct _TPM2_NVReadOut TPM2_NVReadOut;
diff --git a/src/usr/secureboot/trusted/trustedboot.C b/src/usr/secureboot/trusted/trustedboot.C
index 1f5e159a2..28521dc7b 100644
--- a/src/usr/secureboot/trusted/trustedboot.C
+++ b/src/usr/secureboot/trusted/trustedboot.C
@@ -1501,7 +1501,7 @@ errlHndl_t doCreateAttKeys(TpmTarget* i_tpm)
return l_errl;
}
-errlHndl_t doReadAKCert(TpmTarget* i_tpm, AKCertificate_t* o_data)
+errlHndl_t doReadAKCert(TpmTarget* i_tpm, TPM2B_MAX_NV_BUFFER* o_data)
{
errlHndl_t l_errl = nullptr;
@@ -1523,7 +1523,7 @@ errlHndl_t doReadAKCert(TpmTarget* i_tpm, AKCertificate_t* o_data)
}
errlHndl_t doGenQuote(TpmTarget* i_tpm,
- MasterTpmNonce_t* i_masterNonce,
+ const MasterTpmNonce_t* const i_masterNonce,
QuoteDataOut* o_data)
{
errlHndl_t l_errl = nullptr;
@@ -1566,6 +1566,35 @@ errlHndl_t doFlushContext(TpmTarget* i_tpm)
return l_errl;
}
+errlHndl_t doPcrRead(TpmTarget* i_target,
+ const TPM_Pcr i_pcr,
+ const TPM_Alg_Id i_algId,
+ const size_t i_digestSize,
+ uint8_t* const o_digest)
+{
+ errlHndl_t l_errl = nullptr;
+
+ do {
+ l_errl = validateTpmHandle(i_target);
+ if(l_errl)
+ {
+ break;
+ }
+
+ l_errl = tpmCmdPcrRead(i_target,
+ i_pcr,
+ i_algId,
+ o_digest,
+ i_digestSize);
+ if(l_errl)
+ {
+ break;
+ }
+
+ } while(0);
+ return l_errl;
+}
+
void* tpmDaemon(void* unused)
{
bool shutdownPending = false;
@@ -1815,6 +1844,19 @@ void* tpmDaemon(void* unused)
}
break;
+ case TRUSTEDBOOT::MSG_TYPE_PCR_READ:
+ {
+ tb_msg = static_cast<TRUSTEDBOOT::Message*>(msg->extra_data);
+ PcrReadData* l_data =
+ reinterpret_cast<PcrReadData*>(tb_msg->iv_data);
+ tb_msg->iv_errl = doPcrRead(l_data->tpm,
+ l_data->pcr,
+ l_data->alg,
+ l_data->digestSize,
+ l_data->digest);
+ }
+ break;
+
default:
assert(false, "Invalid msg command");
break;
@@ -2219,4 +2261,26 @@ errlHndl_t poisonTpm(const TpmTarget* i_pTpm)
return l_errl;
}
+errlHndl_t poisonAllTpms()
+{
+ errlHndl_t l_errl = nullptr;
+#ifdef CONFIG_TPMDD
+ do {
+
+ TARGETING::TargetHandleList l_tpms;
+ getTPMs(l_tpms, TRUSTEDBOOT::TPM_FILTER::ALL_FUNCTIONAL);
+ for(auto l_tpm : l_tpms)
+ {
+ l_errl = poisonTpm(l_tpm);
+ if(l_errl)
+ {
+ break;
+ }
+ }
+
+ } while(0);
+#endif
+ return l_errl;
+}
+
} // end TRUSTEDBOOT
diff --git a/src/usr/secureboot/trusted/trustedboot.H b/src/usr/secureboot/trusted/trustedboot.H
index 155bbf696..53ddb40fc 100644
--- a/src/usr/secureboot/trusted/trustedboot.H
+++ b/src/usr/secureboot/trusted/trustedboot.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2018 */
+/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -46,7 +46,7 @@ extern trace_desc_t* g_trac_trustedboot;
// Easy macro replace for unit testing
//#define TRACUCOMP(args...) TRACFCOMP(args)
-#define TRACUCOMP(args...)
+#define TRACUCOMP(args...) TRACDCOMP(args)
//#define TRACUBIN(args...) TRACFBIN(args)
#define TRACUBIN(args...)
diff --git a/src/usr/secureboot/trusted/trustedbootCmds.C b/src/usr/secureboot/trusted/trustedbootCmds.C
index 1aeb387f9..c989de719 100644
--- a/src/usr/secureboot/trusted/trustedbootCmds.C
+++ b/src/usr/secureboot/trusted/trustedbootCmds.C
@@ -411,9 +411,9 @@ errlHndl_t tpmUnmarshalResponseData(uint32_t i_commandCode,
reinterpret_cast<TPM2_NVReadOut*>(o_outBuf);
TPM2_NVReadOut* l_tpmRespData =
reinterpret_cast<TPM2_NVReadOut*>(i_respBuf);
- memcpy(l_tpmRespData->NVData,
- l_respPtr->NVData,
- TPM_NV_DATA_SIZE);
+ memcpy(reinterpret_cast<uint8_t*>(&l_tpmRespData->data),
+ reinterpret_cast<uint8_t*>(&l_respPtr->data),
+ sizeof(l_tpmRespData->data));
}
break;
@@ -1346,7 +1346,7 @@ errlHndl_t tpmCmdCreateAttestationKeys(TpmTarget* i_target)
return l_errl;
}
-errlHndl_t tpmCmdReadAKCertificate(TpmTarget* i_target, AKCertificate_t* o_data)
+errlHndl_t tpmCmdReadAKCertificate(TpmTarget* i_target, TPM2B_MAX_NV_BUFFER* o_data)
{
TRACFCOMP(g_trac_trustedboot, ENTER_MRK"tpmCmdReadAKCertificate()");
errlHndl_t l_errl = nullptr;
@@ -1413,8 +1413,10 @@ errlHndl_t tpmCmdReadAKCertificate(TpmTarget* i_target, AKCertificate_t* o_data)
}
TPM2_NVReadOut* l_read = reinterpret_cast<TPM2_NVReadOut*>(l_resp);
- // NVRAM holds the AK certificate. Copy out a fixed size of 500 bytes
- memcpy(*o_data, l_read->NVData, TPM_NV_DATA_SIZE);
+ // NVRAM holds the AK certificate. Copy out the size and the certificate
+ memcpy(reinterpret_cast<uint8_t*>(o_data),
+ reinterpret_cast<uint8_t*>(&l_read->data),
+ sizeof(*o_data));
}while(0);
@@ -1423,7 +1425,7 @@ errlHndl_t tpmCmdReadAKCertificate(TpmTarget* i_target, AKCertificate_t* o_data)
}
errlHndl_t tpmCmdGenerateQuote(TpmTarget* i_target,
- MasterTpmNonce_t* i_masterNonce,
+ const MasterTpmNonce_t* const i_masterNonce,
QuoteDataOut* o_data)
{
TRACFCOMP(g_trac_trustedboot, ENTER_MRK"tpmCmdGenerateQuote()");
@@ -1457,9 +1459,12 @@ errlHndl_t tpmCmdGenerateQuote(TpmTarget* i_target,
l_cmd->quoteData.pcrSelection.pcrSelections[0].algorithmId = TPM_ALG_SHA256;
l_cmd->quoteData.pcrSelection.pcrSelections[0].sizeOfSelect =PCR_SELECT_MAX;
- for(size_t i = PCR_0; i <= PCR_7 ; ++i)
+ memset(l_cmd->quoteData.pcrSelection.pcrSelections[0].pcrSelect, 0,
+ sizeof(l_cmd->quoteData.pcrSelection.pcrSelections[0].pcrSelect));
+
+ for(size_t i = PCR_0; i <= FW_USED_PCR_COUNT; ++i)
{
- l_cmd->quoteData.pcrSelection.pcrSelections[0].pcrSelect[i/8] =
+ l_cmd->quoteData.pcrSelection.pcrSelections[0].pcrSelect[i/8] |=
0x01 << (i % 8);
}
diff --git a/src/usr/secureboot/trusted/trustedbootCmds.H b/src/usr/secureboot/trusted/trustedbootCmds.H
index 9b0e99aaa..571b5224c 100644
--- a/src/usr/secureboot/trusted/trustedbootCmds.H
+++ b/src/usr/secureboot/trusted/trustedbootCmds.H
@@ -175,7 +175,6 @@ errlHndl_t tpmCmdPcrRead(TpmTarget* io_target,
uint8_t* o_digest,
size_t i_digestSize);
-
/**
* @brief Send the TPM_CC_Create to the TPM
* @param[in] i_target the target TPM (must not be nullptr)
@@ -192,7 +191,7 @@ errlHndl_t tpmCmdCreateAttestationKeys(TpmTarget* i_target);
* @return nullptr on success; non-nullptr on error
*/
errlHndl_t tpmCmdReadAKCertificate(TpmTarget* i_target,
- AKCertificate_t* o_data);
+ TPM2B_MAX_NV_BUFFER* o_data);
/**
* @brief Send the TPM_CC_Quote command to the given TPM to generate quote
@@ -204,7 +203,7 @@ errlHndl_t tpmCmdReadAKCertificate(TpmTarget* i_target,
* @return nullptr on success; non-nullptr on error
*/
errlHndl_t tpmCmdGenerateQuote(TpmTarget* i_target,
- MasterTpmNonce_t* i_masterNonce,
+ const MasterTpmNonce_t* i_masterNonce,
QuoteDataOut* o_data);
/**
OpenPOWER on IntegriCloud