Commit Graph

292 Commits (9a4f80054689a315ebd5ea54c0f5bc065cc72516)

Author SHA1 Message Date
Brett Nicholas 25aa151f0b add asymmetric partition sizing for monolithic updates 2026-08-19 17:47:48 +02: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
Daniele Lacamera 6201ba4a38 sign: scrub the primary key when the key load fails
main() exit(1)'d on a key load failure. For the hybrid secondary key that
happens with the primary raw buffer live and the primary key object
initialized, so neither zero_and_free(kbuf) nor free_key() ran -- the case
F-8006 set out to fix. Jump to the tail cleanup instead; the exit status is
unchanged.

Also document why free_key() tolerates an uninitialized or already-freed
object, since load_key() has paths that produce both.
2026-08-12 13:21:08 +02:00
Daniele Lacamera f9957da523 F-8003: separate decoded key objects for hybrid signers
The sign tool kept a single file-static struct for the decoded private
key, so a hybrid run that picks two algorithms sharing one member (e.g.
ECC521 primary + ECC256 secondary, or RSA2048 + RSAPSS2048) had the
secondary load_key() re-init and overwrite the still-live primary key
before either signature was produced. The primary signature was then
made with the secondary key, and the final cleanup in main() dispatched
only on CMD.sign, so the secondary key never reached its algorithm
specific zeroizing free.

Give the primary and the secondary signer their own storage, select it
with key_obj(secondary) in load_key()/load_key_ecc()/load_key_rsa()/
sign_digest()/set_signature_sizes(), and free both keys at exit through
the new free_key() helper.
2026-08-11 09:25:54 +02:00
Daniele Lacamera 748fa8a19a F-8006: return errors from delta base-hash validation in sign tool
make_header_ex() validated the delta base image digest with direct exit(1)
calls. Those are reachable in normal use: base_diff() looks up the base
digest for the selected hash algorithm, and when the base image was signed
with a different algorithm the lookup yields NULL, yet make_header_delta()
is still called. Aborting there skips base_diff()'s cleanup (the temporary
patch file is left in /tmp) and, more importantly, main()'s
zero_and_free(kbuf, key_buffer_sz) and algorithm-specific key free, so the
raw and decoded private signing key are never scrubbed.

Use the function's existing 'failure:' path instead, which returns -1 and
propagates through base_diff() to main()'s unified cleanup.

Reaching 'failure:' from there uncovered a latent double fclose(): the
image-size probe closes 'f' without clearing it, so the cleanup block
closed the same stream again. Clear the pointer after the fclose().

Add unit-sign-delta-basehash-cleanup.py, which signs a SHA256 base image,
requests a SHA384 delta against it, and asserts the run fails with the
temporary patch file removed.
2026-08-11 09:13:31 +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
David Garske 34941079e1 Add aarch64_efi target: wolfBoot as an AArch64 UEFI application 2026-08-10 21:03:50 +02:00
Daniele Lacamera dfdcf7eeb5 F-7053: sign: propagate make_header() failure to the exit status
main() called make_header()/make_hybrid_header() and discarded their
return value. Both are wrappers around make_header_ex(), which returns
-1 on every "goto failure" path (image file not openable, header malloc
failure, firmware version out of range, certificate chain errors,
signing and output write errors). Since ret is initialized to 0 and is
only reassigned by the optional base_diff() delta step, a signing run
that produced no output image still terminated with status 0, so
Makefile recipes and CI treated the failure as success and moved on
with a missing or stale *_v<ver>_signed.bin. This was also asymmetric
with the key loading path just above, which exits on failure.

Capture the return value of both header helpers, skip the delta step
when header generation failed, and let main() return it.

