Skip to content

Commit 8b7ce4e

Browse files
authored
Merge pull request #756 from danielinux/fTPM-TZ
Added support for fwTPM in TrustZone + STM32H5 test app
2 parents 3c11bf3 + c6c2544 commit 8b7ce4e

21 files changed

Lines changed: 995 additions & 13 deletions

File tree

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,19 @@ jobs:
106106
make
107107
m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 600
108108
109+
- name: Clean and build test with fwTPM (stm32h5)
110+
run: |
111+
make clean distclean
112+
cp config/examples/stm32h5-tz-fwtpm.config .config
113+
make
114+
m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 600 \
115+
| tee /tmp/m33mu-fwtpm.log
116+
grep -q "fwTPM PCR0 extended:" /tmp/m33mu-fwtpm.log
117+
grep -q "fwTPM unsealed secret: wolfBoot fwTPM PCR secret" /tmp/m33mu-fwtpm.log
118+
grep -q "fwTPM NSC tests passed" /tmp/m33mu-fwtpm.log
119+
grep -q "\\[BKPT\\] imm=0x7f" /tmp/m33mu-fwtpm.log
120+
grep -q "\\[EXPECT BKPT\\] Success" /tmp/m33mu-fwtpm.log
121+
109122
- name: Clean and build test with DICE attestation + OTP (stm32h5)
110123
run: |
111124
make clean distclean

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ tools/unit-tests/unit-loader-tpm-init
186186
tools/unit-tests/unit-update-ram-nofixed
187187
tools/unit-tests/unit-max-space
188188
tools/unit-tests/unit-sdhci-disk-unaligned
189+
tools/unit-tests/unit-fwtpm-stub
189190

190191

