summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaymes Wilks <mjwilks@us.ibm.com>2018-04-24 10:01:59 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-05-10 21:49:40 -0400
commit98bee5bbab00b1fcb8c6b6255ac07e62e2800b60 (patch)
tree35359cf4fc59989468425e54a9c8b8a510ff87e6
parent7145f5c28a5b4a8fe689d3250fa95acbdfc0c43f (diff)
downloadtalos-hostboot-98bee5bbab00b1fcb8c6b6255ac07e62e2800b60.tar.gz
talos-hostboot-98bee5bbab00b1fcb8c6b6255ac07e62e2800b60.zip
New API to Retrieve Random Number from the TPM
A new programming interface allows us to obtain random numbers from the TPM more easily (i.e. in a more high-level way). Change-Id: Ibd3d3b320411bea146d6eab4d1a59ca760bc726c RTC:191000 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/57802 Reviewed-by: ILYA SMIRNOV <ismirno@us.ibm.com> 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> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
-rw-r--r--src/include/usr/secureboot/trustedboot_reasoncodes.H8
-rw-r--r--src/include/usr/secureboot/trustedbootif.H27
-rw-r--r--src/usr/secureboot/trusted/base/trustedbootMsg.H9
-rw-r--r--src/usr/secureboot/trusted/base/trustedboot_base.C73
-rwxr-xr-xsrc/usr/secureboot/trusted/test/trustedbootTest.H50
-rw-r--r--src/usr/secureboot/trusted/trustedTypes.H19
-rw-r--r--src/usr/secureboot/trusted/trustedboot.C137
-rw-r--r--src/usr/secureboot/trusted/trustedbootCmds.C18
8 files changed, 330 insertions, 11 deletions
diff --git a/src/include/usr/secureboot/trustedboot_reasoncodes.H b/src/include/usr/secureboot/trustedboot_reasoncodes.H
index 82647766a..0020ab20a 100644
--- a/src/include/usr/secureboot/trustedboot_reasoncodes.H
+++ b/src/include/usr/secureboot/trustedboot_reasoncodes.H
@@ -58,7 +58,6 @@ namespace TRUSTEDBOOT
MOD_TPM_SYNCRESPONSE = 0x0C,
MOD_TPM_SEPARATOR = 0x0D,
MOD_TPM_CMD_GETCAPNVINDEX = 0x0E,
-
MOD_TPMLOGMGR_INITIALIZE = 0x10,
MOD_TPMLOGMGR_ADDEVENT = 0x11,
MOD_TPMLOGMGR_INITIALIZEEXISTLOG = 0x12,
@@ -66,7 +65,9 @@ namespace TRUSTEDBOOT
MOD_TPM_MARK_FAILED = 0x14,
MOD_INIT_BACKUP_TPM = 0x15,
MOD_DO_INIT_BACKUP_TPM = 0x16,
- MOD_TEST_CMP_PRIMARY_AND_BACKUP_TPM = 0x17
+ MOD_TEST_CMP_PRIMARY_AND_BACKUP_TPM = 0x17,
+ MOD_TPM_GETRANDOM = 0x18,
+ MOD_VALIDATE_TPM_HANDLE = 0x19,
};
enum TRUSTEDReasonCode
@@ -97,6 +98,9 @@ namespace TRUSTEDBOOT
RC_TPM_NVINDEX_VALIDATE_FAIL = TRBOOT_COMP_ID | 0xB5,
RC_TPMLOGMGR_INITIALIZE_FAIL = TRBOOT_COMP_ID | 0xB6,
RC_BACKUP_TPM_TEST_FAIL = TRBOOT_COMP_ID | 0xB7,
+ RC_INVALID_TPM_HANDLE = TRBOOT_COMP_ID | 0xB8,
+ RC_NON_FUNCTIONAL_TPM_HANDLE = TRBOOT_COMP_ID | 0xB9,
+ RC_UNREACHABLE_TPM = TRBOOT_COMP_ID | 0xBA,
};
#ifdef __cplusplus
}
diff --git a/src/include/usr/secureboot/trustedbootif.H b/src/include/usr/secureboot/trustedbootif.H
index 5ab461cb1..f8af75fb5 100644
--- a/src/include/usr/secureboot/trustedbootif.H
+++ b/src/include/usr/secureboot/trustedbootif.H
@@ -41,6 +41,7 @@
#include <secureboot/containerheader.H>
#include <targeting/common/commontargeting.H>
#include <targeting/common/utilFilter.H>
+#include <config.h>
namespace TRUSTEDBOOT
{
@@ -233,6 +234,32 @@ namespace TRUSTEDBOOT
uint64_t i_xscomAddr,
uint32_t i_i2cMasterOffset);
+ #ifdef CONFIG_TPMDD
+ /**
+ * @brief Generate random numbers via TPM hardware.
+ *
+ * @parm[in] i_pTpm Pointer to TPM target. In order to succeed, it cannot
+ * be null and must be a TPM target pointer. The TPM target must
+ * be functional. All of these conditions must be met or an error
+ * log will result.
+ *
+ * @parm[out] o_randNum A uint64_t reference to be filled with random bits.
+ *
+ * @return errlHndl_t nullptr on success or an error log pointer on failure
+ */
+ errlHndl_t GetRandom(const TpmTarget* i_pTpm, uint64_t& o_randNum);
+ #endif
+
+ /**
+ * @brief Helper function for validating TPM handles. Returns an error log
+ * if the supplied TPM is null, not a TPM target, or not functional.
+ *
+ * @parm[in] i_pTpm Pointer to the TPM target to be checked.
+ *
+ * @return errlHndl_t nullptr if valid or error log otherwise.
+ */
+ errlHndl_t validateTpmHandle(const TpmTarget* i_pTpm);
+
/**
* @brief Checks whether the node has a present and functioning primary TPM.
* @retval true if a present and functional primary TPM is available;
diff --git a/src/usr/secureboot/trusted/base/trustedbootMsg.H b/src/usr/secureboot/trusted/base/trustedbootMsg.H
index 45821f9f4..260fe094a 100644
--- a/src/usr/secureboot/trusted/base/trustedbootMsg.H
+++ b/src/usr/secureboot/trusted/base/trustedbootMsg.H
@@ -55,7 +55,8 @@ namespace TRUSTEDBOOT
MSG_TYPE_SEPARATOR,
MSG_TYPE_SHUTDOWN,
MSG_TYPE_INIT_BACKUP_TPM,
- MSG_TYPE_LAST = MSG_TYPE_INIT_BACKUP_TPM
+ MSG_TYPE_GETRANDOM,
+ MSG_TYPE_LAST = MSG_TYPE_GETRANDOM,
};
/// PCREXTEND message data
@@ -69,6 +70,12 @@ namespace TRUSTEDBOOT
char mLogMsg[MAX_TPM_LOG_MSG];
};
+ struct GetRandomMsgData
+ {
+ TARGETING::Target* i_pTpm; // the TPM to obtain random data from
+ uint64_t o_randNum; // the random data is populated here
+ };
+
// 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 c4929faef..9aba765f5 100644
--- a/src/usr/secureboot/trusted/base/trustedboot_base.C
+++ b/src/usr/secureboot/trusted/base/trustedboot_base.C
@@ -794,4 +794,77 @@ errlHndl_t testCmpPrimaryAndBackupTpm()
return l_err;
}
+#ifdef CONFIG_TPMDD
+errlHndl_t GetRandom(const TpmTarget* i_pTpm, uint64_t& o_randNum)
+{
+ errlHndl_t err = nullptr;
+ Message* msg = nullptr;
+
+ do {
+
+ auto pData = new struct GetRandomMsgData;
+ memset(pData, 0, sizeof(*pData));
+
+ pData->i_pTpm = const_cast<TpmTarget*>(i_pTpm);
+
+ msg = Message::factory(MSG_TYPE_GETRANDOM, sizeof(*pData),
+ reinterpret_cast<uint8_t*>(pData), MSG_MODE_SYNC);
+
+ assert(msg != nullptr, "BUG! Message is null");
+ pData = nullptr; // Message owns msgData now
+
+ int rc = msg_sendrecv(systemData.msgQ, msg->iv_msg);
+ if (0 == rc)
+ {
+ err = msg->iv_errl;
+ msg->iv_errl = nullptr; // taking over ownership of error log
+ if (err != nullptr)
+ {
+ break;
+ }
+ }
+ else // sendrecv failure
+ {
+ /*@
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_GETRANDOM
+ * @reasoncode RC_SENDRECV_FAIL
+ * @userdata1 rc from msq_sendrecv()
+ * @userdata2 TPM HUID if it's not nullptr
+ * @devdesc msg_sendrecv() failed
+ * @custdesc Trusted boot failure
+ */
+ err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_TPM_GETRANDOM,
+ RC_SENDRECV_FAIL,
+ rc,
+ TARGETING::get_huid(i_pTpm),
+ true);
+ break;
+ }
+
+ pData = reinterpret_cast<struct GetRandomMsgData*>(msg->iv_data);
+ assert(pData != nullptr,
+ "BUG! Completed send/recv to random num generator has null data ptr!");
+
+ o_randNum = pData->o_randNum;
+
+ } while (0);
+
+ if (msg != nullptr)
+ {
+ delete msg; // also deletes the msg->iv_data
+ msg = nullptr;
+ }
+
+ if (err)
+ {
+ err->collectTrace(SECURE_COMP_NAME);
+ err->collectTrace(TRBOOT_COMP_NAME);
+ }
+
+ return err;
+}
+#endif // CONFIG_TPMDD
+
} // end TRUSTEDBOOT
diff --git a/src/usr/secureboot/trusted/test/trustedbootTest.H b/src/usr/secureboot/trusted/test/trustedbootTest.H
index 0a8e181ca..0d293f41a 100755
--- a/src/usr/secureboot/trusted/test/trustedbootTest.H
+++ b/src/usr/secureboot/trusted/test/trustedbootTest.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* Contributors Listed Below - COPYRIGHT 2015,2018 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -45,6 +45,7 @@
#include "../trustedboot.H"
#include "../trustedbootCmds.H"
#include "../tpmLogMgr.H"
+#include <config.h>
using namespace TRUSTEDBOOT;
@@ -885,6 +886,53 @@ class TrustedBootTest: public CxxTest::TestSuite
EXIT_MRK "testReadPCR: %d/%d fails",
fails, num_ops );
}
+
+ /**
+ * @brief TPM GetRandom
+ */
+ void testGetRandom ( void )
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ ENTER_MRK "testGetRandom" );
+
+ errlHndl_t err = nullptr;
+ size_t fails = 0;
+ size_t num_ops = 0;
+
+ // Just for fun generate random numbers for each of the TPMs
+ TARGETING::TargetHandleList tpmList;
+ TRUSTEDBOOT::getTPMs(tpmList, TRUSTEDBOOT::TPM_FILTER::ALL_FUNCTIONAL);
+ for (auto pTpm: tpmList)
+ {
+ uint64_t randNum = 0;
+ err = TRUSTEDBOOT::GetRandom(pTpm, randNum);
+ num_ops ++;
+ if(err)
+ {
+ fails++;
+ TS_FAIL( "testGetRandom: Error detected" );
+ errlCommit( err,
+ TRBOOT_COMP_ID );
+ delete err;
+ err = nullptr;
+ }
+ else if (randNum == 0) // if random number is zero still
+ {
+ fails++;
+ TS_FAIL( "testGetRandom: got zero for a random number");
+ }
+ else
+ {
+
+ TRACUCOMP(g_trac_trustedboot, "testGetRandom: GetRandom returned as expected. Random number 0x%.16llX",randNum);
+ }
+
+ }
+
+ TRACFCOMP( g_trac_trustedboot,
+ EXIT_MRK "testGetRandom: %d/%d fails",
+ fails, num_ops );
+ }
};
#endif
diff --git a/src/usr/secureboot/trusted/trustedTypes.H b/src/usr/secureboot/trusted/trustedTypes.H
index 0798295c5..34fc0fff5 100644
--- a/src/usr/secureboot/trusted/trustedTypes.H
+++ b/src/usr/secureboot/trusted/trustedTypes.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* Contributors Listed Below - COPYRIGHT 2015,2018 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -105,6 +105,7 @@ namespace TRUSTEDBOOT
// Command Codes
TPM_CC_Startup = 0x00000144,
TPM_CC_GetCapability = 0x0000017A,
+ TPM_CC_GetRandom = 0x0000017B,
TPM_CC_PCR_Read = 0x0000017E,
TPM_CC_PCR_Extend = 0x00000182,
@@ -453,6 +454,22 @@ namespace TRUSTEDBOOT
size_t* io_tpmBufSize,
size_t i_outBufSize);
+ /// Incoming GetRandom structure
+ struct _TPM2_GetRandomIn
+ {
+ TPM2_BaseIn base;
+ uint16_t bytesRequested;
+ } PACKED;
+ typedef struct _TPM2_GetRandomIn TPM2_GetRandomIn;
+
+ /// Outgoing GetRandom structure
+ struct _TPM2_GetRandomOut
+ {
+ TPM2_BaseOut base;
+ TPM2B_DIGEST randomBytes;
+ } PACKED;
+ typedef struct _TPM2_GetRandomOut TPM2_GetRandomOut;
+
/// TPM Authorization structure
/// This is not the full structure and only works for PW auth with NULL PW
struct _TPMS_AUTH_COMMAND
diff --git a/src/usr/secureboot/trusted/trustedboot.C b/src/usr/secureboot/trusted/trustedboot.C
index 00935f68a..de4222e41 100644
--- a/src/usr/secureboot/trusted/trustedboot.C
+++ b/src/usr/secureboot/trusted/trustedboot.C
@@ -1471,11 +1471,79 @@ void* tpmDaemon(void* unused)
NoTpmShutdownPolicy::BACKGROUND_SHUTDOWN);
}
break;
- case TRUSTEDBOOT::MSG_TYPE_INIT_BACKUP_TPM:
- {
- doInitBackupTpm();
- }
- break;
+ case TRUSTEDBOOT::MSG_TYPE_INIT_BACKUP_TPM:
+ {
+ doInitBackupTpm();
+ }
+ break;
+ case TRUSTEDBOOT::MSG_TYPE_GETRANDOM:
+ {
+ errlHndl_t err = nullptr;
+ tb_msg = static_cast<TRUSTEDBOOT::Message*>(msg->extra_data);
+ assert(tb_msg != nullptr,
+ "Trusted boot message pointer absent in the extra data");
+ tb_msg->iv_errl = nullptr;
+
+ auto msgData =
+ reinterpret_cast<struct GetRandomMsgData*>
+ (tb_msg->iv_data);
+ assert(msgData != nullptr,
+ "Trusted boot message data pointer is null");
+ auto l_pTpm = msgData->i_pTpm;
+
+ err = validateTpmHandle(l_pTpm);
+ if (err)
+ {
+ tb_msg->iv_errl = err;
+ err = nullptr;
+ break;
+ }
+ uint8_t dataBuf[sizeof(TPM2_GetRandomOut)] = {0};
+ size_t dataSize = sizeof(dataBuf);
+ auto cmd = reinterpret_cast<TPM2_GetRandomIn*>(dataBuf);
+ auto resp = reinterpret_cast<TPM2_GetRandomOut*>(dataBuf);
+ uint64_t randNum = 0;
+
+ cmd->base.tag = TPM_ST_NO_SESSIONS;
+ cmd->base.commandCode = TPM_CC_GetRandom;
+ cmd->bytesRequested = sizeof(randNum);
+
+ err = tpmTransmitCommand(l_pTpm, dataBuf, dataSize,
+ TPM_LOCALITY_0);
+
+ if (err != nullptr)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ ERR_MRK"TPM GetRandom Transmit Fail! huid = 0x%08X",
+ TARGETING::get_huid(l_pTpm));
+ auto l_errPlid = err->plid();
+ tpmMarkFailed(l_pTpm, err);
+ /*@
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_TPMDAEMON
+ * @reasoncode RC_UNREACHABLE_TPM
+ * @userdata1 TPM HUID or nullptr
+ * @devdesc Unable to reach the TPM
+ * @custdesc Trusted boot failure
+ */
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_TPM_TPMDAEMON,
+ RC_UNREACHABLE_TPM,
+ TARGETING::get_huid(l_pTpm),
+ 0,
+ true);
+ err->plid(l_errPlid);
+ tb_msg->iv_errl = err;
+ err = nullptr;
+ }
+ else
+ {
+ memcpy(&randNum, resp->randomBytes.buffer,sizeof(randNum));
+ msgData->o_randNum = randNum;
+ }
+ }
+ break;
default:
assert(false, "Invalid msg command");
break;
@@ -1529,6 +1597,65 @@ void* tpmDaemon(void* unused)
return nullptr;
}
+errlHndl_t validateTpmHandle(const TpmTarget* i_pTpm)
+{
+ errlHndl_t err = nullptr;
+
+ do {
+
+ if (i_pTpm == nullptr ||
+ i_pTpm->getAttr<TARGETING::ATTR_TYPE>() != TARGETING::TYPE_TPM)
+ {
+ TRACFCOMP(g_trac_trustedboot,
+ ERR_MRK"Invalid TPM handle passed to GetRandom() huid = 0x%08X",
+ TARGETING::get_huid(i_pTpm));
+ /*@
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_VALIDATE_TPM_HANDLE
+ * @reasoncode RC_INVALID_TPM_HANDLE
+ * @userdata1 TPM HUID if it's not nullptr
+ * @devdesc Caller attempted to get a random number from a TPM
+ * using an invalid TPM target.
+ * @custdesc Trusted boot failure
+ */
+ err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_VALIDATE_TPM_HANDLE,
+ RC_INVALID_TPM_HANDLE,
+ TARGETING::get_huid(i_pTpm),
+ 0,
+ true);
+
+ break;
+ }
+
+ auto l_tpmHwasState = i_pTpm->getAttr<TARGETING::ATTR_HWAS_STATE>();
+ if (!l_tpmHwasState.functional)
+ {
+ TRACFCOMP(g_trac_trustedboot,
+ ERR_MRK"Non functional TPM handle passed to GetRandom() huid = 0x%08X",
+ TARGETING::get_huid(i_pTpm));
+ /*@
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_VALIDATE_TPM_HANDLE
+ * @reasoncode RC_NON_FUNCTIONAL_TPM_HANDLE
+ * @userdata1 TPM HUID if it's not nullptr
+ * @devdesc Call attempted to get a random number from a TPM
+ * that was not functional
+ * @custdesc Trusted boot failure
+ */
+ err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_VALIDATE_TPM_HANDLE,
+ RC_NON_FUNCTIONAL_TPM_HANDLE,
+ TARGETING::get_huid(i_pTpm),
+ 0,
+ true);
+ break;
+ }
+
+ } while(0);
+ return err;
+}
+
bool isTpmRequired()
{
bool retVal = false;
diff --git a/src/usr/secureboot/trusted/trustedbootCmds.C b/src/usr/secureboot/trusted/trustedbootCmds.C
index 709675c2d..9a73a7052 100644
--- a/src/usr/secureboot/trusted/trustedbootCmds.C
+++ b/src/usr/secureboot/trusted/trustedbootCmds.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* Contributors Listed Below - COPYRIGHT 2015,2018 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -237,6 +237,14 @@ errlHndl_t tpmMarshalCommandData(TPM2_BaseIn* i_cmd,
}
break;
+ case TPM_CC_GetRandom:
+ {
+ auto cmdPtr = reinterpret_cast<TPM2_2ByteIn*>(i_cmd);
+ sBuf = TPM2_2ByteIn_marshal(cmdPtr, sBuf,
+ i_bufsize, o_cmdSize);
+ }
+ break;
+
default:
{
// Command code not supported
@@ -385,6 +393,14 @@ errlHndl_t tpmUnmarshalResponseData(uint32_t i_commandCode,
}
break;
+ case TPM_CC_GetRandom:
+ {
+ auto respPtr = reinterpret_cast<TPM2_GetRandomOut*>(o_outBuf);
+ sBuf = TPM2B_DIGEST_unmarshal(&respPtr->randomBytes, sBuf,
+ &i_respBufSize);
+ }
+ break;
+
default:
{
// Command code not supported
OpenPOWER on IntegriCloud