Commit Graph

576 Commits (6025f3540ffb43561ba5890ceee8c18cb4bd3650)

Author SHA1 Message Date
Daniele Lacamera 769c3885f0 Remove the obsolete python keytools, convert remaining users to C
sign.py and keygen.py are superseded by the C tools/keytools/sign and
keygen (built by the same Makefile, no python/wolfcrypt-py
dependency). Rewrite unit-sign-delta-tlv.py to sign a real delta
image with the C sign tool instead of the python bmdiff/sign.py
pipeline, and update README.md and include/delta.h references.
2026-09-23 01:48:54 +02:00
Aidan Garske c48a882cd9 Add a generic secure application handoff with a measured boot record 2026-09-22 15:35:42 +02:00
David Garske 7efe6d410f tpm: reject a measured-boot PCR bank wider than the image hash 2026-09-22 15:32:04 +02:00
David Garske 44ce5d8333 tpm: pair the PCR bank algorithm with its digest size 2026-09-22 15:32:04 +02:00
David Garske 4f33091f74 uart: replace the duplicated NS16550 console code with a shared driver 2026-09-21 18:12:32 +02:00
David Garske fae9e53653 hooks: add pre-boot hook, DTB accessor and FDT alias/reg helpers 2026-09-21 18:10:09 +02:00
David Garske 4093fa0e17 Add NXP i.MX 8QuadMax MEK port including BL33 support 2026-09-21 18:07:44 +02:00
Daniele Lacamera 80af0bfd4b Fix CI: partition-guard extents, duplicate nrf5340 object, opt-out reach
Three CI failures from the new bootloader-region overlap guards:

renesas_rx72n: the swap check measured the swap area as a full
WOLFBOOT_PARTITION_SIZE, but swap is one sector (the pre-existing
boot/update-vs-swap guards already use WOLFBOOT_SECTOR_SIZE). On rx72n
that inflated swap to 0xFFFE0000+0x1F0000 and falsely overlapped the
write-protect region at 0xFFFF0000. Use WOLFBOOT_SECTOR_SIZE.
2026-09-18 18:58:39 +02:00
Daniele Lacamera d45f3446c7 Address Copilot review comments
- Add missing END_TEST after each START_TEST in unit-nrf5340-uart-crlf.c
- Fix partition overlap checks in target.h.in to use standard interval
  intersection (catches partitions that start below WOLFBOOT_ORIGIN and
  extend into the bootloader region)
2026-09-18 17:26:22 +02:00
Daniele Lacamera a2f7d8b651 Fix nrf5340 link error + cypsoc6 partition-overlap false positive
nrf5340: the target references nrf5340_uart_crlf (src/update_flash.c)
but the Makefile does not compile hal/nrf5340_uart.c, so the linker
fails. Add the object to OBJS (Makefile) and APP_OBJS (test-app).

cypsoc6: the new boot/update/swap vs bootloader-region #error guards
in include/target.h.in fire on the cypsoc6 layout, where the boot
partition intentionally overlaps the bootloader region (the bootloader
and the boot image share the same flash region). Introduce
WOLFBOOT_ALLOW_PART_OVERLAP (defined in cypsoc6.config, gated in
target.h.in, added to CONFIG_VARS in tools/config.mk) to suppress the
guards for targets that legitimately overlap.

Verified: nrf5340 builds (make distclean + cp config + make, exit 0,
wolfboot.bin created). cypsoc6 cannot be built locally (the CI checks
out lib/psoc6pdl from Infineon, which is not available locally), but
the WOLFBOOT_ALLOW_PART_OVERLAP guard is verified to suppress the
#error for the cypsoc6 layout.
2026-09-18 15:07:34 +02:00
Daniele Lacamera b0db2b70f7 F-13622: guard partition overlap with the bootloader write-protect region
The boot, update and swap partitions were never checked against the
bootloader write-protect region [WOLFBOOT_ORIGIN, WOLFBOOT_ORIGIN +
BOOTLOADER_PARTITION_SIZE). An over-sized BOOTLOADER_PARTITION_SIZE
silently write-protects the head of a partition; the existing
boot/update/swap overlap guards did not cover this.