191192

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ keys: $(PRIVATE_KEY)
589589
clean:
590590
$(Q)rm -f src/*.o hal/*.o hal/spi/*.o test-app/*.o src/x86/*.o
591591
$(Q)rm -f src/wolfboot_tz_nsc.o
592-
$(Q)rm -f $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/*.o $(WOLFBOOT_LIB_WOLFTPM)/src/*.o $(WOLFBOOT_LIB_WOLFTPM)/hal/*.o $(WOLFBOOT_LIB_WOLFTPM)/examples/pcr/*.o
592+
$(Q)rm -f $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/*.o $(WOLFBOOT_LIB_WOLFTPM)/src/*.o $(WOLFBOOT_LIB_WOLFTPM)/src/fwtpm/*.o $(WOLFBOOT_LIB_WOLFTPM)/hal/*.o $(WOLFBOOT_LIB_WOLFTPM)/examples/pcr/*.o
593593
$(Q)rm -f $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/Renesas/*.o
594594
$(Q)rm -f wolfboot.bin wolfboot.elf wolfboot.map test-update.rom wolfboot.hex wolfboot.srec factory.srec
595595
$(Q)rm -f $(MACHINE_OBJ) $(MAIN_TARGET) $(LSCRIPT)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
ARCH?=ARM
2+
TZEN?=1
3+
TARGET?=stm32h5
4+
SIGN?=ECC256
5+
HASH?=SHA256
6+
DEBUG?=0
7+
VTOR?=1
8+
CORTEX_M0?=0
9+
CORTEX_M33?=1
10+
NO_ASM?=0
11+
NO_MPU=1
12+
EXT_FLASH?=0
13+
SPI_FLASH?=0
14+
ALLOW_DOWNGRADE?=0
15+
NVM_FLASH_WRITEONCE?=1
16+
WOLFBOOT_VERSION?=1
17+
V?=0
18+
SPMATH?=1
19+
RAM_CODE?=1
20+
DUALBANK_SWAP?=0
21+
WOLFBOOT_PARTITION_SIZE?=0xA0000
22+
WOLFBOOT_SECTOR_SIZE?=0x2000
23+
WOLFBOOT_KEYVAULT_ADDRESS?=0x0C040000
24+
WOLFBOOT_KEYVAULT_SIZE?=0x1C000
25+
WOLFBOOT_NSC_ADDRESS?=0x0C05C000
26+
WOLFBOOT_NSC_SIZE?=0x4000
27+
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000
28+
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C100000
29+
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x0C1A0000
30+
FLAGS_HOME=0
31+
DISABLE_BACKUP=0
32+
WOLFCRYPT_TZ=1
33+
WOLFCRYPT_TZ_FWTPM=1
34+
IMAGE_HEADER_SIZE?=1024
35+
ARMORED=1

docs/fwTPM.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# wolfBoot fwTPM on STM32H5
2+
3+
wolfBoot can host wolfTPM's firmware TPM 2.0 implementation in the secure
4+
TrustZone image and expose it to the non-secure application through the wolfBoot
5+
callable service interface. This lets the non-secure application use the normal
6+
wolfTPM client API while TPM commands are processed inside the secure world.
7+
8+
The feature is intended for STM32H5 TrustZone builds. The secure image contains
9+
the fwTPM command processor and the non-secure test application uses a small TIS
10+
shim that forwards commands through the NSC entry point.
11+
12+
## Configuration
13+
14+
Use these wolfBoot configuration options:
15+
16+
| Option | Effect |
17+
| ------ | ------ |
18+
| `TZEN=1` | Builds wolfBoot for TrustZone-enabled STM32H5 parts. |
19+
| `WOLFCRYPT_TZ=1` | Enables the wolfCrypt secure callable service layer. |
20+
| `WOLFCRYPT_TZ_FWTPM=1` | Enables the secure fwTPM service and non-secure fwTPM test support. |
21+
22+
`WOLFCRYPT_TZ_FWTPM=1` defines `WOLFBOOT_TZ_FWTPM` for the secure and
23+
non-secure builds. It also enables wolfTPM fwTPM sources, `WOLFTPM_FWTPM`,
24+
`FWTPM_NO_NV`, and the callable fwTPM object.
25+
26+
The ready-to-use STM32H5 configuration is:
27+
28+
```sh
29+
cp config/examples/stm32h5-tz-fwtpm.config .config
30+
```
31+
32+
## Build
33+
34+
Build wolfBoot and the signed STM32H5 test application from the repository root:
35+
36+
```sh
37+
cp config/examples/stm32h5-tz-fwtpm.config .config
38+
make clean
39+
make
40+
make test-app/image_v1_signed.bin
41+
```
42+
43+
The main outputs are:
44+
45+
| Output | Description |
46+
| ------ | ----------- |
47+
| `wolfboot.bin` | Secure wolfBoot image with the fwTPM service. |
48+
| `test-app/image_v1_signed.bin` | Signed non-secure STM32H5 test application. |
49+
| `test-app/image.elf` | Non-secure test application ELF for debugging. |
50+
51+
## Flash on STM32H5
52+
53+
Enable TrustZone and program the secure and non-secure images with
54+
STM32CubeProgrammer:
55+
56+
```sh
57+
STM32_Programmer_CLI -c port=swd mode=hotplug -ob TZEN=0xB4
58+
STM32_Programmer_CLI -c port=swd -d wolfboot.bin 0x0C000000
59+
STM32_Programmer_CLI -c port=swd -d test-app/image_v1_signed.bin 0x08060000
60+
```
61+
62+
The addresses above match `config/examples/stm32h5-tz-fwtpm.config`:
63+
64+
| Region | Address |
65+
| ------ | ------- |
66+
| Secure wolfBoot image | `0x0C000000` |
67+
| Non-secure boot partition | `0x08060000` |
68+
| Non-secure update partition | `0x0C100000` |
69+
| Swap partition | `0x0C1A0000` |
70+
| NSC veneer region | `0x0C05C000` |
71+
72+
## Test
73+
74+
Open the board serial console and run the fwTPM test command:
75+
76+
```text
77+
fwtpm
78+
```
79+
80+
The test application initializes wolfTPM using the non-secure TIS callback,
81+
queries capabilities, requests random bytes, extends PCR 0, verifies the PCR
82+
value, and seals/unseals a PCR-bound secret. A successful run ends with:
83+
84+
```text
85+
fwTPM NSC tests passed
86+
```
87+
88+
The STM32H5 test app also runs the same fwTPM test automatically during startup
89+
when built with `WOLFBOOT_TZ_FWTPM`.
90+
91+
## Notes
92+
93+
The current wolfBoot integration builds the secure fwTPM service with
94+
`FWTPM_NO_NV`, so TPM NV state is not persistent across resets. To add persistent
95+
NV storage, provide a flash-backed `FWTPM_NV_HAL` implementation and remove
96+
`FWTPM_NO_NV` from the fwTPM build flags.
97+
98+
`WOLFCRYPT_TZ_FWTPM` is mutually exclusive with `WOLFCRYPT_TZ_PKCS11` and
99+
`WOLFCRYPT_TZ_PSA` because each option selects a different TrustZone secure
100+
service surface for the test application.

include/user_settings.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ extern int tolower(int c);
434434
# define NO_CODING
435435
#endif
436436

437-
#ifdef WOLFBOOT_TPM
437+
#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FWTPM)
438438
/* Do not use heap */
439439
#define WOLFTPM2_NO_HEAP
440440
/* small stack options */
@@ -632,6 +632,13 @@ extern int tolower(int c);
632632
#undef NO_KDF
633633
#endif
634634

635+
#if defined(WOLFBOOT_TZ_FWTPM)
636+
#undef NO_CMAC
637+
#undef NO_KDF
638+
#define WOLFSSL_AES_CFB
639+
#define WOLFSSL_SHA384
640+
#endif
641+
635642
#ifdef __QNX__
636643
# define WOLFSSL_HAVE_MIN
637644
# define WOLFSSL_HAVE_MAX

