Commit Graph

3699 Commits (9f456bf86454935237efd641f5e16b3087a325f8)

Author SHA1 Message Date
Daniele Lacamera 9f456bf864 F-9252: fix MPU system-control range end address
Comment said 0xE0000000:0xEFFFFFF (255M) but the system-control
region is 256M, ending at 0xEFFFFFFF.
2026-09-16 12:14:13 +02:00
Daniele Lacamera dcc6c64bd7 unit-tests: pin -std=gnu17 for host test builds
GCC 14+ defaults to gnu23, where glibc string.h defines memchr
and memcpy as _Generic macros that clash with wolfBoot's own
declarations in tests that #include a .c file (unit-string).
gnu17 matches the CI toolchain default.
2026-09-15 18:04:21 +02:00
Daniele Lacamera c1a7d89b2d unit-tests: mock wc_FreeRng for keygen_die
keygen_die() (F-9767) calls wc_FreeRng(); the test mocks
keygen.c's wolfCrypt dependencies one by one and was missing
this one, breaking the unit_tests and test_external_libs jobs.
2026-09-15 18:04:21 +02:00
Daniele Lacamera 4ca67c3063 F-13615: keep TFM_TIMING_RESISTANT for secure-mode fastmath builds
Secure-mode worlds (TZ_PSA/PKCS11/FWTPM/WOLFHSM) process private keys
in software, so a USE_FAST_MATH build of one of them must keep the
timing-resistant TFM path instead of falling back to WC_NO_HARDEN.
The old condition only covered software DICE; FIPS=1 already forces
SPMATH (options.mk M10) and all CMake presets set SPMATH, so no
shipped config changes - this closes the integrator Makefile gap.
WOLFBOOT_DICE_HW stays verify-only (requires WOLFCRYPT_TZ_PSA).
2026-09-15 16:08:57 +02:00
Daniele Lacamera 908d4ec1e3 F-7048: make UDS all-value scan constant-time
buffer_is_all_value() early-exited on the first byte differing from
the target, so the loop trip count leaked the length of the leading
0xFF/0x00 run of the UDS, the DICE root secret read in
hal_uds_derive_key().

Replace the early exit with a volatile |= accumulator over the full
buffer, matching the constant-time compare pattern already used by
image_CT_compare() and the other secret comparisons in the tree.

Verified: gcc -S -O2 shows a straight-line loop body with only the
data-independent i < len branch; arm-none-eabi-gcc (stm32h5 preset)
compiles the file clean.

Reported by Fenrir.
2026-09-15 15:48:15 +02:00
Daniele Lacamera 5f6eb05552 F-6764: scrub passphrase buffer when async ATA command completes
security_command_passphrase() only wiped the static DMA buffer on the
synchronous path; in async mode (ata_security_erase_unit) the
passphrase stayed resident in the file-static buffer for the rest of
the boot, since ata_cmd_complete_async() never scrubbed it.

Add a scrub_buffer flag to the async state, set it when the command
goes in flight (or wipe immediately if it never started), and scrub in
ata_cmd_complete_async() on both the success and task-file-error exits,
once the HBA has retired the command.

Covered by two new unit tests: scrub after async completion and after
an async port error; the in-flight state is asserted unscrubbed.

Reported by Fenrir.
2026-09-15 15:43:11 +02:00
Daniele Lacamera 19d8a42303 F-6765: scrub previous value before overwriting PSA storage
ARM_TEE_PS_SET on an existing object XMEMCPY'd the new value over the
old one without clearing the buffer first, so a SET that stores less
data (or zero data) left the tail of the previous object readable
through ARM_TEE_PS_GET.

Zero the full data area with wc_ForceZero after every validation check
passes and before the copy, matching the DELETE path.