Add three #error guards (boot, update, swap vs bootloader region) to
include/target.h.in, gated on WOLFBOOT_ORIGIN < the partition address so
they only fire for real targets (the mock target has WOLFBOOT_ORIGIN ==
WOLFBOOT_PARTITION_BOOT_ADDRESS, a valid simplified geometry).

The undersized guard (BOOTLOADER_PARTITION_SIZE not covering the
self-update erase range) is deferred: it requires a compile-time
constant for ARCH_FLASH_OFFSET, which is a runtime value (sim_ram_base)
for the mock target.

The compile-only negative tests (part 2 of the finding) are deferred.
2026-09-18 13:56:15 +02:00
Daniele Lacamera 703065b68f Fix wolfCrypt build and footprint limits after the wolfSSL update
The wolfSSL bump to master 4aa1ad7a5 wraps all of coding.h in
"#ifndef NO_CODING".  That block also holds the auto-enable that turns
WOLFSSL_KEY_GEN into WOLFSSL_BASE64_ENCODE, so wolfBoot configurations
that set both WOLFSSL_KEY_GEN (SECURE_PKCS11) and NO_CODING lost the
Base64_Encode() declaration -- and coding.c compiles to nothing under
NO_CODING, so the definition is gone too.  settings.h still derives
WOLFSSL_DER_TO_PEM from WOLFSSL_KEY_GEN, so asn.c kept compiling
wc_DerToPemEx() and failed with an implicit declaration of
Base64_Encode().  This broke every TrustZone and PKCS11 target.

wolfBoot never emits PEM, so define WOLFSSL_NO_DER_TO_PEM whenever
NO_CODING is set rather than pulling base64 back in.  The check sits
after the HAVE_FIPS block, which may undef NO_CODING.  wolfTPM's
wc_DerToPem() callers are themselves guarded by WOLFSSL_DER_TO_PEM, so
they simply drop their optional PEM encoding path.

Separately, the update grows wolfboot by 8-136 bytes depending on the
configuration, so re-measure every test-size-all entry with the CI
container and record the new sizes.
2026-09-17 19:13:42 +02:00
Daniele Lacamera 5f231a890c Fix: keep wolfBoot API declarations visible to app builds
c3f9717f guarded the success/trigger/sector-flag declarations behind
WOLFBOOT_FIXED_PARTITIONS, but wolfboot.h includes target.h only under
__WOLFBOOT, so test-apps (compiled without __WOLFBOOT) never saw the
macro and failed with implicit-declaration errors on imx95_m7, mcxa,
mcxw and mcxw-tz. Unguard the header declarations; keep the definitions
guarded and move wolfBoot_success out of the fixed-partition guard
since it only uses the partition-state API.
2026-09-16 18:31:59 +02:00
Daniele Lacamera 7feb9cbf67 Mark wolfBoot_invalidate_hdr_cache RAMFUNCTION
Called from the RAM-resident update path (update_ram.c) under
EXT_FLASH; place the body in RAM so it runs after flash remap
instead of faulting.

Verification: built unit-custom-trailer-nopart (EXT_FLASH) - compiles
clean; imx95_m7 (EXT_FLASH, CI repro) - compiles clean.
2026-09-16 18:17:48 +02:00
Daniele Lacamera c3f9717fb5 PR 892: address 3 Fenrir review findings
- libwolfboot.c: keep the partition state APIs (set/get_partition_state)
  available to CUSTOM_PARTITION_TRAILER / WOLFBOOT_NO_PARTITIONS builds;
  guard the fixed-partition APIs (sector flags, erase, trigger, success)
  behind WOLFBOOT_FIXED_PARTITIONS. Add the unit-custom-trailer-nopart
  compile target to lock in that configuration.
- unit-p1021-fcm-bytes.c: add program tests for status 0x81 (fail) and
  0x00 (write-protected), asserting no later page is programmed.
