diff options
author | Stephen Cprek <smcprek@us.ibm.com> | 2016-12-06 10:42:23 -0600 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2017-01-30 11:18:51 -0500 |
commit | 6b650f5428297e8dde075d25e7862a20c8d47f04 (patch) | |
tree | b268ac9fb258732a7aea73179c2f09992b76cc36 /src/securerom | |
parent | aff3f67b49b87d5e2755b364ecb512641bbb4540 (diff) | |
download | talos-hostboot-6b650f5428297e8dde075d25e7862a20c8d47f04.tar.gz talos-hostboot-6b650f5428297e8dde075d25e7862a20c8d47f04.zip |
Compile ROM code within Hostboot
Additionally added version id to resolve story 135747
RTC: 143902
Change-Id: I67ad4b28b76464aaa58ec2c344cd1f9ceef9ff73
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33608
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com>
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Reviewed-by: Martin Gloff <mgloff@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/securerom')
-rw-r--r-- | src/securerom/ROM.C | 665 | ||||
-rw-r--r-- | src/securerom/branchtable.S | 88 | ||||
-rw-r--r-- | src/securerom/ecverify.C | 2009 | ||||
-rw-r--r-- | src/securerom/hw_utils.C | 252 | ||||
-rw-r--r-- | src/securerom/inttypes.H | 1 | ||||
-rw-r--r-- | src/securerom/makefile | 231 | ||||
-rw-r--r-- | src/securerom/sha512.C | 681 |
7 files changed, 1651 insertions, 2276 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; } diff --git a/src/securerom/branchtable.S b/src/securerom/branchtable.S index d3c1c8608..86a1f92a8 100644 --- a/src/securerom/branchtable.S +++ b/src/securerom/branchtable.S @@ -25,74 +25,68 @@ #**************************************************************************** #* branch table - a more stable location for software entering rom code #**************************************************************************** -# adr function -# 0 instruction_start -# 2 .SHA512_Init -# 4 .SHA512_Update -# 6 .SHA512_Final -# 8 .SHA512_Hash -# A .ec_verify -# C .ROM_verify -# 100 rom_sreset -branchtable: - .section ".branchtable","ax" +.include "kernel/ppcconsts.S" - .globl _instruction_start -_instruction_start: - b instruction_start - nop +branchtable: + .section ".branchtable","ax" - .globl _SHA512_Init + .globl _SHA512_Init _SHA512_Init: - li r0, .L.SHA512_Init@l - b springboard + li r0, .L.SHA512_Init@l + b springboard - .globl _SHA512_Update + .globl _SHA512_Update _SHA512_Update: - li r0, .L.SHA512_Update@l - b springboard + li r0, .L.SHA512_Update@l + b springboard - .globl _SHA512_Final + .globl _SHA512_Final _SHA512_Final: - li r0, .L.SHA512_Final@l - b springboard + li r0, .L.SHA512_Final@l + b springboard - .globl _SHA512_Hash + .globl _SHA512_Hash _SHA512_Hash: - li r0, .L.SHA512_Hash@l - b springboard + li r0, .L.SHA512_Hash@l + b springboard - .globl _ec_verify + .globl _ec_verify _ec_verify: - li r0, .L.ec_verify@l - b springboard + li r0, .L.ec_verify@l + b springboard - .globl _ROM_verify + .globl _ROM_verify _ROM_verify: - li r0, .L.ROM_verify@l - b springboard + li r0, .L.ROM_verify@l + b springboard #define CFAR 28 springboard: - b boingboing + b boingboing boingboing: - mfspr r2, CFAR // get address of springboard - addi r2, r2, _instruction_start-springboard // base address - add r0, r0, r2 // calculate entry relative - addi r2, r2, 0x4000 //TOC+0x8000 part 1 - addi r2, r2, (__toc_start+0x4000)@l //TOC+0x8000 part 2 - mtctr r0 - bctr // jump + mfspr r2, CFAR ;// get address of springboard + addi r2, r2, _SHA512_Init-springboard ;// base address + add r0, r0, r2 ;// calculate entry relative + addi r2, r2, 0x4000 ;//TOC+0x8000 part 1 + addi r2, r2, (__toc_start+0x4000)@l ;//TOC+0x8000 part 2 + mtctr r0 + bctr ;// jump # could put other assembly ocde routines here to conserver ROM space # including the sreset routine -# need to align on bootrombase+0x100 !!! - .org .branchtable+0x100 - .globl _rom_sreset +# need to align on securerombase+0x100 !!! + .org .branchtable+0x100 + .globl _rom_sreset _rom_sreset: - li r0, rom_sreset@l - b springboard - nop + li r0, rom_sreset@l + b springboard + nop + +.section .data + +.global hbi_ImageId +hbi_ImageId: + .space 128 diff --git a/src/securerom/ecverify.C b/src/securerom/ecverify.C index 659d7d6fb..a4ba85a65 100644 --- a/src/securerom/ecverify.C +++ b/src/securerom/ecverify.C @@ -22,14 +22,6 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -/*---------------------------------------------------------------------- - * (C) COPYRIGHT INTERNATIONAL BUSINESS MACHINES CORPORATION 2010 - * ALL RIGHTS RESERVED - * IBM Research, Zurich and IBM Crypto Competency Center, Copenhagen - *---------------------------------------------------------------------- - * Author: Tamas Visegrady (tvi@zurich.ibm.com) - * Change: W Eric Hall (wehall@us.ibm.com) - *----------------------------------------------------------------------*/ /** ECDSA verification on fixed curve/s (currently, on NIST P-521) * The code below works for a compile-time constant curve, and requires @@ -48,25 +40,23 @@ #include <stdio.h> #include <string.h> #include <stdint.h> /* uint_fast8_t, uintN_t */ -#include <inttypes.h> /* PRIx64 used to format bn_t's */ +#include "inttypes.H" /* PRIx64 used to format bn_t's */ /** * Define __LITTLE_ENDIAN or __BIG_ENDIAN for target. */ #if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN - #define __BIG_ENDIAN - #undef __LITTLE_ENDIAN + #define __BIG_ENDIAN + #undef __LITTLE_ENDIAN #else - #undef __BIG_ENDIAN - #define __LITTLE_ENDIAN + #undef __BIG_ENDIAN + #define __LITTLE_ENDIAN #endif -#include "ecverify.h" - +#include <securerom/ecverify.H> #define EC_PRIMEBITS 521 /* P521 */ -//#define EC_DEBUG 1 /* needs libc (not in Prism version) */ #define EC_STACKTRACE 1 /* debug only; currently, glibc */ #define NO_EC_DOUBLE_XY 1 /* do not implement ec_double_xy */ @@ -76,20 +66,6 @@ typedef uint_fast8_t bnindex_t; #define BN_FMT "%016" PRIx64 /* PRIx64 from inttypes.h */ - -// show word boundaries in bignumbers (diagnostics dump only) -// #define EC_DEBUG_WORDS 1 - - -// define this if we construct ec_prime[] on the fly -// saves code, adds runtime static structs; check your compiler if useful -// does not make sense if non-exec, read-only constants are cheap -// -// #define BN_PRIME_GENERATED 1 - - -//--- nothing user-servicable below --------------------------------------- - #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN) #error "Please define target endianness (__LITTLE_ENDIAN or __BIG_ENDIAN)" #endif @@ -106,8 +82,7 @@ typedef uint_fast8_t bnindex_t; #define BN_MAXBIT (((bn_t) 1) << (BN_BITS -1)) -#define BITS2BN(bits) \ - (((bits) +BN_BITS -1) / BN_BITS) +#define BITS2BN(bits) (((bits) +BN_BITS -1) / BN_BITS) // we only deal with big numbers of fixed size #define NWORDS BITS2BN( EC_PRIMEBITS ) @@ -123,21 +98,22 @@ typedef uint_fast8_t bnindex_t; #else static void __attribute__((noinline)) BN_COPY (bn_t *dst, const bn_t *src) { - size_t i; - for(i=0;i<NWORDS;i++) { - *dst++ = *src++; - } + size_t i; + for(i=0;i<NWORDS;i++) + { + *dst++ = *src++; + } } #endif #ifdef BN_POWER64_DBG static void __attribute__((noinline)) BN_DUMP (int i, bn_t *top) { - asm volatile ("nop" : : "r" (i), "r" (top)); + asm volatile ("nop" : : "r" (i), "r" (top)); } static void BN_EXIT (void) { - asm volatile("b .Check_Stop"); + asm volatile("b .Check_Stop"); } #else #define BN_DUMP(_i,_bn) ((void)0) @@ -161,19 +137,15 @@ static void bn_dprint (const char *msg, const bn_t *m) ; #define EC_DEVASSERT(cond) ((void) 0) // removed '((void) cond)' which still did the cond test #endif - - static bn_t bn_sub (bn_t *a, const bn_t *b) ; static void bn_add (bn_t *a, const bn_t *b) ; static void bn_mul (bn_t *r, const bn_t *a, const bn_t *b) ; static void bn_modadd (bn_t *a, const bn_t *b) ; static void bn_modsub (bn_t *a, const bn_t *b) ; -// static int bn_cmp (const bn_t *a, const bn_t *b) ; static int bn_cmp (const bn_t a[NWORDS], const bn_t b[NWORDS]) ; // P521: a==-3, fixed curve parameter -// static int ec_double (bn_t *x, bn_t *y, bn_t *z) ; @@ -189,105 +161,101 @@ static int ec_double (bn_t *x, bn_t *y, bn_t *z) ; typedef struct { - bn_t ec_prime[ NWORDS ]; + bn_t ec_prime[ NWORDS ]; bn_t ec_order[ NWORDS ]; bn_t prime_px[ NWORDS ]; bn_t prime_py[ NWORDS ]; bn_t ec_order_qn[ NWORDS ]; } consts_t; -const consts_t consts = { +extern "C" +const consts_t consts = { //const bn_t ec_prime[ NWORDS ] = - { - BN_PRIME_MSW, - 0xffffffffffffffffLL, - 0xffffffffffffffffLL, - 0xffffffffffffffffLL, - 0xffffffffffffffffLL, - 0xffffffffffffffffLL, - 0xffffffffffffffffLL, - 0xffffffffffffffffLL, - 0xffffffffffffffffLL, - }, - -//------------------------------------- + { + BN_PRIME_MSW, + 0xffffffffffffffffLL, + 0xffffffffffffffffLL, + 0xffffffffffffffffLL, + 0xffffffffffffffffLL, + 0xffffffffffffffffLL, + 0xffffffffffffffffLL, + 0xffffffffffffffffLL, + 0xffffffffffffffffLL, + }, //const bn_t ec_order[ NWORDS ] = { - 0x00000000000001ffLL, - 0xffffffffffffffffLL, - 0xffffffffffffffffLL, - 0xffffffffffffffffLL, - 0xfffffffffffffffaLL, - 0x51868783bf2f966bLL, - 0x7fcc0148f709a5d0LL, - 0x3bb5c9b8899c47aeLL, - 0xbb6fb71e91386409LL, + 0x00000000000001ffLL, + 0xffffffffffffffffLL, + 0xffffffffffffffffLL, + 0xffffffffffffffffLL, + 0xfffffffffffffffaLL, + 0x51868783bf2f966bLL, + 0x7fcc0148f709a5d0LL, + 0x3bb5c9b8899c47aeLL, + 0xbb6fb71e91386409LL, }, //const bn_t prime_px[ NWORDS ] = { { - 0x00000000000000c6LL, - 0x858e06b70404e9cdLL, - 0x9e3ecb662395b442LL, - 0x9c648139053fb521LL, - 0xf828af606b4d3dbaLL, - 0xa14b5e77efe75928LL, - 0xfe1dc127a2ffa8deLL, - 0x3348b3c1856a429bLL, - 0xf97e7e31c2e5bd66LL, + 0x00000000000000c6LL, + 0x858e06b70404e9cdLL, + 0x9e3ecb662395b442LL, + 0x9c648139053fb521LL, + 0xf828af606b4d3dbaLL, + 0xa14b5e77efe75928LL, + 0xfe1dc127a2ffa8deLL, + 0x3348b3c1856a429bLL, + 0xf97e7e31c2e5bd66LL, }, //const bn_t prime_py[ NWORDS ] = { { - 0x0000000000000118LL, - 0x39296a789a3bc004LL, - 0x5c8a5fb42c7d1bd9LL, - 0x98f54449579b4468LL, - 0x17afbd17273e662cLL, - 0x97ee72995ef42640LL, - 0xc550b9013fad0761LL, - 0x353c7086a272c240LL, - 0x88be94769fd16650LL, - }, - - //-------------------------- mod mul by order (n) ------- - // MS 521 bits of Q/N, fractional part - // -// static const bn_t ec_order_qn[ NWORDS ] = - { - 0LL, - 0LL, - 0LL, - 0LL, - 0x0000000000000005LL, - 0xae79787c40d06994LL, - 0x8033feb708f65a2fLL, - 0xc44a36477663b851LL, - 0x449048e16ec79bf6LL, - } + 0x0000000000000118LL, + 0x39296a789a3bc004LL, + 0x5c8a5fb42c7d1bd9LL, + 0x98f54449579b4468LL, + 0x17afbd17273e662cLL, + 0x97ee72995ef42640LL, + 0xc550b9013fad0761LL, + 0x353c7086a272c240LL, + 0x88be94769fd16650LL, + }, + +//-------------------------- mod mul by order (n) ------- +// MS 521 bits of Q/N, fractional part +// +// static const bn_t ec_order_qn[ NWORDS ] = + { + 0LL, + 0LL, + 0LL, + 0LL, + 0x0000000000000005LL, + 0xae79787c40d06994LL, + 0x8033feb708f65a2fLL, + 0xc44a36477663b851LL, + 0x449048e16ec79bf6LL, + } } ; -inline const consts_t* __attribute__((pure)) consts_p() { +inline const consts_t* __attribute__((pure)) consts_p() +{ + #ifdef EMULATE_HW - return &consts; + return &consts; #else consts_t* result_consts_p; - asm("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,(consts-0x8000)@l" : "=r" (result_consts_p) ); + asm volatile("li %0,(__toc_start)@l ### %0 := base+0x8000 \n\t" // because li does not work + "sub %0,2,%0 \n\t" // because subi does not work + "addi %0,%0,(consts-0x8000)@l" : "=r" (result_consts_p) ); return result_consts_p; #endif } -//------------------------------------- - - #define bn_ge_prime(val) (bn_cmp((val), consts_p()->ec_prime) >= 0) #define bn_ge_order(val) (bn_cmp((val), consts_p()->ec_order) >= 0) - -//------------------------------------- // P521: MSW has unused bits #define BN_MSW_UNUSED_BITS (BN_BITS - BN_PRIME_MSW_BITS) #define BN_MSW_UNUSED_BYTES ((BN_MSW_UNUSED_BITS +7) >>3) @@ -300,23 +268,23 @@ inline const consts_t* __attribute__((pure)) consts_p() { // static bn_t bn_shl (bn_t *a, bn_t acc) { - bnindex_t i = NWORDS; - bn_t cf = 0; - - EC_ASSERT(NULL != a); - EC_ASSERT(0 == a[0]); + bnindex_t i = NWORDS; + bn_t cf = 0; - a += NWORDS; + EC_ASSERT(NULL != a); + EC_ASSERT(0 == a[0]); - while (0<i--) { - cf = *(--a); - *a <<= BN_MSW_UNUSED_BITS; - *a |= BN_MSW_UNUSED_MASK & (acc >> BN_PRIME_MSW_BITS); + a += NWORDS; - acc = cf; - } + while (0<i--) + { + cf = *(--a); + *a <<= BN_MSW_UNUSED_BITS; + *a |= BN_MSW_UNUSED_MASK & (acc >> BN_PRIME_MSW_BITS); + acc = cf; + } - return cf; + return cf; } @@ -325,38 +293,40 @@ static bn_t bn_shl (bn_t *a, bn_t acc) static void bn_printn (const char *msg, const bn_t *m, bnindex_t i) { - EC_ASSERT(NULL != m); + EC_ASSERT(NULL != m); - if (NULL != msg) - printf("%s", msg); + if (NULL != msg) + { + printf("%s", msg); + } - while (0 < i--) { + while (0 < i--) + { #if defined(EC_DEBUG_WORDS) - if (i<NWORDS-1) - printf("."); + if (i<NWORDS-1) + { + printf("."); + } #endif - printf(BN_FMT, *(m++)); - } + printf(BN_FMT, *(m++)); + } - printf("\n"); + printf("\n"); } - static void bn_print (const char *msg, const bn_t *m) { - bn_printn(msg, m, NWORDS); + bn_printn(msg, m, NWORDS); } - static void bn_dprint (const char *msg, const bn_t *m) { - bn_printn(msg, m, NWORDS+NWORDS); + bn_printn(msg, m, NWORDS+NWORDS); } #endif /* defined(EC_DEBUG) */ - //============================================== modular multiplication ==== // this section should be routed to hardware, when it becomes available @@ -368,11 +338,12 @@ static void bn_dprint (const char *msg, const bn_t *m) #define bn_dclear(n) bn_clr((n), 2*NWORDS) static void __attribute__((noinline)) bn_clr (bn_t *dst, size_t s) { - size_t i; - dst--; - for(i=0;i<s;i++) { - *(++dst) = 0LL; - } + size_t i; + dst--; + for(i=0;i<s;i++) + { + *(++dst) = 0LL; + } } #endif @@ -384,40 +355,41 @@ static void __attribute__((noinline)) bn_clr (bn_t *dst, size_t s) static bn_t bn_dmul (bn_t a, bn_t b) { #ifdef EC_POWER64_ASM - bn_t t; - asm("mulhdu %0,%1,%2" : "=r" (t) : "r" (a), "r" (b) ); - return t; + bn_t t; + asm("mulhdu %0,%1,%2" : "=r" (t) : "r" (a), "r" (b) ); + return t; #else - hbn_t ah, al, bh, bl; - bn_t t; - - al = a; - ah = (hbn_t) (a >> HBN_BITS); - bl = b; - bh = (hbn_t) (b >> HBN_BITS); - - a = ((bn_t) ah) * bh; // collects high word - b = ((bn_t) al) * bl; // collects low word - - t = ((bn_t) ah) * bl; - a += t >> HBN_BITS; - t <<= HBN_BITS; - if (b+t < t) - ++a; - b += t; - - t = ((bn_t) al) * bh; - a += t >> HBN_BITS; - t <<= HBN_BITS; - if (b+t < t) - ++a; -// b += t; // we don't actually need this, only its carry above - return a; + hbn_t ah, al, bh, bl; + bn_t t; + + al = a; + ah = (hbn_t) (a >> HBN_BITS); + bl = b; + bh = (hbn_t) (b >> HBN_BITS); + + a = ((bn_t) ah) * bh; // collects high word + b = ((bn_t) al) * bl; // collects low word + + t = ((bn_t) ah) * bl; + a += t >> HBN_BITS; + t <<= HBN_BITS; + if (b+t < t) + { + ++a; + } + b += t; + + t = ((bn_t) al) * bh; + a += t >> HBN_BITS; + t <<= HBN_BITS; + if (b+t < t) + { + ++a; + } + return a; #endif } - -//------------------------------------- /** multiply (a,NWORDS) by (b,NWORDS) into (r,2*NWORDS) * we collect 2-word multiples, and carries across columns in two * arrays: @@ -435,110 +407,121 @@ static bn_t bn_dmul (bn_t a, bn_t b) // static void bn_mul (bn_t *r, const bn_t *a, const bn_t *b) { - unsigned char cf[ NWORDS+NWORDS ]; /* carry collector */ - bnindex_t i, j; - bn_t ph, pl; /* product high,low words */ + unsigned char cf[ NWORDS+NWORDS ]; /* carry collector */ + bnindex_t i, j; + bn_t ph, pl; /* product high,low words */ - EC_ASSERT(NULL != r); - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != b); + EC_ASSERT(NULL != r); + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != b); - bn_dclear(r); - memset(cf, 0, sizeof(cf)); + bn_dclear(r); + memset(cf, 0, sizeof(cf)); - for (j=0; j<NWORDS; ++j) { - for (i=0; i<NWORDS; ++i) { - ph = bn_dmul(a[i], b[j]); - pl = a[i] * b[j]; + for (j=0; j<NWORDS; ++j) + { + for (i=0; i<NWORDS; ++i) + { + ph = bn_dmul(a[i], b[j]); + pl = a[i] * b[j]; #ifdef EC_POWER64_ASM - asm("addc %0,%2,%4\n" - "addze %1,%3" - : "=r" (r[i+j]), "=r" (cf[i+j]) - : "0" (r[i+j]), "1" (cf[i+j]), "r" (ph) - ); - asm("addc %0,%2,%4\n" - "addze %1,%3" - : "=r" (r[i+j+1]), "=r" (cf[i+j+1]) - : "0" (r[i+j+1]), "1" (cf[i+j+1]), "r" (pl) - ); + asm("addc %0,%2,%4\n" + "addze %1,%3" + : "=r" (r[i+j]), "=r" (cf[i+j]) + : "0" (r[i+j]), "1" (cf[i+j]), "r" (ph) + ); + asm("addc %0,%2,%4\n" + "addze %1,%3" + : "=r" (r[i+j+1]), "=r" (cf[i+j+1]) + : "0" (r[i+j+1]), "1" (cf[i+j+1]), "r" (pl) + ); #else - r[i+j] += ph; - if (r[i+j] < ph) { - EC_ASSERT(i+j>0); // MSW can't carry to left - (cf[i+j-1])++; - } - - r[i+j+1] += pl; - if (r[i+j+1] < pl) - (cf[i+j])++; + r[i+j] += ph; + if (r[i+j] < ph) + { + EC_ASSERT(i+j>0); // MSW can't carry to left + (cf[i+j-1])++; + } + + r[i+j+1] += pl; + if (r[i+j+1] < pl) + { + (cf[i+j])++; + } #endif - } - } + } + } - // propagate carries (LS to MS) + // propagate carries (LS to MS) #ifdef EC_POWER64_ASM - i=NWORDS+NWORDS-2; - asm("addc %0,%1,%2" - : "=r" (r[i]) - : "0" (r[i]), "r" (cf[i+1]) - ); - for ( ; 0<i; ) { - --i; - asm("adde %0,%1,%2" - : "=r" (r[i]) - : "0" (r[i]), "r" (cf[i+1]) - ); + i=NWORDS+NWORDS-2; + asm("addc %0,%1,%2" + : "=r" (r[i]) + : "0" (r[i]), "r" (cf[i+1]) + ); + for ( ; 0<i; ) + { + --i; + asm("adde %0,%1,%2" + : "=r" (r[i]) + : "0" (r[i]), "r" (cf[i+1]) + ); #else - for (i=NWORDS+NWORDS; 0<i; ) { - if (cf[--i]) { - r[i] += cf[i]; - if (r[i] < cf[i]) { - EC_ASSERT(0 < i); - cf[i-1]++; - } - } + for (i=NWORDS+NWORDS; 0<i; ) + { + if (cf[--i]) + { + r[i] += cf[i]; + if (r[i] < cf[i]) + { + EC_ASSERT(0 < i); + cf[i-1]++; + } + } #endif - } + } } #else static void bn_mul (bn_t *r, const bn_t *a, const bn_t *b) { - bnindex_t i, j; - bn_t ph, pl, th, tb; /* product high,low words */ + bnindex_t i, j; + bn_t ph, pl, th, tb; /* product high,low words */ - EC_ASSERT(NULL != r); - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != b); + EC_ASSERT(NULL != r); + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != b); - bn_dclear(r); + bn_dclear(r); - r += NWORDS; - b += NWORDS; - for (j=0; j<NWORDS; j++) { - th = 0LL; - tb = *(--b); r += NWORDS; - a += NWORDS; - for (i=0; i<NWORDS; i++) { - asm("mulld %0,%1,%2" //pl = *(--a) * tb - : "=r" (pl) - : "r" (*(--a)), "r" (tb) - ); - asm("mulhdu %0,%1,%2" //ph = *a * tb - : "=r" (ph) - : "r" (*a), "r" (tb) - ); - asm("addc %1,%5,%4\n" //pl += *(--r) - "addze %2,%6\n" //ph += ca - "addc %0,%5,%7\n" //*r = pl + th - "addze %3,%6" //th = ph + ca - : "=r" (*r), "=r" (pl), "=r" (ph), "=r" (th) - : "0" (*(--r)), "1" (pl), "2" (ph), "3" (th) - ); + b += NWORDS; + for (j=0; j<NWORDS; j++) + { + th = 0LL; + tb = *(--b); + r += NWORDS; + a += NWORDS; + for (i=0; i<NWORDS; i++) + { + asm("mulld %0,%1,%2" //pl = *(--a) * tb + : "=r" (pl) + : "r" (*(--a)), "r" (tb) + ); + asm("mulhdu %0,%1,%2" //ph = *a * tb + : "=r" (ph) + : "r" (*a), "r" (tb) + ); + asm("addc %1,%5,%4\n" //pl += *(--r) + "addze %2,%6\n" //ph += ca + "addc %0,%5,%7\n" //*r = pl + th + "addze %3,%6" //th = ph + ca + : "=r" (*r), "=r" (pl), "=r" (ph), "=r" (th) + : "0" (*(--r)), "1" (pl), "2" (ph), "3" (th) + ); + } + *(--r) = th; } - *(--r) = th; - } } #endif @@ -546,75 +529,77 @@ static void bn_mul (bn_t *r, const bn_t *a, const bn_t *b) #ifdef BN_POWER64_SQR static void bn_sqr (bn_t *r, const bn_t *a) { - bnindex_t i, j; - const bn_t *b; /* product high,low words */ - bn_t *c, ph, pl, ta, t0, t1, t2; /* product high,low words */ + bnindex_t i, j; + const bn_t *b; /* product high,low words */ + bn_t *c, ph, pl, ta, t0, t1, t2; /* product high,low words */ - EC_ASSERT(NULL != r); - EC_ASSERT(NULL != a); + EC_ASSERT(NULL != r); + EC_ASSERT(NULL != a); - bn_dclear(r); + bn_dclear(r); - r += 2*NWORDS; - a += NWORDS; - for (j=0; j<NWORDS-1; j++) { + r += 2*NWORDS; + a += NWORDS; + for (j=0; j<NWORDS-1; j++) + { + ta = *(--a); + c = r; + b = a; + asm("mulld %0,%2,%2\n" //pl = ta * ta + "mulhdu %1,%2,%2" //ph = ta * ta + : "=r" (pl), "=r" (ph) + : "r" (ta) + ); + asm("addc %0,%2,%4\n" //*r = *(--r) + pl + "addze %1,%3" //t0 = ph + ca + : "=r" (*c), "=r" (t0) + : "0" (*(--c)), "r" (ph), "r" (pl) + ); + t1 = 0L; + for (i=j+1; i<NWORDS; i++) + { + t2 = 0L; + asm("mulld %0,%1,%2" //pl = *(--b) * ta + : "=r" (pl) + : "r" (*(--b)), "r" (ta) + ); + asm("mulhdu %0,%1,%2" //ph = *b * ta + : "=r" (ph) + : "r" (*b), "r" (ta) + ); + asm("addc %1,%7,%7\n" //pl += pl + "adde %2,%8,%8\n" //ph += ph + ca + "addze %5,%11\n" //t2 += ca + "addc %1,%7,%9\n" //pl += t0 + "adde %2,%8,%10\n" //ph += t1 + ca + "addze %5,%11\n" //t2 += ca + "addc %0,%6,%7\n" //*r = *(--r) + pl + "addze %3,%8\n" //t0 = ph + ca + "addze %4,%11" //t1 = t2 + ca + : "=r" (*c), "=r" (pl), "=r" (ph), "=r" (t0), "=r" (t1), "=r" (t2) + : "0" (*(--c)), "1" (pl), "2" (ph), "3" (t0), "4" (t1), "5" (t2) + ); + } + asm("addc %0,%2,%4\n" //*r = *(--r) + t0 + "addze %1,%3" //t1 += ca + : "=r" (*c), "=r" (t1) + : "0" (*(--c)), "1" (t1), "r" (t0) + ); + *(--c) = t1; + r -= 2; + } ta = *(--a); - c = r; - b = a; - asm("mulld %0,%2,%2\n" //pl = ta * ta - "mulhdu %1,%2,%2" //ph = ta * ta + asm("mulld %0,%2,%2\n" //pl = ta * ta + "mulhdu %1,%2,%2" //ph = ta * ta : "=r" (pl), "=r" (ph) : "r" (ta) ); - asm("addc %0,%2,%4\n" //*r = *(--r) + pl - "addze %1,%3" //t0 = ph + ca - : "=r" (*c), "=r" (t0) - : "0" (*(--c)), "r" (ph), "r" (pl) + asm("addc %0,%2,%4\n" //*r = *(--r) + pl + "addze %1,%3" //ph += ca + : "=r" (*r), "=r" (ph) + : "0" (*(--r)), "1" (ph), "r" (pl) ); - t1 = 0L; - for (i=j+1; i<NWORDS; i++) { - t2 = 0L; - asm("mulld %0,%1,%2" //pl = *(--b) * ta - : "=r" (pl) - : "r" (*(--b)), "r" (ta) - ); - asm("mulhdu %0,%1,%2" //ph = *b * ta - : "=r" (ph) - : "r" (*b), "r" (ta) - ); - asm("addc %1,%7,%7\n" //pl += pl - "adde %2,%8,%8\n" //ph += ph + ca - "addze %5,%11\n" //t2 += ca - "addc %1,%7,%9\n" //pl += t0 - "adde %2,%8,%10\n" //ph += t1 + ca - "addze %5,%11\n" //t2 += ca - "addc %0,%6,%7\n" //*r = *(--r) + pl - "addze %3,%8\n" //t0 = ph + ca - "addze %4,%11" //t1 = t2 + ca - : "=r" (*c), "=r" (pl), "=r" (ph), "=r" (t0), "=r" (t1), "=r" (t2) - : "0" (*(--c)), "1" (pl), "2" (ph), "3" (t0), "4" (t1), "5" (t2) - ); - } - asm("addc %0,%2,%4\n" //*r = *(--r) + t0 - "addze %1,%3" //t1 += ca - : "=r" (*c), "=r" (t1) - : "0" (*(--c)), "1" (t1), "r" (t0) - ); - *(--c) = t1; - r -= 2; - } - ta = *(--a); - asm("mulld %0,%2,%2\n" //pl = ta * ta - "mulhdu %1,%2,%2" //ph = ta * ta - : "=r" (pl), "=r" (ph) - : "r" (ta) - ); - asm("addc %0,%2,%4\n" //*r = *(--r) + pl - "addze %1,%3" //ph += ca - : "=r" (*r), "=r" (ph) - : "0" (*(--r)), "1" (ph), "r" (pl) - ); - *(--r) += ph; + *(--r) += ph; } #endif #endif @@ -636,34 +621,40 @@ static void bn_sqr (bn_t *r, const bn_t *a) #ifndef EC_POWER64_RED static void bn_modred_p521 (bn_t *r, bn_t *a) { - bn_t *al; -bn_t *rc = r; + bn_t *al; + bn_t *rc = r; - EC_ASSERT(NULL != r); - EC_ASSERT(NULL != a); - EC_ASSERT((const bn_t *) r != a); + EC_ASSERT(NULL != r); + EC_ASSERT(NULL != a); + EC_ASSERT((const bn_t *) r != a); - al = a+NWORDS; + al = a+NWORDS; - // P521: product is 1042 bits, MSW of double-width bignum always 0 - // - EC_ASSERT(0 == a[0]); + // P521: product is 1042 bits, MSW of double-width bignum always 0 + // + EC_ASSERT(0 == a[0]); - BN_COPY(rc, a); - bn_shl(rc, *al); + BN_COPY(rc, a); + bn_shl(rc, *al); - *al &= BN_PRIME_MSW_MASK; + *al &= BN_PRIME_MSW_MASK; - if (bn_cmp(rc, consts_p()->ec_prime) >= 0) - bn_sub(rc, consts_p()->ec_prime); // XXX can this happen? (mod-based input) + if (bn_cmp(rc, consts_p()->ec_prime) >= 0) + { + bn_sub(rc, consts_p()->ec_prime); // XXX can this happen? (mod-based input) + } - if (bn_cmp(al, consts_p()->ec_prime) >= 0) - bn_sub(al, consts_p()->ec_prime); - EC_ASSERT(!bn_ge_prime(al)); // al must have bitlen <= ec_prime + if (bn_cmp(al, consts_p()->ec_prime) >= 0) + bn_sub(al, consts_p()->ec_prime); + { + EC_ASSERT(!bn_ge_prime(al)); // al must have bitlen <= ec_prime + } - bn_add(rc, al); - if (bn_cmp(rc, consts_p()->ec_prime) >= 0) - bn_sub(rc, consts_p()->ec_prime); + bn_add(rc, al); + if (bn_cmp(rc, consts_p()->ec_prime) >= 0) + { + bn_sub(rc, consts_p()->ec_prime); + } } #else #ifdef BN_POWER64_SQR @@ -672,71 +663,74 @@ static void __attribute__((noinline)) bn_modred_fast (bn_t *r, bn_t *a) static void bn_modred_fast (bn_t *r, bn_t *a) #endif { - bn_t *ah = a + NWORDS; - bn_t *al = a + 2*NWORDS; - bn_t t0 = (*(a+1) >> 18) + (*ah >> 9); - bn_t t1, t2, t3=0; - size_t i; - r += NWORDS; - for (i=0; i<NWORDS-2; i++) { + bn_t *ah = a + NWORDS; + bn_t *al = a + 2*NWORDS; + bn_t t0 = (*(a+1) >> 18) + (*ah >> 9); + bn_t t1, t2, t3=0; + size_t i; + r += NWORDS; + for (i=0; i<NWORDS-2; i++) { + t1 = *(--ah) << 55; + t2 = *ah >> 9; + asm("addc %3,%7,%5\n" //t3 = *(--al) + t0; + "addze %2,%6\n" //t2 += ca; + "addc %0,%4,%8\n" //*(--r) = t3 + t1; + "addze %1,%6" //t0 = t2 + ca; + : "=r" (*(--r)), "=r" (t0), "=r" (t2), "=r" (t3) + : "3" (t3), "1" (t0), "2" (t2), "r" (*(--al)), "r" (t1) + ); + } t1 = *(--ah) << 55; - t2 = *ah >> 9; - asm("addc %3,%7,%5\n" //t3 = *(--al) + t0; - "addze %2,%6\n" //t2 += ca; - "addc %0,%4,%8\n" //*(--r) = t3 + t1; - "addze %1,%6" //t0 = t2 + ca; + t2 = (*ah >> 9)&BN_PRIME_MSW_MASK; + asm("addc %3,%7,%5\n" //t3 = *(--al) + t0; + "addze %2,%6\n" //t2 += ca; + "addc %0,%4,%8\n" //*(--r) = t3 + t1; + "addze %1,%6" //t0 = t2 + ca; : "=r" (*(--r)), "=r" (t0), "=r" (t2), "=r" (t3) : "3" (t3), "1" (t0), "2" (t2), "r" (*(--al)), "r" (t1) ); - } - t1 = *(--ah) << 55; - t2 = (*ah >> 9)&BN_PRIME_MSW_MASK; - asm("addc %3,%7,%5\n" //t3 = *(--al) + t0; - "addze %2,%6\n" //t2 += ca; - "addc %0,%4,%8\n" //*(--r) = t3 + t1; - "addze %1,%6" //t0 = t2 + ca; - : "=r" (*(--r)), "=r" (t0), "=r" (t2), "=r" (t3) - : "3" (t3), "1" (t0), "2" (t2), "r" (*(--al)), "r" (t1) - ); - *(--r) = (*(--al)&BN_PRIME_MSW_MASK) + t0; + *(--r) = (*(--al)&BN_PRIME_MSW_MASK) + t0; } static void __attribute__((noinline)) bn_modred_slow (bn_t *r) { - size_t i; - if (*r > BN_PRIME_MSW_MASK) { - bn_t t0 = *r >> 9; - *r &= BN_PRIME_MSW_MASK; - r += NWORDS; - asm("addc %0,%1,%2" - : "=r" (*r) - : "0" (*(--r)), "r" (t0) - ); - for (i=0; i<NWORDS-1; i++) { - asm("addze %0,%1" - : "=r" (*r) - : "0" (*(--r)) - ); + size_t i; + if (*r > BN_PRIME_MSW_MASK) + { + bn_t t0 = *r >> 9; + *r &= BN_PRIME_MSW_MASK; + r += NWORDS; + asm("addc %0,%1,%2" + : "=r" (*r) + : "0" (*(--r)), "r" (t0) + ); + for (i=0; i<NWORDS-1; i++) + { + asm("addze %0,%1" + : "=r" (*r) + : "0" (*(--r)) + ); + } + } + if (bn_ge_prime(r)) + { + bn_sub(r, consts_p()->ec_prime); } - } - if (bn_ge_prime(r)) - bn_sub(r, consts_p()->ec_prime); } #endif - static void bn_modmul_prime (bn_t *a, const bn_t *b) { - bn_t prod[ NWORDS+NWORDS ]; + bn_t prod[ NWORDS+NWORDS ]; - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != b); + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != b); - bn_mul(prod, a, b); + bn_mul(prod, a, b); #ifdef EC_POWER64_RED - bn_modred_fast(a, prod); // accepts upto 46 extra bits => outputs at most 1 extra bit (522) + bn_modred_fast(a, prod); // accepts upto 46 extra bits => outputs at most 1 extra bit (522) #else - bn_modred_p521(a, prod); + bn_modred_p521(a, prod); #endif } @@ -744,24 +738,22 @@ static void bn_modmul_prime (bn_t *a, const bn_t *b) static void bn_modsqr_prime (bn_t *a) { #ifdef BN_POWER64_SQR - bn_t prod[ NWORDS+NWORDS ]; + bn_t prod[ NWORDS+NWORDS ]; - EC_ASSERT(NULL != a); + EC_ASSERT(NULL != a); - bn_sqr(prod, a); + bn_sqr(prod, a); #ifdef EC_POWER64_RED - bn_modred_fast(a, prod); // accepts upto 46 extra bits => outputs at most 1 extra bit (522) + bn_modred_fast(a, prod); // accepts upto 46 extra bits => outputs at most 1 extra bit (522) #else - bn_modred_p521(a, prod); + bn_modred_p521(a, prod); #endif #else - bn_modmul_prime(a, a); + bn_modmul_prime(a, a); #endif } #endif - - // mod reduce 2*NWORDS to NWORDS through approximate division // // input (a,2*NWORDS) <= N^2 -2*N +1 @@ -780,88 +772,91 @@ static void bn_modsqr_prime (bn_t *a) // static void bn_modred_p521_order (bn_t *r, const bn_t *a) { - bn_t dbl[ NWORDS+NWORDS ]; + bn_t dbl[ NWORDS+NWORDS ]; - EC_ASSERT(NULL != r); - EC_ASSERT(NULL != a); - EC_ASSERT((const bn_t *) r != a); -// XXX full overlap check + EC_ASSERT(NULL != r); + EC_ASSERT(NULL != a); + EC_ASSERT((const bn_t *) r != a); + // XXX full overlap check - // P521: product is 1042 bits, MSW of double-width bignum always 0 - // - EC_ASSERT(0 == a[0]); + // P521: product is 1042 bits, MSW of double-width bignum always 0 + // + EC_ASSERT(0 == a[0]); - BN_COPY(r, a); - bn_shl(r, a[NWORDS]); + BN_COPY(r, a); + bn_shl(r, a[NWORDS]); - bn_mul(dbl, r, consts_p()->ec_order_qn); - bn_shl(dbl, dbl[NWORDS]); // MS 521 bits of product - bn_add(r, dbl); + bn_mul(dbl, r, consts_p()->ec_order_qn); + bn_shl(dbl, dbl[NWORDS]); // MS 521 bits of product + bn_add(r, dbl); - bn_mul(dbl, r, consts_p()->ec_order); // N * floor(A / N) - EC_ASSERT(bn_cmp(dbl, a) <= 0); - EC_ASSERT(bn_cmp(dbl+NWORDS, a+NWORDS) <= 0); + bn_mul(dbl, r, consts_p()->ec_order); // N * floor(A / N) + EC_ASSERT(bn_cmp(dbl, a) <= 0); + EC_ASSERT(bn_cmp(dbl+NWORDS, a+NWORDS) <= 0); - BN_COPY(r, a+NWORDS); - bn_sub(r, dbl+NWORDS); // A - (N * floor(A/N)) + BN_COPY(r, a+NWORDS); + bn_sub(r, dbl+NWORDS); // A - (N * floor(A/N)) - if (bn_cmp(r, consts_p()->ec_order) >= 0) - bn_sub(r, consts_p()->ec_order); + if (bn_cmp(r, consts_p()->ec_order) >= 0) + { + bn_sub(r, consts_p()->ec_order); + } - if (bn_cmp(r, consts_p()->ec_order) >= 0) - bn_sub(r, consts_p()->ec_order); // XXX can this still be 2+ over? + if (bn_cmp(r, consts_p()->ec_order) >= 0) + { + bn_sub(r, consts_p()->ec_order); // XXX can this still be 2+ over? + } - EC_ASSERT(bn_cmp(r, consts_p()->ec_order) < 0); + EC_ASSERT(bn_cmp(r, consts_p()->ec_order) < 0); } static void bn_modmul_order (bn_t *a, const bn_t *b) { - bn_t prod[ NWORDS+NWORDS ]; + bn_t prod[ NWORDS+NWORDS ]; - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != b); + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != b); - bn_mul(prod, a, b); - bn_modred_p521_order(a, prod); + bn_mul(prod, a, b); + bn_modred_p521_order(a, prod); } -//------------------------------------- // negative,0,positive for a<b, a==b, a>b // #if defined(__BIG_ENDIAN) && !defined(BN_POWER64_CMP) static int bn_cmp (const bn_t *a, const bn_t *b) { - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != b); + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != b); - return memcmp(a, b, sizeof(bn_t)*NWORDS); + return memcmp(a, b, sizeof(bn_t)*NWORDS); } -#else /* defined(__BIG_ENDIAN) */ +#else /* defined(__BIG_ENDIAN) */ static int __attribute__((noinline)) bn_cmp (const bn_t *a, const bn_t *b) { - bnindex_t i; + bnindex_t i; - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != b); + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != b); - for (i=0; i<NWORDS; ++i) { - if (a[i] != b[i]) - return 1 - ((a[i] < b[i]) <<1); - } + for (i=0; i<NWORDS; ++i) + { + if (a[i] != b[i]) + { + return 1 - ((a[i] < b[i]) <<1); + } + } - return 0; + return 0; } #endif /* defined(__BIG_ENDIAN) */ - - -//------------------------------------- //removed: //static const bn_t bn_zero[ NWORDS ]; @@ -869,366 +864,368 @@ static int __attribute__((noinline)) bn_cmp (const bn_t *a, const bn_t *b) // static int bn_is_zero (const bn_t *m, unsigned int mn) { - EC_ASSERT(NULL != m); - EC_ASSERT(mn < NWORDS); + EC_ASSERT(NULL != m); + EC_ASSERT(mn < NWORDS); - const unsigned char *p2 = (const unsigned char *) m; - size_t n=sizeof(bn_t)*(NWORDS-mn); + const unsigned char *p2 = (const unsigned char *) m; + size_t n=sizeof(bn_t)*(NWORDS-mn); - while (n-- > 0) { - if (0 != *p2) - return !(0 - *p2); - p2 += 1; - } - - return !0; + while (n-- > 0) + { + if (0 != *p2) + { + return !(0 - *p2); + } + p2 += 1; + } -// replaces: -// return !memcmp(bn_zero, m, sizeof(bn_t)*(NWORDS-mn)); + return !0; } -//------------------------------------- static void __attribute__((noinline)) bn_add (bn_t *a, const bn_t *b) { - bn_t aw, cf = 0; /* aw: copy of current word to allow a==b */ - bnindex_t i = NWORDS; + bn_t aw, cf = 0; /* aw: copy of current word to allow a==b */ + bnindex_t i = NWORDS; - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != b); + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != b); - a += NWORDS-1; - b += NWORDS-1; + a += NWORDS-1; + b += NWORDS-1; - while (0 < i--) { - aw = *a; - if (cf) - cf = (0 == ++aw); - - aw += *b; - cf |= (aw < *(b--)); - *(a--) = aw; - } + while (0 < i--) + { + aw = *a; + if (cf) + { + cf = (0 == ++aw); + } + aw += *b; + cf |= (aw < *(b--)); + *(a--) = aw; + } } -//------------------------------------- // a,b < prime // never with order as base // static void bn_modadd (bn_t *a, const bn_t *b) { - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != b); - //EC_ASSERT(!bn_ge_prime(a)); - //EC_ASSERT(!bn_ge_prime(b)); + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != b); + //EC_ASSERT(!bn_ge_prime(a)); + //EC_ASSERT(!bn_ge_prime(b)); - bn_add(a, b); // P521: can not generate carry (unused MSW bits) - // other curves need to handle this carry + bn_add(a, b); // P521: can not generate carry (unused MSW bits) + // other curves need to handle this carry #ifndef EC_POWER64_RED - if (bn_ge_prime(a)) - bn_sub(a, consts_p()->ec_prime); + if (bn_ge_prime(a)) + { + bn_sub(a, consts_p()->ec_prime); + } #endif } -//------------------------------------- // never with order as base static bn_t bn_sub (bn_t *a, const bn_t *b) { - bnindex_t i = NWORDS; - bn_t bw, cf = 0; - - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != b); - - a += NWORDS-1; - b += NWORDS-1; - - while (0 < i--) { - if (cf) - cf = (0 == (*a)--); - - bw = *b; - cf |= (*a < *(b--)); - *(a--) -= bw; - } + bnindex_t i = NWORDS; + bn_t bw, cf = 0; + + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != b); + + a += NWORDS-1; + b += NWORDS-1; + + while (0 < i--) { + if (cf) + { + cf = (0 == (*a)--); + } + bw = *b; + cf |= (*a < *(b--)); + *(a--) -= bw; + } - return cf; + return cf; } - -//------------------------------------- // never modular-subtracting with ec_order[], only with ec_prime[] // therefore, implicit modulus // static void bn_modsub (bn_t *a, const bn_t *b) { - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != b); - //EC_ASSERT(!bn_ge_prime(a)); - EC_ASSERT(!bn_ge_prime(b)); + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != b); + EC_ASSERT(!bn_ge_prime(b)); - if (bn_sub(a, b)) - bn_add(a, consts_p()->ec_prime); + if (bn_sub(a, b)) + { + bn_add(a, consts_p()->ec_prime); + } } - - -//------------------------------------- // only rn LS words are touched // static void bn_shl_n (bn_t r[NWORDS], unsigned int rn, unsigned int bits) { - bn_t cf = 0, cfin; + bn_t cf = 0, cfin; - EC_DEVASSERT(NULL != r); - EC_ASSERT(rn <= NWORDS); + EC_DEVASSERT(NULL != r); + EC_ASSERT(rn <= NWORDS); - r += NWORDS-rn; + r += NWORDS-rn; - if (bits >= BN_BITS) { // unlikely, most modinv shift is <5 bits - cfin = bits / BN_BITS; // whole words + if (bits >= BN_BITS) // unlikely, most modinv shift is <5 bits + { + cfin = bits / BN_BITS; // whole words - memmove(r, r+cfin, (NWORDS-cfin)*sizeof(bn_t)); + memmove(r, r+cfin, (NWORDS-cfin)*sizeof(bn_t)); #ifndef BN_POWER64_CLR - memset(r+NWORDS-cfin, 0, cfin*sizeof(bn_t)); + memset(r+NWORDS-cfin, 0, cfin*sizeof(bn_t)); #else - bn_clr(r+NWORDS-cfin, cfin); + bn_clr(r+NWORDS-cfin, cfin); #endif - bits %= BN_BITS; - } + bits %= BN_BITS; + } - if (bits) { - r += rn-1; + if (bits) + { + r += rn-1; + while (0<rn--) + { + cfin = cf; + cf = (*r >> (BN_BITS - bits)); + *r <<= bits; + *r |= cfin; + --r; + } + } +} - while (0<rn--) { - cfin = cf; - cf = (*r >> (BN_BITS - bits)); +static unsigned int bn_bits (const bn_t *a) +{ + unsigned int full = 8*BNBYTES; + bnindex_t i; + bn_t an; - *r <<= bits; - *r |= cfin; - --r; - } - } + for (i=0; i<NWORDS; ++i) + { + full -= BN_BITS; + an = a[i]; + + if (!an) + { + continue; + } + + while (an > 0xff) + { + full += 8; + an >>= 8; + } + + while (an) + { + ++full; + an >>= 1; + } + return full; + } + return 0; } +// XXX route to bnt_msbit +// +#define bn_is_negative(p) (0x1000 & (*(p))) - -static unsigned int bn_bits (const bn_t *a) +// inv stores S during run +// +static int bn_modinv(bn_t *inv, const bn_t *a, const bn_t *n) { - unsigned int full = 8*BNBYTES; - bnindex_t i; - bn_t an; + bn_t r[ NWORDS ], s[ NWORDS ], u[ NWORDS ], v[ NWORDS ], + ss[ NWORDS ], vs[ NWORDS ]; // shifted S,V + unsigned int shl, ub, vb; // shift amount; bitcount + bn_t *pr = r, *ps = s, *pu = u, *pv = v, *pt; - for (i=0; i<NWORDS; ++i) { - full -= BN_BITS; - an = a[i]; + EC_ASSERT(NULL != inv); + EC_ASSERT(NULL != a); + EC_ASSERT(NULL != n); + EC_ASSERT(bn_cmp(a,n) < 0); + EC_ASSERT(!bn_is_zero(a,0)); - if (!an) - continue; + bn_clear(r); + bn_clear(s); + BN_LSW(s) = 1; - while (an > 0xff) { - full += 8; - an >>= 8; - } + BN_COPY(u, n); + BN_COPY(v, a); - while (an) { - ++full; - an >>= 1; - } + // ub = bn_bits(u); + ub = EC_PRIMEBITS; // P521: only ec_prime or ec_order possible + vb = bn_bits(v); - return full; - } + while (1 < vb) + { + EC_ASSERT(ub >= vb); + shl = ub-vb; + + BN_COPY(vs, pv); + BN_COPY(ss, ps); + if (shl) + { + bn_shl_n(vs, NWORDS, shl); + bn_shl_n(ss, NWORDS, shl); + } + + if (bn_is_negative(pv) == bn_is_negative(pu)) + { + bn_sub(pu, vs); + bn_sub(pr, ss); + } + else + { + bn_add(pu, vs); + bn_add(pr, ss); + } + + if (bn_is_negative(pu)) + { + bn_clear(ss); + bn_sub(ss, pu); + ub = bn_bits(ss); + } + else + { + ub = bn_bits(pu); + } + + if (ub < vb) + { + shl = ub; // shl,ss used as swap-scratch + ub = vb; + vb = shl; + + pt = pu; + pu = pv; + pv = pt; + + pt = ps; + ps = pr; + pr = pt; + } + } - return 0; -} + if (bn_is_negative(pv)) + { + BN_COPY(ss, ps); + bn_clear(ps); + bn_sub(ps, ss); + } + if (bn_is_negative(ps)) + { + bn_add(ps, n); + } -// XXX route to bnt_msbit -// -#define bn_is_negative(p) (0x1000 & (*(p))) + if (bn_cmp(ps, n) >= 0) + { + bn_sub(ps, n); + } + BN_COPY(inv, ps); -// inv stores S during run -// -static int bn_modinv(bn_t *inv, const bn_t *a, const bn_t *n) -{ - bn_t r[ NWORDS ], s[ NWORDS ], u[ NWORDS ], v[ NWORDS ], - ss[ NWORDS ], vs[ NWORDS ]; // shifted S,V - unsigned int shl, ub, vb; // shift amount; bitcount - bn_t *pr = r, *ps = s, *pu = u, *pv = v, *pt; - - EC_ASSERT(NULL != inv); - EC_ASSERT(NULL != a); - EC_ASSERT(NULL != n); - EC_ASSERT(bn_cmp(a,n) < 0); - EC_ASSERT(!bn_is_zero(a,0)); - - // [1, a] - // [0, n] - - bn_clear(r); - bn_clear(s); - BN_LSW(s) = 1; - - BN_COPY(u, n); - BN_COPY(v, a); - -// bn_print("U ", u); -// bn_print("V ", v); - // ub = bn_bits(u); - ub = EC_PRIMEBITS; // P521: only ec_prime or ec_order possible - vb = bn_bits(v); -// printf("%d,%d\n", (int) ub, (int) vb); - - while (1 < vb) { - EC_ASSERT(ub >= vb); - shl = ub-vb; -// printf("< %d\n", shl); - - BN_COPY(vs, pv); - BN_COPY(ss, ps); - if (shl) { - bn_shl_n(vs, NWORDS, shl); - bn_shl_n(ss, NWORDS, shl); - } - - if (bn_is_negative(pv) == bn_is_negative(pu)) { - bn_sub(pu, vs); - bn_sub(pr, ss); - } else { - bn_add(pu, vs); - bn_add(pr, ss); - } - -// bn_print("u ", pu); -// bn_print("r ", pr); - if (bn_is_negative(pu)) { - bn_clear(ss); - bn_sub(ss, pu); - ub = bn_bits(ss); - } else { - ub = bn_bits(pu); - } - - if (ub < vb) { - shl = ub; // shl,ss used as swap-scratch - ub = vb; - vb = shl; - - pt = pu; - pu = pv; - pv = pt; - - pt = ps; - ps = pr; - pr = pt; - } -// printf("\n"); - } - - if (bn_is_negative(pv)) { - BN_COPY(ss, ps); - bn_clear(ps); - bn_sub(ps, ss); - } - - if (bn_is_negative(ps)) - bn_add(ps, n); - - if (bn_cmp(ps, n) >= 0) - bn_sub(ps, n); - BN_COPY(inv, ps); - - return 1; + return 1; } - -//------------------------------------- #if defined(__BIG_ENDIAN) - static void bn_read_pt(bn_t *r, const unsigned char *data) { - EC_ASSERT(NULL != r); - EC_ASSERT(NULL != data); + EC_ASSERT(NULL != r); + EC_ASSERT(NULL != data); - r[0] = 0; - memmove(((unsigned char *) r) +BNBYTES-EC_PRIMEBYTES, - data, EC_PRIMEBYTES); + r[0] = 0; + memmove(((unsigned char *) r) +BNBYTES-EC_PRIMEBYTES, + data, EC_PRIMEBYTES); } - // P521: hash does not have unused MS words // static void bn_read_hash(bn_t *r, const unsigned char *data) { - EC_ASSERT(NULL != r); - EC_ASSERT(NULL != data); + EC_ASSERT(NULL != r); + EC_ASSERT(NULL != data); - r[0] = 0; - memmove(((unsigned char *) r) +BNBYTES-EC_HASHBYTES, - data, EC_HASHBYTES); + r[0] = 0; + memmove(((unsigned char *) r) +BNBYTES-EC_HASHBYTES, + data, EC_HASHBYTES); } - #else static void bn_read(bn_t *r, const unsigned char *data, size_t dlen) { - bnindex_t i, whole = dlen / sizeof(bn_t), - rem = dlen % sizeof(bn_t); - bn_t acc = 0; + bnindex_t i, whole = dlen / sizeof(bn_t), + rem = dlen % sizeof(bn_t); + bn_t acc = 0; - EC_ASSERT(NULL != r); - EC_ASSERT(NULL != data); - EC_ASSERT(dlen <= EC_PRIMEBYTES); + EC_ASSERT(NULL != r); + EC_ASSERT(NULL != data); + EC_ASSERT(dlen <= EC_PRIMEBYTES); - acc = whole + (!!rem); - if (acc < NWORDS) { // unused MS words - acc = NWORDS - acc; + acc = whole + (!!rem); + if (acc < NWORDS) // unused MS words + { + acc = NWORDS - acc; #ifndef BN_POWER64_CLR - memset(r, 0, acc*sizeof(bn_t)); + memset(r, 0, acc*sizeof(bn_t)); #else - bn_clr(r, acc); + bn_clr(r, acc); #endif - r += acc; - } - - acc = 0; - if (rem) { - ++whole; - } else { - rem = sizeof(bn_t); - } - - while (0 < whole--) { - for (i=0; i<rem; ++i) - acc = (acc <<8) + *(data++); - *(r++) = acc; - acc = 0; - rem = sizeof(bn_t); - } -} + r += acc; + } + + acc = 0; + if (rem) + { + ++whole; + } + else + { + rem = sizeof(bn_t); + } + while (0 < whole--) + { + for (i=0; i<rem; ++i) + { + acc = (acc <<8) + *(data++); + } + *(r++) = acc; + acc = 0; + rem = sizeof(bn_t); + } +} static void bn_read_pt(bn_t *r, const unsigned char *data) { - return bn_read(r, data, EC_PRIMEBYTES); + return bn_read(r, data, EC_PRIMEBYTES); } - static void bn_read_hash(bn_t *r, const unsigned char *data) { - return bn_read(r, data, EC_HASHBYTES); + return bn_read(r, data, EC_HASHBYTES); } #endif /* defined(__BIG_ENDIAN) */ - //======================================================= EC primitives ==== /* (0,0) is our infinity, since it's not a curve point */ #define ec_is_infinity(px, py, pz) \ @@ -1236,178 +1233,175 @@ static void bn_read_hash(bn_t *r, const unsigned char *data) #define ec_set_infinity(p) bn_clear(p) - -//------------------------------------- // (x) is transformed back to affine from projective (X*Z) // static void ec_projective2affine (bn_t *x, const bn_t *z) { - bn_t zinv[ NWORDS ]; + bn_t zinv[ NWORDS ]; - EC_ASSERT(NULL != x); - EC_ASSERT(NULL != z); + EC_ASSERT(NULL != x); + EC_ASSERT(NULL != z); - EC_ASSERT(!bn_ge_prime(x)); - EC_ASSERT(!bn_ge_prime(z)); + EC_ASSERT(!bn_ge_prime(x)); + EC_ASSERT(!bn_ge_prime(z)); - bn_modinv(zinv, z, consts_p()->ec_prime); - bn_modmul_prime(x, zinv); + bn_modinv(zinv, z, consts_p()->ec_prime); + bn_modmul_prime(x, zinv); #ifdef EC_POWER64_RED - bn_modred_slow(x); + bn_modred_slow(x); #endif } - // returns 1 if result is at infinity, 0 otherwise // static int ec_add (bn_t *x1, bn_t *y1, bn_t *z1, const bn_t *x2, const bn_t *y2, const bn_t *z2) { - bn_t a[ NWORDS ], b[ NWORDS ], c[ NWORDS ], - bs[ NWORDS ], // B^2 - t1[ NWORDS ], t2[ NWORDS ]; // XXX minimize these - int inf1, inf2; - - EC_ASSERT(NULL != x1); - EC_ASSERT(NULL != y1); - EC_ASSERT(NULL != z1); - EC_ASSERT(NULL != x2); - EC_ASSERT(NULL != y2); - EC_ASSERT(NULL != z2); - EC_ASSERT(!bn_ge_prime(x1)); - EC_ASSERT(!bn_ge_prime(y1)); - EC_ASSERT(!bn_ge_prime(z1)); - EC_ASSERT(!bn_ge_prime(x2)); - EC_ASSERT(!bn_ge_prime(y2)); - EC_ASSERT(!bn_ge_prime(z2)); - - inf1 = ec_is_infinity(x1, y1, z1); - inf2 = ec_is_infinity(x2, y2, z2); - - if (inf2) - return inf1; - - if (inf1) { - BN_COPY(x1, x2); - BN_COPY(y1, y2); - BN_COPY(z1, z2); - return 0; // (x1,y1,z1) not infinity (checked above) - } - - if (!bn_cmp(x1, x2) && !bn_cmp(y1, y2)) - return ec_double(x1, y1, z1); + bn_t a[ NWORDS ], b[ NWORDS ], c[ NWORDS ], + bs[ NWORDS ], // B^2 + t1[ NWORDS ], t2[ NWORDS ]; // XXX minimize these + int inf1, inf2; + + EC_ASSERT(NULL != x1); + EC_ASSERT(NULL != y1); + EC_ASSERT(NULL != z1); + EC_ASSERT(NULL != x2); + EC_ASSERT(NULL != y2); + EC_ASSERT(NULL != z2); + EC_ASSERT(!bn_ge_prime(x1)); + EC_ASSERT(!bn_ge_prime(y1)); + EC_ASSERT(!bn_ge_prime(z1)); + EC_ASSERT(!bn_ge_prime(x2)); + EC_ASSERT(!bn_ge_prime(y2)); + EC_ASSERT(!bn_ge_prime(z2)); + + inf1 = ec_is_infinity(x1, y1, z1); + inf2 = ec_is_infinity(x2, y2, z2); + + if (inf2) + { + return inf1; + } + + if (inf1) + { + BN_COPY(x1, x2); + BN_COPY(y1, y2); + BN_COPY(z1, z2); + return 0; // (x1,y1,z1) not infinity (checked above) + } + + if (!bn_cmp(x1, x2) && !bn_cmp(y1, y2)) + { + return ec_double(x1, y1, z1); + } #ifdef EC_POWER64_ALG - BN_COPY(t1, y1); - bn_modmul_prime(t1, z2); // t1 = y1 * z2 - BN_COPY(a, y2); - bn_modmul_prime(a, z1); // A = y2 * z1 - y1 * z2 + BN_COPY(t1, y1); + bn_modmul_prime(t1, z2); // t1 = y1 * z2 + BN_COPY(a, y2); + bn_modmul_prime(a, z1); // A = y2 * z1 - y1 * z2 #ifdef EC_POWER64_RED - bn_modred_slow(t1); + bn_modred_slow(t1); #endif - bn_modsub(a, t1); - - bn_modmul_prime(x1, z2); // x1 := x1 * z2 orig x1 no longer used - BN_COPY(b, x2); - bn_modmul_prime(b, z1); + bn_modsub(a, t1); + bn_modmul_prime(x1, z2); // x1 := x1 * z2 orig x1 no longer used + BN_COPY(b, x2); + bn_modmul_prime(b, z1); #ifdef EC_POWER64_RED - bn_modred_slow(x1); + bn_modred_slow(x1); #endif - bn_modsub(b, x1); // B = x2 * z1 - x1 * z2 + bn_modsub(b, x1); // B = x2 * z1 - x1 * z2 - BN_COPY(bs, b); - bn_modsqr_prime(bs); // B^2 + BN_COPY(bs, b); + bn_modsqr_prime(bs); // B^2 - BN_COPY(c, a); - bn_modsqr_prime(c); - bn_modmul_prime(z1, z2); // z1 = z1 * z2 - bn_modmul_prime(c, z1); // c = A^2 * z1 * z2 + BN_COPY(c, a); + bn_modsqr_prime(c); + bn_modmul_prime(z1, z2); // z1 = z1 * z2 + bn_modmul_prime(c, z1); // c = A^2 * z1 * z2 - bn_modmul_prime(x1, bs); // x1 = B^2 * x1 * z2 - BN_COPY(t2, b); - bn_modmul_prime(t2, bs); // t2 = B^3 + bn_modmul_prime(x1, bs); // x1 = B^2 * x1 * z2 + BN_COPY(t2, b); + bn_modmul_prime(t2, bs); // t2 = B^3 #ifdef EC_POWER64_RED - bn_modred_slow(t2); - bn_modred_slow(x1); + bn_modred_slow(t2); + bn_modred_slow(x1); #endif - bn_modsub(c, t2); - bn_modsub(c, x1); // C = A^2 * z1 * z2 - B^3 - bn_modsub(c, x1); // - 2 B^2 * x1 * z1 + bn_modsub(c, t2); + bn_modsub(c, x1); // C = A^2 * z1 * z2 - B^3 + bn_modsub(c, x1); // - 2 B^2 * x1 * z1 - bn_modmul_prime(z1, t2); // z1 * z2 * B^3 + bn_modmul_prime(z1, t2); // z1 * z2 * B^3 #ifdef EC_POWER64_RED - bn_modred_slow(z1); - bn_modred_slow(c); + bn_modred_slow(z1); + bn_modred_slow(c); #endif - bn_modmul_prime(t1, t2); // (B^3 * y1 * z2) - // A(B 2 X1 Z2 ? C) - bn_modsub(x1, c); - bn_modmul_prime(x1, a); // A * (B^2 * x1 * z2 - C) + bn_modmul_prime(t1, t2); // (B^3 * y1 * z2) + // A(B 2 X1 Z2 ? C) + bn_modsub(x1, c); + bn_modmul_prime(x1, a); // A * (B^2 * x1 * z2 - C) #ifdef EC_POWER64_RED - bn_modred_slow(x1); - bn_modred_slow(t1); + bn_modred_slow(x1); + bn_modred_slow(t1); #endif - bn_modsub(x1, t1); // Y = A * (B^2 * x1 * z2 - C) - (B^3 * y1 * z2) - BN_COPY(y1, x1); + bn_modsub(x1, t1); // Y = A * (B^2 * x1 * z2 - C) - (B^3 * y1 * z2) + BN_COPY(y1, x1); - BN_COPY(x1, b); - bn_modmul_prime(x1, c); // X = B * C + BN_COPY(x1, b); + bn_modmul_prime(x1, c); // X = B * C #ifdef EC_POWER64_RED - bn_modred_slow(x1); + bn_modred_slow(x1); #endif #else // !EC_POWER64_ALG - BN_COPY(t1, y1); - bn_modmul_prime(t1, z2); // t1 = y1 * z2 - BN_COPY(a, y2); - bn_modmul_prime(a, z1); // A = y2 * z1 - y1 * z2 - bn_modsub(a, t1); - - bn_modmul_prime(x1, z2); // x1 := x1 * z2 orig x1 no longer used - BN_COPY(b, x2); - bn_modmul_prime(b, z1); - bn_modsub(b, x1); // B = x2 * z1 - x1 * z2 - - BN_COPY(bs, b); - bn_modmul_prime(bs, bs); // B^2 - - BN_COPY(c, a); - bn_modmul_prime(c, c); - bn_modmul_prime(c, z1); - bn_modmul_prime(c, z2); - - BN_COPY(t2, b); - bn_modadd(t2, x1); - bn_modadd(t2, x1); - bn_modmul_prime(t2, bs); - bn_modsub(c, t2); // C = A^2 * z1 * z2 - B^3 - // - 2 B^2 * x1 * z1 - - bn_modmul_prime(z1, z2); - bn_modmul_prime(z1, b); - bn_modmul_prime(z1, bs); // z1 * z2 * B^3 - - bn_modmul_prime(t1, b); - bn_modmul_prime(t1, bs); // (B^3 * y1 * z2) - // A(B 2 X1 Z2 ? C) - bn_modmul_prime(x1, bs); // (B^2 * x1 * z2) - bn_modsub(x1, c); - bn_modmul_prime(x1, a); // A * (B^2 * x1 * z2 - C) - bn_modsub(x1, t1); - BN_COPY(y1, x1); // Y = - - BN_COPY(x1, b); - bn_modmul_prime(x1, c); // X = B * C + BN_COPY(t1, y1); + bn_modmul_prime(t1, z2); // t1 = y1 * z2 + BN_COPY(a, y2); + bn_modmul_prime(a, z1); // A = y2 * z1 - y1 * z2 + bn_modsub(a, t1); + + bn_modmul_prime(x1, z2); // x1 := x1 * z2 orig x1 no longer used + BN_COPY(b, x2); + bn_modmul_prime(b, z1); + bn_modsub(b, x1); // B = x2 * z1 - x1 * z2 + + BN_COPY(bs, b); + bn_modmul_prime(bs, bs); // B^2 + + BN_COPY(c, a); + bn_modmul_prime(c, c); + bn_modmul_prime(c, z1); + bn_modmul_prime(c, z2); + + BN_COPY(t2, b); + bn_modadd(t2, x1); + bn_modadd(t2, x1); + bn_modmul_prime(t2, bs); + bn_modsub(c, t2); // C = A^2 * z1 * z2 - B^3 + // - 2 B^2 * x1 * z1 + + bn_modmul_prime(z1, z2); + bn_modmul_prime(z1, b); + bn_modmul_prime(z1, bs); // z1 * z2 * B^3 + + bn_modmul_prime(t1, b); + bn_modmul_prime(t1, bs); // (B^3 * y1 * z2) + // A(B 2 X1 Z2 ? C) + bn_modmul_prime(x1, bs); // (B^2 * x1 * z2) + bn_modsub(x1, c); + bn_modmul_prime(x1, a); // A * (B^2 * x1 * z2 - C) + bn_modsub(x1, t1); + BN_COPY(y1, x1); // Y = + + BN_COPY(x1, b); + bn_modmul_prime(x1, c); // X = B * C #endif - return 0; + return 0; } - - - -//---------------------------------------------------------------------------- // (x,y,z) in projective coordinates // P521: curve has a==-3 // @@ -1415,137 +1409,136 @@ static int ec_add (bn_t *x1, bn_t *y1, bn_t *z1, // static int ec_double (bn_t *x, bn_t *y, bn_t *z) { - bn_t a[ NWORDS ], b[ NWORDS ], c[ NWORDS ], d[ NWORDS ], t[ NWORDS ]; + bn_t a[ NWORDS ], b[ NWORDS ], c[ NWORDS ], d[ NWORDS ], t[ NWORDS ]; - EC_ASSERT(NULL != x); - EC_ASSERT(NULL != y); - EC_ASSERT(NULL != z); - EC_ASSERT(!bn_ge_prime(x)); - EC_ASSERT(!bn_ge_prime(y)); - EC_ASSERT(!bn_ge_prime(z)); + EC_ASSERT(NULL != x); + EC_ASSERT(NULL != y); + EC_ASSERT(NULL != z); + EC_ASSERT(!bn_ge_prime(x)); + EC_ASSERT(!bn_ge_prime(y)); + EC_ASSERT(!bn_ge_prime(z)); #ifdef EC_POWER64_ALG - BN_COPY(a, x); - BN_COPY(d, x); - - bn_modadd(a, z); - bn_modsub(d, z); - bn_modmul_prime(a, d); // x^2 - z^2 - BN_COPY(d, a); - bn_modadd(a, a); - bn_modadd(a, d); // A = 3 * (x^2 - z^2) - // P521: generally, A = 3 * x^2 - a * z^2 - - BN_COPY(b, z); - bn_modmul_prime(b, y); // B = y * z - - BN_COPY(c, x); - bn_modmul_prime(y, b); // y = y * B - bn_modmul_prime(c, y); // C = x * y * B - - BN_COPY(z, b); - bn_modsqr_prime(z); - bn_modmul_prime(z, b); - bn_modadd(z, z); - bn_modadd(z, z); - bn_modadd(z, z); // Z = 8 * B^3 + BN_COPY(a, x); + BN_COPY(d, x); + + bn_modadd(a, z); + bn_modsub(d, z); + bn_modmul_prime(a, d); // x^2 - z^2 + BN_COPY(d, a); + bn_modadd(a, a); + bn_modadd(a, d); // A = 3 * (x^2 - z^2) + // P521: generally, A = 3 * x^2 - a * z^2 + + BN_COPY(b, z); + bn_modmul_prime(b, y); // B = y * z + + BN_COPY(c, x); + bn_modmul_prime(y, b); // y = y * B + bn_modmul_prime(c, y); // C = x * y * B + + BN_COPY(z, b); + bn_modsqr_prime(z); + bn_modmul_prime(z, b); + bn_modadd(z, z); + bn_modadd(z, z); + bn_modadd(z, z); // Z = 8 * B^3 #ifdef EC_POWER64_RED - bn_modred_slow(z); + bn_modred_slow(z); #endif - BN_COPY(t, c); - bn_modadd(t, t); - bn_modadd(t, t); - bn_modadd(t, t); - BN_COPY(d, a); - bn_modsqr_prime(d); + BN_COPY(t, c); + bn_modadd(t, t); + bn_modadd(t, t); + bn_modadd(t, t); + BN_COPY(d, a); + bn_modsqr_prime(d); #ifdef EC_POWER64_RED - bn_modred_slow(t); + bn_modred_slow(t); #endif - bn_modsub(d, t); // D = A^2 - 8*C + bn_modsub(d, t); // D = A^2 - 8*C - BN_COPY(x, b); - bn_modmul_prime(x, d); - bn_modadd(x, x); // X = 2 * B * D + BN_COPY(x, b); + bn_modmul_prime(x, d); + bn_modadd(x, x); // X = 2 * B * D #ifdef EC_POWER64_RED - bn_modred_slow(x); - bn_modred_slow(d); + bn_modred_slow(x); + bn_modred_slow(d); #endif - bn_modadd(c, c); - bn_modadd(c, c); - bn_modsub(c, d); - bn_modmul_prime(a, c); // (A * (4*C - D)) + bn_modadd(c, c); + bn_modadd(c, c); + bn_modsub(c, d); + bn_modmul_prime(a, c); // (A * (4*C - D)) - bn_modsqr_prime(y); // (y * B)^2 - bn_modadd(y, y); - bn_modadd(y, y); - bn_modadd(y, y); // (8 * y^2 * B^2) + bn_modsqr_prime(y); // (y * B)^2 + bn_modadd(y, y); + bn_modadd(y, y); + bn_modadd(y, y); // (8 * y^2 * B^2) #ifdef EC_POWER64_RED - bn_modred_slow(a); - bn_modred_slow(y); + bn_modred_slow(a); + bn_modred_slow(y); #endif - bn_modsub(a, y); - BN_COPY(y, a); // Y = A * (4*C - D) - 8 * y^2 * B^2 + bn_modsub(a, y); + BN_COPY(y, a); // Y = A * (4*C - D) - 8 * y^2 * B^2 #else // !EC_POWER64_ALG - BN_COPY(a, x); - BN_COPY(d, z); - - bn_modmul_prime(a, x); - bn_modmul_prime(d, z); - bn_modsub(a, d); - BN_COPY(d, a); - bn_modadd(a, a); - bn_modadd(a, d); // A = 3 * (x^2 - z^2) - // P521: generally, A = 3 * x^2 - a * z^2 - - BN_COPY(b, z); - bn_modmul_prime(b, y); // B = y * z - - BN_COPY(c, y); - bn_modmul_prime(c, b); - bn_modmul_prime(c, x); // C = x * y * B - - BN_COPY(z, b); - bn_modmul_prime(z, b); - bn_modmul_prime(z, b); - bn_modadd(z, z); - bn_modadd(z, z); - bn_modadd(z, z); // Z = 8 * B^3 - - BN_COPY(t, c); - bn_modadd(t, t); - bn_modadd(t, t); - bn_modadd(t, t); - BN_COPY(d, a); - bn_modmul_prime(d, a); - bn_modsub(d, t); // D = A^2 - 8*C - - BN_COPY(x, b); - bn_modmul_prime(x, d); - bn_modadd(x, x); // X = 2 * B * D - - bn_modadd(c, c); - bn_modadd(c, c); - bn_modsub(c, d); - bn_modmul_prime(a, c); // (A * (4*C - D)) - - bn_modmul_prime(y, b); - bn_modmul_prime(y, y); - bn_modadd(y, y); - bn_modadd(y, y); - bn_modadd(y, y); // (8 * y^2 * B^2) - bn_modsub(a, y); - BN_COPY(y, a); // Y = A * (4*C - D) - 8 * y^2 * B^2 + BN_COPY(a, x); + BN_COPY(d, z); + + bn_modmul_prime(a, x); + bn_modmul_prime(d, z); + bn_modsub(a, d); + BN_COPY(d, a); + bn_modadd(a, a); + bn_modadd(a, d); // A = 3 * (x^2 - z^2) + // P521: generally, A = 3 * x^2 - a * z^2 + + BN_COPY(b, z); + bn_modmul_prime(b, y); // B = y * z + + BN_COPY(c, y); + bn_modmul_prime(c, b); + bn_modmul_prime(c, x); // C = x * y * B + + BN_COPY(z, b); + bn_modmul_prime(z, b); + bn_modmul_prime(z, b); + bn_modadd(z, z); + bn_modadd(z, z); + bn_modadd(z, z); // Z = 8 * B^3 + + BN_COPY(t, c); + bn_modadd(t, t); + bn_modadd(t, t); + bn_modadd(t, t); + BN_COPY(d, a); + bn_modmul_prime(d, a); + bn_modsub(d, t); // D = A^2 - 8*C + + BN_COPY(x, b); + bn_modmul_prime(x, d); + bn_modadd(x, x); // X = 2 * B * D + + bn_modadd(c, c); + bn_modadd(c, c); + bn_modsub(c, d); + bn_modmul_prime(a, c); // (A * (4*C - D)) + + bn_modmul_prime(y, b); + bn_modmul_prime(y, y); + bn_modadd(y, y); + bn_modadd(y, y); + bn_modadd(y, y); // (8 * y^2 * B^2) + bn_modsub(a, y); + BN_COPY(y, a); // Y = A * (4*C - D) - 8 * y^2 * B^2 #endif - return 0; + return 0; } -//------------------------------------- // (x,y) in affine coordinates; z is output only // returns (x,y,z) in projective coordinates // @@ -1557,40 +1550,45 @@ static int ec_double (bn_t *x, bn_t *y, bn_t *z) // static int ec_multiply (bn_t *x, bn_t *y, bn_t *z, const bn_t *k) { - bn_t px[ NWORDS ], py[ NWORDS ], pz[ NWORDS ]; - unsigned int i; - bn_t mask = 1; - - EC_ASSERT(NULL != x); - EC_ASSERT(NULL != y); - EC_ASSERT(NULL != k); - EC_ASSERT(!bn_ge_prime(x)); - EC_ASSERT(!bn_ge_prime(y)); - - i=bn_bits(k); - k += NWORDS-1; - - BN_COPY(px, x); - BN_COPY(py, y); - bn_clear(x); - bn_clear(y); - - bn_clear(z); - BN_LSW(z) = 1; // (x,y) -> (x, y, 1) in projective coordinates - BN_COPY(pz, z); // (px,py) -> (px,py,1) - - BN_DUMP(i,x); - BN_DUMP(i,y); - BN_DUMP(i,z); - BN_DUMP(i,px); - BN_DUMP(i,py); - BN_DUMP(i,pz); - while (0 < i--) { - if (mask & *k) - ec_add(x, y, z, px, py, pz); + bn_t px[ NWORDS ], py[ NWORDS ], pz[ NWORDS ]; + unsigned int i; + bn_t mask = 1; + + EC_ASSERT(NULL != x); + EC_ASSERT(NULL != y); + EC_ASSERT(NULL != k); + EC_ASSERT(!bn_ge_prime(x)); + EC_ASSERT(!bn_ge_prime(y)); + + i=bn_bits(k); + k += NWORDS-1; + + BN_COPY(px, x); + BN_COPY(py, y); + bn_clear(x); + bn_clear(y); + + bn_clear(z); + BN_LSW(z) = 1; // (x,y) -> (x, y, 1) in projective coordinates + BN_COPY(pz, z); // (px,py) -> (px,py,1) + + BN_DUMP(i,x); + BN_DUMP(i,y); + BN_DUMP(i,z); + BN_DUMP(i,px); + BN_DUMP(i,py); + BN_DUMP(i,pz); + while (0 < i--) + { + if (mask & *k) + { + ec_add(x, y, z, px, py, pz); + } - if (0 < i) - ec_double(px, py, pz); + if (0 < i) + { + ec_double(px, py, pz); + } BN_DUMP(i,x); BN_DUMP(i,y); @@ -1598,15 +1596,16 @@ static int ec_multiply (bn_t *x, bn_t *y, bn_t *z, const bn_t *k) BN_DUMP(i,px); BN_DUMP(i,py); BN_DUMP(i,pz); - mask <<= 1; - if (!mask) { - --k; - mask = 1; - } - } + mask <<= 1; + if (!mask) + { + --k; + mask = 1; + } + } BN_EXIT(); - return 0; + return 0; } @@ -1616,47 +1615,57 @@ int ec_verify (const unsigned char *publicpt, /* 2*EC_COORDBYTES */ const unsigned char *hash, /* EC_HASHBYTES */ const unsigned char *signature) /* 2*EC_COORDBYTES */ { - bn_t r[ NWORDS ], s[ NWORDS ], e[ NWORDS ], - px[ NWORDS ], py[ NWORDS ], pz[ NWORDS ], - u1[ NWORDS ], u2[ NWORDS ]; + bn_t r[ NWORDS ], s[ NWORDS ], e[ NWORDS ], + px[ NWORDS ], py[ NWORDS ], pz[ NWORDS ], + u1[ NWORDS ], u2[ NWORDS ]; - if ((NULL == publicpt) || (NULL == signature) || (NULL == hash)) - return -1; + if ((NULL == publicpt) || (NULL == signature) || (NULL == hash)) + { + return -1; + } - bn_read_pt (r, signature); - bn_read_pt (s, signature +EC_COORDBYTES); - bn_read_hash(e, hash); - bn_read_pt (px, publicpt); - bn_read_pt (py, publicpt +EC_COORDBYTES); + bn_read_pt (r, signature); + bn_read_pt (s, signature +EC_COORDBYTES); + bn_read_hash(e, hash); + bn_read_pt (px, publicpt); + bn_read_pt (py, publicpt +EC_COORDBYTES); - if (bn_ge_order(r) || bn_ge_order(s) || - bn_is_zero(s,0) || bn_is_zero(r,0)) - return 0; // assume user messed with signature + if (bn_ge_order(r) || bn_ge_order(s) || + bn_is_zero(s,0) || bn_is_zero(r,0)) + { + return 0; // assume user messed with signature + } - if (bn_ge_prime(px) || bn_ge_prime(py) || - bn_is_zero(px,0) || bn_is_zero(py,0)) - return -1; // admin fault; should not happen + if (bn_ge_prime(px) || bn_ge_prime(py) || + bn_is_zero(px,0) || bn_is_zero(py,0)) + { + return -1; // admin fault; should not happen + } - bn_modinv(u1, s, consts_p()->ec_order); // s no longer needed (NLN) - BN_COPY(u2, r); - bn_modmul_order(u2, u1); - bn_modmul_order(u1, e); // e NLN + bn_modinv(u1, s, consts_p()->ec_order); // s no longer needed (NLN) + BN_COPY(u2, r); + bn_modmul_order(u2, u1); + bn_modmul_order(u1, e); // e NLN - // reuse (e,s) for base multiplication - BN_COPY(e, consts_p()->prime_px); // (e,s) <- (base point) - BN_COPY(s, consts_p()->prime_py); + // reuse (e,s) for base multiplication + BN_COPY(e, consts_p()->prime_px); // (e,s) <- (base point) + BN_COPY(s, consts_p()->prime_py); - ec_multiply(px, py, pz, u2); // (px,py,pz) = u2 * (px,py); u2 NLN - ec_multiply(e, s, u2, u1); // (s, e, u2) = u1 * (gx,gy); u1 NLN + ec_multiply(px, py, pz, u2); // (px,py,pz) = u2 * (px,py); u2 NLN + ec_multiply(e, s, u2, u1); // (s, e, u2) = u1 * (gx,gy); u1 NLN - if (ec_add(px, py, pz, e, s, u2)) // u1 * base + u2 * public - return 0; // reached infinity (SNH with sig) + if (ec_add(px, py, pz, e, s, u2)) // u1 * base + u2 * public + { + return 0; // reached infinity (SNH with sig) + } - ec_projective2affine(px, pz); + ec_projective2affine(px, pz); - if (bn_ge_order(px)) - bn_sub(px, consts_p()->ec_order); // px mod order + if (bn_ge_order(px)) + { + bn_sub(px, consts_p()->ec_order); // px mod order + } - return (! bn_cmp(r, px)); + return (! bn_cmp(r, px)); } diff --git a/src/securerom/hw_utils.C b/src/securerom/hw_utils.C index 19d4ee947..7adcb35a8 100644 --- a/src/securerom/hw_utils.C +++ b/src/securerom/hw_utils.C @@ -22,13 +22,9 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -/**************************************************************************** - * - ****************************************************************************/ -#include <hw_utils.h> -#include <status_codes.h> -/****************************************************************************/ +#include <securerom/hw_utils.H> +#include <securerom/status_codes.H> #ifdef EMULATE_HW @@ -36,187 +32,187 @@ #include <unistd.h> #include <sys/mman.h> #include <limits.h> -#include <stdint.h> /* uint_fast8_t, uintN_t */ -#include <inttypes.h> +#include <stdint.h> /* uint_fast8_t, uintN_t */ +#include "inttypes.H" hw_settings HW; -/****************************************************************************/ -void HW_Init (void) { - /* Open the file that will be used to fill the memory contents of the mmap */ - HW.mfd = open ("/dev/zero", O_RDWR, 0); - if (HW.mfd < 0) { - printf ("HW_Init: can't create memory file"); - exit(1); - } +void HW_Init (void) +{ + // Open the file that will be used to fill the memory contents of the mmap + HW.mfd = open ("/dev/zero", O_RDWR, 0); + if (HW.mfd < 0) + { + printf ("HW_Init: can't create memory file"); + exit(1); + } /* Allocate Memory */ #ifdef HOST_64 - HW.data = (uint8_t*) mmap64 (0, TOTAL_TEST_MEMORY, - PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, HW.mfd, 0); + HW.data = (uint8_t*) mmap64 (0, TOTAL_TEST_MEMORY, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_PRIVATE, HW.mfd, 0); #else - HW.data = (uint8_t*) mmap (0, TOTAL_TEST_MEMORY, - PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, HW.mfd, 0); + HW.data = (uint8_t*) mmap (0, TOTAL_TEST_MEMORY, + PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, + HW.mfd, 0); #endif - if ((uint32_t) HW.data == -1) { - printf ("Unable to allocate HW Memory of size %d", TOTAL_TEST_MEMORY); - HW_Free(); - exit(1); - } - HW.memory = HW.data+0x1000-((uint32_t)HW.data&0xfff); + if ((uint32_t) HW.data == -1) + { + printf ("Unable to allocate HW Memory of size %d", TOTAL_TEST_MEMORY); + HW_Free(); + exit(1); + } + HW.memory = HW.data+0x1000-((uint32_t)HW.data&0xfff); } -/****************************************************************************/ void HW_Free (void) { - close (HW.mfd); + close (HW.mfd); } -/****************************************************************************/ void Log (uint64_t code) { - mtspr_SCRATCH2 (code); + mtspr_SCRATCH2 (code); +} + +void Check_Stop (const char* msg) +{ + printf ("CHECK STOP '%s'\n", msg); + printf ("SCRATCH3= 0x%08llX\n", mfspr_SCRATCH3()); + exit(FAIL); } -/****************************************************************************/ -void Check_Stop (char* msg) { - printf ("CHECK STOP '%s'\n", msg); - printf ("SCRATCH3= 0x%08llX\n", mfspr_SCRATCH3()); - exit(FAIL); +void Error_Stop (uint64_t code, const char* msg) +{ + mtspr_SCRATCH3 (ERROR_EVENT|code); + Check_Stop (msg); } -/****************************************************************************/ -void Error_Stop (uint64_t code, char* msg) { - mtspr_SCRATCH3 (ERROR_EVENT|code); - Check_Stop (msg); +void assem_DCBI (uint64_t addr) +{ + addr = physical_addr(addr)&CACHE_MASK; + memset(Convert_Mem_Addr(addr),0xff,CACHE_LINE); // destroys contents in model } -/****************************************************************************/ -void assem_DCBI (uint64_t addr) { - addr = physical_addr(addr)&CACHE_MASK; - memset(Convert_Mem_Addr(addr),0xff,CACHE_LINE); // destroys contents in model - } -/****************************************************************************/ void assem_DCBZ (uint64_t addr) { - addr = physical_addr(addr)&CACHE_MASK; - memset(Convert_Mem_Addr(addr),0,CACHE_LINE); + addr = physical_addr(addr)&CACHE_MASK; + memset(Convert_Mem_Addr(addr),0,CACHE_LINE); } -/****************************************************************************/ + void assem_DCBST (uint8_t* addr) {} -/****************************************************************************/ void assem_ICBI (uint64_t* addr) {} -/****************************************************************************/ void assem_SYNC (void) {} -/****************************************************************************/ void assem_ISYNC (void) {} -/****************************************************************************/ -void mtspr_HRMOR (uint64_t addr) { - HW.HRMOR = addr & HRMOR_MASK; -} - -/****************************************************************************/ -//uint64_t mfspr_HRMOR (void) { -// return HW.HRMOR; -//} - -/****************************************************************************/ - -/****************************************************************************/ -uint64_t getscom_FSP_BAR_value (uint64_t base) { - return HW.FSP_BAR.value; -} - -/****************************************************************************/ -uint64_t getscom_FSP_BAR_mask (uint64_t base) { - return HW.FSP_BAR.mask; +void mtspr_HRMOR (uint64_t addr) +{ + HW.HRMOR = addr & HRMOR_MASK; } -/****************************************************************************/ -void getscom_HW_ECID (uint64_t base, uint8_t* buf) { - memcpy(buf, HW.ECID, ECID_SIZE); +uint64_t getscom_FSP_BAR_value (uint64_t base) +{ + return HW.FSP_BAR.value; } -/****************************************************************************/ -void getscom_PIBMEM_HW_Key_Hash (uint64_t base, uint8_t* buf) { - memcpy(buf, HW.PIBMEM_HW_KEY_HASH, SHA512_DIGEST_SIZE); +uint64_t getscom_FSP_BAR_mask (uint64_t base) +{ + return HW.FSP_BAR.mask; } -/****************************************************************************/ -uint8_t* Convert_Mem_Addr (uint64_t addr) { - if (addr >= TEST_SYSTEM_MEMORY) return NULL; - return HW.memory+addr; +void getscom_HW_ECID (uint64_t base, uint8_t* buf) +{ + memcpy(buf, HW.ECID, ECID_SIZE); } -/****************************************************************************/ -uint64_t physical_addr (uint64_t addr) { - if (addr & HRMOR_IGNORE) addr = PHYSICAL(addr); - else addr = PHYSICAL(addr) | HW.HRMOR; - return addr; +uint8_t* Convert_Mem_Addr (uint64_t addr) +{ + if (addr >= TEST_SYSTEM_MEMORY) + { + return NULL; + } + return HW.memory+addr; } -/****************************************************************************/ -uint64_t Convert_Mem_Offset (uint8_t* addr) { - if (addr < HW.memory) return 0; - return (uint64_t)(uint32_t)(addr-HW.memory); +uint64_t physical_addr (uint64_t addr) +{ + if (addr & HRMOR_IGNORE) + { + addr = PHYSICAL(addr); + } + else + { + addr = PHYSICAL(addr) | HW.HRMOR; + } + return addr; +} + +uint64_t Convert_Mem_Offset (uint8_t* addr) +{ + if (addr < HW.memory) + { + return 0; + } + return (uint64_t)(uint32_t)(addr-HW.memory); } -/****************************************************************************/ -uint16_t GET16(uint16_t data) { +uint16_t GET16(uint16_t data) +{ #ifdef __BIG_ENDIAN - return data; + return data; #endif #ifdef __LITTLE_ENDIAN - return ((data&0x00FF)<<8 - |(data&0xFF00)>>8 - ); + return ((data&0x00FF)<<8 + | (data&0xFF00)>>8 + ); #endif } -/****************************************************************************/ -uint32_t GET32 (uint32_t data) { +uint32_t GET32 (uint32_t data) +{ #ifdef __BIG_ENDIAN - return data; + return data; #endif #ifdef __LITTLE_ENDIAN - return ((data&0x000000FF)<<24 - |(data&0x0000FF00)<<8 - |(data&0x00FF0000)>>8 - |(data&0xFF000000)>>24 - ); + return ((data&0x000000FF)<<24 + |(data&0x0000FF00)<<8 + |(data&0x00FF0000)>>8 + |(data&0xFF000000)>>24 + ); #endif } -/****************************************************************************/ -uint64_t GET64 (uint64_t data) { +uint64_t GET64 (uint64_t data) +{ #ifdef __BIG_ENDIAN - return data; + return data; #endif #ifdef __LITTLE_ENDIAN - return ((data&0x00000000000000FFull)<<(7*8) - |(data&0x000000000000FF00ull)<<(5*8) - |(data&0x0000000000FF0000ull)<<(3*8) - |(data&0x00000000FF000000ull)<<(1*8) - |(data&0x000000FF00000000ull)>>(1*8) - |(data&0x0000FF0000000000ull)>>(3*8) - |(data&0x00FF000000000000ull)>>(5*8) - |(data&0xFF00000000000000ull)>>(7*8) - ); + return ((data&0x00000000000000FFull)<<(7*8) + |(data&0x000000000000FF00ull)<<(5*8) + |(data&0x0000000000FF0000ull)<<(3*8) + |(data&0x00000000FF000000ull)<<(1*8) + |(data&0x000000FF00000000ull)>>(1*8) + |(data&0x0000FF0000000000ull)>>(3*8) + |(data&0x00FF000000000000ull)>>(5*8) + |(data&0xFF00000000000000ull)>>(7*8) + ); #endif } #else -void __attribute__((noreturn)) Check_Stop(void) { - //do not use XSCOM as the XSCOM base is not known for sure +void __attribute__((noreturn)) Check_Stop(void) +{ + //do not use XSCOM as the XSCOM base is not known for sure - //set AVP_out to (optionally) cause secure checkstop - mtspr(SPRC,SPRC_AVP_out); - mtspr(SPRD,-1LL); + //set AVP_out to (optionally) cause secure checkstop + mtspr(SPRC,SPRC_AVP_out); + mtspr(SPRD,-1LL); - asm volatile(" li 0,0 \n" - " mtmsr 0 \n" //ensure there is no error handler so it will checkstop instead - " lis 0,-1107 \n" - " stdcix 0,0,0 \n" //store to invalid address - " eieio "); - for(;;) {} + asm volatile(" li 0,0 \n" + " mtmsr 0 \n" //ensure there is no error handler so it will checkstop instead + " lis 0,-1107 \n" + " stdcix 0,0,0 \n" //store to invalid address + " eieio "); + for(;;) {} } -#endif //emulate_hw +#endif //EMULATE_HW diff --git a/src/securerom/inttypes.H b/src/securerom/inttypes.H index 397732961..5da83836f 100644 --- a/src/securerom/inttypes.H +++ b/src/securerom/inttypes.H @@ -22,6 +22,7 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + #define uint_fast8_t uint8_t #ifndef BYTE_ORDER diff --git a/src/securerom/makefile b/src/securerom/makefile index 4b3a5a3cf..e1c5cc8cf 100644 --- a/src/securerom/makefile +++ b/src/securerom/makefile @@ -23,222 +23,27 @@ # # IBM_PROLOG_END_TAG -bootrom := bootrom -bootrom_bin = $(bootrom).bin -bootrom_dis = $(bootrom).dis -#bootrom_srec = $(bootrom).srec +ROOTPATH = ../.. -bootrom_vhdl = ../vhdl/tpc_secr_rom_pkg.vhdl +COMMONFLAGS += -DBYTE_ORDER=BIG_ENDIAN +COMMONFLAGS += -DBN_POWER64_MUL +COMMONFLAGS += -DBN_POWER64_CMP +COMMONFLAGS += -DBN_POWER64_CPY +COMMONFLAGS += -DBN_POWER64_CLR +COMMONFLAGS += -DEC_POWER64_RED +COMMONFLAGS += -DEC_POWER64_ALG +COMMONFLAGS += -DSHA512_FIX -bootrom_nm = $(bootrom).nm +LDFLAGS += -N -LDSCRIPT = bootrom.lds +ASMFLAGS += -D__ASSEMBLER__ -HOSTTYPE ?= $(shell uname -p) -CELLSIZE ?= 64 +OBJS += branchtable.o +OBJS += ROM.o +OBJS += sha512.o +OBJS += ecverify.o +OBJS += hw_utils.o -ifeq ($(HOSTTYPE),powerpc) -CROSS ?= powerpc-ibm-aix6.1.0.0- -ONLY_CC = $(CROSS)gcc -mpowerpc64 -maix64 -Wa,-mANY -ONLY_AS = $(CROSS)as -m$(CELLSIZE) -ONLY_LD = $(CROSS)ld -melf$(CELLSIZE)ppc -OBJCOPY ?= $(CROSS)objcopy -OBJDUMP ?= $(CROSS)objdump -else -CROSS ?= powerpc-linux-gnu- -ONLY_CC = $(CROSS)gcc -m64 -Wa,-mregnames -ONLY_AS = $(CROSS)as -m64 -mregnames -ONLY_LD = $(CROSS)ld -melf64ppc -OBJCOPY ?= $(CROSS)objcopy -OBJDUMP ?= $(CROSS)objdump -endif +OPT_LEVEL = -Os - -# Verbose level: -# V=0 means completely silent -# V=1 means brief output -# V=2 means full verbose output -V ?= 2 - -ifeq ($(V),0) -Q := @ -MAKEFLAGS += --silent -MAKE += -s -endif - -ifeq ($(V),1) -MAKEFLAGS += --silent -MAKE += -s -CC = printf "\t[CC]\t$@\n"; $(ONLY_CC) -AS = printf "\t[AS]\t$@\n"; $(ONLY_AS) -LD = printf "\t[LD]\t$@\n"; $(ONLY_LD) -CLEAN = printf "\t[CLEAN]\t%s\n" "$(DIRECTORY)$$dir" -else -CC = $(ONLY_CC) -AS = $(ONLY_AS) -LD = $(ONLY_LD) -CLEAN = echo -n -endif - -# need version >= 1_0_0 -#OPENSSL ?= ~/openssl/openssl-1.0.0/bin/openssl -#SREC_CAT ?= srec_cat - -CPPFLAGS += -DCONFIG_AWAN \ - -I./src/ -I./include/ \ - -DCELLSIZE=$(CELLSIZE) \ - -DBYTE_ORDER=BIG_ENDIAN \ - -g \ - -#CPPFLAGS += -DEC_POWER64_ASM -CPPFLAGS += -DBN_POWER64_MUL -CPPFLAGS += -DBN_POWER64_CMP -CPPFLAGS += -DBN_POWER64_CPY -CPPFLAGS += -DBN_POWER64_CLR -CPPFLAGS += -DEC_POWER64_RED -#CPPFLAGS += -DBN_POWER64_SQR -CPPFLAGS += -DEC_POWER64_ALG -#CPPFLAGS += -DBN_POWER64_DBG -CPPFLAGS += -DSHA512_FIX - -OBJDIR = obj - -ifeq ($(MAMBO),yes) -CPPFLAGS += -DCONFIG_MAMBO -bootrom := bootrom_4mambo -OBJDIR = mambo -endif - -asm_srcs = src/branchtable.S -c_srcs = src/ROM.c src/sha512.c src/ecverify.c -c_srcs += src/memmove.c src/memcmp.c src/hw_utils.c -#c_srcs += src/memset.c src/memcpy.c - -CPPFLAGS += -DCONFIG_SOFTWARE_CRYPTO - -srcs = $(asm_srcs) $(c_srcs) -objs = $(subst src/,$(OBJDIR)/,$(asm_srcs:.S=.o) $(c_srcs:.c=.o)) -deps = $(subst src/,$(OBJDIR)/,$(asm_srcs:.S=.d) $(c_srcs:.c=.d)) - -CFLAGS ?= -W -Os -fno-builtin -ffreestanding -nostdinc -mno-toc \ - -msoft-float -mno-altivec -mabi=no-altivec -Wall -mregnames \ - $(CPPFLAGS) - -ASFLAGS += $(CPPFLAGS) -Wa,-mregnames -D__ASSEMBLER__ - -LDFLAGS = -nostdlib -N - - -default: - $(MAKE) all - $(MAKE) MAMBO=yes bootrom_4mambo.dis bootrom_4mambo.bin - -$(OBJDIR): - @if [ -d $(OBJDIR) ] ; then true; else mkdir -p $(OBJDIR); fi - -all: $(bootrom_dis) $(bootrom_bin) $(bootrom_vhdl) - - -NODEPS = clean distclean binclean -ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS)))) --include $(deps) -endif - - -## This was to create a selfsigned rom code but now it is no longer selfsigned : - -#ec_private_key.pem: -# $(OPENSSL) ecparam -name secp521r1 -genkey -out ec_private_key.pem - -#ec_private_key.pem: ec_private_key.pkcs8 -# $(OPENSSL) pkcs8 -inform DER -nocrypt -in ec_private_key.pkcs8 -out ec_private_key.pem -#ec_private_key.pkcs8: -# ./ecdsasig.x86 -r -g x > ec_private_key.pkcs8 - -#ec_public_key.der: ec_private_key.pem -# $(OPENSSL) ec -in ec_private_key.pem -pubout -outform DER -out ec_public_key.der - -#$(bootrom).stage1: $(objs) $(gen_hdrs) $(prism_hdrs) src/dummy_header.o src/dummy_hash.o -# $(LD) $(LDFLAGS) -o $@ $(objs) src/dummy_header.o src/dummy_hash.o - -#$(bootrom).signed.bin: $(bootrom).stage1 -# $(OBJCOPY) -j .text -j .data -O binary $^ $@ - -#dummy_header.bin: $(bootrom).stage1 -# $(OBJCOPY) -j .image_header -O binary $^ $@ - -#$(bootrom).signed.sig: $(bootrom).signed.bin ec_private_key.pem -# $(OPENSSL) dgst -sign ec_private_key.pem -sha512 $^ > $@ - -#image_header.bin: ec_public_key.der $(bootrom).signed.sig src/dummy_header.o dummy_header.bin -# ./asn1extract_pubkey.pl ec_public_key.der > image_header.bin -# dd bs=132 count=2 if=/dev/zero >> image_header.bin -# ./asn1extract.pl bootrom.signed.sig | xxd -r -p >> image_header.bin -# dd bs=132 count=2 if=/dev/zero >> image_header.bin -# dd bs=1 skip=792 count=88 if=dummy_header.bin >> image_header.bin - -#image_header.o: image_header.bin -# $(OBJCOPY) -I binary -O elf64-powerpc -B powerpc --rename-section .data=.image_header --redefine-sym _binary_image_header_bin_start=rom_image_header image_header.bin image_header.o - -#$(bootrom).stage2: $(objs) $(gen_hdrs) $(prism_hdrs) image_header.o src/dummy_hash.o -# $(LD) $(LDFLAGS) -o $@ $(objs) image_header.o src/dummy_hash.o - -#bootrom.hashed.bin: $(bootrom).stage2 -# $(OBJCOPY) -j .image_hash -j .text -j .data -O binary $^ $@ - -#bootrom.hashed.hash: bootrom.hashed.bin -# $(OPENSSL) dgst -sha512 bootrom.hashed.bin | sed -e "s/.* //" | xxd -r -p > bootrom.hashed.hash - -#rom_hash.o: bootrom.hashed.hash -# $(OBJCOPY) -I binary -O elf64-powerpc -B powerpc \ -# --rename-section .data=.rom_hash \ -# --redefine-sym _binary_bootrom_hashed_hash_start=rom_hash \ -# bootrom.hashed.hash rom_hash.o - -#$(bootrom): $(objs) $(gen_hdrs) $(prism_hdrs) image_header.o rom_hash.o -# $(LD) $(LDFLAGS) -o $@ $(objs) image_header.o rom_hash.o - -$(bootrom): $(objs) $(LDSCRIPT) - $(LD) $(LDFLAGS) -T$(LDSCRIPT) -o $@ $(objs) - -$(bootrom_dis): $(bootrom) - $(OBJDUMP) -j .branchtable -j .text -j .data -j .toc --source $^ > $@ - -#$(bootrom_srec): $(bootrom) -# $(OBJCOPY) --change-addresses -0xff80000 $^ -O srec $@ - -$(bootrom_bin): $(bootrom) - $(OBJCOPY) -j .branchtable -j .text -j .data -j .toc -O binary $^ $@ - -$(bootrom_vhdl): $(bootrom_bin) convVhdl.pl - ./convVhdl.pl $^ > $@ - -$(OBJDIR)/%.o: src/%.S $(OBJDIR)/%.d - $(CC) $(ASFLAGS) -c $< -o $@ - -$(OBJDIR)/%.o: src/%.c $(OBJDIR)/%.d - $(CC) $(CFLAGS) -c $< -o $@ - -$(OBJDIR)/%.d: src/%.S Makefile $(OBJDIR) - $(CC) -MM $(ASFLAGS) $< | sed 's,\(\S*\)\.o[ :]*,$(OBJDIR)/\1.o $(OBJDIR)/\1.d : ,g' > $@ - -$(OBJDIR)/%.d: src/%.c Makefile $(OBJDIR) - $(CC) -MM $(CFLAGS) $< | sed 's,\(\S*\)\.o[ :]*,$(OBJDIR)/\1.o $(OBJDIR)/\1.d : ,g' > $@ - -#ecdsa: src/ecdsa.c src/ecverify.c -# gcc -W -Os -fno-builtin -ffreestanding -nostdinc -msoft-float -mno-altivec -mabi=no-altivec -Wall -I./src/ -I./include/ -o ecdsa src/ecdsa.c src/ecverify.c - -clean: - $(RM) -r *~ obj mambo -# ec_public_key.der \ -# $(bootrom).stage1 $(bootrom).signed.bin $(bootrom).signed.sig dummy_header.bin image_header.bin image_header.o\ -# $(bootrom).stage2 $(bootrom).hashed.bin $(bootrom).hashed.hash rom_hash.o - -distclean: clean - @$(MAKE) binclean - @$(MAKE) MAMBO=yes binclean - -binclean: - $(RM) $(bootrom) $(bootrom_bin) $(bootrom_dis) - -.PHONY: default all clean distclean binclean +include ${ROOTPATH}/config.mk diff --git a/src/securerom/sha512.C b/src/securerom/sha512.C index 820ead264..9ec230f4f 100644 --- a/src/securerom/sha512.C +++ b/src/securerom/sha512.C @@ -30,105 +30,100 @@ #include <stdlib.h> #include <stdio.h> #include <stdint.h> -#include <sha512.h> +#include <securerom/sha512.H> /* Initial hash value HASH(32byte) for SHA-512 */ -const uint64_t sha512_initial_hash_value[8] = { - 0x6a09e667f3bcc908ULL, - 0xbb67ae8584caa73bULL, - 0x3c6ef372fe94f82bULL, - 0xa54ff53a5f1d36f1ULL, - 0x510e527fade682d1ULL, - 0x9b05688c2b3e6c1fULL, - 0x1f83d9abfb41bd6bULL, - 0x5be0cd19137e2179ULL +extern "C" +const uint64_t sha512_initial_hash_value[8] = +{ + 0x6a09e667f3bcc908ULL, + 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, + 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, + 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, + 0x5be0cd19137e2179ULL }; /* Hash constant words K for SHA-384 and SHA-512: */ -const uint64_t K512[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, - 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, - 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, - 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, - 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, - 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, - 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, - 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, - 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, - 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, - 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, - 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, - 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, - 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, - 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, - 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, - 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, - 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, - 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, - 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, - 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, - 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, - 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, - 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, - 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, - 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, - 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +extern "C" +const uint64_t K512[80] = +{ + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL }; - - -#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) - - +#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) /* * Macro for incrementally adding the unsigned 64-bit integer n to the * unsigned 128-bit integer (represented using a two-element array of * 64-bit words): */ -#define ADDINC128(w,n) { \ - (w)[0] += (uint64_t)(n); \ - if ((w)[0] < (n)) { \ - (w)[1]++; \ - } \ +#define ADDINC128(w,n) \ +{ \ + (w)[0] += (uint64_t)(n); \ + if ((w)[0] < (n)) \ + { \ + (w)[1]++; \ + } \ } - - /* Shift-right (used in SHA-512): */ -#define R(b,x) ((x) >> (b)) - +#define R(b,x) ((x) >> (b)) /* 64-bit Rotate-right (used in SHA-512): */ -#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) - - +#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) /* Two of six logical functions used in SHA-512: */ -#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) -#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - - +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) /* Four of six logical functions used in SHA-512: */ -#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) -#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) -#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) -#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) +#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) +#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) +#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) +#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) static void SHA512_Last(SHA512_CTX*); static void SHA512_Transform(SHA512_CTX*, const uint64_t *); @@ -137,346 +132,270 @@ static void SHA512_Transform(SHA512_CTX*, const uint64_t *); * Constant used by SHA256/384/512_End() functions for converting the * digest to a readable hexadecimal character string: */ - -static inline void bcopy(const void * SRC, void* DST, size_t length){ +static inline void bcopy(const void * SRC, void* DST, size_t length) +{ unsigned char * source = (unsigned char *) SRC; unsigned char * destination = (unsigned char *) DST; - for( ; length ; length--){ + for( ; length ; length--) + { *destination++ = *source++; } } static inline void bzero(void * DST, size_t length){ unsigned char * destination = (unsigned char *) DST; - for( ; length ; length--){ + for( ; length ; length--) + { *destination++=0x00; } } -// unused: -//static inline int tstrlen(const void * SRC){ -// unsigned char * source = (unsigned char *) SRC; -// int length=0; -// while(source[length]!=0x00){ -// length++; -// } -// return length; -//} - - /*** SHA-512: *********************************************************/ asm(".globl .L.SHA512_Init"); -void SHA512_Init(SHA512_CTX* context) { - if (context == (SHA512_CTX*)0) { - return; - } - - uint64_t* sha512_initial_hash_value_p; - #ifdef EMULATE_HW - sha512_initial_hash_value_p = sha512_initial_hash_value; - #else - //selftest_p = &selftest; //this line would introduce a absolute address in the toc - 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,(sha512_initial_hash_value-0x8000)@l" : "=r" (sha512_initial_hash_value_p) ); - #endif - - bcopy(sha512_initial_hash_value_p, context->state, SHA512_DIGEST_LENGTH); - bzero(context->buffer, SHA512_BLOCK_LENGTH); - context->bitcount[0] = context->bitcount[1] = 0; -} +void SHA512_Init(SHA512_CTX* context) +{ + if (context == (SHA512_CTX*)0) + { + return; + } + uint64_t* sha512_initial_hash_value_p; +#ifdef EMULATE_HW + sha512_initial_hash_value_p = sha512_initial_hash_value; +#else + asm volatile("li %0,(__toc_start)@l ### %0 := base+0x8000 \n\t" // because li does not work + "sub %0,2,%0 \n\t" // because subi does not work + "addi %0,%0,(sha512_initial_hash_value-0x8000)@l" : "=r" (sha512_initial_hash_value_p) ); +#endif -static void SHA512_Transform(SHA512_CTX* context, const uint64_t* data) { - uint64_t a, b, c, d, e, f, g, h, s0, s1; - uint64_t T1, T2, *W512 = (uint64_t*)context->buffer; - int j; - - uint64_t* K512_p; - #ifdef EMULATE_HW - K512_p = K512; - #else - //selftest_p = &selftest; //this line would introduce a absolute address in the toc - 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,(K512-0x8000)@l" : "=r" (K512_p) ); - #endif - - /* Initialize registers with the prev. intermediate value */ - a = context->state[0]; - b = context->state[1]; - c = context->state[2]; - d = context->state[3]; - e = context->state[4]; - f = context->state[5]; - g = context->state[6]; - h = context->state[7]; - - j = 0; - do { - /* Apply the SHA-512 compression function to update a..h with copy */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512_p[j] + (W512[j] = *data++); - T2 = Sigma0_512(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 16); - - do { - /* Part of the message block expansion: */ - s0 = W512[(j+1)&0x0f]; - s0 = sigma0_512(s0); - s1 = W512[(j+14)&0x0f]; - s1 = sigma1_512(s1); - - /* Apply the SHA-512 compression function to update a..h */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512_p[j] + - (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); - T2 = Sigma0_512(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 80); - - /* Compute the current intermediate hash value */ - context->state[0] += a; - context->state[1] += b; - context->state[2] += c; - context->state[3] += d; - context->state[4] += e; - context->state[5] += f; - context->state[6] += g; - context->state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = T2 = 0; + bcopy(sha512_initial_hash_value_p, context->state, SHA512_DIGEST_LENGTH); + bzero(context->buffer, SHA512_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; } +static void SHA512_Transform(SHA512_CTX* context, const uint64_t* data) +{ + uint64_t a, b, c, d, e, f, g, h, s0, s1; + uint64_t T1, T2, *W512 = (uint64_t*)context->buffer; + int j; + + uint64_t* K512_p; +#ifdef EMULATE_HW + K512_p = K512; +#else + asm volatile("li %0,(__toc_start)@l ### %0 := base+0x8000 \n\t" // because li does not work + "sub %0,2,%0 \n\t" // because subi does not work + "addi %0,%0,(K512-0x8000)@l" : "=r" (K512_p) ); +#endif + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + /* Apply the SHA-512 compression function to update a..h with copy */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512_p[j] + (W512[j] = *data++); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512_p[j] + + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + asm(".globl .L.SHA512_Update"); -void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) { - unsigned int freespace, usedspace; - - if (len == 0) { - /* Calling with no data is valid - we do nothing */ - return; - } - - /* Sanity check: */ - //assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0); - - usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; - if (usedspace > 0) { - /* Calculate how much free space is available in the buffer */ - freespace = SHA512_BLOCK_LENGTH - usedspace; - - if (len >= freespace) { - /* Fill the buffer completely and process it */ - bcopy(data, &context->buffer[usedspace], freespace); - ADDINC128(context->bitcount, freespace << 3); - len -= freespace; - data += freespace; - SHA512_Transform(context, (uint64_t*)context->buffer); - } else { - /* The buffer is not yet full */ - bcopy(data, &context->buffer[usedspace], len); - ADDINC128(context->bitcount, len << 3); - /* Clean up: */ - usedspace = freespace = 0; - return; - } - } - while (len >= SHA512_BLOCK_LENGTH) { - /* Process as many complete blocks as we can */ - SHA512_Transform(context, (const uint64_t*)data); - ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); - len -= SHA512_BLOCK_LENGTH; - data += SHA512_BLOCK_LENGTH; - } - if (len > 0) { - /* There's left-overs, so save 'em */ - bcopy(data, context->buffer, len); - ADDINC128(context->bitcount, len << 3); - } - /* Clean up: */ - usedspace = freespace = 0; +void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) +{ + unsigned int freespace, usedspace; + + if (len == 0) + { + /* Calling with no data is valid - we do nothing */ + return; + } + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + if (usedspace > 0) + { + /* Calculate how much free space is available in the buffer */ + freespace = SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) + { + /* Fill the buffer completely and process it */ + bcopy(data, &context->buffer[usedspace], freespace); + ADDINC128(context->bitcount, freespace << 3); + len -= freespace; + data += freespace; + SHA512_Transform(context, (uint64_t*)context->buffer); + } + else + { + /* The buffer is not yet full */ + bcopy(data, &context->buffer[usedspace], len); + ADDINC128(context->bitcount, len << 3); + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA512_BLOCK_LENGTH) + { + /* Process as many complete blocks as we can */ + SHA512_Transform(context, (const uint64_t*)data); + ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); + len -= SHA512_BLOCK_LENGTH; + data += SHA512_BLOCK_LENGTH; + } + if (len > 0) + { + /* There's left-overs, so save 'em */ + bcopy(data, context->buffer, len); + ADDINC128(context->bitcount, len << 3); + } + /* Clean up: */ + usedspace = freespace = 0; } -static void SHA512_Last(SHA512_CTX* context) { - unsigned int usedspace; +static void SHA512_Last(SHA512_CTX* context) +{ + unsigned int usedspace; - usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; - if (usedspace > 0) { - /* Begin padding with a 1 bit: */ - context->buffer[usedspace++] = 0x80; + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + if (usedspace > 0) + { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; #if SHA512_FIX - if (usedspace < SHA512_SHORT_BLOCK_LENGTH) { - /* Set-up for the last transform: */ - bzero(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); - } else if (usedspace > SHA512_SHORT_BLOCK_LENGTH) { - if (usedspace < SHA512_BLOCK_LENGTH) { - bzero(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); - } - /* Do second-to-last transform: */ - SHA512_Transform(context, (uint64_t*)context->buffer); - - /* And set-up for the last transform: */ - bzero(context->buffer, SHA512_SHORT_BLOCK_LENGTH); - } + if (usedspace < SHA512_SHORT_BLOCK_LENGTH) + { + /* Set-up for the last transform: */ + bzero(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH + - usedspace); + } + else if (usedspace > SHA512_SHORT_BLOCK_LENGTH) + { + if (usedspace < SHA512_BLOCK_LENGTH) + { + bzero(&context->buffer[usedspace], SHA512_BLOCK_LENGTH + - usedspace); + } + /* Do second-to-last transform: */ + SHA512_Transform(context, (uint64_t*)context->buffer); + + /* And set-up for the last transform: */ + bzero(context->buffer, SHA512_SHORT_BLOCK_LENGTH); + } #else - if (usedspace < SHA512_SHORT_BLOCK_LENGTH) { - /* Set-up for the last transform: */ - bzero(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); - } else { - if (usedspace < SHA512_BLOCK_LENGTH) { - bzero(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); - } - /* Do second-to-last transform: */ - SHA512_Transform(context, (uint64_t*)context->buffer); - - /* And set-up for the last transform: */ - bzero(context->buffer, SHA512_BLOCK_LENGTH - 2); - } + if (usedspace < SHA512_SHORT_BLOCK_LENGTH) + { + /* Set-up for the last transform: */ + bzero(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH + - usedspace); + } + else + { + if (usedspace < SHA512_BLOCK_LENGTH) + { + bzero(&context->buffer[usedspace], SHA512_BLOCK_LENGTH + - usedspace); + } + /* Do second-to-last transform: */ + SHA512_Transform(context, (uint64_t*)context->buffer); + + /* And set-up for the last transform: */ + bzero(context->buffer, SHA512_BLOCK_LENGTH - 2); + } #endif - } else { - /* Prepare for final transform: */ - bzero(context->buffer, SHA512_SHORT_BLOCK_LENGTH); - - /* Begin padding with a 1 bit: */ - *context->buffer = 0x80; - } - /* Store the length of input data (in bits): */ - *(uint64_t*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; - *(uint64_t*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; - - /* Final transform: */ - SHA512_Transform(context, (uint64_t*)context->buffer); + } + else + { + /* Prepare for final transform: */ + bzero(context->buffer, SHA512_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits): */ + uint64_t* p1 = reinterpret_cast<uint64_t*>(&context->buffer[SHA512_SHORT_BLOCK_LENGTH]); + uint64_t* p2 = reinterpret_cast<uint64_t*>(&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8]); + *p1 = context->bitcount[1]; + *p2 = context->bitcount[0]; + + /* Final transform: */ + SHA512_Transform(context, (uint64_t*)context->buffer); } asm(".globl .L.SHA512_Final"); void SHA512_Final(SHA512_CTX* context, sha2_hash_t *result) { - /* Sanity check: */ - //assert(context != (SHA512_CTX*)0); + /* Sanity check: */ + //assert(context != (SHA512_CTX*)0); - /* If no digest buffer is passed, we don't bother doing this: */ - SHA512_Last(context); + /* If no digest buffer is passed, we don't bother doing this: */ + SHA512_Last(context); - /* Save the hash data for output: */ - bcopy(context->state, result, SHA512_DIGEST_LENGTH); + /* Save the hash data for output: */ + bcopy(context->state, result, SHA512_DIGEST_LENGTH); - /* Zero out state data */ - bzero(context, sizeof(context)); + /* Zero out state data */ + bzero(context, sizeof(context)); } asm(".globl .L.SHA512_Hash"); void SHA512_Hash(const sha2_byte* data, size_t len, sha2_hash_t *result) { - SHA512_CTX context; - - SHA512_Init(&context); - SHA512_Update(&context, data, len); - SHA512_Final(&context, result); -} - -/* -int main( void ){ - int i; - uint64_t hash[8] = {}; - const sha2_byte text[]={"The quick brown fox jumps over the lazy dog"}; - - printf("SHA512 \"%s\"\n",text); - SHA512( text, tstrlen(text), hash ); - for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { - printf("%02x", hash[i]); - if( (i&3) ==3) printf(" "); - if( (i&31) ==31) printf("\n"); - } - - const sha2_byte text2[]={""}; - printf("SHA512 \"%s\"\n",text2); - SHA512( text2, tstrlen(text2), hash ); - for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { - printf("%02x", hash[i]); - if( (i&3) ==3) printf(" "); - if( (i&31) ==31) printf("\n"); - } + SHA512_CTX context; -} -*/ - -#if INCLUDE_SHA_TESTS -/****************************************************************************/ -static uint8_t SHA512_Input[] = "abc"; -static uint64_t SHA512_Result[] = { - 0xddaf35a193617abaull, 0xcc417349ae204131ull, 0x12e6fa4e89a97ea2ull, 0x0a9eeee64b55d39aull, - 0x2192992a274fc1a8ull, 0x36ba3c23a3feebbdull, 0x454d4423643ce80eull, 0x2a9ac94fa54ca49full, -}; -static uint8_t SHA512_Input2[] = - "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" - "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"; -static uint64_t SHA512_Result2[] = { - 0x8e959b75dae313daull, 0x8cf4f72814fc143full, 0x8f7779c6eb9f7fa1ull, 0x7299aeadb6889018ull, - 0x501d289e4900f7e4ull, 0x331b99dec4b5433aull, 0xc7d329eeb6dd2654ull, 0x5e96e55b874be909ull, -}; -#include <selftest.h> -/****************************************************************************/ -void SHA512_Test (void) -{ - SHA512 sha; - SHA512_Init (&sha); - SHA512_Update (&sha, SHA512_Input, 3); - SHA512_Finish (&sha, NULL); - if (memcmp((uint8_t*)sha.H, (uint8_t*)SHA512_Result, SHA512_DIGEST_SIZE)) { - printf ("SHA512 Test 1 FAILED with bad digest (\n"); - printf ("%016llx %016llx %016llx %016llx\n",sha.H[0],sha.H[1],sha.H[2],sha.H[3]); - printf ("%016llx %016llx %016llx %016llx\n",sha.H[4],sha.H[5],sha.H[6],sha.H[7]); - printf (")\n"); - } - else { - printf ("SHA512 Test 1 Complete\n"); - } - SHA512_Init (&sha); - SHA512_Update (&sha, SHA512_Input2, 112); - SHA512_Finish (&sha, NULL); - if (memcmp((uint8_t*)sha.H, (uint8_t*)SHA512_Result2, SHA512_DIGEST_SIZE)) { - printf ("SHA512 Test 2 FAILED with bad digest (\n"); - printf ("%016llx %016llx %016llx %016llx\n",sha.H[0],sha.H[1],sha.H[2],sha.H[3]); - printf ("%016llx %016llx %016llx %016llx\n",sha.H[4],sha.H[5],sha.H[6],sha.H[7]); - printf (")\n"); - } - else { - printf ("SHA512 Test 2 Complete\n"); - } - SHA512_Hash (&sha, (uint8_t*)&selftest.ec, sizeof(selftest.ec), NULL); - sha.H[0] = BE2HO_8(sha.H[0]); - sha.H[1] = BE2HO_8(sha.H[1]); - sha.H[2] = BE2HO_8(sha.H[2]); - sha.H[3] = BE2HO_8(sha.H[3]); - sha.H[4] = BE2HO_8(sha.H[4]); - sha.H[5] = BE2HO_8(sha.H[5]); - sha.H[6] = BE2HO_8(sha.H[6]); - sha.H[7] = BE2HO_8(sha.H[7]); - if (memcmp((uint8_t*)sha.H, selftest.sha.hash, SHA512_DIGEST_SIZE)) { - printf ("SHA512 Test 3 FAILED with bad digest (\n"); - printf ("%016llx %016llx %016llx %016llx\n",sha.H[0],sha.H[1],sha.H[2],sha.H[3]); - printf ("%016llx %016llx %016llx %016llx\n",sha.H[4],sha.H[5],sha.H[6],sha.H[7]); - printf (")\n"); - } - else { - printf ("SHA512 Test 3 Complete\n"); - } -} -#endif + SHA512_Init(&context); + SHA512_Update(&context, data, len); + SHA512_Final(&context, result); +}
\ No newline at end of file |