From a42bbccdd949bc4b78e856087019c73a126420d4 Mon Sep 17 00:00:00 2001 From: Nick Bofferding Date: Wed, 25 Jan 2017 13:10:08 -0600 Subject: Support extending sections to PCRs - Ported p8 secureboot PCR extension code Change-Id: I2bbf6ee6b2980c2fbe32dfb9cad25e9e2aba3285 RTC: 167581 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35632 Tested-by: Jenkins Server Tested-by: FSP CI Jenkins Reviewed-by: Marshall J. Wilks Tested-by: Jenkins OP Build CI Reviewed-by: Stephen M. Cprek Reviewed-by: William G. Hoffa --- src/include/runtime/interface.h | 12 +- src/include/usr/secureboot/header.H | 11 +- src/include/usr/secureboot/service.H | 24 ++- src/usr/devtree/bld_devtree.C | 2 +- src/usr/pnor/pnor_common.C | 45 ++--- src/usr/pnor/pnor_common.H | 5 +- src/usr/pnor/pnorrp.C | 35 ++-- src/usr/secureboot/base/header.C | 85 +++++---- src/usr/secureboot/base/securerom.C | 66 +++++-- src/usr/secureboot/base/securerom.H | 28 ++- src/usr/secureboot/base/service.C | 2 +- src/usr/secureboot/base/test/secureromtest.H | 8 +- src/usr/secureboot/runtime/rt_secureboot.C | 14 +- src/usr/secureboot/trusted/base/trustedboot_base.C | 200 +++++++++++++++++++-- src/usr/secureboot/trusted/trustedboot.C | 2 +- src/usr/secureboot/trusted/trustedboot.H | 4 +- 16 files changed, 402 insertions(+), 141 deletions(-) diff --git a/src/include/runtime/interface.h b/src/include/runtime/interface.h index 6681e49ca..f5eb2cba1 100644 --- a/src/include/runtime/interface.h +++ b/src/include/runtime/interface.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* Contributors Listed Below - COPYRIGHT 2013,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -655,10 +655,10 @@ typedef struct runtimeInterfaces * Must not be NULL. Container is assumed to be stripped of any ECC * and must start with a valid secure header (which contains the * container size information) - * @param[in] i_pHwHashKey Pointer to a valid hardware hash key. + * @param[in] i_pHwKeyHash Pointer to a valid hardware keys' hash. * Must not be NULL. - * @param[in] i_hwHashKeySize Size of the hardware hash key. - * A value which incorrectly states the size of the hardware hash key + * @param[in] i_hwKeyHashSize Size of the hardware keys' hash. + * A value which incorrectly states the size of the hardware keys' hash * will be detected as a verification error or worse, an illegal memory * access. Must not be 0. * @note If secureboot is compiled out, the function pointer will be set to @@ -672,8 +672,8 @@ typedef struct runtimeInterfaces */ int (*verify_container)( const void* i_pContainer, - const void* i_pHwHashKey, - size_t i_hwHashKeySize); + const void* i_pHwKeyHash, + size_t i_hwKeyHashSize); // Reserve some space for future growth. // do NOT ever change this number, even if you add functions. diff --git a/src/include/usr/secureboot/header.H b/src/include/usr/secureboot/header.H index f7a5121c6..4ad1f0e7e 100644 --- a/src/include/usr/secureboot/header.H +++ b/src/include/usr/secureboot/header.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* Contributors Listed Below - COPYRIGHT 2013,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -59,10 +59,8 @@ namespace SECUREBOOT iv_data=NULL; } - // TODO securebootp9 This is from p9 code. See the corresponding - // comment in header.C for more info. - /** @brief Extract header from original HRMOR - 1 page address. */ - void loadBaseHeader(); + // @TODO RTC 168021 Converge to single method of reading + // secure header /** * @brief Extracts base image (HBB) header (ECC removed) from @@ -73,6 +71,9 @@ namespace SECUREBOOT */ void loadSecurely(); + // @TODO RTC 168021 Converge to single method of reading + // secure header + /** * @brief Caches non-secure PNOR copy of the base image (HBB) * header (ECC removed) to support extending HBB measurements diff --git a/src/include/usr/secureboot/service.H b/src/include/usr/secureboot/service.H index 99772b429..afb3ed934 100644 --- a/src/include/usr/secureboot/service.H +++ b/src/include/usr/secureboot/service.H @@ -28,9 +28,13 @@ #include #include #include +#include #include typedef uint8_t SHA512_t[64]; + +typedef std::vector< std::pair > blobPair_t; + /* From sha512.h: */ #define SHA512_DIGEST_LENGTH 64 typedef uint8_t __attribute__((aligned(8))) sha2_hash_t[ \ @@ -160,12 +164,26 @@ namespace SECUREBOOT errlHndl_t hashBlob(const void * i_blob, size_t i_size, SHA512_t o_buf); /** - * @brief Retrieve the internal hardware hash key from secure ROM - * object. + * @brief Retrieve the internal hardware keys' hash used to validate + * containers * @param[out] o_hash Reference to the sha2_hash_t array to copy the * hash to. */ - void getHwHashKeys(sha2_hash_t o_hash); + void getHwKeyHash(sha2_hash_t o_hash); + + /* + * @brief Hash the concatenation of N Blobs + * + * Asserts if any blob pointer is NULL + * + * @param[in] i_blobs Vector of pairs composed of a void + * pointer to effective address and size + * of the blob to concatenate + * @param[out] o_buf SHA512 hash + * + * @return errlHndl_t NULL on success + */ + errlHndl_t hashConcatBlobs(const blobPair_t &i_blobs, SHA512_t o_buf); /** * @brief Common secureboot handler for secureboot failures. diff --git a/src/usr/devtree/bld_devtree.C b/src/usr/devtree/bld_devtree.C index 791e9a79a..ec2237f3f 100644 --- a/src/usr/devtree/bld_devtree.C +++ b/src/usr/devtree/bld_devtree.C @@ -2279,7 +2279,7 @@ errlHndl_t bld_fdt_secureboot(devTree * i_dt, bool i_smallTree) dtOffset_t secBootNode = i_dt->addNode(rootNode, "ibm,secureboot"); sha2_hash_t hw_key_hash; - SECUREBOOT::getHwHashKeys(hw_key_hash); + SECUREBOOT::getHwKeyHash(hw_key_hash); i_dt->addPropertyBytes(secBootNode, "hw-key-hash", reinterpret_cast(hw_key_hash), diff --git a/src/usr/pnor/pnor_common.C b/src/usr/pnor/pnor_common.C index 351386256..2414a15c2 100644 --- a/src/usr/pnor/pnor_common.C +++ b/src/usr/pnor/pnor_common.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2016 */ +/* Contributors Listed Below - COPYRIGHT 2014,2017 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -298,28 +298,31 @@ errlHndl_t PNOR::parseTOC( uint8_t* i_tocBuffer,SectionData_t * o_TOC) } - if (o_TOC[l_secId].version == FFS_VERS_SHA512) + // @TODO RTC 168021 Remove legacy extensions when all + // secure sections are supported + auto isSecure = PNOR::isSecureSection(l_secId); + if ( o_TOC[l_secId].version == FFS_VERS_SHA512 + && !isSecure) { - TRACFCOMP(g_trac_pnor, "PNOR::parseTOC: Incrementing" - " Flash Address for SHA Header"); - uint32_t l_addr = o_TOC[l_secId].flashAddr; - size_t l_headerSize = 0; - if (o_TOC[l_secId].integrity == FFS_INTEG_ECC_PROTECT) - { - l_headerSize = PAGESIZE_PLUS_ECC; - } - else - { - l_headerSize = PAGESIZE; - } - l_errhdl = PNOR::extendHash(l_addr, l_headerSize, - cv_EYECATCHER[l_secId]); - if (l_errhdl) - { - break; - } + // For non-secure sections with a SHA512 header, the + // flash address has incremented past the header, so + // back up by the header size (accounting for ECC) in order + // to extend the header + auto addr = o_TOC[l_secId].flashAddr; + size_t headerSize = + (o_TOC[l_secId].integrity == FFS_INTEG_ECC_PROTECT) ? + PAGESIZE_PLUS_ECC : PAGESIZE; + addr -= headerSize; + + l_errhdl = PNOR::extendHash(addr, headerSize, + cv_EYECATCHER[l_secId]); + if (l_errhdl) + { + break; + } } } + for(int tmpId = 0; tmpId < PNOR::NUM_SECTIONS; tmpId ++ ) @@ -335,6 +338,8 @@ errlHndl_t PNOR::parseTOC( uint8_t* i_tocBuffer,SectionData_t * o_TOC) return l_errhdl; } +// @TODO RTC 168021 Remove legacy extensions when all secure sections are +// supported errlHndl_t PNOR::extendHash(uint64_t i_addr, size_t i_size, const char* i_name) { errlHndl_t l_errhdl = NULL; diff --git a/src/usr/pnor/pnor_common.H b/src/usr/pnor/pnor_common.H index e8b6bd4f8..497e85e83 100644 --- a/src/usr/pnor/pnor_common.H +++ b/src/usr/pnor/pnor_common.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2016 */ +/* Contributors Listed Below - COPYRIGHT 2014,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -73,6 +73,9 @@ namespace PNOR { void physicalToMmioOffset(uint64_t i_hbbAddress, uint64_t& o_mmioOffset); + // @TODO RTC 168021 Remove legacy extensions when all secure sections + // are supported via story 168021 + /** * @brief Reads version header of section, hashes it, and extends to tpm * buffer list. diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C index 827765551..15739c3bc 100644 --- a/src/usr/pnor/pnorrp.C +++ b/src/usr/pnor/pnorrp.C @@ -329,29 +329,34 @@ void PnorRP::initDaemon() break; } + // @TODO RTC 168021 Remove the non-secure extension path and + // always used the converged HBB extension path. + + // If secured, extend base image (HBB) when Hostboot first starts. + // Since HBB is never re-loaded, inhibit extending this image in + // runtime code. #ifndef __HOSTBOOT_RUNTIME #ifdef CONFIG_SECUREBOOT - if(!SECUREBOOT::enabled()) + //TODO: RTC 167581 + // When RTC 166848 is available, add restrictions back in when + // base image header copy availability is detected + // if(!SECUREBOOT::enabled()) { - - // If in secure mode, we already have securely obtained the header - // because we copied it before the blind purge. In non-secure mode, - // cache the header from PNOR (susceptible to attacks). This is ok - // because there are already no security guarantees in non-secure - // mode. We need to get the HBB address separately because the - // OC ignores the header + // If compliant bootloader was present, it saved the HBB header + // to a known location accessible to HBB. Until that bootloader + // is widely distributed, when in non-secure mode in lab, + // manufacturing, etc., read the header directly from PNOR. PNOR::SideInfo_t pnorInfo = {PNOR::WORKING}; l_errhdl = PnorRP::getSideInfo(PNOR::WORKING, pnorInfo); - if(l_errhdl != NULL) + if(l_errhdl != nullptr) { break; } - const SectionData_t* pHbb = &iv_TOC[PNOR::HB_BASE_CODE]; - bool ecc = (pHbb->integrity == FFS_INTEG_ECC_PROTECT) ? true :false; + const SectionData_t* const pHbb = &iv_TOC[PNOR::HB_BASE_CODE]; + const bool ecc = (pHbb->integrity == FFS_INTEG_ECC_PROTECT) ? + true :false; - // We have to read two pages because the secure header is a page by - // itself, but it is prefixed by the SBE header uint8_t pHeader[PAGESIZE] = {0}; uint64_t fatalError = 0; l_errhdl = readFromDevice( @@ -364,12 +369,12 @@ void PnorRP::initDaemon() // If fatalError != 0 there is an uncorrectable ECC error (UE). // In that case, continue on with inaccurate data, as // readFromDevice API will initiate a shutdown - if(l_errhdl != NULL) + if(l_errhdl != nullptr) { break; } - // Skip the SBE header on the HBB image to get the real header + // Cache the header (void)SECUREBOOT::baseHeader().setNonSecurely( pHeader); } diff --git a/src/usr/secureboot/base/header.C b/src/usr/secureboot/base/header.C index 37ba7ca72..4aba9481f 100644 --- a/src/usr/secureboot/base/header.C +++ b/src/usr/secureboot/base/header.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* Contributors Listed Below - COPYRIGHT 2013,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -26,6 +26,7 @@ #include #include #include +#include namespace SECUREBOOT { @@ -34,53 +35,65 @@ namespace SECUREBOOT return Singleton
::instance(); } - // TODO securebootp9 this implementation native to p9 appears to be doing - // approximately the same thing as p8's loadSecurely() method. We need to - // confirm and merge together or leave separate and merely remove comment. - void Header::loadBaseHeader() + // @TODO RTC 168021 Converge on a single method of reading the secure + // header + void Header::loadSecurely() { - // Calculate original address of the secureboot header. - // Zero is purposefully not mapped into the VMM tables, so we - // can't use that for the virtual-to-real translation. Since - // this object is in the base image, EA = HRMOR | PA, so we can - // use PA - EA to find the HRMOR. - uint64_t addr = mm_virt_to_phys(this) - - reinterpret_cast(this); - addr -= PAGESIZE; - - // Map in the header. - void* origHeader = mm_block_map(reinterpret_cast(addr), - PAGESIZE); - - // Copy header to a save area. - // In the future we might want to just extract pieces of the - // header. The header is important when we start updating - // the TPM PCRs. - iv_data = malloc(PAGESIZE); - memcpy(iv_data, origHeader, PAGESIZE); - - // Unmap the header. - mm_block_unmap(origHeader); + //@TODO RTC 167581 + // When RTC 166848 is available, pull in real header return; } - // TODO securebootp9 this implementation of the follwoing two methods need - // to be added based on p8 code - void Header::loadSecurely() - { - } - + // @TODO RTC 168021 Converge on a single method of reading the secure + // header void Header::setNonSecurely( - const void* i_pHeader) + const void* const i_pHeader) { + // Fatal code bug if already loaded + assert(iv_data == nullptr,"BUG! In setNonSecurely(), " + "a cached header is already present."); + + // Fatal code bug if called with nullptr pointer + assert(i_pHeader != nullptr,"BUG! In setNonSecurely(), " + "caller passed a nullptr header."); + + iv_data = calloc(1,PAGESIZE); + memcpy(iv_data,i_pHeader,PAGE_SIZE); } void Header::getHeader( - const void*& o_pHeader ) const + const void*& o_pHeader) const { // Fatal code bug if queried before loaded - assert(iv_data!=nullptr); + assert(iv_data!=nullptr,"BUG! In getHeader(), " + "header is not present."); o_pHeader = iv_data; } + + void Header::_calcSecureLoadAddr( + const void*& o_pCode) const + { + //@TODO RTC 167581 + // When RTC 166848 is available, pull in real header + + // Determine the secure address where the HBB image was loaded by SBE. + // Regardless of whether security is enabled or not, HBB always ends up + // at the secure load address (which corresponds to the HRMOR). + // + // Zero is purposefully not mapped into the VMM tables, so we + // can't use that for the virtual-to-real translation. Since + // this object is in the base (HBB) image, PA = HRMOR | EA, so we can + // use PA - EA to find the HRMOR. + const void* hrmor = reinterpret_cast( + mm_virt_to_phys( + const_cast(this)) - + reinterpret_cast(this)); + + // HRMOR lookup should never fail + assert( reinterpret_cast(hrmor) + != static_cast(-EFAULT)); + + o_pCode = hrmor; + } } diff --git a/src/usr/secureboot/base/securerom.C b/src/usr/secureboot/base/securerom.C index dd1428f33..74c2a18bb 100644 --- a/src/usr/secureboot/base/securerom.C +++ b/src/usr/secureboot/base/securerom.C @@ -84,20 +84,27 @@ errlHndl_t verifyContainer(void * i_container, const sha2_hash_t* i_hwKeyHash) errlHndl_t hashBlob(const void * i_blob, size_t i_size, SHA512_t io_buf) { return Singleton::instance().hashBlob(i_blob, i_size, io_buf); +} +/** + * @brief Hash concatenation of 2 Blobs + * + */ +errlHndl_t hashConcatBlobs(const blobPair_t &i_blobs, SHA512_t o_buf) +{ + return Singleton::instance().hashConcatBlobs(i_blobs, o_buf); } /* - * @brief Externally available hardware hash key function + * @brief Externally available hardware keys' hash retrieval function */ -void getHwHashKeys(sha2_hash_t o_hash) +void getHwKeyHash(sha2_hash_t o_hash) { - return Singleton::instance().getHwHashKeys(o_hash); + return Singleton::instance().getHwKeyHash(o_hash); } }; //end SECUREBOOT namespace - /******************** Public Methods ********************/ @@ -259,13 +266,13 @@ errlHndl_t SecureROM::initialize() /* Retrieve HW Hash Keys From The System */ /***************************************************************/ - // @todo RTC:RTC:34080 - Support for SecureROM::getHwHashKeys() - l_errl = SecureROM::getHwHashKeys(); + // @todo RTC:RTC:34080 - Support for SecureROM::getHwKeyHash() + l_errl = SecureROM::getHwKeyHash(); if (l_errl != NULL) { TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM::initialize():" - " SecureROM::getHwHashKeys() returned an error"); + " SecureROM::getHwKeyHash() returned an error"); l_errl->collectTrace(SECURE_COMP_NAME,256); break; @@ -329,8 +336,8 @@ errlHndl_t SecureROM::verifyContainer(void * i_container, // struct elements my_ecid, entry_point and log memset(&l_hw_parms, 0, sizeof(ROM_hw_params)); - // Now set hw_key_hash, which is of type sha2_hash_t, to iv_hash_key - memcpy (&l_hw_parms.hw_key_hash, &iv_hash_key, sizeof(sha2_hash_t)); + // Now set hw_key_hash, which is of type sha2_hash_t, to iv_key_hash + memcpy (&l_hw_parms.hw_key_hash, &iv_key_hash, sizeof(sha2_hash_t)); TRACFBIN(g_trac_secure,"SecureROM::verifyContainer(): hw_key_hash", l_hw_parms.hw_key_hash, sizeof(sha2_hash_t)); @@ -384,6 +391,7 @@ errlHndl_t SecureROM::verifyContainer(void * i_container, /*@ * @errortype + * @severity ERRL_SEV_UNRECOVERABLE * @moduleid SECUREBOOT::MOD_SECURE_ROM_VERIFY * @reasoncode SECUREBOOT::RC_ROM_VERIFY * @userdata1 l_rc @@ -457,6 +465,28 @@ errlHndl_t SecureROM::hashBlob(const void * i_blob, size_t i_size, SHA512_t io_b return l_errl; } +/** + * @brief Hash concatenation of N Blobs + */ +errlHndl_t SecureROM::hashConcatBlobs(const blobPair_t &i_blobs, + SHA512_t o_buf) const +{ + errlHndl_t pError = nullptr; + std::vector concatBuf; + for (const auto &it : i_blobs) + { + assert(it.first != nullptr, "BUG! In SecureROM::hashConcatBlobs(), " + "User passed in nullptr blob pointer"); + const uint8_t* const blob = static_cast(it.first); + const auto blobSize = it.second; + concatBuf.insert(concatBuf.end(), blob, blob + blobSize); + } + + // Call hash blob on new concatenated buffer + pError = hashBlob(concatBuf.data(),concatBuf.size(),o_buf); + + return pError; +} /******************** Internal Methods @@ -470,8 +500,8 @@ SecureROM::SecureROM() { TRACDCOMP(g_trac_secure, "SecureROM::SecureROM()>"); - // Clear out iv_hash_keys, which is of type sha2_hash_t - memset(&iv_hash_key, 0, sizeof(sha2_hash_t) ); + // Clear out iv_key_hash, which is of type sha2_hash_t + memset(&iv_key_hash, 0, sizeof(sha2_hash_t) ); } @@ -547,26 +577,26 @@ void SecureROM::_cleanup() /** - * @brief Retrieves HW Keys from the system + * @brief Retrieves HW keys' hash from the system */ -errlHndl_t SecureROM::getHwHashKeys() +errlHndl_t SecureROM::getHwKeyHash() { errlHndl_t l_errl = NULL; - TRACFCOMP(g_trac_secure,INFO_MRK"SecureROM::getHwHashKeys() NOT supported"); + TRACFCOMP(g_trac_secure,INFO_MRK"SecureROM::getHwKeyHash() NOT supported"); - // @todo RTC:34080 - Add support for getting HW Hash Keys from System + // @todo RTC:34080 - Add support for getting HW keys' hash from System return l_errl; } /** - * @brief Retrieve the internal hardware hash key from secure ROM object. + * @brief Retrieve the internal hardware keys' hash from secure ROM object. */ -void SecureROM::getHwHashKeys(sha2_hash_t o_hash) +void SecureROM::getHwKeyHash(sha2_hash_t o_hash) { - memcpy(o_hash, iv_hash_key, sizeof(sha2_hash_t)); + memcpy(o_hash, iv_key_hash, sizeof(sha2_hash_t)); } /** diff --git a/src/usr/secureboot/base/securerom.H b/src/usr/secureboot/base/securerom.H index 4bb4fd54e..3704209d9 100644 --- a/src/usr/secureboot/base/securerom.H +++ b/src/usr/secureboot/base/securerom.H @@ -71,13 +71,28 @@ class SecureROM errlHndl_t hashBlob(const void * i_blob, size_t i_size, SHA512_t io_buf) const; /** - * @brief Retrieve the internal hardware hash key from secure ROM + * @brief Retrieve the internal hardware keys' hash from secure ROM * object. * * @param[out] o_hash Reference to the sha2_hash_t array to copy the * hash to. */ - void getHwHashKeys(sha2_hash_t o_hash); + void getHwKeyHash(sha2_hash_t o_hash); + + /* + * @brief Hash the concatenation of N Blobs + * + * Asserts if any blob pointer is NULL + * + * @param[in] i_blobs Vector of pairs composed of a void + * pointer to effective address and size + * of the blob to concatenate + * @param[out] o_buf SHA512 hash + * + * @return errlHndl_t NULL on success + */ + errlHndl_t hashConcatBlobs (const blobPair_t &i_blobs, + SHA512_t o_buf) const; protected: @@ -104,21 +119,20 @@ class SecureROM void * iv_device_ptr; /** - * Hash Key Retrieved From System + * HW key' hash retrieved from system */ - sha2_hash_t iv_hash_key; - + sha2_hash_t iv_key_hash; /******************************************** * Private Functions ********************************************/ /** - * @brief Retrieves HW Keys from the system + * @brief Retrieves HW keys' hash from the system * * @return errlHndl_t NULL on success */ - errlHndl_t getHwHashKeys(); + errlHndl_t getHwKeyHash(); /** * @brief Static instance function for testcase only diff --git a/src/usr/secureboot/base/service.C b/src/usr/secureboot/base/service.C index beed71616..6a8a35935 100644 --- a/src/usr/secureboot/base/service.C +++ b/src/usr/secureboot/base/service.C @@ -68,7 +68,7 @@ void* initializeBase(void* unused) // Load original secureboot header. if (enabled()) { - Singleton
::instance().loadBaseHeader(); + Singleton
::instance().loadSecurely(); } // Extend memory footprint into lower portion of cache. diff --git a/src/usr/secureboot/base/test/secureromtest.H b/src/usr/secureboot/base/test/secureromtest.H index 805b5bc2b..8a4ff4043 100644 --- a/src/usr/secureboot/base/test/secureromtest.H +++ b/src/usr/secureboot/base/test/secureromtest.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* Contributors Listed Below - COPYRIGHT 2013,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -62,7 +62,7 @@ void unloadSignedFile( void * & io_signedFile_pageAddr, // secureboot_signed_container was generated using this hw hash key. If another // key is in pibmem, this test will always fail. -const uint64_t hw_hash_key[] = +const uint64_t hw_key_hash[] = { 0x40d487ff7380ed6a, 0xd54775d5795fea0d, @@ -129,8 +129,8 @@ class SecureROMTest : public CxxTest::TestSuite return; } - // Set hw hash key - memcpy (& l_sRom.iv_hash_key, &hw_hash_key, sizeof(sha2_hash_t)); + // Set hardware keys' hash + memcpy (& l_sRom.iv_key_hash, &hw_key_hash, sizeof(sha2_hash_t)); /*******************************************************************/ /* Call verify function */ diff --git a/src/usr/secureboot/runtime/rt_secureboot.C b/src/usr/secureboot/runtime/rt_secureboot.C index 8ab6d5e51..3b7626553 100644 --- a/src/usr/secureboot/runtime/rt_secureboot.C +++ b/src/usr/secureboot/runtime/rt_secureboot.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -38,17 +38,17 @@ namespace SECUREBOOT int verify_container( const void* i_pContainer, - const void* i_pHwHashKey, - const size_t i_hwHashKeySize) + const void* i_pHwKeyHash, + const size_t i_hwKeyHashSize) { int rc = 0; - SB_ENTER( + SB_ENTER( "verify_container: " "container ptr = %p, " - "HW hash key ptr = %p, " - "HW hash key size = %d", - i_pContainer,i_pHwHashKey,i_hwHashKeySize); + "HW keys' hash ptr = %p, " + "HW keys' hash size = %d", + i_pContainer,i_pHwKeyHash,i_hwKeyHashSize); // TODO: RTC 156485 // Implement guts of verify_container diff --git a/src/usr/secureboot/trusted/base/trustedboot_base.C b/src/usr/secureboot/trusted/base/trustedboot_base.C index dbb47b6e5..c4a149368 100644 --- a/src/usr/secureboot/trusted/base/trustedboot_base.C +++ b/src/usr/secureboot/trusted/base/trustedboot_base.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* Contributors Listed Below - COPYRIGHT 2015,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,6 +42,10 @@ #include #include #include +#include +#include +#include +#include #include "../trustedboot.H" #include "../trustedbootCmds.H" #include "../trustedbootUtils.H" @@ -51,7 +55,7 @@ // Trace definitions // ---------------------------------------------- #ifdef CONFIG_TPMDD -trace_desc_t* g_trac_trustedboot = NULL; +trace_desc_t* g_trac_trustedboot = nullptr; TRAC_INIT( & g_trac_trustedboot, "TRBOOT", KILOBYTE ); #endif @@ -59,6 +63,9 @@ namespace TRUSTEDBOOT { #ifdef CONFIG_TPMDD +// Const string to append to PCR extension messages +const char* const FW_KEY_HASH_EXT = " FW KEY HASH"; + /// Global object to store TPM status SystemTpms systemTpms; @@ -255,26 +262,189 @@ errlHndl_t pcrExtend(TPM_Pcr i_pcr, return err; } -errlHndl_t extendPnorSectionHash(const SECUREBOOT::ContainerHeader& i_conHdr, - const void* i_vaddr, - const PNOR::SectionId i_sec) +errlHndl_t extendPnorSectionHash( + const SECUREBOOT::ContainerHeader& i_conHdr, + const void* const i_vaddr, + const PNOR::SectionId i_sec) { - errlHndl_t l_errhdl = NULL; + errlHndl_t pError = nullptr; + +#ifdef CONFIG_TPMDD + + do { + + PNOR::SectionInfo_t sectionInfo; + pError = PNOR::getSectionInfo(i_sec,sectionInfo); + if(pError) + { + TRACFCOMP(g_trac_trustedboot, ERR_MRK " Failed in call to " + "getSectionInfo() with section ID = %d.", + i_sec); + break; + } + + TRACDCOMP(g_trac_trustedboot, ENTER_MRK " extendPnorSectionHash for " + "section: %s",sectionInfo.name); + + const size_t protectedSize = i_conHdr.payloadTextSize(); + + // Generate pcr extension message + char swKeyMsg[strlen(sectionInfo.name) + strlen(FW_KEY_HASH_EXT) + 1]; + memset(swKeyMsg, 0, sizeof(swKeyMsg)); + strcat(swKeyMsg,sectionInfo.name); + strcat(swKeyMsg,FW_KEY_HASH_EXT); + + TPM_Pcr pnorHashPcr = PCR_0; + // PAYLOAD is the only section that needs its hash extended to PCR_4 + if (i_sec == PNOR::PAYLOAD) + { + pnorHashPcr = PCR_4; + } + // Extend swKeyHash to the next PCR after the hash extension PCR. + const TPM_Pcr swKeyHashPcr = static_cast(pnorHashPcr + 1); + + if (SECUREBOOT::enabled()) + { + // If secureboot is enabled, use protected hash in header + pError = TRUSTEDBOOT::pcrExtend(pnorHashPcr, + reinterpret_cast(i_conHdr.payloadTextHash()), + sizeof(SHA512_t), + sectionInfo.name); + if (pError) + { + TRACFCOMP(g_trac_trustedboot, ERR_MRK " Failed in call to " + "pcrExtend() (extend payload text hash) for section %s.", + sectionInfo.name); + break; + } + + // Extend SW public key hash + pError = TRUSTEDBOOT::pcrExtend(swKeyHashPcr, + reinterpret_cast(i_conHdr.swKeyHash()), + sizeof(SHA512_t), + swKeyMsg); + if (pError) + { + TRACFCOMP(g_trac_trustedboot, ERR_MRK " Failed in call to " + "pcrExtend() (extend SW public key hash) for section %s.", + sectionInfo.name); + break; + } + } + else + { + // If secureboot is not enabled, measure protected section + SHA512_t hash = {0}; + SECUREBOOT::hashBlob(i_vaddr, protectedSize, hash); + pError = TRUSTEDBOOT::pcrExtend(pnorHashPcr, hash, + sizeof(SHA512_t), + sectionInfo.name); + if (pError) + { + TRACFCOMP(g_trac_trustedboot, ERR_MRK " Failed in call to " + "pcrExtend() (extend payload text) for section %s.", + sectionInfo.name); + break; + } + } + + } while(0); + + TRACDCOMP(g_trac_trustedboot, EXIT_MRK " extendPnorSectionHash"); - // TODO securebootp9 - // remove the following code and implement based on p8 code - TRACFCOMP(g_trac_trustedboot, "ExtendPnorSectionHash called for section %d and " - " address %.16llX with payload text size %i" - "but not unimplemented in p9", i_sec, i_vaddr); +#endif - return l_errhdl; + return pError; } errlHndl_t extendBaseImage() { - errlHndl_t pError = NULL; - // TODO securebootp9 - // implement extendBaseImage based on p8 code + errlHndl_t pError = nullptr; + +#ifdef CONFIG_TPMDD + + TRACFCOMP(g_trac_trustedboot, ENTER_MRK " extendBaseImage()"); + + do { + + // Query the HBB header and code address + const void* pHbbHeader = nullptr; + + (void)SECUREBOOT::baseHeader().getHeader( + pHbbHeader); + + // Fatal code bug if either address is nullptr + if(pHbbHeader == nullptr) + { + assert(false,"BUG! In extendBaseImage(), cached header address is " + "nullptr"); + } + + TRACDBIN(g_trac_trustedboot,"Base Header",pHbbHeader, + TRUSTEDBOOT::DEFAULT_BIN_TRACE_SIZE); + + // TODO: RTC 168021 + // Need to remove this when HBB has a secure header across all platforms + // -or- a more general compatibility mechanism has been created allowing + // some platforms to stage in support + if(!PNOR::cmpSecurebootMagicNumber( + reinterpret_cast(pHbbHeader))) + { + TRACFCOMP(g_trac_trustedboot, INFO_MRK " HBB header is not a secure " + "header; inhibiting extending base image measurement"); + break; + } + + // Build a container header object from the raw header + const SECUREBOOT::ContainerHeader hbbContainerHeader(pHbbHeader); + + const void* pHbbVa = nullptr; + if(!SECUREBOOT::enabled()) + { + PNOR::SectionInfo_t l_info; + + // @TODO RTC 168021 Remove this path since header will always be + // cached + pError = getSectionInfo(PNOR::HB_BASE_CODE, l_info); + if(pError) + { + TRACFCOMP(g_trac_trustedboot, ERR_MRK "Failed in call to " + "getSectionInfo for HBB section"); + break; + } + + if(l_info.vaddr == 0) + { + assert(false,"BUG! In extendBaseImage(), HBB virtual address " + "was 0"); + } + + pHbbVa = reinterpret_cast( + l_info.vaddr); + + TRACDBIN(g_trac_trustedboot,"PNOR Base Code",pHbbVa, + TRUSTEDBOOT::DEFAULT_BIN_TRACE_SIZE); + } + + // Extend the HBB measurement to the TPM + pError = extendPnorSectionHash( + hbbContainerHeader, + pHbbVa, + PNOR::HB_BASE_CODE); + + if(pError) + { + TRACFCOMP(g_trac_trustedboot, ERR_MRK "Failed in call to " + "extendPnorSectionHash() for HBB section."); + break; + } + + } while(0); + + TRACFCOMP(g_trac_trustedboot, EXIT_MRK " extendBaseImage()"); + +#endif + return pError; } diff --git a/src/usr/secureboot/trusted/trustedboot.C b/src/usr/secureboot/trusted/trustedboot.C index a7b7f8c56..b6bbd313b 100644 --- a/src/usr/secureboot/trusted/trustedboot.C +++ b/src/usr/secureboot/trusted/trustedboot.C @@ -582,7 +582,7 @@ errlHndl_t tpmLogConfigEntries(TRUSTEDBOOT::TpmTarget & io_target) // HW Key Hash sha2_hash_t l_hw_key_hash; - SECUREBOOT::getHwHashKeys(l_hw_key_hash); + SECUREBOOT::getHwKeyHash(l_hw_key_hash); l_err = pcrExtend(PCR_1, l_hw_key_hash, sizeof(sha2_hash_t),"HW KEY HASH"); if (l_err) diff --git a/src/usr/secureboot/trusted/trustedboot.H b/src/usr/secureboot/trusted/trustedboot.H index 31dcfc2be..14cbe8b93 100644 --- a/src/usr/secureboot/trusted/trustedboot.H +++ b/src/usr/secureboot/trusted/trustedboot.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* Contributors Listed Below - COPYRIGHT 2015,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -55,6 +55,8 @@ extern trace_desc_t* g_trac_trustedboot; namespace TRUSTEDBOOT { +const size_t DEFAULT_BIN_TRACE_SIZE = 128; + /// Common static values enum { -- cgit v1.2.1