summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--img/.gitignore1
-rwxr-xr-xsrc/build/buildpnor/genPnorImages.pl10
-rwxr-xr-xsrc/build/tools/hb5
-rwxr-xr-xsrc/build/tools/hbDistribute7
-rw-r--r--src/include/sys/vfs.h7
-rw-r--r--src/include/usr/vfs/vfs_reasoncodes.H6
-rw-r--r--src/makefile1
-rw-r--r--src/usr/pnor/spnorrp.C3
-rw-r--r--src/usr/secureboot/base/test/makefile3
-rw-r--r--src/usr/secureboot/base/test/securerommgrtest.H232
-rw-r--r--src/usr/vfs/vfsrp.C220
-rw-r--r--src/usr/vfs/vfsrp.H88
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
OpenPOWER on IntegriCloud