blob: c92480657ac9a84cc65701b893c92d451222388b [file] [log] [blame]
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
/* $Source: src/usr/secureboot/trusted/trustedbootCmds.C $ */
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2015,2016 */
/* [+] 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 */
/**
* @file trustedbootCmds.C
*
* @brief Trusted boot TPM command interfaces
*/
/////////////////////////////////////////////////////////////////
// NOTE: This file is exportable as TSS-Lite for skiboot/PHYP //
/////////////////////////////////////////////////////////////////
// ----------------------------------------------
// Includes
// ----------------------------------------------
#include <string.h>
#include <stdlib.h>
#ifdef __HOSTBOOT_MODULE
#include <secureboot/trustedboot_reasoncodes.H>
#else
#include "trustedboot_reasoncodes.H"
#endif
#include "trustedbootCmds.H"
#include "trustedbootUtils.H"
#include "trustedboot.H"
#include "trustedTypes.H"
#ifdef __cplusplus
namespace TRUSTEDBOOT
{
#endif
errlHndl_t tpmTransmitCommand(TpmTarget * io_target,
uint8_t* io_buffer,
size_t i_bufsize )
{
errlHndl_t err = TB_SUCCESS;
uint8_t* transmitBuf = NULL;
size_t cmdSize = 0;
size_t dataSize = 0;
TPM2_BaseIn* cmd = (TPM2_BaseIn*)io_buffer;
TPM2_BaseOut* resp = (TPM2_BaseOut*)io_buffer;
TRACUCOMP( g_trac_trustedboot,
">>TPM TRANSMIT CMD START : BufLen %d : %016llx",
(int)i_bufsize,
*((uint64_t*)io_buffer) );
do
{
transmitBuf = (uint8_t*)malloc(MAX_TRANSMIT_SIZE);
// Marshal the data into a byte array for transfer to the TPM
err = tpmMarshalCommandData(cmd,
transmitBuf,
MAX_TRANSMIT_SIZE,
&cmdSize);
if (TB_SUCCESS != err)
{
break;
}
// Send to the TPM
dataSize = MAX_TRANSMIT_SIZE;
err = tpmTransmit(io_target,
transmitBuf,
cmdSize,
dataSize);
if (TB_SUCCESS != err)
{
break;
}
// Unmarshal the response
err = tpmUnmarshalResponseData(cmd->commandCode,
transmitBuf,
dataSize,
resp,
i_bufsize);
} while ( 0 );
free(transmitBuf);
TRACUCOMP( g_trac_trustedboot,
"<<tpmTransmitCommand() - %s",
((TB_SUCCESS == err) ? "No Error" : "With Error") );
return err;
}
errlHndl_t tpmMarshalCommandData(TPM2_BaseIn* i_cmd,
uint8_t* o_outbuf,
size_t i_bufsize,
size_t* o_cmdSize)
{
errlHndl_t err = TB_SUCCESS;
uint8_t* sBuf = o_outbuf;
uint32_t* sSizePtr = NULL;
size_t curSize = 0;
int stage = 0;
TPM2_BaseIn* baseCmd =
(TPM2_BaseIn*)o_outbuf;
TPMS_AUTH_COMMAND cmdAuth;
*o_cmdSize = 0;
TRACDCOMP( g_trac_trustedboot,
">>tpmMarshalCommandData()" );
do
{
TRACUCOMP( g_trac_trustedboot,
"TPM MARSHAL START : BufLen %d : %016llx",
(int)i_bufsize,
*((uint64_t*)i_cmd) );
// Start with the command header
sBuf = TPM2_BaseIn_marshal(i_cmd, sBuf, i_bufsize, o_cmdSize);
if (NULL == sBuf)
{
break;
}
// Marshal the handles
stage = 1;
if (TPM_CC_PCR_Extend == i_cmd->commandCode)
{
TPM2_ExtendIn* cmdPtr = (TPM2_ExtendIn*)i_cmd;
sBuf = TPM2_ExtendIn_marshalHandle(cmdPtr,
sBuf,
i_bufsize,
o_cmdSize);
if (NULL == sBuf)
{
break;
}
}
// Marshal the authorizations
stage = 2;
if (TPM_CC_PCR_Extend == i_cmd->commandCode)
{
// Insert a password authorization with a null pw
// Make room for the 4 byte size field at the beginning
sSizePtr = (uint32_t*)sBuf;
sBuf += sizeof(uint32_t);
*o_cmdSize += sizeof(uint32_t);
i_bufsize -= sizeof(uint32_t);
curSize = *o_cmdSize;
cmdAuth.sessionHandle = TPM_RS_PW;
cmdAuth.nonceSize = 0;
cmdAuth.sessionAttributes = 0;
cmdAuth.hmacSize = 0;
sBuf = TPMS_AUTH_COMMAND_marshal(&cmdAuth, sBuf, i_bufsize,
o_cmdSize);
if (NULL == sBuf)
{
break;
}
// Put in the size of the auth area
*sSizePtr = (*o_cmdSize - curSize);
}
// Marshal the command parameters
stage = 3;
switch (i_cmd->commandCode)
{
// Two byte parm fields
case TPM_CC_Startup:
{
TPM2_2ByteIn* cmdPtr =
(TPM2_2ByteIn*)i_cmd;
sBuf = TPM2_2ByteIn_marshal(cmdPtr, sBuf,
i_bufsize, o_cmdSize);
}
break;
case TPM_CC_GetCapability:
{
TPM2_GetCapabilityIn* cmdPtr =
(TPM2_GetCapabilityIn*)i_cmd;
sBuf = TPM2_GetCapabilityIn_marshal(cmdPtr,sBuf,
i_bufsize, o_cmdSize);
}
break;
case TPM_CC_PCR_Read:
{
TPM2_PcrReadIn* cmdPtr = (TPM2_PcrReadIn*)i_cmd;
sBuf = TPM2_PcrReadIn_marshal(cmdPtr, sBuf,
i_bufsize - (sBuf - o_outbuf),
o_cmdSize);
}
break;
case TPM_CC_PCR_Extend:
{
TPM2_ExtendIn* cmdPtr = (TPM2_ExtendIn*)i_cmd;
sBuf = TPM2_ExtendIn_marshalParms(cmdPtr, sBuf,
i_bufsize, o_cmdSize);
}
break;
default:
{
// Command code not supported
TRACFCOMP( g_trac_trustedboot,
"TPM MARSHAL INVALID COMMAND : %X",
i_cmd->commandCode );
sBuf = NULL;
/*@
* @errortype
* @reasoncode RC_TPM_MARSHAL_INVALID_CMD
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_MARSHALCMDDATA
* @userdata1 Command Code
* @userdata2 0
* @devdesc Unsupported command code during marshal
*/
err = tpmCreateErrorLog(MOD_TPM_MARSHALCMDDATA,
RC_TPM_MARSHAL_INVALID_CMD,
i_cmd->commandCode,
0);
}
break;
};
if (TB_SUCCESS != err || NULL == sBuf)
{
break;
}
// Do a verification that the cmdSize equals what we used
if (((size_t)(sBuf - o_outbuf)) != *o_cmdSize)
{
TRACFCOMP( g_trac_trustedboot,
"TPM MARSHAL MARSHAL SIZE MISMATCH : %d %d",
(int)(sBuf - o_outbuf), (int)(*o_cmdSize) );
sBuf = NULL;
}
// Lastly now that we know the size update the byte stream
baseCmd->commandSize = *o_cmdSize;
} while ( 0 );
if (NULL == sBuf && TB_SUCCESS == err)
{
TRACFCOMP( g_trac_trustedboot,
"TPM MARSHAL FAILURE : Stage %d", stage);
/*@
* @errortype
* @reasoncode RC_TPM_MARSHALING_FAIL
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_MARSHALCMDDATA
* @userdata1 stage
* @userdata2 0
* @devdesc Marshaling error detected
*/
err = tpmCreateErrorLog(MOD_TPM_MARSHALCMDDATA,
RC_TPM_MARSHALING_FAIL,
stage,
0 );
}
TRACUBIN(g_trac_trustedboot, "Marshal Out",
o_outbuf, *o_cmdSize);
TRACUCOMP( g_trac_trustedboot,
"TPM MARSHAL END : CmdSize: %d : %016llx ",
(int)(*o_cmdSize),
*((uint64_t*)o_outbuf) );
TRACDCOMP( g_trac_trustedboot,
"<<tpmMarshalCommandData()" );
return err;
}
errlHndl_t tpmUnmarshalResponseData(uint32_t i_commandCode,
uint8_t* i_respBuf,
size_t i_respBufSize,
TPM2_BaseOut* o_outBuf,
size_t i_outBufSize)
{
errlHndl_t err = TB_SUCCESS;
const uint8_t* sBuf = i_respBuf;
int stage = 0;
TRACDCOMP( g_trac_trustedboot,
">>tpmUnmarshalResponseData()" );
do {
TRACUCOMP( g_trac_trustedboot,
"TPM UNMARSHAL START : RespBufLen %d : OutBufLen %d",
(int)i_respBufSize, (int)i_outBufSize);
TRACUBIN(g_trac_trustedboot,"Unmarshal In",
i_respBuf, i_respBufSize);
// Start with the response header
stage = 1;
sBuf = TPM2_BaseOut_unmarshal(o_outBuf, sBuf,
&i_respBufSize, i_outBufSize);
if (NULL == sBuf)
{
break;
}
// If the TPM returned a failure it will not send the rest
// Let the caller deal with the RC
if (TPM_SUCCESS != o_outBuf->responseCode)
{
break;
}
// Unmarshal the parameters
stage = 2;
switch (i_commandCode)
{
// Empty response commands
case TPM_CC_Startup:
case TPM_CC_PCR_Extend:
// Nothing to do
break;
case TPM_CC_GetCapability:
{
TPM2_GetCapabilityOut* respPtr =
(TPM2_GetCapabilityOut*)o_outBuf;
sBuf = TPM2_GetCapabilityOut_unmarshal(respPtr, sBuf,
&i_respBufSize,
i_outBufSize);
}
break;
case TPM_CC_PCR_Read:
{
TPM2_PcrReadOut* respPtr = (TPM2_PcrReadOut*)o_outBuf;
sBuf = TPM2_PcrReadOut_unmarshal(respPtr, sBuf,
&i_respBufSize,
i_outBufSize);
}
break;
default:
{
// Command code not supported
TRACFCOMP( g_trac_trustedboot,
"TPM UNMARSHAL INVALID COMMAND : %X",
i_commandCode );
sBuf = NULL;
/*@
* @errortype
* @reasoncode RC_TPM_UNMARSHAL_INVALID_CMD
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_UNMARSHALRESPDATA
* @userdata1 commandcode
* @userdata2 stage
* @devdesc Unsupported command code during unmarshal
*/
err = tpmCreateErrorLog(MOD_TPM_UNMARSHALRESPDATA,
RC_TPM_UNMARSHAL_INVALID_CMD,
i_commandCode,
stage);
}
break;
}
} while ( 0 );
if (NULL == sBuf && TB_SUCCESS == err)
{
TRACFCOMP( g_trac_trustedboot,
"TPM UNMARSHAL FAILURE : Stage %d", stage);
/*@
* @errortype
* @reasoncode RC_TPM_UNMARSHALING_FAIL
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_UNMARSHALRESPDATA
* @userdata1 Stage
* @userdata2 Remaining response buffer size
* @devdesc Unmarshaling error detected
*/
err = tpmCreateErrorLog(MOD_TPM_UNMARSHALRESPDATA,
RC_TPM_UNMARSHALING_FAIL,
stage,
i_respBufSize);
}
TRACUCOMP( g_trac_trustedboot,
"TPM UNMARSHAL END : %016llx ",
*((uint64_t*)o_outBuf) );
TRACDCOMP( g_trac_trustedboot,
"<<tpmUnmarshalResponseData()" );
return err;
}
errlHndl_t tpmCmdStartup(TpmTarget* io_target)
{
errlHndl_t err = TB_SUCCESS;
uint8_t dataBuf[BUFSIZE];
TPM2_BaseOut* resp =
(TPM2_BaseOut*)(dataBuf);
TPM2_2ByteIn* cmd =
(TPM2_2ByteIn*)(dataBuf);
TRACUCOMP( g_trac_trustedboot,
">>tpmCmdStartup()" );
do
{
// Send the TPM startup command
// Build our command block for a startup
memset(dataBuf, 0, sizeof(dataBuf));
cmd->base.tag = TPM_ST_NO_SESSIONS;
cmd->base.commandCode = TPM_CC_Startup;
cmd->param = TPM_SU_CLEAR;
err = tpmTransmitCommand(io_target,
dataBuf,
sizeof(dataBuf));
if (TB_SUCCESS != err)
{
TRACFCOMP( g_trac_trustedboot,
"TPM STARTUP transmit Fail");
break;
}
else if (TPM_SUCCESS != resp->responseCode)
{
TRACFCOMP( g_trac_trustedboot,
"TPM STARTUP OP Fail %X : ",
resp->responseCode);
/*@
* @errortype
* @reasoncode RC_TPM_START_FAIL
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_CMD_STARTUP
* @userdata1 responseCode
* @userdata2 0
* @devdesc Invalid operation type.
*/
err = tpmCreateErrorLog(MOD_TPM_CMD_STARTUP,
RC_TPM_START_FAIL,
resp->responseCode,
0);
break;
}
} while ( 0 );
TRACUCOMP( g_trac_trustedboot,
"<<tpmCmdStartup() - %s",
((TB_SUCCESS == err) ? "No Error" : "With Error") );
return err;
}
errlHndl_t tpmCmdGetCapFwVersion(TpmTarget* io_target)
{
errlHndl_t err = TB_SUCCESS;
uint8_t dataBuf[BUFSIZE];
size_t dataSize = BUFSIZE;
uint16_t fwVersion[4] = {0xFF, 0xFF, 0xFF, 0xFF};
TPM2_GetCapabilityOut* resp =
(TPM2_GetCapabilityOut*)dataBuf;
TPM2_GetCapabilityIn* cmd =
(TPM2_GetCapabilityIn*)dataBuf;
TRACUCOMP( g_trac_trustedboot,
">>tpmCmdGetCapFwVersion()" );
do
{
// Build our command block for a get capability of the FW version
memset(dataBuf, 0, dataSize);
cmd->base.tag = TPM_ST_NO_SESSIONS;
cmd->base.commandCode = TPM_CC_GetCapability;
cmd->capability = TPM_CAP_TPM_PROPERTIES;
cmd->property = TPM_PT_FIRMWARE_VERSION_1;
cmd->propertyCount = 1;
err = tpmTransmitCommand(io_target,
dataBuf,
sizeof(dataBuf));
if (TB_SUCCESS != err)
{
TRACFCOMP( g_trac_trustedboot,
"TPM GETCAP Transmit Fail");
break;
}
if (TPM_SUCCESS != resp->base.responseCode)
{
TRACFCOMP( g_trac_trustedboot,
"TPM GETCAP OP Fail %X Size(%d) ",
resp->base.responseCode,
(int)dataSize);
/*@
* @errortype
* @reasoncode RC_TPM_GETCAP_FAIL
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_CMD_GETCAPFWVERSION
* @userdata1 responseCode
* @userdata2 0
* @devdesc Command failure reading TPM FW version.
*/
err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
RC_TPM_GETCAP_FAIL,
resp->base.responseCode,
0);
break;
}
else
{
// Walk the reponse data to pull the high order bytes out
if (resp->capData.capability != TPM_CAP_TPM_PROPERTIES ||
resp->capData.data.tpmProperties.count != 1 ||
resp->capData.data.tpmProperties.tpmProperty[0].property !=
TPM_PT_FIRMWARE_VERSION_1) {
TRACFCOMP( g_trac_trustedboot,
"TPM GETCAP FW INVALID DATA "
"Cap(%X) Cnt(%X) Prop(%X)",
resp->capData.capability,
resp->capData.data.tpmProperties.count,
resp->capData.data.tpmProperties.
tpmProperty[0].property);
/*@
* @errortype
* @reasoncode RC_TPM_GETCAP_FW_INVALID_RESP
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_CMD_GETCAPFWVERSION
* @userdata1 capability
* @userdata2 property
* @devdesc Command failure reading TPM FW version.
*/
err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
RC_TPM_GETCAP_FW_INVALID_RESP,
resp->capData.capability,
resp->capData.data.tpmProperties.
tpmProperty[0].property);
break;
}
else
{
fwVersion[0] =
(resp->capData.data.
tpmProperties.tpmProperty[0].value >> 16);
fwVersion[1] =
(resp->capData.data.
tpmProperties.tpmProperty[0].value & 0xFFFF);
}
}
// Read part 2 of the version
dataSize = BUFSIZE;
memset(dataBuf, 0, dataSize);
cmd->base.tag = TPM_ST_NO_SESSIONS;
cmd->base.commandCode = TPM_CC_GetCapability;
cmd->capability = TPM_CAP_TPM_PROPERTIES;
cmd->property = TPM_PT_FIRMWARE_VERSION_2;
cmd->propertyCount = 1;
err = tpmTransmitCommand(io_target,
dataBuf,
sizeof(dataBuf));
if (TB_SUCCESS != err)
{
TRACFCOMP( g_trac_trustedboot,
"TPM GETCAP2 Transmit Fail");
break;
}
if ((sizeof(TPM2_GetCapabilityOut) > dataSize) ||
(TPM_SUCCESS != resp->base.responseCode))
{
TRACFCOMP( g_trac_trustedboot,
"TPM GETCAP2 OP Fail %X Size(%d) ",
resp->base.responseCode,
(int)dataSize);
/*@
* @errortype
* @reasoncode RC_TPM_GETCAP2_FAIL
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_CMD_GETCAPFWVERSION
* @userdata1 responseCode
* @userdata2 0
* @devdesc Command failure reading TPM FW version.
*/
err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
RC_TPM_GETCAP2_FAIL,
resp->base.responseCode,
0);
break;
}
else
{
// Walk the reponse data to pull the high order bytes out
if (resp->capData.capability != TPM_CAP_TPM_PROPERTIES ||
resp->capData.data.tpmProperties.count != 1 ||
resp->capData.data.tpmProperties.tpmProperty[0].property !=
TPM_PT_FIRMWARE_VERSION_2) {
TRACFCOMP( g_trac_trustedboot,
"TPM GETCAP2 FW INVALID DATA "
"Cap(%X) Cnt(%X) Prop(%X)",
resp->capData.capability,
resp->capData.data.tpmProperties.count,
resp->capData.data.tpmProperties.
tpmProperty[0].property);
/*@
* @errortype
* @reasoncode RC_TPM_GETCAP2_FW_INVALID_RESP
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_CMD_GETCAPFWVERSION
* @userdata1 capability
* @userdata2 property
* @devdesc Command failure reading TPM FW version.
*/
err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
RC_TPM_GETCAP2_FW_INVALID_RESP,
resp->capData.capability,
resp->capData.data.tpmProperties.
tpmProperty[0].property);
break;
}
else
{
fwVersion[2] =
(resp->capData.data.tpmProperties.
tpmProperty[0].value >> 16);
fwVersion[3] =
(resp->capData.data.tpmProperties.
tpmProperty[0].value & 0xFFFF);
}
// Trace the response
TRACFCOMP( g_trac_trustedboot,
"TPM GETCAP FW Level %d.%d.%d.%d",
fwVersion[0],fwVersion[1],fwVersion[2],fwVersion[3]
);
}
} while ( 0 );
TRACDCOMP( g_trac_trustedboot,
"<<tpmCmdGetCapFwVersion() - %s",
((TB_SUCCESS == err) ? "No Error" : "With Error") );
return err;
}
errlHndl_t tpmCmdPcrExtend(TpmTarget * io_target,
TPM_Pcr i_pcr,
TPM_Alg_Id i_algId,
const uint8_t* i_digest,
size_t i_digestSize)
{
return tpmCmdPcrExtend2Hash(io_target, i_pcr,
i_algId, i_digest, i_digestSize,
TPM_ALG_INVALID_ID, NULL, 0);
}
errlHndl_t tpmCmdPcrExtend2Hash(TpmTarget * io_target,
TPM_Pcr i_pcr,
TPM_Alg_Id i_algId_1,
const uint8_t* i_digest_1,
size_t i_digestSize_1,
TPM_Alg_Id i_algId_2,
const uint8_t* i_digest_2,
size_t i_digestSize_2)
{
errlHndl_t err = 0;
uint8_t dataBuf[sizeof(TPM2_ExtendIn)];
size_t dataSize = sizeof(dataBuf);
size_t fullDigestSize_1 = 0;
size_t fullDigestSize_2 = 0;
TPM2_BaseOut* resp = (TPM2_BaseOut*)dataBuf;
TPM2_ExtendIn* cmd = (TPM2_ExtendIn*)dataBuf;
TRACDCOMP( g_trac_trustedboot,
">>tpmCmdPcrExtend2Hash()" );
if (NULL == i_digest_2)
{
TRACUCOMP( g_trac_trustedboot,
">>tpmCmdPcrExtend2Hash() Pcr(%d) Alg(%X) DS(%d)",
i_pcr, i_algId_1, (int)i_digestSize_1);
}
else
{
TRACUCOMP( g_trac_trustedboot,
">>tpmCmdPcrExtend2Hash() Pcr(%d) Alg(%X:%X) DS(%d:%d)",
i_pcr, i_algId_1, i_algId_2,
(int)i_digestSize_1, (int)i_digestSize_2);
}
do
{
fullDigestSize_1 = getDigestSize(i_algId_1);
if (NULL != i_digest_2)
{
fullDigestSize_2 = getDigestSize(i_algId_2);
}
// Build our command block
memset(dataBuf, 0, sizeof(dataBuf));
// Argument verification
if (fullDigestSize_1 == 0 ||
NULL == i_digest_1 ||
IMPLEMENTATION_PCR < i_pcr ||
(NULL != i_digest_2 && fullDigestSize_2 == 0)
)
{
TRACFCOMP( g_trac_trustedboot,
"TPM PCR EXTEND ARG FAILURE FDS(%d:%d) DS(%d:%d) "
"PCR(%d)",
(int)fullDigestSize_1, (int)fullDigestSize_2,
(int)i_digestSize_1, (int)i_digestSize_2, i_pcr);
/*@
* @errortype
* @reasoncode RC_TPM_INVALID_ARGS
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_CMD_PCREXTEND
* @userdata1 Digest Ptr
* @userdata2[0:15] Full Digest Size 1
* @userdata2[16:31] Full Digest Size 2
* @userdata2[32:63] PCR
* @devdesc Unmarshaling error detected
*/
err = tpmCreateErrorLog(MOD_TPM_CMD_PCREXTEND,
RC_TPM_INVALID_ARGS,
(uint64_t)i_digest_1,
(fullDigestSize_1 << 48) |
(fullDigestSize_2 << 32) |
i_pcr);
break;
}
// Log the input PCR value
TRACUBIN(g_trac_trustedboot, "PCR In",
i_digest_1, fullDigestSize_1);
cmd->base.tag = TPM_ST_SESSIONS;
cmd->base.commandCode = TPM_CC_PCR_Extend;
cmd->pcrHandle = i_pcr;
cmd->digests.count = 1;
cmd->digests.digests[0].algorithmId = i_algId_1;
memcpy(&(cmd->digests.digests[0].digest), i_digest_1,
(i_digestSize_1 < fullDigestSize_1 ?
i_digestSize_1 : fullDigestSize_1) );
if (NULL != i_digest_2)
{
cmd->digests.count = 2;
cmd->digests.digests[1].algorithmId = i_algId_2;
memcpy(&(cmd->digests.digests[1].digest), i_digest_2,
(i_digestSize_2 < fullDigestSize_2 ?
i_digestSize_2 : fullDigestSize_2));
}
err = tpmTransmitCommand(io_target,
dataBuf,
sizeof(dataBuf));
if (TB_SUCCESS != err)
{
TRACFCOMP( g_trac_trustedboot,
"TPM PCRExtend Transmit Fail");
break;
}
else if ((sizeof(TPM2_BaseOut) > dataSize)
|| (TPM_SUCCESS != resp->responseCode))
{
TRACFCOMP( g_trac_trustedboot,
"TPM PCRExtend OP Fail Ret(%X) ExSize(%d) Size(%d) ",
resp->responseCode,
(int)sizeof(TPM2_BaseOut),
(int)dataSize);
/*@
* @errortype
* @reasoncode RC_TPM_COMMAND_FAIL
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_CMD_PCREXTEND
* @userdata1 responseCode
* @userdata2 dataSize
* @devdesc Command failure reading TPM FW version.
*/
err = tpmCreateErrorLog(MOD_TPM_CMD_PCREXTEND,
RC_TPM_COMMAND_FAIL,
resp->responseCode,
dataSize);
break;
}
} while ( 0 );
TRACUCOMP( g_trac_trustedboot,
"<<tpmCmdPcrExtend() - %s",
((TB_SUCCESS == err) ? "No Error" : "With Error") );
return err;
}
errlHndl_t tpmCmdPcrRead(TpmTarget* io_target,
TPM_Pcr i_pcr,
TPM_Alg_Id i_algId,
uint8_t* o_digest,
size_t i_digestSize)
{
errlHndl_t err = 0;
uint8_t dataBuf[sizeof(TPM2_PcrReadOut)];
size_t dataSize = sizeof(dataBuf);
size_t fullDigestSize = 0;
TPM2_PcrReadOut* resp = (TPM2_PcrReadOut*)dataBuf;
TPM2_PcrReadIn* cmd = (TPM2_PcrReadIn*)dataBuf;
TRACDCOMP( g_trac_trustedboot,
">>tpmCmdPcrRead()" );
TRACUCOMP( g_trac_trustedboot,
">>tpmCmdPcrRead() Pcr(%d) DS(%d)",
i_pcr, (int)i_digestSize);
do
{
fullDigestSize = getDigestSize(i_algId);
// Build our command block
memset(dataBuf, 0, sizeof(dataBuf));
// Argument verification
if (fullDigestSize > i_digestSize ||
NULL == o_digest ||
IMPLEMENTATION_PCR < i_pcr
)
{
TRACFCOMP( g_trac_trustedboot,
"TPM PCR READ ARG FAILURE FDS(%d) DS(%d) PCR(%d)",
(int)fullDigestSize, (int)i_digestSize, i_pcr);
/*@
* @errortype
* @reasoncode RC_TPM_INVALID_ARGS
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_CMD_PCRREAD
* @userdata1 Digest Ptr
* @userdata2[0:31] Full Digest Size
* @userdata2[32:63] PCR
* @devdesc Unmarshaling error detected
*/
err = tpmCreateErrorLog(MOD_TPM_CMD_PCRREAD,
RC_TPM_INVALID_ARGS,
(uint64_t)o_digest,
(fullDigestSize << 32) |
i_pcr);
break;
}
cmd->base.tag = TPM_ST_NO_SESSIONS;
cmd->base.commandCode = TPM_CC_PCR_Read;
cmd->pcrSelectionIn.count = 1; // One algorithm
cmd->pcrSelectionIn.pcrSelections[0].algorithmId = i_algId;
cmd->pcrSelectionIn.pcrSelections[0].sizeOfSelect = PCR_SELECT_MAX;
memset(cmd->pcrSelectionIn.pcrSelections[0].pcrSelect, 0,
sizeof(cmd->pcrSelectionIn.pcrSelections[0].pcrSelect));
cmd->pcrSelectionIn.pcrSelections[0].pcrSelect[i_pcr / 8] =
0x01 << (i_pcr % 8);
err = tpmTransmitCommand(io_target,
dataBuf,
sizeof(dataBuf));
if (TB_SUCCESS != err)
{
TRACFCOMP( g_trac_trustedboot,
"TPM PCRRead Transmit Fail ");
break;
}
else if ((sizeof(TPM2_BaseOut) > dataSize) ||
(TPM_SUCCESS != resp->base.responseCode) ||
(resp->pcrValues.count != 1) ||
(resp->pcrValues.digests[0].size != fullDigestSize))
{
TRACFCOMP( g_trac_trustedboot,
"TPM PCRRead OP Fail Ret(%X) ExSize(%d) "
"Size(%d) Cnt(%d) DSize(%d)",
resp->base.responseCode,
(int)sizeof(TPM2_BaseOut),
(int)dataSize,
resp->pcrValues.count,
resp->pcrValues.digests[0].size);
/*@
* @errortype
* @reasoncode RC_TPM_COMMAND_FAIL
* @severity ERRL_SEV_UNRECOVERABLE
* @moduleid MOD_TPM_CMD_PCRREAD
* @userdata1 responseCode
* @userdata2 dataSize
* @devdesc Command failure reading TPM FW version.
*/
err = tpmCreateErrorLog(MOD_TPM_CMD_PCRREAD,
RC_TPM_COMMAND_FAIL,
resp->base.responseCode,
dataSize);
break;
}
else
{
memcpy(o_digest, resp->pcrValues.digests[0].buffer, fullDigestSize);
// Log the PCR value
TRACUBIN(g_trac_trustedboot, "PCR Out",
o_digest, fullDigestSize);
}
} while ( 0 );
TRACUCOMP( g_trac_trustedboot,
"<<tpmCmdPcrRead() - %s",
((TB_SUCCESS == err) ? "No Error" : "With Error") );
return err;
}
#ifdef __cplusplus
} // end TRUSTEDBOOT
#endif