Commit Graph

3658 Commits (a2639e88f8059139dcfddc9b51b2ece86cb513a4)

Author SHA1 Message Date
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
Daniele Lacamera ca06782f42 F-12877: STM32L5: program the 8-byte unit through an aligned pointer
hal_flash_write() stored both words of the 64-bit program unit
relative to the caller's address, so a write starting inside a unit
split the two stores across two units: the flash has no 32-bit
program mode, so nothing is programmed and the second store faults
on alignment. Align the destination down to the unit, take the bytes
outside the requested span from the unit itself, and store through
the aligned pointer, as hal/stm32h5.c does. The TrustZone claim is
unchanged: it is page-granular and already covers every non-secure
byte the aligned program touches.

Extend unit-stm32l5-write with unaligned-start cases. The host data
model cannot observe the program-unit split (pre-fix the bytes land
identically), so these pin the fixed layout: bytes before the
request preserved, nothing past it touched.
2026-09-07 16:31:07 +02:00
Daniele Lacamera 8e86847c1f F-12870: STM32C0: program flash writes through absolute addresses
The HAL contract is absolute (0x08000000-based) addresses, as the
erase path and every NVM caller use, but the double-word fast path
added the flash base on top and targeted an address space past the
flash. The read-modify-write path located its unit from the request
base indexed by i/4, landing in the wrong 8-byte unit once a request
started inside one. Both paths now program the 8-byte unit at
(address + i), and the now-dead FLASHMEM_ADDRESS_SPACE define is
gone.

