Fenrir fixes 2026 08 24 - #870
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR is a batch of correctness and security hardening fixes across wolfBoot’s boot paths and HALs, with accompanying regression unit tests to prevent recurrence.
Changes:
- Hardened boot-time validation and failure handling (RAM-boot “both images failed” panic, ELF load abort on MMU map failure, FDT layout validation before memmove).
- Improved security of fwTPM veneer by staging both command and response in secure memory before interacting with the processor.
- Fixed several HAL logic bugs (STM32 fast-write tail handling, T10xx timeout propagation, P1021 NAND erase loop address advance) and expanded unit-test coverage for these regressions.
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/unit-tests/unit-update-ram.c | Adds regression coverage for panicking when both RAM-boot images fail verification. |
| tools/unit-tests/unit-t10xx-flash-status.c | New unit test to ensure T10xx flash write/erase timeouts propagate as errors. |
| tools/unit-tests/unit-stm32g4-write.c | New unit test ensuring STM32G4 fast-write path doesn’t over-read short tails. |
| tools/unit-tests/unit-p1021-erase-advance.c | New unit test verifying P1021 erase loop advances the target address per block. |
| tools/unit-tests/unit-hifive1-flash-write.c | New unit test for HiFive1 partial-page write sizing and over-read prevention. |
| tools/unit-tests/unit-fwtpm-rsp-overrun.c | New unit test ensuring fwTPM response is staged to prevent caller-buffer overruns. |
| tools/unit-tests/unit-fwtpm-cmd-toctou.c | New unit test ensuring fwTPM command is staged to prevent TOCTOU/DMA rewrite attacks. |
| tools/unit-tests/unit-fdt-memrsv-wrap.c | New unit test for rejecting malformed/wrapped FDT layouts before memmove. |
| tools/unit-tests/unit-elf-mmu-fail.c | New unit test verifying ELF load aborts if mmu_cb mapping fails. |
| tools/unit-tests/unit-ecc-raw-der.c | New unit test verifying ECC raw R||S to DER conversion handles leading-zero fields correctly. |
| tools/unit-tests/Makefile | Wires new unit tests and extraction rules into the unit-test build. |
| src/update_ram.c | Prevents infinite fallback alternation in RAM-boot by panicking once both candidates fail. |
| src/riscv_sbi.c | Updates remote-fence completion protocol to publish completion only after fences execute. |
| src/image.c | Fixes ECC raw-to-DER conversion by passing full-width R/S fields into wc_ecc_rs_raw_to_sig(). |
| src/fwtpm_callable.c | Stages fwTPM commands/responses in secure buffers and zeroes staging before returning. |
| src/fdt.c | Validates FDT layout using 64-bit arithmetic to avoid overflow/wrap-based memmove corruption. |
| src/elf.c | Aborts ELF loading on mmu_cb mapping failure (no silent PT_LOAD drops). |
| hal/stm32g4.c | Requires at least 8 bytes remaining before taking the STM32 double-word fast write path. |
| hal/stm32g0.c | Same STM32 fast-write tail-length fix as stm32g4. |
| hal/stm32c0.c | Same STM32 fast-write tail-length fix as stm32g4. |
| hal/nxp_t10xx.c | Propagates status-wait timeout errors from program/erase operations to callers. |
| hal/nxp_p1021.c | Advances erase address per-iteration in the P1021 multi-block NAND erase loop. |
| hal/library.c | Propagates verification failure return codes from wolfBoot_start() to process exit code. |
| .github/workflows/test-library.yml | Updates CI to rely on non-zero exit codes for failures now that wolfBoot_start() propagates errors. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The double-word fast path in hal_flash_write() on STM32G4, STM32C0 and STM32G0 was selected on 'len - i > 3' but programs an 8-byte unit, so an aligned 4-7 byte tail read up to 4 bytes past the caller's buffer and programmed those bytes into flash. Require len - i >= 8 before taking the fast path. Shorter tails fall through to the existing RMW branch, which rewrites the unit with the out-of-range bytes read back from flash, so nothing past len is read or programmed. Add unit-stm32g4-write (same harness as the STM32L5/STM32U5 twins), which fails on the 60-byte tail before the fix.
…M verify path The wolfHSM verify path of wolfBoot_verify_signature_ecc() converts the fixed-width raw R||S signature to DER with wc_ecc_rs_raw_to_sig(). It passed the minimal field sizes (mp_unsigned_bin_size) while leaving the pointers at the start of each fixed-width field, so whenever R or S had a leading zero byte the conversion encoded a zero-padded integer with the low bytes truncated, and wc_ecc_verify_hash() rejected an otherwise valid signature (each component has roughly a 1 in 256 chance of a leading zero). Pass the full-width fields (point_sz for both): the raw signature is fixed-width and left-zero-padded, and the conversion strips the padding itself. The multiprecision sizing only existed to compute the minimal lengths and is dropped with the fix. unit-ecc-raw-der signs until a leading-zero signature shows up, then checks that the minimal-size pattern rejects it while the full-width pattern accepts it, and that both patterns agree for leading-zero-free signatures. Verification: - Built: src/image.c syntax-clean with WOLFBOOT_ENABLE_WOLFHSM_CLIENT (gcc -fsyntax-only, __WOLFBOOT, ECC256/SHA256 config, partition stubs); normal library build via make test-lib. - Tested: unit-ecc-raw-der 3/3: the minimal pattern rejects the leading-zero signature the full-width pattern accepts; both agree on leading-zero-free signatures. - Pitfalls: no key material touched; the dropped mp values had no matching mp_clear before the fix either (stack variables). - Style: cstyle-check.sh on src/image.c flags two pre-existing violations (L1869 anonymous union, L2079 C99 declaration) outside this change; the new test trips the same uncrustify pointer-alignment class the unit-stm32l5/u5-write twins trip and matches their local style. - Message: F-11024: prefix, no co-author trailers. - Unverified: no wolfHSM target builds in CI; the HSM branch was checked by syntax-only compile, not a full target build.
wolfBoot_start() in hal/library.c ended its exit: path with an unconditional 'return 0;', so a rejected image (bad header, hash or signature) still made the test-lib process exit 0. main() propagates wolfBoot_start()'s return value, so the failure was only visible in the printed "Failure" message, which the test-library workflow had to grep for (TODO referencing PR wolfSSL#625). Return ret, which carries the wolfBoot_verify_*() error on every path that reaches exit: with a failure. The success path never returns: do_boot() jumps to the firmware. The test-library workflow drops the status-rewriting workaround and asserts the non-zero exit code directly, keeping the "Failure" message check as a diagnostic. Verification: - Built: make test-lib (host, library.config, ED25519/SHA256). - Tested: local repro of the workflow flow: corrupt the last byte of a signed image; before the fix the process exited 0 while printing "Failure -1", after the fix it exits 255; a valid image still exits 0 with "Firmware Valid". - Pitfalls: 'return ret' only changes the error paths; do_boot() does not return on success. - Style: the cstyle-check.sh FMT flag on hal/library.c is present on the pre-change file as well (not introduced here). - Message: F-9749: prefix, no co-author trailers.
elf_load_image_mmu() skipped a segment (continue) when its mmu_cb mapping failed, then kept loading the rest, published the ELF entry point and returned success for a partially loaded image. The x86 FSP payload path (boot_x86_fsp_payload.c) passes a real mmu_cb and only panics on a non-zero return, so the buggy continue booted a payload with a missing segment. Return -6 with a fail-loud message, matching the program-header clobber guard that aborts for the same reason: never silently drop a a PT_LOAD segment. unit-elf-mmu-fail fails the first segment's mapping and checks the load is rejected with no entry point published; a second test checks successful mappings still load the segments and publish the entry. Verification: - Built: unit test compiles elf.c (WOLFBOOT_ELF config); elf.c syntax-clean under the WOLFBOOT_FSP config (gcc -fsyntax-only). - Tested: unit-elf-mmu-fail 2/2; pre-fix the failure-path test got ret == 0 (entry published for a partially loaded image). - Pitfalls: no caller switches on the exact code (all check != 0); -6 is new and dedicated to the mapping failure. - Style: cstyle-check.sh on src/elf.c flags pre-existing FMT/R1 issues also present on the pre-change file; the new test trips the uncrustify pointer-alignment class the sibling unit tests trip and matches their local style. - Message: F-11027: prefix, no co-author trailers.
The RAM boot loop switched to the other partition on a verification failure (active ^= 1, continue) with a comment claiming the failing image was invalidated, but nothing was invalidated: wolfBoot_fallback_is_possible() only sees that both partitions carry nonzero versions. Two present but invalid images therefore alternated indefinitely, re-verifying forever. (The flash path does not have this hole because it erases the failing partition, which zeroes its version and makes the second fallback check fail.) Track the candidates attempted this boot: once both partitions have failed, panic with a clear message. Same-version images are used in the regression test so the anti-rollback guard cannot mask the alternation. unit-update-ram gains test_both_images_corrupted_panics: both partitions carry valid-version images with corrupted digests; the boot must panic after exactly two attempts. Pre-fix the loop ran unbounded (process had to be killed; ~60k partition switches in 30 s). Verification: - Built: unit-update-ram, unit-update-ram-enc, unit-update-ram-nofixed, unit-update-ram-uboot all compile. - Tested: unit-update-ram 20/20, unit-update-ram-nofixed 3/3, unit-update-ram-uboot 5/5; the new test shows Boot fail, Update fail, panic. - Pitfalls: attempt tracking is per boot session (local), no new persistent state; the flash path is untouched. - Style: cstyle-check.sh flag count on both changed files is unchanged from the pre-change versions (pre-existing FMT/R1). - Message: F-11028: prefix, no co-author trailers. - Note: unit-update-ram.c defines 21 tests but wires 20 into the suite (test_forward_update_samesize_notrigger was never added); pre-existing, left as-is.
sbi_ipi_irq() read-and-cleared the per-hart op word before executing the requested fence.i/sfence.vma, and sbi_wait_ipi_done() treated a zero op word as completion. The SBI remote-fence ecalls are synchronous, so a requester could return while the target had not yet run its fence (e.g. resume relying on a new page table before the target flushed its TLB). Split the protocol into pending work and completion state, per hart: ipi_done[h] is incremented by the target only after it has executed the fence ops it consumed; the requester snapshots it into ipi_wait_gen[h] before posting (so a concurrent coalesced consume of two requesters' ops still increments past both snapshots) and waits until ipi_done[h] passes the snapshot. SSIP posts are fire-and-forget and do not wait, as before. Verification: - Built: riscv-none-elf-gcc 15.2 -fsyntax-only -Wall with WOLFBOOT_RISCV_MMODE + WOLFBOOT_MMODE_SMODE_BOOT: clean. - Tested: none (race condition; the contract skips failing-first tests for races, and the file is MPFS S-mode monitor code with no host or CI build target). - Pitfalls: the shared DTIM struct gains two per-hart arrays; the struct is self-initialized under init_magic by this same code on every hart, so no cross-version ABI is broken. A target that never runs M-soft still hits the bounded spin timeout as before. The completion increment covers only fence ops, matching the only waiting call sites (both RFENCE paths). - Style: cstyle-check.sh flag count unchanged from the pre-change file (3 pre-existing). - Message: F-11029: prefix, no co-author trailers. - Unverified: no multi-hart runtime execution (MPFS board only).
hal_flash_status_wait() returns -1 when the NOR does not settle its status bits within the poll budget, but hal_flash_write() and hal_flash_erase() discarded the result and returned 0 unconditionally: a stuck program or erase reported success, and the update flow continued as if the flash held the new image. Capture every wait result and return it to the caller on the first failure. No state-restore command is needed: this driver works through the memory-mapped QPI window, where reads are plain loads and the controller issues the read command per access, so there is no device command state to recover. unit-t10xx-flash-status runs the real extracted functions against a mock QPI status model (offset 0 reports the DQ status byte: toggling while busy, 0x44 after a program, 0x4C after an erase). A stuck device burns the full 200 ms / 1.1 s poll budget with a no-op udelay, so the timeout path runs in milliseconds. Verification: - Built: powerpc-linux-gnu-gcc -fsyntax-only -Wall with TARGET_nxp_t1024: clean. - Tested: unit-t10xx-flash-status 4/4; pre-fix both timeout tests got ret == 0 from a stuck device, now -1. Success paths (write lands in the model, erase completes) unchanged. - Pitfalls: the first failing page/sector now aborts the rest of the operation, which is the desired behavior (the caller aborts the update); no callers depended on the unconditional 0. - Style: cstyle-check.sh flag count on hal/nxp_t10xx.c unchanged from the pre-change file; the new test trips only the uncrustify pointer-alignment class the sibling unit tests trip. - Message: F-11033: prefix, no co-author trailers. - Unverified: no T10xx board execution.
ext_flash_erase() decremented the remaining length each iteration but never advanced the address, so the derived page (address / page_size) was identical every pass: the first block of the range was re-erased for the whole loop and every later block was left intact (the caller then programmed an update image into un-erased NAND). The sibling ext_flash_write() loop already advanced address/pos/data and was not affected. Advance address by block_size after each successful erase. unit-p1021-erase-advance runs the real extracted function against mocked ELBC register access and records the page programmed per erase command: two blocks must hit page 0 then page 32 (16 KiB block / 512 page), and a failing command must stop the loop after one attempt. Verification: - Built: powerpc-linux-gnu-gcc -fsyntax-only -Wall with TARGET_nxp_p1021: clean. - Tested: unit-p1021-erase-advance 2/2; pre-fix the second erase re-targeted page 0. - Pitfalls: single-block erases (len <= block_size) behave exactly as before; the error path is unchanged (break on hal_flash_command failure). - Style: cstyle-check.sh flag count on hal/nxp_p1021.c unchanged from the pre-change file; the new test trips only the uncrustify pointer-alignment class the sibling unit tests trip. - Message: F-11034: prefix, no co-author trailers. - Unverified: no P1021 board execution.
…write hal_flash_write() in hal/hifive1.c selected the page path and clamped the partial-page length from the original total len instead of the bytes still remaining (len - j). A page-aligned multi-page write that ended in a partial page therefore took the full-page branch on the last iteration: it read past the end of the caller's buffer and programmed a full 256-byte page where only the remaining bytes were requested, clobbering flash past the update range. Compute remaining = len - j at the top of the loop and use it for both the branch test and the rel_len clamp; j still advances only by the bytes actually consumed (256 on the full-page path, rel_len on the partial path). unit-hifive1-flash-write runs the real extracted function against a mock fespi model (FLASH_BASE points at a flash image buffer, fespi_write_address/fespi_sw_tx program into it, and the RMW path reads the image back through FLASH_BASE as on hardware). The regression case is a 356-byte aligned write: the last page's tail must stay erased, which fails pre-fix (the over-read bytes are programmed instead). Verification: - Built: riscv-none-elf-gcc 15.2 -fsyntax-only -Wall with ARCH_RISCV: clean. - Tested: unit-hifive1-flash-write 3/3; pre-fix the 356-byte case wrote non-erased bytes past offset 356 of the flash image. Unaligned single-page RMW and exact-full-page cases unchanged. - Pitfalls: relative (sub-FLASH_BASE) addresses are accepted as-is by the function, which is what the test passes so the 32-bit address parameter never carries a 64-bit host pointer. - Style: cstyle-check.sh flag count on hal/hifive1.c unchanged from the pre-change file; the new test trips only the uncrustify pointer-alignment class the sibling unit tests trip. - Message: F-11035: prefix, no co-author trailers. - Unverified: no HiFive1 board execution.
wcs_fwtpm_transmit() validated the caller-supplied response capacity and then passed that buffer directly to FWTPM_ProcessCommand with rspLen initialized to the capacity. The fwTPM processor emits a 10-byte TPM error response even for a malformed short command, regardless of the offered capacity, so a non-secure caller offering less than 10 bytes got an out-of-range write into its response buffer before the wrapper compared rspLen against the capacity. Process into a max-sized staging buffer inside the veneer and copy to the caller's buffer only after verifying the produced length fits the snapshotted capacity; when it does not fit, return TPM_RC_FAILURE without touching the buffer. The staging buffer is file-scope static: the CMSE secure callable is not preemptible, so no locking is needed. unit-fwtpm-rsp-overrun includes the real fwtpm_callable.c and mocks FWTPM_ProcessCommand to emulate the processor's behavior of writing the full 10-byte error response no matter the offered capacity. A 6-byte capacity must leave the guard bytes past the capacity intact (fails pre-fix: bytes 6-9 were overwritten); 16-byte and exact-10 capacities must receive the full response. Verification: - Built: unit tests compile the real veneer (host, poisoned fwtpm headers, same pattern as unit-fwtpm-nv-oob). - Tested: unit-fwtpm-rsp-overrun 3/3 (pre-fix the short-capacity test caught the overrun at offset 6); sibling unit-fwtpm-nv-oob 4/4 after the change. - Pitfalls: the copy uses the snapshotted capacity taken before the call, so a concurrent NS write to *rspSz cannot widen the range; the NS_R/NS_RW checks are unchanged. - Style: cstyle-check.sh flag count on src/fwtpm_callable.c unchanged from the pre-change file; the new test trips only the uncrustify pointer-alignment class the sibling unit tests trip. - Message: F-11043: prefix, no co-author trailers. - Unverified: no CMSE/armclang build and no m33mu emulator run here (lib/wolftpm is not checked out in this tree); the trustzone-emulator workflow covers the full build on push.
wcs_fwtpm_transmit() verified that cmd identifies non-secure memory and then passed that mutable buffer directly to FWTPM_ProcessCommand. The processor parses the packet more than once (authentication, then handler execution), so a DMA-capable non-secure attacker who rewrites the command buffer in the window between the two parses can make the authenticated command differ from the executed command. Copy exactly cmdSz bytes into a secure staging buffer after the range validation and invoke the processor only on that copy: an NS DMA master cannot rewrite secure memory, so both parses see the same bytes. The command and response staging are zeroed before returning (the response may carry auth tags or unsealed data). unit-fwtpm-cmd-toctou includes the real fwtpm_callable.c and mocks FWTPM_ProcessCommand with two parse points (authentication, execution). The test plays the attacker, rewriting the NS command buffer at the window between the parses - the mock may only touch the caller's buffer, never secure staging, mirroring the hardware boundary. Pre-fix the processor authenticated the original bytes and executed the rewritten ones (test fails); post-fix both parses see the original command. Verification: - Built: unit tests compile the real veneer (host, poisoned fwtpm headers, same pattern as unit-fwtpm-nv-oob). - Tested: unit-fwtpm-cmd-toctou 2/2 (red demonstrated against the pre-fix veneer via git stash of the fix); sibling unit-fwtpm-rsp-overrun 3/3 and unit-fwtpm-nv-oob 4/4 after the change. - Pitfalls: the staging copy happens after all NS range checks and before any processor access; zeroing covers the full staging buffers regardless of the produced length. - Style: cstyle-check.sh flag count on src/fwtpm_callable.c unchanged (1 pre-existing); the new test trips only the uncrustify pointer-alignment class the sibling unit tests trip. - Message: F-11044: prefix, no co-author trailers. - Unverified: no CMSE/armclang build and no m33mu emulator run here (lib/wolftpm is not checked out in this tree); the trustzone-emulator workflow covers the full build on push.
fdt_add_mem_rsv() added the 32-bit string-block offset and size without overflow checks. A wrapped data_end bypassed the capacity check, and the same wrapped expression derived the memmove length, so a malformed (or attacker-supplied) DTB produced a huge memmove - broad boot-time memory corruption. fdt_check_header validates only magic and version, so raw-DTB callers reach this code with inconsistent layout fields. Compute the block end in 64-bit, validate the layout before touching it (structure block starts after the reserve map terminator, string block after the structure block, shifted layout fits in totalsize), and derive the move length only from the validated 64-bit end. The reserve-map scan bound uses 64-bit arithmetic as well, so a wrapped 32-bit sum cannot pass it. unit-fdt-memrsv-wrap extracts the real fdt_add_mem_rsv (plus the byte-order helpers) and feeds it crafted DTB headers: - a wrapped end below off_dt: pre-fix the memmove length wraps to ~2^32 and the process segfaults; post-fix rejected (-FDT_ERR_NOSPACE) - a wrapped end inside [off_dt, total): pre-fix the layout was accepted (ret == 0) with a silently corrupted FDT; post-fix rejected - a consistent layout: the entry is inserted, the terminator moves down one, structure and string blocks shift by 16 bytes, and the header offsets follow (regression guard, passed pre-fix as well) Verification: - Built: unit test compiles the extracted real function (host). - Tested: unit-fdt-memrsv-wrap 3/3 post-fix; pre-fix (fix stashed) 1 segfault + 1 assertion failure on the wrap cases, valid case passing - red demonstrated on both corruption modes. - Pitfalls: the helper that builds the crafted DTB only writes block contents where the offsets fit the buffer, so the malformed cases cannot corrupt memory in the test itself before reaching the code under test; validation runs before any block access. - Style: cstyle-check.sh flag count on src/fdt.c unchanged (1 pre-existing FMT class); the new test trips only the uncrustify class the sibling unit tests trip. - Message: F-11045: prefix, no co-author trailers. - Unverified: no target build needed (pure C, host-compiled from the real source); fdt.c compiles as part of the normal wolfBoot build paths unchanged.
Four review items on this PR, all valid: - unit-hifive1-flash-write: the over-read test assumed the canary array landed right after the data array on the stack, which C does not guarantee (and the canary was filled but never read). Use a single contiguous buffer split into data and canary regions so an out-of-range read lands on known bytes, and assert the canary stays intact after the call. - unit-fwtpm-rsp-overrun: rsp_fitting_capacity_gets_response checked the guard bytes with a loop bounded by rspSz, which the call had already overwritten to the produced size (10), so the loop never ran. Snapshot the offered capacity before the call and bound the guard check with that. - unit-fdt-memrsv-wrap: put32() encoded header fields by calling fdt32_to_cpu(), which reads as the inverse operation. Call cpu_to_fdt32() directly, matching how production code writes FDT fields. - Makefile: the five new extraction headers (fdt_memrsv, hifive1 flash write, t10xx flash status, p1021 erase x2) were not in GENERATED_SRC, so make clean left them behind. Listed now. Verification: - Built: the three affected unit tests compile clean on the rebased branch. - Tested: unit-hifive1-flash-write 3/3, unit-fwtpm-rsp-overrun 3/3, unit-fdt-memrsv-wrap 3/3; make -n clean now removes all five extraction headers. - Pitfalls: the hifive1 test now passes an explicit request length (data is a pointer into the shared buffer, so sizeof would be wrong). - Style: cstyle-check.sh flag count unchanged per file (1 pre-existing FMT pointer-alignment class each). - Message: no co-author trailers.
danielinux
force-pushed
the
fenrir-fixes-2026-08-24
branch
from
August 25, 2026 07:02
58f3748 to
83a1f73
Compare
dgarske
approved these changes
Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
d44ecc4 F-11045: validate the FDT layout before the memreserve memmove
972913d F-11044: stage the fwTPM command in secure memory before processing
fe7eb45 F-11043: stage the fwTPM response before copying to the caller buffer
5f914b6 F-11035: size the final partial page from remaining bytes in hifive1 write
572cef2 F-11034: advance the address in the P1021 multi-block NAND erase loop
aae94a6 F-11033: propagate program/erase timeouts from the T10xx flash HAL
b006b6f F-11029: publish IPI fence completion only after the fence executes
019c7f0 F-11028: panic when both RAM-boot images fail verification
8c97046 F-11027: abort the ELF load when an mmu_cb mapping fails
9e4abd4 F-9749: propagate the verify result from wolfBoot_start to the exit code
d8ffd2e F-11024: pass full-width fields to wc_ecc_rs_raw_to_sig in the wolfHSM verify path
2964b37 F-11023: require a full double word in the STM32 fast write paths