Skip to content

Commit

Permalink
Secure Boot: Enforce PNOR section component IDs
Browse files Browse the repository at this point in the history
- 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>
  • Loading branch information
Nick Bofferding authored and wghoffa committed Nov 3, 2017
1 parent 47f275a commit 07d7575
Show file tree
Hide file tree
Showing 19 changed files with 625 additions and 49 deletions.
87 changes: 86 additions & 1 deletion src/bootloader/bootloader.C
Expand Up @@ -177,6 +177,89 @@ namespace Bootloader{
sizeof(BlToHbData));
}

/**
* @brief Verify container's component ID against a reference
* component ID. Up to 8 ASCII characters, not including NULL, will be
* compared (thus, it is critical that all components are unique with
* respect to the first 8 bytes).
*
* @param[in] i_pHeader Void pointer to start of the container's secure
* header. Must not be nullptr or function will assert.
* @param[in] i_pComponentId Reference component ID to compare to. Must
* not be nullptr or function will assert.
*/
void verifyComponent(
const void* const i_pHeader,
const char* const i_pComponentId)
{
assert(i_pHeader != nullptr);
assert(i_pComponentId != nullptr);

const auto* const pHwPrefix =
reinterpret_cast<const ROM_prefix_header_raw* const>(
reinterpret_cast<const uint8_t* const>(i_pHeader)
+ offsetof(ROM_container_raw,prefix));
const auto swKeyCount = pHwPrefix->sw_key_count;
const auto ecidCount = pHwPrefix->ecid_count;

const char* const pCompIdInContainer =
reinterpret_cast<const char* const>(i_pHeader)
+ offsetof(ROM_container_raw,prefix)
+ offsetof(ROM_prefix_header_raw,ecid)
+ ecidCount*ECID_SIZE
+ offsetof(ROM_prefix_data_raw,sw_pkey_p)
+ swKeyCount*sizeof(ecc_key_t)
+ offsetof(ROM_sw_header_raw,component_id);

if(strncmp(pCompIdInContainer,
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));

BOOTLOADER_TRACE(BTLDR_TRC_COMP_ID_VERIFY_FAILED);

// Read SBE HB shared data
const auto pBlConfigData = reinterpret_cast<
BootloaderConfigData_t *>(SBE_HB_COMM_ADDR);

/*@
* @errortype
* @moduleid Bootloader::MOD_BOOTLOADER_VERIFY_COMP_ID
* @reasoncode SECUREBOOT::RC_ROM_VERIFY
* @userdata1[0:15] TI_WITH_SRC
* @userdata1[16:31] TI_BOOTLOADER
* @userdata1[32:63] Failing address = 0
* @userdata2[0:31] First 4 bytes of observed component ID
* @userdata2[32:63] Last 4 bytes of observed component ID
* @errorInfo[0:15] SBE boot side
* @errorInfo[16:31] Unused
* @devdesc Container component ID verification failed.
* @custdesc Platform security violation detected
*/
bl_terminate(
MOD_BOOTLOADER_VERIFY_COMP_ID,
SECUREBOOT::RC_ROM_VERIFY,
*reinterpret_cast<const uint32_t*>(
pCompIdInContainer),
*reinterpret_cast<const uint32_t*>(
pCompIdInContainer+sizeof(uint32_t)),
true,
0,
TWO_UINT16_TO_UINT32(
pBlConfigData->sbeBootSide,0));
}
else
{
BOOTLOADER_TRACE(BTLDR_TRC_COMP_ID_VERIFY_SUCCESS);
}
}

/**
* @brief Verify Container against system hash keys
*
Expand Down Expand Up @@ -298,11 +381,13 @@ namespace Bootloader{
}

BOOTLOADER_TRACE(BTLDR_TRC_MAIN_VERIFY_SUCCESS);

verifyComponent(i_pContainer,
PNOR::SectionIdToString(PNOR::HB_BASE_CODE));
}
#endif
}


/** Bootloader main function to work with and start HBB.
*
* @return 0.
Expand Down
2 changes: 2 additions & 0 deletions src/build/debug/Hostboot/BlTrace.pm
Expand Up @@ -41,6 +41,8 @@ my %traceText = (
# @TODO RTC:167740 TI on failed magic # check once signing is widespread
"18" => "Main verify skip verification - no magic number ",
"19" => "Main verify skip verification - SAB unset ",
"1A" => "Main verify component ID succeeded",
"1B" => "Main verify component ID failed",
"20" => "HandleMMIO started",
"21" => "HandleMMIO started using BYTESIZE",
"24" => "HandleMMIO started using WORDSIZE",
Expand Down
6 changes: 6 additions & 0 deletions src/include/bootloader/bootloader_trace.H
Expand Up @@ -77,6 +77,12 @@ enum BootloaderTraces
/** Bootloader main verifyContainer skip verification - SAB unset */
BTLDR_TRC_MAIN_VERIFY_SAB_UNSET = 0x19,

