diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/secureboot/trustedboot_reasoncodes.H | 8 | ||||
-rw-r--r-- | src/include/usr/secureboot/trustedbootif.H | 27 | ||||
-rw-r--r-- | src/usr/secureboot/trusted/base/trustedbootMsg.H | 9 | ||||
-rw-r--r-- | src/usr/secureboot/trusted/base/trustedboot_base.C | 73 | ||||
-rwxr-xr-x | src/usr/secureboot/trusted/test/trustedbootTest.H | 50 | ||||
-rw-r--r-- | src/usr/secureboot/trusted/trustedTypes.H | 19 | ||||
-rw-r--r-- | src/usr/secureboot/trusted/trustedboot.C | 137 | ||||
-rw-r--r-- | src/usr/secureboot/trusted/trustedbootCmds.C | 18 |
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 |