include/wolfboot/wcs_fwtpm.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* wcs_fwtpm.h
2+
*
3+
* Copyright (C) 2026 wolfSSL Inc.
4+
*
5+
* This file is part of wolfBoot.
6+
*/
7+
8+
#ifndef WOLFBOOT_WCS_FWTPM_H
9+
#define WOLFBOOT_WCS_FWTPM_H
10+
11+
#include <stdint.h>
12+
#include "wolfboot/wc_secure.h"
13+
14+
#ifdef WOLFBOOT_TZ_FWTPM
15+
16+
#ifndef WCS_FWTPM_MAX_COMMAND_SIZE
17+
#define WCS_FWTPM_MAX_COMMAND_SIZE 4096U
18+
#endif
19+
20+
int CSME_NSE_API wcs_fwtpm_transmit(const uint8_t *cmd, uint32_t cmdSz,
21+
uint8_t *rsp, uint32_t *rspSz);
22+
23+
void wcs_fwtpm_init(void);
24+
25+
#endif /* WOLFBOOT_TZ_FWTPM */
26+
27+
#endif /* WOLFBOOT_WCS_FWTPM_H */

lib/wolfTPM

Submodule wolfTPM updated 128 files

options.mk

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,15 @@ ifeq ($(WOLFCRYPT_TZ_PKCS11),1)
810810
ifeq ($(WOLFCRYPT_TZ_PSA),1)
811811
$(error WOLFCRYPT_TZ_PKCS11 and WOLFCRYPT_TZ_PSA are mutually exclusive)
812812
endif
813+
ifeq ($(WOLFCRYPT_TZ_FWTPM),1)
814+
$(error WOLFCRYPT_TZ_PKCS11 and WOLFCRYPT_TZ_FWTPM are mutually exclusive)
815+
endif
816+
endif
817+
818+
ifeq ($(WOLFCRYPT_TZ_PSA),1)
819+
ifeq ($(WOLFCRYPT_TZ_FWTPM),1)
820+
$(error WOLFCRYPT_TZ_PSA and WOLFCRYPT_TZ_FWTPM are mutually exclusive)
821+
endif
813822
endif
814823

815824
ifeq ($(WOLFCRYPT_TZ_PKCS11),1)
@@ -919,6 +928,50 @@ ifeq ($(WOLFCRYPT_TZ_PSA),1)
919928
endif
920929
endif
921930

931+
ifeq ($(WOLFCRYPT_TZ_FWTPM),1)
932+
CFLAGS+=-DWOLFBOOT_TZ_FWTPM
933+
CFLAGS+=-DWOLFCRYPT_SECURE_MODE
934+
CFLAGS+=-DWOLFTPM_FWTPM
935+
CFLAGS+=-DFWTPM_NO_NV
936+
CFLAGS+=-DWC_RSA_PSS
937+
CFLAGS+=-DWOLFSSL_PSS_SALT_LEN_DISCOVER
938+
CFLAGS+=-DFWTPM_MAX_COMMAND_SIZE=4096
939+
CFLAGS+=-I$(WOLFBOOT_LIB_WOLFTPM)
940+
ifeq ($(USE_CLANG),1)
941+
CLANG_MULTILIB_FLAGS:=$(filter -mthumb -mlittle-endian,$(LDFLAGS)) $(filter -mcpu=%,$(CFLAGS))
942+
LIBS+=$(shell $(CLANG_GCC_NAME) $(CLANG_MULTILIB_FLAGS) -print-file-name=libc.a)
943+
LIBS+=$(shell $(CLANG_GCC_NAME) $(CLANG_MULTILIB_FLAGS) -print-libgcc-file-name)
944+
else
945+
LDFLAGS+=--specs=nano.specs
946+
endif
947+
WOLFCRYPT_OBJS+=src/store_sbrk.o
948+
WOLFCRYPT_OBJS+=src/fwtpm_callable.o
949+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/fwtpm/fwtpm.o
950+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/fwtpm/fwtpm_command.o
951+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/fwtpm/fwtpm_crypto.o
952+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/fwtpm/fwtpm_nv.o
953+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_util.o
954+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_packet.o
955+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_crypto.o
956+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_param_enc.o
957+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hmac.o
958+
ifneq ($(SIGN),ED25519)
959+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha512.o
960+
endif
961+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wc_encrypt.o
962+
ifeq ($(ENCRYPT_WITH_AES128)$(ENCRYPT_WITH_AES256),)
963+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/aes.o
964+
endif
965+
WOLFCRYPT_OBJS+=$(RSA_OBJS)
966+
ifeq ($(findstring ECC,$(SIGN)),)
967+
ifeq ($(findstring ECC,$(SIGN_SECONDARY)),)
968+
WOLFCRYPT_OBJS+=$(ECC_OBJS)
969+
WOLFCRYPT_OBJS+=$(MATH_OBJS)
970+
endif
971+
endif
972+
STACK_USAGE=20000
973+
endif
974+
922975
OBJS+=$(PUBLIC_KEY_OBJS)
923976
ifneq ($(STAGE1),1)
924977
OBJS+=$(UPDATE_OBJS)
@@ -931,6 +984,8 @@ ifeq ($(WOLFTPM),1)
931984
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_packet.o \
932985
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_tis.o \
933986
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_wrap.o \
987+
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_crypto.o \
988+
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_util.o \
934989
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_param_enc.o
935990
CFLAGS+=-I$(WOLFBOOT_LIB_WOLFTPM)
936991
CFLAGS+=-D"WOLFBOOT_TPM"

0 commit comments

Comments
 (0)