Add unit-stm32c0-write: runs the extracted hal_flash_write() against
a host register/flash model with a second mapping standing in for
the wrong address space (4/5 checks fail pre-fix, 5/5 pass post-fix).
2026-09-07 16:05:51 +02:00
Daniele Lacamera 376f9e124f F-12920: zero firmware-DTB initrd pointers in hal_get_boot_dts
The CM4 firmware DTB is unverified (unsigned FAT partition) and this
path never attaches an authenticated ramdisk, so a non-zero
linux,initrd-start/end in it would direct the signed kernel to an
unauthenticated initramfs in RAM. Zero both properties on the
relocated DTB (fail closed on fixup error) and update the SECURITY
comment to state the new behavior.
2026-09-07 15:49:31 +02:00
Daniele Lacamera 49c1fff186 F-12876: riscv_sbi: report remote-fence timeout as SBI error
sbi_wait_ipi_done() returned void, so a target hart that never
completed its fence within the bounded wait was invisible and both
the standard and legacy remote-fence interfaces reported success
while the caller kept relying on a fence that may not have run.
Return SBI_ERR_FAILED when any target does not complete within the
bound, and propagate it through both SBI interfaces (standard
RFENCE via err, legacy v0.1 remote fence via a0).
2026-09-07 14:54:57 +02:00
Daniele Lacamera 9475169bdc F-12875: stm32f7 fix non-dual-bank sector 11 start address
Sector 11 was at 0x818C000, inside sector 10's 256 KB range
(0x8180000-0x81C0000), so hal_flash_erase mapped the upper part of
sector 10 to sector 11 and erased the wrong sector. Sector 11 is
0x81C0000, contiguous after sector 10 and ending at FLASH_TOP.
2026-09-07 14:43:15 +02:00
Daniele Lacamera 22356e6d02 F-12874: stm32wb switch SYSCLK to MSI and confirm SWS before disabling PLL
The MSIRDY wait read RCC_CFGR (bit 1 is SW status) instead of RCC_CR,
so it never gated, and the MSI selection was cleared only in a local
variable, never written back to RCC_CFGR. The PLL was disabled while
still the SYSCLK source, dropping the system clock. Now: wait MSIRDY,
commit the MSI selection, wait for SWS to confirm, then turn off PLL.
2026-09-07 14:43:15 +02:00
Daniele Lacamera 394f160a83 F-12873: update_disk: FSP low-mem check reuses validated slot_max
The final image-size check re-derived the low-memory limit with a
uint32 subtraction and no ordering check, so an inverted tolum
wrapped into a near-2^32 limit and accepted any image. Compare the
tolum/load_address ordering in 32-bit (low-memory) form when
computing slot_max, and reuse that validated value in the check.
Add a unit test for the inverted-tolum case (fails closed, both
slots rejected).
2026-09-07 14:40:35 +02:00
Daniele Lacamera 194322ec73 F-12921: erase keyvault payload on object removal
The PKCS#11 and PSA store Remove paths invalidated the metadata and
freed the bitmap slot but left the payload in flash, so removed keys
stayed recoverable by a physical reader. Both Remove paths now call
erase_object_payload() before invalidating the metadata; the existing
sector read-modify-write preserves neighboring slots. Raw-flash
deletion tests added to both unit suites.
2026-09-07 14:36:29 +02:00
David Garske 173bb298e9
Merge pull request #882 from danielinux/fenrir-fixes-2026-09-04 2026-09-04 21:10:45 -07:00
Daniele Lacamera c2916395a9 x86_64_efi: early-return after remaining panic() sites under UNIT_TEST
do_boot() already returned after its panic() calls, but GetVolume() and
efi_main() did not: under UNIT_TEST panic() returns, so GetVolume() hit a
NULL deref / uninitialized return and efi_main() ran wolfBoot_start().
Return NULL / EFI_LOAD_ERROR at each site (unreachable on target).
2026-09-04 21:08:36 +02:00
Daniele Lacamera 2dbb8aea01 image: cast ELF scatter log fields to unsigned long
offset/filesz are uint64_t now; cast them for the %08lx/%lu
conversions so the varargs read matches on 32-bit targets, matching
the check function and the rejection messages above.
2026-09-04 20:02:10 +02:00
Daniele Lacamera faaad372cc Address minor PR 882 review nits
Cap the library fw_size clamp at UINT32_MAX (a > 4 GiB file would
otherwise truncate to a small value), say 'restore' not 'store' in the
scatter-restore error message, and print stdout as well as stderr in
the compile-check scripts on failure.
2026-09-04 16:39:26 +02:00
Daniele Lacamera b0209d0bf6 image: use uint64_t for ELF scatter program-header locals
paddr/filesz/offset were unsigned long, which is 32-bit on the
ELF-scatter targets (aurix-tc375, sim32). ELF64 program headers
truncate before the segment guards run, so filesz > UINT32_MAX is
never true and an out-of-range paddr wraps in-range. Use uint64_t to
match wolfBoot_check_flash_image_elf so the guards see untruncated
values.
2026-09-04 16:39:26 +02:00
Daniele Lacamera 01a71c7d39 x86_64_efi: return after LoadImage-failure panic under UNIT_TEST
panic() returns under UNIT_TEST, so the LoadImage-failure site fell
through to StartImage on a failed load. Add the return to match the
zero-size guard; on target panic() never returns, so behavior is
unchanged.
2026-09-04 15:52:27 +02:00
Daniele Lacamera 58e79daec7 F-11047: image: drop incorrect boot-partition destination check
The ELF scatter destination is the exec region, which sits outside the
boot partition that stores the signed ELF. Bounding it to the boot
partition rejected every legitimate segment (aurix exec is below boot,
sim scatter is above it) and bricked corruption recovery. The paddr is
covered by the image signature verified before this restore path and the
overflow check keeps it from wrapping, so no destination bound is needed;
this also matches the check function, which bounds no destination.
2026-09-04 15:52:19 +02:00
Daniele Lacamera 62918f2e90 F-12107: pkcs11 nsc: zero work buffer before it can be freed
If the snap allocation fails but the work allocation succeeds, the
initialisation loop never runs and nsc_tmpl_free() would release
indeterminate work[].pValue pointers. Zero work[] right after the
allocation (before the NULL check) so every path that reaches the
free hands out initialised, NULL pValue entries.
2026-09-04 14:53:15 +02:00
Daniele Lacamera d64f15af05 F-7392: stm32h7: document inherent OTP immutability in set_readonly
The H7 OTP memory is one-time programmable, so the keystore and UDS
are permanent once written; the H7 has no OTP block-lock register
(unlike the H5), so there is no write-protection step to perform.
Replace the misleading TODO with the reason the no-op is correct.
2026-09-04 14:33:29 +02:00
Daniele Lacamera b9068ce162 F-12105: tpm: keep keystore size as int in load_pubkey
keystore_get_size() returns -1 on invalid or oversized OTP slot
data; storing it in uint16_t made -1 become 65535, which passed the
hdrSz <= 0 check and was fed to the ECC/RSA parser as a 65535-byte
read from the keystore buffer. Keep it as int and reject values
<= 0 or above KEYSTORE_PUBKEY_SIZE.
2026-09-04 14:06:33 +02:00
Daniele Lacamera b5ab88a50a F-9744: store: reject negative length before unsigned arithmetic
wolfPKCS11/PSA_Store_Read/Write added int len to unsigned
in_buffer_offset before validation: a sufficiently negative len
wrapped, hit the truncation branch, and was replaced by the remaining
object or capacity bytes, bypassing Write's later len < 0 guard.
Reject len < 0 first in all four functions (post-clamp guard kept).
2026-09-04 13:56:55 +02:00
Daniele Lacamera a6628a324a F-12108: image: clamp sha block/peek to fw_size
get_sha_block() accepted offset == fw_size and always read
WOLFBOOT_SHA_BLOCK_SIZE bytes; wolfBoot_peek_image() always reported
the full block size. Both could hand callers a window past the end
of the image. Reject offset >= fw_size, clamp the external read to
the bytes remaining, and report the clamped size (0 when no bytes
remain). Hash callers already clamp their input, so this is API
hardening; pinned by test_peek_image_bounds (internal + ext cases).
2026-09-04 13:40:37 +02:00
Daniele Lacamera 0e2a463750 F-11047: image: validate ELF scatter segments before flash writes
wolfBoot_load_flash_image_elf() ignored read_flash_fwimage failures
and used the program-header fields unchecked, so a failed read
consumed indeterminate stack data and a malformed (but signed) ELF
could drive an out-of-bounds source read and erase/write at an
unintended destination.

