Skip to content

Commit

Permalink
Trustedboot: GetRandom API Changes
Browse files Browse the repository at this point in the history
New Secure Multinode Comm protocol calls for generation of
random number that is 32 bytes in size. This commit extends
the existing GetRandom API to be able to accept a size of
the random number to be generated by TPM.

Change-Id: Ic6fc1705594f51f121ff75aaa489d6d32fe41409
RTC: 202364
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/70116
Tested-by: Jenkins Server <[email protected]>
Tested-by: Jenkins OP Build CI <[email protected]>
Tested-by: Jenkins OP HW <[email protected]>
Reviewed-by: Nicholas E. Bofferding <[email protected]>
Tested-by: FSP CI Jenkins <[email protected]>
Reviewed-by: Michael Baiocchi <[email protected]>
Reviewed-by: Daniel M. Crowell <[email protected]>
  • Loading branch information
Ilya Smirnov authored and dcrowell77 committed Jan 10, 2019
1 parent 21f75b9 commit 26f7f6d
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 24 deletions.
3 changes: 2 additions & 1 deletion src/include/usr/secureboot/trustedboot_reasoncodes.H
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2015,2018 */
/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -103,6 +103,7 @@ namespace TRUSTEDBOOT
RC_INVALID_TPM_HANDLE = TRBOOT_COMP_ID | 0xB8,
RC_NON_FUNCTIONAL_TPM_HANDLE = TRBOOT_COMP_ID | 0xB9,
RC_UNREACHABLE_TPM = TRBOOT_COMP_ID | 0xBA,
RC_RAND_NUM_TOO_BIG = TRBOOT_COMP_ID | 0xBB,
};
#ifdef __cplusplus
}
Expand Down
14 changes: 10 additions & 4 deletions src/include/usr/secureboot/trustedbootif.H
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2015,2018 */
/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -245,16 +245,22 @@ namespace TRUSTEDBOOT
/**
* @brief Generate random numbers via TPM hardware.
*
* @parm[in] i_pTpm Pointer to TPM target. In order to succeed, it cannot
* @param[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.
* @param[out] o_randNum A pointer to the array to be filled with random
* bits
*
* @param[in] i_randNumSize The desired size (bytes) of the random number
* to be requested from the TPM
*
* @return errlHndl_t nullptr on success or an error log pointer on failure
*/
errlHndl_t GetRandom(const TpmTarget* i_pTpm, uint64_t& o_randNum);
errlHndl_t GetRandom(const TpmTarget* i_pTpm,
uint8_t* o_randNum,
size_t i_randNumSize);
#endif

/**
Expand Down
4 changes: 3 additions & 1 deletion src/usr/secureboot/node_comm/node_comm_exchange.C
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ errlHndl_t nodeCommAbusGetRandom(uint64_t & o_nonce)
// but no extra error handling is needed as it should not have gotten this
// far if CONFIG_TPMDD wasn't set
#ifdef CONFIG_TPMDD
err = TRUSTEDBOOT::GetRandom(tpm_tgt, o_nonce);
err = TRUSTEDBOOT::GetRandom(tpm_tgt,
reinterpret_cast<uint8_t*>(&o_nonce),
sizeof(o_nonce));
#endif
if (err)
{
Expand Down
5 changes: 3 additions & 2 deletions src/usr/secureboot/trusted/base/trustedbootMsg.H
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2016,2018 */
/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -76,7 +76,8 @@ namespace TRUSTEDBOOT
struct GetRandomMsgData
{
TARGETING::Target* i_pTpm; // the TPM to obtain random data from
uint64_t o_randNum; // the random data is populated here
size_t i_randNumSize; // the size (in bytes) of the rand number
uint8_t* o_randNum; // the random data is populated here
};

