diff options
-rw-r--r-- | img/.gitignore | 1 | ||||
-rw-r--r-- | src/build/citest/etc/bbuild | 2 | ||||
-rw-r--r-- | src/build/citest/etc/patches/p8_master.por | 2 | ||||
-rw-r--r-- | src/build/citest/etc/patches/patchlist.txt | 11 | ||||
-rwxr-xr-x | src/build/citest/etc/workarounds.postsimsetup | 20 | ||||
-rw-r--r-- | src/include/usr/secureboot/secure_reasoncodes.H | 10 | ||||
-rw-r--r-- | src/include/usr/secureboot/service.H | 35 | ||||
-rw-r--r-- | src/kernel/exception.C | 50 | ||||
-rw-r--r-- | src/makefile | 5 | ||||
-rw-r--r-- | src/usr/secureboot/base/makefile | 4 | ||||
-rw-r--r-- | src/usr/secureboot/base/rom_entry.S | 51 | ||||
-rw-r--r-- | src/usr/secureboot/base/securerom.C | 510 | ||||
-rw-r--r-- | src/usr/secureboot/base/securerom.H | 223 | ||||
-rw-r--r-- | src/usr/secureboot/base/service.C | 9 | ||||
-rw-r--r-- | src/usr/secureboot/base/settings.C | 5 | ||||
-rw-r--r-- | src/usr/secureboot/base/test/makefile | 31 | ||||
-rw-r--r-- | src/usr/secureboot/base/test/secureromtest.H | 241 |
17 files changed, 1203 insertions, 7 deletions
diff --git a/img/.gitignore b/img/.gitignore index 43697738d..4c83d78a0 100644 --- a/img/.gitignore +++ b/img/.gitignore @@ -16,3 +16,4 @@ errlparser *.pnor *.dat *.prf +test_signed_container diff --git a/src/build/citest/etc/bbuild b/src/build/citest/etc/bbuild index 64438aa26..f63192b1a 100644 --- a/src/build/citest/etc/bbuild +++ b/src/build/citest/etc/bbuild @@ -1 +1 @@ -/esw/fips810/Builds/b0605a_1323.810 +/esw/fips810/Builds/b0617a_1325.810 diff --git a/src/build/citest/etc/patches/p8_master.por b/src/build/citest/etc/patches/p8_master.por new file mode 100644 index 000000000..8fae70244 --- /dev/null +++ b/src/build/citest/etc/patches/p8_master.por @@ -0,0 +1,2 @@ +# Set Secure ROM address in TBROM_BASE_REG scom register +REG(0x02020017)=0x0003FFFF C0000000 #TBROM_BASE_REG Scom Register diff --git a/src/build/citest/etc/patches/patchlist.txt b/src/build/citest/etc/patches/patchlist.txt index c605c55de..538335cb5 100644 --- a/src/build/citest/etc/patches/patchlist.txt +++ b/src/build/citest/etc/patches/patchlist.txt @@ -19,3 +19,14 @@ Add action for L3 purge register. -CMVC: 876083 -Files: p8_ex_l3purge.act -Coreq: None + +Add POR setting for TBROM scom register +-RTC: 72729 +-CMVC: 885548, 885681, 886545, 887736 +-Files + src/build/citest/etc/workarounds.postsimsetup + src/build/citest/etc/patches/patchlist.txt + src/build/citest/etc/patches/p8_master.por + Indirectly: p8_slave.por, s1_master.por, s1_slave.por +-Coreq: None + diff --git a/src/build/citest/etc/workarounds.postsimsetup b/src/build/citest/etc/workarounds.postsimsetup index 54a80b8a5..191f06aed 100755 --- a/src/build/citest/etc/workarounds.postsimsetup +++ b/src/build/citest/etc/workarounds.postsimsetup @@ -40,3 +40,23 @@ cat $HOSTBOOTROOT/src/build/citest/etc/patches/p8_ex_l3purge.act >> \ $sb/simu/data/cec-chip/p8_ex.act cat $HOSTBOOTROOT/src/build/citest/etc/patches/p8_ex_l3purge.act >> \ $sb/simu/data/cec-chip/s1_ex.act + + +echo "+++ Updating POR files for Secure ROM Support (removed with RTC 72729)" +mkdir -p $sb/simu/data/cec-chip/ +grep -v 0x02020017 $BACKING_BUILD/src/simu/data/cec-chip/p8_master.por > \ + $sb/simu/data/cec-chip/p8_master.por +grep -v 0x02020017 $BACKING_BUILD/src/simu/data/cec-chip/p8_slave.por > \ + $sb/simu/data/cec-chip/p8_slave.por +grep -v 0x02020017 $BACKING_BUILD/src/simu/data/cec-chip/s1_master.por > \ + $sb/simu/data/cec-chip/s1_master.por +grep -v 0x02020017 $BACKING_BUILD/src/simu/data/cec-chip/s1_slave.por > \ + $sb/simu/data/cec-chip/s1_slave.por +cat $HOSTBOOTROOT/src/build/citest/etc/patches/p8_master.por >> \ + $sb/simu/data/cec-chip/p8_master.por +cat $HOSTBOOTROOT/src/build/citest/etc/patches/p8_master.por >> \ + $sb/simu/data/cec-chip/p8_slave.por +cat $HOSTBOOTROOT/src/build/citest/etc/patches/p8_master.por >> \ + $sb/simu/data/cec-chip/s1_master.por +cat $HOSTBOOTROOT/src/build/citest/etc/patches/p8_master.por >> \ + $sb/simu/data/cec-chip/s1_slave.por diff --git a/src/include/usr/secureboot/secure_reasoncodes.H b/src/include/usr/secureboot/secure_reasoncodes.H index eac9dfda9..38d5b7079 100644 --- a/src/include/usr/secureboot/secure_reasoncodes.H +++ b/src/include/usr/secureboot/secure_reasoncodes.H @@ -31,12 +31,20 @@ namespace SECUREBOOT { MOD_SECURE_INVALID = 0x00, MOD_SECURE_BLINDPURGE = 0x01, - }; + MOD_SECURE_ROM_INIT = 0x02, + MOD_SECURE_ROM_VERIFY = 0x03, + MOD_SECURE_ROM_CLEANUP = 0x04, + }; enum SECUREReasonCode { RC_PURGEOP_PENDING = SECURE_COMP_ID | 0x01, RC_PURGEOP_FAIL_COMPLETE = SECURE_COMP_ID | 0x02, + RC_DEV_MAP_FAIL = SECURE_COMP_ID | 0x03, + RC_PAGE_ALLOC_FAIL = SECURE_COMP_ID | 0x04, + RC_SET_PERMISSION_FAIL_EXE = SECURE_COMP_ID | 0x05, + RC_SET_PERMISSION_FAIL_WRITE = SECURE_COMP_ID | 0x06, + RC_ROM_VERIFY = SECURE_COMP_ID | 0x07, }; } diff --git a/src/include/usr/secureboot/service.H b/src/include/usr/secureboot/service.H index a83d5d510..b640fd978 100644 --- a/src/include/usr/secureboot/service.H +++ b/src/include/usr/secureboot/service.H @@ -23,6 +23,10 @@ #ifndef __SECUREBOOT_SERVICE_H #define __SECUREBOOT_SERVICE_H +#include <errl/errlentry.H> + +typedef uint8_t SHA512_t[64]; + namespace SECUREBOOT { /** @brief Perform initialization of Secureboot for the Base image. @@ -33,9 +37,40 @@ namespace SECUREBOOT */ void* initializeBase(void* unused); + /** + * @brief Initialize Secure Rom by loading it into memory and + * retrieving Hash Keys + * + * @return errlHndl_t NULL on success + */ + errlHndl_t initializeSecureROM(void); + + /** @brief Determines if Secureboot is enabled. */ bool enabled(); + + /** + * @brief Verify Signed Container + * + * @param[in] i_container Void pointer to effective address of container + * @param[in] i_size Size of container in bytes + * + * @return errlHndl_t NULL on success + */ + errlHndl_t verifyContainer(void * i_container, size_t i_size); + + /** + * @brief Hash Signed Blob + * + * @param[in] i_blob Void pointer to effective address of blob + * @param[in] i_size Size of blob in bytes + * @param[out] o_hash SHA512 hash + * + * @return errlHndl_t NULL on success + */ + errlHndl_t hashBlob(void * i_blob, size_t i_size, SHA512_t o_buf); + } #endif diff --git a/src/kernel/exception.C b/src/kernel/exception.C index ac8638585..77499f03a 100644 --- a/src/kernel/exception.C +++ b/src/kernel/exception.C @@ -158,6 +158,12 @@ void kernel_execute_hype_emu_assist() TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED); } +const uint32_t EXCEPTION_BRANCH_INSTR_MASK = 0xFC000000; +const uint32_t EXCEPTION_BRANCH_INSTR = 0x48000000; +const uint32_t EXCEPTION_MFSPR_CFAR_INSTR_MASK = 0xFC1FFFFE; +const uint32_t EXCEPTION_MFSPR_CFAR_INSTR = 0x7C1C02A6; +const uint32_t EXCEPTION_MFSPR_GFR_NAME_MASK = 0x03E00000; + namespace ExceptionHandles { bool PrivInstr(task_t* t) @@ -176,9 +182,51 @@ namespace ExceptionHandles { printk("Error: Nap executed with lowered permissions on %d\n", t->tid); - t->context.nip = static_cast<void*>(instruction + 1); + t->context.nip = reinterpret_cast<void *> ( + (reinterpret_cast<uint64_t>(t->context.nip)) + 4); return true; } + + + // Check for 'mfspr r*, CFAR' instructions (from MFSPR RT,SPR) + // and handle the setting of the specific r* register + if (( *instruction & EXCEPTION_MFSPR_CFAR_INSTR_MASK) + == EXCEPTION_MFSPR_CFAR_INSTR ) + { + + // check to make sure previous instruction was a branch + // if not, then we don't want to handle ths exception + uint32_t* previous_instr = + (reinterpret_cast<uint32_t*>(phys_addr)) - 1; + if ( (*previous_instr & EXCEPTION_BRANCH_INSTR_MASK) + == EXCEPTION_BRANCH_INSTR ) + { + uint32_t gpr_name = 0; + + // GPR register in bits 6:10 of mfspr instruction + gpr_name = (*instruction & EXCEPTION_MFSPR_GFR_NAME_MASK) + >> 21; + + // Move contents of previous instruction address to r* + t->context.gprs[gpr_name] = + (reinterpret_cast<uint64_t>(t->context.nip)) - 4; + + // move instruction stream to next instruction + t->context.nip = reinterpret_cast<void *> ( + (reinterpret_cast<uint64_t>(t->context.nip)) + 4); + + printkd("mfsr r%d to CFAR handled, nip=%p\n", + gpr_name, t->context.nip ); + + return true; + } + else + { + printk("Error: mfspr r* to CFAR found, but previous " + "inst not a branch\n"); + return false; + } + } } return false; diff --git a/src/makefile b/src/makefile index df5c82d0e..98c1301ef 100644 --- a/src/makefile +++ b/src/makefile @@ -64,7 +64,7 @@ TESTCASE_MODULES = cxxtest testtrace testerrl testdevicefw testsyslib \ testhwpf testecmddatabuffer initsvctesttask testcxxtest \ testpnor testi2c testfsi testvfs testhwas testintr testvpd \ testpore testutil testmbox testmdia testprdf testattn \ - testscan testruntime testibscom testdump + testscan testruntime testibscom testdump testsecureboot RELOCATABLE_IMAGE_LDFLAGS = -pie --export-dynamic @@ -93,7 +93,8 @@ hbicore_DATA_MODULES = sample.if p8.dmi.scom.if cen.dmi.scom.if \ hbicore_test_OBJECTS = ${hbicore_OBJECTS} hbicore_test_MODULES = ${hbicore_MODULES} hbicore_test_EXTENDED_MODULES = ${hbicore_EXTENDED_MODULES} ${TESTCASE_MODULES} -hbicore_test_DATA_MODULES = ${hbicore_DATA_MODULES} testdata +hbicore_test_DATA_MODULES = ${hbicore_DATA_MODULES} testdata \ + test_signed_container IMAGE_PASS_POST += buildpnor imgsizecheck diff --git a/src/usr/secureboot/base/makefile b/src/usr/secureboot/base/makefile index 8a63e1537..479b8aa32 100644 --- a/src/usr/secureboot/base/makefile +++ b/src/usr/secureboot/base/makefile @@ -22,9 +22,9 @@ # IBM_PROLOG_END_TAG ROOTPATH = ../../../.. MODULE = secureboot_base -SUBDIRS = +SUBDIRS = test.d -OBJS = service.o settings.o header.o purge.o +OBJS = service.o settings.o header.o purge.o securerom.o rom_entry.o CFLAGS += -iquote ../ include ${ROOTPATH}/config.mk diff --git a/src/usr/secureboot/base/rom_entry.S b/src/usr/secureboot/base/rom_entry.S new file mode 100644 index 000000000..f2d67e3f1 --- /dev/null +++ b/src/usr/secureboot/base/rom_entry.S @@ -0,0 +1,51 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/secureboot/base/rom_entry.S $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2013 +# +# p1 +# +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code +# +# The source code for this program is not published or otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END_TAG +.include "kernel/ppcconsts.S" + +.section .text + +.global call_rom_verify +.global call_rom_SHA512 + +call_rom_verify: +call_rom_SHA512: + +call_rom_entry: + std r2, 40(r1) + mflr r0 + std r0, 16(r1) + stdu r1, -128(r1) + li r2, 0 + mtctr r3 + mr r3, r4 + mr r4, r5 + mr r5, r6 + mr r6, r7 + mr r7, r8 + bctrl + addi r1, r1, 128 + ld r2, 40(r1) + ld r0, 16(r1) + mtlr r0 + blr + diff --git a/src/usr/secureboot/base/securerom.C b/src/usr/secureboot/base/securerom.C new file mode 100644 index 000000000..af12b365b --- /dev/null +++ b/src/usr/secureboot/base/securerom.C @@ -0,0 +1,510 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/base/securerom.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include <secureboot/service.H> +#include <secureboot/secure_reasoncodes.H> +#include <sys/mmio.h> +#include <kernel/pagemgr.H> +#include <limits.h> +#include <targeting/common/commontargeting.H> +#include <targeting/common/targetservice.H> +#include <devicefw/driverif.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> + +#include "securerom.H" +#include "../settings.H" + +extern trace_desc_t* g_trac_secure; + +// Quick change for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + + +// Hardcode define for Secure ROM code (bootrom.bin) in system +// Secure ROM has 16KB reserved address space +#define SECUREROM_MEMORY_SIZE (16 * KILOBYTE) +// 4 pages * (PAGESIZE=4K) = 16K +#define SECUREROM_NUM_PAGES (SECUREROM_MEMORY_SIZE / PAGESIZE) + +namespace SECUREBOOT +{ + + +/** + * @brief Initialize Secure Rom by loading it into memory and + * retrieving Hash Keys + */ +errlHndl_t initializeSecureROM(void) +{ + return Singleton<SecureROM>::instance().initialize(); +} + +/** + * @brief Verify Signed Container + */ +errlHndl_t verifyContainer(void * i_container, size_t i_size) +{ + TRACUCOMP(g_trac_secure, "verifyContainer(): i_container=%p, size=0x%x", + i_container, i_size); + + return Singleton<SecureROM>::instance().verifyContainer(i_container, + i_size); +} + +/** + * @brief Hash Signed Blob + * + */ +errlHndl_t hashBlob(void * i_blob, size_t i_size) +{ + return Singleton<SecureROM>::instance().hashBlob(i_blob, i_size); + +} + +}; //end SECUREBOOT namespace + + +/******************** + Public Methods + ********************/ + + +/** + * @brief Initialize Secure Rom by loading it into memory and + * getting Hash Keys + */ +errlHndl_t SecureROM::initialize() +{ + TRACDCOMP(g_trac_secure,ENTER_MRK"SecureROM::initialize()"); + + errlHndl_t l_errl = NULL; + bool l_cleanup = false; + uint32_t l_rc = 0; + + do{ + + // Check to see if ROM has already been initialized + if (iv_device_ptr != NULL) + { + // The Secure ROM has already been initialized + TRACUCOMP(g_trac_secure,"SecureROM::initialize(): Already " + "Loaded: iv_device_ptr=%p", iv_device_ptr); + + // Can skip the rest of this function + break; + } + + + /*********************************************************************/ + /* Find base address of Secure ROM via TBROM_BASE_REG scom register */ + /*********************************************************************/ + + const uint32_t tbrom_reg_addr = 0x02020017; + uint64_t tbrom_reg_data; + size_t op_size = sizeof(uint64_t); + + l_errl = deviceRead( TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL, + &(tbrom_reg_data), + op_size, + DEVICE_SCOM_ADDRESS(tbrom_reg_addr) ); + + if (l_errl != NULL) + { + TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM::initialize():" + " Fail SCOM Read of tbrom_reg_addr (0x%x)", tbrom_reg_addr); + + break; + } + + + TRACUCOMP(g_trac_secure,INFO_MRK"SecureROM::initialize(): " + "tbrom_reg_data = 0x%016llx", tbrom_reg_data); + + + // This register contains the starting address of the bootrom device + void * l_rom_baseAddr = reinterpret_cast<void*>(tbrom_reg_data); + + + /*******************************************************************/ + /* Map the bootrom code into virtual memory */ + /*******************************************************************/ + void * l_rom_virtAddr = mmio_dev_map(l_rom_baseAddr, THIRTYTWO_GB); + + if (l_rom_virtAddr == NULL) + { + TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM::initialize():" + " mmio_dev_map failed: l_rom_virtAddr=%p, l_rom_baseAddr=%p", + l_rom_virtAddr, l_rom_baseAddr); + + /*@ + * @errortype + * @moduleid SECUREBOOT::MOD_SECURE_ROM_INIT + * @reasoncode SECUREBOOT::RC_DEV_MAP_FAIL + * @userdata1 TBROM Register Address + * @userdata2 TBROM Register Data + * @devdesc mmio_dev_map() failed for Secure ROM + */ + l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SECUREBOOT::MOD_SECURE_ROM_INIT, + SECUREBOOT::RC_DEV_MAP_FAIL, + TO_UINT64(tbrom_reg_addr), + tbrom_reg_data); + + l_errl->collectTrace("SECURE",256); + break; + + } + + /**********************************************************************/ + /* Allocate Memory: Request full SECUREROM_MEMORY_SIZE */ + /**********************************************************************/ + + // Using malloc() rather than allocatePage because malloc() will + // handle error path + iv_device_ptr = malloc(SECUREROM_MEMORY_SIZE); + + // Pages are now allocated, so free below if necessary + l_cleanup = true; + + /***************************************************************/ + /* Copy and setup ROM code in allocated memory */ + /***************************************************************/ + + // memcpy from mapped device to allocated pages + memcpy( iv_device_ptr, l_rom_virtAddr, SECUREROM_MEMORY_SIZE ); + + // invalidate icache to make sure that bootrom code in memory is used + size_t l_icache_invalid_size = (SECUREROM_MEMORY_SIZE / + sizeof(uint64_t)); + + mm_icache_invalidate( iv_device_ptr, l_icache_invalid_size); + + // Make this address space executable + uint64_t l_access_type = EXECUTABLE; + l_rc = mm_set_permission( iv_device_ptr, + SECUREROM_MEMORY_SIZE, + l_access_type); + + + if (l_rc != 0) + { + TRACFCOMP(g_trac_secure,EXIT_MRK"SecureROM::initialize():" + " Fail from mm_set_permission(EXECUTABLE): l_rc=0x%x, ptr=%p, " + "size=0x%x, access=0x%x", l_rc, iv_device_ptr, + SECUREROM_MEMORY_SIZE, l_access_type); + + /*@ + * @errortype + * @moduleid SECUREBOOT::MOD_SECURE_ROM_INIT + * @reasoncode SECUREBOOT::RC_SET_PERMISSION_FAIL_EXE + * @userdata1 l_rc + * @userdata2 iv_device_ptr + * @devdesc mm_set_permission(EXECUTABLE) failed for Secure ROM + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SECUREBOOT::MOD_SECURE_ROM_INIT, + SECUREBOOT::RC_SET_PERMISSION_FAIL_EXE, + TO_UINT64(l_rc), + reinterpret_cast<uint64_t>(iv_device_ptr)); + + l_errl->collectTrace("SECURE",256); + break; + + } + + + /***************************************************************/ + /* Retrieve HW Hash Keys From The System */ + /***************************************************************/ + + // @todo RTC:RTC:34080 - Support for SecureROM::getHwHashKeys() + l_errl = SecureROM::getHwHashKeys(); + + if (l_errl != NULL) + { + TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM::initialize():" + " SecureROM::getHwHashKeys() returned an error"); + + l_errl->collectTrace("SECURE",256); + break; + + } + + + /***************************************************************/ + /* Secure ROM successfully initialized */ + /***************************************************************/ + // If we've made it this far without an error, than Secure ROM + // is properly initialized and pages shouldn't be de-allocated + l_cleanup = false; + TRACFCOMP(g_trac_secure,INFO_MRK"SecureROM::initialize(): SUCCESSFUL:" + " iv_device_ptr=%p", iv_device_ptr); + + + }while(0); + + // Check to see if we should free pages + if (l_cleanup == true) + { + SecureROM::_cleanup(); + } + + TRACDCOMP(g_trac_secure,EXIT_MRK"SecureROM::initialize() - %s", + ((NULL == l_errl) ? "No Error" : "With Error") ); + + return l_errl; + +} + + +/** + * @brief Verify Container against system hash keys + */ +errlHndl_t SecureROM::verifyContainer(void * i_container, size_t i_size) +{ + TRACDCOMP(g_trac_secure,ENTER_MRK"SecureROM::verifyContainer(): " + "i_container=%p, size=0x%x", i_container, i_size); + + + errlHndl_t l_errl = NULL; + uint64_t l_rc = 0; + + do{ + + // Check to see if ROM has already been initialized + // This should have been done early in IPL so assert if this + // is not the case as system is in a bad state + assert(iv_device_ptr != NULL); + + + // Declare local input struct + ROM_hw_params l_hw_parms; + + // Clear/zero-out the struct since we want 0 ('zero') values for + // struct elements my_ecid, entry_point and log + memset(&l_hw_parms, 0, sizeof(ROM_hw_params)); + + // Now set hw_key_hash, which is of type sha2_hash_t, to iv_hash_key + memcpy (&l_hw_parms.hw_key_hash, &iv_hash_key, sizeof(sha2_hash_t)); + + + /*******************************************************************/ + /* Call ROM_verify() function via an assembly call */ + /*******************************************************************/ + + // Set startAddr to ROM_verify() function at an offset of Secure ROM + uint64_t l_rom_verify_startAddr = reinterpret_cast<uint64_t>( + iv_device_ptr) + + ROM_VERIFY_FUNCTION_OFFSET; + + TRACUCOMP(g_trac_secure,"SecureROM::verifyContainer(): " + " Calling ROM_verify() via call_rom_verify: l_rc=0x%x, " + "l_hw_parms.log=0x%x (&l_hw_parms=%p) addr=%p (iv_d_p=%p)", + l_rc, l_hw_parms.log, &l_hw_parms, l_rom_verify_startAddr, + iv_device_ptr); + + + l_rc = call_rom_verify(reinterpret_cast<void*> + (l_rom_verify_startAddr), + reinterpret_cast<ROM_container_raw*> + (i_container), + &l_hw_parms); + + + TRACUCOMP(g_trac_secure,"SecureROM::verifyContainer(): " + "Back from ROM_verify() via call_rom_verify: l_rc=0x%x, " + "l_hw_parms.log=0x%x (&l_hw_parms=%p) addr=%p (iv_d_p=%p)", + l_rc, l_hw_parms.log, &l_hw_parms, l_rom_verify_startAddr, + iv_device_ptr); + + + + if (l_rc != 0) + { + TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM::verifyContainer():" + " ROM_verify() FAIL: l_rc=0x%x, l_hw_parms.log=0x%x " + "addr=%p (iv_d_p=%p)", l_rc, l_hw_parms.log, + l_rom_verify_startAddr, iv_device_ptr); + + /*@ + * @errortype + * @moduleid SECUREBOOT::MOD_SECURE_ROM_VERIFY + * @reasoncode SECUREBOOT::RC_ROM_VERIFY + * @userdata1 l_rc + * @userdata2 l_hw_parms.log + * @devdesc ROM_verify() Call Failed + */ + l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SECUREBOOT::MOD_SECURE_ROM_VERIFY, + SECUREBOOT::RC_ROM_VERIFY, + l_rc, + l_hw_parms.log); + + l_errl->collectTrace("SECURE",256); + break; + + } + + }while(0); + + + TRACDCOMP(g_trac_secure,EXIT_MRK"SecureROM::verifyContainer() - %s", + ((NULL == l_errl) ? "No Error" : "With Error") ); + + return l_errl; +} + + +/** + * @brief Hash Blob + */ +errlHndl_t SecureROM::hashBlob(void * i_blob, size_t i_size) +{ + + TRACDCOMP(g_trac_secure,INFO_MRK"SecureROM::hashBlob() NOT " + "supported, but not returning error log"); + + // @todo RTC:34080 - Add support for this function + + errlHndl_t l_errl = NULL; + + TRACDCOMP(g_trac_secure,EXIT_MRK"SecureROM::hashBlob() - %s", + ((NULL == l_errl) ? "No Error" : "With Error") ); + + return l_errl; + +} + + +/******************** + Internal Methods + ********************/ + +/** + * @brief Constructor + */ +SecureROM::SecureROM() +:iv_device_ptr(NULL) +{ + TRACDCOMP(g_trac_secure, "SecureROM::SecureROM()>"); + + // Clear out iv_hash_keys, which is of type sha2_hash_t + memset(&iv_hash_key, 0, sizeof(sha2_hash_t) ); + +} + +/** + * @brief Destructor + */ +SecureROM::~SecureROM() { SecureROM::_cleanup(); }; + +void SecureROM::_cleanup() +{ + // deallocate pages + if ( iv_device_ptr != NULL ) + { + + // Make this address space writable before sending it back + // to the Page Manager via free, otherwise PM will crash trying to + // update the previously-defined-as-excutable memory space + uint64_t l_access_type = WRITABLE; + uint64_t l_rc = mm_set_permission( iv_device_ptr, + SECUREROM_NUM_PAGES, + l_access_type ); + + if (l_rc != 0) + { + TRACFCOMP(g_trac_secure,ERR_MRK"SecureROM:::_cleanup():" + " Fail from mm_set_permission(WRITABLE): l_rc=0x%x, ptr=%p, " + "size=0x%x, pages=%d, access=0x%x", l_rc, iv_device_ptr, + SECUREROM_MEMORY_SIZE, SECUREROM_NUM_PAGES, l_access_type); + + /*@ + * @errortype + * @moduleid SECUREBOOT::MOD_SECURE_ROM_CLEANUP + * @reasoncode SECUREBOOT::RC_SET_PERMISSION_FAIL_WRITE + * @userdata1 l_rc + * @userdata2 iv_device_ptr + * @devdesc mm_set_permission(WRITABLE) failed for Secure ROM + */ + errlHndl_t l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SECUREBOOT::MOD_SECURE_ROM_CLEANUP, + SECUREBOOT::RC_SET_PERMISSION_FAIL_WRITE, + TO_UINT64(l_rc), + reinterpret_cast<uint64_t>(iv_device_ptr)); + + l_errl->collectTrace("SECURE",256); + + // Commit here because funtion doesn't return error handle + errlCommit(l_errl, SECURE_COMP_ID); + + // NOTE: Purposely not calling free() here - + // prefer to have a memory leak than have another task crash + // due to pages still being excutable or in a bad state + + } + else + { + // Safe to free allocated pages + free(iv_device_ptr); + + TRACDCOMP(g_trac_secure,INFO_MRK + "SecureROM::_cleanup(): pages set to " + "WRITABLE (rc=0x%x) and free called", l_rc); + + + // Reset device ptr + iv_device_ptr = NULL; + } + + } +} + + +/** + * @brief Retrieves HW Keys from the system + */ +errlHndl_t SecureROM::getHwHashKeys() +{ + + errlHndl_t l_errl = NULL; + + TRACFCOMP(g_trac_secure,INFO_MRK"SecureROM::getHwHashKeys() NOT supported"); + + // @todo RTC:34080 - Add support for getting HW Hash Keys from System + + return l_errl; +} + +/** + * @brief Static instance function for testcase only + */ +SecureROM& SecureROM::getInstance() +{ + return Singleton<SecureROM>::instance(); +} + + diff --git a/src/usr/secureboot/base/securerom.H b/src/usr/secureboot/base/securerom.H new file mode 100644 index 000000000..b42145b6d --- /dev/null +++ b/src/usr/secureboot/base/securerom.H @@ -0,0 +1,223 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/base/securerom.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#ifndef __SECUREBOOT_SECUREROM_H +#define __SECUREBOOT_SECUREROM_H + +/** @file SecureRom.H + * + * @brief SecureROM class definition and miscellaneious defines + * needed to work with Secure ROM binary + */ + +#include <errl/errlentry.H> + + +/******************************************************************/ +/* Start of Chip Logic Secure ROM include section */ +/******************************************************************/ +// These defines come from the following directory: +// /afs/awd/projects/eclipz/c22/libs/tp/logic/p8m/head/trusted_boot_rom/src +// and are needed to run functions in the SecureROM code stored in memory + +/* From hw_utils.h: */ +#define ECID_SIZE 16 + + +/* From ecverify.h */ +#define EC_COORDBYTES 66 /* P-521 */ +typedef uint8_t ecc_key_t[2*EC_COORDBYTES]; + + +/* From sha512.h: */ +#define SHA512_DIGEST_LENGTH 64 +typedef uint8_t __attribute__((aligned(8))) sha2_hash_t[ \ + SHA512_DIGEST_LENGTH / sizeof(uint8_t) ]; + +typedef uint8_t sha2_byte; /* Exactly 1 byte */ + +void SHA512_Hash(const sha2_byte *data, size_t len, sha2_hash_t *result); + + +/* From ROM.h */ +typedef enum { ROM_DONE, ROM_FAILED, PHYP_PARTIAL } ROM_response; + +typedef struct { + uint32_t magic_number; // (17082011) + uint16_t version; // (1: see versions above) + uint64_t container_size; // filled by caller + uint64_t target_hrmor; // filled by caller + uint64_t stack_pointer; // filled by caller + //bottom of stack -> 128k added by rom code to get real stack pointer + ecc_key_t hw_pkey_a; + ecc_key_t hw_pkey_b; + ecc_key_t hw_pkey_c; + uint64_t prefix; // prefix header place holder + // followed by sw header (if not special prefix) + // followed by optional unprotected payload data +}__attribute__((packed)) ROM_container_raw; + + +typedef struct { + sha2_hash_t hw_key_hash; + uint8_t my_ecid[ECID_SIZE]; + uint64_t entry_point; + uint64_t log; +}__attribute__((packed)) ROM_hw_params; + + +// Need this for the following definition +#ifdef __cplusplus +extern "C" +{ +#endif + +// Interfaces for Assembly Functions to call into Secure ROM +// - 1st parameter is address of function offset into Secure ROM, +// followed by additional parameters as necssary +// MAB: void* call_rom_entry(void*, void*, void*, void*); + +ROM_response call_rom_verify(void*, ROM_container_raw*, ROM_hw_params*); +void call_rom_SHA512(void*, const sha2_byte *, size_t, sha2_hash_t*); + +#ifdef __cplusplus +} +#endif + + +/* Offsets needed to call functions in jump table at start of */ +/* SecureROM code - see .../trusted_boot_rom/bootrom.dis */ +#define SHA512_HASH_FUNCTION_OFFSET 0x20 +#define ROM_VERIFY_FUNCTION_OFFSET 0x30 + + +/******************************************************************/ +/* End of Chip Logic Secure ROM include section */ +/******************************************************************/ + + +/** @class SecureROM + * @brief Class for loading and interacting with SecureROM in memory + */ +class SecureROM +{ + public: + + /** + * @brief Initialize Secure Rom by loading it into memory and + * getting Hash Keys + * + * @return errlHndl_t NULL on success + */ + errlHndl_t initialize(); + + + /** + * @brief Verify Container against system hash keys + * + * @param[in] i_container Void pointer to effective address + * of container + * @param[in] i_size Size of container + * + * @return errlHndl_t NULL on success + */ + errlHndl_t verifyContainer(void * i_container, size_t i_size); + + /** + * @brief Hash Blob + * + * @param[in] i_blob Void pointer to effective address + * of blob + * @param[in] i_size Size of blob in bytes + * + * @return errlHndl_t NULL on success + */ + errlHndl_t hashBlob(void * i_blob, size_t i_size); + + + protected: + + /** + * @brief Constructor + */ + SecureROM(); + + /** + * @brief Destructor + */ + ~SecureROM(); + + private: + + /******************************************** + * VARIABLES + ********************************************/ + + /** + * Void pointer to effective address location of Secure ROM + * in memory + */ + void * iv_device_ptr; + + /** + * Hash Key Retrieved From System + */ + sha2_hash_t iv_hash_key; + + + /******************************************** + * Private Functions + ********************************************/ + + /** + * @brief Retrieves HW Keys from the system + * + * @return errlHndl_t NULL on success + */ + errlHndl_t getHwHashKeys(); + + /** + * @brief Static instance function for testcase only + */ + static SecureROM& getInstance(); + + + /** + * @brief Safely Frees Allocated Memory + */ + void _cleanup(); + + + /******************************************** + * Friend(s) + ********************************************/ + + // let my testcase poke around + friend class SecureROMTest; + + +}; // end of SecureROM class + + + +#endif diff --git a/src/usr/secureboot/base/service.C b/src/usr/secureboot/base/service.C index bb18bef9f..e0d78dfa6 100644 --- a/src/usr/secureboot/base/service.C +++ b/src/usr/secureboot/base/service.C @@ -56,6 +56,15 @@ namespace SECUREBOOT // to post-secureboot state. Major coding bug, so just assert. assert(0 == mm_extend(MM_EXTEND_POST_SECUREBOOT)); + + // Initialize the Secure ROM + l_errl = initializeSecureROM(); + if (l_errl) + { + break; + } + + } while(0); return l_errl; diff --git a/src/usr/secureboot/base/settings.C b/src/usr/secureboot/base/settings.C index dfacf46e7..1974fd158 100644 --- a/src/usr/secureboot/base/settings.C +++ b/src/usr/secureboot/base/settings.C @@ -25,6 +25,11 @@ #include "settings.H" +// SECUREBOOT : General driver traces +trace_desc_t* g_trac_secure = NULL; +TRAC_INIT(&g_trac_secure, "SECURE", KILOBYTE); //1K + + namespace SECUREBOOT { const uint64_t Settings::SECURITY_SWITCH_REGISTER = 0x00010005; diff --git a/src/usr/secureboot/base/test/makefile b/src/usr/secureboot/base/test/makefile new file mode 100644 index 000000000..a1a0dc4d6 --- /dev/null +++ b/src/usr/secureboot/base/test/makefile @@ -0,0 +1,31 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/secureboot/base/test/makefile $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2013 +# +# p1 +# +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code +# +# The source code for this program is not published or otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END_TAG +ROOTPATH = ../../../../.. + +MODULE = testsecureboot +TESTS = *.H + +BINARY_FILES = $(IMGDIR)/test_signed_container:d0be6f0399eee8ecdc3ded896ecccd2551a439f3 + +include ${ROOTPATH}/config.mk + diff --git a/src/usr/secureboot/base/test/secureromtest.H b/src/usr/secureboot/base/test/secureromtest.H new file mode 100644 index 000000000..de1e1e35c --- /dev/null +++ b/src/usr/secureboot/base/test/secureromtest.H @@ -0,0 +1,241 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/base/test/secureromtest.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SECUREROMTEST_H +#define __SECURETOMTEST_H + + +#include <sys/mm.h> +#include <sys/mmio.h> +#include <vfs/vfs.H> +#include <kernel/pagemgr.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <secureboot/service.H> +#include <secureboot/secure_reasoncodes.H> + +#include "../securerom.H" + +extern trace_desc_t* g_trac_secure; + +// Quick change for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + + +/**********************************************************************/ +/* UTILITY FUNCTIONS */ +/* -- note: these functions do not commit error logs */ +/**********************************************************************/ + +// Moves signed files from PNOR to paged-in memory +errlHndl_t loadSignedFile( const char * i_signedFile_name, + void * & o_signedFile_pageAddr, + size_t & o_signedFile_size ); + +// @todo RTC:34080 - In future key hash will come from HW, but +// Get the software keys that match the signed container +void useSwKeyHash(sha2_hash_t * o_sw_key_hash); + + +/**********************************************************************/ +/* End of UTILITY FUNCTIONS */ +/**********************************************************************/ + + + +class SecureROMTest : public CxxTest::TestSuite +{ + public: + + /** + * @brief Secure ROM Test - Verify a Signed Container + */ + void test_verify(void) + { + TRACFCOMP(g_trac_secure,ENTER_MRK"SecureROMTest::test_verify>"); + + errlHndl_t l_errl = NULL; + + /*******************************************************************/ + /* Load "test_signed_container" from PNOR to use for verification */ + /*******************************************************************/ + + // Signed file variables + const char * signedFile_name = "test_signed_container"; + void * signedFile_pageAddr = NULL; + size_t signedFile_size = 0; + + // Call utility function + l_errl = loadSignedFile( signedFile_name, + signedFile_pageAddr, + signedFile_size); + + if (l_errl) + { + TS_FAIL("SecureROMTest::test_verify: loadSignedFile() Failed"); + errlCommit(l_errl, SECURE_COMP_ID); + return; + } + + TRACUCOMP(g_trac_secure, "SecureROMTest::test_verify: " + "signedFile info: addr = %p, size=0x%x", + signedFile_pageAddr, signedFile_size); + + + + /*******************************************************************/ + /* @todo RTC:34080 - In future key hash will come from HW, but */ + /* for now, create and initialize a local SecureROM class and */ + /* and then override the hash key variable to use the SW Key Hash */ + /* for the test_signed_container */ + /*******************************************************************/ + SecureROM l_sRom; + + // Call initializeSecureROM() + l_errl = l_sRom.initialize(); + + if (l_errl) + { + TS_FAIL("SecureROMTest::test_verify: initializeSecureROM() Failed"); + errlCommit(l_errl, SECURE_COMP_ID); + return; + } + + // Use Utility Function to load software keys into iv_hash_key + useSwKeyHash( & l_sRom.iv_hash_key); + + + /*******************************************************************/ + /* Call verify function */ + /*******************************************************************/ + + // Warn about the exception being handled during verification + printkd("test_verify(): expect to see 'mfsr r2 to CFAR handled': "); + + l_errl = l_sRom.verifyContainer( signedFile_pageAddr, + signedFile_size ); + + if (l_errl) + { + TS_FAIL("SecureROMTest::test_verify: verifyContainer() Failed"); + errlCommit(l_errl, SECURE_COMP_ID); + return; + } + + TRACFCOMP(g_trac_secure,EXIT_MRK"SecureROMTest::test_verify"); + + + }; + +}; + + +/**********************************************************************/ +/* UTILITY FUNCTIONS */ +/**********************************************************************/ + +// Moved test_signed_container from PNOR to paged-in memory +errlHndl_t loadSignedFile( const char * i_signedFile_name, + void * & o_signedFile_pageAddr, + size_t & o_signedFile_size ) +{ + + errlHndl_t l_errl = NULL; + const char * l_signedFile_virtAddr = NULL; + + + /*******************************************************************/ + /* Load file from PNOR to use for verification */ + /*******************************************************************/ + + // Load file into virtual memory + l_errl = VFS::module_load( i_signedFile_name ); + if (l_errl) + { + TRACFCOMP(g_trac_secure, "loadSignedFile(): Module " + "Load FAILED: %s", i_signedFile_name); + + return l_errl; + } + + // Get memory address of file + l_errl = VFS::module_address ( i_signedFile_name, + l_signedFile_virtAddr, + o_signedFile_size); + if (l_errl) + { + TRACFCOMP(g_trac_secure, "loadSignedFile()> Module " + "Address FAILED: %s", i_signedFile_name); + + return l_errl; + } + + + // Request contiguous memory block to copy in file + size_t l_num_pages = ALIGN_PAGE(o_signedFile_size)/PAGESIZE; + bool l_isUserspace = true; + o_signedFile_pageAddr = PageManager::allocatePage(l_num_pages, + l_isUserspace); + + // memcpy the file to allocated pages + memcpy( o_signedFile_pageAddr, l_signedFile_virtAddr, + o_signedFile_size ); + + TRACUCOMP(g_trac_secure, "loadSignedFile()> signedFile '%s' " + "Info: sF_pA=%p, sF_vA=%p, size=0x%x (pages=%d)", + i_signedFile_name, o_signedFile_pageAddr, + l_signedFile_virtAddr, o_signedFile_size, l_num_pages); + + return l_errl; +} + + + +// @todo RTC:34080 - In future key hash will come from HW, but +// Get the software keys that match the signed container +void useSwKeyHash(sha2_hash_t * o_sw_key_hash) +{ + + + /* On HW hw_key_hash will be pulled from SBE's SEEPROM or PIB Memory */ + + /* For simics/testing, we're hardcoding the value from Dale */ + /* Peterson here, which I've stored here: */ + /* /gsa/rchgsa-h1/00/baiocchi/HB/Story_Notes/Story_64764/ */ + /* Secure_ROM_Files/HB_SW_Files/hdwkeyHash */ + + /* Dale's files' hw-hash-key */ + uint64_t l_hdwkeyHash[] = { 0x6c8206fa4f551088, 0xc8c23af693ed242d, + 0x96824dac71bccf07, 0x73abb342d4bb932f, + 0x9a9a8d72fbf28202, 0xd89fa8fad5658959, + 0xc89ccf0d0205b8ca, 0x2071ba27e18ae0f8 + }; + + // Copy l_hdwkeyHash into sha2_hash_t + memcpy (o_sw_key_hash, &l_hdwkeyHash, sizeof(sha2_hash_t)); + + return; +} + + +#endif |