Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/trustzone-emulator-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ jobs:
make
m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 600

- name: Clean and build test with fwTPM (stm32h5)
run: |
make clean distclean
cp config/examples/stm32h5-tz-fwtpm.config .config
make
m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 600 \
| tee /tmp/m33mu-fwtpm.log
grep -q "fwTPM PCR0 extended:" /tmp/m33mu-fwtpm.log
grep -q "fwTPM unsealed secret: wolfBoot fwTPM PCR secret" /tmp/m33mu-fwtpm.log
grep -q "fwTPM NSC tests passed" /tmp/m33mu-fwtpm.log
grep -q "\\[BKPT\\] imm=0x7f" /tmp/m33mu-fwtpm.log
grep -q "\\[EXPECT BKPT\\] Success" /tmp/m33mu-fwtpm.log

- name: Clean and build test with DICE attestation + OTP (stm32h5)
run: |
make clean distclean
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ tools/unit-tests/unit-loader-tpm-init
tools/unit-tests/unit-update-ram-nofixed
tools/unit-tests/unit-max-space
tools/unit-tests/unit-sdhci-disk-unaligned
tools/unit-tests/unit-fwtpm-stub



Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ keys: $(PRIVATE_KEY)
clean:
$(Q)rm -f src/*.o hal/*.o hal/spi/*.o test-app/*.o src/x86/*.o
$(Q)rm -f src/wolfboot_tz_nsc.o
$(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
$(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
$(Q)rm -f $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/Renesas/*.o
$(Q)rm -f wolfboot.bin wolfboot.elf wolfboot.map test-update.rom wolfboot.hex wolfboot.srec factory.srec
$(Q)rm -f $(MACHINE_OBJ) $(MAIN_TARGET) $(LSCRIPT)
Expand Down
35 changes: 35 additions & 0 deletions config/examples/stm32h5-tz-fwtpm.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
ARCH?=ARM
TZEN?=1
TARGET?=stm32h5
SIGN?=ECC256
HASH?=SHA256
DEBUG?=0
VTOR?=1
CORTEX_M0?=0
CORTEX_M33?=1
NO_ASM?=0
NO_MPU=1
EXT_FLASH?=0
SPI_FLASH?=0
ALLOW_DOWNGRADE?=0
NVM_FLASH_WRITEONCE?=1
WOLFBOOT_VERSION?=1
V?=0
SPMATH?=1
RAM_CODE?=1
DUALBANK_SWAP?=0
WOLFBOOT_PARTITION_SIZE?=0xA0000
WOLFBOOT_SECTOR_SIZE?=0x2000
WOLFBOOT_KEYVAULT_ADDRESS?=0x0C040000
WOLFBOOT_KEYVAULT_SIZE?=0x1C000
WOLFBOOT_NSC_ADDRESS?=0x0C05C000
WOLFBOOT_NSC_SIZE?=0x4000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C100000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x0C1A0000
FLAGS_HOME=0
DISABLE_BACKUP=0
WOLFCRYPT_TZ=1
WOLFCRYPT_TZ_FWTPM=1
IMAGE_HEADER_SIZE?=1024
ARMORED=1
100 changes: 100 additions & 0 deletions docs/fwTPM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# wolfBoot fwTPM on STM32H5

wolfBoot can host wolfTPM's firmware TPM 2.0 implementation in the secure
TrustZone image and expose it to the non-secure application through the wolfBoot
callable service interface. This lets the non-secure application use the normal
wolfTPM client API while TPM commands are processed inside the secure world.

The feature is intended for STM32H5 TrustZone builds. The secure image contains
the fwTPM command processor and the non-secure test application uses a small TIS
shim that forwards commands through the NSC entry point.

## Configuration

Use these wolfBoot configuration options:

| Option | Effect |
| ------ | ------ |
| `TZEN=1` | Builds wolfBoot for TrustZone-enabled STM32H5 parts. |
| `WOLFCRYPT_TZ=1` | Enables the wolfCrypt secure callable service layer. |
| `WOLFCRYPT_TZ_FWTPM=1` | Enables the secure fwTPM service and non-secure fwTPM test support. |

`WOLFCRYPT_TZ_FWTPM=1` defines `WOLFBOOT_TZ_FWTPM` for the secure and
non-secure builds. It also enables wolfTPM fwTPM sources, `WOLFTPM_FWTPM`,
`FWTPM_NO_NV`, and the callable fwTPM object.

The ready-to-use STM32H5 configuration is:

```sh
cp config/examples/stm32h5-tz-fwtpm.config .config
```

## Build

Build wolfBoot and the signed STM32H5 test application from the repository root:

```sh
cp config/examples/stm32h5-tz-fwtpm.config .config
make clean
make
make test-app/image_v1_signed.bin
```

The main outputs are:

| Output | Description |
| ------ | ----------- |
| `wolfboot.bin` | Secure wolfBoot image with the fwTPM service. |
| `test-app/image_v1_signed.bin` | Signed non-secure STM32H5 test application. |
| `test-app/image.elf` | Non-secure test application ELF for debugging. |

## Flash on STM32H5

Enable TrustZone and program the secure and non-secure images with
STM32CubeProgrammer:

```sh
STM32_Programmer_CLI -c port=swd mode=hotplug -ob TZEN=0xB4
STM32_Programmer_CLI -c port=swd -d wolfboot.bin 0x0C000000
STM32_Programmer_CLI -c port=swd -d test-app/image_v1_signed.bin 0x08060000
```

The addresses above match `config/examples/stm32h5-tz-fwtpm.config`:

| Region | Address |
| ------ | ------- |
| Secure wolfBoot image | `0x0C000000` |
| Non-secure boot partition | `0x08060000` |
| Non-secure update partition | `0x0C100000` |
| Swap partition | `0x0C1A0000` |
| NSC veneer region | `0x0C05C000` |

## Test

Open the board serial console and run the fwTPM test command:

```text
fwtpm
```

The test application initializes wolfTPM using the non-secure TIS callback,
queries capabilities, requests random bytes, extends PCR 0, verifies the PCR
value, and seals/unseals a PCR-bound secret. A successful run ends with:

```text
fwTPM NSC tests passed
```

The STM32H5 test app also runs the same fwTPM test automatically during startup
when built with `WOLFBOOT_TZ_FWTPM`.

## Notes

The current wolfBoot integration builds the secure fwTPM service with
`FWTPM_NO_NV`, so TPM NV state is not persistent across resets. To add persistent
NV storage, provide a flash-backed `FWTPM_NV_HAL` implementation and remove
`FWTPM_NO_NV` from the fwTPM build flags.

`WOLFCRYPT_TZ_FWTPM` is mutually exclusive with `WOLFCRYPT_TZ_PKCS11` and
`WOLFCRYPT_TZ_PSA` because each option selects a different TrustZone secure
service surface for the test application.
9 changes: 8 additions & 1 deletion include/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ extern int tolower(int c);
# define NO_CODING
#endif

#ifdef WOLFBOOT_TPM
#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FWTPM)
/* Do not use heap */
#define WOLFTPM2_NO_HEAP
/* small stack options */
Expand Down Expand Up @@ -632,6 +632,13 @@ extern int tolower(int c);
#undef NO_KDF
#endif