// Trustedboot message class
Expand Down
6 changes: 4 additions & 2 deletions src/usr/secureboot/trusted/test/trustedbootTest.H
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2015,2018 */
/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -905,7 +905,9 @@ class TrustedBootTest: public CxxTest::TestSuite
for (auto pTpm: tpmList)
{
uint64_t randNum = 0;
err = TRUSTEDBOOT::GetRandom(pTpm, randNum);
err = TRUSTEDBOOT::GetRandom(pTpm,
reinterpret_cast<uint8_t*>(&randNum),
sizeof(randNum));
num_ops ++;
if(err)
{
Expand Down
76 changes: 62 additions & 14 deletions src/usr/secureboot/trusted/trustedboot.C
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2015,2018 */
/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -1547,6 +1547,34 @@ void* tpmDaemon(void* unused)
assert(msgData != nullptr,
"Trusted boot message data pointer is null");
auto l_pTpm = msgData->i_pTpm;
size_t l_randNumSize = msgData->i_randNumSize;

if(l_randNumSize > sizeof(TPM2B_DIGEST))
{
TRACFCOMP( g_trac_trustedboot,
ERR_MRK"TPM GetRandom: The size of the requested random number (%d) is larger than max size the TPM can return (%d).", l_randNumSize, sizeof(TPM2B_DIGEST));
/*@
* @errortype ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_TPMDAEMON
* @reasoncode RC_RAND_NUM_TOO_BIG
* @userdata1 The size of requested random number
* @userdata2 The maximum random number size
* @devdesc Attempted to request a random number that
* is bigger than the max a TPM can provide
* @custdesc Trusted boot failure
*/
err = new ERRORLOG::ErrlEntry(
ERRORLOG::ERRL_SEV_UNRECOVERABLE,
MOD_TPM_TPMDAEMON,
RC_RAND_NUM_TOO_BIG,
l_randNumSize,
sizeof(TPM2B_DIGEST),
ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);

tb_msg->iv_errl = err;
err = nullptr;
break;
}

err = validateTpmHandle(l_pTpm);
if (err)
Expand All @@ -1559,11 +1587,10 @@ void* tpmDaemon(void* unused)
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);
cmd->bytesRequested = l_randNumSize;

err = tpmTransmitCommand(l_pTpm, dataBuf, dataSize,
TPM_LOCALITY_0);
Expand All @@ -1588,15 +1615,16 @@ void* tpmDaemon(void* unused)
RC_UNREACHABLE_TPM,
TARGETING::get_huid(l_pTpm),
0,
true);
ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
err->plid(l_errPlid);
tb_msg->iv_errl = err;
err = nullptr;
}
else
{
memcpy(&randNum, resp->randomBytes.buffer,sizeof(randNum));
msgData->o_randNum = randNum;
memcpy(msgData->o_randNum,
resp->randomBytes.buffer,
l_randNumSize);
}
}
break;
Expand Down Expand Up @@ -1669,7 +1697,7 @@ errlHndl_t validateTpmHandle(const TpmTarget* i_pTpm)
i_pTpm->getAttr<TARGETING::ATTR_TYPE>() != TARGETING::TYPE_TPM)
{
TRACFCOMP(g_trac_trustedboot,
ERR_MRK"Invalid TPM handle passed to GetRandom() huid = 0x%08X",
ERR_MRK"Invalid TPM handle passed to validateTpmHandle: huid = 0x%08X",
TARGETING::get_huid(i_pTpm));
/*@
* @errortype ERRL_SEV_UNRECOVERABLE
Expand All @@ -1694,7 +1722,7 @@ errlHndl_t validateTpmHandle(const TpmTarget* i_pTpm)
if (!l_tpmHwasState.functional)
{
TRACFCOMP(g_trac_trustedboot,
ERR_MRK"Non functional TPM handle passed to GetRandom() huid = 0x%08X",
ERR_MRK"Non functional TPM handle passed to validateTpmHandle: huid = 0x%08X",
TARGETING::get_huid(i_pTpm));
/*@
* @errortype ERRL_SEV_UNRECOVERABLE
Expand Down Expand Up @@ -1870,17 +1898,22 @@ errlHndl_t tpmDrtmReset(TpmTarget* const i_pTpm)
#endif

#ifdef CONFIG_TPMDD
errlHndl_t GetRandom(const TpmTarget* i_pTpm, uint64_t& o_randNum)
errlHndl_t GetRandom(const TpmTarget* i_pTpm,
uint8_t* o_randNum,
const size_t i_randNumSize)
{
errlHndl_t err = nullptr;
Message* msg = nullptr;

auto pData = new struct GetRandomMsgData;

do {

auto pData = new struct GetRandomMsgData;
memset(pData, 0, sizeof(*pData));

pData->i_pTpm = const_cast<TpmTarget*>(i_pTpm);
pData->i_randNumSize = i_randNumSize;
pData->o_randNum = new uint8_t[i_randNumSize];
memset(pData->o_randNum, 0, i_randNumSize);

msg = Message::factory(MSG_TYPE_GETRANDOM, sizeof(*pData),
reinterpret_cast<uint8_t*>(pData), MSG_MODE_SYNC);
Expand Down Expand Up @@ -1914,18 +1947,31 @@ errlHndl_t GetRandom(const TpmTarget* i_pTpm, uint64_t& o_randNum)
RC_SENDRECV_FAIL,
rc,
TARGETING::get_huid(i_pTpm),
true);
ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
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;
memcpy(o_randNum, pData->o_randNum, pData->i_randNumSize);

} while (0);

// If an error occurs before the reponse is written, then pData
// will be nullptr and dereferencing o_randNum will cause crashes.
// So, we need to check for pData before attempting to delete the
// o_randNum.
if(pData)
{
if(pData->o_randNum)
{
delete[](pData->o_randNum);
pData->o_randNum = nullptr;
}
}

if (msg != nullptr)
{
delete msg; // also deletes the msg->iv_data
Expand Down Expand Up @@ -1953,7 +1999,9 @@ errlHndl_t poisonTpm(const TpmTarget* i_pTpm)

// Note: GetRandom validates the TPM handle internally and returns an
// error log if invalid
l_errl = GetRandom(i_pTpm, l_randNum);
l_errl = GetRandom(i_pTpm,
reinterpret_cast<uint8_t*>(&l_randNum),
sizeof(l_randNum));

if (l_errl)
{
Expand Down

0 comments on commit 26f7f6d

Please sign in to comment.