Reported by Fenrir.
2026-09-15 15:35:10 +02:00
Daniele Lacamera b97d94deeb F-9768: rot: scrub NV auth and session state at exit
The TPM NV auth copy and the HMAC session state lived on the
stack until process teardown. Zeroize both at the common exit
label after the TPM device is unloaded, on success and error
paths alike.
2026-09-15 15:21:54 +02:00
Daniele Lacamera 483facf339 F-9767: keygen: free RNG before helper failure exit
keygen_ed25519/ed448/lms/xmss/ml_dsa have the same bypass as
the RSA/ECC helpers: exit() from their cleanup labels skips
main()'s wc_FreeRng(). Route their failure exits through
keygen_die() as well.
2026-09-15 15:19:25 +02:00
Daniele Lacamera a08badf880 F-8008: keygen: free RNG before helper failure exit
keygen_rsa/keygen_ecc exit() from their own cleanup labels,
bypassing main()'s wc_FreeRng() and leaving DRBG state resident.
Add keygen_die() that frees and zeroes the RNG before exit and
use it in the two helpers' failure paths.
2026-09-15 15:14:38 +02:00
Daniele Lacamera b1884b03d7 F-7394: sign: free RNG on RSA-PSS unsupported-hash error
The error path returned before the common wc_FreeRng(), leaving
DRBG state on the stack. Route it through the shared cleanup and
guard the sign call so hash_type/mgf are only used when set.
2026-09-15 15:14:38 +02:00
Daniele Lacamera e38e844381 unit-tests: rename noramboot fallback TCase
The F-12922 test checks fallback to the lower version, but the
TCase was still named "rollback denied" from before the fix,
describing the opposite behavior.
2026-09-15 14:32:18 +02:00
Daniele Lacamera 2c636e9606 nrf5340: add memory clobber to DSB()
The F-12879 fix publishes SHM status with plain C stores before
IPC_TASKS_SEND; without a compiler memory barrier an optimized
build can reorder the stores past the dsb asm. Matches the
existing clobber in imx95_m7.h and stm32g4.h.
2026-09-15 14:32:18 +02:00
Daniele Lacamera efc5753b28 unit-tests: extract NAND_STATUS_* for p1021 erase test
ext_flash_erase() now checks NAND_STATUS_FAIL | NAND_STATUS_WPS
(F-12881), but the sed extraction rule only pulled the command
defines, so the unit_tests CI jobs failed to compile the test.
2026-09-15 14:32:18 +02:00
Daniele Lacamera bad522f654 F-12942: pkcs11: wipe PIN on terminal init failure
pkcs11_crypto_init() tore down the session on failure but left the
pre-populated pkcs11_pin credential in retained bootloader memory
after the handoff. Wipe it in the failure path, same as the deinit
path (F-12114). Regression test in unit-pkcs11-pin-zeroize: login
rejected -> init fails -> every pin byte is zero.
2026-09-15 13:24:14 +02:00
Daniele Lacamera b99847624b F-12879: nrf5340: publish SHM status before signaling IPC
hal_shm_status_set() triggered the IPC event before storing the
magic/status fields, so the peer core could wake on the event, read
stale fields, and wait for a second event that never comes. Store
the fields first, order them with a DSB, then signal; the receiver
pairs it with a DSB after clearing the event, before re-reading the
fields. Not verified on real nRF5340 hardware.
2026-09-15 08:47:28 +02:00
Daniele Lacamera 4e01a45e3b F-12881: p1021: check NAND program/erase status and ECC results
The write/erase loops discarded the JEDEC status byte from MDR and
hal_flash_command ignored the PAR (uncorrectable ECC) and FCT (FCM
timeout) bits, so failed programs, erases and uncorrectable reads
all reported success. Check P/WPS in the status byte and stop the
loop, and fail the command on PAR/FCT. The small-page FCM sequence
now ends with the status command (CM3+RSW) so MDR holds a valid
status like the large-page path; not verified on real P1021
hardware. config_io_pin now uses a single masked store for CPDIR/
CPPAR (F-12880): the clear-then-set pair could drop a concurrent
update to another pin in the same register.

F-12880, F-12881, F-12882
2026-09-15 08:42:58 +02:00
Daniele Lacamera 63f1ce7872 F-12922: do not block fallback to a valid image in wolfBoot_start
The version gate in the retry loop panicked whenever the selected
candidate failed verification and the fallback partition carried a
lower version, even though that image is valid and signed. A single
corrupted higher-version image bricked the device instead of falling
back. The gate only ever fired on the failure path (candidate
selection already prefers the higher version), so remove it; the
TESTING-state anti-rollback check in wolfBoot_dualboot_candidate()
still guards the confirmed-update path.
2026-09-15 08:24:11 +02:00
Daniele Lacamera f0ad5692d2 F-13604: Reset image state on each retry in update_ram fallback
wolfBoot_start() zeroed os_image once, before the retry loop, so the
fallback iteration kept the stale img->hdr of the failed partition and
wolfBoot_open_image_address() (which only adopts load_address when
hdr is NULL) re-verified the wrong image. The external header cache
had the same problem: it kept the first image opened.

