Skip to content

Commit

Permalink
Secureboot best effort compatibility support
Browse files Browse the repository at this point in the history
Change-Id: I1671459ca58684b14f65f322ff6dccddcaad40a2
RTC: 170685
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/38104
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
  • Loading branch information
Stephen Cprek authored and dcrowell77 committed Mar 30, 2017
1 parent da8ebbb commit 7e53643
Show file tree
Hide file tree
Showing 16 changed files with 277 additions and 204 deletions.
19 changes: 3 additions & 16 deletions src/bootloader/bootloader.C
Expand Up @@ -137,19 +137,6 @@ namespace Bootloader{
sizeof(BlToHbData));
}

/**
* @brief Memcmp a vaddr to the known secureboot magic number
*
* @param[in] i_vaddr: vaddr of secureboot header to check for magic number
* Note: must point to a buffer of size >= 4 bytes
*
* @return bool - True if the magic number and starting bytes of the vaddr
* match. False otherwise.
*/
bool cmpSecurebootMagicNumber(const uint8_t* i_vaddr)
{
return memcmp(&ROM_MAGIC_NUMBER, i_vaddr, sizeof(ROM_MAGIC_NUMBER))==0;
}

/**
* @brief Verify Container against system hash keys
Expand Down Expand Up @@ -179,8 +166,8 @@ namespace Bootloader{
BOOTLOADER_TRACE(BTLDR_TRC_MAIN_VERIFY_NO_EYECATCH);
}
// # @TODO RTC:170136 terminate in this case
else if ( !cmpSecurebootMagicNumber(reinterpret_cast<const uint8_t*>
(i_pContainer)))
else if ( !PNOR::cmpSecurebootMagicNumber(
reinterpret_cast<const uint8_t*>(i_pContainer)))
{
BOOTLOADER_TRACE(BTLDR_TRC_MAIN_VERIFY_NO_MAGIC_NUM);
}
Expand Down Expand Up @@ -328,7 +315,7 @@ namespace Bootloader{
verifyContainer(l_src_addr);

// Increment past secure header
if (isSecureSection(PNOR::HB_BASE_CODE))
if (isEnforcedSecureSection(PNOR::HB_BASE_CODE))
{
l_src_addr += PAGE_SIZE/sizeof(uint64_t);
l_hbbLength -= PAGE_SIZE;
Expand Down
12 changes: 6 additions & 6 deletions src/build/buildpnor/genPnorImages.pl
Expand Up @@ -500,18 +500,18 @@ sub manipulateImages
# Sections that have secureboot support. Secureboot still must be
# enabled for secureboot actions on these partitions to occur.
# @TODO securebootp9 re-enable with SBE/SBEC/PAYLOAD secureboot ports
my $isNormalSecure = ($eyeCatch eq "SBKT")
|| ($eyeCatch eq "HBRT");
my $isNormalSecure = 0; #($eyeCatch eq "SBKT")
#|| ($eyeCatch eq "HBRT");
#|| ($eyeCatch eq "SBE")
#|| ($eyeCatch eq "SBEC")
#|| ($eyeCatch eq "PAYLOAD")
#|| ($eyeCatch eq "OCC")
#|| ($eyeCatch eq "CAPP")
#|| ($eyeCatch eq "BOOTKERNEL");

my $isSpecialSecure = ($eyeCatch eq "HBB")
|| ($eyeCatch eq "HBI")
|| ($eyeCatch eq "HBD");
my $isSpecialSecure = ($eyeCatch eq "HBB");
#|| ($eyeCatch eq "HBI")
#|| ($eyeCatch eq "HBD");

my $openSigningFlags = OP_SIGNING_FLAG.$sb_hdrs{DEFAULT}{flags};
my $secureboot_hdr = $sb_hdrs{DEFAULT}{file};
Expand Down Expand Up @@ -566,7 +566,7 @@ sub manipulateImages
$fsp_prefix.=".header";
# Add secure container header
# @TODO RTC:155374 Remove when official signing supported
if ($secureboot)
if ($secureboot && $isSpecialSecure)
{
$callerHwHdrFields{configure} = 1;
# @TODO securebootp9 re-enable hash page table with vfs page table port
Expand Down
1 change: 1 addition & 0 deletions src/build/debug/Hostboot/BlTrace.pm
Expand Up @@ -66,6 +66,7 @@ my %traceText = (
"E6" => "Utils checkHeader header size invalid",
"E7" => "Utils parseEntries invalid section",
"E8" => "Utils SectionIdToString PNOR section id out of range",
"E9" => "Utils cmpSecurebootMagicNumber requested address to compare is a nullptr",
"F0" => "Main getHBBSection returned",
"F1" => "Main removeECC returned error",
"F2" => "PNOR Access readTOC checkForNullBuffer null buffer",
Expand Down
5 changes: 4 additions & 1 deletion src/include/bootloader/bootloader_trace.H
Expand Up @@ -142,7 +142,10 @@ enum BootloaderTraces
BTLDR_TRC_UTILS_PARSE_INVALID_SECTION = 0xE7,

/** Bootloader Utils SectionIdToString PNOR section id out of range*/
BTLDR_TRC_UTILS_PARSE_PNOR_SECID_OUT_OF_RANGE = 0xE8,
BTLDR_TRC_UTILS_PNOR_SECID_OUT_OF_RANGE = 0xE8,

