From b22c85ed275b9f6a2ca9ed329649f990c884b40d Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Tue, 21 Apr 2026 20:53:48 +0200 Subject: [PATCH 1/5] Added support for fTPM in TrustZone + STM32H5 test app --- .../workflows/trustzone-emulator-tests.yml | 13 + Makefile | 2 +- config/examples/stm32h5-tz-ftpm.config | 35 +++ include/user_settings.h | 9 +- include/wolfboot/wcs_ftpm.h | 27 ++ lib/wolfTPM | 2 +- options.mk | 53 ++++ src/ftpm_callable.c | 146 +++++++++++ src/loader.c | 2 +- src/wc_callable.c | 7 + test-app/Makefile | 40 ++- test-app/app_stm32h5.c | 244 +++++++++++++++++- test-app/wcs/ftpm_stub.c | 208 +++++++++++++++ test-app/wcs/user_settings.h | 2 +- tools/config.mk | 2 + 15 files changed, 780 insertions(+), 12 deletions(-) create mode 100644 config/examples/stm32h5-tz-ftpm.config create mode 100644 include/wolfboot/wcs_ftpm.h create mode 100644 src/ftpm_callable.c create mode 100644 test-app/wcs/ftpm_stub.c diff --git a/.github/workflows/trustzone-emulator-tests.yml b/.github/workflows/trustzone-emulator-tests.yml index 757e779ebf..95214785e9 100644 --- a/.github/workflows/trustzone-emulator-tests.yml +++ b/.github/workflows/trustzone-emulator-tests.yml @@ -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 fTPM (stm32h5) + run: | + make clean distclean + cp config/examples/stm32h5-tz-ftpm.config .config + make + m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 600 \ + | tee /tmp/m33mu-ftpm.log + grep -q "fTPM PCR0 extended:" /tmp/m33mu-ftpm.log + grep -q "fTPM unsealed secret: wolfBoot fTPM PCR secret" /tmp/m33mu-ftpm.log + grep -q "fTPM NSC tests passed" /tmp/m33mu-ftpm.log + grep -q "\\[BKPT\\] imm=0x7f" /tmp/m33mu-ftpm.log + grep -q "\\[EXPECT BKPT\\] Success" /tmp/m33mu-ftpm.log + - name: Clean and build test with DICE attestation + OTP (stm32h5) run: | make clean distclean diff --git a/Makefile b/Makefile index 775822c7e4..f85d53f75c 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/config/examples/stm32h5-tz-ftpm.config b/config/examples/stm32h5-tz-ftpm.config new file mode 100644 index 0000000000..21d10f9586 --- /dev/null +++ b/config/examples/stm32h5-tz-ftpm.config @@ -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_FTPM=1 +IMAGE_HEADER_SIZE?=1024 +ARMORED=1 diff --git a/include/user_settings.h b/include/user_settings.h index ca93d72af9..a8735216b7 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -434,7 +434,7 @@ extern int tolower(int c); # define NO_CODING #endif -#ifdef WOLFBOOT_TPM +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) /* Do not use heap */ #define WOLFTPM2_NO_HEAP /* small stack options */ @@ -632,6 +632,13 @@ extern int tolower(int c); #undef NO_KDF #endif +#if defined(WOLFBOOT_TZ_FTPM) +#undef NO_CMAC +#undef NO_KDF +#define WOLFSSL_AES_CFB +#define WOLFSSL_SHA384 +#endif + #ifdef __QNX__ # define WOLFSSL_HAVE_MIN # define WOLFSSL_HAVE_MAX diff --git a/include/wolfboot/wcs_ftpm.h b/include/wolfboot/wcs_ftpm.h new file mode 100644 index 0000000000..1cd28f6551 --- /dev/null +++ b/include/wolfboot/wcs_ftpm.h @@ -0,0 +1,27 @@ +/* wcs_ftpm.h + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + */ + +#ifndef WOLFBOOT_WCS_FTPM_H +#define WOLFBOOT_WCS_FTPM_H + +#include +#include "wolfboot/wc_secure.h" + +#ifdef WOLFBOOT_TZ_FTPM + +#ifndef WCS_FTPM_MAX_COMMAND_SIZE +#define WCS_FTPM_MAX_COMMAND_SIZE 4096U +#endif + +int CSME_NSE_API wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, + uint8_t *rsp, uint32_t *rspSz); + +void wcs_ftpm_init(void); + +#endif /* WOLFBOOT_TZ_FTPM */ + +#endif /* WOLFBOOT_WCS_FTPM_H */ diff --git a/lib/wolfTPM b/lib/wolfTPM index efaab4afe6..c8d51e9693 160000 --- a/lib/wolfTPM +++ b/lib/wolfTPM @@ -1 +1 @@ -Subproject commit efaab4afe67fbe8616a08d46b721cb0cbd375894 +Subproject commit c8d51e969301859b16fd62fdaf2011a23546d8f2 diff --git a/options.mk b/options.mk index e75f43c6a2..2c4b22b0e4 100644 --- a/options.mk +++ b/options.mk @@ -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_FTPM),1) + $(error WOLFCRYPT_TZ_PKCS11 and WOLFCRYPT_TZ_FTPM are mutually exclusive) + endif +endif + +ifeq ($(WOLFCRYPT_TZ_PSA),1) + ifeq ($(WOLFCRYPT_TZ_FTPM),1) + $(error WOLFCRYPT_TZ_PSA and WOLFCRYPT_TZ_FTPM are mutually exclusive) + endif endif ifeq ($(WOLFCRYPT_TZ_PKCS11),1) @@ -919,6 +928,50 @@ ifeq ($(WOLFCRYPT_TZ_PSA),1) endif endif +ifeq ($(WOLFCRYPT_TZ_FTPM),1) + CFLAGS+=-DWOLFBOOT_TZ_FTPM + 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/ftpm_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) diff --git a/src/ftpm_callable.c b/src/ftpm_callable.c new file mode 100644 index 0000000000..8a4c39aba4 --- /dev/null +++ b/src/ftpm_callable.c @@ -0,0 +1,146 @@ +/* ftpm_callable.c + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + */ + +#ifdef WOLFBOOT_TZ_FTPM + +#include +#include + +#include "store_sbrk.h" +#include "wolfboot/wcs_ftpm.h" +#include "wolftpm/fwtpm/fwtpm.h" +#include "wolftpm/fwtpm/fwtpm_command.h" +#include "wolftpm/fwtpm/fwtpm_nv.h" +#include "wolftpm/tpm2_types.h" + +static FWTPM_CTX ftpm_ctx; +static int ftpm_ready; + +extern unsigned int _start_heap; +extern unsigned int _heap_size; + +void *_sbrk(unsigned int incr) +{ + static uint8_t *heap; + return wolfboot_store_sbrk(incr, &heap, (uint8_t *)&_start_heap, + (uint32_t)(&_heap_size)); +} + +#ifndef FWTPM_NO_NV +#define WCS_FTPM_NV_SIZE (16U * 1024U) +static uint8_t ftpm_nv[WCS_FTPM_NV_SIZE]; + +static int ftpm_nv_read(void *ctx, word32 offset, byte *buf, word32 size) +{ + uint8_t *nv = (uint8_t *)ctx; + + if (nv == NULL || buf == NULL || offset > WCS_FTPM_NV_SIZE || + size > (WCS_FTPM_NV_SIZE - offset)) { + return BAD_FUNC_ARG; + } + + XMEMCPY(buf, nv + offset, size); + return TPM_RC_SUCCESS; +} + +static int ftpm_nv_write(void *ctx, word32 offset, const byte *buf, + word32 size) +{ + uint8_t *nv = (uint8_t *)ctx; + + if (nv == NULL || buf == NULL || offset > WCS_FTPM_NV_SIZE || + size > (WCS_FTPM_NV_SIZE - offset)) { + return BAD_FUNC_ARG; + } + + XMEMCPY(nv + offset, buf, size); + return TPM_RC_SUCCESS; +} + +static int ftpm_nv_erase(void *ctx, word32 offset, word32 size) +{ + uint8_t *nv = (uint8_t *)ctx; + + if (nv == NULL || offset > WCS_FTPM_NV_SIZE || + size > (WCS_FTPM_NV_SIZE - offset)) { + return BAD_FUNC_ARG; + } + + XMEMSET(nv + offset, 0xFF, size); + return TPM_RC_SUCCESS; +} + +static FWTPM_NV_HAL ftpm_nv_hal = { + ftpm_nv_read, + ftpm_nv_write, + ftpm_nv_erase, + ftpm_nv, + WCS_FTPM_NV_SIZE +}; +#endif /* !FWTPM_NO_NV */ + +static uint32_t ftpm_rsp_size(const uint8_t *rsp, int rspLen) +{ + if (rsp == NULL || rspLen < TPM2_HEADER_SIZE) { + return 0; + } + + return ((uint32_t)rsp[2] << 24) | + ((uint32_t)rsp[3] << 16) | + ((uint32_t)rsp[4] << 8) | + (uint32_t)rsp[5]; +} + +void wcs_ftpm_init(void) +{ + int rc; + +#ifndef FWTPM_NO_NV + XMEMSET(ftpm_nv, 0xFF, sizeof(ftpm_nv)); +#endif + XMEMSET(&ftpm_ctx, 0, sizeof(ftpm_ctx)); +#ifndef FWTPM_NO_NV + (void)FWTPM_NV_SetHAL(&ftpm_ctx, &ftpm_nv_hal); +#endif + + rc = FWTPM_Init(&ftpm_ctx); + if (rc == 0) { + ftpm_ctx.wasStarted = 1; + ftpm_ready = 1; + } +} + +int CSME_NSE_API wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, + uint8_t *rsp, uint32_t *rspSz) +{ + int rspLen; + + if (!ftpm_ready) { + return TPM_RC_INITIALIZE; + } + if (cmd == NULL || rsp == NULL || rspSz == NULL || cmdSz == 0U || + cmdSz > WCS_FTPM_MAX_COMMAND_SIZE || *rspSz == 0U || + *rspSz > WCS_FTPM_MAX_COMMAND_SIZE) { + return BAD_FUNC_ARG; + } + + rspLen = (int)*rspSz; + int rc = FWTPM_ProcessCommand(&ftpm_ctx, cmd, (int)cmdSz, rsp, &rspLen, 0); + if (rc >= 0) { + uint32_t wireSz = ftpm_rsp_size(rsp, rspLen); + if (wireSz > 0U && wireSz <= *rspSz) { + *rspSz = wireSz; + rc = TPM_RC_SUCCESS; + } + else if (rspLen >= 0) { + *rspSz = (uint32_t)rspLen; + } + } + return rc; +} + +#endif /* WOLFBOOT_TZ_FTPM */ diff --git a/src/loader.c b/src/loader.c index 929b818872..59527031de 100644 --- a/src/loader.c +++ b/src/loader.c @@ -123,7 +123,7 @@ int main(void) uart_init(UART_FLASH_BITRATE, 8, 'N', 1); uart_send_current_version(); #endif -#ifdef WOLFBOOT_TPM +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) if (wolfBoot_tpm2_init() != 0) { wolfBoot_panic(); } diff --git a/src/wc_callable.c b/src/wc_callable.c index 656f9746b2..f3159e8cd0 100644 --- a/src/wc_callable.c +++ b/src/wc_callable.c @@ -30,6 +30,10 @@ #include "hal.h" #include +#ifdef WOLFBOOT_TZ_FTPM +#include "wolfboot/wcs_ftpm.h" +#endif + static WC_RNG wcs_rng; int CSME_NSE_API wcs_get_random(uint8_t *rand, uint32_t size) @@ -41,6 +45,9 @@ void wcs_Init(void) { hal_trng_init(); wc_InitRng(&wcs_rng); +#ifdef WOLFBOOT_TZ_FTPM + wcs_ftpm_init(); +#endif } #endif /* WOLFCRYPT_SECURE_MODE */ diff --git a/test-app/Makefile b/test-app/Makefile index bb50facbab..531bdd7fa8 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -4,9 +4,13 @@ -include ./wcs/pkcs11.mk WOLFBOOT_LIB_WOLFSSL?=../lib/wolfssl +WOLFBOOT_LIB_WOLFTPM?=../lib/wolfTPM WOLFSSL_LOCAL_OBJDIR?=wolfssl_obj +WOLFTPM_LOCAL_OBJDIR?=wolftpm_obj vpath %.c $(WOLFBOOT_LIB_WOLFSSL) vpath %.S $(WOLFBOOT_LIB_WOLFSSL) +vpath %.c $(WOLFBOOT_LIB_WOLFTPM) +vpath %.S $(WOLFBOOT_LIB_WOLFTPM) TARGET?=none ARCH?=ARM @@ -100,6 +104,11 @@ ifeq ($(WOLFCRYPT_TZ_PSA),1) WOLFCRYPT_TZ_PSA=1 endif +ifeq ($(WOLFCRYPT_TZ_FTPM),1) + WOLFCRYPT_TZ=1 + WOLFCRYPT_TZ_FTPM=1 +endif + # Setup default linker flags LDFLAGS+=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=image.map -nostartfiles @@ -325,6 +334,24 @@ ifeq ($(TZEN),1) $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/psa/psa_hash.o \ $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/psa/psa_pkcbs.o endif + ifeq ($(WOLFCRYPT_TZ_FTPM),1) + CFLAGS:=$(filter-out -DWOLFTPM_FWTPM,$(CFLAGS)) + CFLAGS+=-DWOLFBOOT_TZ_FTPM -DWOLFBOOT_TPM -DWOLFTPM_ADV_IO + CFLAGS+=-DWOLFTPM_EXAMPLE_HAL + CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFTPM)" + APP_OBJS+=./wcs/ftpm_stub.o + WOLFTPM_APP_OBJS+=\ + $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2.o \ + $(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_param_enc.o \ + $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_util.o \ + $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_crypto.o + WOLFTPM_APP_OBJS := $(patsubst $(WOLFBOOT_LIB_WOLFTPM)/%, \ + $(WOLFTPM_LOCAL_OBJDIR)/%, $(WOLFTPM_APP_OBJS)) + APP_OBJS+=$(sort $(WOLFTPM_APP_OBJS)) + endif WOLFCRYPT_APP_OBJS := $(patsubst $(WOLFBOOT_LIB_WOLFSSL)/%, \ $(WOLFSSL_LOCAL_OBJDIR)/%, $(WOLFCRYPT_APP_OBJS)) ifneq ($(WOLFCRYPT_TZ_PKCS11),1) @@ -908,6 +935,7 @@ endif # Capture final flags for locally built wolfSSL objects. WOLFSSL_CFLAGS:=$(CFLAGS) +WOLFTPM_CFLAGS:=$(CFLAGS) ifeq ($(WOLFHSM_CLIENT),1) CFLAGS += -DSTRING_USER -I"$(WOLFBOOT_LIB_WOLFSSL)" @@ -995,9 +1023,19 @@ $(WOLFSSL_LOCAL_OBJDIR)/%.o: %.S $(Q)mkdir -p $(dir $@) $(Q)$(CC) $(WOLFSSL_CFLAGS) -c $(OUTPUT_FLAG) $@ $< +$(WOLFTPM_LOCAL_OBJDIR)/%.o: %.c + @echo "\t[CC-$(ARCH)] $@" + $(Q)mkdir -p $(dir $@) + $(Q)$(CC) $(WOLFTPM_CFLAGS) -c $(OUTPUT_FLAG) $@ $< + +$(WOLFTPM_LOCAL_OBJDIR)/%.o: %.S + @echo "\t[AS-$(ARCH)] $@" + $(Q)mkdir -p $(dir $@) + $(Q)$(CC) $(WOLFTPM_CFLAGS) -c $(OUTPUT_FLAG) $@ $< + clean: $(Q)rm -f *.bin *.elf tags *.o $(LSCRIPT) $(APP_OBJS) wcs/*.o - $(Q)rm -rf $(WOLFSSL_LOCAL_OBJDIR) + $(Q)rm -rf $(WOLFSSL_LOCAL_OBJDIR) $(WOLFTPM_LOCAL_OBJDIR) $(LSCRIPT): $(LSCRIPT_TEMPLATE) FORCE $(Q)printf "%d" $(WOLFBOOT_PARTITION_BOOT_ADDRESS) > .wolfboot-offset diff --git a/test-app/app_stm32h5.c b/test-app/app_stm32h5.c index 2c68e25839..f8f1351172 100644 --- a/test-app/app_stm32h5.c +++ b/test-app/app_stm32h5.c @@ -36,10 +36,15 @@ #endif #include "target.h" -#ifdef WOLFBOOT_TPM +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) #include "tpm.h" #endif +#ifdef WOLFBOOT_TZ_FTPM +#include "wolftpm/tpm2_wrap.h" +#include "wolfssl/wolfcrypt/sha256.h" +#endif + #ifdef WOLFBOOT_TZ_PKCS11 #include "test_pkcs11.h" #endif @@ -201,7 +206,7 @@ static int cmd_timestamp(const char *args); static int cmd_update(const char *args); static int cmd_update_xmodem(const char *args); static int cmd_reboot(const char *args); -#ifdef WOLFBOOT_TPM +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) static int cmd_tpm_info(const char *args); #ifdef WOLFTPM_MFG_IDENTITY static int cmd_tpm_idevid(const char *args); @@ -210,6 +215,9 @@ static int cmd_tpm_signed_timestamp(const char *args); static int cmd_tpm_quote(const char *args); #endif #endif +#ifdef WOLFBOOT_TZ_FTPM +static int cmd_ftpm_test(const char *args); +#endif #define CMD_BUFFER_SIZE 256 @@ -238,7 +246,7 @@ struct console_command COMMANDS[] = {cmd_test, "test", "run the wolfCrypt test"}, {cmd_update_xmodem, "update", "update the firmware via XMODEM"}, {cmd_reboot, "reboot", "reboot the system"}, -#ifdef WOLFBOOT_TPM +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) {cmd_tpm_info, "tpm", "get TPM capabilities"}, #ifdef WOLFTPM_MFG_IDENTITY {cmd_tpm_idevid, "idevid", "show Initial Device Identification (IDevID) certificate"}, @@ -246,6 +254,9 @@ struct console_command COMMANDS[] = {cmd_tpm_signed_timestamp, "signed_time", "TPM IAK signed timestamp attestation report"}, {cmd_tpm_quote, "quote", "TPM IAK signed PCR(s) attestation report"}, #endif +#endif +#ifdef WOLFBOOT_TZ_FTPM + {cmd_ftpm_test, "ftpm", "run fTPM tests through the secure NSC interface"}, #endif {NULL, "", ""} }; @@ -852,7 +863,7 @@ static int cmd_test(const char *args) return 0; } -#ifdef WOLFBOOT_TPM +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) #include #include @@ -1119,7 +1130,221 @@ static int cmd_tpm_quote(const char *args) return rc; } #endif /* WOLFTPM_MFG_IDENTITY */ -#endif /* WOLFBOOT_TPM */ +#endif /* WOLFBOOT_TPM && !WOLFBOOT_TZ_FTPM */ + +#ifdef WOLFBOOT_TZ_FTPM +extern int TPM2_IoCb_FtpmNsc(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, + BYTE *buf, UINT16 size, void *userCtx); + +static int ftpm_expected_pcr_after_extend(const uint8_t *before, + const uint8_t *event, uint8_t *expected) +{ + wc_Sha256 sha; + int rc; + + rc = wc_InitSha256(&sha); + if (rc == 0) { + rc = wc_Sha256Update(&sha, before, WC_SHA256_DIGEST_SIZE); + } + if (rc == 0) { + rc = wc_Sha256Update(&sha, event, WC_SHA256_DIGEST_SIZE); + } + if (rc == 0) { + rc = wc_Sha256Final(&sha, expected); + } + + wc_Sha256Free(&sha); + return rc; +} + +static int ftpm_seal_unseal_pcr_secret(WOLFTPM2_DEV *dev) +{ + static const uint8_t secret[] = "wolfBoot fTPM PCR secret"; + uint8_t pcrArray[1] = { 0 }; + uint8_t policyDigest[TPM_MAX_DIGEST_SIZE]; + word32 policyDigestSz = sizeof(policyDigest); + WOLFTPM2_KEY storage; + WOLFTPM2_KEYBLOB sealBlob; + WOLFTPM2_SESSION trialSession; + WOLFTPM2_SESSION policySession; + TPMT_PUBLIC sealTemplate; + Unseal_In unsealIn; + Unseal_Out unsealOut; + int rc; + + XMEMSET(&storage, 0, sizeof(storage)); + XMEMSET(&sealBlob, 0, sizeof(sealBlob)); + XMEMSET(&trialSession, 0, sizeof(trialSession)); + XMEMSET(&policySession, 0, sizeof(policySession)); + XMEMSET(&sealTemplate, 0, sizeof(sealTemplate)); + XMEMSET(&unsealIn, 0, sizeof(unsealIn)); + XMEMSET(&unsealOut, 0, sizeof(unsealOut)); + + rc = wolfTPM2_CreateSRK(dev, &storage, TPM_ALG_ECC, NULL, 0); + if (rc != TPM_RC_SUCCESS) { + printf("fTPM seal SRK failed: 0x%x\r\n", rc); + return rc; + } + + rc = wolfTPM2_StartSession(dev, &trialSession, NULL, NULL, + TPM_SE_TRIAL, TPM_ALG_NULL); + if (rc == TPM_RC_SUCCESS) { + rc = wolfTPM2_PolicyPCR(dev, trialSession.handle.hndl, + TPM_ALG_SHA256, pcrArray, 1); + } + if (rc == TPM_RC_SUCCESS) { + rc = wolfTPM2_GetPolicyDigest(dev, trialSession.handle.hndl, + policyDigest, &policyDigestSz); + } + wolfTPM2_UnloadHandle(dev, &trialSession.handle); + if (rc != TPM_RC_SUCCESS) { + printf("fTPM seal policy failed: 0x%x\r\n", rc); + wolfTPM2_UnloadHandle(dev, &storage.handle); + return rc; + } + + wolfTPM2_GetKeyTemplate_KeySeal(&sealTemplate, TPM_ALG_SHA256); + sealTemplate.objectAttributes &= ~TPMA_OBJECT_userWithAuth; + sealTemplate.authPolicy.size = (UINT16)policyDigestSz; + XMEMCPY(sealTemplate.authPolicy.buffer, policyDigest, policyDigestSz); + + rc = wolfTPM2_CreateKeySeal_ex(dev, &sealBlob, &storage.handle, + &sealTemplate, NULL, 0, TPM_ALG_SHA256, pcrArray, 1, + secret, (int)sizeof(secret)); + if (rc == TPM_RC_SUCCESS) { + rc = wolfTPM2_LoadKey(dev, &sealBlob, &storage.handle); + } + if (rc == TPM_RC_SUCCESS) { + rc = wolfTPM2_StartSession(dev, &policySession, NULL, NULL, + TPM_SE_POLICY, TPM_ALG_NULL); + } + if (rc == TPM_RC_SUCCESS) { + rc = wolfTPM2_PolicyPCR(dev, policySession.handle.hndl, + TPM_ALG_SHA256, pcrArray, 1); + } + if (rc == TPM_RC_SUCCESS) { + rc = wolfTPM2_SetAuthSession(dev, 0, &policySession, + TPMA_SESSION_continueSession); + } + if (rc == TPM_RC_SUCCESS) { + wolfTPM2_SetAuthHandleName(dev, 0, &sealBlob.handle); + unsealIn.itemHandle = sealBlob.handle.hndl; + rc = TPM2_Unseal(&unsealIn, &unsealOut); + } + + wolfTPM2_UnloadHandle(dev, &policySession.handle); + wolfTPM2_UnloadHandle(dev, &sealBlob.handle); + wolfTPM2_UnloadHandle(dev, &storage.handle); + + if (rc != TPM_RC_SUCCESS) { + printf("fTPM unseal failed: 0x%x\r\n", rc); + return rc; + } + + if (unsealOut.outData.size != sizeof(secret) || + XMEMCMP(unsealOut.outData.buffer, secret, sizeof(secret)) != 0) { + printf("fTPM unsealed secret mismatch\r\n"); + return TPM_RC_FAILURE; + } + + printf("fTPM unsealed secret: %.*s\r\n", + unsealOut.outData.size, unsealOut.outData.buffer); + return TPM_RC_SUCCESS; +} + +static int cmd_ftpm_test(const char *args) +{ + int rc; + WOLFTPM2_DEV dev; + WOLFTPM2_CAPS caps; + uint8_t rnd[16]; + uint8_t pcr[TPM_MAX_DIGEST_SIZE]; + uint8_t pcrBefore[TPM_SHA256_DIGEST_SIZE]; + uint8_t pcrEvent[TPM_SHA256_DIGEST_SIZE]; + uint8_t pcrExpected[TPM_SHA256_DIGEST_SIZE]; + int pcrSz = 0; + + (void)args; + + XMEMSET(&dev, 0, sizeof(dev)); + XMEMSET(&caps, 0, sizeof(caps)); + XMEMSET(rnd, 0, sizeof(rnd)); + XMEMSET(pcr, 0, sizeof(pcr)); + XMEMSET(pcrBefore, 0, sizeof(pcrBefore)); + XMEMSET(pcrEvent, 0, sizeof(pcrEvent)); + XMEMSET(pcrExpected, 0, sizeof(pcrExpected)); + + rc = wolfTPM2_Init(&dev, TPM2_IoCb_FtpmNsc, NULL); + if (rc != TPM_RC_SUCCESS) { + printf("fTPM init failed: 0x%x\r\n", rc); + return rc; + } + + rc = wolfTPM2_GetCapabilities(&dev, &caps); + if (rc == TPM_RC_SUCCESS) { + printf("fTPM caps: mfg %s vendor %s fw %u.%u\r\n", + caps.mfgStr, caps.vendorStr, caps.fwVerMajor, caps.fwVerMinor); + } + + if (rc == TPM_RC_SUCCESS) { + int randRc = wolfTPM2_GetRandom(&dev, rnd, sizeof(rnd)); + if (randRc == TPM_RC_SUCCESS) { + printf("fTPM random:"); + print_hex(rnd, sizeof(rnd), 0); + } + else { + printf("fTPM random unavailable: 0x%x\r\n", randRc); + } + } + + if (rc == TPM_RC_SUCCESS) { + pcrSz = sizeof(pcr); + rc = wolfTPM2_ReadPCR(&dev, 0, TPM_ALG_SHA256, pcr, &pcrSz); + if (rc == TPM_RC_SUCCESS) { + XMEMCPY(pcrBefore, pcr, sizeof(pcrBefore)); + } + } + + if (rc == TPM_RC_SUCCESS) { + rc = wc_Sha256Hash((const uint8_t *)"wolfBoot fTPM PCR event", + 23, pcrEvent); + } + if (rc == TPM_RC_SUCCESS) { + rc = ftpm_expected_pcr_after_extend(pcrBefore, pcrEvent, pcrExpected); + } + if (rc == TPM_RC_SUCCESS) { + rc = wolfTPM2_ExtendPCR(&dev, 0, TPM_ALG_SHA256, pcrEvent, + sizeof(pcrEvent)); + } + if (rc == TPM_RC_SUCCESS) { + pcrSz = sizeof(pcr); + rc = wolfTPM2_ReadPCR(&dev, 0, TPM_ALG_SHA256, pcr, &pcrSz); + if (rc == TPM_RC_SUCCESS) { + printf("fTPM PCR0 extended:"); + print_hex(pcr, (uint32_t)pcrSz, 0); + } + } + if (rc == TPM_RC_SUCCESS && (pcrSz != (int)sizeof(pcrExpected) || + XMEMCMP(pcr, pcrExpected, sizeof(pcrExpected)) != 0)) { + printf("fTPM PCR0 extend mismatch\r\n"); + rc = TPM_RC_FAILURE; + } + if (rc == TPM_RC_SUCCESS) { + rc = ftpm_seal_unseal_pcr_secret(&dev); + } + + wolfTPM2_Cleanup(&dev); + + if (rc == TPM_RC_SUCCESS) { + printf("fTPM NSC tests passed\r\n"); + } + else { + printf("fTPM NSC tests failed: 0x%x\r\n", rc); + } + + return rc; +} +#endif /* WOLFBOOT_TZ_FTPM */ static int parse_cmd(const char *cmd) @@ -1268,9 +1493,16 @@ void main(void) #endif cmd_info(NULL); -#ifdef WOLFBOOT_TPM +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) cmd_tpm_info(NULL); #endif +#ifdef WOLFBOOT_TZ_FTPM + ret = cmd_ftpm_test(NULL); + if (ret == 0) + asm volatile ("bkpt #0x7f"); + else + asm volatile ("bkpt #0x7e"); +#endif #if defined(WOLFBOOT_ATTESTATION_TEST) && defined(WOLFCRYPT_TZ_PSA) (void)run_attestation_test(); diff --git a/test-app/wcs/ftpm_stub.c b/test-app/wcs/ftpm_stub.c new file mode 100644 index 0000000000..c698c02f23 --- /dev/null +++ b/test-app/wcs/ftpm_stub.c @@ -0,0 +1,208 @@ +/* ftpm_stub.c + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + */ + +#ifdef WOLFBOOT_TZ_FTPM + +#include +#include + +#include "wolfboot/wcs_ftpm.h" +#include "wolftpm/tpm2.h" +#include "wolftpm/tpm2_tis.h" + +#define FTPM_TIS_BASE 0xD40000U +#define FTPM_TIS_ACCESS 0x0000U +#define FTPM_TIS_INTF_CAPS 0x0014U +#define FTPM_TIS_STS 0x0018U +#define FTPM_TIS_BURST_COUNT 0x0019U +#define FTPM_TIS_DATA_FIFO 0x0024U +#define FTPM_TIS_DID_VID 0x0F00U +#define FTPM_TIS_RID 0x0F04U + +#define FTPM_ACCESS_VALID 0x80U +#define FTPM_ACCESS_ACTIVE_LOCALITY 0x20U +#define FTPM_ACCESS_REQUEST_USE 0x02U + +#define FTPM_STS_VALID 0x80U +#define FTPM_STS_COMMAND_READY 0x40U +#define FTPM_STS_GO 0x20U +#define FTPM_STS_DATA_AVAIL 0x10U +#define FTPM_STS_DATA_EXPECT 0x08U + +#define FTPM_BURST_COUNT 64U + +struct ftpm_tis_state { + uint8_t cmd[WCS_FTPM_MAX_COMMAND_SIZE]; + uint8_t rsp[WCS_FTPM_MAX_COMMAND_SIZE]; + uint32_t cmdSz; + uint32_t rspSz; + uint32_t rspPos; + uint8_t locality; + uint8_t status; +}; + +static struct ftpm_tis_state ftpm_tis = { + {0}, {0}, 0, 0, 0, 0, + FTPM_STS_VALID | FTPM_STS_COMMAND_READY +}; + +static uint32_t ftpm_reg_offset(uint32_t addr) +{ + return (addr - FTPM_TIS_BASE) & 0x0FFFU; +} + +static void ftpm_store_le(uint8_t *buf, uint16_t size, uint32_t val) +{ + uint16_t i; + + for (i = 0; i < size; i++) { + buf[i] = (uint8_t)(val >> (8U * i)); + } +} + +static uint32_t ftpm_cmd_size(void) +{ + if (ftpm_tis.cmdSz < TPM2_HEADER_SIZE) { + return TPM2_HEADER_SIZE; + } + + return ((uint32_t)ftpm_tis.cmd[2] << 24) | + ((uint32_t)ftpm_tis.cmd[3] << 16) | + ((uint32_t)ftpm_tis.cmd[4] << 8) | + (uint32_t)ftpm_tis.cmd[5]; +} + +static int ftpm_execute(void) +{ + int rc; + + ftpm_tis.rspSz = sizeof(ftpm_tis.rsp); + ftpm_tis.rspPos = 0; + + rc = wcs_ftpm_transmit(ftpm_tis.cmd, ftpm_tis.cmdSz, ftpm_tis.rsp, + &ftpm_tis.rspSz); + ftpm_tis.cmdSz = 0; + + if (rc == TPM_RC_SUCCESS) { + ftpm_tis.status = FTPM_STS_VALID | FTPM_STS_DATA_AVAIL; + } + else { + ftpm_tis.rspSz = 0; + ftpm_tis.status = FTPM_STS_VALID | FTPM_STS_COMMAND_READY; + } + + return rc; +} + +int TPM2_IoCb_FtpmNsc(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, + BYTE *buf, UINT16 size, void *userCtx) +{ + uint32_t off; + uint16_t burst; + + (void)ctx; + (void)userCtx; + + if (buf == NULL || size == 0U || addr < FTPM_TIS_BASE) { + return BAD_FUNC_ARG; + } + + off = ftpm_reg_offset(addr); + burst = FTPM_BURST_COUNT; + + if (isRead) { + switch (off) { + case FTPM_TIS_ACCESS: + buf[0] = FTPM_ACCESS_VALID | FTPM_ACCESS_ACTIVE_LOCALITY; + break; + case FTPM_TIS_STS: + XMEMSET(buf, 0, size); + buf[0] = ftpm_tis.status; + if (size > 1U) { + buf[1] = (uint8_t)burst; + } + if (size > 2U) { + buf[2] = (uint8_t)(burst >> 8); + } + break; + case FTPM_TIS_BURST_COUNT: + ftpm_store_le(buf, size, burst); + break; + case FTPM_TIS_BURST_COUNT + 1U: + ftpm_store_le(buf, size, burst >> 8); + break; + case FTPM_TIS_DATA_FIFO: + if (ftpm_tis.rspPos + size > ftpm_tis.rspSz) { + return TPM_RC_FAILURE; + } + XMEMCPY(buf, ftpm_tis.rsp + ftpm_tis.rspPos, size); + ftpm_tis.rspPos += size; + if (ftpm_tis.rspPos >= ftpm_tis.rspSz) { + ftpm_tis.status = FTPM_STS_VALID | FTPM_STS_COMMAND_READY; + } + break; + case FTPM_TIS_INTF_CAPS: + ftpm_store_le(buf, size, 0x00000183U); + break; + case FTPM_TIS_DID_VID: + ftpm_store_le(buf, size, 0x00011B4EU); + break; + case FTPM_TIS_RID: + buf[0] = 0x01U; + break; + default: + XMEMSET(buf, 0, size); + break; + } + } + else { + switch (off) { + case FTPM_TIS_ACCESS: + if ((buf[0] & FTPM_ACCESS_REQUEST_USE) != 0U) { + ftpm_tis.locality = 0; + } + break; + case FTPM_TIS_STS: + if ((buf[0] & FTPM_STS_COMMAND_READY) != 0U) { + ftpm_tis.cmdSz = 0; + ftpm_tis.rspSz = 0; + ftpm_tis.rspPos = 0; + ftpm_tis.status = FTPM_STS_VALID | + FTPM_STS_COMMAND_READY; + } + else if ((buf[0] & FTPM_STS_GO) != 0U) { + return ftpm_execute(); + } + break; + case FTPM_TIS_DATA_FIFO: + if (ftpm_tis.cmdSz + size > sizeof(ftpm_tis.cmd)) { + return TPM_RC_FAILURE; + } + XMEMCPY(ftpm_tis.cmd + ftpm_tis.cmdSz, buf, size); + ftpm_tis.cmdSz += size; + if (ftpm_tis.cmdSz < ftpm_cmd_size()) { + ftpm_tis.status = FTPM_STS_VALID | FTPM_STS_DATA_EXPECT; + } + else { + ftpm_tis.status = FTPM_STS_VALID; + } + break; + default: + break; + } + } + + return TPM_RC_SUCCESS; +} + +int TPM2_IoCb(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, BYTE *buf, + UINT16 size, void *userCtx) +{ + return TPM2_IoCb_FtpmNsc(ctx, isRead, addr, buf, size, userCtx); +} + +#endif /* WOLFBOOT_TZ_FTPM */ diff --git a/test-app/wcs/user_settings.h b/test-app/wcs/user_settings.h index 2f497f77a1..20e431503c 100644 --- a/test-app/wcs/user_settings.h +++ b/test-app/wcs/user_settings.h @@ -156,7 +156,7 @@ extern int tolower(int c); #define HAVE_PKCS8 #define HAVE_PKCS12 -#ifdef SECURE_PKCS11 +#if defined(SECURE_PKCS11) || defined(WOLFBOOT_TZ_FTPM) static inline int wcs_cmse_get_random(unsigned char* output, int sz) { diff --git a/tools/config.mk b/tools/config.mk index 2d158ee3ff..3aae0835fe 100644 --- a/tools/config.mk +++ b/tools/config.mk @@ -66,6 +66,7 @@ ifeq ($(ARCH),) WOLFCRYPT_TZ?=0 WOLFCRYPT_TZ_PKCS11?=0 WOLFCRYPT_TZ_PSA?=0 + WOLFCRYPT_TZ_FTPM?=0 WOLFBOOT_PARTITION_SIZE?=0x20000 WOLFBOOT_SECTOR_SIZE?=0x20000 WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08020000 @@ -104,6 +105,7 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO WOLFBOOT_UDS_OBKEYS \ WOLFCRYPT_TZ WOLFCRYPT_TZ_PKCS11 \ WOLFCRYPT_TZ_PSA \ + WOLFCRYPT_TZ_FTPM \ WOLFBOOT_PARTITION_SIZE WOLFBOOT_SECTOR_SIZE \ WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \ WOLFBOOT_PARTITION_SWAP_ADDRESS WOLFBOOT_LOAD_ADDRESS \ From 884352cf08a148c8803f30239879c60adf8ef976 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 22 Apr 2026 12:17:51 +0200 Subject: [PATCH 2/5] Updated object list to match latest wolfTPM --- options.mk | 2 ++ stage1/Makefile | 2 ++ tools/tpm/Makefile | 2 ++ 3 files changed, 6 insertions(+) diff --git a/options.mk b/options.mk index 2c4b22b0e4..c8828aed47 100644 --- a/options.mk +++ b/options.mk @@ -984,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" diff --git a/stage1/Makefile b/stage1/Makefile index a5af1526df..2f0b027b26 100644 --- a/stage1/Makefile +++ b/stage1/Makefile @@ -59,6 +59,8 @@ ifeq ($(WOLFTPM),1) tpm2_packet.o \ tpm2_tis.o \ tpm2_wrap.o \ + tpm2_crypto.o \ + tpm2_util.o \ tpm2_param_enc.o \ image.o endif diff --git a/tools/tpm/Makefile b/tools/tpm/Makefile index e9bf9f37cc..050554b460 100644 --- a/tools/tpm/Makefile +++ b/tools/tpm/Makefile @@ -67,6 +67,8 @@ OBJS_REAL=\ $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2.o \ $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_linux.o \ $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_packet.o \ + $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_crypto.o \ + $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_util.o \ $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_param_enc.o \ $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_swtpm.o \ $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_tis.o \ From b26d38ed414fe7c0d9b678b5cc13e381cdebeab4 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 22 Apr 2026 12:22:43 +0200 Subject: [PATCH 3/5] Fix fTPM NSC bounds handling --- src/ftpm_callable.c | 27 ++++++---- test-app/wcs/ftpm_stub.c | 17 +++++-- tools/unit-tests/Makefile | 7 ++- tools/unit-tests/unit-ftpm-stub.c | 83 +++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 14 deletions(-) create mode 100644 tools/unit-tests/unit-ftpm-stub.c diff --git a/src/ftpm_callable.c b/src/ftpm_callable.c index 8a4c39aba4..94d9879376 100644 --- a/src/ftpm_callable.c +++ b/src/ftpm_callable.c @@ -117,28 +117,37 @@ void wcs_ftpm_init(void) int CSME_NSE_API wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, uint8_t *rsp, uint32_t *rspSz) { + int rc; int rspLen; + uint32_t rspCapacity; + uint32_t wireSz; if (!ftpm_ready) { return TPM_RC_INITIALIZE; } if (cmd == NULL || rsp == NULL || rspSz == NULL || cmdSz == 0U || - cmdSz > WCS_FTPM_MAX_COMMAND_SIZE || *rspSz == 0U || - *rspSz > WCS_FTPM_MAX_COMMAND_SIZE) { + cmdSz > WCS_FTPM_MAX_COMMAND_SIZE) { return BAD_FUNC_ARG; } - rspLen = (int)*rspSz; - int rc = FWTPM_ProcessCommand(&ftpm_ctx, cmd, (int)cmdSz, rsp, &rspLen, 0); - if (rc >= 0) { - uint32_t wireSz = ftpm_rsp_size(rsp, rspLen); - if (wireSz > 0U && wireSz <= *rspSz) { + rspCapacity = *rspSz; + if (rspCapacity == 0U || rspCapacity > WCS_FTPM_MAX_COMMAND_SIZE) { + return BAD_FUNC_ARG; + } + + rspLen = (int)rspCapacity; + rc = FWTPM_ProcessCommand(&ftpm_ctx, cmd, (int)cmdSz, rsp, &rspLen, 0); + if (rc == TPM_RC_SUCCESS) { + wireSz = ftpm_rsp_size(rsp, rspLen); + if (wireSz > 0U && wireSz <= rspCapacity) { *rspSz = wireSz; - rc = TPM_RC_SUCCESS; } - else if (rspLen >= 0) { + else if (rspLen >= 0 && (uint32_t)rspLen <= rspCapacity) { *rspSz = (uint32_t)rspLen; } + else { + rc = TPM_RC_FAILURE; + } } return rc; } diff --git a/test-app/wcs/ftpm_stub.c b/test-app/wcs/ftpm_stub.c index c698c02f23..9df3de3217 100644 --- a/test-app/wcs/ftpm_stub.c +++ b/test-app/wcs/ftpm_stub.c @@ -50,9 +50,15 @@ static struct ftpm_tis_state ftpm_tis = { FTPM_STS_VALID | FTPM_STS_COMMAND_READY }; -static uint32_t ftpm_reg_offset(uint32_t addr) +static int ftpm_reg_offset(uint32_t addr, uint32_t *off) { - return (addr - FTPM_TIS_BASE) & 0x0FFFU; + if (off == NULL || addr < FTPM_TIS_BASE || + addr >= (FTPM_TIS_BASE + 0x1000U)) { + return BAD_FUNC_ARG; + } + + *off = addr - FTPM_TIS_BASE; + return TPM_RC_SUCCESS; } static void ftpm_store_le(uint8_t *buf, uint16_t size, uint32_t val) @@ -107,11 +113,14 @@ int TPM2_IoCb_FtpmNsc(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, (void)ctx; (void)userCtx; - if (buf == NULL || size == 0U || addr < FTPM_TIS_BASE) { + if (buf == NULL || size == 0U) { + return BAD_FUNC_ARG; + } + + if (ftpm_reg_offset(addr, &off) != TPM_RC_SUCCESS) { return BAD_FUNC_ARG; } - off = ftpm_reg_offset(addr); burst = FTPM_BURST_COUNT; if (isRead) { diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index 63b4334a14..c9a82b9d42 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -50,7 +50,7 @@ TESTS:=unit-parser unit-fdt unit-extflash unit-string unit-spi-flash unit-aes128 unit-enc-nvm-flagshome unit-delta unit-update-flash unit-update-flash-delta \ unit-update-flash-self-update \ unit-update-flash-enc unit-update-ram unit-update-ram-nofixed unit-pkcs11_store unit-psa_store unit-disk \ - unit-update-disk unit-multiboot unit-boot-x86-fsp unit-loader-tpm-init unit-qspi-flash unit-tpm-rsa-exp \ + unit-update-disk unit-multiboot unit-boot-x86-fsp unit-loader-tpm-init unit-qspi-flash unit-ftpm-stub unit-tpm-rsa-exp \ unit-image-nopart unit-image-sha384 unit-image-sha3-384 unit-store-sbrk \ unit-tpm-blob unit-policy-create unit-policy-sign unit-rot-auth unit-sdhci-response-bits \ unit-sdhci-disk-unaligned unit-sign-encrypted-output @@ -168,6 +168,11 @@ unit-tpm-check-rot-auth: ../../include/target.h unit-tpm-check-rot-auth.c ../../ -DWOLFBOOT_HASH_SHA256 \ -ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections +unit-ftpm-stub: ../../include/target.h unit-ftpm-stub.c + gcc -o $@ $^ $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFTPM) \ + -DWOLFTPM_USER_SETTINGS -ffunction-sections -fdata-sections \ + $(LDFLAGS) -Wl,--gc-sections + unit-tpm-blob: ../../include/target.h unit-tpm-blob.c gcc -o $@ $^ $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFTPM) -DWOLFBOOT_TPM \ -DWOLFTPM_USER_SETTINGS -DWOLFBOOT_TPM_SEAL -DWOLFBOOT_SIGN_RSA2048 \ diff --git a/tools/unit-tests/unit-ftpm-stub.c b/tools/unit-tests/unit-ftpm-stub.c new file mode 100644 index 0000000000..bd46bf3c39 --- /dev/null +++ b/tools/unit-tests/unit-ftpm-stub.c @@ -0,0 +1,83 @@ +/* unit-ftpm-stub.c + * + * Unit tests for the fTPM non-secure TIS callback shim. + */ + +#include +#include + +#define WOLFBOOT_TZ_FTPM + +int wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, uint8_t *rsp, + uint32_t *rspSz) +{ + (void)cmd; + (void)cmdSz; + (void)rsp; + (void)rspSz; + return -1; +} + +#include "../../test-app/wcs/ftpm_stub.c" + +START_TEST(ftpm_tis_rejects_address_below_window) +{ + BYTE buf[4] = {0}; + + ck_assert_int_eq(TPM2_IoCb_FtpmNsc(NULL, 1, FTPM_TIS_BASE - 1U, + buf, sizeof(buf), NULL), BAD_FUNC_ARG); +} +END_TEST + +START_TEST(ftpm_tis_rejects_address_above_window) +{ + BYTE buf[4] = {0}; + + ck_assert_int_eq(TPM2_IoCb_FtpmNsc(NULL, 1, FTPM_TIS_BASE + 0x1000U, + buf, sizeof(buf), NULL), BAD_FUNC_ARG); +} +END_TEST + +START_TEST(ftpm_tis_accepts_valid_window_register) +{ + BYTE buf[4] = {0}; + + ck_assert_int_eq(TPM2_IoCb_FtpmNsc(NULL, 1, + FTPM_TIS_BASE + FTPM_TIS_DID_VID, buf, sizeof(buf), NULL), + TPM_RC_SUCCESS); + ck_assert_uint_eq(buf[0], 0x4EU); + ck_assert_uint_eq(buf[1], 0x1BU); + ck_assert_uint_eq(buf[2], 0x01U); + ck_assert_uint_eq(buf[3], 0x00U); +} +END_TEST + +static Suite *ftpm_stub_suite(void) +{ + Suite *s; + TCase *tc; + + s = suite_create("ftpm_stub"); + tc = tcase_create("tis_window"); + tcase_add_test(tc, ftpm_tis_rejects_address_below_window); + tcase_add_test(tc, ftpm_tis_rejects_address_above_window); + tcase_add_test(tc, ftpm_tis_accepts_valid_window_register); + suite_add_tcase(s, tc); + + return s; +} + +int main(void) +{ + int fails; + Suite *s; + SRunner *sr; + + s = ftpm_stub_suite(); + sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + fails = srunner_ntests_failed(sr); + srunner_free(sr); + + return fails == 0 ? 0 : 1; +} From cffa75d4a4a54ccf1121c69d48cabc59545ce012 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 22 Apr 2026 14:14:28 +0200 Subject: [PATCH 4/5] Proper interface renaming + documentation --- .gitignore | 1 + ...tz-ftpm.config => stm32h5-tz-fwtpm.config} | 2 +- docs/fwTPM.md | 100 ++++++++ include/user_settings.h | 4 +- include/wolfboot/wcs_ftpm.h | 27 --- include/wolfboot/wcs_fwtpm.h | 27 +++ options.mk | 14 +- src/{ftpm_callable.c => fwtpm_callable.c} | 74 +++--- src/loader.c | 2 +- src/wc_callable.c | 8 +- test-app/Makefile | 10 +- test-app/app_stm32h5.c | 77 ++++--- test-app/wcs/ftpm_stub.c | 217 ------------------ test-app/wcs/fwtpm_stub.c | 217 ++++++++++++++++++ test-app/wcs/user_settings.h | 2 +- tools/config.mk | 4 +- tools/unit-tests/Makefile | 4 +- tools/unit-tests/unit-ftpm-stub.c | 83 ------- tools/unit-tests/unit-fwtpm-stub.c | 83 +++++++ 19 files changed, 529 insertions(+), 427 deletions(-) rename config/examples/{stm32h5-tz-ftpm.config => stm32h5-tz-fwtpm.config} (96%) create mode 100644 docs/fwTPM.md delete mode 100644 include/wolfboot/wcs_ftpm.h create mode 100644 include/wolfboot/wcs_fwtpm.h rename src/{ftpm_callable.c => fwtpm_callable.c} (55%) delete mode 100644 test-app/wcs/ftpm_stub.c create mode 100644 test-app/wcs/fwtpm_stub.c delete mode 100644 tools/unit-tests/unit-ftpm-stub.c create mode 100644 tools/unit-tests/unit-fwtpm-stub.c diff --git a/.gitignore b/.gitignore index 71dcbc5cba..77ef20818e 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/config/examples/stm32h5-tz-ftpm.config b/config/examples/stm32h5-tz-fwtpm.config similarity index 96% rename from config/examples/stm32h5-tz-ftpm.config rename to config/examples/stm32h5-tz-fwtpm.config index 21d10f9586..7cb45acf38 100644 --- a/config/examples/stm32h5-tz-ftpm.config +++ b/config/examples/stm32h5-tz-fwtpm.config @@ -30,6 +30,6 @@ WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x0C1A0000 FLAGS_HOME=0 DISABLE_BACKUP=0 WOLFCRYPT_TZ=1 -WOLFCRYPT_TZ_FTPM=1 +WOLFCRYPT_TZ_FWTPM=1 IMAGE_HEADER_SIZE?=1024 ARMORED=1 diff --git a/docs/fwTPM.md b/docs/fwTPM.md new file mode 100644 index 0000000000..69758e65a8 --- /dev/null +++ b/docs/fwTPM.md @@ -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. diff --git a/include/user_settings.h b/include/user_settings.h index a8735216b7..4c701be45d 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -434,7 +434,7 @@ extern int tolower(int c); # define NO_CODING #endif -#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FWTPM) /* Do not use heap */ #define WOLFTPM2_NO_HEAP /* small stack options */ @@ -632,7 +632,7 @@ extern int tolower(int c); #undef NO_KDF #endif -#if defined(WOLFBOOT_TZ_FTPM) +#if defined(WOLFBOOT_TZ_FWTPM) #undef NO_CMAC #undef NO_KDF #define WOLFSSL_AES_CFB diff --git a/include/wolfboot/wcs_ftpm.h b/include/wolfboot/wcs_ftpm.h deleted file mode 100644 index 1cd28f6551..0000000000 --- a/include/wolfboot/wcs_ftpm.h +++ /dev/null @@ -1,27 +0,0 @@ -/* wcs_ftpm.h - * - * Copyright (C) 2026 wolfSSL Inc. - * - * This file is part of wolfBoot. - */ - -#ifndef WOLFBOOT_WCS_FTPM_H -#define WOLFBOOT_WCS_FTPM_H - -#include -#include "wolfboot/wc_secure.h" - -#ifdef WOLFBOOT_TZ_FTPM - -#ifndef WCS_FTPM_MAX_COMMAND_SIZE -#define WCS_FTPM_MAX_COMMAND_SIZE 4096U -#endif - -int CSME_NSE_API wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, - uint8_t *rsp, uint32_t *rspSz); - -void wcs_ftpm_init(void); - -#endif /* WOLFBOOT_TZ_FTPM */ - -#endif /* WOLFBOOT_WCS_FTPM_H */ diff --git a/include/wolfboot/wcs_fwtpm.h b/include/wolfboot/wcs_fwtpm.h new file mode 100644 index 0000000000..9f75f047eb --- /dev/null +++ b/include/wolfboot/wcs_fwtpm.h @@ -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 +#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 */ diff --git a/options.mk b/options.mk index c8828aed47..24f6e32904 100644 --- a/options.mk +++ b/options.mk @@ -810,14 +810,14 @@ 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_FTPM),1) - $(error WOLFCRYPT_TZ_PKCS11 and WOLFCRYPT_TZ_FTPM are mutually exclusive) + 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_FTPM),1) - $(error WOLFCRYPT_TZ_PSA and WOLFCRYPT_TZ_FTPM are mutually exclusive) + ifeq ($(WOLFCRYPT_TZ_FWTPM),1) + $(error WOLFCRYPT_TZ_PSA and WOLFCRYPT_TZ_FWTPM are mutually exclusive) endif endif @@ -928,8 +928,8 @@ ifeq ($(WOLFCRYPT_TZ_PSA),1) endif endif -ifeq ($(WOLFCRYPT_TZ_FTPM),1) - CFLAGS+=-DWOLFBOOT_TZ_FTPM +ifeq ($(WOLFCRYPT_TZ_FWTPM),1) + CFLAGS+=-DWOLFBOOT_TZ_FWTPM CFLAGS+=-DWOLFCRYPT_SECURE_MODE CFLAGS+=-DWOLFTPM_FWTPM CFLAGS+=-DFWTPM_NO_NV @@ -945,7 +945,7 @@ ifeq ($(WOLFCRYPT_TZ_FTPM),1) LDFLAGS+=--specs=nano.specs endif WOLFCRYPT_OBJS+=src/store_sbrk.o - WOLFCRYPT_OBJS+=src/ftpm_callable.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 diff --git a/src/ftpm_callable.c b/src/fwtpm_callable.c similarity index 55% rename from src/ftpm_callable.c rename to src/fwtpm_callable.c index 94d9879376..0aa514bbcf 100644 --- a/src/ftpm_callable.c +++ b/src/fwtpm_callable.c @@ -1,24 +1,24 @@ -/* ftpm_callable.c +/* fwtpm_callable.c * * Copyright (C) 2026 wolfSSL Inc. * * This file is part of wolfBoot. */ -#ifdef WOLFBOOT_TZ_FTPM +#ifdef WOLFBOOT_TZ_FWTPM #include #include #include "store_sbrk.h" -#include "wolfboot/wcs_ftpm.h" +#include "wolfboot/wcs_fwtpm.h" #include "wolftpm/fwtpm/fwtpm.h" #include "wolftpm/fwtpm/fwtpm_command.h" #include "wolftpm/fwtpm/fwtpm_nv.h" #include "wolftpm/tpm2_types.h" -static FWTPM_CTX ftpm_ctx; -static int ftpm_ready; +static FWTPM_CTX fwtpm_ctx; +static int fwtpm_ready; extern unsigned int _start_heap; extern unsigned int _heap_size; @@ -31,15 +31,15 @@ void *_sbrk(unsigned int incr) } #ifndef FWTPM_NO_NV -#define WCS_FTPM_NV_SIZE (16U * 1024U) -static uint8_t ftpm_nv[WCS_FTPM_NV_SIZE]; +#define WCS_FWTPM_NV_SIZE (16U * 1024U) +static uint8_t fwtpm_nv[WCS_FWTPM_NV_SIZE]; -static int ftpm_nv_read(void *ctx, word32 offset, byte *buf, word32 size) +static int fwtpm_nv_read(void *ctx, word32 offset, byte *buf, word32 size) { uint8_t *nv = (uint8_t *)ctx; - if (nv == NULL || buf == NULL || offset > WCS_FTPM_NV_SIZE || - size > (WCS_FTPM_NV_SIZE - offset)) { + if (nv == NULL || buf == NULL || offset > WCS_FWTPM_NV_SIZE || + size > (WCS_FWTPM_NV_SIZE - offset)) { return BAD_FUNC_ARG; } @@ -47,13 +47,13 @@ static int ftpm_nv_read(void *ctx, word32 offset, byte *buf, word32 size) return TPM_RC_SUCCESS; } -static int ftpm_nv_write(void *ctx, word32 offset, const byte *buf, +static int fwtpm_nv_write(void *ctx, word32 offset, const byte *buf, word32 size) { uint8_t *nv = (uint8_t *)ctx; - if (nv == NULL || buf == NULL || offset > WCS_FTPM_NV_SIZE || - size > (WCS_FTPM_NV_SIZE - offset)) { + if (nv == NULL || buf == NULL || offset > WCS_FWTPM_NV_SIZE || + size > (WCS_FWTPM_NV_SIZE - offset)) { return BAD_FUNC_ARG; } @@ -61,12 +61,12 @@ static int ftpm_nv_write(void *ctx, word32 offset, const byte *buf, return TPM_RC_SUCCESS; } -static int ftpm_nv_erase(void *ctx, word32 offset, word32 size) +static int fwtpm_nv_erase(void *ctx, word32 offset, word32 size) { uint8_t *nv = (uint8_t *)ctx; - if (nv == NULL || offset > WCS_FTPM_NV_SIZE || - size > (WCS_FTPM_NV_SIZE - offset)) { + if (nv == NULL || offset > WCS_FWTPM_NV_SIZE || + size > (WCS_FWTPM_NV_SIZE - offset)) { return BAD_FUNC_ARG; } @@ -74,16 +74,16 @@ static int ftpm_nv_erase(void *ctx, word32 offset, word32 size) return TPM_RC_SUCCESS; } -static FWTPM_NV_HAL ftpm_nv_hal = { - ftpm_nv_read, - ftpm_nv_write, - ftpm_nv_erase, - ftpm_nv, - WCS_FTPM_NV_SIZE +static FWTPM_NV_HAL fwtpm_nv_hal = { + fwtpm_nv_read, + fwtpm_nv_write, + fwtpm_nv_erase, + fwtpm_nv, + WCS_FWTPM_NV_SIZE }; #endif /* !FWTPM_NO_NV */ -static uint32_t ftpm_rsp_size(const uint8_t *rsp, int rspLen) +static uint32_t fwtpm_rsp_size(const uint8_t *rsp, int rspLen) { if (rsp == NULL || rspLen < TPM2_HEADER_SIZE) { return 0; @@ -95,26 +95,26 @@ static uint32_t ftpm_rsp_size(const uint8_t *rsp, int rspLen) (uint32_t)rsp[5]; } -void wcs_ftpm_init(void) +void wcs_fwtpm_init(void) { int rc; #ifndef FWTPM_NO_NV - XMEMSET(ftpm_nv, 0xFF, sizeof(ftpm_nv)); + XMEMSET(fwtpm_nv, 0xFF, sizeof(fwtpm_nv)); #endif - XMEMSET(&ftpm_ctx, 0, sizeof(ftpm_ctx)); + XMEMSET(&fwtpm_ctx, 0, sizeof(fwtpm_ctx)); #ifndef FWTPM_NO_NV - (void)FWTPM_NV_SetHAL(&ftpm_ctx, &ftpm_nv_hal); + (void)FWTPM_NV_SetHAL(&fwtpm_ctx, &fwtpm_nv_hal); #endif - rc = FWTPM_Init(&ftpm_ctx); + rc = FWTPM_Init(&fwtpm_ctx); if (rc == 0) { - ftpm_ctx.wasStarted = 1; - ftpm_ready = 1; + fwtpm_ctx.wasStarted = 1; + fwtpm_ready = 1; } } -int CSME_NSE_API wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, +int CSME_NSE_API wcs_fwtpm_transmit(const uint8_t *cmd, uint32_t cmdSz, uint8_t *rsp, uint32_t *rspSz) { int rc; @@ -122,23 +122,23 @@ int CSME_NSE_API wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, uint32_t rspCapacity; uint32_t wireSz; - if (!ftpm_ready) { + if (!fwtpm_ready) { return TPM_RC_INITIALIZE; } if (cmd == NULL || rsp == NULL || rspSz == NULL || cmdSz == 0U || - cmdSz > WCS_FTPM_MAX_COMMAND_SIZE) { + cmdSz > WCS_FWTPM_MAX_COMMAND_SIZE) { return BAD_FUNC_ARG; } rspCapacity = *rspSz; - if (rspCapacity == 0U || rspCapacity > WCS_FTPM_MAX_COMMAND_SIZE) { + if (rspCapacity == 0U || rspCapacity > WCS_FWTPM_MAX_COMMAND_SIZE) { return BAD_FUNC_ARG; } rspLen = (int)rspCapacity; - rc = FWTPM_ProcessCommand(&ftpm_ctx, cmd, (int)cmdSz, rsp, &rspLen, 0); + rc = FWTPM_ProcessCommand(&fwtpm_ctx, cmd, (int)cmdSz, rsp, &rspLen, 0); if (rc == TPM_RC_SUCCESS) { - wireSz = ftpm_rsp_size(rsp, rspLen); + wireSz = fwtpm_rsp_size(rsp, rspLen); if (wireSz > 0U && wireSz <= rspCapacity) { *rspSz = wireSz; } @@ -152,4 +152,4 @@ int CSME_NSE_API wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, return rc; } -#endif /* WOLFBOOT_TZ_FTPM */ +#endif /* WOLFBOOT_TZ_FWTPM */ diff --git a/src/loader.c b/src/loader.c index 59527031de..3c26f4db42 100644 --- a/src/loader.c +++ b/src/loader.c @@ -123,7 +123,7 @@ int main(void) uart_init(UART_FLASH_BITRATE, 8, 'N', 1); uart_send_current_version(); #endif -#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FWTPM) if (wolfBoot_tpm2_init() != 0) { wolfBoot_panic(); } diff --git a/src/wc_callable.c b/src/wc_callable.c index f3159e8cd0..1dd9761232 100644 --- a/src/wc_callable.c +++ b/src/wc_callable.c @@ -30,8 +30,8 @@ #include "hal.h" #include -#ifdef WOLFBOOT_TZ_FTPM -#include "wolfboot/wcs_ftpm.h" +#ifdef WOLFBOOT_TZ_FWTPM +#include "wolfboot/wcs_fwtpm.h" #endif static WC_RNG wcs_rng; @@ -45,8 +45,8 @@ void wcs_Init(void) { hal_trng_init(); wc_InitRng(&wcs_rng); -#ifdef WOLFBOOT_TZ_FTPM - wcs_ftpm_init(); +#ifdef WOLFBOOT_TZ_FWTPM + wcs_fwtpm_init(); #endif } diff --git a/test-app/Makefile b/test-app/Makefile index 531bdd7fa8..f404e1c063 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -104,9 +104,9 @@ ifeq ($(WOLFCRYPT_TZ_PSA),1) WOLFCRYPT_TZ_PSA=1 endif -ifeq ($(WOLFCRYPT_TZ_FTPM),1) +ifeq ($(WOLFCRYPT_TZ_FWTPM),1) WOLFCRYPT_TZ=1 - WOLFCRYPT_TZ_FTPM=1 + WOLFCRYPT_TZ_FWTPM=1 endif # Setup default linker flags @@ -334,12 +334,12 @@ ifeq ($(TZEN),1) $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/psa/psa_hash.o \ $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/psa/psa_pkcbs.o endif - ifeq ($(WOLFCRYPT_TZ_FTPM),1) + ifeq ($(WOLFCRYPT_TZ_FWTPM),1) CFLAGS:=$(filter-out -DWOLFTPM_FWTPM,$(CFLAGS)) - CFLAGS+=-DWOLFBOOT_TZ_FTPM -DWOLFBOOT_TPM -DWOLFTPM_ADV_IO + CFLAGS+=-DWOLFBOOT_TZ_FWTPM -DWOLFBOOT_TPM -DWOLFTPM_ADV_IO CFLAGS+=-DWOLFTPM_EXAMPLE_HAL CFLAGS+=-I"$(WOLFBOOT_LIB_WOLFTPM)" - APP_OBJS+=./wcs/ftpm_stub.o + APP_OBJS+=./wcs/fwtpm_stub.o WOLFTPM_APP_OBJS+=\ $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2.o \ $(WOLFBOOT_LIB_WOLFTPM)/src/tpm2_packet.o \ diff --git a/test-app/app_stm32h5.c b/test-app/app_stm32h5.c index f8f1351172..660718aa4a 100644 --- a/test-app/app_stm32h5.c +++ b/test-app/app_stm32h5.c @@ -36,11 +36,11 @@ #endif #include "target.h" -#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FWTPM) #include "tpm.h" #endif -#ifdef WOLFBOOT_TZ_FTPM +#ifdef WOLFBOOT_TZ_FWTPM #include "wolftpm/tpm2_wrap.h" #include "wolfssl/wolfcrypt/sha256.h" #endif @@ -206,7 +206,7 @@ static int cmd_timestamp(const char *args); static int cmd_update(const char *args); static int cmd_update_xmodem(const char *args); static int cmd_reboot(const char *args); -#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FWTPM) static int cmd_tpm_info(const char *args); #ifdef WOLFTPM_MFG_IDENTITY static int cmd_tpm_idevid(const char *args); @@ -215,8 +215,8 @@ static int cmd_tpm_signed_timestamp(const char *args); static int cmd_tpm_quote(const char *args); #endif #endif -#ifdef WOLFBOOT_TZ_FTPM -static int cmd_ftpm_test(const char *args); +#ifdef WOLFBOOT_TZ_FWTPM +static int cmd_fwtpm_test(const char *args); #endif @@ -246,7 +246,7 @@ struct console_command COMMANDS[] = {cmd_test, "test", "run the wolfCrypt test"}, {cmd_update_xmodem, "update", "update the firmware via XMODEM"}, {cmd_reboot, "reboot", "reboot the system"}, -#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FWTPM) {cmd_tpm_info, "tpm", "get TPM capabilities"}, #ifdef WOLFTPM_MFG_IDENTITY {cmd_tpm_idevid, "idevid", "show Initial Device Identification (IDevID) certificate"}, @@ -255,8 +255,8 @@ struct console_command COMMANDS[] = {cmd_tpm_quote, "quote", "TPM IAK signed PCR(s) attestation report"}, #endif #endif -#ifdef WOLFBOOT_TZ_FTPM - {cmd_ftpm_test, "ftpm", "run fTPM tests through the secure NSC interface"}, +#ifdef WOLFBOOT_TZ_FWTPM + {cmd_fwtpm_test, "fwtpm", "run fwTPM tests through the secure NSC interface"}, #endif {NULL, "", ""} }; @@ -863,7 +863,7 @@ static int cmd_test(const char *args) return 0; } -#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FWTPM) #include #include @@ -1130,13 +1130,13 @@ static int cmd_tpm_quote(const char *args) return rc; } #endif /* WOLFTPM_MFG_IDENTITY */ -#endif /* WOLFBOOT_TPM && !WOLFBOOT_TZ_FTPM */ +#endif /* WOLFBOOT_TPM && !WOLFBOOT_TZ_FWTPM */ -#ifdef WOLFBOOT_TZ_FTPM -extern int TPM2_IoCb_FtpmNsc(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, +#ifdef WOLFBOOT_TZ_FWTPM +extern int TPM2_IoCb_FwtpmNsc(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, BYTE *buf, UINT16 size, void *userCtx); -static int ftpm_expected_pcr_after_extend(const uint8_t *before, +static int fwtpm_expected_pcr_after_extend(const uint8_t *before, const uint8_t *event, uint8_t *expected) { wc_Sha256 sha; @@ -1157,9 +1157,9 @@ static int ftpm_expected_pcr_after_extend(const uint8_t *before, return rc; } -static int ftpm_seal_unseal_pcr_secret(WOLFTPM2_DEV *dev) +static int fwtpm_seal_unseal_pcr_secret(WOLFTPM2_DEV *dev) { - static const uint8_t secret[] = "wolfBoot fTPM PCR secret"; + static const uint8_t secret[] = "wolfBoot fwTPM PCR secret"; uint8_t pcrArray[1] = { 0 }; uint8_t policyDigest[TPM_MAX_DIGEST_SIZE]; word32 policyDigestSz = sizeof(policyDigest); @@ -1182,7 +1182,7 @@ static int ftpm_seal_unseal_pcr_secret(WOLFTPM2_DEV *dev) rc = wolfTPM2_CreateSRK(dev, &storage, TPM_ALG_ECC, NULL, 0); if (rc != TPM_RC_SUCCESS) { - printf("fTPM seal SRK failed: 0x%x\r\n", rc); + printf("fwTPM seal SRK failed: 0x%x\r\n", rc); return rc; } @@ -1198,7 +1198,7 @@ static int ftpm_seal_unseal_pcr_secret(WOLFTPM2_DEV *dev) } wolfTPM2_UnloadHandle(dev, &trialSession.handle); if (rc != TPM_RC_SUCCESS) { - printf("fTPM seal policy failed: 0x%x\r\n", rc); + printf("fwTPM seal policy failed: 0x%x\r\n", rc); wolfTPM2_UnloadHandle(dev, &storage.handle); return rc; } @@ -1237,22 +1237,22 @@ static int ftpm_seal_unseal_pcr_secret(WOLFTPM2_DEV *dev) wolfTPM2_UnloadHandle(dev, &storage.handle); if (rc != TPM_RC_SUCCESS) { - printf("fTPM unseal failed: 0x%x\r\n", rc); + printf("fwTPM unseal failed: 0x%x\r\n", rc); return rc; } if (unsealOut.outData.size != sizeof(secret) || XMEMCMP(unsealOut.outData.buffer, secret, sizeof(secret)) != 0) { - printf("fTPM unsealed secret mismatch\r\n"); + printf("fwTPM unsealed secret mismatch\r\n"); return TPM_RC_FAILURE; } - printf("fTPM unsealed secret: %.*s\r\n", + printf("fwTPM unsealed secret: %.*s\r\n", unsealOut.outData.size, unsealOut.outData.buffer); return TPM_RC_SUCCESS; } -static int cmd_ftpm_test(const char *args) +static int cmd_fwtpm_test(const char *args) { int rc; WOLFTPM2_DEV dev; @@ -1274,26 +1274,26 @@ static int cmd_ftpm_test(const char *args) XMEMSET(pcrEvent, 0, sizeof(pcrEvent)); XMEMSET(pcrExpected, 0, sizeof(pcrExpected)); - rc = wolfTPM2_Init(&dev, TPM2_IoCb_FtpmNsc, NULL); + rc = wolfTPM2_Init(&dev, TPM2_IoCb_FwtpmNsc, NULL); if (rc != TPM_RC_SUCCESS) { - printf("fTPM init failed: 0x%x\r\n", rc); + printf("fwTPM init failed: 0x%x\r\n", rc); return rc; } rc = wolfTPM2_GetCapabilities(&dev, &caps); if (rc == TPM_RC_SUCCESS) { - printf("fTPM caps: mfg %s vendor %s fw %u.%u\r\n", + printf("fwTPM caps: mfg %s vendor %s fw %u.%u\r\n", caps.mfgStr, caps.vendorStr, caps.fwVerMajor, caps.fwVerMinor); } if (rc == TPM_RC_SUCCESS) { int randRc = wolfTPM2_GetRandom(&dev, rnd, sizeof(rnd)); if (randRc == TPM_RC_SUCCESS) { - printf("fTPM random:"); + printf("fwTPM random:"); print_hex(rnd, sizeof(rnd), 0); } else { - printf("fTPM random unavailable: 0x%x\r\n", randRc); + printf("fwTPM random unavailable: 0x%x\r\n", randRc); } } @@ -1306,11 +1306,12 @@ static int cmd_ftpm_test(const char *args) } if (rc == TPM_RC_SUCCESS) { - rc = wc_Sha256Hash((const uint8_t *)"wolfBoot fTPM PCR event", - 23, pcrEvent); + static const uint8_t pcrEventName[] = "wolfBoot fwTPM PCR event"; + rc = wc_Sha256Hash(pcrEventName, sizeof(pcrEventName) - 1U, + pcrEvent); } if (rc == TPM_RC_SUCCESS) { - rc = ftpm_expected_pcr_after_extend(pcrBefore, pcrEvent, pcrExpected); + rc = fwtpm_expected_pcr_after_extend(pcrBefore, pcrEvent, pcrExpected); } if (rc == TPM_RC_SUCCESS) { rc = wolfTPM2_ExtendPCR(&dev, 0, TPM_ALG_SHA256, pcrEvent, @@ -1320,31 +1321,31 @@ static int cmd_ftpm_test(const char *args) pcrSz = sizeof(pcr); rc = wolfTPM2_ReadPCR(&dev, 0, TPM_ALG_SHA256, pcr, &pcrSz); if (rc == TPM_RC_SUCCESS) { - printf("fTPM PCR0 extended:"); + printf("fwTPM PCR0 extended:"); print_hex(pcr, (uint32_t)pcrSz, 0); } } if (rc == TPM_RC_SUCCESS && (pcrSz != (int)sizeof(pcrExpected) || XMEMCMP(pcr, pcrExpected, sizeof(pcrExpected)) != 0)) { - printf("fTPM PCR0 extend mismatch\r\n"); + printf("fwTPM PCR0 extend mismatch\r\n"); rc = TPM_RC_FAILURE; } if (rc == TPM_RC_SUCCESS) { - rc = ftpm_seal_unseal_pcr_secret(&dev); + rc = fwtpm_seal_unseal_pcr_secret(&dev); } wolfTPM2_Cleanup(&dev); if (rc == TPM_RC_SUCCESS) { - printf("fTPM NSC tests passed\r\n"); + printf("fwTPM NSC tests passed\r\n"); } else { - printf("fTPM NSC tests failed: 0x%x\r\n", rc); + printf("fwTPM NSC tests failed: 0x%x\r\n", rc); } return rc; } -#endif /* WOLFBOOT_TZ_FTPM */ +#endif /* WOLFBOOT_TZ_FWTPM */ static int parse_cmd(const char *cmd) @@ -1493,11 +1494,11 @@ void main(void) #endif cmd_info(NULL); -#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FTPM) +#if defined(WOLFBOOT_TPM) && !defined(WOLFBOOT_TZ_FWTPM) cmd_tpm_info(NULL); #endif -#ifdef WOLFBOOT_TZ_FTPM - ret = cmd_ftpm_test(NULL); +#ifdef WOLFBOOT_TZ_FWTPM + ret = cmd_fwtpm_test(NULL); if (ret == 0) asm volatile ("bkpt #0x7f"); else diff --git a/test-app/wcs/ftpm_stub.c b/test-app/wcs/ftpm_stub.c deleted file mode 100644 index 9df3de3217..0000000000 --- a/test-app/wcs/ftpm_stub.c +++ /dev/null @@ -1,217 +0,0 @@ -/* ftpm_stub.c - * - * Copyright (C) 2026 wolfSSL Inc. - * - * This file is part of wolfBoot. - */ - -#ifdef WOLFBOOT_TZ_FTPM - -#include -#include - -#include "wolfboot/wcs_ftpm.h" -#include "wolftpm/tpm2.h" -#include "wolftpm/tpm2_tis.h" - -#define FTPM_TIS_BASE 0xD40000U -#define FTPM_TIS_ACCESS 0x0000U -#define FTPM_TIS_INTF_CAPS 0x0014U -#define FTPM_TIS_STS 0x0018U -#define FTPM_TIS_BURST_COUNT 0x0019U -#define FTPM_TIS_DATA_FIFO 0x0024U -#define FTPM_TIS_DID_VID 0x0F00U -#define FTPM_TIS_RID 0x0F04U - -#define FTPM_ACCESS_VALID 0x80U -#define FTPM_ACCESS_ACTIVE_LOCALITY 0x20U -#define FTPM_ACCESS_REQUEST_USE 0x02U - -#define FTPM_STS_VALID 0x80U -#define FTPM_STS_COMMAND_READY 0x40U -#define FTPM_STS_GO 0x20U -#define FTPM_STS_DATA_AVAIL 0x10U -#define FTPM_STS_DATA_EXPECT 0x08U - -#define FTPM_BURST_COUNT 64U - -struct ftpm_tis_state { - uint8_t cmd[WCS_FTPM_MAX_COMMAND_SIZE]; - uint8_t rsp[WCS_FTPM_MAX_COMMAND_SIZE]; - uint32_t cmdSz; - uint32_t rspSz; - uint32_t rspPos; - uint8_t locality; - uint8_t status; -}; - -static struct ftpm_tis_state ftpm_tis = { - {0}, {0}, 0, 0, 0, 0, - FTPM_STS_VALID | FTPM_STS_COMMAND_READY -}; - -static int ftpm_reg_offset(uint32_t addr, uint32_t *off) -{ - if (off == NULL || addr < FTPM_TIS_BASE || - addr >= (FTPM_TIS_BASE + 0x1000U)) { - return BAD_FUNC_ARG; - } - - *off = addr - FTPM_TIS_BASE; - return TPM_RC_SUCCESS; -} - -static void ftpm_store_le(uint8_t *buf, uint16_t size, uint32_t val) -{ - uint16_t i; - - for (i = 0; i < size; i++) { - buf[i] = (uint8_t)(val >> (8U * i)); - } -} - -static uint32_t ftpm_cmd_size(void) -{ - if (ftpm_tis.cmdSz < TPM2_HEADER_SIZE) { - return TPM2_HEADER_SIZE; - } - - return ((uint32_t)ftpm_tis.cmd[2] << 24) | - ((uint32_t)ftpm_tis.cmd[3] << 16) | - ((uint32_t)ftpm_tis.cmd[4] << 8) | - (uint32_t)ftpm_tis.cmd[5]; -} - -static int ftpm_execute(void) -{ - int rc; - - ftpm_tis.rspSz = sizeof(ftpm_tis.rsp); - ftpm_tis.rspPos = 0; - - rc = wcs_ftpm_transmit(ftpm_tis.cmd, ftpm_tis.cmdSz, ftpm_tis.rsp, - &ftpm_tis.rspSz); - ftpm_tis.cmdSz = 0; - - if (rc == TPM_RC_SUCCESS) { - ftpm_tis.status = FTPM_STS_VALID | FTPM_STS_DATA_AVAIL; - } - else { - ftpm_tis.rspSz = 0; - ftpm_tis.status = FTPM_STS_VALID | FTPM_STS_COMMAND_READY; - } - - return rc; -} - -int TPM2_IoCb_FtpmNsc(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, - BYTE *buf, UINT16 size, void *userCtx) -{ - uint32_t off; - uint16_t burst; - - (void)ctx; - (void)userCtx; - - if (buf == NULL || size == 0U) { - return BAD_FUNC_ARG; - } - - if (ftpm_reg_offset(addr, &off) != TPM_RC_SUCCESS) { - return BAD_FUNC_ARG; - } - - burst = FTPM_BURST_COUNT; - - if (isRead) { - switch (off) { - case FTPM_TIS_ACCESS: - buf[0] = FTPM_ACCESS_VALID | FTPM_ACCESS_ACTIVE_LOCALITY; - break; - case FTPM_TIS_STS: - XMEMSET(buf, 0, size); - buf[0] = ftpm_tis.status; - if (size > 1U) { - buf[1] = (uint8_t)burst; - } - if (size > 2U) { - buf[2] = (uint8_t)(burst >> 8); - } - break; - case FTPM_TIS_BURST_COUNT: - ftpm_store_le(buf, size, burst); - break; - case FTPM_TIS_BURST_COUNT + 1U: - ftpm_store_le(buf, size, burst >> 8); - break; - case FTPM_TIS_DATA_FIFO: - if (ftpm_tis.rspPos + size > ftpm_tis.rspSz) { - return TPM_RC_FAILURE; - } - XMEMCPY(buf, ftpm_tis.rsp + ftpm_tis.rspPos, size); - ftpm_tis.rspPos += size; - if (ftpm_tis.rspPos >= ftpm_tis.rspSz) { - ftpm_tis.status = FTPM_STS_VALID | FTPM_STS_COMMAND_READY; - } - break; - case FTPM_TIS_INTF_CAPS: - ftpm_store_le(buf, size, 0x00000183U); - break; - case FTPM_TIS_DID_VID: - ftpm_store_le(buf, size, 0x00011B4EU); - break; - case FTPM_TIS_RID: - buf[0] = 0x01U; - break; - default: - XMEMSET(buf, 0, size); - break; - } - } - else { - switch (off) { - case FTPM_TIS_ACCESS: - if ((buf[0] & FTPM_ACCESS_REQUEST_USE) != 0U) { - ftpm_tis.locality = 0; - } - break; - case FTPM_TIS_STS: - if ((buf[0] & FTPM_STS_COMMAND_READY) != 0U) { - ftpm_tis.cmdSz = 0; - ftpm_tis.rspSz = 0; - ftpm_tis.rspPos = 0; - ftpm_tis.status = FTPM_STS_VALID | - FTPM_STS_COMMAND_READY; - } - else if ((buf[0] & FTPM_STS_GO) != 0U) { - return ftpm_execute(); - } - break; - case FTPM_TIS_DATA_FIFO: - if (ftpm_tis.cmdSz + size > sizeof(ftpm_tis.cmd)) { - return TPM_RC_FAILURE; - } - XMEMCPY(ftpm_tis.cmd + ftpm_tis.cmdSz, buf, size); - ftpm_tis.cmdSz += size; - if (ftpm_tis.cmdSz < ftpm_cmd_size()) { - ftpm_tis.status = FTPM_STS_VALID | FTPM_STS_DATA_EXPECT; - } - else { - ftpm_tis.status = FTPM_STS_VALID; - } - break; - default: - break; - } - } - - return TPM_RC_SUCCESS; -} - -int TPM2_IoCb(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, BYTE *buf, - UINT16 size, void *userCtx) -{ - return TPM2_IoCb_FtpmNsc(ctx, isRead, addr, buf, size, userCtx); -} - -#endif /* WOLFBOOT_TZ_FTPM */ diff --git a/test-app/wcs/fwtpm_stub.c b/test-app/wcs/fwtpm_stub.c new file mode 100644 index 0000000000..aa8b6d62eb --- /dev/null +++ b/test-app/wcs/fwtpm_stub.c @@ -0,0 +1,217 @@ +/* fwtpm_stub.c + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + */ + +#ifdef WOLFBOOT_TZ_FWTPM + +#include +#include + +#include "wolfboot/wcs_fwtpm.h" +#include "wolftpm/tpm2.h" +#include "wolftpm/tpm2_tis.h" + +#define FWTPM_TIS_BASE 0xD40000U +#define FWTPM_TIS_ACCESS 0x0000U +#define FWTPM_TIS_INTF_CAPS 0x0014U +#define FWTPM_TIS_STS 0x0018U +#define FWTPM_TIS_BURST_COUNT 0x0019U +#define FWTPM_TIS_DATA_FIFO 0x0024U +#define FWTPM_TIS_DID_VID 0x0F00U +#define FWTPM_TIS_RID 0x0F04U + +#define FWTPM_ACCESS_VALID 0x80U +#define FWTPM_ACCESS_ACTIVE_LOCALITY 0x20U +#define FWTPM_ACCESS_REQUEST_USE 0x02U + +#define FWTPM_STS_VALID 0x80U +#define FWTPM_STS_COMMAND_READY 0x40U +#define FWTPM_STS_GO 0x20U +#define FWTPM_STS_DATA_AVAIL 0x10U +#define FWTPM_STS_DATA_EXPECT 0x08U + +#define FWTPM_BURST_COUNT 64U + +struct fwtpm_tis_state { + uint8_t cmd[WCS_FWTPM_MAX_COMMAND_SIZE]; + uint8_t rsp[WCS_FWTPM_MAX_COMMAND_SIZE]; + uint32_t cmdSz; + uint32_t rspSz; + uint32_t rspPos; + uint8_t locality; + uint8_t status; +}; + +static struct fwtpm_tis_state fwtpm_tis = { + {0}, {0}, 0, 0, 0, 0, + FWTPM_STS_VALID | FWTPM_STS_COMMAND_READY +}; + +static int fwtpm_reg_offset(uint32_t addr, uint32_t *off) +{ + if (off == NULL || addr < FWTPM_TIS_BASE || + addr >= (FWTPM_TIS_BASE + 0x1000U)) { + return BAD_FUNC_ARG; + } + + *off = addr - FWTPM_TIS_BASE; + return TPM_RC_SUCCESS; +} + +static void fwtpm_store_le(uint8_t *buf, uint16_t size, uint32_t val) +{ + uint16_t i; + + for (i = 0; i < size; i++) { + buf[i] = (uint8_t)(val >> (8U * i)); + } +} + +static uint32_t fwtpm_cmd_size(void) +{ + if (fwtpm_tis.cmdSz < TPM2_HEADER_SIZE) { + return TPM2_HEADER_SIZE; + } + + return ((uint32_t)fwtpm_tis.cmd[2] << 24) | + ((uint32_t)fwtpm_tis.cmd[3] << 16) | + ((uint32_t)fwtpm_tis.cmd[4] << 8) | + (uint32_t)fwtpm_tis.cmd[5]; +} + +static int fwtpm_execute(void) +{ + int rc; + + fwtpm_tis.rspSz = sizeof(fwtpm_tis.rsp); + fwtpm_tis.rspPos = 0; + + rc = wcs_fwtpm_transmit(fwtpm_tis.cmd, fwtpm_tis.cmdSz, fwtpm_tis.rsp, + &fwtpm_tis.rspSz); + fwtpm_tis.cmdSz = 0; + + if (rc == TPM_RC_SUCCESS) { + fwtpm_tis.status = FWTPM_STS_VALID | FWTPM_STS_DATA_AVAIL; + } + else { + fwtpm_tis.rspSz = 0; + fwtpm_tis.status = FWTPM_STS_VALID | FWTPM_STS_COMMAND_READY; + } + + return rc; +} + +int TPM2_IoCb_FwtpmNsc(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, + BYTE *buf, UINT16 size, void *userCtx) +{ + uint32_t off; + uint16_t burst; + + (void)ctx; + (void)userCtx; + + if (buf == NULL || size == 0U) { + return BAD_FUNC_ARG; + } + + if (fwtpm_reg_offset(addr, &off) != TPM_RC_SUCCESS) { + return BAD_FUNC_ARG; + } + + burst = FWTPM_BURST_COUNT; + + if (isRead) { + switch (off) { + case FWTPM_TIS_ACCESS: + buf[0] = FWTPM_ACCESS_VALID | FWTPM_ACCESS_ACTIVE_LOCALITY; + break; + case FWTPM_TIS_STS: + XMEMSET(buf, 0, size); + buf[0] = fwtpm_tis.status; + if (size > 1U) { + buf[1] = (uint8_t)burst; + } + if (size > 2U) { + buf[2] = (uint8_t)(burst >> 8); + } + break; + case FWTPM_TIS_BURST_COUNT: + fwtpm_store_le(buf, size, burst); + break; + case FWTPM_TIS_BURST_COUNT + 1U: + fwtpm_store_le(buf, size, burst >> 8); + break; + case FWTPM_TIS_DATA_FIFO: + if (fwtpm_tis.rspPos + size > fwtpm_tis.rspSz) { + return TPM_RC_FAILURE; + } + XMEMCPY(buf, fwtpm_tis.rsp + fwtpm_tis.rspPos, size); + fwtpm_tis.rspPos += size; + if (fwtpm_tis.rspPos >= fwtpm_tis.rspSz) { + fwtpm_tis.status = FWTPM_STS_VALID | FWTPM_STS_COMMAND_READY; + } + break; + case FWTPM_TIS_INTF_CAPS: + fwtpm_store_le(buf, size, 0x00000183U); + break; + case FWTPM_TIS_DID_VID: + fwtpm_store_le(buf, size, 0x00011B4EU); + break; + case FWTPM_TIS_RID: + buf[0] = 0x01U; + break; + default: + XMEMSET(buf, 0, size); + break; + } + } + else { + switch (off) { + case FWTPM_TIS_ACCESS: + if ((buf[0] & FWTPM_ACCESS_REQUEST_USE) != 0U) { + fwtpm_tis.locality = 0; + } + break; + case FWTPM_TIS_STS: + if ((buf[0] & FWTPM_STS_COMMAND_READY) != 0U) { + fwtpm_tis.cmdSz = 0; + fwtpm_tis.rspSz = 0; + fwtpm_tis.rspPos = 0; + fwtpm_tis.status = FWTPM_STS_VALID | + FWTPM_STS_COMMAND_READY; + } + else if ((buf[0] & FWTPM_STS_GO) != 0U) { + return fwtpm_execute(); + } + break; + case FWTPM_TIS_DATA_FIFO: + if (fwtpm_tis.cmdSz + size > sizeof(fwtpm_tis.cmd)) { + return TPM_RC_FAILURE; + } + XMEMCPY(fwtpm_tis.cmd + fwtpm_tis.cmdSz, buf, size); + fwtpm_tis.cmdSz += size; + if (fwtpm_tis.cmdSz < fwtpm_cmd_size()) { + fwtpm_tis.status = FWTPM_STS_VALID | FWTPM_STS_DATA_EXPECT; + } + else { + fwtpm_tis.status = FWTPM_STS_VALID; + } + break; + default: + break; + } + } + + return TPM_RC_SUCCESS; +} + +int TPM2_IoCb(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, BYTE *buf, + UINT16 size, void *userCtx) +{ + return TPM2_IoCb_FwtpmNsc(ctx, isRead, addr, buf, size, userCtx); +} + +#endif /* WOLFBOOT_TZ_FWTPM */ diff --git a/test-app/wcs/user_settings.h b/test-app/wcs/user_settings.h index 20e431503c..1f71ff86a8 100644 --- a/test-app/wcs/user_settings.h +++ b/test-app/wcs/user_settings.h @@ -156,7 +156,7 @@ extern int tolower(int c); #define HAVE_PKCS8 #define HAVE_PKCS12 -#if defined(SECURE_PKCS11) || defined(WOLFBOOT_TZ_FTPM) +#if defined(SECURE_PKCS11) || defined(WOLFBOOT_TZ_FWTPM) static inline int wcs_cmse_get_random(unsigned char* output, int sz) { diff --git a/tools/config.mk b/tools/config.mk index 3aae0835fe..4ef65ca06b 100644 --- a/tools/config.mk +++ b/tools/config.mk @@ -66,7 +66,7 @@ ifeq ($(ARCH),) WOLFCRYPT_TZ?=0 WOLFCRYPT_TZ_PKCS11?=0 WOLFCRYPT_TZ_PSA?=0 - WOLFCRYPT_TZ_FTPM?=0 + WOLFCRYPT_TZ_FWTPM?=0 WOLFBOOT_PARTITION_SIZE?=0x20000 WOLFBOOT_SECTOR_SIZE?=0x20000 WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08020000 @@ -105,7 +105,7 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO WOLFBOOT_UDS_OBKEYS \ WOLFCRYPT_TZ WOLFCRYPT_TZ_PKCS11 \ WOLFCRYPT_TZ_PSA \ - WOLFCRYPT_TZ_FTPM \ + WOLFCRYPT_TZ_FWTPM \ WOLFBOOT_PARTITION_SIZE WOLFBOOT_SECTOR_SIZE \ WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \ WOLFBOOT_PARTITION_SWAP_ADDRESS WOLFBOOT_LOAD_ADDRESS \ diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index c9a82b9d42..24b7ccab03 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -50,7 +50,7 @@ TESTS:=unit-parser unit-fdt unit-extflash unit-string unit-spi-flash unit-aes128 unit-enc-nvm-flagshome unit-delta unit-update-flash unit-update-flash-delta \ unit-update-flash-self-update \ unit-update-flash-enc unit-update-ram unit-update-ram-nofixed unit-pkcs11_store unit-psa_store unit-disk \ - unit-update-disk unit-multiboot unit-boot-x86-fsp unit-loader-tpm-init unit-qspi-flash unit-ftpm-stub unit-tpm-rsa-exp \ + unit-update-disk unit-multiboot unit-boot-x86-fsp unit-loader-tpm-init unit-qspi-flash unit-fwtpm-stub unit-tpm-rsa-exp \ unit-image-nopart unit-image-sha384 unit-image-sha3-384 unit-store-sbrk \ unit-tpm-blob unit-policy-create unit-policy-sign unit-rot-auth unit-sdhci-response-bits \ unit-sdhci-disk-unaligned unit-sign-encrypted-output @@ -168,7 +168,7 @@ unit-tpm-check-rot-auth: ../../include/target.h unit-tpm-check-rot-auth.c ../../ -DWOLFBOOT_HASH_SHA256 \ -ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections -unit-ftpm-stub: ../../include/target.h unit-ftpm-stub.c +unit-fwtpm-stub: ../../include/target.h unit-fwtpm-stub.c gcc -o $@ $^ $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFTPM) \ -DWOLFTPM_USER_SETTINGS -ffunction-sections -fdata-sections \ $(LDFLAGS) -Wl,--gc-sections diff --git a/tools/unit-tests/unit-ftpm-stub.c b/tools/unit-tests/unit-ftpm-stub.c deleted file mode 100644 index bd46bf3c39..0000000000 --- a/tools/unit-tests/unit-ftpm-stub.c +++ /dev/null @@ -1,83 +0,0 @@ -/* unit-ftpm-stub.c - * - * Unit tests for the fTPM non-secure TIS callback shim. - */ - -#include -#include - -#define WOLFBOOT_TZ_FTPM - -int wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, uint8_t *rsp, - uint32_t *rspSz) -{ - (void)cmd; - (void)cmdSz; - (void)rsp; - (void)rspSz; - return -1; -} - -#include "../../test-app/wcs/ftpm_stub.c" - -START_TEST(ftpm_tis_rejects_address_below_window) -{ - BYTE buf[4] = {0}; - - ck_assert_int_eq(TPM2_IoCb_FtpmNsc(NULL, 1, FTPM_TIS_BASE - 1U, - buf, sizeof(buf), NULL), BAD_FUNC_ARG); -} -END_TEST - -START_TEST(ftpm_tis_rejects_address_above_window) -{ - BYTE buf[4] = {0}; - - ck_assert_int_eq(TPM2_IoCb_FtpmNsc(NULL, 1, FTPM_TIS_BASE + 0x1000U, - buf, sizeof(buf), NULL), BAD_FUNC_ARG); -} -END_TEST - -START_TEST(ftpm_tis_accepts_valid_window_register) -{ - BYTE buf[4] = {0}; - - ck_assert_int_eq(TPM2_IoCb_FtpmNsc(NULL, 1, - FTPM_TIS_BASE + FTPM_TIS_DID_VID, buf, sizeof(buf), NULL), - TPM_RC_SUCCESS); - ck_assert_uint_eq(buf[0], 0x4EU); - ck_assert_uint_eq(buf[1], 0x1BU); - ck_assert_uint_eq(buf[2], 0x01U); - ck_assert_uint_eq(buf[3], 0x00U); -} -END_TEST - -static Suite *ftpm_stub_suite(void) -{ - Suite *s; - TCase *tc; - - s = suite_create("ftpm_stub"); - tc = tcase_create("tis_window"); - tcase_add_test(tc, ftpm_tis_rejects_address_below_window); - tcase_add_test(tc, ftpm_tis_rejects_address_above_window); - tcase_add_test(tc, ftpm_tis_accepts_valid_window_register); - suite_add_tcase(s, tc); - - return s; -} - -int main(void) -{ - int fails; - Suite *s; - SRunner *sr; - - s = ftpm_stub_suite(); - sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - fails = srunner_ntests_failed(sr); - srunner_free(sr); - - return fails == 0 ? 0 : 1; -} diff --git a/tools/unit-tests/unit-fwtpm-stub.c b/tools/unit-tests/unit-fwtpm-stub.c new file mode 100644 index 0000000000..6c23b0ad47 --- /dev/null +++ b/tools/unit-tests/unit-fwtpm-stub.c @@ -0,0 +1,83 @@ +/* unit-fwtpm-stub.c + * + * Unit tests for the fwTPM non-secure TIS callback shim. + */ + +#include +#include + +#define WOLFBOOT_TZ_FWTPM + +int wcs_fwtpm_transmit(const uint8_t *cmd, uint32_t cmdSz, uint8_t *rsp, + uint32_t *rspSz) +{ + (void)cmd; + (void)cmdSz; + (void)rsp; + (void)rspSz; + return -1; +} + +#include "../../test-app/wcs/fwtpm_stub.c" + +START_TEST(fwtpm_tis_rejects_address_below_window) +{ + BYTE buf[4] = {0}; + + ck_assert_int_eq(TPM2_IoCb_FwtpmNsc(NULL, 1, FWTPM_TIS_BASE - 1U, + buf, sizeof(buf), NULL), BAD_FUNC_ARG); +} +END_TEST + +START_TEST(fwtpm_tis_rejects_address_above_window) +{ + BYTE buf[4] = {0}; + + ck_assert_int_eq(TPM2_IoCb_FwtpmNsc(NULL, 1, FWTPM_TIS_BASE + 0x1000U, + buf, sizeof(buf), NULL), BAD_FUNC_ARG); +} +END_TEST + +START_TEST(fwtpm_tis_accepts_valid_window_register) +{ + BYTE buf[4] = {0}; + + ck_assert_int_eq(TPM2_IoCb_FwtpmNsc(NULL, 1, + FWTPM_TIS_BASE + FWTPM_TIS_DID_VID, buf, sizeof(buf), NULL), + TPM_RC_SUCCESS); + ck_assert_uint_eq(buf[0], 0x4EU); + ck_assert_uint_eq(buf[1], 0x1BU); + ck_assert_uint_eq(buf[2], 0x01U); + ck_assert_uint_eq(buf[3], 0x00U); +} +END_TEST + +static Suite *fwtpm_stub_suite(void) +{ + Suite *s; + TCase *tc; + + s = suite_create("fwtpm_stub"); + tc = tcase_create("tis_window"); + tcase_add_test(tc, fwtpm_tis_rejects_address_below_window); + tcase_add_test(tc, fwtpm_tis_rejects_address_above_window); + tcase_add_test(tc, fwtpm_tis_accepts_valid_window_register); + suite_add_tcase(s, tc); + + return s; +} + +int main(void) +{ + int fails; + Suite *s; + SRunner *sr; + + s = fwtpm_stub_suite(); + sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + fails = srunner_ntests_failed(sr); + srunner_free(sr); + + return fails == 0 ? 0 : 1; +} From c6c254403b79c567d8345feda88cf99507207aa4 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 22 Apr 2026 14:38:59 +0200 Subject: [PATCH 5/5] Fixed path of config file for fwtpm tests in trustzone --- .github/workflows/trustzone-emulator-tests.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/trustzone-emulator-tests.yml b/.github/workflows/trustzone-emulator-tests.yml index 95214785e9..432421dc0a 100644 --- a/.github/workflows/trustzone-emulator-tests.yml +++ b/.github/workflows/trustzone-emulator-tests.yml @@ -106,18 +106,18 @@ 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 fTPM (stm32h5) + - name: Clean and build test with fwTPM (stm32h5) run: | make clean distclean - cp config/examples/stm32h5-tz-ftpm.config .config + 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-ftpm.log - grep -q "fTPM PCR0 extended:" /tmp/m33mu-ftpm.log - grep -q "fTPM unsealed secret: wolfBoot fTPM PCR secret" /tmp/m33mu-ftpm.log - grep -q "fTPM NSC tests passed" /tmp/m33mu-ftpm.log - grep -q "\\[BKPT\\] imm=0x7f" /tmp/m33mu-ftpm.log - grep -q "\\[EXPECT BKPT\\] Success" /tmp/m33mu-ftpm.log + | 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: |