Skip to content

Commit 23ce21b

Browse files
committed
Add wolfHSM TrustZone server + NSC bridge for STM32H5
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
1 parent c3dd2fa commit 23ce21b

10 files changed

Lines changed: 466 additions & 41 deletions

File tree

include/user_settings.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -756,12 +756,14 @@ extern int tolower(int c);
756756
#endif
757757

758758
#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \
759-
defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER)
759+
defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) || \
760+
defined(WOLFCRYPT_TZ_WOLFHSM)
760761
# define WOLF_CRYPTO_CB
761762
# undef HAVE_ANONYMOUS_INLINE_AGGREGATES
762763
# define HAVE_ANONYMOUS_INLINE_AGGREGATES 1
763764
# define WOLFSSL_KEY_GEN
764-
#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT || WOLFBOOT_ENABLE_WOLFHSM_SERVER */
765+
#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT || WOLFBOOT_ENABLE_WOLFHSM_SERVER ||
766+
WOLFCRYPT_TZ_WOLFHSM */
765767

766768
#if defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) && \
767769
defined(WOLFBOOT_CERT_CHAIN_VERIFY)

include/wolfboot/wcs_wolfhsm.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* wcs_wolfhsm.h
2+
*
3+
* Copyright (C) 2026 wolfSSL Inc.
4+
*
5+
* This file is part of wolfBoot.
6+
*/
7+
8+
#ifndef WOLFBOOT_WCS_WOLFHSM_H
9+
#define WOLFBOOT_WCS_WOLFHSM_H
10+
11+
#include <stdint.h>
12+
#include "wolfboot/wc_secure.h"
13+
14+
#ifdef WOLFCRYPT_TZ_WOLFHSM
15+
16+
/* Match wolfHSM's WH_COMM_MTU; bridge buffers are sized to this. */
17+
#ifndef WCS_WOLFHSM_MAX_REQ_SIZE
18+
#define WCS_WOLFHSM_MAX_REQ_SIZE 1288U
19+
#endif
20+
21+
#ifndef WCS_WOLFHSM_MAX_RSP_SIZE
22+
#define WCS_WOLFHSM_MAX_RSP_SIZE 1288U
23+
#endif
24+
25+
int CSME_NSE_API wcs_wolfhsm_transmit(const uint8_t *cmd, uint32_t cmdSz,
26+
uint8_t *rsp, uint32_t *rspSz);
27+
28+
void wcs_wolfhsm_init(void);
29+
30+
#endif /* WOLFCRYPT_TZ_WOLFHSM */
31+
32+
#endif /* WOLFBOOT_WCS_WOLFHSM_H */