/** Bootloader main verifyComponent succeeded */
BTLDR_TRC_COMP_ID_VERIFY_SUCCESS = 0x1A,

/** Bootloader main verifyComponent failed */
BTLDR_TRC_COMP_ID_VERIFY_FAILED = 0x1B,

/** Bootloader handleMMIO started */
BTLDR_TRC_HANDLEMMIO_START = 0x20,

Expand Down
1 change: 1 addition & 0 deletions src/include/bootloader/hbblreasoncodes.H
Expand Up @@ -49,6 +49,7 @@ namespace Bootloader
MOD_PNORACC_GETHBBSECT = 0x04, /**< bl_pnorAccess.C : get HBB sect */
MOD_BOOTLOADER_VERIFY = 0x05, /**< bootloader.C : verifyContainer */
MOD_BOOTLOADER_ASSERT = 0x06, /**< bootloader.H assert */
MOD_BOOTLOADER_VERIFY_COMP_ID = 0x07, /**< bootloader.C : verifyComponent */
};

/**
Expand Down
3 changes: 2 additions & 1 deletion src/include/string.h 100755 → 100644
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2010,2014 */
/* Contributors Listed Below - COPYRIGHT 2010,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -42,6 +42,7 @@ extern "C"
char* strcpy(char* d, const char* s);
char* strncpy(char* d, const char* s, size_t l);
int strcmp(const char* s1, const char* s2) __attribute__((pure));
int strncmp(const char* s1, const char* s2, size_t l) __attribute__((pure));
size_t strlen(const char* s1) __attribute__((pure));
size_t strnlen(const char* s1, size_t n) __attribute__((pure));

Expand Down
9 changes: 8 additions & 1 deletion src/include/usr/errl/errlreasoncodes.H
Expand Up @@ -62,7 +62,7 @@ namespace ERRORLOG
ERRL_LAST_ERR = ERRL_COMP_ID | 0xFF
};

// Identifiers for ERRL user data sections.
// Identifiers for ERRL user data subsections.
enum errlUserDetailDataSubsection
{
ERRL_UDT_NOFORMAT = 0x00,
Expand All @@ -74,6 +74,13 @@ namespace ERRORLOG
ERRL_UDT_CALLOUT = 0x06,
ERRL_UDT_PRINTK = 0x07,
ERRL_UDT_SENSOR = 0x08,
ERRL_UDT_STRING_SET = 0x09,
};

// Identifiers for ERRL user data subsection versions
enum errlUserDetailDataSubsectionVersion
{
ERRL_UDT_STRING_SET_VER_1 = 0x01,
};
};

Expand Down
62 changes: 57 additions & 5 deletions src/include/usr/errl/errludstring.H
Expand Up @@ -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. */
Expand Down Expand Up @@ -57,10 +59,60 @@ public:
*/
virtual ~ErrlUserDetailsString();

private:
// Disabled
ErrlUserDetailsString(const ErrlUserDetailsString &);
ErrlUserDetailsString & operator=(const ErrlUserDetailsString &);
private:

// Disable compiler provided default functions
ErrlUserDetailsString(
const ErrlUserDetailsString &);
ErrlUserDetailsString & operator=(
const ErrlUserDetailsString &);
ErrlUserDetailsString (
ErrlUserDetailsString&&) = delete;
ErrlUserDetailsString& operator = (
ErrlUserDetailsString&&) = delete;
};