#if defined(WOLFBOOT_TZ_FWTPM)
#undef NO_CMAC
#undef NO_KDF
#define WOLFSSL_AES_CFB
#define WOLFSSL_SHA384
#endif

#ifdef __QNX__
# define WOLFSSL_HAVE_MIN
# define WOLFSSL_HAVE_MAX
Expand Down
27 changes: 27 additions & 0 deletions include/wolfboot/wcs_fwtpm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* wcs_fwtpm.h
*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*/

#ifndef WOLFBOOT_WCS_FWTPM_H
#define WOLFBOOT_WCS_FWTPM_H

#include <stdint.h>
#include "wolfboot/wc_secure.h"

#ifdef WOLFBOOT_TZ_FWTPM

#ifndef WCS_FWTPM_MAX_COMMAND_SIZE
#define WCS_FWTPM_MAX_COMMAND_SIZE 4096U
#endif

int CSME_NSE_API wcs_fwtpm_transmit(const uint8_t *cmd, uint32_t cmdSz,
uint8_t *rsp, uint32_t *rspSz);

void wcs_fwtpm_init(void);

#endif /* WOLFBOOT_TZ_FWTPM */

#endif /* WOLFBOOT_WCS_FWTPM_H */
2 changes: 1 addition & 1 deletion lib/wolfTPM
Submodule wolfTPM updated 128 files
55 changes: 55 additions & 0 deletions options.mk
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,15 @@ ifeq ($(WOLFCRYPT_TZ_PKCS11),1)
ifeq ($(WOLFCRYPT_TZ_PSA),1)
$(error WOLFCRYPT_TZ_PKCS11 and WOLFCRYPT_TZ_PSA are mutually exclusive)
endif
ifeq ($(WOLFCRYPT_TZ_FWTPM),1)
$(error WOLFCRYPT_TZ_PKCS11 and WOLFCRYPT_TZ_FWTPM are mutually exclusive)
endif
endif

