Skip to content

Commit 1f1a3ac

Browse files
committed
port/stmicro/stm32h5-tz-wolfhsm: convenience wrapper + CI to whTest_ClientConfig
1 parent 8afb235 commit 1f1a3ac

13 files changed

Lines changed: 1055 additions & 272 deletions

File tree

.github/workflows/trustzone-emulator-tests.yml

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -122,48 +122,40 @@ jobs:
122122
- name: Clean and build test with wolfHSM (stm32h5)
123123
run: |
124124
make clean distclean
125-
cp config/examples/stm32h5-tz-wolfhsm.config .config
125+
cd port/stmicro/stm32h5-tz-wolfhsm
126126
make
127+
test -f out/wolfboot.bin
128+
test -f out/image_v1_signed.bin
129+
test -f out/manifest.env
127130
128131
- name: Prepare wolfHSM persistence directory
129132
run: |
130133
rm -rf /tmp/m33mu-wolfhsm-persist
131134
mkdir -p /tmp/m33mu-wolfhsm-persist
132-
rm -f /tmp/m33mu-wolfhsm-first.log /tmp/m33mu-wolfhsm-second.log
133135
134-
- name: Run wolfHSM first boot (stm32h5)
136+
- name: Run wolfHSM whTest_ClientConfig (stm32h5)
135137
run: |
136138
cd /tmp/m33mu-wolfhsm-persist
137139
m33mu "$GITHUB_WORKSPACE/wolfboot.bin" \
138140
"$GITHUB_WORKSPACE/test-app/image_v1_signed.bin:0x60000" \
139-
--persist --uart-stdout --timeout 120 --expect-bkpt 0x7d \
140-
| tee /tmp/m33mu-wolfhsm-first.log
141-
142-
- name: Verify wolfHSM first boot (stm32h5)
143-
run: |
144-
grep -q "wolfHSM CommInit ok" /tmp/m33mu-wolfhsm-first.log
145-
grep -q "wolfHSM RNG ok:" /tmp/m33mu-wolfhsm-first.log
146-
grep -q "wolfHSM SHA256 ok" /tmp/m33mu-wolfhsm-first.log
147-
grep -q "wolfHSM AES ok" /tmp/m33mu-wolfhsm-first.log
148-
grep -q "wolfHSM first boot path, committing key to NVM" /tmp/m33mu-wolfhsm-first.log
149-
grep -q "wolfHSM NSC tests passed" /tmp/m33mu-wolfhsm-first.log
150-
grep -q "\\[BKPT\\] imm=0x7d" /tmp/m33mu-wolfhsm-first.log
151-
grep -q "\\[EXPECT BKPT\\] Success" /tmp/m33mu-wolfhsm-first.log
152-
153-
- name: Run wolfHSM second boot (stm32h5)
154-
run: |
155-
cd /tmp/m33mu-wolfhsm-persist
156-
m33mu "$GITHUB_WORKSPACE/wolfboot.bin" \
157-
"$GITHUB_WORKSPACE/test-app/image_v1_signed.bin:0x60000" \
158-
--persist --uart-stdout --timeout 120 --expect-bkpt 0x7f \
159-
| tee /tmp/m33mu-wolfhsm-second.log
160-
161-
- name: Verify wolfHSM second boot (stm32h5)
162-
run: |
163-
grep -q "wolfHSM second boot path, restored persisted key" /tmp/m33mu-wolfhsm-second.log
164-
grep -q "wolfHSM NSC tests passed" /tmp/m33mu-wolfhsm-second.log
165-
grep -q "\\[BKPT\\] imm=0x7f" /tmp/m33mu-wolfhsm-second.log
166-
grep -q "\\[EXPECT BKPT\\] Success" /tmp/m33mu-wolfhsm-second.log
141+
--persist --uart-stdout --timeout 600 --expect-bkpt 0x7d \
142+
--quit-on-faults \
143+
| tee /tmp/m33mu-wolfhsm.log
144+
145+
- name: Verify wolfHSM whTest_ClientConfig (stm32h5)
146+
run: |
147+
# Final success marker - the test itself reports PASSED.
148+
grep -q "wolfHSM whTest_ClientConfig PASSED" /tmp/m33mu-wolfhsm.log
149+
# Spot-check that the major test phases each landed.
150+
grep -q "RNG DEVID=0x5748534D SUCCESS" /tmp/m33mu-wolfhsm.log
151+
grep -q "AES GCM DEVID=0x5748534D SUCCESS" /tmp/m33mu-wolfhsm.log
152+
grep -q "RSA SUCCESS" /tmp/m33mu-wolfhsm.log
153+
grep -q "ECC ephemeral ECDH SUCCESS" /tmp/m33mu-wolfhsm.log
154+
grep -q "SHA256 DEVID=0x5748534D SUCCESS" /tmp/m33mu-wolfhsm.log
155+
grep -q "HKDF SUCCESS" /tmp/m33mu-wolfhsm.log
156+
# App reached the success BKPT and m33mu trapped on it.
157+
grep -q "\\[BKPT\\] imm=0x7d" /tmp/m33mu-wolfhsm.log
158+
grep -q "\\[EXPECT BKPT\\] Success" /tmp/m33mu-wolfhsm.log
167159
168160
- name: Clean and build test with DICE attestation + OTP (stm32h5)
169161
run: |