Check the ELF header and program header reads, then validate each
PT_LOAD segment before copying: file_size fits a 32-bit length, the
source stays inside the manifest image, the paddr range fits the
destination address width, and the destination stays inside the boot
partition (mirrors the sibling check-function validation). Check the
copy result.

New unit tests in unit-image-elf-scatter.c cover the load path: a
valid restore (positive control) and rejections for source past
fw_size, paddr range overflow, destination outside the boot
partition, and a program header that cannot be read. The first three
fail pre-fix (the mock flash layer also catches the two
out-of-range destinations with its own address check); the phdr
read-failure case consumed uninitialized stack data pre-fix
(valgrind: conditional jump on uninitialised value at the
is_loadable check).
2026-09-04 11:53:12 +02:00
Daniele Lacamera 55711243c6 F-11026: image: declare wolfHSM DER sig length as word32
wc_ecc_rs_raw_to_sig() takes a word32* outlen, but the wolfHSM
client/server path in wolfBoot_verify_signature_ecc() declared the
buffer length as size_t and cast the pointer. On a 64-bit
big-endian target the API reads the high (zero) half, so the DER
conversion sees outlen 0 and the write-back lands in the wrong
half of the size_t.

Declare tmpSigSz as word32 and pass &tmpSigSz directly; this also
matches the word32 sigLen of wc_ecc_verify_hash() below.

Add a host compile check for the WOLFBOOT_ENABLE_WOLFHSM_CLIENT
build of image.c, which unit CI did not cover (only the PIC32CZ
cross build).
2026-09-04 11:24:13 +02:00
Daniele Lacamera 785a285ca7 F-11025: update_flash: document deliberately inert PCR extend block
The PCR-extension block in wolfBoot_unlock_disk() is guarded with
!defined(ARCH_SIM) while the function itself only builds for
ARCH_SIM, so it can never compile. The exclusion is deliberate
(eb2978ab: do not extend the unseal PCR on the simulator, or the
secret becomes un-unsealable), not an oversight.