- unit-p1021-erase-advance.c: add an erase test for status 0x00
  (write-protected), asserting failure before advancing to the next block.
2026-09-16 17:19:16 +02:00
Daniele Lacamera cc7fec1ea2 PR 892: anti-rollback for CUSTOM_PARTITION_TRAILER targets
Add HAVE_PARTITION_TRAILERS macro (set when WOLFBOOT_FIXED_PARTITIONS or
CUSTOM_PARTITION_TRAILER is defined) and use it to gate the TESTING state
transition in update_ram.c. Previously the gate was WOLFBOOT_FIXED_PARTITIONS
only, so targets using custom partition trailers never transitioned from
UPDATING to TESTING, allowing rollback to older versions.

Add unit-update-ram-custom-trailer test covering the CUSTOM_PARTITION_TRAILER
path with mocked get/set_trailer_at callbacks.
2026-09-16 14:30:26 +02:00
Daniele Lacamera c527ac7ee1 F-9261: sector-size check allows equality
The #if fires on WOLFBOOT_SECTOR_SIZE < IMAGE_HEADER_SIZE, so equal
is accepted; the comment and #error said 'larger than'.
2026-09-16 12:14:13 +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 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
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 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 95227f823c fdt: rewrite device tree parser with capacity bound and full validation 2026-09-02 10:48:52 +02:00
David Garske 1091fc6d45 ext4: add read-only extent-based ext4 filesystem support 2026-09-02 10:47:33 +02:00
David Garske f06f081a20 disk_fs: add read-only FAT32 filesystem support for disk boot 2026-09-02 10:47:33 +02:00
David Garske 336ee7fd56 gpt: parse MBR and GPT byte-wise so disk boot works big-endian 2026-09-02 10:47:33 +02:00
Daniele Lacamera 2fdc99f323 pci: keep the allocation cursors 64-bit at the 4 GiB pool end
The cursors mem, mem_pf and io advanced as 32-bit values: after a
BAR allocation whose end is exactly the pool end 0x100000000 (now
reachable), *base = bar_value + length wrapped to 0.  Every later
allocation then passed the start and end checks and programmed its
BAR at address 0, over the legacy IO range and DRAM.

Widen the three cursors to 64-bit and advance with a 64-bit sum, so
an exhausted pool leaves the cursor at the end.  The address
parameters of pci_enum_next_aligned32 and pci_align_check_up widen
with them; pci_enum_next_aligned32 computes in uint64_t rather than
uintptr_t, which on 32-bit targets would truncate the exhausted
cursor back to 0 and defeat the addr > 0xffffffff rejection.  The
programmed BAR value stays 32-bit.

The 4 GiB pool unit test now also adds a second device with a
preset (previously programmed) BAR: exactly filling the pool must
leave that BAR untouched instead of re-allocating it from a wrapped
cursor.  The mock learns to seed a BAR preset from the bar info,
and the loop variable shadowing in test_pci_commit that it exposed
is fixed (the inner preset loop clobbered the outer node loop
counter, so only the first node was ever committed).

Verified: unit-pci 30/30, unit-pci-4gib green, full nxp_t1024
powerpc build green.
2026-08-26 20:05:56 +02:00
Daniele Lacamera b115363291 pci: accept MMIO pools whose exclusive end is 4 GiB
A pool ending exactly at 0x100000000 (e.g. 0xC0000000 + 0x40000000,
the classic top-half 32-bit MMIO layout) was a working configuration:
the old base + length - 1 initialization wrapped to 0xFFFFFFFF in
32-bit arithmetic. The overflow guard from the exclusive-limit fix
rejected such pools with base + length > 0xFFFFFFFF, aborting
enumeration - and the FSP caller discards the return value, so the
platform would boot with no PCI BARs programmed.

The limit fields cannot hold the exclusive end 0x100000000 while
32-bit, so widen mem_limit and mem_pf_limit (and the limit
parameters of pci_enum_next_aligned32 and pci_align_check_up, plus
the local in pci_program_bar) to 64-bit, and reject only pools whose
end is above the 32-bit space. The initialization now casts to
64-bit before the addition so the sum cannot wrap.