include/user_settings.h

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,10 @@ extern int tolower(int c);
516516
defined(WOLFBOOT_SIGN_ML_DSA)) && \
517517
!defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER)
518518
#define WC_NO_RNG
519+
/* wolfssl rejects WC_NO_RNG with the default blinding macros.
520+
* wolfBoot is verify-only, no blinding is meaningful with a
521+
* disabled RNG. */
522+
#define WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS
519523
#endif
520524
#define WC_NO_HASHDRBG
521525
#define NO_AES_CBC
@@ -569,6 +573,9 @@ extern int tolower(int c);
569573
defined(WOLFBOOT_SIGN_ML_DSA)) && \
570574
!defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER)
571575
# define WC_NO_RNG
576+
/* wolfssl rejects WC_NO_RNG with the default blinding macros. wolfBoot
577+
* is verify-only, no blinding is meaningful with a disabled RNG. */
578+
# define WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS
572579
# endif
573580
# define WC_NO_HASHDRBG
574581
# define NO_DEV_RANDOM
@@ -774,8 +781,53 @@ extern int tolower(int c);
774781
# undef HAVE_ANONYMOUS_INLINE_AGGREGATES
775782
# define HAVE_ANONYMOUS_INLINE_AGGREGATES 1
776783
# define WOLFSSL_KEY_GEN
777-
#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT || WOLFBOOT_ENABLE_WOLFHSM_SERVER ||
778-
WOLFCRYPT_TZ_WOLFHSM */
784+
#endif
785+
786+
/* Crypto algorithms exercised by the wolfHSM client test suite over
787+
* the NSC bridge. These are SECURE-SIDE only - the wolfHSM server
788+
* needs AES/HKDF/SHA384/512 to handle the test requests. Gated out
789+
* of the wolfHSM client build (which has NO_AES) and out of host
790+
* unit tests (UNIT_TEST), neither of which want AES dragged in. */
791+
#if (defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) || \
792+
defined(WOLFCRYPT_TZ_WOLFHSM)) && !defined(UNIT_TEST)
793+
/* Earlier guards in this file set NO_AES and NO_HMAC for the
794+
* verify-only bootloader path. The wolfHSM server needs both AES
795+
* and HMAC (HKDF builds on HMAC), so drop them here. */
796+
# undef NO_AES
797+
# undef NO_HMAC
798+
# ifndef WOLFSSL_AES_DIRECT
799+
# define WOLFSSL_AES_DIRECT
800+
# endif
801+
# ifndef HAVE_HKDF
802+
# define HAVE_HKDF
803+
# endif
804+
# ifndef WOLFSSL_AES_COUNTER
805+
# define WOLFSSL_AES_COUNTER
806+
# endif
807+
# ifndef HAVE_AESCTR
808+
# define HAVE_AESCTR
809+
# endif
810+
# ifndef WOLFSSL_AES_GCM
811+
# define WOLFSSL_AES_GCM
812+
# endif
813+
# ifndef HAVE_AESGCM
814+
# define HAVE_AESGCM
815+
# endif
816+
# ifndef GCM_TABLE_4BIT
817+
# define GCM_TABLE_4BIT
818+
# endif
819+
/* Match NS-side WC_MAX_DIGEST_SIZE. NS test-app/wcs/user_settings.h
820+
* enables WOLFSSL_SHA3 which sets WC_MAX_DIGEST_SIZE = 64. Without
821+
* SHA384/SHA512 on the secure side, WC_MAX_DIGEST_SIZE caps at
822+
* SHA256's 32 and wc_ecc_sign_hash (ecc.c:7281) rejects legitimately
823+
* oversized hashes (e.g. ECDSA truncation tests) with BAD_LENGTH_E. */
824+
# ifndef WOLFSSL_SHA384
825+
# define WOLFSSL_SHA384
826+
# endif
827+
# ifndef WOLFSSL_SHA512
828+
# define WOLFSSL_SHA512
829+
# endif
830+
#endif /* WOLFBOOT_ENABLE_WOLFHSM_SERVER || WOLFCRYPT_TZ_WOLFHSM, !UNIT_TEST */
779831

