diff options
Diffstat (limited to 'src/securerom/ROM.C')
-rw-r--r-- | src/securerom/ROM.C | 665 |
1 files changed, 158 insertions, 507 deletions
diff --git a/src/securerom/ROM.C b/src/securerom/ROM.C index 2f73a5da5..bb1438772 100644 --- a/src/securerom/ROM.C +++ b/src/securerom/ROM.C @@ -22,558 +22,209 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -/**************************************************************************** - * - ****************************************************************************/ -#ifndef PHYPLIBFUNCTIONS -#include <ROM.h> -#endif -#include <ecverify.h> -#include <status_codes.h> -#include <string.h> - -/****************************************************************************/ -#define valid_magic_number(header) (GET32((header)->magic_number) == ROM_MAGIC_NUMBER) -#define valid_container_version(header) (GET16((header)->version) == CONTAINER_VERSION) - -/****************************************************************************/ -static int valid_ver_alg(ROM_version_raw* ver_alg, uint8_t sig_alg) { - if (GET16(ver_alg->version) != HEADER_VERSION) return 0; - if (ver_alg->hash_alg != HASH_ALG_SHA512) return 0; - if (!sig_alg) return 1; - if (ver_alg->sig_alg != sig_alg) return 0; - return 1; -} - -/****************************************************************************/ -static int valid_ecid(int ecid_count, uint8_t* ecids, uint8_t* hw_ecid) { - if (!ecid_count) return 1; - for (;ecid_count;ecid_count--,ecids+=ECID_SIZE) - if (!memcmp (hw_ecid, ecids, ECID_SIZE)) return 1; - return 0; -} -/****************************************************************************/ -static int multi_key_verify(uint8_t* digest, int key_count, uint8_t* keys, uint8_t* sigs) { - for (;key_count;key_count--,keys+=sizeof(ecc_key_t),sigs+=sizeof(ecc_signature_t)) - if (ec_verify (keys, digest, sigs)<1) return 0; - return 1; -} - -#ifndef PHYPLIBFUNCTIONS -/****************************************************************************/ -static inline ROM_container_raw* cast_container(uint64_t addr) { - return (ROM_container_raw*) Convert_Mem_Addr(physical_addr(addr)); -} - -/****************************************************************************/ -static inline void ROM_init_cache_area(uint64_t target, uint64_t size) { - uint64_t i; - for (i=0;i<size;i+=CACHE_LINE) { - assem_DCBZ(target); - target+=CACHE_LINE; - } -} +#include <securerom/ROM.H> +#include <securerom/ecverify.H> +#include <securerom/status_codes.H> +#include <string.h> -/****************************************************************************/ -//static inline void ROM_invalidate_cache_area(uint64_t target, uint64_t size) { -// uint64_t i; -// for (i=0;i<size;i+=CACHE_LINE) { -// assem_DCBI(target); -// target+=CACHE_LINE; -// } -//} +#define valid_magic_number(header) \ + (GET32((header)->magic_number) == ROM_MAGIC_NUMBER) +#define valid_container_version(header) \ + (GET16((header)->version) == CONTAINER_VERSION) -/****************************************************************************/ -static void ROM_memcpy_icbi (uint64_t* to, uint64_t* from, int64_t size) { - uint64_t* src=from; - uint64_t* dst=to; - for(;size>0;size-=sizeof(uint64_t)) { - *dst++ = *src++; - } - assem_SYNC(); //heavy weight form of sync instruction - //which ensures all stores have been performed - //prior to the subsequent icbi - assem_ICBI(to); //only need one of these to any address.... - //this is only needed to set internal scoreboard bit - //to tell the processor to flush - //when it sees a subsequent isync - assem_ISYNC(); +static int valid_ver_alg(ROM_version_raw* ver_alg, uint8_t sig_alg) +{ + if (GET16(ver_alg->version) != HEADER_VERSION) + { + return 0; + } + if (ver_alg->hash_alg != HASH_ALG_SHA512) + { + return 0; + } + if (!sig_alg) + { + return 1; + } + if (ver_alg->sig_alg != sig_alg) + { + return 0; + } + return 1; } -//extern void* __toc_start; - -#if 0 - -#define STACK_ASSUMPTION 128*1024 -#define STACK_FRAME (2*8) -/****************************************************************************/ -#undef CONTEXT -#define CONTEXT ROM_INSTRUCTION_START -/****************************************************************************/ -static inline void Create_C_Environment(uint64_t stack) { - #ifdef EMULATE_HW - printf ("Creating C Environment with stack pointer 0x%016llX\n",stack); - #else - // zero (create) stack area - ROM_init_cache_area(stack-STACK_ASSUMPTION, STACK_ASSUMPTION); - LOG(STACK_ZERO_DONE); - - // set stackpointer - register volatile uint64_t r1 __asm__ ("r1"); // if you remove the volatile keyword then the compiler removes your code - grr - r1 = stack-8; - //*((uint64_t*)stack) = 0ull; -- end stackframe --already 0 by dcbz above - - //setup initial stackframe - asm("stdu r1, -56(r1)"); - - #endif +static int valid_ecid(int ecid_count, uint8_t* ecids, uint8_t* hw_ecid) +{ + if (ecid_count == 0) + { + return 1; + } + return 0; } -static inline void initTOCpointer() { - #ifdef EMULATE_HW - printf ("Initialize r2 with TOC pointer\n"); - #else - // set TOC pointer (unused because no global variables) - // register uint64_t r2 __asm__ ("r2"); - // r2 = (uint64_t)__toc_start+0x8000; //only for one TOC - // r2 = ((uint64_t*)&ROM_instruction_start)[1]; //saver to get from { entry_point, toc_base, environment } - asm( - "springboard2: \n" - " b boingboing2 \n" // set CFAR - "boingboing2: \n" - " mfspr r2, 28 \n" // mfCFAR get address of springboard2 - " addi r2, r2, 0x4000 \n" // adjust to __toc_start (part 1) - " addi r2, r2, (__toc_start+0x4000-springboard2)@l \n" // adjust to __toc_start (part 2) - ); - #endif +static int multi_key_verify(uint8_t* digest, int key_count, uint8_t* keys, + uint8_t* sigs) +{ + for (;key_count;key_count--,keys+=sizeof(ecc_key_t), + sigs+=sizeof(ecc_signature_t)) + { + if (ec_verify (keys, digest, sigs)<1) + { + return 0; + } + } + return 1; } -/****************************************************************************/ -#undef CONTEXT -#define CONTEXT ROM_SELFTEST -/****************************************************************************/ -static void ROM_selftest(void) { -#ifndef EMULATE_HW - selftest_t const *selftest_p; - asm volatile("li %0,(__toc_start)@l ### %0 := base+0x8000 \n\t" // because li does not work - "sub %0,r2,%0 \n\t" // because subi does not work - "addi %0,%0,(selftest-0x8000)@l" : "=r" (selftest_p) ); -#else - selftest_t const *selftest_p = &selftest; //this line would introduce a absolute address in the toc -#endif - - sha2_hash_t digest; - LOG(BEGIN); - // sha512 good selftest - SHA512_Hash((uint8_t*)&selftest_p->ec, sizeof(selftest_p->ec), &digest); - if(memcmp(digest, selftest_p->sha.hash, sizeof(sha2_hash_t))) - ERROR_STOP(SHA_GOOD_TEST,"sha512 good selftest failed"); - // sha512 bad selftest - SHA512_Hash((uint8_t*)&selftest_p->ec, sizeof(selftest_p->ec)-1, &digest); - if(!memcmp (digest, selftest_p->sha.hash, sizeof(sha2_hash_t))) - ERROR_STOP(SHA_BAD_TEST,"sha512 bad selftest failed"); - // ecdsa verify good selftest - if (ec_verify (selftest_p->ec.pkey, selftest_p->ec.hash, selftest_p->ec.sig)<1) - ERROR_STOP(ECDSA_GOOD_TEST,"ecdsa good selftest failed"); - // ecdsa verify bad selftest (use digest from sha512 bad test) - if (ec_verify (selftest_p->ec.pkey, digest, selftest_p->ec.sig)!=0) - ERROR_STOP(ECDSA_BAD_TEST,"ecdsa bad selftest failed"); +static inline ROM_container_raw* cast_container(uint64_t addr) +{ + return (ROM_container_raw*) Convert_Mem_Addr(physical_addr(addr)); } -/****************************************************************************/ -#undef CONTEXT -#define CONTEXT C_INSTRUCTION_START -/****************************************************************************/ -uint64_t C_instruction_start( uint64_t xscom - , uint64_t fsp_bar - , uint64_t stack - , ROM_container_raw* container - ) { - LOG(BEGIN); - - // run crypto selftests - ROM_selftest(); - LOG(SELFTEST_DONE); - - // test for valid target hrmor address in trusted memory (security checks) - uint64_t target_hrmor = GET64(container->target_hrmor); - if(target_hrmor < 4096) - ERROR_STOP(TARGET_LOW_TEST,"target hrmor too low"); - if(target_hrmor & ~HRMOR_MASK) - ERROR_STOP(TARGET_VALID_TEST,"invalid target hrmor address"); - if(physical_addr(target_hrmor-4096)<fsp_bar) - ERROR_STOP(TARGET_TRUST_TEST,"target hrmor in untrusted memory"); - target_hrmor = ABSOLUTE_ADDR(target_hrmor); //WEH bug fix, moved to allow previous test to work - - // test for stack and container collision - uint64_t size = GET64(container->container_size); - if( stack > target_hrmor-4096 - && stack-STACK_ASSUMPTION <= target_hrmor+size - ) - ERROR_STOP(STACK_VS_TARGET_TEST,"container vs stack collision"); - - mtspr_HRMOR(target_hrmor); - - // clear ERATS because hrmor has changed - #ifdef EMULATE_HW - printf ("clear ERATS because hrmor has changed\n"); - #else - asm volatile ("slbia"); - #endif - - // zero target area and copy container - ROM_init_cache_area(target_hrmor-4096, size); - LOG(TARGET_ZERO_DONE); - ROM_container_raw* target = cast_container(target_hrmor-4096); - ROM_memcpy_icbi((uint64_t*)target, (uint64_t*)container, size); - LOG(CONTAINER_COPY_DONE); - - // test for prefix header with HBI base code (firmware) signing keys - ROM_prefix_header_raw* prefix = (ROM_prefix_header_raw*) &target->prefix; - if(!valid_ver_alg(&prefix->ver_alg, SIG_ALG_ECDSA521)) - ERROR_STOP(PREFIX_VER_ALG_TEST,"bad prefix header version,alg's"); - uint32_t flags = GET32 (prefix->flags); - if(!(flags & HBI_BASE_SIGNING_KEY)) - ERROR_STOP(HBI_KEY_TEST,"not HBI base code key prefix"); - - // verify - - // fill verify hw params - ROM_hw_params params; - getscom_PIBMEM_HW_Key_Hash(xscom, params.hw_key_hash); - getscom_HW_ECID(xscom, params.my_ecid); - if (ROM_verify(target,¶ms) != ROM_DONE) - ERROR_STOP(params.log,"see above"); // this will added C_INSTRUCTION_START to ROM_VERIFY for 0600 - LOG(CONTAINER_VERIFY_DONE); - - return HRMOR_RELATIVE(params.entry_point); +static inline void ROM_init_cache_area(uint64_t target, uint64_t size) +{ + uint64_t i; + for (i=0;i<size;i+=CACHE_LINE) + { + assem_DCBZ(target); + target+=CACHE_LINE; + } } -#endif - -/****************************************************************************/ #undef CONTEXT #define CONTEXT ROM_SRESET -/****************************************************************************/ -#ifdef EMULATE_HW -void ROM_sreset (void) { -#else -void ROM_sreset(void) { - asm volatile (".globl rom_sreset\n rom_sreset:"); //skip prologue -#endif - // should never get here unless started too soon by fsp/sbe, checkstop - ERROR_STOP(EXECUTION_ERROR,"sreset"); -} - -#if 0 -/****************************************************************************/ -#undef CONTEXT -#define CONTEXT ROM_INSTRUCTION_START -/****************************************************************************/ -//static inline void ROM_Cleanup_Stack(uint64_t stack) { -//#ifdef EMULATE_HW -// printf ("Cleaning up stack\n"); -//#endif -// ROM_invalidate_cache_area(stack-STACK_ASSUMPTION, STACK_ASSUMPTION); -//} - -/****************************************************************************/ -#ifdef EMULATE_HW -static void Call_Entry_Point(uint64_t start) { - printf ("Branching to entry point 0x%016llX (PHY 0x%016llX)\n",start,physical_addr(start)); - return; -#else -static void __attribute__((noreturn)) Call_Entry_Point(uint64_t start) { - - asm volatile ( " mtctr %0 \n" - " bctr \n" - " nop " - : // no output - : "r" (start) // input, %0 - // no impacts ? - ); - - ERROR_STOP(RETURNED_ERROR,"returned from Entry_Point"); - #if !defined(_lint_) - for (;;); - #endif -#endif -} - -/* Check the maximum limit of a untrusted memory BAR - * - * A BAR are two SCOM register one containing a mask and the other the pattern - * the address is in the untrusted memory when this is true: - * (address & mask) == pattern - * If this is true then a untrusted PIB master (like FSI) can write it. - * Remark: - * If a mask bit is 0 and the coresponding pattern bit is 1 then it is always false. - * - * parameter: - * limit = previous limit from other BARs or 0 - * xscom = the xscom base address - * bar = the pib address of the BAR register containing the pattern - * barMask = the pib address of the BAR register containing the mask - * return value: - * the new limit is the maximum from previous limit and the bars limit - */ -uint64_t check_bar(uint64_t limit, uint64_t xscom, uint64_t bar, uint64_t barMask) { - uint64_t barValue = getscom(xscom,bar); - uint64_t barMaskValue = getscom(xscom,barMask); - - barMaskValue |= 0xFFFC000000000000; // bit 0:13 not implemented and must be '1' - - uint64_t barLimit = (barValue | ~barMaskValue) + 1; - if( ( (barValue & ~barMaskValue) == 0) - && ( barLimit > limit) - ) { - limit=barLimit; - } - return limit; -} - -#endif - -/****************************************************************************/ #ifdef EMULATE_HW -void ROM_instruction_start(void) { -#else -void __attribute__((noreturn)) ROM_instruction_start(void) { - asm volatile (".globl instruction_start\ninstruction_start:"); //skip prologue -#endif - -#if 0 - - initTOCpointer(); - - LOG(BEGIN); - - // test for reasonable xscom base address (security check) - register uint64_t xscom = mfspr_SCRATCH0(); - if(!xscom) { - ERROR_STOP(XSCOM_LOW_TEST,"xscom base address too low"); - } - if(xscom & ~XSCOM_MASK) { - ERROR_STOP(XSCOM_VALID_TEST,"invalid xscom base address"); - } - xscom = ABSOLUTE_ADDR(xscom); - -#ifndef EMULATE_HW - // get trusted memory base - uint64_t fsp_bar=0; - fsp_bar = check_bar(fsp_bar, xscom, ALTD_UNTRUSTED_BAR_ADDR_REG, ALTD_UNTRUSTED_BAR_MASK_ADDR_REG); - fsp_bar = check_bar(fsp_bar, xscom, PSIHB_NOTRUST_BAR0, PSIHB_NOTRUST_BAR0MASK ); - fsp_bar = check_bar(fsp_bar, xscom, PSIHB_NOTRUST_BAR1, PSIHB_NOTRUST_BAR1MASK ); +void ROM_sreset (void) +{ #else - // get trusted memory base - uint64_t fsp_bar = (getscom_FSP_BAR_value(xscom) | ~getscom_FSP_BAR_mask(xscom)) + 1; +void ROM_sreset(void) +{ + asm volatile (".globl rom_sreset\n rom_sreset:"); //skip prologue #endif - - LOG(TRUSTED_MEM_BAR); - - register uint64_t raw_container = mfspr_SCRATCH1(); - if (raw_container < 4096) //must check for value that will wrap around - ERROR_STOP(CONTAINER_LOW_TEST,"container too low"); - raw_container = ABSOLUTE_ADDR(raw_container)-4096; - ROM_container_raw* container = cast_container(raw_container); - - // test for valid container magic number, version, hash & signature algorithms (sanity checks) - if(!valid_magic_number(container)) - ERROR_STOP(MAGIC_NUMBER_TEST,"bad container magic number"); - if (!valid_container_version (container)) - ERROR_STOP(CONTAINER_VERSION_TEST,"bad container version"); - - // test for trusted memory stack pointer (assumes 8K max depth) - register uint64_t stack = GET64(container->stack_pointer); - stack += STACK_ASSUMPTION; - if(stack < STACK_ASSUMPTION) { - ERROR_STOP(STACK_LOW_TEST,"stack pointer too low"); - } - if(stack & ~STACK_MASK) - ERROR_STOP(STACK_VALID_TEST,"invalid stack pointer address"); - if(physical_addr(stack-STACK_ASSUMPTION)<fsp_bar) - ERROR_STOP(STACK_TRUST_TEST,"stack in untrusted memory"); - stack = ABSOLUTE_ADDR(stack); //WEH bug fix, moved to allow previous test to work - - // launch C environment (zero stack) - Create_C_Environment(stack); - - // Jump to C code - register uint64_t entry = C_instruction_start(xscom,fsp_bar,stack,container); - - // cleanup (invalidate) stack - no longer required HBI takes care - //ROM_Cleanup_Stack(stack); - //LOG(STACK_CLEANUP_DONE); - - // clear scratch 0 and 1 reg - no longer required - //mtspr_SCRATCH0(0); - //mtspr_SCRATCH1(0); - - LOG(COMPLETED); - Call_Entry_Point(entry); // never return from here!!! - #endif + // should never get here unless started too soon by fsp/sbe, checkstop + ERROR_STOP(EXECUTION_ERROR,"sreset"); } -/****************************************************************************/ -#endif - #ifdef EMULATE_HW - #define FAILED(_c,_m) { params->log=ERROR_EVENT|CONTEXT|(_c); printf ("FAILED '%s'\n", (_m)); return ROM_FAILED; } + #define FAILED(_c,_m) { params->log=ERROR_EVENT|CONTEXT|(_c); \ + printf ("FAILED '%s'\n", (_m)); return ROM_FAILED; } #else - #define FAILED(_c,_m) { params->log=ERROR_EVENT|CONTEXT|(_c); return ROM_FAILED; } + #define FAILED(_c,_m) { params->log=ERROR_EVENT|CONTEXT|(_c); \ + return ROM_FAILED; } #endif -//**************************************************************************** #undef CONTEXT -#ifndef PHYPLIBFUNCTIONS #define CONTEXT ROM_VERIFY -//**************************************************************************** -// NOTE: ROM_verify is called with absolute addresses from c_instruction_start -// and with hrmor relative addresses from Hostboot +// NOTE: ROM_verify is called with with hrmor relative addresses from Hostboot asm(".globl .L.ROM_verify"); ROM_response ROM_verify( ROM_container_raw* container, - ROM_hw_params* params ) { -#else -#define CONTEXT PHYP_VERIFY -//**************************************************************************** -// NOTE: PHYP_verify is called with hrmor relative addresses from PHYP -ROM_response PHYP_verify( PHYP_command cmnd, - ROM_container_raw* container, - PHYP_hw_params* params, - PHYP_verify_state* state ) { -#endif - sha2_hash_t digest; - ROM_prefix_header_raw* prefix; - ROM_prefix_data_raw* hw_data; - ROM_sw_header_raw* header; - ROM_sw_sig_raw* sw_sig; - uint64_t size; - - params->log=CONTEXT|BEGIN; - -#ifdef PHYPLIBFUNCTIONS - if(cmnd != PHYP_CONTINUE) { -#endif - // test for valid container magic number, version, hash & signature algorithms (sanity check) + ROM_hw_params* params ) +{ + sha2_hash_t digest; + ROM_prefix_header_raw* prefix; + ROM_prefix_data_raw* hw_data; + ROM_sw_header_raw* header; + ROM_sw_sig_raw* sw_sig; + uint64_t size; + + params->log=CONTEXT|BEGIN; + + // test for valid container magic number, version, hash & signature + // algorithms (sanity check) if(!valid_magic_number(container)) FAILED(MAGIC_NUMBER_TEST,"bad container magic number"); if(!valid_container_version(container)) FAILED(CONTAINER_VERSION_TEST,"bad container version"); -#ifdef PHYPLIBFUNCTIONS - // initialize verify state - state->state = PHYP_START_VERIFY; - } - do { - switch(state->state) { - case PHYP_START_VERIFY: -#endif - // process hw keys - // test for valid hw keys - SHA512_Hash(container->hw_pkey_a, 3*sizeof(ecc_key_t), &digest); - if(memcmp(params->hw_key_hash, digest, sizeof(sha2_hash_t))) + // process hw keys + // test for valid hw keys + SHA512_Hash(container->hw_pkey_a, 3*sizeof(ecc_key_t), &digest); + if(memcmp(params->hw_key_hash, digest, sizeof(sha2_hash_t))) + { FAILED(HW_KEY_HASH_TEST,"invalid hw keys"); + } - // process prefix header - prefix = (ROM_prefix_header_raw*) &container->prefix; - // test for valid header version, hash & signature algorithms (sanity check) - if(!valid_ver_alg(&prefix->ver_alg, SIG_ALG_ECDSA521)) + // process prefix header + prefix = (ROM_prefix_header_raw*) &container->prefix; + // test for valid header version, hash & signature algorithms (sanity check) + if(!valid_ver_alg(&prefix->ver_alg, SIG_ALG_ECDSA521)) + { FAILED(PREFIX_VER_ALG_TEST,"bad prefix header version,alg's"); - // test for valid prefix header signatures (all) - hw_data = (ROM_prefix_data_raw*) (prefix->ecid + prefix->ecid_count*ECID_SIZE); - SHA512_Hash((uint8_t*)prefix, PREFIX_HEADER_SIZE(prefix), &digest); - if(!multi_key_verify(digest, 3, container->hw_pkey_a, hw_data->hw_sig_a)) + } + // test for valid prefix header signatures (all) + hw_data = (ROM_prefix_data_raw*) (prefix->ecid + + prefix->ecid_count*ECID_SIZE); + SHA512_Hash((uint8_t*)prefix, PREFIX_HEADER_SIZE(prefix), &digest); + if(!multi_key_verify(digest, 3, container->hw_pkey_a, hw_data->hw_sig_a)) + { FAILED(HW_SIGNATURE_TEST,"invalid hw signature"); - // test for machine specific matching ecid - if(!valid_ecid(prefix->ecid_count, prefix->ecid, params->my_ecid)) + } + // test for machine specific matching ecid + if(!valid_ecid(prefix->ecid_count, prefix->ecid, params->my_ecid)) + { FAILED(PREFIX_ECID_TEST,"unauthorized prefix ecid"); - // test for valid prefix payload hash - size = GET64(prefix->payload_size); - SHA512_Hash(hw_data->sw_pkey_p, size, &digest); - if(memcmp(prefix->payload_hash, digest, sizeof(sha2_hash_t))) + } + // test for valid prefix payload hash + size = GET64(prefix->payload_size); + SHA512_Hash(hw_data->sw_pkey_p, size, &digest); + if(memcmp(prefix->payload_hash, digest, sizeof(sha2_hash_t))) + { FAILED(PREFIX_HASH_TEST,"invalid prefix payload hash"); - // test for special prefix header - if(!prefix->sw_key_count) { - // finish processing special prefix header - // test for machine specfic (sanity check) - if(prefix->ecid_count == 0) - FAILED(SPECIAL_NO_ECID_TEST,"special prefix with ecid_count == 0"); - // test for signing of keys only (sanity check) - if(size != 0) - FAILED(SPECIAL_SIZE_0_TEST,"special prefix with payload_size != 0"); - // return hrmor relative code start address - params->entry_point = GET64(prefix->code_start_offset); - //check if the entry is HRMOR-relative and aligned - if(params->entry_point & ~(ENTRY_MASK)) - FAILED(ENTRY_VALID_TEST,"entry is not HRMOR relative or not aligned"); - params->log=CONTEXT|COMPLETED; - return ROM_DONE; - } - // finish processing prefix header - // test for protection of all sw key material (sanity check) - if(size != (prefix->sw_key_count * sizeof(ecc_key_t))) + } + // test for valid sw key count + if (prefix->sw_key_count < 1 || prefix->sw_key_count > 3) + { + FAILED(SW_KEY_INVALID_COUNT,"sw key count not between 1-3"); + } + // finish proce`sing prefix header + // test for protection of all sw key material (sanity check) + if(size != (prefix->sw_key_count * sizeof(ecc_key_t))) + { FAILED(SW_KEY_PROTECTION_TEST,"incomplete sw key protection in prefix header"); + } - // start processing sw header - header = (ROM_sw_header_raw*) (hw_data->sw_pkey_p + prefix->sw_key_count*sizeof(ecc_key_t)); - // test for valid header version, hash & signature algorithms (sanity check) - if(!valid_ver_alg(&header->ver_alg, 0)) + // start processing sw header + header = (ROM_sw_header_raw*) (hw_data->sw_pkey_p + + prefix->sw_key_count*sizeof(ecc_key_t)); + // test for valid header version, hash & signature algorithms (sanity check) + if(!valid_ver_alg(&header->ver_alg, 0)) + { FAILED(HEADER_VER_ALG_TEST,"bad sw header version,alg"); - // test for valid sw header signatures (all) - sw_sig = (ROM_sw_sig_raw*) (header->ecid + header->ecid_count*ECID_SIZE); - SHA512_Hash((uint8_t*)header, SW_HEADER_SIZE(header), &digest); - if(!multi_key_verify(digest, prefix->sw_key_count, hw_data->sw_pkey_p, sw_sig->sw_sig_p)) + } + // test for valid sw header signatures (all) + sw_sig = (ROM_sw_sig_raw*) (header->ecid + header->ecid_count*ECID_SIZE); + SHA512_Hash((uint8_t*)header, SW_HEADER_SIZE(header), &digest); + if(!multi_key_verify(digest, prefix->sw_key_count, hw_data->sw_pkey_p, + sw_sig->sw_sig_p)) + { FAILED(SW_SIGNATURE_TEST,"invalid sw signature"); - // test for machine specific matching ecid - if(!valid_ecid(header->ecid_count, header->ecid, params->my_ecid)) + } + // test for machine specific matching ecid + if(!valid_ecid(header->ecid_count, header->ecid, params->my_ecid)) + { FAILED(HEADER_ECID_TEST,"unauthorized sw ecid"); - // test for entry point within protected payload (sanity check) - params->entry_point = GET64(header->code_start_offset); - //check if the entry is HRMOR-relative and aligned - if(params->entry_point & ~(ENTRY_MASK)) - FAILED(ENTRY_VALID_TEST,"entry is not HRMOR relative or not aligned"); - size = GET64(header->payload_size); - if(params->entry_point+3 >= size) // must have full instruction (3 more bytes) + } + // test for entry point within protected payload (sanity check) + params->entry_point = GET64(header->code_start_offset); + //check if the entry is HRMOR-relative and aligned + if(params->entry_point & ~(ENTRY_MASK)) + { + FAILED(ENTRY_VALID_TEST,"entry is not HRMOR relative or not aligned"); + } + size = GET64(header->payload_size); + // must have full instruction (3 more bytes) + if(params->entry_point+3 >= size) + { FAILED(CODE_PROTECTION_TEST,"unprotected code_start in sw header"); - // begin test for valid sw payload hash -#ifdef PHYPLIBFUNCTIONS - state->message = (uint8_t*)container + 4096; - state->remain = size; - SHA512_Init(&state->sha); - state->header = header; - state->state = PHYP_CONT_VERIFY; - params->log=CONTEXT|PARTIAL; - break; - - case PHYP_CONT_VERIFY: - if(state->remain > params->max_hash) { - // continue test for valid sw payload hash - SHA512_Update(&state->sha, state->message, params->max_hash); - state->message += params->max_hash; - state->remain -= params->max_hash; - } else { - // finish test for valid sw payload hash - SHA512_Update(&state->sha, state->message, state->remain); - SHA512_Final(&state->sha, &digest); - header = state->header; -#else - SHA512_Hash((uint8_t*)container + 4096, size, &digest); -#endif - if(memcmp(header->payload_hash, digest, sizeof(sha2_hash_t))) - FAILED(HEADER_HASH_TEST,"invalid sw payload hash"); - params->log=CONTEXT|COMPLETED; - return ROM_DONE; -#ifdef PHYPLIBFUNCTIONS - } - break; + } + // begin test for valid sw payload hash + SHA512_Hash((uint8_t*)container + 4096, size, &digest); - default: - FAILED(EXECUTION_ERROR,"bad internal state"); - break; + if(memcmp(header->payload_hash, digest, sizeof(sha2_hash_t))) + { + FAILED(HEADER_HASH_TEST,"invalid sw payload hash"); } - } while (cmnd == PHYP_WHOLE); - params->log=CONTEXT|PARTIAL; - return PHYP_PARTIAL; -#endif + params->log=CONTEXT|COMPLETED; + return ROM_DONE; } |