/** Bootloader Utils cmpSecurebootMagicNumber requested address to compare is a nullptr*/
BTLDR_TRC_UTILS_CMP_MAGIC_NUM_NULLPTR = 0xE9,

/** Bootloader main getHBBSection returned error */
BTLDR_TRC_MAIN_GETHBBSECTION_FAIL = 0xF0,
Expand Down
4 changes: 3 additions & 1 deletion src/include/bootloader/hbblreasoncodes.H
Expand Up @@ -48,7 +48,8 @@ namespace Bootloader
MOD_PNORACC_READTOC = 0x03, /**< bl_pnorAccess.C : read TOC */
MOD_PNORACC_GETHBBSECT = 0x04, /**< bl_pnorAccess.C : get HBB sect */
MOD_BOOTLOADER_VERIFY = 0x05, /**< bootloader.C : verifyContainer */
MOD_BOOTLOADER_PNOR_SECID_TO_STR = 0x06 /**< pnor_utils.C : SectionIdToString */
MOD_BOOTLOADER_PNOR_SECID_TO_STR = 0x06, /**< pnor_utils.C : SectionIdToString */
MOD_BOOTLOADER_PNOR_CMP_MAGIC_NUM = 0x07 /**< pnor_utils.C : cmpSecurebootMagicNumber */

};

Expand All @@ -73,6 +74,7 @@ namespace Bootloader
RC_PARSE_ENTRIES_ERR = HBBL_COMP_ID | 0x0B, /**< Parse Entries Error */
RC_NO_HBB_IN_TOC = HBBL_COMP_ID | 0x0C, /**< No HBB Sect in TOC */
RC_PNOR_SECID_OUT_OF_RANGE = HBBL_COMP_ID | 0x0D, /**< Requested PNOR SecId DNE in string array */
RC_PNOR_NULLPTR = HBBL_COMP_ID | 0x0E, /**< Requested address to compare is a nullptr */
};

}; // end Bootloader
Expand Down
19 changes: 18 additions & 1 deletion src/include/usr/pnor/pnor_const.H
Expand Up @@ -81,7 +81,7 @@ enum SectionId
// Size and layout of this structure must be maintained for debug framework.
struct SectionInfo_t
{
SectionInfo_t(): id(INVALID_SECTION) {}
SectionInfo_t(): id(INVALID_SECTION), secure(false) {}
SectionId id; /**< Identifier for this section */
const char* name; /**< Name of the section */
uint64_t vaddr; /**< Virtual address of the start of the section */
Expand All @@ -92,13 +92,30 @@ struct SectionInfo_t
bool sha512perEC; /**< Version Checking perEC */
bool readOnly; /**< Section is read only */
bool reprovision; /**< Erase this section during a reprovision */
bool secure; /**< Indicates if a section is secure */
#ifdef CONFIG_SECUREBOOT
size_t secureProtectedPayloadSize; /**< Cache the secure payload size so
that the secure container only
needs to be parsed once */
#endif
};

/**
* Internal information to deal with the sections of PNOR
*/
struct SectionData_t {
SectionData_t(): secure(false) {}
PNOR::SectionId id; /**< Identifier for this section */
uint64_t virtAddr; /**< Virtual address for the start of the section */
uint32_t flashAddr; /**< Address in flash */
uint32_t size;/**< Actual size of content in bytes (not including ECC)*/
uint8_t chip; /**< Chip Select */
uint8_t version; /**< Version Checking */
uint16_t integrity; /**< Data Integrity */
uint8_t misc; /**< Misc Flags */
uint8_t secure; /**< Indicates if a section is secure */
} PACKED;

/**
* PNOR Sides
*/
Expand Down
45 changes: 15 additions & 30 deletions src/include/usr/pnor/pnorif.H
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2011,2016 */
/* Contributors Listed Below - COPYRIGHT 2011,2017 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
Expand Down Expand Up @@ -112,37 +112,8 @@ errlHndl_t loadSecureSection(SectionId i_section);
*/
errlHndl_t unloadSecureSection(SectionId i_section);

/**
* @brief Memcmp a vaddr to the known secureboot magic number
*
* @param[in] i_vaddr: vaddr of secureboot header to check for magic number
* Note: must point to a buffer of size >= 4 bytes
*
* @return bool - True if the magic number and starting bytes of the vaddr
* match. False otherwise.
*/
bool cmpSecurebootMagicNumber(const uint8_t* i_vaddr);