/**
* @class ErrlUserDetailsStringSet
*
* @brief Adds multiple, tagged FFDC strings to an error log as user details
* data
*/
class ErrlUserDetailsStringSet : public ErrlUserDetails
{

public:

/**
* @brief Constructor; creates the object
*/
ErrlUserDetailsStringSet();

/**
* @brief Adds a new tagged string to the object's string cache
*
* @param[in] i_pDescriptionString Description of the string to add. Must
* not be nullptr or function will substitute an error message.
* @param[in] i_pString The string to add. Must not be nullptr or function
* will substitute an error message.
*/
void add(const char* i_pDescriptionString,
const char* i_pString);

/**
* @brief Destructor
*/
virtual ~ErrlUserDetailsStringSet();

// Disable compiler provided default functions
ErrlUserDetailsStringSet(
const ErrlUserDetailsStringSet&) = delete;
ErrlUserDetailsStringSet& operator=(
const ErrlUserDetailsStringSet&) = delete;
ErrlUserDetailsStringSet (
ErrlUserDetailsStringSet&&) = delete;
ErrlUserDetailsStringSet& operator = (
ErrlUserDetailsStringSet&&) = delete;
};

}
Expand Down
1 change: 1 addition & 0 deletions src/include/usr/secureboot/secure_reasoncodes.H
Expand Up @@ -40,6 +40,7 @@ namespace SECUREBOOT
MOD_SECURE_READ_REG = 0x06,
MOD_SECURE_WRITE_REG = 0x07,
MOD_SECURE_SETTINGS_INIT = 0x08,
MOD_SECURE_VERIFY_COMPONENT = 0x09,
};

enum SECUREReasonCode
Expand Down
20 changes: 20 additions & 0 deletions src/include/usr/secureboot/service.H
Expand Up @@ -58,6 +58,8 @@ typedef uint8_t PAGE_TABLE_ENTRY_t[HASH_PAGE_TABLE_ENTRY_SIZE];

namespace SECUREBOOT
{
class ContainerHeader;

/** @brief Perform initialization of Secureboot for the Base image.
*
* - Copy secure header from original location.
Expand Down Expand Up @@ -222,6 +224,24 @@ namespace SECUREBOOT
errlHndl_t verifyContainer(void * i_container,
const SHA512_t* i_hwKeyHash = nullptr);

/**
* @brief Verify component ID in a container header against a reference
* component ID. Up to 8 ASCII characters, not including NULL, will be
* compared (thus, it is critical that all components are unique with
* respect to the first 8 bytes).
*
* @param[in] i_containerHeader Verified container's header
* @param[in] i_pComponentString Reference component ID string; must not be
* nullptr or function will assert.
*
* @return errlHndl_t Error log handle
* @retval nullptr Component ID verification succeeded
* @retval !nullptr Error; component ID verification failed
*/
errlHndl_t verifyComponent(
const ContainerHeader& i_containerHeader,
const char* i_pComponentId);

/**
* @brief Hash Signed Blob
*
Expand Down
22 changes: 0 additions & 22 deletions src/lib/string.C
Expand Up @@ -78,28 +78,6 @@ extern "C" char* strcpy(char* d, const char* s)
} while(1);
}

extern "C" char* strncpy(char* d, const char* s, size_t l)
{
char* d1 = d;
size_t len = 0;

do
{
if (len++ >= l) break;
*d1 = *s;
if (*s == '\0') break;
d1++; s++;
} while(1);

// pad the remainder
while( len < l )
{
d1[len++] = '\0';
}

return d;
}

extern "C" int strcmp(const char* a, const char* b)
{
while((*a != '\0') && (*b != '\0'))
Expand Down
59 changes: 58 additions & 1 deletion src/lib/string_utils.C
Expand Up @@ -120,4 +120,61 @@ extern "C" int memcmp(const void *p1, const void *p2, size_t len)
}

return 0;
}
}

extern "C" int strncmp(const char* a, const char* b, size_t l)
{
if(l==0)
{
return 0;
}

const char* begin=a;
while( (*a != '\0') && (*b != '\0')
&& (static_cast<size_t>(a-begin)+1<l) )
{
if (*a == *b)
{
a++; b++;
}
else
{
return (*a > *b) ? 1 : -1;
}
}
if (*a == *b)
{
return 0;
}
if (*a == '\0')
{
return -1;
}
else
{
return 1;
}
}

extern "C" char* strncpy(char* d, const char* s, size_t l)
{
char* d1 = d;
size_t len = 0;

do
{
if (len++ >= l) break;
*d1 = *s;
if (*s == '\0') break;
d1++; s++;
} while(1);

// pad the remainder
while( len < l )
{
d1[len++] = '\0';
}

return d;
}

0 comments on commit 07d7575

Please sign in to comment.