From 52a1b085e09d31dc6279926d3bc89ca56d79d82b Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Tue, 18 Aug 2026 10:16:44 +0200 Subject: [PATCH] libwolfboot: scrub NVM_CACHE without pulling in wolfCrypt Widening the misc.c include guard with NVM_FLASH_WRITEONCE made this file include and in every such build, including the two that cannot resolve them: tools/check_config has no wolfSSL include path, and the STM32Cube test-app has no stm32wbxx_hal_conf.h. Both fail to compile. Scrub with a local volatile byte loop instead and put the guard back. That also suits the RAMFUNCTION callers better, since ForceZero() lives in flash and must not be called while flash is being programmed. --- src/libwolfboot.c | 35 ++++++++++++++++++++++++++--------- tools/unit-tests/Makefile | 3 ++- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 3fa096a3..3c69f69c 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -186,11 +186,11 @@ static uint32_t ext_cache; /* EXT_ENCRYPTED is listed because the key-handling code below calls * ForceZero() unconditionally, including from the test-app build of this file, - * where __WOLFBOOT is not defined. NVM_FLASH_WRITEONCE is listed for the - * same reason: the partition-trailer read-modify-write helpers scrub - * NVM_CACHE with ForceZero() in the test-app build too. */ -#if defined(__WOLFBOOT) || defined(UNIT_TEST) || defined(EXT_ENCRYPTED) || \ - defined(NVM_FLASH_WRITEONCE) + * where __WOLFBOOT is not defined. NVM_FLASH_WRITEONCE is deliberately NOT + * listed: the partition-trailer helpers scrub with nvm_cache_scrub(), so the + * NVM path stays free of the wolfSSL headers that tools/check_config and the + * STM32Cube test-app cannot resolve. */ +#if defined(__WOLFBOOT) || defined(UNIT_TEST) || defined(EXT_ENCRYPTED) #define WOLFSSL_MISC_INCLUDED /* allow misc.c code to be inlined */ #include #include @@ -255,6 +255,23 @@ static const uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL; #include static uint8_t NVM_CACHE[NVM_CACHE_SIZE] XALIGNED(16); static int nvm_cached_sector = 0; + +/* Scrub the staging buffer without depending on wolfCrypt. ForceZero() + * would drag and + * into every NVM_FLASH_WRITEONCE build of this file, including the two + * that cannot supply them: tools/check_config (no wolfSSL include + * path) and the STM32Cube test-app (no stm32*_hal_conf.h). A volatile + * byte loop is also the right shape for a RAMFUNCTION caller, since + * ForceZero() itself lives in flash and must not be called while the + * flash is being programmed. */ +static void RAMFUNCTION nvm_cache_scrub(void) +{ + volatile uint8_t *p = (volatile uint8_t *)NVM_CACHE; + unsigned int i; + + for (i = 0; i < NVM_CACHE_SIZE; i++) + p[i] = 0; +} static uint8_t get_base_offset(uint8_t *base, uintptr_t off) { return *(uint8_t*)((uintptr_t)base - off); /* ignore array bounds error */ @@ -396,14 +413,14 @@ static int RAMFUNCTION trailer_write(uint8_t part, uintptr_t addr, uint8_t val) /* The staged sector may hold the firmware key/nonce (see * ENCRYPT_CACHE under NVM_FLASH_WRITEONCE): scrub it before * returning, success or not. */ - ForceZero(NVM_CACHE, NVM_CACHE_SIZE); + nvm_cache_scrub(); return ret; } /* Once a copy has been written, erase the older sector */ ret = hal_flash_erase(addr_read, NVM_CACHE_SIZE); nvm_cached_sector = !nvm_cached_sector; - ForceZero(NVM_CACHE, NVM_CACHE_SIZE); + nvm_cache_scrub(); return ret; } @@ -433,12 +450,12 @@ static int RAMFUNCTION partition_magic_write(uint8_t part, uintptr_t addr) /* The staged sector may hold the firmware key/nonce (see * ENCRYPT_CACHE under NVM_FLASH_WRITEONCE): scrub it before * returning, success or not. */ - ForceZero(NVM_CACHE, NVM_CACHE_SIZE); + nvm_cache_scrub(); return ret; } nvm_cached_sector = !nvm_cached_sector; ret = hal_flash_erase(addr_read, WOLFBOOT_SECTOR_SIZE); - ForceZero(NVM_CACHE, NVM_CACHE_SIZE); + nvm_cache_scrub(); return ret; } #ifdef __CCRX__ diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index ab7b6e99..9ccf567a 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -975,7 +975,8 @@ unit-stm32u5-write: unit-stm32u5-write.c stm32u5_write_extract.h # owns NVM_CACHE, stages a key-bearing sector image, and stubs the # flash layer; after each call the whole buffer must be zeroed. nvm_cache_scrub_extract.h: ../../src/libwolfboot.c - sed -n '/^static int RAMFUNCTION trailer_write(/,/^}/p' $< > $@ + sed -n '/^static void RAMFUNCTION nvm_cache_scrub(/,/^}/p' $< > $@ + sed -n '/^static int RAMFUNCTION trailer_write(/,/^}/p' $< >> $@ sed -n '/^static int RAMFUNCTION partition_magic_write(/,/^}/p' $< >> $@ unit-nvm-cache-scrub: unit-nvm-cache-scrub.c nvm_cache_scrub_extract.h