Clarify the comment with the intended build scope instead of
removing the block: the code and the WOLFBOOT_NO_UNSEAL_PCR_EXTEND
option exist for the day the unlock-disk path is ported to a
non-sim target.
2026-09-04 11:13:32 +02:00
Daniele Lacamera eb3d587fe2 F-9746: x86_64_efi: fix do_boot prototype mismatch, drop unused param
boot_x86_64.c declared x86_64_efi_do_boot(uint8_t *) while the HAL
defines (uint32_t *, uint8_t *): the linker connected the incompatible
pair and the call was undefined behavior, mostly latent because the
second parameter was discarded. Match the AArch64 sibling: single
const uint32_t *boot_addr in the declaration, definition and call,
and remove the unused dts_address parameter.
2026-09-04 10:57:08 +02:00
Daniele Lacamera d244fd9b7e F-9745: x86_64_efi: inclusive mem path end, reject zero-size image
The UEFI MEMMAP_DEVICE_PATH EndingAddress is inclusive (last valid
byte), but x86_64_efi_do_boot() set it to boot_addr + size, describing
every image as one byte longer than it is; the AArch64 sibling already
uses size - 1. A zero-size image would underflow that computation and
hand an empty range to LoadImage, so reject it up front, as the
AArch64 sibling does. The local panic() returns to the unit test under
UNIT_TEST so the zero-size path is observable.
2026-09-04 10:44:34 +02:00
Daniele Lacamera a2d5543ebb F-9740: update_disk: FSP low-mem rejection falls back to other slot
The WOLFBOOT_FSP low-memory size check was the only per-slot rejection
in the boot retry loop that used a bare break, so an image whose
header-declared fw_size exceeded the tolum window aborted the boot
instead of trying the other slot. Every other rejection in the same
loop switches partitions and retries; match that.
2026-09-04 10:32:13 +02:00
Daniele Lacamera 77fe733e7f F-7391: library hal: reject undersized files, bound hash to loaded size
main() loaded a file of any size and parsed it as a manifest: header
fields (size, TLVs) were read past the end of the heap allocation, and
a header claiming a larger fw_size drove the image hash over an
unbounded range. Reject files smaller than IMAGE_HEADER_SIZE before
parsing and clamp fw_size to the bytes actually loaded.
2026-09-04 10:24:11 +02:00
Daniele Lacamera 88af5b6472 F-7390: x86 fsp: drop dead FSP auth scaffolding, fix comment
STAGE1_AUTH only authenticates the stage2 wolfBoot payload; the FSP-M and
FSP-S blobs are executed unverified. Remove the dead fsp_m/ret
declarations in start(), the orphaned .sig_fsp_s placeholder section
(no stage1 linker script places it), and correct the comment that
claimed the FSPs were authenticated. Add a compile check for the
STAGE1_AUTH variant (unit-x86-fsp-stage1auth-build.py), which the unit
test CI never builds for lack of an i686 toolchain.

Verification: full unit suite 1096 checks, 0 failures; both
STAGE1_AUTH variants of boot_x86_fsp.c compile clean; no references to
sig_fsp_s remain.
2026-09-04 10:00:54 +02:00
Daniele Lacamera 455c1c6cc6 F-7067: elf scatter: fix PART_IS_EXT arg and check load result
In the DISABLE_BACKUP branch of wolfBoot_update() the ELF-scatter restore
block passed the boot struct by value to the pointer-taking PART_IS_EXT
macro, so DISABLE_BACKUP + WOLFBOOT_ELF_FLASH_SCATTER + EXT_FLASH did not
even compile, and the load result was discarded. Mirror the
wolfBoot_start() pattern (PART_IS_EXT(&boot), panic on load failure), drop
the dead base local, and add a compile check for the combination
(unit-elf-scatter-db-build.py) guarding the one test that needs a
DISABLE_BACKUP-excluded symbol.

Verification: full unit suite 1096 checks, 0 failures; new test fails
pre-fix (struct vs pointer compile error), passes post-fix.
2026-09-04 09:52:22 +02:00
Daniele Lacamera f598b3fd41 F-6878: delta: reject non-multiple SECTOR_SIZE/DELTA_BLOCK_SIZE at build
The per-sector fill loop in wolfBoot_delta_update() advances in
DELTA_BLOCK_SIZE steps, so a WOLFBOOT_SECTOR_SIZE that is not a multiple
of DELTA_BLOCK_SIZE writes past the one-sector SWAP partition and
misaligns the resume path. Enforce the invariant with a #error and add a
negative build test (unit-delta-sector-align.py).