options.mk

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,43 @@
11
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/asn.o
2+
3+
# Shared wolfHSM client/server object lists. Defined here at the top so any
4+
# downstream block (legacy WOLFHSM_CLIENT/SERVER, or WOLFCRYPT_TZ_WOLFHSM TZ
5+
# engine) can reference them by variable name without ordering hazards.
6+
WOLFHSM_CLIENT_OBJS := \
7+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_client.o \
8+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_client_nvm.o \
9+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_client_cryptocb.o \
10+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_client_crypto.o \
11+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_client_dma.o \
12+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_crypto.o \
13+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_dma.o \
14+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_utils.o \
15+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_comm.o \
16+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_comm.o \
17+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_nvm.o \
18+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_customcb.o
19+
20+
WOLFHSM_SERVER_OBJS := \
21+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_utils.o \
22+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_comm.o \
23+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_nvm.o \
24+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_nvm_flash.o \
25+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_keyid.o \
26+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_flash_unit.o \
27+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_crypto.o \
28+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server.o \
29+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server_nvm.o \
30+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server_crypto.o \
31+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server_counter.o \
32+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server_keystore.o \
33+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server_customcb.o \
34+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_customcb.o \
35+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_keystore.o \
36+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_crypto.o \
37+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_counter.o \
38+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_nvm.o \
39+
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_comm.o
40+
241
USE_CLANG?=0
342
ifeq ($(USE_CLANG),1)
443
USE_GCC?=0
@@ -1095,14 +1134,39 @@ ifeq ($(WOLFCRYPT_TZ_WOLFHSM),1)
10951134
CFLAGS+=-DWOLFCRYPT_SECURE_MODE
10961135
CFLAGS+=-DWOLFHSM_CFG_ENABLE_SERVER
10971136
CFLAGS+=-DWOLFHSM_CFG_COMM_DATA_LEN=1280
1137+
CFLAGS+=-DWOLFHSM_CFG_PORT_STM32_TZ_NSC
1138+
CFLAGS+=-DWOLFHSM_CFG_NO_SYS_TIME
10981139
CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFHSM)"
1140+
CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFHSM)/port/stmicro/stm32-tz"
10991141
ifeq ($(USE_CLANG),1)
11001142
CLANG_MULTILIB_FLAGS:=$(filter -mthumb -mlittle-endian,$(LDFLAGS)) $(filter -mcpu=%,$(CFLAGS))
11011143
LIBS+=$(shell $(CLANG_GCC_NAME) $(CLANG_MULTILIB_FLAGS) -print-file-name=libc.a)
11021144
LIBS+=$(shell $(CLANG_GCC_NAME) $(CLANG_MULTILIB_FLAGS) -print-libgcc-file-name)
11031145
else
11041146
LDFLAGS+=--specs=nano.specs
11051147
endif
1148+
WOLFCRYPT_OBJS+=src/store_sbrk.o
1149+
WOLFCRYPT_OBJS+=src/wolfhsm_callable.o
1150+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/cryptocb.o
1151+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/coding.o
1152+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hmac.o
1153+
ifneq ($(SIGN),ED25519)
1154+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha512.o
1155+
endif
1156+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wc_encrypt.o
1157+
ifeq ($(ENCRYPT_WITH_AES128)$(ENCRYPT_WITH_AES256),)
1158+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/aes.o
1159+
endif
1160+
WOLFCRYPT_OBJS+=$(RSA_OBJS)
1161+
ifeq ($(findstring ECC,$(SIGN)),)
1162+
ifeq ($(findstring ECC,$(SIGN_SECONDARY)),)
1163+
WOLFCRYPT_OBJS+=$(ECC_OBJS)
1164+
WOLFCRYPT_OBJS+=$(MATH_OBJS)
1165+
endif
1166+
endif
1167+
WOLFHSM_OBJS+=$(WOLFHSM_SERVER_OBJS)
1168+
WOLFHSM_OBJS+=$(WOLFBOOT_LIB_WOLFHSM)/src/wh_flash_ramsim.o
1169+
WOLFHSM_OBJS+=$(WOLFBOOT_LIB_WOLFHSM)/port/stmicro/stm32-tz/wh_transport_nsc.o
11061170
STACK_USAGE=20000
11071171
endif
11081172

@@ -1301,44 +1365,6 @@ ifneq ($(WOLFBOOT_PART_ID),)
13011365
SIGN_OPTIONS+=--id $(WOLFBOOT_PART_ID)
13021366
endif
13031367

1304-
# Shared wolfHSM client/server object lists. Both the legacy WOLFHSM_CLIENT=1 /
1305-
# WOLFHSM_SERVER=1 flags and the WOLFCRYPT_TZ_WOLFHSM=1 TZ engine reference
1306-
# these to avoid object-list duplication.
1307-
WOLFHSM_CLIENT_OBJS := \
1308-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_client.o \
1309-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_client_nvm.o \
1310-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_client_cryptocb.o \
1311-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_client_crypto.o \
1312-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_client_dma.o \
1313-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_crypto.o \
1314-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_dma.o \
1315-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_utils.o \
1316-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_comm.o \
1317-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_comm.o \
1318-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_nvm.o \
1319-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_customcb.o
1320-
1321-
WOLFHSM_SERVER_OBJS := \
1322-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_utils.o \
1323-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_comm.o \
1324-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_nvm.o \
1325-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_nvm_flash.o \
1326-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_keyid.o \
1327-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_flash_unit.o \
1328-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_crypto.o \
1329-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server.o \
1330-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server_nvm.o \
1331-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server_crypto.o \
1332-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server_counter.o \
1333-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server_keystore.o \
1334-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_server_customcb.o \
1335-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_customcb.o \
1336-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_keystore.o \
1337-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_crypto.o \
1338-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_counter.o \
1339-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_nvm.o \
1340-
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_message_comm.o
1341-
13421368
# wolfHSM client options
13431369
ifeq ($(WOLFHSM_CLIENT),1)
13441370
WOLFCRYPT_OBJS += \

