diff options
author | Chen Du <duchen@us.ibm.com> | 2019-03-04 10:56:19 -0600 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2019-05-09 16:10:29 -0500 |
commit | bbbd68a140c9b34ccded9273d91e6b5bc97d0f28 (patch) | |
tree | 930afab97b728563743d597510fe3e473bd998b3 | |
parent | 6aeba3917d4d42f6b99a059eeacc57c850dca6b9 (diff) | |
download | blackbird-hostboot-bbbd68a140c9b34ccded9273d91e6b5bc97d0f28.tar.gz blackbird-hostboot-bbbd68a140c9b34ccded9273d91e6b5bc97d0f28.zip |
Add page tables to read only partitions
Changed partitions (WOFDATA, MEMD)
to be signed with a hash page table bit. This generates
a hash page table in the protected payload which will be
used to validate pages in the unprotected payload
Change-Id: I9be4b1f6e65b9a52a8b6ba23affdacc4d89f5295
RTC: 179519
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/72776
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
-rwxr-xr-x | src/build/buildpnor/genPnorImages.pl | 19 | ||||
-rw-r--r-- | src/include/securerom/ROM.H | 8 | ||||
-rw-r--r-- | src/include/usr/pnor/pnor_const.H | 4 | ||||
-rw-r--r-- | src/include/usr/pnor/pnor_reasoncodes.H | 7 | ||||
-rw-r--r-- | src/include/usr/pnor/pnorif.H | 1 | ||||
-rw-r--r-- | src/usr/pnor/pnorrp.C | 14 | ||||
-rw-r--r-- | src/usr/pnor/spnorrp.C | 217 | ||||
-rw-r--r-- | src/usr/pnor/spnorrp.H | 13 | ||||
-rw-r--r-- | src/usr/runtime/populate_hbruntime.C | 26 | ||||
-rw-r--r-- | src/usr/secureboot/base/securerommgr.C | 2 | ||||
-rw-r--r-- | src/usr/secureboot/common/containerheader.C | 3 | ||||
-rw-r--r-- | src/usr/util/runtime/utillidmgr_rt.C | 23 | ||||
-rw-r--r-- | src/usr/util/utillidpnor.C | 8 | ||||
-rw-r--r-- | src/usr/vfs/vfsrp.C | 2 | ||||
-rw-r--r-- | src/usr/vfs/vfsrp.H | 2 |
15 files changed, 287 insertions, 62 deletions
diff --git a/src/build/buildpnor/genPnorImages.pl b/src/build/buildpnor/genPnorImages.pl index 74b317c3a..eae4e1fe7 100755 --- a/src/build/buildpnor/genPnorImages.pl +++ b/src/build/buildpnor/genPnorImages.pl @@ -74,6 +74,7 @@ use constant VFS_MODULE_TABLE_MAX_SIZE => VFS_EXTENDED_MODULE_MAX # Flag parameter string passed into signing tools # Note spaces before/after are critical. use constant OP_SIGNING_FLAG => " --flags "; +use constant SW_FLAG_HAS_A_HPT => 0x80000000; # Security bits HW flag strings use constant OP_BUILD_FLAG => 0x80000000; use constant FIPS_BUILD_FLAG => 0x40000000; @@ -464,7 +465,10 @@ sub manipulateImages # Partitions that have a hash page table at the beginning of the section # for secureboot purposes. - my %hashPageTablePartitions = (HBI => 1); + # TODO: add back SBE and HCODE as per story 209485 + my %hashPageTablePartitions = (HBI => 1, + WOFDATA => 1, + MEMD => 1); if($ENV{'RM_HASH_PAGE_TABLE'}) { undef %hashPageTablePartitions; @@ -514,24 +518,24 @@ sub manipulateImages # Sections that have secureboot support. Secureboot still must be # enabled for secureboot actions on these partitions to occur. my $isNormalSecure = ($eyeCatch eq "HBBL"); - $isNormalSecure ||= ($eyeCatch eq "SBE"); - $isNormalSecure ||= ($eyeCatch eq "MEMD"); $isNormalSecure ||= ($eyeCatch eq "HBRT"); $isNormalSecure ||= ($eyeCatch eq "PAYLOAD"); $isNormalSecure ||= ($eyeCatch eq "OCC"); $isNormalSecure ||= ($eyeCatch eq "CAPP"); $isNormalSecure ||= ($eyeCatch eq "BOOTKERNEL"); - $isNormalSecure ||= ($eyeCatch eq "HCODE"); - $isNormalSecure ||= ($eyeCatch eq "CENHWIMG"); - $isNormalSecure ||= ($eyeCatch eq "WOFDATA"); $isNormalSecure ||= ($eyeCatch eq "IMA_CATALOG"); $isNormalSecure ||= ($eyeCatch eq "TESTRO"); $isNormalSecure ||= ($eyeCatch eq "TESTLOAD"); $isNormalSecure ||= ($eyeCatch eq "VERSION"); + $isNormalSecure ||= ($eyeCatch eq "CENHWIMG"); + $isNormalSecure ||= ($eyeCatch eq "SBE"); + $isNormalSecure ||= ($eyeCatch eq "HCODE"); my $isSpecialSecure = ($eyeCatch eq "HBB"); $isSpecialSecure ||= ($eyeCatch eq "HBD"); $isSpecialSecure ||= ($eyeCatch eq "HBI"); + $isSpecialSecure ||= ($eyeCatch eq "WOFDATA"); + $isSpecialSecure ||= ($eyeCatch eq "MEMD"); # Used to indicate security is supported in firmware my $secureSupported = $isNormalSecure || $isSpecialSecure; @@ -670,6 +674,9 @@ sub manipulateImages else { run_command("cp $tempImages{hashPageTable} $tempImages{PAYLOAD_TEXT}"); + # Hash table generated so need to set sw-flags + my $hex_sw_flag = sprintf("0x%08X", SW_FLAG_HAS_A_HPT); + $CUR_OPEN_SIGN_REQUEST .= " --sw-flags $hex_sw_flag "; } run_command("$CUR_OPEN_SIGN_REQUEST " diff --git a/src/include/securerom/ROM.H b/src/include/securerom/ROM.H index f4cf76528..0d97537e0 100644 --- a/src/include/securerom/ROM.H +++ b/src/include/securerom/ROM.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2018 */ +/* Contributors Listed Below - COPYRIGHT 2016,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -284,7 +284,7 @@ enum HW_SB_FLAGS // SW Security Flags enum SW_SB_FLAGS { - // placeholder + HASH_PAGE_TABLE_FLAG = 0x80000000 }; // Structure to store all hw and sw flag values in a container header @@ -295,7 +295,8 @@ struct sb_flags_t hw_opal(false), hw_phyp(false), hw_lab_override(false), - hw_key_transition(false) + hw_key_transition(false), + sw_hash(false) { } @@ -305,6 +306,7 @@ struct sb_flags_t bool hw_lab_override; ///< Whether to enable lab security override; ///< Only applicable for SBE partition bool hw_key_transition; ///< Indicates this is a key transition container + bool sw_hash; ///< Indicates presence of hash page table }; /** diff --git a/src/include/usr/pnor/pnor_const.H b/src/include/usr/pnor/pnor_const.H index 41d1ebdee..44050eb50 100644 --- a/src/include/usr/pnor/pnor_const.H +++ b/src/include/usr/pnor/pnor_const.H @@ -111,7 +111,8 @@ struct SectionInfo_t reprovision(false), Volatile(false), secure(false), - clearOnEccErr(false) + clearOnEccErr(false), + hasHashTable(false) {} SectionId id; /**< Identifier for this section */ const char* name; /**< Name of the section */ @@ -126,6 +127,7 @@ struct SectionInfo_t bool Volatile; /**< Section loses contents on non HB reboots */ bool secure; /**< Indicates if a section is secure */ bool clearOnEccErr; /**< Indicates on ECC errors, clear and reboot*/ + bool hasHashTable; /**< Indicates if there exists a hash page table*/ size_t secureProtectedPayloadSize; /**< Cache the secure payload size so that the secure container only needs to be parsed once */ diff --git a/src/include/usr/pnor/pnor_reasoncodes.H b/src/include/usr/pnor/pnor_reasoncodes.H index fb7435a33..10c3e7b22 100644 --- a/src/include/usr/pnor/pnor_reasoncodes.H +++ b/src/include/usr/pnor/pnor_reasoncodes.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -98,8 +98,7 @@ namespace PNOR MOD_PNORCOMMON_PARSETOC = 0xC0, /**< PNOR::parseTOC */ // spnorrp.C - // Note: 0xD0 is available, so should be the next one used for spnorrp. - // Remove this comment after doing so. + MOD_SPNORRP_VERIFY_PAGE = 0xD0, /**< SPnorRP::verify_page */ MOD_SPNORRP_DIDSTARTUPFAIL = 0xD1, /**< didSecureStartupFail(rc) */ MOD_SPNORRP_ALLOCATE_BLOCK = 0xD2, /**< SPnorRP::initDaemon */ MOD_SPNORRP_WAITFORMESSAGE = 0xD3, /**< SPnorRP::waitForMessage */ @@ -192,7 +191,7 @@ namespace PNOR RC_NOT_PAGE_ALIGNED = PNOR_COMP_ID | 0x3B, RC_SECURE_PRO_SIZE_MISMATCH = PNOR_COMP_ID | 0x3C, RC_READ_ONLY_PERM_FAIL = PNOR_COMP_ID | 0x3D, - + RC_VERIFY_PAGE_FAILED = PNOR_COMP_ID | 0x3E, //@fixme-RTC:131607-Temporary value to allow HWSV compile //termination_rc RC_PNOR_CORRUPTION = PNOR_COMP_ID | 0x99, diff --git a/src/include/usr/pnor/pnorif.H b/src/include/usr/pnor/pnorif.H index 11cc98a10..835c100d7 100644 --- a/src/include/usr/pnor/pnorif.H +++ b/src/include/usr/pnor/pnorif.H @@ -269,7 +269,6 @@ bool cmpSecurebootMagicNumber(const uint8_t* i_vaddr); * False otherwise. */ bool isSectionEmpty(const PNOR::SectionId i_section); - } // PNOR #endif diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C index af6ccf3fa..cb70eb94c 100644 --- a/src/usr/pnor/pnorrp.C +++ b/src/usr/pnor/pnorrp.C @@ -522,6 +522,7 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section, #ifdef CONFIG_SECUREBOOT o_info.secure = iv_TOC[id].secure; + o_info.size = iv_TOC[id].size; o_info.secureProtectedPayloadSize = 0; // for non secure sections // the protected payload size // defaults to zero @@ -591,6 +592,17 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section, // was done previously in pnor_common.C o_info.size -= PAGESIZE; + // Need to change size to accommodate for hash table + if (l_conHdr.sb_flags()->sw_hash) + { + o_info.vaddr += payloadTextSize; + // Hash page table needs to use containerSize as the base + // and subtract off header and hash table size + o_info.size = l_conHdr.totalContainerSize() - PAGE_SIZE - + payloadTextSize; + o_info.hasHashTable = true; + } + // cache the value in SectionInfo struct so that we can // parse the container header less often o_info.secureProtectedPayloadSize = payloadTextSize; @@ -598,11 +610,11 @@ errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section, else #endif { + o_info.size = iv_TOC[id].size; o_info.vaddr = iv_TOC[id].virtAddr; } o_info.flashAddr = iv_TOC[id].flashAddr; - o_info.size = iv_TOC[id].size; o_info.eccProtected = ((iv_TOC[id].integrity & FFS_INTEG_ECC_PROTECT) != 0) ? true : false; o_info.sha512Version = ((iv_TOC[id].version & FFS_VERS_SHA512) diff --git a/src/usr/pnor/spnorrp.C b/src/usr/pnor/spnorrp.C index 5b1ef5b03..a58f1c566 100644 --- a/src/usr/pnor/spnorrp.C +++ b/src/usr/pnor/spnorrp.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -41,6 +41,7 @@ #include <secureboot/trustedbootif.H> #include <secureboot/header.H> #include <sys/task.h> +#include <arch/ppc.H> extern trace_desc_t* g_trac_pnor; @@ -363,6 +364,15 @@ uint64_t SPnorRP::verifySections(SectionId i_id, PNOR::SectionIdToString(i_id)); } + // If hash table exists, need to adjust sizes + if (l_info.hasHashTable) + { + io_rec->hasHashTable = true; + l_info.vaddr -= l_info.secureProtectedPayloadSize; + l_info.size += l_info.secureProtectedPayloadSize; + io_rec->hashTableVaddr = l_info.vaddr; + } + l_info.vaddr -= PAGESIZE; // back up a page to expose the secure header l_info.size += PAGESIZE; // add a page to size to account for the header @@ -643,13 +653,23 @@ uint64_t SPnorRP::verifySections(SectionId i_id, SHA512_DIGEST_LENGTH); } - // set permissions on the secured pages to writable + // set permissions to be writable + // in the case of HPT this is the header + HPT + // in the case of no HPT this is the header + text region l_errhdl = setPermission(io_rec->secAddr, l_protectedSizeWithHdr, WRITABLE); - if(l_errhdl) + if (l_errhdl) { - TRACFCOMP(g_trac_pnor,"SPnorRP::verifySections set permissions " - "failed on text section"); + if (l_info.hasHashTable) + { + TRACFCOMP(g_trac_pnor, ERR_MRK"SPnorRP::verifySections set permissions " + "failed on header + hash page table"); + } + else + { + TRACFCOMP(g_trac_pnor, ERR_MRK"SPnorRP::verifySections set permissions " + "failed on header + text section"); + } break; } @@ -691,10 +711,18 @@ uint64_t SPnorRP::verifySections(SectionId i_id, break; } - - l_errhdl = setPermission(io_rec->secAddr + l_protectedSizeWithHdr, - unprotectedPayloadSize, - WRITABLE | WRITE_TRACKED); + if (l_info.hasHashTable) + { + l_errhdl = setPermission(io_rec->secAddr + l_protectedSizeWithHdr, + unprotectedPayloadSize, + READ_ONLY); + } + else + { + l_errhdl = setPermission(io_rec->secAddr + l_protectedSizeWithHdr, + unprotectedPayloadSize, + WRITABLE | WRITE_TRACKED); + } if(l_errhdl) { TRACFCOMP(g_trac_pnor,"SPnorRP::verifySections set permissions " @@ -704,8 +732,11 @@ uint64_t SPnorRP::verifySections(SectionId i_id, // Register the write tracked memory range to be flushed on // shutdown. - INITSERVICE::registerBlock(io_rec->secAddr + l_protectedSizeWithHdr, - unprotectedPayloadSize, SPNOR_PRIORITY); + if (!l_info.hasHashTable) + { + INITSERVICE::registerBlock(io_rec->secAddr + l_protectedSizeWithHdr, + unprotectedPayloadSize, SPNOR_PRIORITY); + } } else { @@ -738,6 +769,83 @@ uint64_t SPnorRP::verifySections(SectionId i_id, return l_rc; } +int64_t getHashPageTableIndex(const int64_t i_vaddr) +{ + return (i_vaddr / static_cast<int64_t>(PAGE_SIZE)) + 1; +} + + +PAGE_TABLE_ENTRY_t* getHashPageTableEntry(const int64_t i_vaddr, + const uint64_t i_hash_vaddr) +{ + int64_t l_index = getHashPageTableIndex(i_vaddr); + int64_t l_offset = l_index * HASH_PAGE_TABLE_ENTRY_SIZE; + + // l_offset is the offset for the start of the hash page table + // i_hash_vaddr is the vaddr for the start of the hash in SECURE + // subtract off DELTA of 3GB to get into TEMP space + return reinterpret_cast<PAGE_TABLE_ENTRY_t*>(l_offset + i_hash_vaddr - + VMM_VADDR_SPNOR_DELTA); +} + +errlHndl_t verify_page(const int64_t i_offset_vaddr, const uint64_t i_hash_vaddr, + const uint64_t i_hash_size) +{ + errlHndl_t l_errl = nullptr; + + // Get current hash page table entry in TEMP space + PAGE_TABLE_ENTRY_t* l_pageTableEntry = + getHashPageTableEntry(i_offset_vaddr, i_hash_vaddr); + + // Get previous hash page table entry in TEMP space + PAGE_TABLE_ENTRY_t* l_prevPageTableEntry = + getHashPageTableEntry(i_offset_vaddr - PAGE_SIZE, i_hash_vaddr); + + // Concatenate previous hash with current page data + std::vector< std::pair<void*,size_t> > l_blobs; + l_blobs.push_back(std::make_pair<void*,size_t>(l_prevPageTableEntry, + HASH_PAGE_TABLE_ENTRY_SIZE)); + + // To get to PNOR space, we have the address of the hash in SECURE space and + // we add hash table size to get passed the hash page table. Then we add + // i_offset_vaddr, the offset of the requested vaddr, to end up at the + // requested vaddr in SECURE space. Finally we subtract off 2 DELTAS of + // 3GB each to get to the requested vaddr in PNOR space + l_blobs.push_back(std::make_pair<void*,size_t>( + reinterpret_cast<void*>(i_offset_vaddr + + i_hash_vaddr + i_hash_size - + 2 * VMM_VADDR_SPNOR_DELTA), + PAGE_SIZE)); + SHA512_t l_curPageHash = {0}; + SECUREBOOT::hashConcatBlobs(l_blobs, l_curPageHash); + + // Compare existing hash page table entry with the derived one. + if (memcmp(l_pageTableEntry,l_curPageHash,HASH_PAGE_TABLE_ENTRY_SIZE) != 0) + { + TRACFCOMP(g_trac_pnor, "ERROR:>PNOR::verify_page secureboot verify fail on vaddr 0x%016llX", + i_hash_vaddr + i_hash_size + i_offset_vaddr); + /*@ + * @severity ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid MOD_SPNORRP_VERIFY_PAGE + * @reasoncode RC_VERIFY_PAGE_FAILED + * @userdata1 Kernel RC + * @userdata2 Virtual address accessed + * + * @devdesc Secureboot page verify failure + * @custdesc Corrupted flash image or firmware error during system boot + */ + l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + MOD_SPNORRP_VERIFY_PAGE, + RC_VERIFY_PAGE_FAILED, + TO_UINT64(EACCES), + i_offset_vaddr, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + l_errl->collectTrace(PNOR_COMP_NAME); + l_errl->collectTrace(SECURE_COMP_NAME); + } + return l_errl; +} + /** @@ -769,6 +877,7 @@ void SPnorRP::waitForMessage() // data[0] = virtual address requested // data[1] = address to place contents + uint64_t requested_vaddr = message->data[0]; eff_addr = reinterpret_cast<uint8_t*>(message->data[0]); user_addr = reinterpret_cast<uint8_t*>(message->data[1]); @@ -819,10 +928,34 @@ void SPnorRP::waitForMessage() TRACDCOMP( g_trac_pnor, "SPnorRP::waitForMessage got a" " request to read from secure space - " "message : user_addr=%p, eff_addr=%p, msgtype=%d, " - "textSize=0x%.16llX secAddr0x%.16llX", user_addr, + "textSize=0x%.16llX secAddr=0x%.16llX", user_addr, eff_addr, message->type, l_rec.textSize, l_rec.secAddr); + // If record has an associated hash page table, then we + // want to verify the page with the hash table in temp + if (SECUREBOOT::enabled() && l_rec.hasHashTable) + { + // Pass in the offset of just the data + int64_t offset_vaddr = requested_vaddr - + l_rec.hashTableVaddr - l_rec.textSize; + + // There is no hash table entry when we try to + // verify the header + if (offset_vaddr >= 0) { + l_errhdl = verify_page(offset_vaddr, + l_rec.hashTableVaddr, + l_rec.textSize); + } + + if (l_errhdl) + { + SECUREBOOT::handleSecurebootFailure(l_errhdl, false, true); + status_rc = -EFAULT; + break; + } + } + // determine the source of the data depending on // whether it is part of the secure payload. // by the way, this if could be removed to make this @@ -843,8 +976,8 @@ void SPnorRP::waitForMessage() // if the page came from temp space then free up // the temp page now that we're done with it // NOTE: secAddr points to Secure Header - if (eff_addr < ( (l_rec.secAddr + PAGESIZE) + - l_rec.textSize)) + if (!l_rec.hasHashTable && (eff_addr < ( (l_rec.secAddr + PAGESIZE) + + l_rec.textSize))) { mm_remove_pages(RELEASE, eff_addr - delta, PAGESIZE); @@ -924,7 +1057,6 @@ void SPnorRP::waitForMessage() // cache the record to use fields later as hints l_rec = *l_record; - } while (0); } break; @@ -936,7 +1068,7 @@ void SPnorRP::waitForMessage() do { // Disallow unload of HBB, HBI and Targeting if (l_id == HB_BASE_CODE || - l_id == HB_EXT_CODE || + l_id == HB_EXT_CODE || l_id == HB_DATA) { TRACFCOMP( g_trac_pnor, ERR_MRK"SPnorRP::waitForMessage> Secure unload of HBB, HBI, and targeting is not allowed secId=%d", l_id); @@ -998,7 +1130,7 @@ void SPnorRP::waitForMessage() size_t l_sizeWithHdr = PAGESIZE + l_rec->textSize; // if the section has an unsecured portion - if (l_sizeWithHdr != l_rec->infoSize) + if (l_sizeWithHdr != l_rec->infoSize && !l_rec->hasHashTable) { TRACFCOMP( g_trac_pnor, ERR_MRK"SPnorRP::waitForMessage> Attempting to unload an unsupported section: 0x%X textsize+hdr: 0x%llX infosize: 0x%llX (the two sizes must be equal)", l_id, l_sizeWithHdr, l_rec->infoSize); /*@ @@ -1031,6 +1163,40 @@ void SPnorRP::waitForMessage() } TRACDCOMP(g_trac_pnor,"Completely unloading %s", PNOR::SectionIdToString(l_id)); + if (l_rec->hasHashTable) + { + // remove unprotected pages + l_errhdl = removePages(l_rec->secAddr + PAGE_SIZE + l_rec->textSize, + l_rec->infoSize - PAGE_SIZE - l_rec->textSize); + if (l_errhdl) + { + TRACFCOMP(g_trac_pnor, + ERR_MRK"SPnorRP::waitForMessage> " + "removePages failed for address " + "0x%11X of length 0x%11X", + l_rec->secAddr + PAGE_SIZE + l_rec->textSize, + l_rec->infoSize - PAGE_SIZE - l_rec->textSize); + status_rc = -EFAULT; + break; + } + + l_errhdl = setPermission(l_rec->secAddr + PAGE_SIZE + l_rec->textSize, + l_rec->infoSize - PAGE_SIZE - l_rec->textSize, + NO_ACCESS); + if (l_errhdl) + { + TRACFCOMP(g_trac_pnor, + ERR_MRK"SPnorRP::waitForMessage> " + "setPermission failed for address " + "0x%11X of length 0x%11X", + l_rec->secAddr + PAGE_SIZE + l_rec->textSize, + l_rec->infoSize - PAGE_SIZE - l_rec->textSize); + + status_rc = -EFAULT; + break; + } + } + l_errhdl = removePages(l_rec->secAddr, l_sizeWithHdr); if (l_errhdl) @@ -1039,21 +1205,21 @@ void SPnorRP::waitForMessage() ERR_MRK"SPnorRP::waitForMessage> " "removePages failed for address " "0x%llX of length 0x%llX", l_rec->secAddr, - l_sizeWithHdr); + l_sizeWithHdr); status_rc = -EFAULT; break; } l_errhdl = setPermission(l_rec->secAddr, - l_sizeWithHdr, - NO_ACCESS); + l_sizeWithHdr, + NO_ACCESS); if (l_errhdl) { TRACFCOMP( g_trac_pnor, ERR_MRK"SPnorRP::waitForMessage> " "setPermission failed for address " "0x%llX of length 0x%llX", l_rec->secAddr, - l_sizeWithHdr); + l_sizeWithHdr); status_rc = -EFAULT; break; @@ -1067,7 +1233,7 @@ void SPnorRP::waitForMessage() l_sizeWithHdr); if (l_errhdl) { - TRACFCOMP( g_trac_pnor, + TRACFCOMP(g_trac_pnor, ERR_MRK"SPnorRP::waitForMessage> " "removePages failed for address " "0x%llX of length 0x%llX", l_tempAddr, @@ -1083,16 +1249,15 @@ void SPnorRP::waitForMessage() l_sizeWithHdr); l_errhdl = setPermission(l_tempAddr, - l_sizeWithHdr, - NO_ACCESS); + l_sizeWithHdr, + NO_ACCESS); if (l_errhdl) { - TRACFCOMP( g_trac_pnor, + TRACFCOMP(g_trac_pnor, ERR_MRK"SPnorRP::waitForMessage> " "setPermission failed for address " "0x%llX of length 0x%llX", l_tempAddr, l_sizeWithHdr); - status_rc = -EFAULT; break; } diff --git a/src/usr/pnor/spnorrp.H b/src/usr/pnor/spnorrp.H index 11da539ef..578858e5e 100644 --- a/src/usr/pnor/spnorrp.H +++ b/src/usr/pnor/spnorrp.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2017 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -113,13 +113,16 @@ class SPnorRP * Keep track of secured payload size and secure section addresses */ struct LoadRecord{ - uint8_t* secAddr; - size_t textSize; - size_t infoSize; + uint8_t* secAddr; // virtual address of the start of the record + uint64_t hashTableVaddr; // virtual address of the hash table (if it exists) + size_t textSize; // size of the protected payload, not including header + size_t infoSize; // size of the entire partition size_t refCount; + bool hasHashTable; // indicates if the record has a hash table + SHA512_t payloadTextHash; LoadRecord() - :secAddr(nullptr), textSize(0), infoSize(0), refCount(0) + :secAddr(nullptr), hashTableVaddr(0), textSize(0), infoSize(0), refCount(0), hasHashTable(false) { memset(&payloadTextHash[0], 0, SHA512_DIGEST_LENGTH); } diff --git a/src/usr/runtime/populate_hbruntime.C b/src/usr/runtime/populate_hbruntime.C index 371c3bee8..813620ddd 100644 --- a/src/usr/runtime/populate_hbruntime.C +++ b/src/usr/runtime/populate_hbruntime.C @@ -854,9 +854,18 @@ errlHndl_t fill_RsvMem_hbData(uint64_t & io_start_address, } #ifdef CONFIG_SECUREBOOT - memcpy(reinterpret_cast<uint8_t*>(l_prevDataAddr), - reinterpret_cast<uint8_t *>(l_memd_info.vaddr), - l_memd_info.secureProtectedPayloadSize); + if (l_memd_info.hasHashTable) + { + memcpy(reinterpret_cast<uint8_t*>(l_prevDataAddr), + reinterpret_cast<uint8_t *>(l_memd_info.vaddr), + l_memd_info.size); + } + else + { + memcpy(reinterpret_cast<uint8_t*>(l_prevDataAddr), + reinterpret_cast<uint8_t *>(l_memd_info.vaddr), + l_memd_info.secureProtectedPayloadSize); + } #else memcpy(reinterpret_cast<uint8_t*>(l_prevDataAddr), reinterpret_cast<uint8_t *>(l_memd_info.vaddr), @@ -1009,7 +1018,16 @@ errlHndl_t hbResvLoadSecureSection (const PNOR::SectionId i_sec, if (i_secHdrExpected) { // If section is signed, only the protected size was loaded into memory - l_imgSize = l_info.secureProtectedPayloadSize; + if (!l_info.hasHashTable) + { + l_imgSize = l_info.secureProtectedPayloadSize; + } + else + { + // Need to expose header and hash table + l_pnorVaddr -= l_info.secureProtectedPayloadSize; + l_imgSize += l_info.secureProtectedPayloadSize; + } // Include secure header // NOTE: we do not preserve the header in virtual memory when SB // is compiled out. So "-PAGESIZE" only works when SB is compiled in diff --git a/src/usr/secureboot/base/securerommgr.C b/src/usr/secureboot/base/securerommgr.C index 17becb6b6..87a9dccc9 100644 --- a/src/usr/secureboot/base/securerommgr.C +++ b/src/usr/secureboot/base/securerommgr.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2018 */ +/* Contributors Listed Below - COPYRIGHT 2013,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/usr/secureboot/common/containerheader.C b/src/usr/secureboot/common/containerheader.C index 53baa5afc..28c2c551f 100644 --- a/src/usr/secureboot/common/containerheader.C +++ b/src/usr/secureboot/common/containerheader.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2018 */ +/* Contributors Listed Below - COPYRIGHT 2016,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -514,6 +514,7 @@ void ContainerHeader::parseFlags() & LAB_OVERRIDE_FLAG); iv_sbFlags.hw_key_transition =( iv_headerInfo.hw_prefix_hdr.flags & KEY_TRANSITION_FLAG); + iv_sbFlags.sw_hash = iv_headerInfo.sw_hdr.flags & HASH_PAGE_TABLE_FLAG; } #ifndef __HOSTBOOT_RUNTIME diff --git a/src/usr/util/runtime/utillidmgr_rt.C b/src/usr/util/runtime/utillidmgr_rt.C index ad5a7cd48..55bebdeb3 100644 --- a/src/usr/util/runtime/utillidmgr_rt.C +++ b/src/usr/util/runtime/utillidmgr_rt.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2018 */ +/* Contributors Listed Below - COPYRIGHT 2013,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -192,13 +192,24 @@ errlHndl_t UtilLidMgr::loadLid() UTIL_FT(ERR_MRK"UtilLidMgr::loadLid - setheader failed"); break; } - iv_lidSize = l_conHdr.payloadTextSize(); UTIL_FT("UtilLidMgr::loadLid - resv mem section has secure header"); - - // Increment by page size to not expose secure header - iv_lidBuffer = static_cast<uint8_t*>(iv_lidBuffer) + - PAGESIZE; + if (l_conHdr.sb_flags()->sw_hash) + { + // Size of lid has to be size of unprotected data. So we + // need to take out header and hash table sizes + iv_lidSize = l_conHdr.totalContainerSize() - PAGESIZE - + l_conHdr.payloadTextSize(); + iv_lidBuffer = static_cast<uint8_t*>(iv_lidBuffer) + + PAGESIZE + l_conHdr.payloadTextSize(); + } + else + { + iv_lidSize = l_conHdr.payloadTextSize(); + // Increment by page size to not expose secure header + iv_lidBuffer = static_cast<uint8_t*>(iv_lidBuffer) + + PAGESIZE; + } } } else if(iv_isLidInVFS) diff --git a/src/usr/util/utillidpnor.C b/src/usr/util/utillidpnor.C index 7e910f6eb..8d81ad0c1 100644 --- a/src/usr/util/utillidpnor.C +++ b/src/usr/util/utillidpnor.C @@ -179,7 +179,13 @@ errlHndl_t UtilLidMgr::getLidPnorSectionInfo(const uint32_t i_lidId, // downstream logic from going past the end of the image. // NOTE: This assumes that any secure lid loaded from PNOR by // UtilLidMgr does not contain an unprotected section - iv_lidPnorInfo.size = iv_lidPnorInfo.secureProtectedPayloadSize; + // In this case of hash tables, we need to load the entire + // partition size because the user data is part of the + // unprotected payload + if (!iv_lidPnorInfo.hasHashTable) + { + iv_lidPnorInfo.size = iv_lidPnorInfo.secureProtectedPayloadSize; + } } #endif #endif diff --git a/src/usr/vfs/vfsrp.C b/src/usr/vfs/vfsrp.C index fde05d820..a200bcaab 100644 --- a/src/usr/vfs/vfsrp.C +++ b/src/usr/vfs/vfsrp.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/usr/vfs/vfsrp.H b/src/usr/vfs/vfsrp.H index ebf9c86fd..7530445c1 100644 --- a/src/usr/vfs/vfsrp.H +++ b/src/usr/vfs/vfsrp.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2017 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ |