Add WOLFCRYPT_TZ_WOLFHSM TrustZone engine for STM32H5#769
Open
aidangarske wants to merge 13 commits into
Open
Conversation
3 tasks
- New WOLFCRYPT_TZ_WOLFHSM build flag, mutually exclusive with
WOLFCRYPT_TZ_PKCS11 / _PSA / _FWTPM
- Extract WOLFHSM_CLIENT_OBJS and WOLFHSM_SERVER_OBJS shared
variables; legacy WOLFHSM_CLIENT/SERVER blocks now reference them
to share file lists with the new TZ engine
- New config/examples/stm32h5-tz-wolfhsm.config (one-line delta
from stm32h5-tz-fwtpm.config)
- NS test-app RNG seed routes through wcs_get_random (same pattern
as PKCS11 / fwTPM)
No NSC entries or wolfHSM-specific code yet — Phase 0 only wires up
the build flag and validates existing-engine compatibility. Builds
cleanly with stm32h5-tz-wolfhsm.config; existing TZ configs and the
sim wolfHSM client/server configs continue to build.
The four files to stage:
- options.mk (mutex guards, shared-vars refactor, TZ_WOLFHSM block)
- test-app/Makefile (NS-side TZ_WOLFHSM block + alias)
- test-app/wcs/user_settings.h (RNG seed CFG)
- config/examples/stm32h5-tz-wolfhsm.config (new)
Phase 1 of the WOLFCRYPT_TZ_WOLFHSM=1 lane: hosts a wolfHSM server in the
secure world and exposes it across the NSC boundary via a single packet-
shaped veneer (wcs_wolfhsm_transmit), mirroring fwTPM lane 2's shape.
NS test-app runs a wolfHSM client; wc_RNG_GenerateBlock with WH_DEV_ID
round-trips through the bridge.
- include/wolfboot/wcs_wolfhsm.h: NSC entry declarations
- src/wolfhsm_callable.c: secure-side server init (RNG + ramsim NVM +
comm + transport) and the single-NSC veneer with TOCTOU single-fetch
defense on *rspSz
- src/wc_callable.c: hook wcs_wolfhsm_init() into wcs_Init()
- test-app/wcs/wolfhsm_stub.c: NS .bss buffers + transport context
- test-app/wcs/wolfhsm_test.c: client init + CommInit handshake +
RNG-via-WH_DEV_ID exerciser; auto-runs at boot
- options.mk + test-app/Makefile: wire the WOLFHSM_*_OBJS lists, the
ramsim NVM, the wolfssl crypto primitives, and a separate wolfhsm_obj/
build dir so NS-side compiles wolfHSM with WOLFHSM_CFG_ENABLE_CLIENT
while the secure side gets WOLFHSM_CFG_ENABLE_SERVER
- user_settings.h (both): set WOLF_CRYPTO_CB / HAVE_ANONYMOUS_INLINE_-
AGGREGATES=1 / WOLFSSL_KEY_GEN whenever WOLFCRYPT_TZ_WOLFHSM is set;
NS RNG seed routes through wcs_get_random
- D25 hardware test recipe wired in via WOLFBOOT_TZ_TEST_NO_BKPT
Builds clean against stm32h5-tz-wolfhsm.config; m33mu CI passes:
wolfHSM CommInit ok (client=1 server=56)
wolfHSM RNG ok: ...
wolfHSM NSC tests passed
[BKPT] imm=0x7f / [EXPECT BKPT] Success
The auto-test block in app_stm32h5.c gates its bkpt #0x7f / #0x7e on
WOLFBOOT_TZ_TEST_NO_BKPT, but the make-flag was never propagated to
CFLAGS. Building with make WOLFBOOT_TZ_TEST_NO_BKPT=1 now actually
swaps the BKPTs for printf(WOLFHSM_TZ_TEST_{PASS,FAIL}) + while(1)
loops, which is the canonical hardware-test path (per D25) since
real silicon HardFaults on bkpt without a debugger attached.
Verified on NUCLEO-H563ZI hardware:
wolfHSM CommInit ok (client=1 server=56)
wolfHSM RNG ok: <16 random bytes>
wolfHSM NSC tests passed
WOLFHSM_TZ_TEST_PASS
- include/wolfboot/wcs_wolfhsm.h: remove WCS_WOLFHSM_MAX_REQ_SIZE /
MAX_RSP_SIZE macros that hardcoded 1288U; the value is just WH_COMM_MTU
and silently desyncs if WOLFHSM_CFG_COMM_DATA_LEN changes
- src/wolfhsm_callable.c: use WH_COMM_MTU directly in size guards;
replace bare 56 server_id with WCS_WOLFHSM_SERVER_ID; drop Phase 1b /
Phase 3 comment, keep only the real-HW pageSize=8 invariant
- test-app/wcs/wolfhsm_test.c: drop unused wolfboot/wcs_wolfhsm.h
include; reword the Phase 1c exerciser header to a stable description
m33mu still green (CommInit + RNG round-trip + BKPT 0x7f).
cmd_wolfhsm_test now exercises three crypto round-trips:
- SHA256(abc) → digest matches FIPS 180-2 Appendix B.1 vector.
- AES-128-CBC encrypt with a cached HSM key:
wh_Client_KeyCache(WH_NVM_FLAGS_USAGE_ENCRYPT) imports the key
to the server's keystore; wc_AesInit + wh_Client_AesSetKeyId
links the wolfCrypt Aes struct to the cached keyId; the
cryptocb dispatches wc_AesCbcEncrypt to the server, which
runs the AES op against its in-cache key. Ciphertext compared
against the FIPS 197 Appendix B vector. Key evicted on exit.
- RNG via WH_DEV_ID (already in Phase 1).
Each step prints a labelled UART line (wolfHSM RNG/SHA256/AES ok).
Verified on m33mu; the AES path forces WH_NVM_FLAGS_USAGE_ENCRYPT
since cached keys without usage flags fail with WH_ERROR_USAGE.
Stack budget unchanged (STACK_USAGE=20000 sufficient). PKCS11 / PSA /
Replaces the Phase 1 ramsim NVM with a real flash-backed store living
in the existing wolfBoot keyvault region (FLASH_KEYVAULT, 112 KiB at
0x0C040000), so wolfHSM-cached keys persist across reset.
- include/wolfboot/wolfhsm_flash_hal.h: whFlashH5Ctx (base / size /
partition_size) and whFlashH5_Cb extern.
- src/wolfhsm_flash_hal.c: 10-callback whFlashCb adapter wrapping
hal_flash_unlock/lock/write/erase. PartitionSize is configurable via
the context (default 32 KiB per partition; two partitions = 64 KiB
used, 48 KiB headroom in the 112 KiB keyvault). Direct memory reads
for Read/Verify/BlankCheck. WriteLock/Unlock are no-ops on H5 (lock
is global).
- src/wolfhsm_callable.c: drop ramsim ctx/cfg + wh_flash_ramsim
include; wire wh_NvmFlashConfig to the new adapter; vault address /
size sourced from the linker symbols _flash_keyvault /
_flash_keyvault_size, matching the PSA / PKCS11 store pattern.
- options.mk: drop wh_flash_ramsim.o, add src/wolfhsm_flash_hal.o.
Verified on m33mu with --persist: CommInit handshake + RNG + SHA256 +
AES cached-key round-trips all pass through wolfHSM's two-partition
journaling layer talking to actual flash. Persistence-across-reset
test (P3.3) follows in a separate commit. PKCS11 / PSA / fwTPM
regression builds remain clean.
e2e real HW tests with first and second boot persistant trip
- docs/wolfHSM.md: append a STM32H5 TrustZone Engine section
alongside the simulator section. Covers build (incl.
WOLFBOOT_TZ_TEST_NO_BKPT for hardware), flashing via
set-stm32-tz-option-bytes.sh + STM32_Programmer_CLI, expected UART
output for both boots, and notes the H5 quad-word ECC handling
shared with psa_store / pkcs11_store. Existing client/server
content untouched.
- .github/workflows/trustzone-emulator-tests.yml: add a wolfHSM step
that mirrors the PKCS11 first/second-boot pattern -- one m33mu
--persist run with --expect-bkpt 0x7d after the first boot path,
committing key to NVM message, then a second --persist run with
--expect-bkpt 0x7f after the restored persisted key message.
Add a wolfHSM section to docs/STM32-TZ.md alongside the PKCS11 and PSA sections, with a cross-reference to the dedicated docs/wolfHSM.md for the full STM32H5 build/flash/test recipe.
- callable: runtime flash config init (drop non-portable static cast),
panic on init failures, volatile *rspSz read, clear borrowed NS
pointers post-dispatch.
- flash_hal: propagate hal_flash_* errors, hoist unlock/lock outside
loop, per-iteration cached_sector wipe, validate config before
copying into ctx, rename sector_base to sector_offset.
- test-app: aes_inited guard, KeyEvict after KeyCommit, ForceZero
consistency, drop redundant keyId reassignment.
- test-app/Makefile: WOLFBOOT_LIB_WOLFHSM default for standalone
test-app builds.
- tools/unit-tests/unit-wolfhsm_flash_hal.c: 10-test host unit test
for the flash adapter, modeled on unit-psa_store.
CMSE pointer-range checks intentionally not applied: m33mu lacks
TT/TTAT, and PKCS11/PSA/fwTPM siblings all skip CMSE
- options.mk: drop duplicate WOLFHSM_CLIENT_OBJS / WOLFHSM_SERVER_OBJS
block; top-of-file definitions are reached before all consumers.
- wolfhsm_callable.c: idempotency guard in wcs_wolfhsm_init; defensive
memset of g_srv_tx_ctx; move g_flash_cfg to a stack local; clamp
rsp_size to rsp_capacity before publishing *rspSz; set *rspSz = 0
on every early-validation error path; use { 0 } initializer; switch
to #ifdef WOLF_CRYPTO_CB.
- wolfhsm_flash_hal.c: rename _Foo callbacks to whFlashH5_Foo to avoid
C-reserved leading-underscore-uppercase identifiers; constant-time
compare in Verify since data may be key material; defensive
wc_ForceZero(cached_sector) on entry to Program; Erase short-circuits
size == 0 before the alignment check for consistency.
- test-app/wcs/wolfhsm_test.c: split AesSetIV vs AesCbcEncrypt error
diagnostics; KeyEvict the cached key when KeyCommit fails; use { 0 }
initializer for nsc_cfg.
- tools/unit-tests/Makefile: add WOLFBOOT_LIB_WOLFHSM default and
external-libs fallback so unit-wolfhsm_flash_hal finds wolfhsm
headers in CI.
- .github/workflows/test-external-library-paths.yml: pass
WOLFBOOT_LIB_WOLFHSM to the unit-test matrix entry.
- unit-wolfhsm_flash_hal.c: cover Cleanup, erase-failure propagation,
Read happy path, multi-sector Program, NULL context for
Read/PartitionSize/Program/Erase/Verify/BlankCheck, NULL data, and
WriteLock/WriteUnlock; use MAP_FIXED_NOREPLACE when available.
e312cbb to
0c7b556
Compare
c86b935 to
2c6827d
Compare
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.
Description
WOLFCRYPT_TZ_WOLFHSM=1a fourth TrustZone engine for STM32H5alongside PKCS11, PSA, and fwTPM. New config:
config/examples/stm32h5-tz-wolfhsm.config.the non-secure application through a single NSC veneer
(
wcs_wolfhsm_transmit). The non-secure app uses the standardwolfCrypt API; operations through
WH_DEV_IDroute to the secureside. Keys never leave the secure world.
whFlashCbadapter(
src/wolfhsm_flash_hal.c) overhal_flash_*, mirroringpsa_store.c's sector-cached read-modify-erase-write pattern.Two-partition journaling in the existing keyvault region.
WOLFHSM_SERVER_OBJS/WOLFHSM_CLIENT_OBJSvariables avoidobject-list duplication with the existing AURIX/sim wolfHSM lanes.
.github/workflows/trustzone-emulator-tests.yml:m33mu first-boot/second-boot persistence test asserting CommInit,
RNG, SHA256, AES, and keystore restore across reset.
tools/unit-tests/unit-wolfhsm_flash_hal.ccovers bounds, alignment, multi-sector, and write-failure paths.
docs/wolfHSM.md+ wolfHSM section indocs/STM32-TZ.md.Notes
lib/wolfHSMsubmodule pin is not bumped in this PR. The wolfHSMPR (
port/stmicro/stm32-tzNSC bridge transport) lands first; thepin bump will follow in a small standalone PR.
Test plan
WOLFHSM_TZ_TEST_PASSover UART