memset the struct and invalidate the EXT_FLASH header cache at the
top of each loop iteration, per the documented precondition of
wolfBoot_open_image_address().

Add unit-update-ram-nofixed-noramboot: the non-fixed-partition,
non-RAMBOOT (XIP) layout where load_address varies per retry, with
fallback tests both directions plus candidate-selection checks.
2026-09-15 02:58:57 +02:00
David Garske 8eafe1ef76
Merge pull request #890 from bigbrett/tc4-wolfboot
AURIX TC4xx support
2026-09-14 14:22:21 -07:00
Brett Nicholas 7c88ae7413 add TC4 PVER retry 2026-09-14 10:55:07 -06:00
Brett Nicholas ade42b51fa add TC4 EVER retry 2026-09-14 10:40:31 -06:00
David Garske 0ca05cf9b4 Add m2354 secure and non-secure emulator tests 2026-09-14 18:08:40 +02:00
David Garske b0fe251747 Add Nuvoton NuMaker M2354 Cortex-M23 target with TrustZone 2026-09-14 18:08:40 +02:00
Marco Oliverio 1b99727d4c pic32cz: fix: use the right IMAGE_HEADER_SIZE value
otherwise the VTOR will be underaligned
2026-09-14 17:53:04 +02:00
Brett Nicholas 6d652d444f Support for AURIX TC4xx host and CSRM cores 2026-09-12 09:21:38 -06:00
David Garske bafa907e9a
Merge pull request #873 from danielinux/pkcs11-store-batch-commit
pkcs11 store: Improve Store performance through batch sector commits to Store_Close
2026-09-10 16:14:04 -07:00
David Garske 871ab86dc5
Merge pull request #886 from bigbrett/aurix-makefile-reorg
AURIX makefile housekeeping
2026-09-10 16:13:56 -07:00
Daniele Lacamera ba544022e2 pkcs11 store: cover torn flash ops and require a present, truncated header
The mock abandoned a faulting erase/program whole, so half-written sectors
went untested; it can now tear one part-way and the sweep runs every crash
point at 1/4, 1/2 and 3/4. An empty read must also leave the node in place
with size 8, so a lost or torn header no longer passes as an empty rewrite.
2026-09-10 21:39:18 +02:00
Daniele Lacamera 7919445c62 pkcs11 store: pin the no-fault control in the power-fail test
The crash == ops iteration injects nothing, so it must read back new_p; the
empty/absent branch was letting a silently lost complete rewrite pass. Also
assert the uninjected baseline write lands before measuring against it.
2026-09-10 21:17:52 +02:00
Daniele Lacamera b2d8200dd2 pkcs11 store: restore both mock flash views before each injected power fail
Under MOCK_STALE_CACHE the shadow is the flash array and vault_base only the
CPU's view, so restoring vault_base alone let the power cycle copy the last
iteration's result back: no crash case started from the old generation.
2026-09-10 20:57:53 +02:00
Daniele Lacamera 3d5bebeefe pkcs11 store: tighten power-fail assert, rebase F4 footprint limits
vault_obj_read() now separates "object absent" from a failed read, so the
power-fail test rejects a corrupted vault instead of accepting any negative.
hal_cache_invalidate() shrank 120 -> 44 bytes; the 48 it still costs every
STM32F407 build is folded into the test-size-all limits.
2026-09-10 19:23:57 +02:00
Daniele Lacamera 9b06b907f8 hal: always define hal_cache_invalidate(), implement it on F4 and G4
The weak no-op sat inside NVM_FLASH_WRITEONCE, so pkcs11_store.c failed to
link on the nrf5340/nrf54l TrustZone configs. STM32F4 and STM32G4 enable the
flash instruction/data caches and never reset them, so give them a real one.
2026-09-10 18:42:54 +02:00
Brett Nicholas 678781db39 AURIX tc3 ARCH/TARGET refactor anticipating TC4xx 2026-09-10 10:19:08 -06:00
Daniele Lacamera 42e6dba558 pkcs11 store: invalidate the flash read cache after every commit
The store commits sectors with hal_flash_erase()/hal_flash_write() and
then reads them back through the memory map - sector_ptr(),
cache_get_sector()'s refill, and the raw magic reads in check_vault().
On a part that caches flash reads (STM32 ICACHE) those reads can return
pre-erase bytes. check_vault() is the worst case: a stale magic there
does not merely read wrong, it triggers restore_backup() or a full vault
re-initialisation, losing the token.
2026-09-10 10:45:55 +02:00
Daniele Lacamera 1d3b576f03 pkcs11 store: pin the Open-time durability rule with a power-fail test
Adds power-fail injection to the flash mock and a test that cuts power at
every flash operation of a rewrite window, asserting the object always reads
back as the whole old payload, the whole new payload, or empty. Fails at
op 3 without this fix, passes with it.

