From e914974751a5125cff6fa7078399db6f3aac5641 Mon Sep 17 00:00:00 2001 From: Chris Engel Date: Mon, 3 Aug 2015 16:01:14 -0500 Subject: Trustedboot: Additional commands in trusted boot init sequence - getCap FW Version - TPM Command marshal/unmarshal code Change-Id: Ia9a90b1160c9c3b5d818318771bff21eb013bdf4 RTC: 125287 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/20056 Tested-by: Jenkins Server Tested-by: Jenkins OP Build CI Reviewed-by: STEPHEN M. CPREK Reviewed-by: Timothy R. Block Reviewed-by: A. Patrick Williams III --- src/include/usr/i2c/tpmddif.H | 46 ++ .../usr/secureboot/trustedboot_reasoncodes.H | 14 +- src/include/usr/secureboot/trustedbootif.H | 5 +- src/makefile | 1 + src/usr/i2c/test/tpmddtest.H | 98 +-- src/usr/i2c/tpmdd.C | 46 +- src/usr/i2c/tpmdd.H | 44 -- src/usr/secureboot/trusted/base/trustedboot_base.C | 1 + src/usr/secureboot/trusted/makefile | 4 + src/usr/secureboot/trusted/test/makefile | 30 + src/usr/secureboot/trusted/test/trustedbootTest.H | 529 +++++++++++++++ src/usr/secureboot/trusted/trustedTypes.C | 219 +++++++ src/usr/secureboot/trusted/trustedTypes.H | 297 +++++++++ src/usr/secureboot/trusted/trustedboot.C | 110 ++-- src/usr/secureboot/trusted/trustedboot.H | 147 ++--- src/usr/secureboot/trusted/trustedbootCmds.C | 717 +++++++++++++++++++++ 16 files changed, 1999 insertions(+), 309 deletions(-) create mode 100644 src/usr/secureboot/trusted/test/makefile create mode 100755 src/usr/secureboot/trusted/test/trustedbootTest.H create mode 100644 src/usr/secureboot/trusted/trustedTypes.C create mode 100644 src/usr/secureboot/trusted/trustedTypes.H create mode 100644 src/usr/secureboot/trusted/trustedbootCmds.C (limited to 'src') diff --git a/src/include/usr/i2c/tpmddif.H b/src/include/usr/i2c/tpmddif.H index 0a8233eda..08fbebfc0 100644 --- a/src/include/usr/i2c/tpmddif.H +++ b/src/include/usr/i2c/tpmddif.H @@ -50,6 +50,35 @@ enum tpm_op_types_t TPM_OP_FIRSTOP = TPM_OP_READVENDORID }; +/** +* @brief Enumerations to describe the type of devices to be accessed. +*/ +enum tpm_addr_size_t +{ + ONE_BYTE_ADDR = 1, + TWO_BYTE_ADDR = 2, + LAST_DEVICE_TYPE +}; + +/** + * @brief Structure of common parameters needed by different parts of + * the code. + */ +struct tpm_info_t +{ + tpm_op_types_t operation; ///< TPM operation to perform + TARGETING::EntityPath i2cMasterPath; ///< I2C Master path + TARGETING::Target * i2cTarget; ///< I2C Target + + uint8_t port; ///< I2C Master port + uint8_t engine; ///< I2C Master engine + uint8_t chip; ///< Chip target, primary/backup + uint8_t tpmEnabled; ///< TPM attribute defined as available + uint8_t devAddr; ///< I2C Address + size_t offset; ///< TPM Device register offset + tpm_addr_size_t addrSize; ///< I2C Addr size +}; + /** * * @brief Determine if targeted TPM is present and enabled in the system @@ -63,6 +92,23 @@ enum tpm_op_types_t bool tpmPresence ( TARGETING::Target * i_target, tpm_chip_types_t i_chip ); +/** + * @brief this function will read all of the associated attributes needed + * to access the intended TPM. These attributes will be used to + * determine the type of I2C device as well as how to address it via + * the I2C device driver. + * + * @param[in] i_target target node. + * + * @param[in/out] io_tpmInfo The structure that will contain the attribute data + * read from the target device. Chip field must be set + * + * @return errlHndl_t NULL if successful, otherwise a pointer to the + * error log. + */ +errlHndl_t tpmReadAttributes ( TARGETING::Target * i_target, + tpm_info_t & io_tpmInfo ); + }; // end namespace TPMDD diff --git a/src/include/usr/secureboot/trustedboot_reasoncodes.H b/src/include/usr/secureboot/trustedboot_reasoncodes.H index 53fb6f8fc..4ee9a16e1 100644 --- a/src/include/usr/secureboot/trustedboot_reasoncodes.H +++ b/src/include/usr/secureboot/trustedboot_reasoncodes.H @@ -33,7 +33,11 @@ namespace TRUSTEDBOOT { MOD_HOST_UPDATE_MASTER_TPM = 0x00, MOD_TPM_INITIALIZE = 0x01, - }; + MOD_TPM_CMD_STARTUP = 0x02, + MOD_TPM_CMD_GETCAPFWVERSION = 0x03, + MOD_TPM_MARSHALCMDDATA = 0x04, + MOD_TPM_UNMARSHALRESPDATA = 0x05, + }; enum TRUSTEDReasonCode { @@ -41,6 +45,14 @@ namespace TRUSTEDBOOT RC_TPM_START_FAIL = SECURE_COMP_ID | 0xA0, RC_TPM_EXISTENCE_FAIL = SECURE_COMP_ID | 0xA1, + RC_TPM_GETCAP_FAIL = SECURE_COMP_ID | 0xA2, + RC_TPM_GETCAP_FW_INVALID_RESP = SECURE_COMP_ID | 0xA3, + RC_TPM_GETCAP2_FAIL = SECURE_COMP_ID | 0xA4, + RC_TPM_GETCAP2_FW_INVALID_RESP = SECURE_COMP_ID | 0xA5, + RC_TPM_MARSHAL_INVALID_CMD = SECURE_COMP_ID | 0xA6, + RC_TPM_MARSHALING_FAIL = SECURE_COMP_ID | 0xA7, + RC_TPM_UNMARSHAL_INVALID_CMD = SECURE_COMP_ID | 0xA8, + RC_TPM_UNMARSHALING_FAIL = SECURE_COMP_ID | 0xA9, }; } diff --git a/src/include/usr/secureboot/trustedbootif.H b/src/include/usr/secureboot/trustedbootif.H index d59cd1e14..dea32b959 100644 --- a/src/include/usr/secureboot/trustedbootif.H +++ b/src/include/usr/secureboot/trustedbootif.H @@ -45,13 +45,14 @@ namespace TRUSTEDBOOT TARGETING::Target* nodeTarget; ///< Node target ptr TPMDD::tpm_chip_types_t chip; ///< Chip Pri vs Backup uint8_t initAttempted:1;///< Has TPM init been run + uint8_t available:1; ///< Is TPM physically in system uint8_t failed:1; ///< Is TPM currently failed mutex_t tpmMutex; ///< TPM Mutex TpmTarget(); }; - /// TPM PCR designations + /// TPM PCR designations enum TPM_Pcr { PCR_0 = 0, @@ -73,7 +74,7 @@ namespace TRUSTEDBOOT void* host_update_master_tpm( void *io_pArgs ); /** - * @brief Extend a measurement into the TPMs and log + * @brief Extend a measurement into the TPMs and log atomically * @param[in] i_pcr PCR to write to * @param[in] i_digest Digest value to write to PCR * @param[in] i_digestSize Byte size of i_digest data diff --git a/src/makefile b/src/makefile index f581ebafb..ec511c80d 100644 --- a/src/makefile +++ b/src/makefile @@ -204,6 +204,7 @@ TESTCASE_MODULES += $(if $(CONFIG_VPO_COMPILE),,testruntime) TESTCASE_MODULES += testibscom TESTCASE_MODULES += $(if $(CONFIG_VPO_COMPILE),,testdump) TESTCASE_MODULES += $(if $(CONFIG_VPO_COMPILE),,testsecureboot) +TESTCASE_MODULES += $(if $(CONFIG_TPMDD),testtrusted) TESTCASE_MODULES += testfsiscom TESTCASE_MODULES += testrtloader TESTCASE_MODULES += testsbe diff --git a/src/usr/i2c/test/tpmddtest.H b/src/usr/i2c/test/tpmddtest.H index 74f71b28e..4053245a6 100755 --- a/src/usr/i2c/test/tpmddtest.H +++ b/src/usr/i2c/test/tpmddtest.H @@ -38,9 +38,10 @@ #include #include #include +#include "secureboot/trustedbootif.H" #include "i2ctest.H" #include "../tpmdd.H" -#include "../../secureboot/trusted/trustedboot.H" +#include "../../secureboot/trusted/trustedTypes.H" extern trace_desc_t* g_trac_tpmdd; @@ -541,16 +542,16 @@ class TPMDDTest: public CxxTest::TestSuite memset(data, 0xFE, sizeof(data)); TRUSTEDBOOT::TPM2_GetCapabilityIn* cmd = - (TRUSTEDBOOT::TPM2_GetCapabilityIn*)data; + reinterpret_cast + (data); - cmd->base.tag = TRUSTEDBOOT::TPM_ST_NO_SESSIONS; cmd->base.commandSize = sizeof (TRUSTEDBOOT::TPM2_GetCapabilityIn); + cmd->base.tag = TRUSTEDBOOT::TPM_ST_NO_SESSIONS; cmd->base.commandCode = TRUSTEDBOOT::TPM_CC_GetCapability; cmd->capability = TRUSTEDBOOT::TPM_CAP_TPM_PROPERTIES; cmd->property = TRUSTEDBOOT::TPM_PT_MANUFACTURER; cmd->propertyCount = 1; - cmdSize = cmd->base.commandSize; num_ops++; @@ -623,97 +624,12 @@ class TPMDDTest: public CxxTest::TestSuite continue; } - // Build our command block for a startup - memset(data, 0xFE, sizeof(data)); - - // Test a TPM command underflow - TRUSTEDBOOT::TPM2_GetCapabilityIn* cmd = - (TRUSTEDBOOT::TPM2_GetCapabilityIn*)data; - - cmd->base.tag = TRUSTEDBOOT::TPM_ST_NO_SESSIONS; - cmd->base.commandSize = - sizeof (TRUSTEDBOOT::TPM2_GetCapabilityIn); - cmd->base.commandCode = TRUSTEDBOOT::TPM_CC_GetCapability; - cmd->capability = TRUSTEDBOOT::TPM_CAP_TPM_PROPERTIES; - cmd->property = TRUSTEDBOOT::TPM_PT_MANUFACTURER; - cmd->propertyCount = 1; - - cmdSize = cmd->base.commandSize; - - num_ops++; - err = deviceRead(testTarget, - &data, - dataSize, - DEVICE_TPM_ADDRESS( TPM_PRIMARY, - TPM_OP_TRANSMIT, - cmdSize - 1) ); - - if( NULL == err || - err->reasonCode() != TPM_UNDERFLOW_ERROR) - { - fails++; - TS_FAIL( "testTPMTransmitOverUnder - Error " - "command underflow not detected" ); - errlCommit( err, - TPMDD_COMP_ID ); - delete err; - err = NULL; - } - else - { - TRACUCOMP(g_trac_tpmdd, "testTPMTransmitOverUnder - " - "CmdUnder Transmit returned as expected. len=%d", - dataSize); - } - - - // Build our command block for a startup - dataSize = sizeof(data); - memset(data, 0xFE, sizeof(data)); - - // Test a TPM command overflow - - cmd->base.tag = TRUSTEDBOOT::TPM_ST_NO_SESSIONS; - cmd->base.commandSize = - sizeof (TRUSTEDBOOT::TPM2_GetCapabilityIn); - cmd->base.commandCode = TRUSTEDBOOT::TPM_CC_GetCapability; - cmd->capability = TRUSTEDBOOT::TPM_CAP_TPM_PROPERTIES; - cmd->property = TRUSTEDBOOT::TPM_PT_MANUFACTURER; - cmd->propertyCount = 1; - - cmdSize = cmd->base.commandSize; - - num_ops++; - err = deviceRead(testTarget, - &data, - dataSize, - DEVICE_TPM_ADDRESS( TPM_PRIMARY, - TPM_OP_TRANSMIT, - cmdSize + 1) ); - - if( NULL == err || - err->reasonCode() != TPM_OVERFLOW_ERROR) - { - fails++; - TS_FAIL( "testTPMTransmitOverUnder - Error " - "command overflow not detected" ); - errlCommit( err, - TPMDD_COMP_ID ); - delete err; - err = NULL; - } - else - { - TRACUCOMP(g_trac_tpmdd, "testTPMTransmitOverUnder - " - "CmdOver Transmit returned as expected. len=%d", - dataSize); - } - - // Build our command block for a startup dataSize = sizeof(data); memset(data, 0xFE, sizeof(data)); // Test a TPM data overflow + TRUSTEDBOOT::TPM2_GetCapabilityIn* cmd = + reinterpret_cast(data); cmd->base.tag = TRUSTEDBOOT::TPM_ST_NO_SESSIONS; cmd->base.commandSize = diff --git a/src/usr/i2c/tpmdd.C b/src/usr/i2c/tpmdd.C index 16748c4b3..ef34ba2b7 100755 --- a/src/usr/i2c/tpmdd.C +++ b/src/usr/i2c/tpmdd.C @@ -154,16 +154,6 @@ errlHndl_t tpmPerformOp( DeviceFW::OperationType i_opType, - // Get i2c master target - err = tpmGetI2CMasterTarget( i_target, - tpmInfo ); - - if( err ) - { - break; - } - - // Lock to sequence operations mutex_lock( &g_tpmMutex ); unlock = true; @@ -326,21 +316,6 @@ bool tpmPresence ( TARGETING::Target * i_target, break; } - // Get i2c master target - err = tpmGetI2CMasterTarget( i_target, - tpmInfo ); - - if( err ) - { - TRACFCOMP(g_trac_tpmdd, - ERR_MRK"Error in tpmPresence::tpmGetI2Cmaster() " - "RC 0x%X", err->reasonCode()); - l_present = false; - delete err; - err = NULL; - break; - } - // Ensure the TPM is enabled if (!tpmInfo.tpmEnabled) { @@ -1267,6 +1242,19 @@ errlHndl_t tpmReadAttributes ( TARGETING::Target * i_target, } + // Get i2c master target + err = tpmGetI2CMasterTarget( i_target, + io_tpmInfo ); + + if( err ) + { + TRACFCOMP(g_trac_tpmdd, + ERR_MRK"Error in tpmReadAttributes::tpmGetI2Cmaster() " + "RC 0x%X", err->reasonCode()); + break; + } + + } while( 0 ); TRACUCOMP(g_trac_tpmdd,"tpmReadAttributes() tgt=0x%X, %d/%d/0x%X " @@ -1320,9 +1308,9 @@ errlHndl_t tpmGetI2CMasterTarget ( TARGETING::Target * i_target, { // Path element: type:8 instance:8 l_epCompressed |= - io_tpmInfo.i2cMasterPath[i].type << (16*(3-i)); + io_tpmInfo.i2cMasterPath[i].type << ((16*(3-i))+8); l_epCompressed |= - io_tpmInfo.i2cMasterPath[i].instance << ((16*(3-i))-8); + io_tpmInfo.i2cMasterPath[i].instance << (16*(3-i)); // Can only fit 4 path elements into 64 bits if ( i == 3 ) @@ -1374,9 +1362,9 @@ errlHndl_t tpmGetI2CMasterTarget ( TARGETING::Target * i_target, { // Path element: type:8 instance:8 l_epCompressed |= - io_tpmInfo.i2cMasterPath[i].type << (16*(3-i)); + io_tpmInfo.i2cMasterPath[i].type << ((16*(3-i))+8); l_epCompressed |= - io_tpmInfo.i2cMasterPath[i].instance << ((16*(3-i))-8); + io_tpmInfo.i2cMasterPath[i].instance << (16*(3-i)); // Can only fit 4 path elements into 64 bits if ( i == 3 ) diff --git a/src/usr/i2c/tpmdd.H b/src/usr/i2c/tpmdd.H index c81e436d4..ad531d67d 100755 --- a/src/usr/i2c/tpmdd.H +++ b/src/usr/i2c/tpmdd.H @@ -41,15 +41,6 @@ namespace TPMDD { -/** -* @brief Enumerations to describe the type of devices to be accessed. -*/ -enum tpm_addr_size_t -{ - ONE_BYTE_ADDR = 1, - TWO_BYTE_ADDR = 2, - LAST_DEVICE_TYPE -}; /// TPM Timeouts listed in ms /// Timeout names and durations are as described in the TCG specification @@ -67,24 +58,6 @@ enum MAX_STSVALID_POLLS = 5, ///< Max poll of 50ms (5*10ms) }; -/** - * @brief Structure of common parameters needed by different parts of - * the code. - */ -struct tpm_info_t -{ - tpm_op_types_t operation; ///< TPM operation to perform - uint64_t port; ///< I2C Master port - uint64_t engine; ///< I2C Master engin - tpm_addr_size_t addrSize; ///< I2C Addr size - TARGETING::EntityPath i2cMasterPath; ///< I2C Master path - TARGETING::Target * i2cTarget; ///< I2C Target - - uint8_t chip; ///< Chip target, primary/backup - uint8_t tpmEnabled; ///< Is this TPM available and functional? - uint8_t devAddr; ///< I2C Address - size_t offset; ///< TPM Device register offset -}; @@ -256,23 +229,6 @@ errlHndl_t tpmPrepareAddress ( void * io_buffer, size_t & o_bufSize, tpm_info_t i_tpmInfo ); -/** - * @brief this function will read all of the associated attributes needed - * to access the intended TPM. These attributes will be used to - * determine the type of I2C device as well as how to address it via - * the I2C device driver. - * - * @param[in] i_target target node. - * - * @param[in/out] io_tpmInfo The structure that will contain the attribute data - * read from the target device. - * - * @return errlHndl_t NULL if successful, otherwise a pointer to the - * error log. - */ -errlHndl_t tpmReadAttributes ( TARGETING::Target * i_target, - tpm_info_t & io_tpmInfo ); - /** * @brief This function decides whether or not the target passed into the * TPM device driver actually contains the I2C Master engines. If diff --git a/src/usr/secureboot/trusted/base/trustedboot_base.C b/src/usr/secureboot/trusted/base/trustedboot_base.C index 95a55fdc2..d7d3295cb 100644 --- a/src/usr/secureboot/trusted/base/trustedboot_base.C +++ b/src/usr/secureboot/trusted/base/trustedboot_base.C @@ -65,6 +65,7 @@ SystemTpms::SystemTpms() TpmTarget::TpmTarget() { memset(this, 0, sizeof(TpmTarget)); + available = true; // Default to available until we know better mutex_init(&tpmMutex); } diff --git a/src/usr/secureboot/trusted/makefile b/src/usr/secureboot/trusted/makefile index 00991ed0f..fec117924 100644 --- a/src/usr/secureboot/trusted/makefile +++ b/src/usr/secureboot/trusted/makefile @@ -26,6 +26,10 @@ ROOTPATH = ../../../.. MODULE = secureboot_trusted OBJS += $(if $(CONFIG_TPMDD),trustedboot.o,) +OBJS += $(if $(CONFIG_TPMDD),trustedbootCmds.o,) +OBJS += $(if $(CONFIG_TPMDD),trustedTypes.o,) + +SUBDIRS += $(if $(CONFIG_TPMDD),test.d,) CFLAGS += -iquote ../ include ${ROOTPATH}/config.mk diff --git a/src/usr/secureboot/trusted/test/makefile b/src/usr/secureboot/trusted/test/makefile new file mode 100644 index 000000000..3345252a6 --- /dev/null +++ b/src/usr/secureboot/trusted/test/makefile @@ -0,0 +1,30 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/secureboot/trusted/test/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2015 +# [+] 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 +ROOTPATH = ../../../../.. + +MODULE = testtrusted +TESTS += $(if $(CONFIG_TPMDD),trustedbootTest.H,) + +include ${ROOTPATH}/config.mk \ No newline at end of file diff --git a/src/usr/secureboot/trusted/test/trustedbootTest.H b/src/usr/secureboot/trusted/test/trustedbootTest.H new file mode 100755 index 000000000..de2a2d8ed --- /dev/null +++ b/src/usr/secureboot/trusted/test/trustedbootTest.H @@ -0,0 +1,529 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/trusted/test/trustedbootTest.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015 */ +/* [+] 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 */ +#ifndef __TRUSTEDBOOTTEST_H +#define __TRUSTEDBOOTTEST_H + +/** + * @file trustedbootTest.H + * + * @brief Test cases for trustedboot + */ + +#include +#include +#include +#include +#include +#include +#include +#include "../trustedTypes.H" +#include "../trustedboot.H" + +extern trace_desc_t* g_trac_trustedboot; + +// Easy macro replace for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) +//#define TRACUBIN(args...) TRACFBIN(args) +#define TRACUBIN(args...) + + +using namespace TRUSTEDBOOT; + + +class TrustedBootTest: public CxxTest::TestSuite +{ + public: + + + /** + * @brief Helper to run failing marshal tests + */ + void runTpmMarshalFailTest(TRUSTEDBOOT::TPM2_BaseIn* i_cmd, + uint8_t* o_outbuf, + size_t i_bufsize, + size_t & o_cmdSize, + const char* i_testName, + int64_t & io_num_ops, + int64_t & io_fails) + { + errlHndl_t err = NULL; + + err = tpmMarshalCommandData(i_cmd, + o_outbuf, + i_bufsize, + o_cmdSize); + io_num_ops++; + if (NULL == err) + { + io_fails++; + TS_FAIL( "runTpmMarshalFailTest(%s) - Error not detected", + i_testName); + } + else + { + delete err; + err = NULL; + } + + } + /** + * @brief Helper to run marshal tests + */ + void runTpmMarshalTest(TRUSTEDBOOT::TPM2_BaseIn* i_cmd, + uint8_t* o_outbuf, + size_t i_bufsize, + size_t & o_cmdSize, + const char* i_testName, + int64_t & io_num_ops, + int64_t & io_fails, + size_t i_expSize) + { + errlHndl_t err = NULL; + TRUSTEDBOOT::TPM2_BaseIn* baseCmd = + reinterpret_cast(o_outbuf); + + do + { + + + err = tpmMarshalCommandData(i_cmd, + o_outbuf, + i_bufsize, + o_cmdSize); + io_num_ops++; + if (NULL != err) + { + io_fails++; + TS_FAIL( "runTpmMarshalTest(%s) - Error detected", i_testName); + errlCommit( err, + TPMDD_COMP_ID ); + delete err; + err = NULL; + break; + } + io_num_ops++; + if (o_cmdSize == 0 || + o_cmdSize != baseCmd->commandSize || + o_cmdSize != i_expSize) + { + io_fails++; + TS_FAIL( "runTpmMarshalTest(%s) - Size Mismatch " + "oC %d aC %d Exp %d", + i_testName, o_cmdSize, + baseCmd->commandSize, i_expSize); + break; + } + + // Try some that should fail + err = tpmMarshalCommandData(i_cmd, + o_outbuf, + i_expSize-1, + o_cmdSize); + io_num_ops++; + if (NULL == err) + { + io_fails++; + TS_FAIL( "runTpmMarshalTest(%s) - Size-1 error not detected", + i_testName); + break; + } + else + { + delete err; + err = NULL; + } + + err = tpmMarshalCommandData(i_cmd, + o_outbuf, + i_expSize/2, + o_cmdSize); + io_num_ops++; + if (NULL == err) + { + io_fails++; + TS_FAIL( "runTpmMarshalTest(%s) - Size/2 error not detected", + i_testName); + break; + } + else + { + delete err; + err = NULL; + } + + err = tpmMarshalCommandData(i_cmd, + o_outbuf, + i_expSize/3, + o_cmdSize); + io_num_ops++; + if (NULL == err) + { + io_fails++; + TS_FAIL( "runTpmMarshalTest(%s) - Size/3 error not detected", + i_testName); + break; + } + else + { + delete err; + err = NULL; + } + + } while( 0 ); + } + + + /** + * @brief Helper to run failing unmarshal tests + */ + void runTpmUnmarshalFailTest(uint32_t i_commandCode, + uint8_t* i_respBuf, + size_t i_respBufSize, + TRUSTEDBOOT::TPM2_BaseOut* o_outBuf, + size_t i_outBufSize, + const char* i_testName, + int64_t & io_num_ops, + int64_t & io_fails) + { + errlHndl_t err = NULL; + + err = tpmUnmarshalResponseData(i_commandCode, + i_respBuf, + i_respBufSize, + o_outBuf, + i_outBufSize); + io_num_ops++; + if (NULL == err) + { + io_fails++; + TS_FAIL( "runTpmUnmarshalFailTest(%s) - Error not detected", + i_testName); + } + else + { + delete err; + err = NULL; + } + + } + /** + * @brief Helper to run unmarshal tests + */ + void runTpmUnmarshalTest(uint32_t i_commandCode, + uint8_t* i_respBuf, + size_t i_respBufSize, + TRUSTEDBOOT::TPM2_BaseOut* o_outBuf, + size_t i_outBufSize, + const char* i_testName, + int64_t & io_num_ops, + int64_t & io_fails) + { + errlHndl_t err = NULL; + + do + { + + + err = tpmUnmarshalResponseData(i_commandCode, + i_respBuf, + i_respBufSize, + o_outBuf, + i_outBufSize); + io_num_ops++; + if (NULL != err) + { + io_fails++; + TS_FAIL( "runTpmUnmarshalTest(%s) - Error detected", + i_testName); + errlCommit( err, + TPMDD_COMP_ID ); + delete err; + err = NULL; + break; + } + + // Try some that should fail + err = tpmUnmarshalResponseData(i_commandCode, + i_respBuf, + 4, + o_outBuf, + i_outBufSize); + io_num_ops++; + if (NULL == err) + { + io_fails++; + TS_FAIL( "runTpmUnmarshalTest(%s) - " + "RespBuf Size=4 error not detected", + i_testName); + break; + } + else + { + delete err; + err = NULL; + } + + // If the response output buffer is more then just the base we + // can do another failing size verif + if (i_outBufSize > sizeof(TPM2_BaseOut)) + { + err = tpmUnmarshalResponseData(i_commandCode, + i_respBuf, + sizeof(TPM2_BaseOut), + o_outBuf, + i_outBufSize); + io_num_ops++; + if (NULL == err) + { + io_fails++; + TS_FAIL( "runTpmUnmarshalTest(%s) - " + "RespBuf Size=10 error not detected", + i_testName); + break; + } + else + { + delete err; + err = NULL; + } + } + + err = tpmUnmarshalResponseData(i_commandCode, + i_respBuf, + i_respBufSize, + o_outBuf, + 4); + io_num_ops++; + if (NULL == err) + { + io_fails++; + TS_FAIL( "runTpmUnmarshalTest(%s) - " + "OutBuf Size=4 error not detected", + i_testName); + break; + } + else + { + delete err; + err = NULL; + } + + if (i_outBufSize > sizeof(TPM2_BaseOut)) + { + err = tpmUnmarshalResponseData(i_commandCode, + i_respBuf, + i_respBufSize, + o_outBuf, + sizeof(TPM2_BaseOut)); + io_num_ops++; + if (NULL == err) + { + io_fails++; + TS_FAIL( "runTpmUnmarshalTest(%s) - " + "OutBuf Size=10 error not detected", + i_testName); + break; + } + else + { + delete err; + err = NULL; + } + } + + } while( 0 ); + } + + + /** + * @brief Test command marshaling + */ + void testCommandMarshal ( void ) + { + int64_t fails = 0, num_ops = 0; + uint8_t dataBufIn[BUFSIZE]; + uint8_t dataBufOut[BUFSIZE]; + size_t cmdSize = 0; + TRUSTEDBOOT::TPM2_BaseIn* baseCmd = + reinterpret_cast(dataBufIn); + + TRACFCOMP( g_trac_trustedboot, + "testCommandMarshal - Start" ); + do + { + + // Unsupported command + { + memset(dataBufIn, 0, sizeof(dataBufIn)); + memset(dataBufOut, 0, sizeof(dataBufOut)); + baseCmd->commandCode = 0x12345; + + runTpmMarshalFailTest(baseCmd, + dataBufOut, + sizeof(dataBufOut), + cmdSize, + "Unsupported command", + num_ops, + fails); + } + + // Test 2ByteIn with Startup command + { + memset(dataBufIn, 0, sizeof(dataBufIn)); + memset(dataBufOut, 0, sizeof(dataBufOut)); + TRUSTEDBOOT::TPM2_2ByteIn* cmdPtr = + reinterpret_cast(dataBufIn); + cmdPtr->base.commandCode = TRUSTEDBOOT::TPM_CC_Startup; + + runTpmMarshalTest(baseCmd, + dataBufOut, + sizeof(dataBufOut), + cmdSize, + "2ByteIn", + num_ops, + fails, + sizeof(TPM2_2ByteIn)); + } + + // Test GetCapabilityIn + { + memset(dataBufIn, 0, sizeof(dataBufIn)); + memset(dataBufOut, 0, sizeof(dataBufOut)); + TRUSTEDBOOT::TPM2_GetCapabilityIn* cmdPtr = + reinterpret_cast + (dataBufIn); + cmdPtr->base.commandCode = TRUSTEDBOOT::TPM_CC_GetCapability; + + runTpmMarshalTest(baseCmd, + dataBufOut, + sizeof(dataBufOut), + cmdSize, + "GetCapabilityIn", + num_ops, + fails, + sizeof(TPM2_GetCapabilityIn)); + } + + + + } while( 0 ); + TRACFCOMP( g_trac_trustedboot, + "testCommandMarshal - End: %d/%d fails", + fails, num_ops ); + + } + + /** + * @brief Test command unmarshaling + */ + void testCommandUnmarshal ( void ) + { + int64_t fails = 0, num_ops = 0; + uint8_t dataBufIn[BUFSIZE]; + uint8_t dataBufOut[BUFSIZE]; + TRUSTEDBOOT::TPM2_BaseOut* baseCmd = + reinterpret_cast(dataBufOut); + + TRACFCOMP( g_trac_trustedboot, + "testCommandUnmarshal - Start" ); + do + { + + // Unsupported command + { + memset(dataBufIn, 0, sizeof(dataBufIn)); + memset(dataBufOut, 0, sizeof(dataBufOut)); + + runTpmUnmarshalFailTest(0x12345, + dataBufIn, + sizeof(dataBufIn), + baseCmd, + sizeof(dataBufOut), + "Unsupported command", + num_ops, + fails); + } + + // Test BaseOut with Startup command + { + memset(dataBufIn, 0, sizeof(dataBufIn)); + memset(dataBufOut, 0, sizeof(dataBufOut)); + + runTpmUnmarshalTest(TRUSTEDBOOT::TPM_CC_Startup, + dataBufIn, + sizeof(dataBufIn), + baseCmd, + sizeof(TPM2_BaseOut), + "BaseOut", + num_ops, + fails); + } + + // Test GetCapabilityOut + { + memset(dataBufIn, 0, sizeof(dataBufIn)); + memset(dataBufOut, 0, sizeof(dataBufOut)); + + // Test will fail because we haven't set the capability + runTpmUnmarshalFailTest(TRUSTEDBOOT::TPM_CC_GetCapability, + dataBufIn, + sizeof(dataBufIn), + baseCmd, + sizeof(TPM2_GetCapabilityOut), + "GetCapabilityOut - invalid cap", + num_ops, + fails); + + // Set the capability coming from the TPM + TRUSTEDBOOT::TPM2_GetCapabilityOut* respPtr = + reinterpret_cast + (dataBufIn); + respPtr->capData.capability = + TRUSTEDBOOT::TPM_CAP_TPM_PROPERTIES; + + runTpmUnmarshalTest(TRUSTEDBOOT::TPM_CC_GetCapability, + dataBufIn, + sizeof(dataBufIn), + baseCmd, + sizeof(TPM2_GetCapabilityOut), + "GetCapabilityOut", + num_ops, + fails); + } + + + + } while( 0 ); + TRACFCOMP( g_trac_trustedboot, + "testCommandUnmarshal - End: %d/%d fails", + fails, num_ops ); + + } + + +}; + +#endif diff --git a/src/usr/secureboot/trusted/trustedTypes.C b/src/usr/secureboot/trusted/trustedTypes.C new file mode 100644 index 000000000..404a56860 --- /dev/null +++ b/src/usr/secureboot/trusted/trustedTypes.C @@ -0,0 +1,219 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/trusted/trustedTypes.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015 */ +/* [+] 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 trustedTypes.C + * + * @brief Trusted boot type inline functions + */ + +// ---------------------------------------------- +// Includes +// ---------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include "trustedTypes.H" + +extern trace_desc_t* g_trac_trustedboot; + +// Easy macro replace for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + +namespace TRUSTEDBOOT +{ + + uint32_t getDigestSize(TPM_Alg_Id i_algId) + { + uint32_t ret = 0; + switch (i_algId) + { + case TPM_ALG_SHA1: + ret = TPM_ALG_SHA1_SIZE; + break; + case TPM_ALG_SHA256: + ret = TPM_ALG_SHA256_SIZE; + break; + default: + ret = 0; + break; + }; + return ret; + } + + uint8_t* unmarshalChunk(uint8_t* i_tpmBuf, + size_t & io_tpmBufSize, + void* o_chunkPtr, + size_t i_chunkSize) + { + if (NULL != i_tpmBuf) + { + if (i_chunkSize > io_tpmBufSize) + { + return NULL; + } + memcpy(o_chunkPtr, i_tpmBuf, i_chunkSize); + i_tpmBuf += i_chunkSize; + io_tpmBufSize -= i_chunkSize; + } + return i_tpmBuf; + } + + uint8_t* marshalChunk(uint8_t* o_tpmBuf, + size_t i_tpmBufSize, + size_t & io_cmdSize, + void* i_chunkPtr, + size_t i_chunkSize) + { + if (NULL != o_tpmBuf) + { + if ((io_cmdSize + i_chunkSize) > i_tpmBufSize) + { + return NULL; + } + memcpy(o_tpmBuf, i_chunkPtr, i_chunkSize); + o_tpmBuf += i_chunkSize; + io_cmdSize += i_chunkSize; + } + return o_tpmBuf; + } + + uint8_t* TPML_TAGGED_TPM_PROPERTY::unmarshal(uint8_t* i_tpmBuf, + size_t & io_tpmBufSize, + size_t i_outBufSize) + { + + i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize, + &count, sizeof(count)); + + // Now we know the count as well + i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize, + &(tpmProperty[0]), + sizeof(TPMS_TAGGED_PROPERTY) * count); + + return i_tpmBuf; + } + + uint8_t* TPMS_CAPABILITY_DATA::unmarshal(uint8_t* i_tpmBuf, + size_t & io_tpmBufSize, + size_t i_outBufSize) + { + i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize, + &capability, sizeof(capability)); + + switch (capability) + { + case TRUSTEDBOOT::TPM_CAP_TPM_PROPERTIES: + { + return data.tpmProperties.unmarshal(i_tpmBuf, io_tpmBufSize, + i_outBufSize); + } + break; + default: + { + TRACFCOMP( g_trac_trustedboot, + "TPMS_CAPABILITY_DATA::unmarshal Unknown capability"); + return NULL; + } + break; + } + return NULL; + } + + size_t TPML_DIGEST_VALUES::marshalSize() const + { + size_t ret = sizeof(count); + for (size_t idx = 0; (idx < count && idx < HASH_COUNT); idx++) + { + ret += digests[idx].marshalSize(); + } + return ret; + } + + uint8_t* TPM2_BaseIn::marshal(uint8_t* o_tpmBuf, size_t i_tpmBufSize, + size_t & io_cmdSize) + { + return marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + this, sizeof(TPM2_BaseIn)); + } + + uint8_t* TPM2_BaseOut::unmarshal(uint8_t* i_tpmBuf, size_t & io_tpmBufSize, + size_t i_outBufSize) + { + if (sizeof(TPM2_BaseOut) > i_outBufSize) + { + return NULL; + } + return unmarshalChunk(i_tpmBuf, io_tpmBufSize, + this, sizeof(TPM2_BaseOut)); + } + + uint8_t* TPM2_2ByteIn::marshal(uint8_t* o_tpmBuf, + size_t i_tpmBufSize, + size_t & io_cmdSize) + { + // Base has already been marshaled + return marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + ¶m, sizeof(param)); + } + + + uint8_t* TPM2_GetCapabilityIn::marshal(uint8_t* o_tpmBuf, + size_t i_tpmBufSize, + size_t& io_cmdSize) + { + // Base has already been marshaled + o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + &capability, sizeof(capability)); + o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + &property, sizeof(property)); + o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize, + &propertyCount, sizeof(propertyCount)); + return o_tpmBuf; + } + + uint8_t* TPM2_GetCapabilityOut::unmarshal(uint8_t* i_tpmBuf, + size_t & io_tpmBufSize, + size_t i_outBufSize) + { + // Base has already been unmarshaled + if (sizeof(TPM2_GetCapabilityOut) > i_outBufSize) + { + return NULL; + } + i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize, + &moreData, sizeof(moreData)); + + // Capability data block + return capData.unmarshal(i_tpmBuf, io_tpmBufSize, i_outBufSize); + + } + + +} // end TRUSTEDBOOT diff --git a/src/usr/secureboot/trusted/trustedTypes.H b/src/usr/secureboot/trusted/trustedTypes.H new file mode 100644 index 000000000..c32128a60 --- /dev/null +++ b/src/usr/secureboot/trusted/trustedTypes.H @@ -0,0 +1,297 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/trusted/trustedTypes.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015 */ +/* [+] 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 trustedTypes.H + * + * @brief Trustedboot TPM Types + * + */ +#ifndef __TRUSTEDTYPES_H +#define __TRUSTEDTYPES_H +// ----------------------------------------------- +// Includes +// ----------------------------------------------- +#include + +namespace TRUSTEDBOOT +{ + + + + /// TPM Algorithm defines + enum TPM_Alg_Id + { + TPM_ALG_SHA1 = 0x0004, + TPM_ALG_SHA256 = 0x000B, + }; + + /// Common static values + enum + { + MAX_SYSTEM_TPMS = 2, + TPM_MASTER_INDEX = 0, ///< Index into tpm array for master chip + TPM_BACKUP_INDEX = 1, ///< Index for backup TPM + MAX_TPM_LOG_MSG = 128, ///< Maximum log message size + + HASH_COUNT = 1, ///< Maximum # of digests + TPM_ALG_SHA1_SIZE = 20, ///< SHA1 digest byte size + TPM_ALG_SHA256_SIZE = 32, ///< SHA256 digest byte size + + // Event types + EV_NO_ACTION = 0x3, ///< Event field contains info + EV_ACTION = 0x5, ///< Must extend a PCR + + }; + + /// Class object to store system TPM information + class SystemTpms + { + public: + SystemTpms(); + + TpmTarget tpm[MAX_SYSTEM_TPMS]; + }; + + /** + * @brief Get the digest size of the selected hash algorithm + * @param[in] i_algId Algorith ID to query + * @returns digest length in bytes, 0 on invalid algorithm + */ + uint32_t getDigestSize(TPM_Alg_Id i_algId); + + + /// Various static values + enum + { + // TPM Spec supported + TPM_SPEC_MAJOR = 2, + TPM_SPEC_MINOR = 0, + TPM_SPEC_ERRATA = 0, + TPM_PLATFORM_SERVER = 1, + + // Command structure tags + TPM_ST_NO_SESSIONS = 0x8001, ///< A command with no sess/auth + TPM_ST_SESSIONS = 0x8002, ///< A command has sessions + + // Command Codes + TPM_CC_Startup = 0x00000144, + TPM_CC_GetCapability = 0x0000017A, + TPM_CC_PCR_Read = 0x0000017E, + TPM_CC_PCR_Extend = 0x00000182, + + + // TPM Startup types + TPM_SU_CLEAR = 0x0000,///< TPM perform reset,restart + TPM_SU_STATE = 0x0001,///< TPM perform restore saved state + + // Capability + MAX_TPM_PROPERTIES = 2, + TPM_CAP_TPM_PROPERTIES = 0x00000006, ///< Pull TPM Properties + + // TPM Properties + TPM_PT_MANUFACTURER = 0x00000105, + TPM_PT_FIRMWARE_VERSION_1 = 0x0000010B, + TPM_PT_FIRMWARE_VERSION_2 = 0x0000010C, + + + // TPM Return Codes + TPM_SUCCESS = 0x000, + + TPM_RC_INITIALIZE = 0x100, + + }; + + + // Command structures taken from Trusted Platform Module Library Part 3: + // Commands Family "2.0" + + /// TPM capability response structure + struct TPMS_TAGGED_PROPERTY + { + uint32_t property; ///< TPM_PT_xx identifier + uint32_t value; ///< value of the property + } PACKED; + + struct TPML_TAGGED_TPM_PROPERTY + { + uint32_t count; ///< Number of properties + TPMS_TAGGED_PROPERTY tpmProperty[MAX_TPM_PROPERTIES]; + uint8_t* unmarshal(uint8_t* i_tpmBuf, size_t & io_tpmBufSize, + size_t i_outBufSize); + } PACKED; + + union TPMU_CAPABILITIES + { + // Currently only TPM properties supported + TPML_TAGGED_TPM_PROPERTY tpmProperties; + } PACKED; + + struct TPMS_CAPABILITY_DATA + { + uint32_t capability; ///< The capability type + TPMU_CAPABILITIES data; ///< The capability data + uint8_t* unmarshal(uint8_t* i_tpmBuf, size_t & io_tpmBufSize, + size_t i_outBufSize); + } PACKED; + + + /// SHA1 Event log entry format + struct TCG_PCR_EVENT + { + uint32_t pcrIndex; ///< PCRIndex event extended to + uint32_t eventType; ///< Type of event + uint8_t digest[20]; ///< Value extended into PCR index + uint32_t eventSize; ///< Size of event data + uint8_t event[0]; ///< The event data + + inline size_t marshalSize() const + { return (sizeof(TCG_PCR_EVENT) + eventSize); } + + } PACKED; + + /// Digest union + union TPMU_HA + { + uint8_t sha1[TPM_ALG_SHA1_SIZE]; + uint8_t sha256[TPM_ALG_SHA256_SIZE]; + } PACKED; + + /// Crypto agile digest + struct TPMT_HA + { + uint16_t algorithmId; ///< ID of hashing algorithm + TPMU_HA digest; ///< Digest, depends on algorithmid + inline size_t marshalSize() const; + } PACKED; + + inline size_t TPMT_HA::marshalSize() const + { + return (sizeof(TPMT_HA) - sizeof(TPMU_HA) + + getDigestSize((TPM_Alg_Id)algorithmId)); + } + + /// Crypto agile digests list + struct TPML_DIGEST_VALUES + { + uint32_t count; ///< Number of digests + TPMT_HA digests[HASH_COUNT]; ///< Digests + size_t marshalSize() const; + } PACKED; + + /// Event field structure + struct TPM_EVENT_FIELD + { + uint32_t eventSize; ///< Size of event data + uint8_t event[MAX_TPM_LOG_MSG]; ///< The event data + /** + * @brief Return size of entire structure + */ + inline size_t marshalSize() const; + } PACKED; + inline size_t TPM_EVENT_FIELD::marshalSize() const + { + return (sizeof(eventSize) + eventSize); + } + + /// Crypto agile log entry format + struct TCG_PCR_EVENT2 + { + uint32_t pcrIndex; ///< PCRIndex event extended to + uint32_t eventType; ///< Type of event + TPML_DIGEST_VALUES digests; ///< List of digests extended to PCRIndex + TPM_EVENT_FIELD event; ///< Event information + + } PACKED; + + + struct TPM2_BaseIn + { + uint16_t tag; ///< Type TPM_ST_xx + uint32_t commandSize; ///< Total # output bytes incl cmdSize & tag + uint32_t commandCode; ///< Type TPM_CC_xx + uint8_t* marshal(uint8_t* o_tpmBuf, size_t i_tpmBufSize, + size_t & io_cmdSize); + } PACKED; + + /// Base of all outgoing messages + struct TPM2_BaseOut + { + uint16_t tag; ///< Type TPM_ST_xx + uint32_t responseSize; ///< Total # out bytes incl paramSize & tag + uint32_t responseCode; ///< The return code of the operation + uint8_t* unmarshal(uint8_t* i_tpmBuf, size_t & io_tpmBufSize, + size_t i_outBufSize); + } PACKED; + + /// Generic TPM Input Command structure with a 2 byte param + struct TPM2_2ByteIn + { + TPM2_BaseIn base; + uint16_t param; + uint8_t* marshal(uint8_t* o_tpmBuf, size_t i_tpmBufSize, + size_t & io_cmdSize); + } PACKED; + + + /// Generic TPM Output Command structure with a 4 byte return data + struct TPM2_4ByteOut + { + TPM2_BaseOut base; + uint32_t resp; + } PACKED; + + /// Incoming TPM_GetCapability structure + struct TPM2_GetCapabilityIn + { + TPM2_BaseIn base; + uint32_t capability; ///< group selection + uint32_t property; ///< Further definition + uint32_t propertyCount; ///< Number of properties to return + uint8_t* marshal(uint8_t* o_tpmBuf, size_t i_tpmBufSize, + size_t& io_cmdSize); + } PACKED; + + /// Outgoing TPM_GetCapability structure + struct TPM2_GetCapabilityOut + { + TPM2_BaseOut base; + uint8_t moreData; ///< Flag to indicate if more values available + TPMS_CAPABILITY_DATA capData; ///< The capability response + uint8_t* unmarshal(uint8_t* i_tpmBuf, size_t & io_tpmBufSize, + size_t i_outBufSize); + } PACKED; + + + /// Incoming TPM_EXTEND structure + struct TPM2_ExtendIn + { + TPM2_BaseIn base; + uint32_t pcrHandle; ///< PCR number to extend + TPML_DIGEST_VALUES digests; ///< Values to be extended + } PACKED; + +} // end TRUSTEDBOOT namespace +#endif + diff --git a/src/usr/secureboot/trusted/trustedboot.C b/src/usr/secureboot/trusted/trustedboot.C index 631448ad7..cf777d0f5 100644 --- a/src/usr/secureboot/trusted/trustedboot.C +++ b/src/usr/secureboot/trusted/trustedboot.C @@ -39,11 +39,9 @@ #include #include #include -#include -#include #include -#include #include "trustedboot.H" +#include "trustedTypes.H" #include // ---------------------------------------------- @@ -100,8 +98,13 @@ void* host_update_master_tpm( void *io_pArgs ) TPMDD::TPM_PRIMARY); } + else + { + systemTpms.tpm[TPM_MASTER_INDEX].available = false; + } - if (systemTpms.tpm[TPM_MASTER_INDEX].failed) + if (systemTpms.tpm[TPM_MASTER_INDEX].failed || + !systemTpms.tpm[TPM_MASTER_INDEX].available) { /// @todo RTC:134913 Switch to backup chip if backup TPM avail @@ -131,6 +134,24 @@ void* host_update_master_tpm( void *io_pArgs ) } + // Lastly we will check on the backup TPM and see if it is enabled + // in the attributes at least + TPMDD::tpm_info_t tpmInfo; + tpmInfo.chip = TPMDD::TPM_BACKUP; + err = TPMDD::tpmReadAttributes(nodeTarget, tpmInfo); + if (NULL != err) + { + break; + } + else if (!tpmInfo.tpmEnabled) + { + TRACUCOMP( g_trac_trustedboot, + "host_update_master_tpm() tgt=0x%X " + "Marking backup TPM unavailable", + TARGETING::get_huid(nodeTarget)); + systemTpms.tpm[TPM_BACKUP_INDEX].available = false; + } + } while ( 0 ); if( unlock ) @@ -151,9 +172,6 @@ void tpmInitialize(TRUSTEDBOOT::TpmTarget & io_target, TPMDD::tpm_chip_types_t i_chip) { errlHndl_t err = NULL; - uint8_t dataBuf[BUFSIZE]; - size_t dataSize = sizeof(dataBuf); - size_t cmdSize = 0; TRACDCOMP( g_trac_trustedboot, ENTER_MRK"tpmInitialize()" ); @@ -164,86 +182,60 @@ void tpmInitialize(TRUSTEDBOOT::TpmTarget & io_target, do { + // TPM Initialization sequence io_target.nodeTarget = i_nodeTarget; io_target.chip = i_chip; io_target.initAttempted = true; + io_target.available = true; io_target.failed = false; - // Send the TPM startup command - // Build our command block for a startup - memset(dataBuf, 0, sizeof(dataBuf)); - - TRUSTEDBOOT::TPM2_BaseOut* resp = - (TRUSTEDBOOT::TPM2_BaseOut*)dataBuf; - TRUSTEDBOOT::TPM2_2ByteIn* cmd = - (TRUSTEDBOOT::TPM2_2ByteIn*)dataBuf; - - cmd->base.tag = TRUSTEDBOOT::TPM_ST_NO_SESSIONS; - cmd->base.commandSize = sizeof (TRUSTEDBOOT::TPM2_2ByteIn); - cmd->base.commandCode = TRUSTEDBOOT::TPM_CC_Startup; - cmd->param = TRUSTEDBOOT::TPM_SU_CLEAR; - cmdSize = cmd->base.commandSize; - - err = deviceRead(io_target.nodeTarget, - &dataBuf, - dataSize, - DEVICE_TPM_ADDRESS( io_target.chip, - TPMDD::TPM_OP_TRANSMIT, - cmdSize) ); - + // TPM_STARTUP + err = tpmCmdStartup(io_target); if (NULL != err) { - TRACFCOMP( g_trac_trustedboot, - "TPM STARTUP I2C Fail %X : ", - err->reasonCode() ); break; - } - else if (TRUSTEDBOOT::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_INITIALIZE - * @userdata1 node - * @userdata2 returnCode - * @devdesc Invalid operation type. - */ - err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - MOD_TPM_INITIALIZE, - RC_TPM_START_FAIL, - TARGETING::get_huid( - io_target.nodeTarget), - resp->responseCode, - true /*Add HB SW Callout*/ ); - err->collectTrace( SECURE_COMP_NAME ); + // TPM_GETCAPABILITY to read FW Version + err = tpmCmdGetCapFwVersion(io_target); + if (NULL != err) + { break; } + } while ( 0 ); // If the TPM failed we will mark it not functional if (NULL != err) { - io_target.failed = true; + tpmMarkFailed(io_target); // Log this failure errlCommit(err, SECURE_COMP_ID); } TRACDCOMP( g_trac_trustedboot, - EXIT_MRK"tpmInitialize() - %s", - ((NULL == err) ? "No Error" : "With Error") ); + EXIT_MRK"tpmInitialize()"); + +} + +void tpmMarkFailed(TRUSTEDBOOT::TpmTarget & io_target) +{ + + TRACFCOMP( g_trac_trustedboot, + ENTER_MRK"tpmMarkFailed() Marking TPM as failed : " + "tgt=0x%X chip=%d", + TARGETING::get_huid(io_target.nodeTarget), + io_target.chip); + + io_target.failed = true; + /// @todo RTC:125287 Add fail marker to TPM log and disable TPM access } + } // end TRUSTEDBOOT diff --git a/src/usr/secureboot/trusted/trustedboot.H b/src/usr/secureboot/trusted/trustedboot.H index 3e3b43411..76630ba9a 100644 --- a/src/usr/secureboot/trusted/trustedboot.H +++ b/src/usr/secureboot/trusted/trustedboot.H @@ -34,110 +34,91 @@ // Includes // ----------------------------------------------- #include +#include +#include "trustedTypes.H" namespace TRUSTEDBOOT { enum { - MAX_SYSTEM_TPMS = 2, BUFSIZE = 256, - TPM_MASTER_INDEX = 0, ///< Index into tpmTargets array for master chip - TPM_BACKUP_INDEX = 1, ///< Index for backup chip TPM + MAX_TRANSMIT_SIZE = 1024, ///< Maximum send/receive transmit size }; - /** * @brief Initialize the targetted TPM * @param[in/out] io_target Current TPM target structure * @param[in] i_nodeTarget Node Target * @param[in] i_chip Chip to initialize */ - void tpmInitialize(TRUSTEDBOOT::TpmTarget & io_target, - TARGETING::Target* i_nodeTarget, - TPMDD::tpm_chip_types_t i_chip); - -/// Class object to store system TPM information -class SystemTpms -{ -public: - SystemTpms(); - - TpmTarget tpm[MAX_SYSTEM_TPMS]; -}; - -// Command structures taken from Trusted Platform Module Library Part 3: -// Commands Family "2.0" -struct TPM2_BaseIn { - uint16_t tag; ///< Type TPM_ST_xx - uint32_t commandSize; ///< Total # output bytes incl cmdSize and tag - uint32_t commandCode; ///< Type TPM_CC_xx -} PACKED; - -/// Base of all outgoing messages -struct TPM2_BaseOut { - uint16_t tag; ///< Type TPM_ST_xx - uint32_t responseSize; ///< Total # output bytes incl paramSize and tag - uint32_t responseCode;///< The return code of the operation -} PACKED; - -/// Generic TPM Input Command structure with a 2 byte param -struct TPM2_2ByteIn { - TPM2_BaseIn base; - uint16_t param; -} PACKED; - -/// Generic TPM Output Command structure with a 4 byte return data -struct TPM2_4ByteOut { - TPM2_BaseOut base; - uint32_t resp; -} PACKED; +void tpmInitialize(TRUSTEDBOOT::TpmTarget & io_target, + TARGETING::Target* i_nodeTarget, + TPMDD::tpm_chip_types_t i_chip); -/// Incoming TPM_GetCapability structure -struct TPM2_GetCapabilityIn { - TPM2_BaseIn base; - uint32_t capability; ///< group selection - uint32_t property; ///< Further definition - uint32_t propertyCount; ///< Number of properties to return -} PACKED; - -/// Outgoing TPM_GetCapability structure -struct TPM2_GetCapabilityOut { - TPM2_BaseOut base; - uint8_t moreData; ///< Flag to indicate if more values available - uint8_t capData[]; ///< The capability response -} PACKED; - -/// Various static values -enum { - // Command structure tags - TPM_ST_NO_SESSIONS = 0x8001, ///< A command with no sess/auth - - - // Command Codes - TPM_CC_Startup = 0x00000144, - TPM_CC_GetCapability = 0x0000017A, - TPM_CC_PCR_Read = 0x0000017E, - TPM_CC_PCR_Extend = 0x00000182, - - - // TPM Startup types - TPM_SU_CLEAR = 0x0000, ///< TPM perform reset,restart - TPM_SU_STATE = 0x0001, ///< TPM perform restore saved state - - // Capability - TPM_CAP_TPM_PROPERTIES = 0x00000006, ///< Pull TPM Properties +/** + * @brief Mark the TPM as non-functional and take required steps + * @param[in/out] io_target Current TPM target structure + */ +void tpmMarkFailed(TRUSTEDBOOT::TpmTarget & io_target); - // TPM Properties - TPM_PT_MANUFACTURER = 0x00000105, +/** + * @brief Transmit the command to the TPM and perform marshaling + * @param[in/out] io_target Current TPM target structure + * @param[in/out] io_buffer Input the command buffer to send, response on exit + * @param[in] i_bufsize Size of io_buffer in bytes + * @return errlHndl_t NULL if successful, otherwise a pointer to the + * error log. + */ +errlHndl_t tpmTransmitCommand(TRUSTEDBOOT::TpmTarget & io_target, + uint8_t* io_buffer, + size_t i_bufsize ); - // TPM Return Codes - TPM_SUCCESS = 0x000, +/** + * @brief Take structure pointed to by cmd and format for input into TPM + * @param[in] i_cmd Prefilled command input structure + * @param[out] o_outbuf Buffer to place marshalled data + * @param[in] i_bufsize Size of o_outbuf in bytes + * @param[out] o_cmdSize Byte size of io_outbuf data after marshal + * @return errlHndl_t NULL if successful, otherwise a pointer to the + * error log. + */ +errlHndl_t tpmMarshalCommandData(TRUSTEDBOOT::TPM2_BaseIn* i_cmd, + uint8_t* o_outbuf, + size_t i_bufsize, + size_t & o_cmdSize); - TPM_RC_INITIALIZE = 0x100, +/** + * @brief Take structure pointed to by cmd and format for input into TPM + * @param[in] i_commandCode Command code that was executed on the TPM + * @param[in] i_respBuf Buffer with response data from TPM + * @param[in] i_respBufSize Byte size of respBuf buffer from TPM + * @param[out] o_outBuf Buffer to place formatted response data + * @param[in] i_outBufSize Byte size of o_outBuf buffer + * @return errlHndl_t NULL if successful, otherwise a pointer to the + * error log. + */ +errlHndl_t tpmUnmarshalResponseData(uint32_t i_commandCode, + uint8_t* i_respBuf, + size_t i_respBufSize, + TRUSTEDBOOT::TPM2_BaseOut* o_outBuf, + size_t i_outBufSize); +/** + * @brief Send the TPM_STARTUP command to the targetted TPM + * @param[in/out] io_target Current TPM target structure + * @return errlHndl_t NULL if successful, otherwise a pointer to the + * error log. +*/ +errlHndl_t tpmCmdStartup(TRUSTEDBOOT::TpmTarget & io_target); -}; +/** + * @brief Send the TPM_GETCAPABILITY command to read FW version from TPM + * @param[in/out] io_target Current TPM target structure + * @return errlHndl_t NULL if successful, otherwise a pointer to the + * error log. +*/ +errlHndl_t tpmCmdGetCapFwVersion(TRUSTEDBOOT::TpmTarget & io_target); } // end TRUSTEDBOOT namespace diff --git a/src/usr/secureboot/trusted/trustedbootCmds.C b/src/usr/secureboot/trusted/trustedbootCmds.C new file mode 100644 index 000000000..311d1fce8 --- /dev/null +++ b/src/usr/secureboot/trusted/trustedbootCmds.C @@ -0,0 +1,717 @@ +/* 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 */ +/* [+] 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 + */ + +// ---------------------------------------------- +// Includes +// ---------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "trustedboot.H" +#include "trustedTypes.H" +#include + +// ---------------------------------------------- +// Trace definitions +// ---------------------------------------------- +extern trace_desc_t* g_trac_trustedboot; + +// Easy macro replace for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) +//#define TRACUBIN(args...) TRACFBIN(args) +#define TRACUBIN(args...) + +namespace TRUSTEDBOOT +{ + + +errlHndl_t tpmTransmitCommand(TRUSTEDBOOT::TpmTarget & io_target, + uint8_t* io_buffer, + size_t i_bufsize ) +{ + errlHndl_t err = NULL; + uint8_t* transmitBuf = NULL; + size_t cmdSize = 0; + size_t dataSize = 0; + TRUSTEDBOOT::TPM2_BaseIn* cmd = + reinterpret_cast(io_buffer); + TRUSTEDBOOT::TPM2_BaseOut* resp = + reinterpret_cast(io_buffer); + + TRACUCOMP( g_trac_trustedboot, + ENTER_MRK"TPM TRANSMIT CMD START : BufLen %d : %016llx", + i_bufsize, + *(reinterpret_cast(io_buffer)) ); + + do + { + transmitBuf = new uint8_t[MAX_TRANSMIT_SIZE]; + + // Marshal the data into a byte array for transfer to the TPM + err = tpmMarshalCommandData(cmd, + transmitBuf, + MAX_TRANSMIT_SIZE, + cmdSize); + if (NULL != err) + { + break; + } + + + // Send to the TPM + dataSize = MAX_TRANSMIT_SIZE; + err = deviceRead(io_target.nodeTarget, + transmitBuf, + dataSize, + DEVICE_TPM_ADDRESS( io_target.chip, + TPMDD::TPM_OP_TRANSMIT, + cmdSize)); + if (NULL != err) + { + break; + } + + // Unmarshal the response + err = tpmUnmarshalResponseData(cmd->commandCode, + transmitBuf, + dataSize, + resp, + i_bufsize); + + + } while ( 0 ); + + + delete transmitBuf; + + TRACUCOMP( g_trac_trustedboot, + EXIT_MRK"tpmTransmitCommand() - %s", + ((NULL == err) ? "No Error" : "With Error") ); + return err; +} + +errlHndl_t tpmMarshalCommandData(TRUSTEDBOOT::TPM2_BaseIn* i_cmd, + uint8_t* o_outbuf, + size_t i_bufsize, + size_t & o_cmdSize) +{ + errlHndl_t err = NULL; + uint8_t* sBuf = o_outbuf; + o_cmdSize = 0; + int stage = 0; + TRUSTEDBOOT::TPM2_BaseIn* baseCmd = + reinterpret_cast(o_outbuf); + + TRACDCOMP( g_trac_trustedboot, + ENTER_MRK"tpmMarshalCommandData()" ); + do + { + + TRACUCOMP( g_trac_trustedboot, + "TPM MARSHAL START : BufLen %d : %016llx", + i_bufsize, + *(reinterpret_cast(i_cmd)) ); + + // Start with the command header + sBuf = i_cmd->marshal(sBuf, i_bufsize, o_cmdSize); + if (NULL == sBuf) + { + break; + } + + + // Marshal the handles + stage = 1; + + + // Marshal the authorizations + stage = 2; + + // Marshal the parameters + stage = 3; + switch (i_cmd->commandCode) + { + // Two byte parm fields + case TRUSTEDBOOT::TPM_CC_Startup: + { + TRUSTEDBOOT::TPM2_2ByteIn* cmdPtr = + reinterpret_cast(i_cmd); + sBuf = cmdPtr->marshal(sBuf, + i_bufsize, + o_cmdSize); + } + break; + + case TRUSTEDBOOT::TPM_CC_GetCapability: + { + TRUSTEDBOOT::TPM2_GetCapabilityIn* cmdPtr = + reinterpret_cast(i_cmd); + sBuf = cmdPtr->marshal(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 = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_TPM_MARSHALCMDDATA, + RC_TPM_MARSHAL_INVALID_CMD, + i_cmd->commandCode, + 0, + true /*Add HB SW Callout*/ ); + + err->collectTrace( SECURE_COMP_NAME ); + } + break; + }; + + if (NULL != err) + { + break; + } + + + // Lastly now that we know the size update the byte stream + baseCmd->commandSize = o_cmdSize; + + } while ( 0 ); + + if (NULL == sBuf && NULL == 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 = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_TPM_MARSHALCMDDATA, + RC_TPM_MARSHALING_FAIL, + stage, + 0, + true /*Add HB SW Callout*/ ); + + err->collectTrace( SECURE_COMP_NAME ); + + } + + TRACUBIN(g_trac_trustedboot, "Marshal Out", + o_outbuf, o_cmdSize); + + TRACUCOMP( g_trac_trustedboot, + "TPM MARSHAL END : CmdSize: %d : %016llx ", o_cmdSize, + *(reinterpret_cast(o_outbuf)) ); + + TRACDCOMP( g_trac_trustedboot, + EXIT_MRK"tpmMarshalCommandData()" ); + + return err; +} + +errlHndl_t tpmUnmarshalResponseData(uint32_t i_commandCode, + uint8_t* i_respBuf, + size_t i_respBufSize, + TRUSTEDBOOT::TPM2_BaseOut* o_outBuf, + size_t i_outBufSize) +{ + errlHndl_t err = NULL; + uint8_t* sBuf = i_respBuf; + int stage = 0; + + TRACDCOMP( g_trac_trustedboot, + ENTER_MRK"tpmUnmarshalResponseData()" ); + + do { + + TRACUCOMP( g_trac_trustedboot, + "TPM UNMARSHAL START : RespBufLen %d : OutBufLen %d", + i_respBufSize, i_outBufSize); + TRACUBIN(g_trac_trustedboot,"Unmarshal In", + i_respBuf, i_respBufSize); + + + // Start with the response header + stage = 1; + sBuf = o_outBuf->unmarshal(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 (TRUSTEDBOOT::TPM_SUCCESS != o_outBuf->responseCode) + { + break; + } + + + // Unmarshal the parameters + stage = 2; + switch (i_commandCode) + { + // Empty response commands + case TRUSTEDBOOT::TPM_CC_Startup: + // Nothing to do + break; + + case TRUSTEDBOOT::TPM_CC_GetCapability: + { + TRUSTEDBOOT::TPM2_GetCapabilityOut* respPtr = + reinterpret_cast + (o_outBuf); + sBuf = respPtr->unmarshal(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 = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_TPM_UNMARSHALRESPDATA, + RC_TPM_UNMARSHAL_INVALID_CMD, + i_commandCode, + stage, + true /*Add HB SW Callout*/ ); + + err->collectTrace( SECURE_COMP_NAME ); + } + break; + } + + + } while ( 0 ); + + if (NULL == sBuf && NULL == 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 = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_TPM_UNMARSHALRESPDATA, + RC_TPM_UNMARSHALING_FAIL, + stage, + i_respBufSize, + true /*Add HB SW Callout*/ ); + + err->collectTrace( SECURE_COMP_NAME ); + + + } + + TRACUCOMP( g_trac_trustedboot, + "TPM UNMARSHAL END : %016llx ", + *(reinterpret_cast(o_outBuf)) ); + + TRACDCOMP( g_trac_trustedboot, + EXIT_MRK"tpmUnmarshalResponseData()" ); + + return err; +} + +errlHndl_t tpmCmdStartup(TRUSTEDBOOT::TpmTarget & io_target) +{ + errlHndl_t err = NULL; + uint8_t dataBuf[BUFSIZE]; + + TRACDCOMP( g_trac_trustedboot, + ENTER_MRK"tpmCmdStartup()" ); + TRACUCOMP( g_trac_trustedboot, + ENTER_MRK"tpmCmdStartup() tgt=0x%X chip=%d", + TARGETING::get_huid(io_target.nodeTarget), + io_target.chip); + + do + { + // Send the TPM startup command + // Build our command block for a startup + memset(dataBuf, 0, sizeof(dataBuf)); + + TRUSTEDBOOT::TPM2_BaseOut* resp = + reinterpret_cast(dataBuf); + + TRUSTEDBOOT::TPM2_2ByteIn* cmd = + reinterpret_cast(dataBuf); + + cmd->base.tag = TRUSTEDBOOT::TPM_ST_NO_SESSIONS; + cmd->base.commandCode = TRUSTEDBOOT::TPM_CC_Startup; + cmd->param = TRUSTEDBOOT::TPM_SU_CLEAR; + + err = tpmTransmitCommand(io_target, + dataBuf, + sizeof(dataBuf)); + + if (NULL != err) + { + TRACFCOMP( g_trac_trustedboot, + "TPM STARTUP transmit Fail %X : ", + err->reasonCode() ); + break; + + } + else if (TRUSTEDBOOT::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 node + * @userdata2 responseCode + * @devdesc Invalid operation type. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_TPM_CMD_STARTUP, + RC_TPM_START_FAIL, + TARGETING::get_huid( + io_target.nodeTarget), + resp->responseCode, + true /*Add HB SW Callout*/ ); + + err->collectTrace( SECURE_COMP_NAME ); + break; + } + + + } while ( 0 ); + + + TRACUCOMP( g_trac_trustedboot, + EXIT_MRK"tpmCmdStartup() - %s", + ((NULL == err) ? "No Error" : "With Error") ); + return err; +} + +errlHndl_t tpmCmdGetCapFwVersion(TRUSTEDBOOT::TpmTarget & io_target) +{ + errlHndl_t err = NULL; + uint8_t dataBuf[BUFSIZE]; + size_t dataSize = BUFSIZE; + uint16_t fwVersion[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + + TRACDCOMP( g_trac_trustedboot, + ENTER_MRK"tpmCmdGetCapFwVersion()" ); + TRACUCOMP( g_trac_trustedboot, + ENTER_MRK"tpmCmdGetCapFwVersion() tgt=0x%X chip=%d", + TARGETING::get_huid(io_target.nodeTarget), + io_target.chip); + + do + { + + // Build our command block for a get capability of the FW version + memset(dataBuf, 0, dataSize); + + TRUSTEDBOOT::TPM2_GetCapabilityOut* resp = + reinterpret_cast(dataBuf); + TRUSTEDBOOT::TPM2_GetCapabilityIn* cmd = + reinterpret_cast(dataBuf); + + cmd->base.tag = TRUSTEDBOOT::TPM_ST_NO_SESSIONS; + cmd->base.commandCode = TRUSTEDBOOT::TPM_CC_GetCapability; + cmd->capability = TRUSTEDBOOT::TPM_CAP_TPM_PROPERTIES; + cmd->property = TRUSTEDBOOT::TPM_PT_FIRMWARE_VERSION_1; + cmd->propertyCount = 1; + + err = tpmTransmitCommand(io_target, + dataBuf, + sizeof(dataBuf)); + + if (NULL != err) + { + TRACFCOMP( g_trac_trustedboot, + "TPM GETCAP Transmit Fail %X : ", + err->reasonCode() ); + break; + + } + + if (TRUSTEDBOOT::TPM_SUCCESS != resp->base.responseCode) + { + TRACFCOMP( g_trac_trustedboot, + "TPM GETCAP OP Fail %X Size(%d) ", + resp->base.responseCode, + dataSize); + + /*@ + * @errortype + * @reasoncode RC_TPM_GETCAP_FAIL + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_TPM_CMD_GETCAPFWVERSION + * @userdata1 node + * @userdata2[0:31] responseCode + * @userdata2[32:63] dataSize + * @devdesc Command failure reading TPM FW version. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_TPM_CMD_GETCAPFWVERSION, + RC_TPM_GETCAP_FAIL, + TARGETING::get_huid( + io_target.nodeTarget), + resp->base.responseCode, + true /*Add HB SW Callout*/ ); + + err->collectTrace( SECURE_COMP_NAME ); + 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 node + * @userdata2[0:31] capability + * @userdata2[32:63] propery + * @devdesc Command failure reading TPM FW version. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_TPM_CMD_GETCAPFWVERSION, + RC_TPM_GETCAP_FW_INVALID_RESP, + TARGETING::get_huid( + io_target.nodeTarget), + ((uint64_t)resp->capData.capability << 32) | + resp->capData.data.tpmProperties. + tpmProperty[0].property, + true /*Add HB SW Callout*/ ); + + err->collectTrace( SECURE_COMP_NAME ); + 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 = TRUSTEDBOOT::TPM_ST_NO_SESSIONS; + cmd->base.commandCode = TRUSTEDBOOT::TPM_CC_GetCapability; + cmd->capability = TRUSTEDBOOT::TPM_CAP_TPM_PROPERTIES; + cmd->property = TRUSTEDBOOT::TPM_PT_FIRMWARE_VERSION_2; + cmd->propertyCount = 1; + + + err = tpmTransmitCommand(io_target, + dataBuf, + sizeof(dataBuf)); + + if (NULL != err) + { + TRACFCOMP( g_trac_trustedboot, + "TPM GETCAP2 Transmit Fail %X : ", + err->reasonCode() ); + break; + + } + + if ((sizeof(TRUSTEDBOOT::TPM2_GetCapabilityOut) > dataSize) || + (TRUSTEDBOOT::TPM_SUCCESS != resp->base.responseCode)) + { + TRACFCOMP( g_trac_trustedboot, + "TPM GETCAP2 OP Fail %X Size(%d) ", + resp->base.responseCode, + dataSize); + + /*@ + * @errortype + * @reasoncode RC_TPM_GETCAP2_FAIL + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_TPM_CMD_GETCAPFWVERSION + * @userdata1 node + * @userdata2[0:31] responseCode + * @userdata2[32:63] dataSize + * @devdesc Command failure reading TPM FW version. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_TPM_CMD_GETCAPFWVERSION, + RC_TPM_GETCAP2_FAIL, + TARGETING::get_huid( + io_target.nodeTarget), + resp->base.responseCode, + true /*Add HB SW Callout*/ ); + + err->collectTrace( SECURE_COMP_NAME ); + 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 node + * @userdata2[0:31] capability + * @userdata2[32:63] propery + * @devdesc Command failure reading TPM FW version. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_TPM_CMD_GETCAPFWVERSION, + RC_TPM_GETCAP2_FW_INVALID_RESP, + TARGETING::get_huid( + io_target.nodeTarget), + ((uint64_t)resp->capData.capability << 32) | + resp->capData.data.tpmProperties. + tpmProperty[0].property, + true /*Add HB SW Callout*/ ); + + err->collectTrace( SECURE_COMP_NAME ); + 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, + EXIT_MRK"tpmCmdGetCapFwVersion() - %s", + ((NULL == err) ? "No Error" : "With Error") ); + return err; +} + + + + +} // end TRUSTEDBOOT -- cgit v1.2.1