The T10xx PCIe setup initializes the same struct with the old
inclusive base + length - 1 form; align it to the exclusive
semantics the allocator enforces, or the last byte of the configured
pool is unusable.

New unit-pci-4gib build of the existing test file with the MMIO
pool [0xC0000000, 0x100000000): pci_enum_do() must accept the pool
and map a 1 MB BAR at the pool base. Fails on the old guard.
2026-08-26 18:59:48 +02:00
David Garske 25cdd5a0d7 c2000: add wolfBoot TI C28x (TMS320F28P550SJ) secure-boot XIP port 2026-08-25 00:01:33 +02:00
David Garske c409adb088 lib/wolfssl: bump to ti_c25 merge (e71b086fc) for CHAR_BIT!=8 wide-byte support 2026-08-25 00:01:33 +02:00
David Garske a5c94502d4
Merge pull request #868 from danielinux/fenrir-fixes-2026-08-21
Fenrir fixes 2026 08 21
2026-08-24 13:34:37 -04:00
David Garske 8015a1fa4f Peer review fixes (thanks Daniele) 2026-08-24 12:47:34 +02:00
David Garske 88984858d5 Peer review fixes (thanks Jack) 2026-08-24 12:47:34 +02:00
David Garske 67c819bc0b cm4: add RAUC A/B slot selection via U-Boot env (wolfBoot replaces U-Boot) 2026-08-24 12:47:34 +02:00
David Garske 56651bde95 cm4: add Linux kernel FIT boot via firmware-provided DTB with injected bootargs 2026-08-24 12:47:34 +02:00
David Garske 71b855f7b5 cm4: add wolfCrypt FIPS 140-3 support + CI, SDHCI unit test, review fixes 2026-08-24 12:47:34 +02:00
Daniele Lacamera 9b1a48554a share the DTS size bounds in fdt.h and state the window assumption
The WOLFBOOT_DTS_MAX_SIZE/WOLFBOOT_DTS_MIN_SIZE pair was defined
separately in update_disk.c (F-7066) and update_ram.c (pre-existing), so
the two copies could drift. Move it to include/fdt.h, the FDT dialect
header both translation units already pull in via image.h; the hal
override (nxp_ppc.h, included before fdt.h in boot_ppc.c) keeps its
precedence. Also replace the 'bounded by the staging region' comment,
which claimed more than the code guarantees: the copy is clamped to
WOLFBOOT_DTS_MAX_SIZE, so the staging window at
WOLFBOOT_LOAD_DTS_ADDRESS must be at least that large (or the bound
overridden for the target), and the header comment now says so.

Skoll review finding 3, 2026-08-21 wolfboot review.
2026-08-21 09:08:26 +02:00
Brett Nicholas 25aa151f0b add asymmetric partition sizing for monolithic updates 2026-08-19 17:47:48 +02:00
David Garske d42109c843
Merge pull request #862 from danielinux/fenrir-fixes-2026-08-18
Fenrir fixes 2026 08 18
2026-08-18 12:12:50 -07:00
Daniele Lacamera 502a69e9df Condense the verbose comments
The test file headers ran to 20-40 lines of prose before the licence,
restating the whole finding and the harness design. Cut them to a short
paragraph on what broke and a short one on how the test reaches the
code. Same for the long inline blocks in the HAL and libwolfboot
changes.