unit-pkcs11_store 10/10; full unit-tests suite green.
2026-09-10 09:40:17 +02:00
Daniele Lacamera b9ef442faf pkcs11 store: harden sector cache (eviction, release scrub, open durability)
Three fixes from the 2026-08-31 Fenrir PR review round:

1. cache_get_sector() LRU eviction could pick the header sector (offset 0)
   as the victim, committing it to flash while the batch's payload sectors
   were still only in RAM - a mixed pre/post-batch state that breaks the
   header-last atomic commit point cache_flush_all() relies on. The header
   is now exempt from victim selection; if it is the only cached sector,
   flush the whole batch instead (header-last is then trivial).

2. cache_flush_all() and LRU eviction released a slot by clearing .sector
   without wiping the buffer, so private-key bytes staged by Store_Write
   lingered in secure-world SRAM until the slot was next reused. The single
   staging buffer this cache replaced self-cleaned (the header sector
   overwrote it on every size update); per-sector slots do not. A new
   cache_release() wc_ForceZero()s the buffer before freeing the slot.

3. Store_Open in write mode set the size to 8 (truncation) in the cache
   only; with batched commits the payload sectors are flushed before the
   header, so a power loss during the erase/rewrite left the old size over
   a partly erased payload. The truncated header is now committed to flash
   before erase_object_payload(), so the empty state is the crash fallback.

Addresses PR #873 review comments (wolfSSL-Fenrir-bot,
src/pkcs11_store.c:301, :333, :670, 2026-08-31).

Verification: tools/unit-tests unit-pkcs11_store 9/9 pass (incl.
test_concurrent_reader_sees_pending_writes,
test_shorter_overwrite_erases_residual_key_material,
test_interleaved_write_windows_both_persist).
2026-09-10 09:40:17 +02:00
Daniele Lacamera d6a5570f69 pkcs11 store: exercise the cached read path in the concurrent test
test_concurrent_reader_sees_pending_writes only ever read from flash:
the reader's Store_Open calls check_vault(), which flushes the sector
cache, so the sector_ptr() read path in Store_Read was never exercised
and the test passed identically against the pre-PR memcpy.

Write more on the still-open writer after the reader is open. That
batch lands only in the sector cache, so the reader can only see it
through the cached read path and the live header size; a flash-only or
snapshot-size read returns EOF here. Verified: the new assertion fails
against the pre-fix store (ret == 0) and passes with the live-size fix.

Addresses PR #873 review comments (wolfSSL-Fenrir-bot,
tools/unit-tests/unit-pkcs11_store.c:587, both near-duplicate findings).
2026-09-10 09:40:17 +02:00
Daniele Lacamera 241004367b pkcs11 store: read object size live from the cached header
Store_Read and Store_Write used handle->size, a snapshot taken at
Store_Open. The payload path reads through the sector cache, so once
another window's batch (e.g. a write-open truncation) sat pending in
the cache, the window saw live erased data under a stale size and
returned 0xFF bytes past the true end instead of EOF. Pre-PR the size
was read live from the flash header on every call, so the PR regressed
that case.

Read the size from the same (possibly cached) header sector the payload
comes from, via store_live_size(), so size and data share one source of
truth. Drop the now-dead handle->size snapshot; update_store_size()
only writes the cached header node.

Addresses PR #873 review comment (wolfSSL-Fenrir-bot,
src/pkcs11_store.c:711).
2026-09-10 09:40:17 +02:00
Daniele Lacamera b5c9c366f5 pkcs11 store: commit pending sectors in check_vault, read via cache
check_vault() dropped the shared sector cache on every vault
validation, silently losing the pending writes of any still-open
window when another handle was opened or an object removed
(MAX_OPEN_STORES allows 16). Flush instead - the atomic header-last
commit - so an in-flight batch only gets an earlier commit point;
its data is never discarded.

