diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 5b8d3566ba..ad9d3799b5 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -229,6 +229,28 @@ jobs: config-file: ./config/examples/nxp-t2080.config make-args: CFLAGS_EXTRA=-DBOARD_CW_VPX3152 + # TEMPORARY: these two build the bare-metal test app against the QorIQ SEC + # port, which lives in wolfSSL PR #11199. The lib/wolfssl submodule is pinned + # to that PR's head so CI can prove the integration before it merges. Once + # #11199 lands, repin lib/wolfssl to a wolfSSL master commit containing it; + # these two jobs then keep working unchanged and stop being temporary. + nxp_t2080_sec_qoriq_test: + uses: ./.github/workflows/test-build-powerpc.yml + with: + arch: ppc + config-file: ./config/examples/nxp-t2080.config + # Build the test app only. The full target would also sign it, and + # signing a WOLFCRYPT_TEST=1 T2080 image aborts in tools/keytools/sign + # on a pre-existing double free unrelated to this change. + make-args: SEC_QORIQ=1 SEC_QORIQ_CCSRBAR=0xEF000000UL WOLFCRYPT_TEST=1 test-app/image.bin + + nxp_t1040_sec_qoriq_test: + uses: ./.github/workflows/test-build-powerpc.yml + with: + arch: ppc + config-file: ./config/examples/nxp-t1040.config + make-args: SEC_QORIQ=1 SEC_QORIQ_CCSRBAR=0xFE000000UL WOLFCRYPT_TEST=1 test-app/image.bin + nxp_lpc54s0xx_test: uses: ./.github/workflows/test-build.yml with: diff --git a/lib/wolfssl b/lib/wolfssl index 5418d6cfdc..1e80aaca35 160000 --- a/lib/wolfssl +++ b/lib/wolfssl @@ -1 +1 @@ -Subproject commit 5418d6cfdc4acd126983331a498ba2a8c70839c7 +Subproject commit 1e80aaca3507202f0e939bf2d0c52a86dbe0d358 diff --git a/test-app/Makefile b/test-app/Makefile index 7312762376..bb535568b0 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -82,6 +82,15 @@ ifeq ($(TARGET),sim) STACK_USAGE_LIMIT:=4608 endif +# SP_MATH_ALL with RSA-2048 puts ~18 KB frames in sp_int.c. The PowerPC test +# app runs from DDR with a 256 KB stack, so that is affordable here even +# though it would not be on a small target. +ifeq ($(ARCH),PPC) + ifeq ($(WOLFCRYPT_TEST),1) + STACK_USAGE_LIMIT:=20480 + endif +endif + ifeq ($(TARGET),ti_hercules) APP_OBJS:=app_$(TARGET).o ../test-app/libwolfboot.o CFLAGS+=-I"../include" @@ -205,6 +214,31 @@ ifeq ($(TARGET),max32666) endif endif +# NXP QorIQ SEC hardware crypto, selected through the crypto callback layer. +ifeq ($(SEC_QORIQ),1) + # CCSR base is board specific: the NXP RDBs leave it at the 0xFE000000 + # reset value, the CW VPX3-152 U-Boot relocates it to 0xEF000000. A wrong + # base does not fail cleanly -- the driver reads an unmapped address and the + # core takes a data TLB error -- so there is deliberately no default. State + # it per build. + ifeq ($(SEC_QORIQ_CCSRBAR),) + $(error SEC_QORIQ=1 requires SEC_QORIQ_CCSRBAR to be set, e.g. \ + SEC_QORIQ_CCSRBAR=0xFE000000UL for the NXP T1040/T2080 RDBs or \ + SEC_QORIQ_CCSRBAR=0xEF000000UL for the CW VPX3-152) + endif + CFLAGS+=-DWOLFSSL_SEC_QORIQ -DWOLFSSL_SEC_QORIQ_BAREMETAL + CFLAGS+=-DSEC_QORIQ_CCSRBAR=$(SEC_QORIQ_CCSRBAR) + WOLFCRYPT_SUPPORT=1 + APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/cryptocb.o + APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/sec_qoriq.o + APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/sec_qoriq_cb.o + APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/sec_qoriq_hash.o + APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/sec_qoriq_aes.o + APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/sec_qoriq_rng.o + APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/sec_qoriq_pkha.o + APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/sec_qoriq_baremetal.o +endif + ifeq ($(WOLFCRYPT_TEST),1) CFLAGS+=-DWOLFCRYPT_TEST WOLFCRYPT_SUPPORT=1 diff --git a/test-app/PPC.ld b/test-app/PPC.ld index dad96fce5f..8ece86a55d 100644 --- a/test-app/PPC.ld +++ b/test-app/PPC.ld @@ -67,9 +67,13 @@ SECTIONS /* Heap for _sbrk (used by syscalls.c malloc) */ _Min_Heap_Size = 0x10000; /* 64KB */ - /* Stack: 64KB, grows downward from _stack_top. - * wolfCrypt ECC384 operations need deep stack (~11KB per frame). */ - _Min_Stack_Size = 0x10000; /* 64KB */ + /* Stack: 256KB, grows downward from _stack_top. + * wolfCrypt ECC384 operations need deep stack (~11KB per frame), and an + * RSA-enabled wolfcrypt_test build needs far more again: SP_INT_BITS + * rises to the RSA key size, which enlarges every mp_int the PBKDF and + * PKCS#12 paths put on the stack. The app runs from DDR, so the space + * costs nothing. */ + _Min_Stack_Size = 0x40000; /* 256KB */ _stack_end = _end + _Min_Heap_Size; _stack_top = _stack_end + _Min_Stack_Size; } diff --git a/test-app/app_nxp_t1040.c b/test-app/app_nxp_t1040.c index 19548afbee..4009112b4d 100644 --- a/test-app/app_nxp_t1040.c +++ b/test-app/app_nxp_t1040.c @@ -27,6 +27,23 @@ #include "target.h" #include "wolfboot/wolfboot.h" +/* wolfCrypt test/benchmark support */ +#ifdef WOLFCRYPT_TEST +#include +#include +int wolfcrypt_test(void *args); +#endif + +#ifdef WOLFCRYPT_BENCHMARK +#include +#include +int benchmark_test(void *args); +#endif + +#ifdef WOLFSSL_SEC_QORIQ +#include +#endif + /* wait_ticks: spin for r3 ticks using PPC timebase. * Required by udelay() in nxp_ppc.c (linked via HAL). */ __asm__ ( @@ -47,9 +64,8 @@ __asm__ ( " blr\n" ); -/* Assembly entry: set SP (_stack_top, PPC ABI: 16-byte aligned, back-chain 0), - * enable the FPU (MSR[FP]) -- the variadic printf ABI saves FP regs via stfd - * and would otherwise fault -- then branch to main. */ +/* Entry: set SP (PPC ABI, 16-byte aligned, back-chain 0), enable MSR[FP] so + * the variadic printf ABI can save FP regs with stfd, then branch to main. */ __asm__ ( ".section .text._app_entry\n" ".global _app_entry\n" @@ -152,14 +168,17 @@ static int print_info(void) void main(void) { - /* Zero BSS - required for bare-metal since there's no crt0 startup. - * Without this, static variables contain DDR garbage. */ extern char _start_bss[], _end_bss[]; - { - char *p = _start_bss; - while (p < _end_bss) - *p++ = 0; - } + char *p; +#if (defined(WOLFCRYPT_TEST) || defined(WOLFCRYPT_BENCHMARK)) && \ + defined(WOLFSSL_SEC_QORIQ) + SecQoriqDev* d; + int secRet; +#endif + + /* No crt0 on bare metal, so statics start as DDR garbage. */ + for (p = _start_bss; p < _end_bss; p++) + *p = 0; uart_init(); @@ -169,11 +188,66 @@ void main(void) wolfBoot_printf("GPL v3\r\n"); wolfBoot_printf("========================\r\n"); +#ifndef APP_SKIP_WOLFBOOT_STATE print_info(); /* Mark boot partition as successful */ wolfBoot_success(); wolfBoot_printf("\r\nBoot partition marked successful\r\n"); +#else + /* Loaded from a debugger, not wolfBoot: the partition headers are not + * mapped at their runtime addresses, so reading them would fault. */ + wolfBoot_printf("(wolfBoot state skipped, loaded directly)\r\n"); +#endif + +#if defined(WOLFCRYPT_TEST) || defined(WOLFCRYPT_BENCHMARK) + wolfCrypt_Init(); + +#ifdef WOLFSSL_SEC_QORIQ + secRet = wc_SecQoriqInit(); + if (secRet == 0) { + wolfBoot_printf("QorIQ SEC: enabled, devId 0x%x\r\n", + (unsigned int)WOLFSSL_SEC_QORIQ_DEVID); + } + else { + wolfBoot_printf("QorIQ SEC: init failed (%d), software only\r\n", + secRet); + } +#endif + +#ifdef WOLFCRYPT_TEST + wolfBoot_printf("\r\nRunning wolfCrypt tests...\r\n"); + wolfcrypt_test(NULL); + wolfBoot_printf("Tests complete.\r\n\r\n"); +#endif + +#ifdef WOLFCRYPT_BENCHMARK + wolfBoot_printf("Running wolfCrypt benchmarks...\r\n"); + benchmark_test(NULL); + wolfBoot_printf("Benchmarks complete.\r\n\r\n"); +#endif + +#ifdef WOLFSSL_SEC_QORIQ + /* Report what actually reached the engine: a passing test proves nothing + * about offload, since every unhandled case falls back to software. */ + d = wc_SecQoriqGetDev(); + if (d != NULL) { + wolfBoot_printf("SEC offload counters:\r\n"); + wolfBoot_printf(" jobs submitted : %u\r\n", + (unsigned int)d->jobCount); + wolfBoot_printf(" hash seen %u offloaded %u\r\n", + (unsigned int)d->cbHashCount, (unsigned int)d->cbHashOffload); + wolfBoot_printf(" cipher seen %u offloaded %u\r\n", + (unsigned int)d->cbCipherCount, (unsigned int)d->cbCipherOffload); + wolfBoot_printf(" pk seen %u offloaded %u\r\n", + (unsigned int)d->cbPkCount, (unsigned int)d->cbPkOffload); + wolfBoot_printf(" seed seen %u\r\n", + (unsigned int)d->cbSeedCount); + } +#endif + + wolfCrypt_Cleanup(); +#endif #ifdef ENABLE_WOLFIP wolfip_tftp_test_report(); diff --git a/test-app/app_nxp_t2080.c b/test-app/app_nxp_t2080.c index fd2e1cd1b4..f58cb852cb 100644 --- a/test-app/app_nxp_t2080.c +++ b/test-app/app_nxp_t2080.c @@ -68,6 +68,10 @@ int wolfcrypt_test(void *args); int benchmark_test(void *args); #endif +#ifdef WOLFSSL_SEC_QORIQ +#include +#endif + static uint8_t boot_part_state = IMG_STATE_NEW; static uint8_t update_part_state = IMG_STATE_NEW; @@ -143,14 +147,22 @@ static int print_info(void) void main(void) { - /* Zero BSS (no crt0 on bare metal): the wolfCrypt static-memory pools - * (gTestMemory/HEAP_HINT) must start zeroed or wc_LoadStaticMemory crashes. */ extern char _start_bss[], _end_bss[]; - { - char *p = _start_bss; - while (p < _end_bss) - *p++ = 0; - } + char *p; +#ifdef APP_SKIP_WOLFBOOT_STATE + unsigned long msr; +#endif +#if (defined(WOLFCRYPT_TEST) || defined(WOLFCRYPT_BENCHMARK)) && \ + defined(WOLFSSL_SEC_QORIQ) + SecQoriqDev* d; + int secRet; +#endif + + /* No crt0 on bare metal, and the wolfCrypt static-memory pools + * (gTestMemory/HEAP_HINT) must start zeroed or wc_LoadStaticMemory + * crashes. */ + for (p = _start_bss; p < _end_bss; p++) + *p = 0; uart_init(); @@ -160,11 +172,40 @@ void main(void) wolfBoot_printf("GPL v3\r\n"); wolfBoot_printf("========================\r\n"); +#ifdef APP_SKIP_WOLFBOOT_STATE + /* wolfBoot enables MSR[FP] before handing over and U-Boot does not, so + * the first FP instruction in this -mhard-float build would trap. */ + __asm__ __volatile__("mfmsr %0" : "=r"(msr)); + msr |= 0x00002000UL; /* MSR[FP] */ + __asm__ __volatile__("mtmsr %0" :: "r"(msr)); + __asm__ __volatile__("isync"); +#endif + +#ifndef APP_SKIP_WOLFBOOT_STATE print_info(); +#else + /* Loaded from U-Boot, not wolfBoot: the partition headers are not + * mapped at their runtime addresses, so reading them would fault. */ + wolfBoot_printf("(wolfBoot state skipped, loaded directly)\r\n"); +#endif #if defined(WOLFCRYPT_TEST) || defined(WOLFCRYPT_BENCHMARK) wolfCrypt_Init(); +#ifdef WOLFSSL_SEC_QORIQ + /* test.c and benchmark.c take their devId from WC_USE_DEVID, which + * sec_qoriq.h sets when the port is enabled. */ + secRet = wc_SecQoriqInit(); + if (secRet == 0) { + wolfBoot_printf("QorIQ SEC: enabled, devId 0x%x\r\n", + (unsigned int)WOLFSSL_SEC_QORIQ_DEVID); + } + else { + wolfBoot_printf("QorIQ SEC: init failed (%d), software only\r\n", + secRet); + } +#endif + #ifdef WOLFCRYPT_TEST wolfBoot_printf("\r\nRunning wolfCrypt tests...\r\n"); wolfcrypt_test(NULL); @@ -177,6 +218,25 @@ void main(void) wolfBoot_printf("Benchmarks complete.\r\n\r\n"); #endif +#ifdef WOLFSSL_SEC_QORIQ + /* Report what actually reached the engine: a passing test proves nothing + * about offload, since every unhandled case falls back to software. */ + d = wc_SecQoriqGetDev(); + if (d != NULL) { + wolfBoot_printf("SEC offload counters:\r\n"); + wolfBoot_printf(" jobs submitted : %u\r\n", + (unsigned int)d->jobCount); + wolfBoot_printf(" hash seen %u offloaded %u\r\n", + (unsigned int)d->cbHashCount, (unsigned int)d->cbHashOffload); + wolfBoot_printf(" cipher seen %u offloaded %u\r\n", + (unsigned int)d->cbCipherCount, (unsigned int)d->cbCipherOffload); + wolfBoot_printf(" pk seen %u offloaded %u\r\n", + (unsigned int)d->cbPkCount, (unsigned int)d->cbPkOffload); + wolfBoot_printf(" seed seen %u\r\n", + (unsigned int)d->cbSeedCount); + } +#endif + wolfCrypt_Cleanup(); #endif diff --git a/test-app/wolfcrypt_support.c b/test-app/wolfcrypt_support.c index 5a3e52daea..6342e7318c 100644 --- a/test-app/wolfcrypt_support.c +++ b/test-app/wolfcrypt_support.c @@ -44,7 +44,8 @@ extern volatile uint64_t HAL_time_ms; #elif defined(TARGET_lpc55s69) extern volatile uint64_t SysTick_time_ms; -#elif defined(TARGET_nxp_t2080) || defined(TARGET_nxp_t1024) +#elif defined(TARGET_nxp_t2080) || defined(TARGET_nxp_t1024) || \ + defined(TARGET_nxp_t1040) /* PPC time base register for accurate timing (e6500). */ static uint32_t ppc_tb_hz = 0; static unsigned long long ppc_start_ticks = 0; @@ -77,7 +78,9 @@ #endif volatile uint32_t *rcwsr0 = (volatile uint32_t *)(ccsr + 0xE0100UL); uint32_t plat_ratio = ((*rcwsr0) >> 25) & 0x1FU; - #if defined(BOARD_NAII_68PPC2) || defined(TARGET_nxp_t1024) + #if defined(BOARD_NAII_68PPC2) || defined(TARGET_nxp_t1024) || \ + defined(TARGET_nxp_t1040) + /* T10xx boards run a 100 MHz SYSCLK; see SYS_CLK in hal/nxp_t10xx.c */ uint32_t sys_clk = 100000000; /* 100 MHz */ #else uint32_t sys_clk = 66666667; /* 66.66 MHz */ @@ -147,7 +150,8 @@ unsigned long my_time(unsigned long* timer) unsigned long t = (unsigned long)(SysTick_time_ms / 1000); if (timer) *timer = t; return t; -#elif defined(TARGET_nxp_t2080) || defined(TARGET_nxp_t1024) +#elif defined(TARGET_nxp_t2080) || defined(TARGET_nxp_t1024) || \ + defined(TARGET_nxp_t1040) if (ppc_tb_hz == 0) ppc_tb_hz = ppc_get_timebase_hz(); { @@ -191,7 +195,8 @@ double current_time(int reset) #elif defined(TARGET_lpc55s69) (void)reset; return (double)SysTick_time_ms / 1000.0; -#elif defined(TARGET_nxp_t2080) || defined(TARGET_nxp_t1024) +#elif defined(TARGET_nxp_t2080) || defined(TARGET_nxp_t1024) || \ + defined(TARGET_nxp_t1040) if (ppc_tb_hz == 0) ppc_tb_hz = ppc_get_timebase_hz(); if (reset)