diff options
author | Nick Bofferding <bofferdn@us.ibm.com> | 2017-10-20 21:13:34 -0500 |
---|---|---|
committer | William G. Hoffa <wghoffa@us.ibm.com> | 2017-11-03 09:45:20 -0400 |
commit | 07d75753d59419ea6ba9ee3bd930e0aa8e7e7fd5 (patch) | |
tree | 78633da60312ff8cfd54807f787219036e976621 /src/usr | |
parent | 47f275a6bd3b2104a82d9786122afd6fe25f05de (diff) | |
download | talos-hostboot-07d75753d59419ea6ba9ee3bd930e0aa8e7e7fd5.tar.gz talos-hostboot-07d75753d59419ea6ba9ee3bd930e0aa8e7e7fd5.zip |
Secure Boot: Enforce PNOR section component IDs
- In secure mode, bootloader will enforce that HBB component ID is set
- In secure mode, Hostboot will enforce that PNOR component IDs are set
Change-Id: I04f3bbc45417b3229003c56e1083e1fc31c01cd7
RTC: 179422
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/48711
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Marshall J. Wilks <mjwilks@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Stephen M. Cprek <smcprek@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r-- | src/usr/errl/errludstring.C | 56 | ||||
-rw-r--r-- | src/usr/errl/plugins/errludparserfactoryerrl.H | 11 | ||||
-rw-r--r-- | src/usr/errl/plugins/errludstring.H | 104 | ||||
-rw-r--r-- | src/usr/pnor/spnorrp.C | 11 | ||||
-rw-r--r-- | src/usr/scom/plugins/errludP_scom.H | 14 | ||||
-rw-r--r-- | src/usr/scom/plugins/scomUdParserFactory.H | 18 | ||||
-rw-r--r-- | src/usr/secureboot/base/securerommgr.C | 59 | ||||
-rw-r--r-- | src/usr/secureboot/base/test/securerommgrtest.H | 129 |
8 files changed, 384 insertions, 18 deletions
diff --git a/src/usr/errl/errludstring.C b/src/usr/errl/errludstring.C index 43943774d..888a303b6 100644 --- a/src/usr/errl/errludstring.C +++ b/src/usr/errl/errludstring.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ +/* [+] 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. */ @@ -54,5 +56,57 @@ ErrlUserDetailsString::~ErrlUserDetailsString() } +// ErrlUserDetailsStringSet implementation + +ErrlUserDetailsStringSet::ErrlUserDetailsStringSet() +{ + // Set up ErrlUserDetails instance variables + iv_CompId = ERRL_COMP_ID; + iv_Version = ERRL_UDT_STRING_SET_VER_1; + iv_SubSection = ERRL_UDT_STRING_SET; + + // override the default of false. + iv_merge = true; } +void ErrlUserDetailsStringSet::add( + const char* const i_pDescriptionString, + const char* const i_pString) +{ + // [Object Memory Layout] + // + // Offset Size Description + // ========================================================================= + // 0 X Existing object contents before this call, where X=0 if + // this is the first add call to the object + // X Y NULL terminated description string describing the string + // being logged, where Y=strlen(this string) + length (1) of + // NULL terminator. + // X+Y Z NULL terminated FFDC string, where Z=strlen(this string) + + // length (1) of NULL terminator. + + // Absorb API errors on error path and instead substitue error string for + // any input that is nullptr + const char* const pDescriptionString = (i_pDescriptionString == nullptr) ? + "BUG! Invalid description" : i_pDescriptionString; + const char* const pString = (i_pString == nullptr) ? "BUG! Invalid string" : + i_pString; + + const auto currentSize = static_cast<size_t>(getUsrBufSize()); + const auto descriptionSize = strlen(pDescriptionString)+1; + const auto stringSize = strlen(pString)+1; + const auto newSize = currentSize + descriptionSize + stringSize; + char* const pBuf = reinterpret_cast<char*>( + reallocUsrBuf(newSize)); + strcpy(pBuf+currentSize, pDescriptionString); + strcpy(pBuf+currentSize+descriptionSize,pString); +} + +ErrlUserDetailsStringSet::~ErrlUserDetailsStringSet() +{ + +} + +} // End of ERRORLOG namespace + + diff --git a/src/usr/errl/plugins/errludparserfactoryerrl.H b/src/usr/errl/plugins/errludparserfactoryerrl.H index 1db49a8dc..ebe7acb47 100644 --- a/src/usr/errl/plugins/errludparserfactoryerrl.H +++ b/src/usr/errl/plugins/errludparserfactoryerrl.H @@ -58,6 +58,7 @@ public: ErrlUserDetailsParserFactoryErrl() { registerParser<ErrlUserDetailsParserString>(ERRL_UDT_STRING); + registerParser<ErrlUserDetailsParserStringSet>(ERRL_UDT_STRING_SET); registerParser<ErrlUserDetailsParserTarget>(ERRL_UDT_TARGET); registerParser<ErrlUserDetailsParserBackTrace>(ERRL_UDT_BACKTRACE); registerParser<ErrlUserDetailsParserAttribute>(ERRL_UDT_ATTRIBUTE); @@ -68,10 +69,16 @@ public: private: - // Disabled - ErrlUserDetailsParserFactoryErrl(const ErrlUserDetailsParserFactoryErrl &); + // Parser isn't compiled with c++11 in all environments, and therefore + // "delete" of unused interfaces (like below) is not supported, nor are + // functions with move semantics + + // Disable compiler provided default functions + ErrlUserDetailsParserFactoryErrl( + const ErrlUserDetailsParserFactoryErrl &); ErrlUserDetailsParserFactoryErrl & operator=( const ErrlUserDetailsParserFactoryErrl &); + }; } diff --git a/src/usr/errl/plugins/errludstring.H b/src/usr/errl/plugins/errludstring.H index 51f91d5f8..9fbd185f1 100644 --- a/src/usr/errl/plugins/errludstring.H +++ b/src/usr/errl/plugins/errludstring.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ +/* [+] 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. */ @@ -79,14 +81,106 @@ public: } } -private: - // Disabled - ErrlUserDetailsParserString(const ErrlUserDetailsParserString &); + private: + + // Parser isn't compiled with c++11 in all environments, and therefore + // "delete" of unused interfaces (like below) is not supported, nor are + // functions with move semantics + + // Disable compiler provided default functions + ErrlUserDetailsParserString( + const ErrlUserDetailsParserString &); ErrlUserDetailsParserString & operator=( const ErrlUserDetailsParserString &); + +}; + +/** + * @class ErrlUserDetailsParserStringSet + * + * Parses string set user details from an error log + */ +class ErrlUserDetailsParserStringSet : public ErrlUserDetailsParser +{ + + public: + + /** + * @brief Constructor + */ + ErrlUserDetailsParserStringSet() + { + } + + /** + * @brief Destructor + */ + virtual ~ErrlUserDetailsParserStringSet() + { + } + + /** + * @brief Parses string set user details data from an error log + * + * @param i_version Version of the data + * @param i_parse ErrlUsrParser object for outputting information + * @param i_pBuffer Pointer to buffer containing detail data + * @param i_buflen Length of the buffer + */ + virtual void parse( + errlver_t i_version, + ErrlUsrParser& i_parser, + void* i_pBuffer, + const uint32_t i_buflen) const + { + // [Input Buffer Memory Layout] + // + // The input buffer contains N sequentially packed pairs of variable + // length, NULL terminated strings, where each string pair is also + // sequentially packed and the sum of the lengths of all such pairs + // exactly equals the input buffer length. Each string pair is + // formatted as below, beginning from either the start of the buffer or + // the end of the previous string pair: + // + // Offset Size Description + // ===================================================================== + // 0 Y NULL terminated description string describing the + // significance of the string to follow, Y=strlen(this + // string) + length (1) of NULL terminator. + // Y Z NULL terminated FFDC string, where Z=strlen(this + // string) + length (1) of NULL terminator. + + const char* pBuf = static_cast<const char*>(i_pBuffer); + const size_t len = static_cast<size_t>(i_buflen); + const char* pBufEnd = pBuf + len; + while(pBuf < pBufEnd) + { + const size_t descriptionStringSize = strlen(pBuf) + 1; + const char* const pDescriptionString = pBuf; + pBuf += descriptionStringSize; + + const size_t stringSize = strlen(pBuf) + 1; + const char* const pString = pBuf; + pBuf += stringSize; + + i_parser.PrintString(pDescriptionString,pString); + } + } + + private: + + // Parser isn't compiled with c++11 in all environments, and therefore + // "delete" of unused interfaces (like below) is not supported, nor are + // functions with move semantics + + // Disable compiler provided default functions + ErrlUserDetailsParserStringSet( + const ErrlUserDetailsParserStringSet&); + ErrlUserDetailsParserStringSet & operator=( + const ErrlUserDetailsParserStringSet&); }; -} +} // End ERRLOG namespace #endif diff --git a/src/usr/pnor/spnorrp.C b/src/usr/pnor/spnorrp.C index 78453f59c..1643215fd 100644 --- a/src/usr/pnor/spnorrp.C +++ b/src/usr/pnor/spnorrp.C @@ -465,6 +465,17 @@ uint64_t SPnorRP::verifySections(SectionId i_id, failedVerify = true; break; } + + auto const * const pPnorString = PNOR::SectionIdToString(i_id); + l_errhdl = SECUREBOOT::verifyComponent(l_conHdr,pPnorString); + if(l_errhdl) + { + TRACFCOMP(g_trac_pnor, ERR_MRK"SPnorrRP::verifySections: " + "Failed in call to SECUREBOOT::verifyComponent"); + failedVerify = true; + break; + } + l_errhdl = miscSectionVerification(l_tempAddr, i_id); if (l_errhdl) { diff --git a/src/usr/scom/plugins/errludP_scom.H b/src/usr/scom/plugins/errludP_scom.H index f3a704cf6..c8201f9fa 100644 --- a/src/usr/scom/plugins/errludP_scom.H +++ b/src/usr/scom/plugins/errludP_scom.H @@ -98,9 +98,17 @@ namespace SCOM i_parser.PrintString("Pib Err", l_outputStr ); } - // Disabled - UdParserPib(const UdParserPib&) = delete; - UdParserPib & operator=(const UdParserPib&) = delete; + private: + + // Parser isn't compiled with c++11 in all environments, and + // therefore "delete" of unused interfaces (like below) is not + // supported, nor are functions with move semantics + + // Disable compiler provided default functions + UdParserPib( + const UdParserPib&); + UdParserPib & operator=( + const UdParserPib&); }; } diff --git a/src/usr/scom/plugins/scomUdParserFactory.H b/src/usr/scom/plugins/scomUdParserFactory.H index d8ff3ceef..2763e0f32 100644 --- a/src/usr/scom/plugins/scomUdParserFactory.H +++ b/src/usr/scom/plugins/scomUdParserFactory.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,10 +40,18 @@ namespace SCOM (SCOM_UDT_PIB); } - //Disabled - UserDetailsParserFactory(const UserDetailsParserFactory &) = delete; - UserDetailsParserFactory & operator= - (const UserDetailsParserFactory &) = delete; + + private: + + // Parser isn't compiled with c++11 in all environments, and + // therefore "delete" of unused interfaces (like below) is not + // supported, nor are functions with move semantics + + // Disable compiler provided default functions + UserDetailsParserFactory( + const UserDetailsParserFactory &); + UserDetailsParserFactory & operator= ( + const UserDetailsParserFactory &); }; }; diff --git a/src/usr/secureboot/base/securerommgr.C b/src/usr/secureboot/base/securerommgr.C index 072fcf950..7e517c31d 100644 --- a/src/usr/secureboot/base/securerommgr.C +++ b/src/usr/secureboot/base/securerommgr.C @@ -34,12 +34,14 @@ #include <errl/errlmanager.H> #include "../common/securetrace.H" #include <kernel/bltohbdatamgr.H> +#include <errl/errludstring.H> +#include <string.h> #include "securerommgr.H" #include <secureboot/settings.H> #include <config.h> #include <console/consoleif.H> -#include <array> +#include <secureboot/containerheader.H> // Quick change for unit testing //#define TRACUCOMP(args...) TRACFCOMP(args) @@ -85,6 +87,61 @@ errlHndl_t verifyContainer(void * i_container, const SHA512_t* i_hwKeyHash) return l_errl; } +errlHndl_t verifyComponent( + const ContainerHeader& i_containerHeader, + const char* const i_pComponentId) +{ + assert(i_pComponentId != nullptr,"BUG! Component ID string was nullptr"); + + errlHndl_t pError = nullptr; + + if(strncmp(i_containerHeader.componentId(), + i_pComponentId, + sizeof(ROM_sw_header_raw::component_id)) != 0) + { + char pTruncatedComponentId[sizeof(ROM_sw_header_raw::component_id)+ + sizeof(uint8_t)]={0}; + strncpy(pTruncatedComponentId, + i_pComponentId, + sizeof(ROM_sw_header_raw::component_id)); + + TRACFCOMP(g_trac_secure,ERR_MRK"SECUREROM::verifyComponent: " + "Secure Boot verification failure; container's component ID of " + "[%s] does not match expected component ID of [%s] (truncated " + "from [%s]", + i_containerHeader.componentId(), + pTruncatedComponentId, + i_pComponentId); + + /*@ + * @errortype + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid SECUREBOOT::MOD_SECURE_VERIFY_COMPONENT + * @reasoncode SECUREBOOT::RC_ROM_VERIFY + * @devdesc Container's component ID does not match expected + * component ID + * @custdesc Secure Boot firmware validation failed + */ + pError = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SECUREBOOT::MOD_SECURE_VERIFY_COMPONENT, + SECUREBOOT::RC_ROM_VERIFY, + 0, + 0, + true /*Add HB Software Callout*/ ); + + ERRORLOG::ErrlUserDetailsStringSet stringSet; + stringSet.add("Actual component ID",i_containerHeader.componentId()); + stringSet.add("Expected ID (truncated)",pTruncatedComponentId); + stringSet.add("Expected ID (full)",i_pComponentId); + stringSet.addToLog(pError); + + pError->collectTrace(SECURE_COMP_NAME,ERROR_TRACE_SIZE); + } + + return pError; +} + /** * @brief Hash Signed Blob * diff --git a/src/usr/secureboot/base/test/securerommgrtest.H b/src/usr/secureboot/base/test/securerommgrtest.H index 7db0dc2cc..4a445b52f 100644 --- a/src/usr/secureboot/base/test/securerommgrtest.H +++ b/src/usr/secureboot/base/test/securerommgrtest.H @@ -25,7 +25,7 @@ #ifndef __SECUREROMMANAGERTEST_H #define __SECUREROMMANAGERTEST_H - +#include <array> #include <sys/mm.h> #include <sys/mmio.h> #include <vfs/vfs.H> @@ -35,6 +35,7 @@ #include <secureboot/service.H> #include <secureboot/secure_reasoncodes.H> #include <kernel/bltohbdatamgr.H> +#include <stddef.h> #include "../securerommgr.H" @@ -398,6 +399,132 @@ class SecureRomManagerTest : public CxxTest::TestSuite TRACFCOMP(g_trac_secure,EXIT_MRK"SecureRomManagerTest::test_hash_page_table_verify"); } + void test_verifyComponent(void) + { + errlHndl_t pError = nullptr; + + // Signed file variables + const char* signedFile_name = "secureboot_signed_container"; + void* signedFile_pageAddr = nullptr; + size_t signedFile_size = 0; + uint64_t signedFile_vaddr = 0; + + do { + + struct verifyComponentTest + { + const char* pActualCompId; + const char* pRefCompId; + bool shouldPass; + }; + + const std::vector<verifyComponentTest> tests = + { {"ABCD1234","ABCD12345", true }, + {"ABCD1234","ABCD1234" , true }, + {"ABCD1234","ABCD123" , false}, + {"ABCD123" ,"ABCD12345", false}, + {"ABCD123" ,"ABCD1234" , false}, + {"ABCD123" ,"ABCD123" , true }, + {"A" ,"A" , true }, + {"A" ,"B" , false}, + {"A" ,"AB" , false}, + {"A" ,"" , false}, + {"" ,"A" , false}, + {"" ,"" , true } }; + + // Call utility function + pError = loadSignedFile( signedFile_name, + signedFile_pageAddr, + signedFile_size, + signedFile_vaddr); + + if (pError) + { + TS_FAIL("SecureRomManagerTest::test_verifyComponent: " + "loadSignedFile() Failed"); + errlCommit(pError, SECURE_COMP_ID); + break; + } + + char pHeader[MAX_SECURE_HEADER_SIZE]={0}; + memcpy(pHeader,signedFile_pageAddr,sizeof(pHeader)); + + char* const pCompIdInContainer = pHeader + + offsetof(ROM_container_raw,prefix) + + offsetof(ROM_prefix_header_raw,ecid) + + offsetof(ROM_prefix_data_raw,sw_pkey_q) + + offsetof(ROM_sw_header_raw,component_id); + + const size_t compIdSize = sizeof(ROM_sw_header_raw::component_id); + + for(const auto& test : tests) + { + memset(pCompIdInContainer,0x00,compIdSize); + strncpy(pCompIdInContainer,test.pActualCompId,compIdSize); + SECUREBOOT::ContainerHeader containerHeader(pHeader); + + pError = SECUREBOOT::verifyComponent( + containerHeader, + test.pRefCompId); + if(pError) + { + if(test.shouldPass) + { + TS_FAIL("SecureRomManagerTest::test_verifyContainer: " + "Expected SECUREBOOT::verifyComponent to pass, but it " + "failed. Actual component ID was [%s], reference " + "component ID was [%s]", + test.pActualCompId, + test.pRefCompId); + errlCommit(pError, SECURE_COMP_ID); + } + else // Should fail + { + // But verify it's the right fail + if( ( pError->reasonCode() + != SECUREBOOT::RC_ROM_VERIFY) + || ( pError->moduleId() + != SECUREBOOT::MOD_SECURE_VERIFY_COMPONENT)) + { + TS_FAIL("SecureRomManagerTest::test_verifyContainer: " + "Expected SECUREBOOT::verifyComponent to fail with " + "reason code of 0x%04X and module ID of 0x%02, but " + "failed with reason code of 0x%04X and module ID " + "of 0x%02X. Actual component ID was [%s], " + "reference component ID was [%s]", + SECUREBOOT::RC_ROM_VERIFY, + SECUREBOOT::MOD_SECURE_VERIFY_COMPONENT, + pError->reasonCode(), + pError->moduleId(), + test.pActualCompId, + test.pRefCompId); + errlCommit(pError, SECURE_COMP_ID); + } + else + { + delete pError; + pError = nullptr; + } + } + } + else if(!test.shouldPass) + { + TS_FAIL("SecureRomManagerTest::test_verifyContainer: " + "Expected SECUREBOOT::verifyComponent to fail, but it " + "passed. Actual component ID was [%s], reference " + "component ID was [%s]", + test.pActualCompId, + test.pRefCompId); + } + } + + } while(0); + + if ( signedFile_pageAddr != nullptr ) + { + unloadSignedFile( signedFile_pageAddr, signedFile_size); + } + } }; /**********************************************************************/ |