Comments only; no functional change.
2026-08-18 20:12:06 +02:00
David Garske 27edd0f5e7 tegra234: bare-metal BL33 target with verified EL2->EL1 + device-tree boot 2026-08-18 11:01:45 +02:00
Daniele Lacamera 3865c62614 user_settings: actually harden fast math for software DICE
tfm.c never tests WC_NO_HARDEN, so dropping it enabled nothing; it only
un-silenced the advisory #warning in settings.h, which -Werror turns
into a build failure for any USE_FAST_MATH + WOLFCRYPT_TZ_PSA build.
Define TFM_TIMING_RESISTANT, which is what makes tfm.c constant time.
2026-08-18 09:19:13 +02:00
Daniele Lacamera b9c32027bc F-9722: keep WC_NO_HARDEN out of software-DICE fast-math builds
The comment justified WC_NO_HARDEN on the grounds that 'wolfBoot only
does public asymmetric operations'. That is not true for software
DICE: with WOLFCRYPT_TZ_PSA and no WOLFBOOT_DICE_HW, src/dice/dice.c
retrieves the private IAK (wolfboot_attest_get_private_key) and signs
the attestation claims with wc_CoseSign1_Sign_ex(), and arch.mk still
selects USE_FAST_MATH for those builds. A configuration maintainer
trusting the comment would have left the private-key signing path
without timing hardening.

Gate the definition to verify-only configurations: WC_NO_HARDEN is
now defined only when WOLFCRYPT_TZ_PSA is absent or WOLFBOOT_DICE_HW
is set (hardware DICE keeps signing in the crypto engine), and the
comment states the actual rationale.

Verified with a preprocessor probe: plain fast-math and hardware DICE
still get WC_NO_HARDEN; software DICE no longer does.
2026-08-18 05:03:00 +02:00
Daniele Lacamera 3a3f66e1b4 F-9720: describe IMG_STATE_TESTING as the post-swap boot-confirmation state
The comment labeled IMG_STATE_TESTING as an 'ELF loading state', but
the constant is wolfBoot's general dual-bank confirm/rollback marker:
it is set on the BOOT partition after every swap (update_flash.c,
update_flash_hwswap.c, update_ram.c - none ELF-specific) and cleared
by wolfBoot_success(); if still present at the next boot it triggers
a rollback. A maintainer trusting the old comment could have treated
the state as inert on non-ELF targets and disabled the anti-brick
path.

Reword to the accurate description already used in
docs/flash_partitions.md, keeping the note that it only lives on the
boot partition so it cannot conflict with IMAGE_STATE_UPDATING.

Comment-only change; no code or behavior changes.
2026-08-18 05:01:22 +02:00
Alex Lanzano 4fb9e81b44
Merge pull request #853 from dgarske/zynqmp_sdhci_reset
SDHCI: fix silent read failures and unbootable warm reset with UHS-I cards
2026-08-14 12:51:20 -04:00
David Garske c8faa5adc2 Authenticate raw device tree via signed HDR_DEVICE_TREE_DIGEST TLV (Fenrir #7998) 2026-08-13 08:39:22 +02:00
David Garske 38ec1e1bed sdhci: fix silent read failures and unbootable warm reset with UHS-I cards 2026-08-11 15:37:56 -07:00
David Garske 2b3b7034a5 aarch64_efi: address PR818 review (measure cmdline, DTB GUID, size/page/desc fixes) 2026-08-10 21:03:50 +02:00
David Garske 4a16dce4f8 efi: authenticate the kernel command line via a signed HDR_CMDLINE manifest TLV 2026-08-10 21:03:50 +02:00
Daniele Lacamera 31f0168afc ARMORED: harden digest comparison against instruction skips 2026-08-05 20:13:44 +02:00
David Garske 5f40400e57 PolarFire SoC: address PR review
- wolfBoot_fit_memcpy: return int so a failed PDMA copy propagates instead
  of being swallowed. The weak default (memcpy) returns 0; the MPFS250 PDMA
  override returns -1 if any chunk's mpfs_pdma_memcpy() fails. Callers now
  fail closed: fit_load_image_inner returns NULL (kernel load then panics
  via update_disk.c), the update_disk DTS copy panics, and hal_dts_fixup
  returns an error on a failed L2->DDR copy-back.
- options.mk: gate -DSTACK_SIZE_PER_HART behind RISC-V arch (RISCV/RISCV64).
  The macro is only consumed by the RISC-V startup asm and the mpfs250-m.ld
  sed token, so it is no longer emitted for PPC/ARM/other targets. The
  unconditional default (?= 0) is kept because the linker sed always needs
  a value to substitute.
2026-08-03 12:27:22 +02:00