src/wc_callable.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
#include "wolfboot/wcs_fwtpm.h"
3535
#endif
3636

37+
#ifdef WOLFCRYPT_TZ_WOLFHSM
38+
#include "wolfboot/wcs_wolfhsm.h"
39+
#endif
40+
3741
static WC_RNG wcs_rng;
3842

3943
int CSME_NSE_API wcs_get_random(uint8_t *rand, uint32_t size)
@@ -48,6 +52,9 @@ void wcs_Init(void)
4852
#ifdef WOLFBOOT_TZ_FWTPM
4953
wcs_fwtpm_init();
5054
#endif
55+
#ifdef WOLFCRYPT_TZ_WOLFHSM
56+
wcs_wolfhsm_init();
57+
#endif
5158
}
5259

5360
#endif /* WOLFCRYPT_SECURE_MODE */

src/wolfhsm_callable.c

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/* wolfhsm_callable.c
2+
*
3+
* Copyright (C) 2026 wolfSSL Inc.
4+
*
5+
* This file is part of wolfBoot.
6+
*/
7+
8+
#ifdef WOLFCRYPT_TZ_WOLFHSM
9+
10+
#include <stdint.h>
11+
#include <string.h>
12+
13+
#include "store_sbrk.h"
14+
#include "wolfboot/wcs_wolfhsm.h"
15+
16+
#include "wolfssl/wolfcrypt/settings.h"
17+
#include "wolfssl/wolfcrypt/random.h"
18+
19+
#include "wolfhsm/wh_comm.h"
20+
#include "wolfhsm/wh_error.h"
21+
#include "wolfhsm/wh_flash.h"
22+
#include "wolfhsm/wh_flash_ramsim.h"
23+
#include "wolfhsm/wh_nvm.h"
24+
#include "wolfhsm/wh_nvm_flash.h"
25+
#include "wolfhsm/wh_server.h"
26+
27+
#include "wh_transport_nsc.h"
28+
29+
extern unsigned int _start_heap;
30+
extern unsigned int _heap_size;
31+
32+
void *_sbrk(unsigned int incr)
33+
{
34+
static uint8_t *heap;
35+
return wolfboot_store_sbrk(incr, &heap, (uint8_t *)&_start_heap,
36+
(uint32_t)(&_heap_size));
37+
}
38+
39+
/* Phase 1b uses a 32 KiB ramsim partition pair for the NVM backend; Phase 3
40+
* swaps this for a flash-backed adapter over wolfBoot's hal_flash_*.
41+
* pageSize must match WHFU_BYTES_PER_UNIT (8) — wolfHSM programs the flash
42+
* one unit at a time, so a larger pageSize causes the modulo check in
43+
* whFlashRamsim_Program to fail. */
44+
#define WCS_WOLFHSM_RAMSIM_SIZE (32U * 1024U)
45+
#define WCS_WOLFHSM_RAMSIM_SECTOR (8U * 1024U)
46+
#define WCS_WOLFHSM_RAMSIM_PAGE 8U
47+
48+
static uint8_t g_ramsim_buf[WCS_WOLFHSM_RAMSIM_SIZE];
49+
static whFlashRamsimCtx g_ramsim_ctx;
50+
static whFlashRamsimCfg g_ramsim_cfg = {
51+
.memory = g_ramsim_buf,
52+
.size = WCS_WOLFHSM_RAMSIM_SIZE,
53+
.sectorSize = WCS_WOLFHSM_RAMSIM_SECTOR,
54+
.pageSize = WCS_WOLFHSM_RAMSIM_PAGE,
55+
.erasedByte = 0xFFU,
56+
.initData = NULL,
57+
};
58+
static whFlashCb g_flash_cb = WH_FLASH_RAMSIM_CB;
59+
60+
static whNvmFlashContext g_nvm_flash_ctx;
61+
static whNvmFlashConfig g_nvm_flash_cfg = {
62+
.cb = &g_flash_cb,
63+
.context = &g_ramsim_ctx,
64+
.config = &g_ramsim_cfg,
65+
};
66+
static whNvmCb g_nvm_flash_cb = WH_NVM_FLASH_CB;
67+
static whNvmContext g_nvm_ctx;
68+
static whNvmConfig g_nvm_cfg = {
69+
.cb = &g_nvm_flash_cb,
70+
.context = &g_nvm_flash_ctx,
71+
.config = &g_nvm_flash_cfg,
72+
};
73+
74+
static whServerCryptoContext g_crypto_ctx;
75+
static whTransportNscServerContext g_srv_tx_ctx;
76+
static whTransportNscServerConfig g_srv_tx_cfg = { { 0 } };
77+
static whCommServerConfig g_comm_cfg = {
78+
.transport_context = &g_srv_tx_ctx,
79+
.transport_cb = &whTransportNscServer_Cb,
80+
.transport_config = &g_srv_tx_cfg,
81+
.server_id = 56, /* server identifier; NS client uses client_id=1 */
82+
};
83+
static whServerConfig g_server_cfg = {
84+
.comm_config = &g_comm_cfg,
85+
.nvm = &g_nvm_ctx,
86+
.crypto = &g_crypto_ctx,
87+
#if defined WOLF_CRYPTO_CB
88+
.devId = INVALID_DEVID,
89+
#endif
90+
};
91+
92+
static whServerContext g_server;
93+
static int g_wolfhsm_ready;
94+
95+
void wcs_wolfhsm_init(void)
96+
{
97+
int rc;
98+
99+
rc = wc_InitRng(g_crypto_ctx.rng);
100+
if (rc != 0) {
101+
return;
102+
}
103+
rc = wh_Nvm_Init(&g_nvm_ctx, &g_nvm_cfg);
104+
if (rc != WH_ERROR_OK) {
105+
return;
106+
}
107+
rc = wh_Server_Init(&g_server, &g_server_cfg);
108+
if (rc != WH_ERROR_OK) {
109+
return;
110+
}
111+
(void)wh_Server_SetConnected(&g_server, WH_COMM_CONNECTED);
112+
g_wolfhsm_ready = 1;
113+
}
114+
115+
/* Single NSC veneer. Per call: validate the NS pointers/sizes (single-fetch
116+
* defeats TOCTOU on *rspSz), park the buffers in the secure-side transport
117+
* context, run wh_Server_HandleRequestMessage exactly once, write back the
118+
* captured response size. */
119+
int CSME_NSE_API wcs_wolfhsm_transmit(const uint8_t *cmd, uint32_t cmdSz,
120+
uint8_t *rsp, uint32_t *rspSz)
121+
{
122+
uint32_t rsp_capacity;
123+
int rc;
124+
125+
if (cmd == NULL || rsp == NULL || rspSz == NULL) {
126+
return WH_ERROR_BADARGS;
127+
}
128+
/* Single fetch of the caller-supplied capacity; subsequent code uses
129+
* only this local copy. The NS caller cannot mutate it under us. */
130+
rsp_capacity = *rspSz;
131+
132+
if (cmdSz == 0U || cmdSz > WCS_WOLFHSM_MAX_REQ_SIZE) {
133+
return WH_ERROR_BADARGS;
134+
}
135+
if (rsp_capacity == 0U || rsp_capacity > WCS_WOLFHSM_MAX_RSP_SIZE) {
136+
return WH_ERROR_BADARGS;
137+
}
138+
if (!g_wolfhsm_ready) {
139+
return WH_ERROR_NOTREADY;
140+
}
141+
142+
g_srv_tx_ctx.req_buf = cmd;
143+
g_srv_tx_ctx.req_size = (uint16_t)cmdSz;
144+
g_srv_tx_ctx.rsp_buf = rsp;
145+
g_srv_tx_ctx.rsp_capacity = (uint16_t)rsp_capacity;
146+
g_srv_tx_ctx.rsp_size = 0;
147+
g_srv_tx_ctx.request_pending = 1;
148+
149+
rc = wh_Server_HandleRequestMessage(&g_server);
150+
151+
if (rc == WH_ERROR_OK) {
152+
*rspSz = (uint32_t)g_srv_tx_ctx.rsp_size;
153+
} else {
154+
*rspSz = 0;
155+
}
156+
return rc;
157+
}
158+
159+
#endif /* WOLFCRYPT_TZ_WOLFHSM */

0 commit comments

Comments
 (0)