Add tools/unit-tests/unit-sign-header-failure, covering the exit status
of both the plain and the hybrid signing path when the input image
cannot be opened.
2026-08-04 08:16:53 +02:00
Daniele Lacamera 675a927fa2 F-7054: sign: fail when the hybrid secondary key cannot be loaded
main() checked load_key() for the primary key but not for the hybrid
secondary key, and load_key() left *pubkey/*pubkey_sz untouched (or
dangling, after the ED25519/ED448 free(*pubkey)) on its failure paths.

With a missing or undecodable secondary key file the sign tool therefore
either silently emitted a manifest with no secondary public key hashed,
dereferenced a freed pubkey buffer and double-freed it, or crashed on the
uninitialized pubkey_sz2 stack value.

Clear *pubkey/*pubkey_sz on every load_key() failure path, initialize
pubkey_sz2, and exit(1) when the secondary key fails to load.

Add tools/unit-tests/unit-sign-hybrid-keyload, covering the missing-file
and decode-failure contracts of load_key() plus the end-to-end exit
status of the sign tool.
2026-08-04 08:13:36 +02:00
Mattia Moffa 190de90224 Clean up build flag usage, use trng healthtest in test-app 2026-07-31 14:33:56 +02:00
Mattia Moffa 60b9e87413 SHA256 acceleration for bootloader 2026-07-31 14:33:56 +02:00
Mattia Moffa 640d017610 Check key len for truncation; add unit test 2026-07-30 15:38:11 +02:00
Mattia Moffa e6c87d86a9 Add --custom-tlv-pubkey-der option to signing tool
Allows extracting a public key from a DER file and adding it in the same
format as the keystore:

- `X||Y` for ECC
- Raw for Ed25519/Ed448
- Public key DER for RSA
2026-07-30 15:38:11 +02:00
David Garske eaa39be9e4 renesas-rx: fix build for GCC RX 8.3/14.2 2026-07-30 15:32:31 +02:00
Brett Nicholas f5877b4de6 simplify comments 2026-07-22 09:51:39 -06:00
Brett Nicholas 95e90f2e91 revined comment 2026-07-22 09:42:45 -06:00
Brett Nicholas 8c476ae3a0 fixed aliased variable 2026-07-21 18:05:22 -06:00
Brett Nicholas 358fe03668 fix sign tool arg index error 2026-07-21 17:34:26 -06:00
Brett Nicholas 22b2fe5dc9 add custom file-backed TLV sign option 2026-07-21 16:19:04 -06:00
Brett Nicholas 6c148b2e9e increase custom TLV size limit to UINT16_MAX 2026-07-21 15:15:10 -06:00
Mattia Moffa 20307e47b5 Remove argc <= 14 limit in signing tool 2026-07-20 13:28:55 +02:00
Daniele Lacamera 9a25fae89d F-6127: fix custom-TLV 8-byte value saturation in arg2num
arg2num() parsed --custom-tlv values with signed strtoll(), which
saturates to LLONG_MAX (0x7FFFFFFFFFFFFFFF) on positive overflow. For
LEN==8 no masking is applied afterwards (unlike LEN 1/2/4), so any
value >= 2^63 silently encoded as 0x7FFFFFFFFFFFFFFF instead of the
value the user supplied, breaking the TLV encode/decode roundtrip.

Switch to strtoull() and reject (exit 16) when it reports ERANGE for
an 8-byte value, mirroring the existing fw_version range check.
2026-07-02 15:28:09 +02:00
Daniele Lacamera 8df96895f6 F-6408: zeroize UDS from OTP keystore generator's heap and stack buffers
otp-keystore-gen.c reads the device root UDS into the stack buffer
`uds` and copies it into the heap buffer `otp_buf` at OTP_UDS_OFFSET,
then on every exit path calls free(otp_buf) without wiping it first,
and never clears `uds`. Both copies of the highest-value device secret
remain in the host process's freed heap chunk and stack frame.

Add a local secure_zero() helper (no wolfSSL dependency, matching this
standalone host tool's existing bare-gcc build) and call it on the
success path and on the write-failure/short-UDS-read error paths,
before free()/exit(), mirroring the zeroize-before-release pattern
already used elsewhere in this tree (src/x86/ata.c,
src/x86/ahci.c). Paths that exit before `uds` is populated are left
untouched since there is no secret to wipe yet.
2026-07-02 14:56:48 +02:00
Daniele Lacamera 1690522078 F-3970: serialise custom TLV integer values through header_store_u64_le
The --custom-tlv TAG LEN VAL path in make_header_ex() passed
&CMD.custom_tlv[i].val (a raw uint64_t pointer) directly to
header_append_tag(), which does a memcpy.  On big-endian build hosts the
first LEN bytes of the uint64_t are the high bytes, producing the wrong
LE encoding (e.g. 4-byte value 0x12345678 encodes as 00 00 00 00).  The
fix serialises through header_store_u64_le() before calling
header_append_tag(), matching the pattern already used by
header_append_tag_u16/u32/u64 for all system TLVs.

Add unit-sign-custom-tlv-le.py to verify the LE byte encoding of 4-byte
and 8-byte custom TLV values in the signed image header.
2026-06-11 17:53:25 +02:00
Daniele Lacamera 9e390e8fce F-4414: replace strtol with strtoul for fw_version to fix saturation on 32-bit-long platforms
strtol saturates to LONG_MAX (INT32_MAX) and sets errno=ERANGE for
version strings above 2147483647 on Windows LLP64 and 32-bit hosts,
silently encoding the wrong version. strtoul covers the full uint32_t
range on all platforms (ULONG_MAX >= UINT32_MAX). Add explicit
out-of-range error to match existing pattern (lines 2063-2071).
2026-06-10 21:01:17 +02:00
Daniele Lacamera aebecba524 F-4419: zeroize LmsKey on all error paths in keygen_lms
Replace bare exit(1) calls with goto cleanup / exit_code pattern matching
keygen_xmss; wc_LmsKey_Free + wc_ForceZero now run on every error path
after wc_LmsKey_Init succeeds, preventing LMS private-state exposure.
2026-06-10 21:01:17 +02:00
Daniele Lacamera ef16945b24 F-4420: zeroize XmssKey on all error paths in keygen_xmss
Replace bare exit(1) calls with goto cleanup / exit_code pattern matching
keygen_ml_dsa; wc_XmssKey_Free + wc_ForceZero now run on every error path
after wc_XmssKey_Init succeeds, preventing XMSS private-state exposure.
2026-06-10 21:01:17 +02:00
Daniele Lacamera 051c41cdba F-4786: fix delta_base_version LE decode in base_diff for big-endian hosts
sign_tool_find_header returns a raw pointer into LE-encoded TLV bytes.
Aliasing it as uint32_t* and dereferencing produces the wrong value on
big-endian build hosts (e.g. version 5 read as 0x05000000). Decode
explicitly byte-by-byte like header_store_u32_le does for writes.
2026-06-10 21:01:16 +02:00
Daniele Lacamera 5958185968 F-4788: zeroize stack ed25519_key after Free in keygen_ed25519 cleanup 2026-06-10 21:01:16 +02:00
Daniele Lacamera 793cec45e3 F-4969: zeroize stack RsaKey after FreeRsaKey in keygen_rsa cleanup 2026-06-10 21:01:16 +02:00
Daniele Lacamera ca3e76a9bc F-4970: zeroize stack ecc_key after Free in keygen_ecc cleanup
wc_ecc_free does not zero the struct; add wc_ForceZero(&k, sizeof(k))
immediately after, matching the pattern used for ed448 (F-4971), ml_dsa
(F-4972), and the d[] / priv_der[] zeroing already present on the
following lines.
2026-06-10 21:01:16 +02:00
Daniele Lacamera 652febdcef F-4971: zeroize stack ed448_key after Free in keygen_ed448 cleanup
wc_ed448_free does not zero the struct; add wc_ForceZero(&k, sizeof(k))
immediately after, matching the pattern used for ml_dsa (F-4972) and the
priv[] zeroing already present on the preceding line.
2026-06-10 21:01:16 +02:00
Daniele Lacamera f20cd3022a F-4972: zeroize stack wc_MlDsaKey after Free in keygen_ml_dsa cleanup
wc_MlDsaKey_Free does not zero the struct; add wc_ForceZero(&key,
sizeof(key)) immediately after, matching the explicit pattern already
used in the adjacent keygen_xmss function.
2026-06-10 21:01:16 +02:00
Daniele Lacamera d85feeb8b2 Address Copilot review comments 2026-06-09 15:52:07 +02:00
Daniele Lacamera 74b8fc0664 F-5131: fix stale delta inverse-patch offset when cert chain expands header
base_diff() captured patch_inv_off = len3 + CMD.header_sz before calling
make_header_delta(), which signs the delta image via make_header_ex(is_diff=1).
When a certificate chain is present, the delta (is_diff=1) header needs ~72
more bytes than the non-delta header for the four delta TLVs plus the base-hash
TLV. For a window of cert-chain sizes, header_required_size(is_diff=0) still fit
the current CMD.header_sz while header_required_size(is_diff=1) did not, so
make_header_ex(is_diff=1) grew CMD.header_sz to the next power of two *after*
patch_inv_off was captured. The HDR_IMG_DELTA_INVERSE TLV then encoded a stale,
too-small offset; the bootloader (update_flash.c) uses it as a raw byte offset
into the update partition to locate the inverse patch, so rollback read from the
wrong offset and failed.

Resolve the is_diff=1 header-size expansion (same logic as make_header_ex)
before computing patch_inv_off. Add unit-sign-delta-cert-inv-off.py, which signs
an ed25519 delta with a 300-byte chain (inside the triggering window) and
asserts the inverse patch is the trailing HDR_IMG_DELTA_INVERSE_SIZE bytes of
the file; it fails before this fix.
2026-06-09 15:52:07 +02:00
Daniele Lacamera 84d5bd3dde F-5352: emit 4-byte delta size TLVs from Python signer
sign.py encoded HDR_IMG_DELTA_SIZE and HDR_IMG_DELTA_INVERSE_SIZE with a
2-byte length via struct.pack("<H", ...), but wolfBoot_get_delta_info()
accepts those tags only when wolfBoot_find_header() returns
sizeof(uint32_t). Delta images produced by sign.py were therefore signed
with parseable TLVs yet rejected by the bootloader before the patch was
applied. Encode both size TLVs as 4-byte little-endian values, matching
sign.c (header_append_tag_u32) and the bootloader parser.

Add a regression test that signs a real delta image with sign.py and
asserts the bootloader-side parse recovers each delta TLV with the
required 4-byte length.
2026-06-09 15:50:48 +02:00
Tobias Frauenschläger 6e60abd034 Continue the ML-DSA renaming 2026-05-19 11:21:20 -07:00
Tobias Frauenschläger cab04ad789 Update wolfssl submodule to latest master
* file level rename for ML-DSA
* Add missing source file to build system
* Update some macros
* Other minor fixes
* Update size limitations for some slight increases
2026-05-18 23:02:54 -07:00
Mattia Moffa 172ecdc975 Sign tool: fix wrong fread/fwrite API usage when HAVE_MMAP==0
(F#3534)
2026-05-06 19:03:12 +02:00
Thomas Cook 8d96afb7e2 Fix lms/xmss header includes. 2026-05-05 14:08:35 +02:00
Daniele Lacamera a60461f18b Fix XMSS keygen param fallback
F/3306
2026-04-29 12:30:23 +02:00
Brett Nicholas 65d84a29ec Add SW-only RSA PSS 2026-04-28 15:02:57 +02:00
Brett Nicholas 401c034690 Fix XMSS and ML_DSA keygen type mismatch between image headers and keystore by unifying AUTH_KEY_*/KEYGEN_* constants 2026-04-28 15:02:57 +02:00
Daniele Lacamera 776378ca78 Preparing release v2.8.0 + update copyright 2026-04-16 13:11:56 +02:00
Daniele Lacamera 91e0b16788 keygen_lms: zero LmsKey after free
F/2589
2026-04-15 17:26:18 +02:00
Daniele Lacamera a64fa8fbcf Addressed Fenrir's review comments + fixed more regressions 2026-04-14 17:59:30 +02:00
Daniele Lacamera 00342ac584 Addressed more copilot's comments 2026-04-14 17:25:18 +02:00
Daniele Lacamera 9ac6b1f485 Fixed more regressions 2026-04-14 16:47:11 +02:00
Daniele Lacamera 76f0b3cba9 keygen_xmss: zeroize XmssKey after free
F/2590
2026-04-14 14:32:45 +02:00
Daniele Lacamera cc7c3bbb68 Reject oversized signature TLV lengths
F/2585
2026-04-14 14:25:10 +02:00