diff --git a/.github/workflows/trustzone-emulator-tests.yml b/.github/workflows/trustzone-emulator-tests.yml index 6602a45c79..a30753da05 100644 --- a/.github/workflows/trustzone-emulator-tests.yml +++ b/.github/workflows/trustzone-emulator-tests.yml @@ -54,7 +54,7 @@ jobs: make clean distclean cp config/examples/stm32h5-tz-psa.config .config make - m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 300 + m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 600 - name: Clean and build test with DICE attestation + OTP (stm32h5) run: | @@ -64,4 +64,4 @@ jobs: make -C tools/keytools/otp TARGET=stm32h5 otp-keystore-primer.bin otp-keystore-gen ./tools/keytools/otp/otp-keystore-gen m33mu tools/keytools/otp/otp-keystore-primer.bin --persist --timeout 10 || true - m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 300 --persist + m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 600 --persist diff --git a/config/examples/stm32h5-no-tz.config b/config/examples/stm32h5-no-tz.config new file mode 100644 index 0000000000..6629d80b48 --- /dev/null +++ b/config/examples/stm32h5-no-tz.config @@ -0,0 +1,34 @@ +ARCH?=ARM +TZEN?=0 +TARGET?=stm32h5 +SIGN?=ECC256 +HASH?=SHA256 +DEBUG?=0 +VTOR?=1 +CORTEX_M0?=0 +CORTEX_M33?=1 +NO_ASM?=0 +NO_MPU=1 +EXT_FLASH?=0 +SPI_FLASH?=0 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=1 +WOLFBOOT_VERSION?=1 +V?=0 +SPMATH?=1 +RAM_CODE?=0 +DUALBANK_SWAP?=0 +WOLFBOOT_PARTITION_SIZE?=0xA0000 +#Double sector size to fit header in ML-DSA-87 +WOLFBOOT_SECTOR_SIZE?=0x4000 +WOLFBOOT_KEYVAULT_ADDRESS?=0x0C040000 +WOLFBOOT_KEYVAULT_SIZE?=0x1C000 +WOLFBOOT_NSC_ADDRESS?=0x0C05C000 +WOLFBOOT_NSC_SIZE?=0x4000 +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08100000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x081A0000 +FLAGS_HOME=0 +DISABLE_BACKUP=0 +IMAGE_HEADER_SIZE?=1024 +ARMORED=1 diff --git a/hal/stm32_tz.c b/hal/stm32_tz.c index d7b67d58a5..83309fc8a9 100644 --- a/hal/stm32_tz.c +++ b/hal/stm32_tz.c @@ -311,7 +311,7 @@ void hal_tz_sau_init(void) WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE - 1, 0); /* Non-secure RAM region */ - sau_init_region(2, 0x20050000, 0x2008FFFF, 0); + sau_init_region(2, 0x20050000, 0x2009FFFF, 0); /* Non-secure: internal peripherals */ sau_init_region(3, 0x40000000, 0x4FFFFFFF, 0); diff --git a/include/image.h b/include/image.h index 51c8ba9ad5..6f9b5924b8 100644 --- a/include/image.h +++ b/include/image.h @@ -444,6 +444,7 @@ static void __attribute__((noinline)) wolfBoot_image_clear_signature_ok( asm volatile("bne hnope"); \ /* Repeat memcmp call */ \ compare_res = XMEMCMP(digest, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE); \ + compare_res; \ /* Redundant checks that ensure the function actually returned 0 */ \ asm volatile("cmp r0, #0":::"cc"); \ asm volatile("cmp r0, #0":::"cc"); \ diff --git a/include/loader.h b/include/loader.h index 167d9b0e5b..e5613a1347 100644 --- a/include/loader.h +++ b/include/loader.h @@ -32,19 +32,19 @@ extern "C" { #define ED25519_IMAGE_SIGNATURE_SIZE (64) #define ED448_IMAGE_SIGNATURE_SIZE (114) -#if defined(WOLFBOOT_SIGN_ECC256) || defined(WOLFBOOT_SECONDARY_SIGN_ECC256) +#if defined(WOLFBOOT_SIGN_ECC256) || defined(WOLFBOOT_SIGN_SECONDARY_ECC256) #define ECC_IMAGE_SIGNATURE_SIZE (64) -#elif defined(WOLFBOOT_SIGN_ECC384) || defined(WOLFBOOT_SECONDARY_SIGN_ECC384) +#elif defined(WOLFBOOT_SIGN_ECC384) || defined(WOLFBOOT_SIGN_SECONDARY_ECC384) #define ECC_IMAGE_SIGNATURE_SIZE (96) -#elif defined(WOLFBOOT_SIGN_ECC521) || defined(WOLFBOOT_SECONDARY_SIGN_ECC521) +#elif defined(WOLFBOOT_SIGN_ECC521) || defined(WOLFBOOT_SIGN_SECONDARY_ECC521) #define ECC_IMAGE_SIGNATURE_SIZE (132) #endif -#if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SECONDARY_SIGN_RSA2048) +#if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) #define RSA_IMAGE_SIGNATURE_SIZE (256) -#elif defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SECONDARY_SIGN_RSA3072) +#elif defined(WOLFBOOT_SIGN_RSA3072) || defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) #define RSA_IMAGE_SIGNATURE_SIZE (384) -#elif defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SECONDARY_SIGN_RSA4096) +#elif defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SIGN_SECONDARY_RSA4096) #define RSA_IMAGE_SIGNATURE_SIZE (512) #endif diff --git a/options.mk b/options.mk index 0ccf841ecb..175206dba0 100644 --- a/options.mk +++ b/options.mk @@ -1,11 +1,21 @@ WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/asn.o USE_GCC?=1 +WOLFBOOT_TEST_FILLER?=0 +WOLFBOOT_TIME_TEST?=0 # Support for Built-in ROT into OTP flash memory ifeq ($(FLASH_OTP_KEYSTORE),1) CFLAGS+=-D"FLASH_OTP_KEYSTORE" endif +ifeq ($(WOLFBOOT_TEST_FILLER),1) + CFLAGS+=-D"WOLFBOOT_TEST_FILLER" +endif + +ifeq ($(WOLFBOOT_TIME_TEST),1) + CFLAGS+=-D"WOLFBOOT_TIME_TEST" +endif + # Support for TPM signature verification ifeq ($(WOLFBOOT_TPM_VERIFY),1) WOLFTPM:=1 @@ -200,7 +210,7 @@ ifeq ($(SIGN),ECC521) ifneq ($(SPMATH),1) STACK_USAGE=11256 else - STACK_USAGE=8288 + STACK_USAGE=8480 endif endif endif diff --git a/src/dice/dice.c b/src/dice/dice.c index a8acf9e4b4..ecdaaf54b7 100644 --- a/src/dice/dice.c +++ b/src/dice/dice.c @@ -491,7 +491,7 @@ static int wolfboot_dice_fixup_priv(uint8_t *priv, size_t priv_len) ret = mp_mod(&k, &order, &mod); } if (ret == MP_OKAY && mp_iszero(&mod) == MP_YES) { - ret = mp_set_int(&mod, 1); + ret = mp_set(&mod, 1); } if (ret == MP_OKAY) { XMEMSET(priv, 0, priv_len); diff --git a/src/image.c b/src/image.c index d1f2c6dcc3..7c11d06715 100644 --- a/src/image.c +++ b/src/image.c @@ -2183,6 +2183,7 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) if (SIG_OK(img)) { uint8_t *stored_secondary_signature; uint16_t stored_secondary_signature_size; + uint16_t expected_secondary_signature_size = 0; /* Invalidate the signature_ok flag */ wolfBoot_image_clear_signature_ok(img); /* Load the pubkey hint for the secondary key */ @@ -2199,6 +2200,37 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) CONFIRM_MASK_VALID(image_part, key_mask); stored_secondary_signature_size = get_header(img, HDR_SECONDARY_SIGNATURE, &stored_secondary_signature); + if (stored_secondary_signature_size == 0 || + stored_secondary_signature == NULL) { + return -1; + } +#if defined(WOLFBOOT_SIGN_SECONDARY_ED25519) + expected_secondary_signature_size = ED25519_IMAGE_SIGNATURE_SIZE; +#elif defined(WOLFBOOT_SIGN_SECONDARY_ED448) + expected_secondary_signature_size = ED448_IMAGE_SIGNATURE_SIZE; +#elif defined (WOLFBOOT_SIGN_SECONDARY_RSA2048) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSA3072) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSA4096) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSA2048ENC) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSA3072ENC) || \ + defined (WOLFBOOT_SIGN_SECONDARY_RSA4096ENC) + expected_secondary_signature_size = RSA_IMAGE_SIGNATURE_SIZE; +#elif defined (WOLFBOOT_SIGN_SECONDARY_ECC256) || \ + defined (WOLFBOOT_SIGN_SECONDARY_ECC384) || \ + defined (WOLFBOOT_SIGN_SECONDARY_ECC521) + expected_secondary_signature_size = ECC_IMAGE_SIGNATURE_SIZE; +#elif defined(WOLFBOOT_SIGN_SECONDARY_LMS) + expected_secondary_signature_size = LMS_IMAGE_SIGNATURE_SIZE; +#elif defined(WOLFBOOT_SIGN_SECONDARY_XMSS) + expected_secondary_signature_size = XMSS_IMAGE_SIGNATURE_SIZE; +#elif defined(WOLFBOOT_SIGN_SECONDARY_ML_DSA) + expected_secondary_signature_size = ML_DSA_IMAGE_SIGNATURE_SIZE; +#endif + if (expected_secondary_signature_size == 0 || + stored_secondary_signature_size != + expected_secondary_signature_size) { + return -1; + } wolfBoot_printf("Verification of hybrid signature\n"); wolfBoot_verify_signature_secondary(key_slot, img, stored_secondary_signature); diff --git a/test-app/ARM-stm32h5-ns.ld b/test-app/ARM-stm32h5-ns.ld index 82000cfd0e..cef93e419c 100644 --- a/test-app/ARM-stm32h5-ns.ld +++ b/test-app/ARM-stm32h5-ns.ld @@ -1,7 +1,7 @@ MEMORY { FLASH (rx) : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ - RAM (rwx) : ORIGIN = 0x20050000, LENGTH = 0x40000 + RAM (rwx) : ORIGIN = 0x20050000, LENGTH = 0x50000 } SECTIONS diff --git a/test-app/ARM-stm32h5.ld b/test-app/ARM-stm32h5.ld index 88e7749383..419362232c 100644 --- a/test-app/ARM-stm32h5.ld +++ b/test-app/ARM-stm32h5.ld @@ -1,7 +1,7 @@ MEMORY { FLASH (rx) : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ - RAM (rwx) : ORIGIN = 0x30000000, LENGTH = 64K /* Run in lowmem */ + RAM (rwx) : ORIGIN = 0x30000000, LENGTH = 256K } SECTIONS diff --git a/test-app/Makefile b/test-app/Makefile index e978a8fefb..f0f1bd0878 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -289,10 +289,12 @@ ifeq ($(TARGET),stm32h5) LDFLAGS+=-Wl,-gc-sections -Wl,-Map=image.map CFLAGS+=-I.. APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET).o - ifeq ($(FLASH_OTP_KEYSTORE),1) - APP_OBJS+=../src/flash_otp_keystore.o - else - APP_OBJS+=../src/keystore.o + ifneq ($(SIGN),NONE) + ifeq ($(FLASH_OTP_KEYSTORE),1) + APP_OBJS+=../src/flash_otp_keystore.o + else + APP_OBJS+=../src/keystore.o + endif endif endif @@ -330,7 +332,9 @@ endif ifeq ($(TARGET),va416x0) APP_OBJS+=$(SDK_OBJS) LSCRIPT_TEMPLATE=ARM-va416x0.ld - APP_OBJS+=../src/keystore.o + ifneq ($(SIGN),NONE) + APP_OBJS+=../src/keystore.o + endif endif ifeq ($(TARGET),sim) diff --git a/test-app/app_stm32h5.c b/test-app/app_stm32h5.c index 544181105d..68c1758a0b 100644 --- a/test-app/app_stm32h5.c +++ b/test-app/app_stm32h5.c @@ -31,7 +31,9 @@ #include "hal/stm32h5.h" #include "uart_drv.h" #include "wolfboot/wolfboot.h" +#ifndef WOLFBOOT_NO_SIGN #include "keystore.h" +#endif #include "target.h" #ifdef WOLFBOOT_TPM @@ -76,9 +78,20 @@ static int uart_poll(void); #define LED_BOOT_PIN (4) /* PG4 - Nucleo - Red Led */ #define LED_USR_PIN (0) /* PB0 - Nucleo - Green Led */ #define LED_EXTRA_PIN (4) /* PF4 - Nucleo - Orange Led */ +#define BOOT_TIME_PIN (13) /* PA13 - scope trigger */ + +#ifdef WOLFBOOT_TEST_FILLER +#define FILLER_SIZE (64 * 1024) +static volatile uint8_t filler_data[FILLER_SIZE] = { 0x01, 0x02, 0x03 }; +#endif #define NVIC_USART3_IRQN (60) +#ifndef GPIOA_MODER +#define GPIOA_MODER (*(volatile uint32_t *)(GPIOA_BASE + 0x00)) +#define GPIOA_PUPDR (*(volatile uint32_t *)(GPIOA_BASE + 0x0C)) +#define GPIOA_BSRR (*(volatile uint32_t *)(GPIOA_BASE + 0x18)) +#endif /* SysTick */ static uint32_t cpu_freq = 250000000; @@ -119,6 +132,21 @@ static void boot_led_on(void) GPIOG_BSRR |= (1 << (pin)); } +void boot_time_pin_on_early(void) +{ + uint32_t reg; + uint32_t pin = BOOT_TIME_PIN; + + RCC_AHB2ENR_CLOCK_ER |= GPIOA_AHB2ENR1_CLOCK_ER; + /* Delay after an RCC peripheral clock enabling */ + reg = RCC_AHB2ENR_CLOCK_ER; + + reg = GPIOA_MODER & ~(0x03 << (pin * 2)); + GPIOA_MODER = reg | (1 << (pin * 2)); + GPIOA_PUPDR &= ~(0x03 << (pin * 2)); + GPIOA_BSRR = (1 << (pin)); +} + static void boot_led_off(void) { GPIOG_BSRR |= (1 << (LED_BOOT_PIN + 16)); @@ -542,6 +570,7 @@ static int cmd_info(const char *args) printf("No image in update partition.\r\n"); } +#ifndef WOLFBOOT_NO_SIGN printf("\r\n"); printf("Bootloader OTP keystore information\r\n"); printf("====================================\r\n"); @@ -559,6 +588,10 @@ static int cmd_info(const char *args) printf(" ====================================\r\n "); print_hex(keybuf, size, 0); } +#else + printf("\r\n"); + printf("Signing disabled (SIGN=NONE)\r\n"); +#endif return 0; } @@ -1295,6 +1328,10 @@ void main(void) /* Turn on boot LED */ boot_led_on(); +#ifdef WOLFBOOT_TEST_FILLER + filler_data[FILLER_SIZE - 1] = 0xAA; +#endif + /* Enable SysTick */ systick_enable(); diff --git a/test-app/app_stm32h7.c b/test-app/app_stm32h7.c index bcf886e3d9..c7e24435a1 100644 --- a/test-app/app_stm32h7.c +++ b/test-app/app_stm32h7.c @@ -363,8 +363,10 @@ void uart_print(const char *s) } } -#define FILLER_SIZE (100 * 1024) +#ifdef WOLFBOOT_TEST_FILLER +#define FILLER_SIZE (64 * 1024) static volatile uint8_t filler_data[FILLER_SIZE] = { 0x01, 0x02, 0x03 }; +#endif void main(void) { @@ -377,7 +379,9 @@ void main(void) if (FIRMWARE_A) ld3_write(LED_INIT); +#ifdef WOLFBOOT_TEST_FILLER filler_data[FILLER_SIZE - 1] = 0xAA; +#endif /* LED Indicator of successful UART initialization. SUCCESS = ON, FAIL = OFF */ if (uart_setup(115200) < 0) ld2_write(LED_OFF); diff --git a/test-app/emu-test-apps/mcxw71/target.ld.in b/test-app/emu-test-apps/mcxw71/target.ld.in index 94ac011dad..009d8d6cda 100644 --- a/test-app/emu-test-apps/mcxw71/target.ld.in +++ b/test-app/emu-test-apps/mcxw71/target.ld.in @@ -23,7 +23,7 @@ MEMORY { FLASH (rx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x000FFF00 - RAM (rwx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x0001C000 + RAM (rwx) : ORIGIN = 0x20010000, LENGTH = 0x00006000 } _estack = ORIGIN(RAM) + LENGTH(RAM); diff --git a/test-app/emu-test-apps/nrf5340/target.ld.in b/test-app/emu-test-apps/nrf5340/target.ld.in index 465647c526..80e71491b4 100644 --- a/test-app/emu-test-apps/nrf5340/target.ld.in +++ b/test-app/emu-test-apps/nrf5340/target.ld.in @@ -23,7 +23,7 @@ MEMORY { FLASH (rx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x000FFF00 - RAM (rwx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x00080000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00080000 } _estack = ORIGIN(RAM) + LENGTH(RAM); diff --git a/test-app/emu-test-apps/stm32h563/target.ld.in b/test-app/emu-test-apps/stm32h563/target.ld.in index aa2ea51211..3d33737e0c 100644 --- a/test-app/emu-test-apps/stm32h563/target.ld.in +++ b/test-app/emu-test-apps/stm32h563/target.ld.in @@ -23,7 +23,7 @@ MEMORY { FLASH (rx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x001FFF00 - RAM (rwx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x000A0000 + RAM (rwx) : ORIGIN = 0x20050000, LENGTH = 0x00050000 } _estack = ORIGIN(RAM) + LENGTH(RAM); diff --git a/test-app/emu-test-apps/stm32h563/target_v8.ld b/test-app/emu-test-apps/stm32h563/target_v8.ld index 5760374f0b..adfb7dc2d3 100644 --- a/test-app/emu-test-apps/stm32h563/target_v8.ld +++ b/test-app/emu-test-apps/stm32h563/target_v8.ld @@ -23,7 +23,7 @@ MEMORY { FLASH (rx) : ORIGIN = 0x8060100, LENGTH = 0x001FFF00 - RAM (rwx) : ORIGIN = 0x8060100, LENGTH = 0x000A0000 + RAM (rwx) : ORIGIN = 0x20050000, LENGTH = 0x00050000 } _estack = ORIGIN(RAM) + LENGTH(RAM); diff --git a/test-app/emu-test-apps/stm32l552/target.ld.in b/test-app/emu-test-apps/stm32l552/target.ld.in index 68c3f6e1ce..cd0f42d2a1 100644 --- a/test-app/emu-test-apps/stm32l552/target.ld.in +++ b/test-app/emu-test-apps/stm32l552/target.ld.in @@ -23,7 +23,7 @@ MEMORY { FLASH (rx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x0007FF00 - RAM (rwx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x00040000 + RAM (rwx) : ORIGIN = 0x20020000, LENGTH = 0x00020000 } _estack = ORIGIN(RAM) + LENGTH(RAM); diff --git a/test-app/emu-test-apps/stm32u585/target.ld.in b/test-app/emu-test-apps/stm32u585/target.ld.in index 38688d984f..7805815ead 100644 --- a/test-app/emu-test-apps/stm32u585/target.ld.in +++ b/test-app/emu-test-apps/stm32u585/target.ld.in @@ -23,7 +23,7 @@ MEMORY { FLASH (rx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x001FFF00 - RAM (rwx) : ORIGIN = @FLASH_ORIGIN@, LENGTH = 0x000C0000 + RAM (rwx) : ORIGIN = 0x20020000, LENGTH = 0x00020000 } _estack = ORIGIN(RAM) + LENGTH(RAM); diff --git a/test-app/emu-test-apps/test.sh b/test-app/emu-test-apps/test.sh index a6b5ec3a87..8aa08b499b 100755 --- a/test-app/emu-test-apps/test.sh +++ b/test-app/emu-test-apps/test.sh @@ -133,6 +133,7 @@ UPDATE_OFFSET_HEX=$(printf "0x%x" "$UPDATE_OFFSET") get_check_config_val() { local key="$1" local val + make -C "$WOLFBOOT_ROOT" include/target.h >/dev/null make -C "$WOLFBOOT_ROOT/tools/check_config" check_config RAM_CODE=0 >/dev/null val="$("$WOLFBOOT_ROOT/tools/check_config/check_config" | grep -m1 "^${key}" | sed 's/.*: *//')" [[ -n "$val" ]] || die "missing ${key} from tools/check_config output" @@ -187,6 +188,7 @@ REBOOT_TIMEOUT="${REBOOT_TIMEOUT:-10}" write_target_ld() { local tpl="" local base="" + local emu_tpl="" local addr local size addr=$((BOOT_ADDR + IMAGE_HEADER_SIZE)) @@ -201,6 +203,13 @@ write_target_ld() { *) die "unsupported TARGET for linker template: $TARGET" ;; esac + emu_tpl="$EMU_PATH/target.ld.in" + if [[ -f "$emu_tpl" ]]; then + sed -e "s/@FLASH_ORIGIN@/0x$(printf '%x' "$addr")/g" \ + "$emu_tpl" > "$EMU_PATH/target.ld" + return 0 + fi + if [[ "${TZEN}" == "1" && -f "$WOLFBOOT_ROOT/test-app/${base}-ns.ld" ]]; then tpl="$WOLFBOOT_ROOT/test-app/${base}-ns.ld" else diff --git a/test-app/startup_arm.c b/test-app/startup_arm.c index 68e6c37465..ff65084d34 100644 --- a/test-app/startup_arm.c +++ b/test-app/startup_arm.c @@ -63,6 +63,12 @@ extern void main(void); void isr_reset(void) { register unsigned int *src, *dst; + +#if defined(WOLFBOOT_TIME_TEST) && defined(TARGET_stm32h5) + extern void boot_time_pin_on_early(void); + boot_time_pin_on_early(); +#endif + src = (unsigned int *) &_stored_data; dst = (unsigned int *) &_start_data; while (dst < (unsigned int *)&_end_data) { diff --git a/tools/check_config/Makefile b/tools/check_config/Makefile index 342d3b2c8a..1bfa759ffc 100644 --- a/tools/check_config/Makefile +++ b/tools/check_config/Makefile @@ -3,6 +3,7 @@ include ../config.mk include ../../options.mk +HOSTCC?=gcc CFLAGS+=-I. -I../../ -I../../include .PHONY: run clean @@ -12,11 +13,11 @@ run: $(Q)$(MAKE) check_config check_config: check_config.o - $(Q)gcc -o $@ $^ $(CFLAGS) + $(Q)$(HOSTCC) -o $@ $^ $(CFLAGS) $(Q)./$@ %.o:%.c - $(Q)gcc -c -o $@ $^ $(CFLAGS) + $(Q)$(HOSTCC) -c -o $@ $^ $(CFLAGS) clean: $(Q)rm -f check_config *.o diff --git a/tools/scripts/benchmark.sh b/tools/scripts/benchmark.sh index a76d60ce6f..50638dc243 100755 --- a/tools/scripts/benchmark.sh +++ b/tools/scripts/benchmark.sh @@ -1,34 +1,12 @@ #!/bin/bash # function run_on_board() { - # GPIO2: RST - # GPIO3: BOOT (input) + # GPIO2 (pin 27): RST (output) -- connected to STM32H5 NRST + # GPIO4 (pin 16): BOOT (input) -- connected to STM32H5 PA14 - if ! (st-flash reset &>/dev/null); then - echo -n "No data." - else + openocd -f board/st_nucleo_h5.cfg -c "reset_config connect_assert_srst; init; program wolfboot.bin 0x08000000; program test-app/image_v1_signed.bin 0x08060000; shutdown" &>/dev/null sleep 1 - st-flash --connect-under-reset write factory.bin 0x8000000 &>/dev/null - sleep .2 - echo "2" > /sys/class/gpio/export 2>/dev/null - echo "out" > /sys/class/gpio/gpio2/direction - echo "1" > /sys/class/gpio/gpio2/value # Release reset - echo "0" > /sys/class/gpio/gpio2/value # Keep reset low - sleep 1 - echo -n " | " - echo "1" > /sys/class/gpio/gpio2/value # Release reset - START=`date +%s.%N` - while (test `cat /sys/class/gpio/gpio4/value` -eq 0); do - sleep .01 - done - while (test `cat /sys/class/gpio/gpio4/value` -eq 0); do - sleep .01 - done - END=`date +%s.%N` - echo "scale=3; $END/1 - $START/1 "| bc - echo "in" > /sys/class/gpio/gpio2/direction - echo "2" >/sys/class/gpio/unexport 2>/dev/null - fi + python3 tools/scripts/boot-time.py } function set_benchmark { @@ -37,16 +15,16 @@ function set_benchmark { CONFIG=$@ # Name echo -n "| " - echo -n $NAME + echo -n "$NAME" echo -n " | " # Configuration echo -n $CONFIG | tr -d '\n' echo -n " | " make clean &>/dev/null make keysclean &>/dev/null - make $@ &>/dev/null || make $@ factory.bin - make $@ stack-usage &>/dev/null - make $@ image-header-size &>/dev/null + make WOLFBOOT_TEST_FILLER=1 WOLFBOOT_TIME_TEST=1 $@ &>/dev/null + make WOLFBOOT_TEST_FILLER=1 WOLFBOOT_TIME_TEST=1 $@ stack-usage &>/dev/null + make WOLFBOOT_TEST_FILLER=1 WOLFBOOT_TIME_TEST=1 $@ image-header-size &>/dev/null # Bootloader size echo -n `ls -l wolfboot.bin | cut -d " " -f 5 | tr -d '\n'` echo -n " | " @@ -55,20 +33,21 @@ function set_benchmark { echo -n " | " # Image header size cat .image_header_size | tr -d '\n' + # Application size + echo -n " | " + echo -n `ls -l test-app/image.bin | cut -d " " -f 5 | tr -d '\n'` # Boot time + echo -n " | " run_on_board 2>&1 | tr -d '\n' echo " |" } -echo "4" > /sys/class/gpio/export 2>/dev/null -echo "2" > /sys/class/gpio/unexport 2>/dev/null make keytools &>/dev/null -cp config/examples/stm32h7.config .config -echo "in" > /sys/class/gpio/gpio4/direction -# Output benchmark results in a Markdown table -echo "| Name | Configuration | Bootloader size | Stack size | Image header size | Boot time |" -echo "|------|---------------|-----------------|------------|-------------------|-----------|" +cp config/examples/stm32h5-no-tz.config .config +# Output benchmark results in a Markdown table +echo "| Name | Configuration | Bootloader size | Stack size | Image header size | Application size | Boot time |" +echo "|------|---------------|-----------------|------------|-------------------|------------------|-----------|" set_benchmark "SHA2 only" SIGN=NONE set_benchmark "SHA384 only" SIGN=NONE HASH=SHA384 @@ -97,4 +76,3 @@ set_benchmark "LMS 1-10-8" SIGN=LMS LMS_LEVELS=1 LMS_HEIGHT=10 LMS_WINTERNITZ=8 set_benchmark "XMSS-SHA2_10_256'" XMSS_PARAMS='XMSS-SHA2_10_256' SIGN=XMSS IMAGE_SIGNATURE_SIZE=2500 IMAGE_HEADER_SIZE=8192 set_benchmark "ML_DSA-65 hybrid with ECDSA384" SIGN=ML_DSA ML_DSA_LEVEL=3 IMAGE_SIGNATURE_SIZE=3309 IMAGE_HEADER_SIZE=8192 SIGN_SECONDARY=ECC384 WOLFBOOT_UNIVERSAL_KEYSTORE=1 set_benchmark "ML_DSA-87 hybrid with ECDSA521" SIGN=ML_DSA ML_DSA_LEVEL=5 IMAGE_SIGNATURE_SIZE=4627 IMAGE_HEADER_SIZE=12288 SIGN_SECONDARY=ECC521 WOLFBOOT_UNIVERSAL_KEYSTORE=1 - diff --git a/tools/scripts/boot-time.py b/tools/scripts/boot-time.py new file mode 100644 index 0000000000..835e806537 --- /dev/null +++ b/tools/scripts/boot-time.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +import select +import time +from datetime import datetime, timedelta + +import gpiod +from gpiod.line import Direction, Edge, Bias, Value + +CHIP = "/dev/gpiochip0" +GPIO2 = 2 +GPIO4 = 4 + +HOLD_LOW_S = 0.5 +DEBOUNCE_MS_GPIO4 = 0 # set e.g. to 100 if you want + +def now(): + return datetime.now().strftime("%H:%M:%S.%f")[:-3] + + +def value_to_01(v: Value) -> int: + return 1 if v == Value.ACTIVE else 0 + +def get_val(req, off: int) -> int: + return value_to_01(req.get_value(off)) + +def dump_vals(req, offs): + parts = [] + for o in offs: + try: + parts.append(f"{o}={get_val(req, o)}") + except Exception as e: + parts.append(f"{o}=? ({e})") + return ", ".join(parts) + +def drain_events(req): + try: + req.read_edge_events() + except Exception as e: + print(f"Warning: failed to read edge events: {e}") + +def main(): + + cfg_initial = { + (GPIO2,): gpiod.LineSettings( + direction=Direction.OUTPUT, + output_value=Value.INACTIVE, # 0 + ), + (GPIO4,): gpiod.LineSettings( + direction=Direction.INPUT, + bias=Bias.PULL_DOWN, + edge_detection=Edge.RISING, + debounce_period=timedelta(milliseconds=DEBOUNCE_MS_GPIO4), + ), + } + + with gpiod.request_lines(CHIP, consumer="release-to-edge", config=cfg_initial) as req: + + # Ensure we don't accidentally read an earlier GPIO4 edge + #drain_events(req) + + time.sleep(HOLD_LOW_S) + + + # Reconfigure GPIO2 to input (no edge needed on GPIO2) + cfg_release = { + (GPIO2,): gpiod.LineSettings( + direction=Direction.INPUT, + bias=Bias.DISABLED, # keep bias none (you said bias not working anyway) + edge_detection=Edge.NONE, + ), + (GPIO4,): None, # unchanged + } + + # Take a best-effort timestamp around the reconfigure call. + # Using midpoint reduces the error to roughly half of the call duration. + t_before = time.monotonic_ns() + req.reconfigure_lines(cfg_release) + t_after = time.monotonic_ns() + t0 = (t_before + t_after) // 2 + + + t4 = None + while t4 is None: + select.select([req.fd], [], []) + for ev in req.read_edge_events(): + if ev.line_offset == GPIO4 and ev.event_type == gpiod.EdgeEvent.Type.RISING_EDGE: + t4 = ev.timestamp_ns + break + + delta_ns = t4 - t0 + print(f"{delta_ns/1e6:.3f} ms") + +if __name__ == "__main__": + main()