Verification: full unit suite 1096 checks, 0 failures; new test fails
pre-fix (misaligned config built), passes post-fix (build rejected).
2026-09-04 09:46:27 +02:00
David Garske 6883532da8
Merge pull request #880 from danielinux/fenrir-fixes-2026-09-01
Fenrir fixes 2026 09 01
2026-09-03 07:51:13 -07:00
Daniele Lacamera 931d224652 F-12065: unit test: clear the short-read mock before the assertion
PR review (wolfSSL/wolfBoot#880, Fenrir bot) flagged that
test_noramboot_ext_flash_short_read_rejected set the shared mock
globals mock_ext_flash_short_len/mock_ext_flash_short_bytes and only
cleared them after the ck_assert. The suite runs CK_NOFORK, so a
failing assertion longjmps out of the test and leaves every full-size
ext_flash_read truncated for test_noramboot_highversion_rollback_denied,
which then fails for an unrelated reason.

Clear the mock globals immediately after wolfBoot_start() returns,
before the assertion: the assert only checks wolfBoot_staged_ok, which
is set during wolfBoot_start(), so the ordering changes nothing about
what is tested and the mock state can no longer leak into the next
test on a failure path.

Verification: full unit suite in wolfboot-ci-sim (make -C
tools/unit-tests; make run) exit 0; unit-update-ram-noramboot 3/3.
2026-09-03 08:54:51 +02:00
David Garske 99725d278c
Merge pull request #878 from bigbrett/tc3-tweaks
tc3 quickfixes
2026-09-02 14:08:40 -07:00
Daniele Lacamera 80e92ea728 F-12065: update_ram: type-safe short-read check for -Wsign-compare
The F-12065 fix compared the int return of ext_flash_read() directly
against the uint32_t os_image.fw_size. That int-vs-unsigned comparison
triggers -Wsign-compare, which is a hard error under the default
-Werror -Wextra for every EXT_FLASH+NO_XIP update_ram target (e.g.
zynqmp) at -O0 and on host x86_64 gcc.

Check the error range explicitly and cast for the size comparison,
matching the established pattern in src/disk_fs.c (ret < 0 check
followed by (uint32_t)ret != len). Semantics are unchanged: negative
returns and positive short reads are both rejected.

Verified: host gcc -Werror -Wextra -fsyntax-only warns on the old
line and is clean on this one; unit-update-ram-noramboot 3/3.
2026-09-02 18:21:54 +02:00
Daniele Lacamera fa0c329a02 F-12064: p1021: drop already-delivered pages of a bad block
When the bad-block marker is found on the block's second page, the
first page has already been copied to the caller's buffer and counted
in pos; the skip advanced only the source address, so the bad block's
page stayed in the output and the read returned len with the bad
block's content mixed into the image.

Record the output position at the start of each erase block and, on a
bad block, rewind both pos and the data pointer to it before advancing
the source address. This preserves the data = original + pos
invariant (no out-of-bounds write) and discards the bad block's
delivered pages.

test_bad_marker_second_page_dropped now asserts the bad block is fully
skipped (output starts at the next block's first page); it fails
against the previous code.
2026-09-02 13:17:48 +02:00
Daniele Lacamera a504552883 unit test: match wolfBoot_get_dts_size mock to the 2-arg signature
95227f82 (fdt: rewrite device tree parser with capacity bound and full
validation) changed wolfBoot_get_dts_size() to take a capacity argument
but left the mock in unit-update-disk-fs.c with the old 1-arg
signature, so the test no longer compiles (conflicting types). Update
the mock; behavior is unchanged (always -1, no DTS in this test).
2026-09-02 12:19:13 +02:00
Daniele Lacamera 634d67904c F-12061: unit test: keep the XIP fast-path source in the flash model
PR review (wolfSSL/wolfBoot#880, Fenrir bot) flagged that
test_aligned_page_multiple_write_xip filled its 512-byte source at
offset 3 * FLASH_PAGE_SIZE (768) of the 1024-byte flash model, so
both the fixture and the HAL's XIP staging read 256 bytes past the
modeled region; it only passed because mmap rounds the mapping up to
a full page.

Move the source to pages 2-3 (offset 2 * FLASH_PAGE_SIZE) with the
destination at pages 0-1: non-overlapping, fully inside the model.

Verification: unit-rp2350-flash-write 6/6, full unit suite green.
2026-09-02 12:15:52 +02:00
Daniele Lacamera 5e80903103 F-12104: kontron tgl: correct the SPIBAR FREG/FPR register offsets
PR review (wolfSSL/wolfBoot#880, Fenrir bot) flagged that the
register offsets introduced by the F-12104 fix are wrong, and the
Linux kernel's Intel PCH SPI driver (drivers/spi/spi-intel.c)
confirms it:

  FDATA(n) = 0x10 + 4n  -> 0x48 is FDATA14, a scratch data register
  FRACC    = 0x50       -> not FREG0
  FREG(n)  = 0x54 + 4n  -> FREG0 = 0x54, FREG1 = 0x58
  FPR0-4   = 0x84-0x9C  (BXT/CNL protection-range base)

Two consequences. First, the BIOS range source: Intel flash region
numbering is region 0 = flash descriptor, region 1 = BIOS, and the
kernel driver's partition code reflects that ("start from the
mandatory descriptor region", then iterate FREG(1..)). The original
pre-F-12104 code read FREG1 (0x58) for the BIOS range and was right
on that point; the F-12104 fix regressed it to FREG0 (0x50), which
is the FRACC register. Restore FREG1.

Second, FPR0: the original 0x48 came from the buggy PCI-config-space
write path and is a FDATA scratch register in the SPIBAR map, so the
readback check passed on a register that never programs protection.
FPR0 is 0x84 (BXT/CNL PR base; JSL is not in the kernel's platform
table but follows the same-generation layout). HSFSTS_CTL at 0x04
and the RPE (bit 15) / WPE (bit 31) / base / limit fields match the
kernel's PR_ definitions and are unchanged.

unit-kontron-tgl-spi.c: mirror the corrected offsets (FREG0 decoy at
0x54, FREG1 BIOS source at 0x58, FPR0 at 0x84) and assert FPR0
carries the FREG1 range; the test runs the real extracted
tgl_lock_bios_region(), so it fails if the HAL offsets drift.

Verification: unit-kontron-tgl-spi 4/4, full unit suite green, sim
build green, cstyle clean on changed hunks.
2026-09-02 12:15:51 +02:00
Daniele Lacamera 65cab0a0a7 F-12104: unit test: model the TGL SPI MMIO as 32-bit registers
The Kontron TGL SPI regression test kept the MMIO shadow in a
uint8_t array and reached into it through uint32_t * casts. The
accesses are all 32-bit at 4-aligned register offsets (0x04, 0x48,
0x50, 0x58), so the model is now a uint32_t array indexed by
offset/4: no casts, no alignment or strict-aliasing doubt, and the
redundant byte-clear before the 32-bit FREG0 store is gone.

Verification: unit-kontron-tgl-spi 4/4, full unit suite green,
cstyle clean.
2026-09-02 12:15:51 +02:00
Daniele Lacamera 1c57f8c06b F-12114: pkcs11: wipe the PIN even when no session was established
pkcs11_pin is pre-populated from the compile-time credential
(ENCRYPT_PKCS11_PIN), so the RAM copy exists from image load, not
from a successful C_Login. pkcs11_crypto_deinit() only wiped it
inside the encrypt_initialized branch, so on a target where init
never completed the credential stayed in retained memory after the
pre-handoff path ran.

Move pkcs11_pin_wipe() out of the branch: the token interaction
(C_CloseSession) stays conditional on an established session, the
credential wipe is unconditional. deinit only runs on the terminal
pre-handoff paths, so this cannot break the init retry in
wolfBoot_initialize_encryption, which runs at decryption time,
well before handoff.

test_pkcs11_deinit_no_session now re-populates the pin and asserts
every byte is zero after deinit without init (plus no C_CloseSession
and repeat-call safety). Pre-fix it failed with "pkcs11_pin byte 0
not wiped" (1/2); post-fix 2/2.

Verification: unit-pkcs11-pin-zeroize 2/2, full unit suite green,
sim build green, cstyle clean on changed hunks.
2026-09-02 12:15:51 +02:00
Daniele Lacamera b548341e9b F-12114: pkcs11: wipe the login PIN on all pre-handoff paths
pkcs11_crypto_deinit() - the only caller of pkcs11_pin_wipe() - was
invoked from the update_flash path alone (src/update_flash.c:1715).
On the RAMBOOT, hwswap and disk pre-handoff paths the PKCS#11 login
credential stayed in retained bootloader memory after handoff.

Add the same #ifdef ENCRYPT_PKCS11 deinit block after the WOLFHSM
cleanup in src/update_ram.c, src/update_flash_hwswap.c and
src/update_disk.c, in the same position as the existing update_flash
call (before hal_flash_protect/hal_prepare_boot). update_ram.c and
update_flash_hwswap.c did not include encrypt.h, where
pkcs11_crypto_deinit() is declared - add the include (update_flash.c
and update_disk.c already had it). The deinit is a no-op when crypto
was never initialized, so the calls are safe on every build.

Verification: full build with PKCS11 enabled (sim config +
CFLAGS_EXTRA: ENCRYPT_PKCS11, EXT_ENCRYPTED, EXT_FLASH,
WOLFCRYPT_SECURE_MODE, SECURE_PKCS11, WOLFPKCS11_USER_SETTINGS +
mechanism/sizes/PIN) compiles all sources cleanly; the link stops on
pre-existing externals (token library + secure-mode wolfssl objects
that a real target's link config supplies) - a control build of the
unpatched tree fails identically with the same undefined-symbol set.
sim and kontron_vx3060_s2 builds green (PKCS11 disabled, hunks
inactive). cstyle clean on the changed hunks.
2026-09-02 12:15:51 +02:00