ifeq ($(WOLFCRYPT_TZ_PSA),1)
ifeq ($(WOLFCRYPT_TZ_FWTPM),1)
$(error WOLFCRYPT_TZ_PSA and WOLFCRYPT_TZ_FWTPM are mutually exclusive)
endif
endif

ifeq ($(WOLFCRYPT_TZ_PKCS11),1)
Expand Down Expand Up @@ -919,6 +928,50 @@ ifeq ($(WOLFCRYPT_TZ_PSA),1)
endif
endif

ifeq ($(WOLFCRYPT_TZ_FWTPM),1)
CFLAGS+=-DWOLFBOOT_TZ_FWTPM
CFLAGS+=-DWOLFCRYPT_SECURE_MODE
CFLAGS+=-DWOLFTPM_FWTPM
CFLAGS+=-DFWTPM_NO_NV
CFLAGS+=-DWC_RSA_PSS
CFLAGS+=-DWOLFSSL_PSS_SALT_LEN_DISCOVER
CFLAGS+=-DFWTPM_MAX_COMMAND_SIZE=4096
CFLAGS+=-I$(WOLFBOOT_LIB_WOLFTPM)
ifeq ($(USE_CLANG),1)
CLANG_MULTILIB_FLAGS:=$(filter -mthumb -mlittle-endian,$(LDFLAGS)) $(filter -mcpu=%,$(CFLAGS))
LIBS+=$(shell $(CLANG_GCC_NAME) $(CLANG_MULTILIB_FLAGS) -print-file-name=libc.a)
LIBS+=$(shell $(CLANG_GCC_NAME) $(CLANG_MULTILIB_FLAGS) -print-libgcc-file-name)
else
LDFLAGS+=--specs=nano.specs
endif
WOLFCRYPT_OBJS+=src/store_sbrk.o
WOLFCRYPT_OBJS+=src/fwtpm_callable.o
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/fwtpm/fwtpm.o
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/fwtpm/fwtpm_command.o
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/fwtpm/fwtpm_crypto.o
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/fwtpm/fwtpm_nv.o
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_util.o
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_packet.o
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_crypto.o
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_param_enc.o
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hmac.o
ifneq ($(SIGN),ED25519)
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha512.o
endif
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/wc_encrypt.o
ifeq ($(ENCRYPT_WITH_AES128)$(ENCRYPT_WITH_AES256),)
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/aes.o
endif
WOLFCRYPT_OBJS+=$(RSA_OBJS)
ifeq ($(findstring ECC,$(SIGN)),)
ifeq ($(findstring ECC,$(SIGN_SECONDARY)),)
WOLFCRYPT_OBJS+=$(ECC_OBJS)
WOLFCRYPT_OBJS+=$(MATH_OBJS)
endif
endif
STACK_USAGE=20000
endif

OBJS+=$(PUBLIC_KEY_OBJS)
ifneq ($(STAGE1),1)
OBJS+=$(UPDATE_OBJS)
Expand All @@ -931,6 +984,8 @@ ifeq ($(WOLFTPM),1)
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_packet.o \
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_tis.o \
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_wrap.o \
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_crypto.o \
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_util.o \
$(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_param_enc.o
CFLAGS+=-I$(WOLFBOOT_LIB_WOLFTPM)
CFLAGS+=-D"WOLFBOOT_TPM"
Expand Down
Loading
Loading