780832
#if defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) && \
781833
defined(WOLFBOOT_CERT_CHAIN_VERIFY)

lib/wolfssl

Submodule wolfssl updated 136 files

options.mk

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1456,7 +1456,16 @@ ifeq ($(WOLFHSM_SERVER),1)
14561456
WOLFCRYPT_OBJS += \
14571457
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/cryptocb.o \
14581458
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/coding.o \
1459-
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/random.o
1459+
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/random.o \
1460+
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hmac.o \
1461+
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/aes.o \
1462+
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wc_encrypt.o
1463+
# SHA-384/512 are used by the wolfHSM crypto handlers (HKDF, larger
1464+
# ECDSA hash sizes, etc.). Always link sha512.o except when ED25519
1465+
# is the signature algorithm, which already pulls it in.
1466+
ifneq ($(SIGN),ED25519)
1467+
WOLFCRYPT_OBJS += $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha512.o
1468+
endif
14601469

14611470
ifeq ($(SIGN),ML_DSA)
14621471
WOLFCRYPT_OBJS += $(MATH_OBJS)
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Makefile - top-level wrapper for the wolfHSM TrustZone demo on STM32H5
2+
#
3+
# Copyright (C) 2026 wolfSSL Inc.
4+
#
5+
# This file is part of wolfBoot.
6+
#
7+
# wolfBoot is free software; you can redistribute it and/or modify
8+
# it under the terms of the GNU General Public License as published by
9+
# the Free Software Foundation; either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# wolfBoot is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU General Public License for more details.
16+
17+
# This Makefile is a convenience wrapper around the top-level wolfBoot
18+
# build. It stages the stm32h5-tz-wolfhsm config, builds the secure
19+
# wolfBoot image (with the wolfHSM server linked in) and the non-secure
20+
# test application (which connects to the server via the ARMv8-M NSC
21+
# bridge and runs whTest_ClientConfig), and stages both binaries here
22+
# for flashing.
23+
#
24+
# Quick start:
25+
# make # build wolfboot.bin + test app, stage in ./out/
26+
# ./load.sh # flash to a NUCLEO-H563ZI and open a serial console
27+
# make emu # run the m33mu emulator over the built binaries
28+
# make clean # drop staged artifacts (keeps the wolfBoot tree)
29+
# make distclean # also wipe wolfBoot build state
30+
31+
PORT_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
32+
WOLFBOOT_ROOT := $(abspath $(PORT_DIR)/../../..)
33+
CONFIG_EXAMPLE := $(WOLFBOOT_ROOT)/config/examples/stm32h5-tz-wolfhsm.config
34+
CONFIG_TARGET := $(WOLFBOOT_ROOT)/.config
35+
OUT_DIR := $(PORT_DIR)/out
36+
37+
# Default to the lib/wolfHSM submodule (matches wolfBoot's own
38+
# Makefile). Override with `make WOLFBOOT_LIB_WOLFHSM=...` to point
39+
# at a different wolfHSM checkout.
40+
WOLFBOOT_LIB_WOLFHSM ?= $(WOLFBOOT_ROOT)/lib/wolfHSM
41+
42+
WOLFBOOT_BIN := $(WOLFBOOT_ROOT)/wolfboot.bin
43+
TEST_APP_BIN := $(WOLFBOOT_ROOT)/test-app/image_v1_signed.bin
44+
45+
# Address the test app must be flashed to. Read from the staged .config
46+
# so it stays in sync with what wolfBoot itself was built against.
47+
BOOT_ADDR := 0x08060000
48+
49+
# Forward extra options to the wolfBoot top-level make. Example:
50+
# make WOLFBOOT_MAKE_FLAGS='V=1'
51+
WOLFBOOT_MAKE_FLAGS ?=
52+
53+
.PHONY: all build stage clean distclean emu flash help
54+
55+
all: build stage
56+
57+
# Stage the config and run the wolfBoot top-level build. wolfBoot itself
58+
# emits wolfboot.bin (secure image) and test-app/image_v1_signed.bin
59+
# (the non-secure test application). With WOLFCRYPT_TZ_WOLFHSM=1 in the
60+
# staged config, the non-secure app calls cmd_wolfhsm_test(), which
61+
# initialises the wolfHSM client over the NSC bridge and runs the
62+
# wolfHSM client test suite against the in-secure-world server.
63+
#
64+
# We `cd` into WOLFBOOT_ROOT rather than using `$(MAKE) -C ...` because
65+
# the wolfBoot sign step shells out with `./tools/keytools/sign`, which
66+
# resolves against the original process cwd. From a sub-directory the
67+
# relative path fails; cd-ing keeps the resolution correct.
68+
build: stage-config
69+
@echo "==> wolfBoot build (stm32h5-tz-wolfhsm)"
70+
@echo "==> WOLFBOOT_LIB_WOLFHSM=$(WOLFBOOT_LIB_WOLFHSM)"
71+
cd $(WOLFBOOT_ROOT) && $(MAKE) wolfboot.bin WOLFBOOT_LIB_WOLFHSM=$(WOLFBOOT_LIB_WOLFHSM) $(WOLFBOOT_MAKE_FLAGS)
72+
cd $(WOLFBOOT_ROOT) && $(MAKE) test-app/image_v1_signed.bin WOLFBOOT_LIB_WOLFHSM=$(WOLFBOOT_LIB_WOLFHSM) $(WOLFBOOT_MAKE_FLAGS)
73+
74+
# Force-overwrite .config every build so a stale config from a
75+
# previous CI step (PKCS11, fwTPM, DICE) cannot bleed through.
76+
.PHONY: stage-config
77+
stage-config:
78+
@echo "==> Staging config: $(CONFIG_EXAMPLE) -> $(CONFIG_TARGET)"
79+
cp $(CONFIG_EXAMPLE) $(CONFIG_TARGET)
80+
81+
# Copy the produced binaries into ./out so this directory is the single
82+
# place the user has to look. Also drop the boot address into a small
83+
# manifest so load.sh and CI scripts do not have to re-parse .config.
84+
stage: build
85+
@mkdir -p $(OUT_DIR)
86+
cp $(WOLFBOOT_BIN) $(OUT_DIR)/wolfboot.bin
87+
cp $(TEST_APP_BIN) $(OUT_DIR)/image_v1_signed.bin
88+
@echo "BOOT_ADDR=$(BOOT_ADDR)" > $(OUT_DIR)/manifest.env
89+
@echo "WOLFBOOT_BIN=$(OUT_DIR)/wolfboot.bin" >> $(OUT_DIR)/manifest.env
90+
@echo "TEST_APP_BIN=$(OUT_DIR)/image_v1_signed.bin" >> $(OUT_DIR)/manifest.env
91+
@echo "==> Staged in $(OUT_DIR):"
92+
@ls -l $(OUT_DIR)
93+
94+
# Convenience: invoke load.sh from anywhere.
95+
flash: stage
96+
$(PORT_DIR)/load.sh
97+
98+
# Run the wolfBoot m33mu emulator harness over the produced binaries.
99+
# This uses wolfBoot's own emulator script so the test path is identical
100+
# to what runs in CI.
101+
emu: stage
102+
cd $(WOLFBOOT_ROOT)/test-app/emu-test-apps && \
103+
TARGET=stm32h5 ./test.sh
104+
105+
clean:
106+
rm -rf $(OUT_DIR)
107+
108+
distclean: clean
109+
cd $(WOLFBOOT_ROOT) && $(MAKE) clean distclean
110+
rm -f $(CONFIG_TARGET)
111+
112+
help:
113+
@echo "Targets:"
114+
@echo " make Build wolfboot.bin + signed test app, stage in ./out"
115+
@echo " make flash Build (if needed) and flash via load.sh"
116+
@echo " make emu Build (if needed) and run wolfBoot m33mu harness"
117+
@echo " make clean Drop ./out"
118+
@echo " make distclean Also clean the wolfBoot tree and drop .config"

0 commit comments

Comments
 (0)