diff options
-rw-r--r-- | img/.gitignore | 1 | ||||
-rwxr-xr-x | src/build/buildpnor/genPnorImages.pl | 10 | ||||
-rwxr-xr-x | src/build/tools/hb | 5 | ||||
-rwxr-xr-x | src/build/tools/hbDistribute | 7 | ||||
-rw-r--r-- | src/include/sys/vfs.h | 7 | ||||
-rw-r--r-- | src/include/usr/vfs/vfs_reasoncodes.H | 6 | ||||
-rw-r--r-- | src/makefile | 1 | ||||
-rw-r--r-- | src/usr/pnor/spnorrp.C | 3 | ||||
-rw-r--r-- | src/usr/secureboot/base/test/makefile | 3 | ||||
-rw-r--r-- | src/usr/secureboot/base/test/securerommgrtest.H | 232 | ||||
-rw-r--r-- | src/usr/vfs/vfsrp.C | 220 | ||||
-rw-r--r-- | src/usr/vfs/vfsrp.H | 88 |
12 files changed, 508 insertions, 75 deletions
diff --git a/img/.gitignore b/img/.gitignore index cb339c260..6edc0175e 100644 --- a/img/.gitignore +++ b/img/.gitignore @@ -20,3 +20,4 @@ test_signed_container secureboot_signed_container *.protected *.unprotected +secureboot_hash_page_table_container diff --git a/src/build/buildpnor/genPnorImages.pl b/src/build/buildpnor/genPnorImages.pl index 3c8d4c973..fb5c5f5d7 100755 --- a/src/build/buildpnor/genPnorImages.pl +++ b/src/build/buildpnor/genPnorImages.pl @@ -541,7 +541,7 @@ 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 "HBBL"); + my $isNormalSecure = ($eyeCatch eq "HBBL"); $isNormalSecure ||= ($eyeCatch eq "SBE"); $isNormalSecure ||= ($eyeCatch eq "HBRT"); #$isNormalSecure ||= ($eyeCatch eq "SBEC"); @@ -552,7 +552,7 @@ sub manipulateImages my $isSpecialSecure = ($eyeCatch eq "HBB"); $isSpecialSecure ||= ($eyeCatch eq "HBD"); - #$isSpecialSecure ||= ($eyeCatch eq "HBI"); + $isSpecialSecure ||= ($eyeCatch eq "HBI"); # Used to indicate security is supported in firmware my $secureSupported = $isNormalSecure || $isSpecialSecure; @@ -620,8 +620,7 @@ sub manipulateImages if ($secureboot && $secureSupported) { $callerHwHdrFields{configure} = 1; - # @TODO securebootp9 re-enable hash page table with vfs page table port - if (0) #exists $hashPageTablePartitions{$eyeCatch}) + if (exists $hashPageTablePartitions{$eyeCatch}) { if ($eyeCatch eq "HBI") { @@ -635,8 +634,7 @@ sub manipulateImages } } # Add hash page table - # @TODO securebootp9 re-enable hash page table with vfs page table port - if (0) #$tempImages{hashPageTable} ne "" && -e $tempImages{hashPageTable}) + if ($tempImages{hashPageTable} ne "" && -e $tempImages{hashPageTable}) { trace(1,"Adding hash page table for $eyeCatch"); my $hashPageTableSize = -s $tempImages{hashPageTable}; diff --git a/src/build/tools/hb b/src/build/tools/hb index fb049d5f4..ceb40b7bb 100755 --- a/src/build/tools/hb +++ b/src/build/tools/hb @@ -6,7 +6,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2011,2016 +# Contributors Listed Below - COPYRIGHT 2011,2017 # [+] International Business Machines Corp. # # @@ -242,9 +242,6 @@ hb_helptext() echo " #!/bin/sh" echo " export SANDBOXROOT=~/sandboxes" echo " export SANDBOXNAME=hostboot" - echo " # Dev key signing of images for secureboot" - echo " export SIGNING_DIR=/esw/san2/hostboot/secure-boot/secure-boot-scripts/rom_new_header/sign/obj" - echo " export DEV_KEY_DIR=/esw/san2/hostboot/secure-boot/dev_keys" echo echo " See also:" echo " All other sub-commands." diff --git a/src/build/tools/hbDistribute b/src/build/tools/hbDistribute index 003905e93..99119c818 100755 --- a/src/build/tools/hbDistribute +++ b/src/build/tools/hbDistribute @@ -199,6 +199,13 @@ else export DEFAULT_PNOR=1 fi +# Clean up preivous rand files. Should only be needed if a previous call failed. +# Done before dist.targets.mk because there are parallel operations that occur. +# So if we delete in genPnorImages.pl we would wipe out stuff currently being +# used elsewhere and cause a file not found error. +# Note: Prefix is set by genPnorImages.pl +rm -f ${SANDBOXROOT}/${SANDBOXNAME}/obj/ppc/hbfw/img/rand-* + # Execute makefile for distribution. mkdir -p $TARGET_DIR mkdir -p $SBFW_DIR diff --git a/src/include/sys/vfs.h b/src/include/sys/vfs.h index 7bbe73e30..fabe546cc 100644 --- a/src/include/sys/vfs.h +++ b/src/include/sys/vfs.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2010,2015 */ +/* Contributors Listed Below - COPYRIGHT 2010,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -44,6 +44,7 @@ #define VFS_EXTENDED_MODULE_VADDR (1 * 1024 * 1024 * 1024) #define VFS_EXTENDED_MODULE_TABLE_ADDRESS (VFS_EXTENDED_MODULE_VADDR) #define VFS_EXTENDED_MODULE_TABLE_OFFSET 0 +// Note: VFS_EXTENDED_MODULE_MAX used in src/build/buildpnor/buildpnor.pl #define VFS_EXTENDED_MODULE_MAX 128 #define VFS_MODULE_NAME_MAX 64 #define VFS_SYMBOL_INIT _init @@ -82,6 +83,8 @@ enum VfsMessages VFS_MSG_UNLOAD, //!< Message to vfsrp to unload a module }; +// Note: size of VfsSystemModule (VFS_MODULE_TABLE_ENTRY_SIZE) used in +// src/build/buildpnor/buildpnor.pl struct VfsSystemModule { char module[VFS_MODULE_NAME_MAX]; //!< Module name @@ -97,6 +100,8 @@ extern VfsSystemModule VFS_MODULES[VFS_MODULE_MAX]; extern uint64_t VFS_LAST_ADDRESS; +#define VFS_MODULE_TABLE_SIZE (VFS_EXTENDED_MODULE_MAX * sizeof(VfsSystemModule)) + // Offset for TLS "dtv-relative displacement". // See http://www.uclibc.org/docs/tls-ppc64.txt #define VFS_PPC64_DTPREL_OFFSET 0x8000 diff --git a/src/include/usr/vfs/vfs_reasoncodes.H b/src/include/usr/vfs/vfs_reasoncodes.H index 2d29aba58..99c78c2da 100644 --- a/src/include/usr/vfs/vfs_reasoncodes.H +++ b/src/include/usr/vfs/vfs_reasoncodes.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,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. */ @@ -35,6 +37,7 @@ namespace VFS VFS_WATCHER = 0x03, VFS_MODULE_LOAD_MONITOR = 0x04, VFS_MODULE_EXEC_MONITOR = 0x05, + VFS_VERIFY_PAGE = 0x06, }; enum VfsReasonCode @@ -46,6 +49,7 @@ namespace VFS VFS_MODULE_DOES_NOT_EXIST = VFS_COMP_ID | 0x05, VFS_INVALID_DATA_MODULE = VFS_COMP_ID | 0x06, VFS_TASK_CRASHED = VFS_COMP_ID | 0x07, + VFS_PAGE_VERIFY_FAILED = VFS_COMP_ID | 0x08, }; }; diff --git a/src/makefile b/src/makefile index bfa05ca9b..3a13f2971 100644 --- a/src/makefile +++ b/src/makefile @@ -345,6 +345,7 @@ hbicore_test_DATA_MODULES += ${hbicore_DATA_MODULES} hbicore_test_DATA_MODULES += testdata ifndef SKIP_BINARY_FILES hbicore_test_DATA_MODULES += secureboot_signed_container +hbicore_test_DATA_MODULES += secureboot_hash_page_table_container endif hbicore_test_LDFILE = kernel.ld diff --git a/src/usr/pnor/spnorrp.C b/src/usr/pnor/spnorrp.C index f9d286da0..7c6e48a5d 100644 --- a/src/usr/pnor/spnorrp.C +++ b/src/usr/pnor/spnorrp.C @@ -816,14 +816,11 @@ errlHndl_t SPnorRP::miscSectionVerification(const uint8_t *i_vaddr, // Do any additional verification needed for a specific PNOR section switch (i_secId) { - // TODO securebootp9 - remove the following #if 0 and address issues - #if 0 case HB_EXT_CODE: // Compare HBB and HBI versions. Pass the vaddr of HBI's hash page // table by skipping past the container header. l_errl = baseExtVersCheck((i_vaddr + PAGESIZE)); break; - #endif case SBKT: // Ensure the nested container of the SBKT partition has a valid key // transition container and that the outer containers' key diff --git a/src/usr/secureboot/base/test/makefile b/src/usr/secureboot/base/test/makefile index 293daed2e..3e2f54266 100644 --- a/src/usr/secureboot/base/test/makefile +++ b/src/usr/secureboot/base/test/makefile @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2013,2016 +# Contributors Listed Below - COPYRIGHT 2013,2017 # [+] International Business Machines Corp. # # @@ -28,6 +28,7 @@ MODULE = testsecureboot TESTS = *.H BINARY_FILES = $(IMGDIR)/secureboot_signed_container:7cff7a85f0db014016a61eac856c3775cd266240 +BINARY_FILES += $(IMGDIR)/secureboot_hash_page_table_container:16ccaff1e3c94cf17c2858e3a917dd9d64528848 include ${ROOTPATH}/config.mk diff --git a/src/usr/secureboot/base/test/securerommgrtest.H b/src/usr/secureboot/base/test/securerommgrtest.H index 4ef0db2a6..a10bd853c 100644 --- a/src/usr/secureboot/base/test/securerommgrtest.H +++ b/src/usr/secureboot/base/test/securerommgrtest.H @@ -40,6 +40,11 @@ #include "../../common/securetrace.H" +#include <secureboot/containerheader.H> +#include "../../../vfs/vfsrp.H" +#include <sys/vfs.h> +#include <kernel/console.H> + // Quick change for unit testing //#define TRACUCOMP(args...) TRACFCOMP(args) #define TRACUCOMP(args...) @@ -76,6 +81,23 @@ const sha2_hash_t hw_key_hash = 0xfb,0x70,0x85,0x35,0x1d,0x01,0xd6,0xd1 }; + +// secureboot_signed_container payload text size +size_t payload_text_size = 0x200; + +// secureboot_signed_container payload text hash +const SHA512_t payload_text_hash = +{ + 0xff,0xc3,0x93,0xb7,0x71,0xc4,0x09,0xd4, + 0x4d,0x8f,0xef,0xfa,0xcf,0xeb,0x7a,0x09, + 0x11,0x7c,0x75,0x3f,0x62,0x27,0x34,0x70, + 0xc2,0x93,0x24,0x04,0xea,0xd1,0x51,0xd5, + 0xba,0xe5,0x2e,0xbd,0x49,0x30,0x10,0x61, + 0xee,0x53,0x7b,0x7f,0xd9,0x64,0xac,0x84, + 0x97,0x21,0x64,0xa3,0x09,0x6c,0x87,0xc4, + 0x65,0x3e,0x8e,0xcb,0xfe,0x8f,0x4a,0xc5 +}; + /**********************************************************************/ /* End of UTILITY FUNCTIONS */ /**********************************************************************/ @@ -91,7 +113,7 @@ class SecureRomManagerTest : public CxxTest::TestSuite { TRACUCOMP(g_trac_secure,ENTER_MRK"SecureRomManagerTest::test_verify>"); - errlHndl_t l_errl = NULL; + errlHndl_t l_errl = nullptr; /*******************************************************************/ /* Load "secureboot_signed_container" from PNOR to use for verification */ @@ -99,7 +121,7 @@ class SecureRomManagerTest : public CxxTest::TestSuite // Signed file variables const char * signedFile_name = "secureboot_signed_container"; - void * signedFile_pageAddr = NULL; + void * signedFile_pageAddr = nullptr; size_t signedFile_size = 0; uint64_t signedFile_vaddr = 0; @@ -134,7 +156,7 @@ class SecureRomManagerTest : public CxxTest::TestSuite /*******************************************************************/ /* Unload "secureboot_signed_container" from memory */ /*******************************************************************/ - if ( signedFile_pageAddr != NULL ) + if ( signedFile_pageAddr != nullptr ) { unloadSignedFile( signedFile_pageAddr, signedFile_size); } @@ -177,6 +199,204 @@ class SecureRomManagerTest : public CxxTest::TestSuite TRACUCOMP(g_trac_secure,EXIT_MRK"SecureRomManagerTest::test_sha512"); } + + /** + * @brief Secure ROM Test - Parse a Signed Container and check if the values + * match what's expected for secureboot_signed_container + */ + void test_parse_container_header(void) + { + TRACFCOMP(g_trac_secure,ENTER_MRK"SecureRomManagerTest::test_parse_container_header>"); + + errlHndl_t l_errl = nullptr; + + /*******************************************************************/ + /* Load "secureboot_signed_container" from PNOR to use for verification */ + /*******************************************************************/ + + // 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{ + + // Call utility function + l_errl = loadSignedFile( signedFile_name, + signedFile_pageAddr, + signedFile_size, + signedFile_vaddr); + + if (l_errl) + { + TS_FAIL("SecureRomManagerTest::test_parse_container_header: loadSignedFile() Failed"); + errlCommit(l_errl, SECURE_COMP_ID); + break; + } + + TRACUCOMP(g_trac_secure, "SecureRomManagerTest::test_parse_container_header: " + "signedFile info: addr = %p, size=0x%x", + signedFile_pageAddr, signedFile_size); + + /*******************************************************************/ + /* Parse Secure Container Header */ + /*******************************************************************/ + SECUREBOOT::ContainerHeader l_conHdr(signedFile_pageAddr); + + // Check if container header seems valid + if (!l_conHdr.iv_isValid) + { + TS_FAIL("SecureRomManagerTest::test_parse_container_header: Header is not valid"); + break; + } + // Check a few of the values that are parsed out. + if(l_conHdr.payloadTextSize() != payload_text_size) + { + TS_FAIL("SecureRomManagerTest::test_parse_container_header: Incorrect payload text size"); + break; + } + + if (memcmp(l_conHdr.payloadTextHash(), payload_text_hash, + sizeof(SHA512_t) != 0)) + { + TS_FAIL("SecureRomManagerTest::test_parse_container_header: Incorrect payload text hash"); + break; + } + + } while(0); + /*******************************************************************/ + /* Unload "secureboot_signed_container" from memory */ + /*******************************************************************/ + if ( signedFile_pageAddr != nullptr ) + { + unloadSignedFile( signedFile_pageAddr, signedFile_size); + } + + TRACFCOMP(g_trac_secure,EXIT_MRK"SecureRomManagerTest::test_parse_container_header"); + } + + /** + * @brief Secure ROM Test - Verification of pages via a hash page table at + * the beginning of a payload text section. + */ + void test_hash_page_table_verify(void) + { + TRACFCOMP(g_trac_secure,ENTER_MRK"SecureRomManagerTest::test_hash_page_table_verify>"); + + errlHndl_t l_errl = nullptr; + // secureboot_hash_page_table_container has 5 pages of data + const uint64_t TEST_PAGE_NUM = 2; + + // Signed file variables + const char * signedFile_name = "secureboot_hash_page_table_container"; + void * signedFile_pageAddr = nullptr; + size_t signedFile_size = 0; + uint64_t signedFile_vaddr = 0; + + uint8_t* l_originPage = new uint8_t[PAGESIZE](); + + do{ + + // Call utility function + l_errl = loadSignedFile( signedFile_name, + signedFile_pageAddr, + signedFile_size, + signedFile_vaddr); + + if (l_errl) + { + TS_FAIL("SecureRomManagerTest::test_hash_page_table_verify: loadSignedFile() Failed"); + errlCommit(l_errl, SECURE_COMP_ID); + break; + } + + TRACUCOMP(g_trac_secure, "SecureRomManagerTest::test_hash_page_table_verify: " + "signedFile info: addr = %p, size=0x%x", + signedFile_pageAddr, signedFile_size); + + /*******************************************************************/ + /* Parse Secure Container Header */ + /*******************************************************************/ + + SECUREBOOT::ContainerHeader l_conHdr(signedFile_pageAddr); + size_t l_payloadTextSize = l_conHdr.payloadTextSize(); + TRACUCOMP(g_trac_secure, "SecureRomManagerTest::test_hash_page_table_verify ContainerHeader payload_size = 0x%X", + l_payloadTextSize); + + /*******************************************************************/ + /* Test Verifying a correct page */ + /*******************************************************************/ + + // Get base offset of test container with respect to the HBI section + signedFile_vaddr-=VFS_EXTENDED_MODULE_VADDR; + uint64_t l_hashPageTableOffset = signedFile_vaddr + PAGE_SIZE; + uint64_t l_baseOffset = signedFile_vaddr + + PAGE_SIZE + + l_payloadTextSize; + + // Get offset of TEST_PAGE_NUM + uint64_t l_vaddr = l_baseOffset + + (TEST_PAGE_NUM * PAGESIZE); + + // Verify a page + TRACUCOMP(g_trac_secure, "SecureRomManagerTest::test_hash_page_table_verify vaddr = 0x%X, base offset = 0x%X, hash page table offset = 0x%X", + l_vaddr, l_baseOffset, l_hashPageTableOffset); + l_errl = VFS::VfsRp::getInstance().verify_page(l_vaddr, + l_baseOffset, + l_hashPageTableOffset); + // Failed to pass secureboot verification + if (l_errl) + { + TS_FAIL("SecureRomManagerTest::test_hash_page_table_verify failed"); + errlCommit(l_errl, SECURE_COMP_ID); + break; + } + + /*******************************************************************/ + /* Test verifying a corrupt page */ + /*******************************************************************/ + + // Calculate pnor vaddr and read original page so we can run test case + // in both secure and unsecure mode. + uint64_t l_pnorVaddr = VFS::VfsRp::getInstance().iv_pnor_vaddr + + l_vaddr; + memcpy(l_originPage, reinterpret_cast<uint8_t*>(l_pnorVaddr), PAGESIZE); + + // Corrupt page + uint8_t l_corruptByte = 0xFF; + memcpy(reinterpret_cast<uint8_t*>(l_pnorVaddr), &l_corruptByte, sizeof(uint8_t)); + l_errl = VFS::VfsRp::getInstance().verify_page(l_vaddr, + l_baseOffset, + l_hashPageTableOffset); + + // Fix page back up + memcpy(reinterpret_cast<uint8_t*>(l_pnorVaddr), l_originPage, PAGESIZE); + + // Failed to catch secureboot verification failure + if (!l_errl) + { + TS_FAIL("SecureRomManagerTest::test_hash_page_table_verify did not catch verification error"); + break; + } + delete l_errl; + l_errl = nullptr; + + } while(0); + + if ( signedFile_pageAddr != nullptr ) + { + unloadSignedFile( signedFile_pageAddr, signedFile_size); + } + if (l_originPage != nullptr) + { + delete [] l_originPage; + l_originPage = nullptr; + } + + TRACFCOMP(g_trac_secure,EXIT_MRK"SecureRomManagerTest::test_hash_page_table_verify"); + } + }; /**********************************************************************/ @@ -190,8 +410,8 @@ errlHndl_t loadSignedFile( const char * i_signedFile_name, uint64_t & o_signedFile_virtAddr) { - errlHndl_t l_errl = NULL; - const char * l_signedFile_virtAddr = NULL; + errlHndl_t l_errl = nullptr; + const char * l_signedFile_virtAddr = nullptr; /*******************************************************************/ /* Load file from PNOR to use for verification */ @@ -251,7 +471,7 @@ void unloadSignedFile( void * & io_signedFile_pageAddr, PageManager::freePage(io_signedFile_pageAddr, l_num_pages); // Reset pageAddr pointer - io_signedFile_pageAddr = NULL; + io_signedFile_pageAddr = nullptr; TRACUCOMP(g_trac_secure, "unloadSignedFile()> " "Info: sF_pA=%p, size=0x%x (pages=%d)", diff --git a/src/usr/vfs/vfsrp.C b/src/usr/vfs/vfsrp.C index 125197b89..6284edd5a 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,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,6 +42,10 @@ #include <util/align.H> #include <errl/errludstring.H> #include <errl/errlmanager.H> +#include <secureboot/service.H> +#include <secureboot/containerheader.H> +#include <kernel/console.H> +#include <config.h> using namespace VFS; @@ -136,54 +140,89 @@ errlHndl_t VfsRp::_init() { errlHndl_t err = NULL; size_t rc = 0; + + do { + iv_msgQ = msg_q_create(); rc = msg_q_register(iv_msgQ, VFS_ROOT_MSG_VFS); + assert(rc == 0,"Msg Queue Registration failed in VFS"); + +#ifdef CONFIG_SECUREBOOT + err = loadSecureSection(PNOR::HB_EXT_CODE); + if(err) + { + break; + } +#endif // Discover PNOR virtual address of extended image PNOR::SectionInfo_t l_pnor_info; - err = PNOR::getSectionInfo(PNOR::HB_EXT_CODE, l_pnor_info); - if(!err) + if(err) { - iv_pnor_vaddr = l_pnor_info.vaddr; + break; + } - rc = mm_alloc_block - (iv_msgQ, - (void *)VFS_EXTENDED_MODULE_VADDR, - ALIGN_PAGE(l_pnor_info.size) - ); - if(rc == 0) - { - // Note: permissions are set elsewhere + iv_pnor_vaddr = l_pnor_info.vaddr; + iv_hbExtSecure = l_pnor_info.secure; +#ifdef CONFIG_SECUREBOOT + // Assume if HBI is signed it also has a hash page table. + if (iv_hbExtSecure) + { + // store the hash page table offset for reference + iv_hashPageTableOffset = iv_pnor_vaddr; + + // Extract total protected payload size from header + iv_protectedPayloadSize = l_pnor_info.secureProtectedPayloadSize; + + // calculate the hash page table size + iv_hashPageTableSize = iv_protectedPayloadSize - VFS_MODULE_TABLE_SIZE; + TRACFCOMP(g_trac_vfs, "VfsRp::_init HB_EXT total payload_text_size = 0x%X, hash page table size = 0x%X", + l_pnor_info.secureProtectedPayloadSize, + iv_hashPageTableSize); + // skip the hash page table + iv_pnor_vaddr += iv_hashPageTableSize; + } +#endif - // Start msg_handler task watcher - // NOTE: This would be a weak consistancy issues if - // task_create were not a system call. - task_create(VfsRp::vfsWatcher, NULL); - } - else - { - /*@ errorlog tag - * @errortype ERRL_SEV_CRITICAL_SYS_TERM - * @moduleid VFS_MODULE_ID - * @reasoncode VFS_ALLOC_VMEM_FAILED - * @userdata1 returncode from mm_alloc_block() - * @userdata2 Size of memory to allocate - * - * @devdesc Could not allocate virtual memory. - * - */ - err = new ERRORLOG::ErrlEntry - ( - ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity - VFS::VFS_MODULE_ID, // moduleid - VFS::VFS_ALLOC_VMEM_FAILED, // reason Code - rc, // user1 = rc - l_pnor_info.size, // user2 = size - true /*Add HB Software Callout*/ - ); - } + rc = mm_alloc_block + (iv_msgQ, + (void *)VFS_EXTENDED_MODULE_VADDR, + ALIGN_PAGE(l_pnor_info.size) + ); + if(rc == 0) + { + // Note: permissions are set elsewhere + + // Start msg_handler task watcher + // NOTE: This would be a weak consistancy issues if + // task_create were not a system call. + task_create(VfsRp::vfsWatcher, NULL); } + else + { + /*@ errorlog tag + * @errortype ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid VFS_MODULE_ID + * @reasoncode VFS_ALLOC_VMEM_FAILED + * @userdata1 returncode from mm_alloc_block() + * @userdata2 Size of memory to allocate + * + * @devdesc Could not allocate virtual memory. + * + */ + err = new ERRORLOG::ErrlEntry + ( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity + VFS::VFS_MODULE_ID, // moduleid + VFS::VFS_ALLOC_VMEM_FAILED, // reason Code + rc, // user1 = rc + l_pnor_info.size, // user2 = size + true /*Add HB Software Callout*/ + ); + break; + } + } while (0); return err; } @@ -308,15 +347,30 @@ void VfsRp::msgHandler() iv_msg = msg; // save message in case task crashes uint64_t vaddr = msg->data[0]; //page aligned uint64_t paddr = msg->data[1]; //page aligned - - vaddr -= VFS_EXTENDED_MODULE_VADDR; - memcpy((void *)paddr, (void *)(iv_pnor_vaddr+vaddr), - PAGE_SIZE); - - mm_icache_invalidate((void*)paddr,PAGE_SIZE/8); - + // Get relative virtual address within VFS space + vaddr-=VFS_EXTENDED_MODULE_VADDR; + do + { +#ifdef CONFIG_SECUREBOOT + if (SECUREBOOT::enabled() && iv_hbExtSecure) + { + errlHndl_t l_errl = verify_page(vaddr); + // Failed to pass secureboot verification + if(l_errl) + { + SECUREBOOT::handleSecurebootFailure( + l_errl,false); + msg->data[1] = -EACCES; + break; + } + } +#endif + memcpy((void *)paddr, (void *)(iv_pnor_vaddr+vaddr), + PAGE_SIZE); + mm_icache_invalidate((void*)paddr,PAGE_SIZE/8); + msg->data[1] = 0; + } while(0); } - msg->data[1] = 0; msg_respond(iv_msgQ, msg); break; @@ -704,6 +758,76 @@ void VfsRp::get_test_modules(std::vector<const char *> & o_list) const } +errlHndl_t VfsRp::verify_page(uint64_t i_vaddr, uint64_t i_baseOffset, + uint64_t i_hashPageTableOffset) const +{ + errlHndl_t l_errl = nullptr; + uint64_t l_pnorVaddr = iv_pnor_vaddr + i_vaddr; + + // Get current hash page table entry + TRACDCOMP(g_trac_vfs, "VfsRp::verify_page Current Page vaddr = 0x%llX, index = %d, bin file offset = 0x%llX", + i_vaddr, + getHashPageTableIndex(i_vaddr,i_baseOffset), + i_vaddr+PAGE_SIZE+iv_protectedPayloadSize); + PAGE_TABLE_ENTRY_t* l_pageTableEntry = getHashPageTableEntry(i_vaddr, + i_baseOffset, + i_hashPageTableOffset); + + // Get previous hash page table entry + uint64_t l_prevPage = i_vaddr - PAGE_SIZE; + TRACDCOMP(g_trac_vfs, "VfsRp::verify_page Prev Page vaddr = 0x%llX, index = %d, bin file offset = 0x%llX", + l_prevPage, + getHashPageTableIndex(l_prevPage,i_baseOffset), + l_prevPage+PAGE_SIZE+iv_protectedPayloadSize); + PAGE_TABLE_ENTRY_t* l_prevPageTableEntry = getHashPageTableEntry( + l_prevPage, + i_baseOffset, + i_hashPageTableOffset); + + // Concatenate previous page table entry 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)); + l_blobs.push_back(std::make_pair<void*,size_t>( + reinterpret_cast<void*>(l_pnorVaddr), + 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_vfs, "ERROR:>VfsRp::verify_page secureboot verify fail on vaddr 0x%llX, offset into HBI 0x%llX", + i_vaddr, + i_vaddr+PAGE_SIZE+iv_protectedPayloadSize); + /*@ + * @severity ERRL_SEV_CRITICAL_SYS_TERM + * @moduleid VFS_VERIFY_PAGE + * @reasoncode VFS_PAGE_VERIFY_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, + VFS_VERIFY_PAGE, + VFS_PAGE_VERIFY_FAILED, + TO_UINT64(EACCES), + i_vaddr, + true); + l_errl->collectTrace(VFS_COMP_NAME); + l_errl->collectTrace(PNOR_COMP_NAME); + } + + return l_errl; +} + +VfsRp& VfsRp::getInstance() +{ + return Singleton<VfsRp>::instance(); +} + // -- External interface ------------------------------------------------------ errlHndl_t VFS::module_load_unload(const char * i_module, VfsMessages i_msgtype) @@ -812,5 +936,3 @@ bool VFS::module_is_loaded(const char * i_name) { return Singleton<VfsRp>::instance().is_module_loaded(i_name); } - - diff --git a/src/usr/vfs/vfsrp.H b/src/usr/vfs/vfsrp.H index ca4d13512..6c1feb7db 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,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -31,8 +31,11 @@ #include <sys/msg.h> #include <vector> #include <sys/sync.h> +#include <secureboot/service.H> +// Forward declarations struct msg_t; +class SecureRomManagerTest; namespace VFS { @@ -90,7 +93,9 @@ namespace VFS /** * Ctor */ - VfsRp() : iv_msgQ(NULL), iv_msg(NULL), iv_pnor_vaddr(0) + VfsRp() : iv_msgQ(NULL), iv_msg(NULL), iv_pnor_vaddr(0), + iv_hashPageTableOffset(0),iv_hashPageTableSize(0), + iv_protectedPayloadSize(0),iv_hbExtSecure(0) { mutex_init(&iv_mutex); } @@ -121,7 +126,7 @@ namespace VFS /** * Call _start on module. Montior for crash * @param[in] i_msg the message - * @note Does not return. + * @note Does not return. */ static void* execMonitored(void * i_msg); @@ -179,16 +184,91 @@ namespace VFS */ void _vfsWatcher(); + /** + * Verify page using secure hash page table + * + * @param[in] i_vaddr address to verify + * @param[in] i_baseOffset base offset within a PNOR section + * [Default 0 when called within VfsRP. + * Fill for test cases] + * @param[in] i_hashPageTableOffset hash page table offset based on + * iv_pnor_vaddr + * [Default 0 when called within VfsRP to + * get internal hpt offset. Otherwise + * filled in by test cases] + * + * @return errlog - error log to pass along shutdown path. + */ + errlHndl_t verify_page(uint64_t i_vaddr, + uint64_t i_baseOffset = 0, + uint64_t i_hashPageTableOffset = 0) const; + + /** + * @brief Determines the hash page table index associated with a + * vaddr. The hash page table has n-pages + 1 entries. + * + * @param[in] i_vaddr Vaddr the caller is accessing, + * @param[in] i_baseOffset base offset within a PNOR section + * [Optional - Used by test cases] + * + * @return index of the hash page table + */ + inline size_t getHashPageTableIndex (uint64_t i_vaddr, + uint64_t i_baseOffset = 0) const + { + assert(i_baseOffset <= i_vaddr); + return ( (i_vaddr - i_baseOffset) / PAGE_SIZE) + 1; + } + + /** + * @brief Returns a hash page table entry + * + * @param[in] i_pageTableVaddr Vaddr the caller is accessing + * @param[in] i_baseOffset base offset within a PNOR section + * [Optional - Used by test cases] + * @param[in] i_hashPageTableOffset hash page table offset. + * [Default to 0 when called within VfsRP] + * Filled in by test cases] + * + * @return single entry of hash page table + */ + inline PAGE_TABLE_ENTRY_t* getHashPageTableEntry(uint64_t i_vaddr, + uint64_t i_baseOffset = 0, + uint64_t i_hashPageTableOffset = 0) const + { + size_t l_index = getHashPageTableIndex(i_vaddr, i_baseOffset); + size_t l_offset = l_index * HASH_PAGE_TABLE_ENTRY_SIZE; + + // Decide whether to use the internal or passed in value for + // hash page table offset. + size_t l_hashPageTableOffset = (i_hashPageTableOffset == 0) ? + iv_hashPageTableOffset : + iv_pnor_vaddr + i_hashPageTableOffset; + return reinterpret_cast<PAGE_TABLE_ENTRY_t*> + (l_hashPageTableOffset+l_offset); + } + private: // data msg_q_t iv_msgQ; //!< message queue msg_t* iv_msg; //!< Current message being handled - uint64_t iv_pnor_vaddr; //!< virtual address of ext image in PFNOR + uint64_t iv_pnor_vaddr; //!< virtual address of ext image in PNOR + uint64_t iv_hashPageTableOffset; //!< virtual address of hashPageTable of ext image + uint64_t iv_hashPageTableSize; //!< size of hashPageTable of ext image + uint64_t iv_protectedPayloadSize; //!< size of entire protected payload of ext img + //!< Includes Hash page table and VFS module table + bool iv_hbExtSecure; //!< cache result if hostboot extended image is secure typedef std::vector<VfsSystemModule *> ModuleList_t; mutex_t iv_mutex; //!< lock for iv_loaded ModuleList_t iv_loaded; //!< Loaded modules + + friend class ::SecureRomManagerTest; + /** + * @brief Static instance function + */ + static VfsRp& getInstance(); }; }; // VFS namepsace |