wolfPKCS11_Store_Read() now reads through sector_ptr() like every
other read in the file, so a sector still in the cache can never be
read stale against a live size.

Add unit tests covering the interleaved-window data loss and a
concurrent reader observing a pending write; both fail without the
check_vault fix.
2026-09-10 09:40:12 +02:00
Daniele Lacamera febf29ad61 pkcs11 store: batch sector commits to Store_Close
Every wolfPKCS11 field write flushed the payload sector and the header
sector to flash (2 erases + 2 programs of a full sector each), and the
token store re-serializes all objects per C_CreateObject/C_DestroyObject,
so those calls cost hundreds of sector erases and tens of seconds on
flash with slow erase times.

Cache modified sectors in RAM and commit them together when the store
window closes:

- sector cache sized to the worst-case span of one object plus the
  header sector (WOLFBOOT_PKCS11_STORE_CACHE_SECTORS), LRU eviction
  when exceeded
- header sector commits last, so a committed header is the atomic
  commit point of the batch: power failure during a flush leaves the
  flash in either the pre-batch or the post-batch state
- per-commit backup sector write preserved, keeping recovery of the
  sector in flight at failure time
- delete_object commits on return (durability contract, unit-tested)
- nodes table, bitmap, payload ids and the live object size
  (handle->size) are read from the cache when the sector is dirty

Measured on an STM32H5 with 8KB sectors, wolfPKCS11 in the secure
world: C_CreateObject 1.5s -> 0.15s, C_DestroyObject 1.3s -> 0.12s,
456 -> 40 sector erases per create, and the count no longer scales
with the number of objects in the token.

PKCS11_STORE_STATS (off by default) adds flash-activity counters and a
test-app bench to quantify store traffic: make PKCS11_STORE_STATS=1.
2026-09-10 09:40:02 +02:00
David Garske a2639e88f8 versal: report EL2 exceptions, fix FIT ramdisk fixup and the EL2->EL1 cache handoff 2026-09-10 08:17:21 +02:00
David Garske 24c23e767b Add T1040 eSDHC SD card disk boot support, first big-endian disk-boot target 2026-09-10 08:15:48 +02:00
David Garske ced2b1059c
Merge pull request #883 from danielinux/fenrir-fixes-2026-09-07
Fenrir fixes 2026 09 07
2026-09-08 16:21:42 -07:00
Daniele Lacamera 609294789f Address Fenrir PR review: make program-window observable in l5/u5 write tests
The new unaligned tests passed against the pre-fix HAL (identical
final bytes), so the alignment fix had no regression coverage. Mock
hal_flash_wait_complete now diffs the flash per program window and
asserts the changed bytes fit in one aligned unit; the 20-byte
unaligned test goes red on the pre-fix HAL (l5: bytes 4-11 across two
8-byte units, u5: bytes 4-19 across two 16-byte units).
2026-09-07 19:19:22 +02:00
Daniele Lacamera fc688f18c1 Address PR review: SWS macros + test decl style
hal/stm32wb.c: dedicated RCC_CFGR_SWS_{MSI,MASK} macros for the
clock-switch confirmation wait; SW/SWS encodings verified identical
in RM0434 6.4.3 and the STM32WB55 SVD.
unit-stm32u5-write.c: START_TEST brace on the next line, matching
the file and the unit-suite convention.
2026-09-07 17:43:22 +02:00
Daniele Lacamera 4751f89967 Merge branch 'wb-campaign-a4' into fenrir-fixes-2026-09-07 2026-09-07 16:38:42 +02:00
Daniele Lacamera 6f62fa0d4f Merge branch 'wb-campaign-a3' into fenrir-fixes-2026-09-07 2026-09-07 16:38:42 +02:00
Daniele Lacamera 33e5bed910 Merge branch 'wb-campaign-a2' into fenrir-fixes-2026-09-07 2026-09-07 16:38:42 +02:00
Daniele Lacamera cfd44bc5c1 F-12878: STM32U5: program the 16-byte unit through an aligned pointer
An unaligned starting address split the four word stores across two
16-byte program units, leaving partial quad-words that set
FLASH_SR_WDW and hang the wait for completion. Align the destination
down to the unit, read-modify-write the whole unit, and store through
the aligned pointer. The unit test gains unaligned-start cases.
2026-09-07 16:31:07 +02:00