/**
* @brief Returns true if a PNOR section has the secureboot container
* header magic number at the beginning. This is mainly used to
* ignore unwanted PNOR sections like secureboot key transition.
* It indicates the section has valid content to be securely
* loaded, otherwise the section content will not be loaded.
* If a section does not have the header but needs to be loaded,
* it will fail ROM verify later on anyhow.
* Note: Does not work with HBB section and will assert if attempted
*
* @param[in] i_section: PNOR section to check first bytes of.
* @param[out] o_valid: true if section has the correct magic number at
* the beginning
*
* @return errlHndl_t - NULL if success, errlHndl_t otherwise.
* */
errlHndl_t hasSecurebootMagicNumber(SectionId i_section, bool &o_valid);
#endif // CONFIG_SECUREBOOT


/**
* @brief Determines whether the given section is inhibited by secure boot
* for containing attribute overrides.
Expand Down Expand Up @@ -206,6 +177,20 @@ errlHndl_t validateAltMaster( void );
*/
void getPnorInfo( PnorInfo_t& o_pnorInfo );

/**
* @brief Check if PNOR section appears to be secure and sets the
* internal TOC of PnorRp accordingly.
* Note: The setting of the flag is based on the Secureboot policy.
*
* @param[in] i_secId Section ID or index in the TOC to modify
* @param[in] io_TOC Pointer to internal array of section data that
* represents the TOC of pnor flash
* Asserts if nullptr
*
* @return errlHndl_t Error log if request was invalid
*/
errlHndl_t setSecure(const uint32_t i_secId, SectionData_t* io_TOC);

} // PNOR

#endif
58 changes: 50 additions & 8 deletions src/usr/pnor/pnor_common.C
Expand Up @@ -235,12 +235,15 @@ errlHndl_t PNOR::parseTOC( uint8_t* i_tocBuffer,SectionData_t * o_TOC)

ffs_entry* l_err_entry = NULL;

PNOR::parseEntries(l_ffs_hdr, l_errCode, o_TOC, l_err_entry);

if(l_errCode != NO_ERROR)
l_errhdl = PNOR::parseEntries(l_ffs_hdr, l_errCode, o_TOC, l_err_entry);
if (l_errhdl)
{
TRACFCOMP(g_trac_pnor, "PNOR::parseTOC parseEntries"
" parse entries returned an error");
TRACFCOMP(g_trac_pnor, "PNOR::parseTOC parseEntries returned an error log");
break;
}
else if(l_errCode != NO_ERROR)
{
TRACFCOMP(g_trac_pnor, "PNOR::parseTOC parseEntries returned an error code");
o_TOC = NULL;
/* @errortype
* @moduleid PNOR::MOD_PNORRP_READTOC
Expand Down Expand Up @@ -295,9 +298,7 @@ errlHndl_t PNOR::parseTOC( uint8_t* i_tocBuffer,SectionData_t * o_TOC)

// @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)
if (PNOR::hasNonSecureHeader(o_TOC[l_secId]))
{
// Never extend the base image through this path, it will be
// handled elsewhere
Expand Down Expand Up @@ -385,3 +386,44 @@ bool PNOR::isInhibitedSection(const uint32_t i_section)
#endif
}

errlHndl_t PNOR::setSecure(const uint32_t i_secId,
PNOR::SectionData_t* io_TOC)
{
errlHndl_t l_errhdl = nullptr;

assert(io_TOC != nullptr, "PNOR::setSecure received a NULL toc to modify");

do {

// Set secure field based on enforced policy
io_TOC[i_secId].secure = PNOR::isEnforcedSecureSection(i_secId);

#ifndef __HOSTBOOT_RUNTIME
#ifdef CONFIG_SECUREBOOT_BEST_EFFORT
if (io_TOC[i_secId].secure)
{
// Apply best effort policy by checking if the section appears to have a
// secure header
size_t l_size = sizeof(ROM_MAGIC_NUMBER);
auto l_buf = new uint8_t[l_size]();
auto l_target = TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
// Read first 8 bytes of section data from the PNOR DD
// Note: Do not need to worry about ECC as the 9th byte is the first
// ECC byte.
l_errhdl = DeviceFW::deviceRead(l_target, l_buf, l_size,
DEVICE_PNOR_ADDRESS(0,io_TOC[i_secId].flashAddr));
if (l_errhdl)
{
break;
}

// Check if first 8 bytes match the Secureboot Magic Number
io_TOC[i_secId].secure &= PNOR::cmpSecurebootMagicNumber(l_buf);
}
#endif
#endif

} while (0);

return l_errhdl;
}

0 comments on commit 7e53643

Please sign in to comment.