From daaf097b67a85e91008f63a0d684cd2f8085b08b Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Thu, 22 Oct 2026 19:55:08 -0600 Subject: [PATCH 1/6] new TC3 port IPC scheme --- hal/aurix_tc3xx.c | 52 +++++++++----------------------------- test-app/app_aurix_tc3xx.c | 3 ++- 2 files changed, 14 insertions(+), 41 deletions(-) diff --git a/hal/aurix_tc3xx.c b/hal/aurix_tc3xx.c index b8132f8c8d..8e60377003 100644 --- a/hal/aurix_tc3xx.c +++ b/hal/aurix_tc3xx.c @@ -91,7 +91,9 @@ /* wolfHSM client context and configuration */ #if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) -static int _connectCb(void* context, whCommConnected connect); +/* wolfHSM TC3xx port client, which selects the comm buffer and the bridge + * flags. wolfBoot and then the application on CPU0 both use client 0. */ +#define HSM_CLIENT 0 /* Client configuration/contexts */ static whTransportMemClientContext tmcCtx[1] = {0}; @@ -172,8 +174,8 @@ void wolfBoot_panic(void) TC3_LONGCALL; * to force the HSM core to execute from RAM while the host-driven flash * command completes. * The server app must be running first to process a park request */ -#define HSM_PARK() (void)tchsmHhHost_HsmPark() -#define HSM_RELEASE() (void)tchsmHhHost_HsmRelease() +#define HSM_PARK() (void)tchsmHhHost_HsmPark(HSM_CLIENT) +#define HSM_RELEASE() (void)tchsmHhHost_HsmRelease(HSM_CLIENT) #else #define HSM_PARK() #define HSM_RELEASE() @@ -587,41 +589,11 @@ RAMFUNCTION void ext_flash_unlock(void) #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT -static int _connectCb(void* context, whCommConnected connect) -{ - int ret; - - switch (connect) { - case WH_COMM_CONNECTED: - ret = tchsmHhHost2Hsm_Notify(TCHSM_HOST2HSM_NOTIFY_CONNECT); - break; - case WH_COMM_DISCONNECTED: - ret = tchsmHhHost2Hsm_Notify(TCHSM_HOST2HSM_NOTIFY_DISCONNECT); - break; - default: - ret = WH_ERROR_BADARGS; - break; - } - - return ret; -} - int hal_hsm_init_connect(void) { - int rc = 0; - size_t i; - - /* init shared memory buffers */ - uint32_t* req = (uint32_t*)hsmShmCore0CommBuf; - uint32_t* resp = - (uint32_t*)hsmShmCore0CommBuf + HSM_SHM_CORE0_COMM_BUF_WORDS / 2; - whTransportMemConfig tmcCfg[1] = {{ - .req = req, - .req_size = HSM_SHM_CORE0_COMM_BUF_SIZE / 2, - .resp = resp, - .resp_size = HSM_SHM_CORE0_COMM_BUF_SIZE / 2, - }}; + int rc = 0; + whTransportMemConfig tmcCfg[1] = {{0}}; /* Client configuration/contexts */ whCommClientConfig cc_conf[1] = {{ @@ -629,21 +601,21 @@ int hal_hsm_init_connect(void) .transport_context = (void*)tmcCtx, .transport_config = (void*)tmcCfg, .client_id = WOLFBOOT_WOLFHSM_CLIENT_ID, - .connect_cb = _connectCb, + .connect_cb = hsm_ipc_connect_cb, }}; whClientConfig c_conf[1] = {{ .comm = cc_conf, }}; - rc = hsm_ipc_init(); + rc = hsm_ipc_init(HSM_CLIENT); if (rc != WH_ERROR_OK) { return rc; } - /* init shared memory buffers */ - for (i = 0; i < HSM_SHM_CORE0_COMM_BUF_WORDS; i++) { - hsmShmCore0CommBuf[i] = 0; + rc = hsm_ipc_transport_config(HSM_CLIENT, tmcCfg); + if (rc != WH_ERROR_OK) { + return rc; } rc = wh_Client_Init(&hsmClientCtx, c_conf); diff --git a/test-app/app_aurix_tc3xx.c b/test-app/app_aurix_tc3xx.c index b6c275fd03..fd58d937dd 100644 --- a/test-app/app_aurix_tc3xx.c +++ b/test-app/app_aurix_tc3xx.c @@ -49,7 +49,8 @@ static void hsmUpdate(void) if (wolfBoot_current_firmware_version() > BASE_FW_VERSION) { return; } - rc = tchsmHhHost_HsmUpdateTrigger(); + /* Client 0 is the wolfHSM client of this core */ + rc = tchsmHhHost_HsmUpdateTrigger(0); if (rc == 0) { wolfBoot_printf("HSM update triggered\n"); } From 3a86ceb102f324695e2b6e0c11fd0e239a77749d Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Thu, 22 Oct 2026 21:16:29 -0600 Subject: [PATCH 2/6] small tweak for new port lib API after static lib refactor --- hal/aurix_tc3xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hal/aurix_tc3xx.c b/hal/aurix_tc3xx.c index 8e60377003..8e660247f1 100644 --- a/hal/aurix_tc3xx.c +++ b/hal/aurix_tc3xx.c @@ -601,7 +601,7 @@ int hal_hsm_init_connect(void) .transport_context = (void*)tmcCtx, .transport_config = (void*)tmcCfg, .client_id = WOLFBOOT_WOLFHSM_CLIENT_ID, - .connect_cb = hsm_ipc_connect_cb, + .connect_cb = hsm_ipc_get_connect_cb(HSM_CLIENT), }}; whClientConfig c_conf[1] = {{ From 49313ec8dafe626c39c65d2822ea12831a6a27c4 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Fri, 23 Oct 2026 14:35:51 -0600 Subject: [PATCH 3/6] self-update: check self-header version in monolithic mode --- .gitignore | 1 + docs/firmware_update.md | 9 +++ src/update_flash.c | 12 +++- tools/test.mk | 6 ++ tools/unit-tests/Makefile | 15 +++- tools/unit-tests/unit-update-flash.c | 100 +++++++++++++++++++++++++++ 6 files changed, 141 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 3a07d3512c..95fd7b8ea9 100644 --- a/.gitignore +++ b/.gitignore @@ -209,6 +209,7 @@ tools/unit-tests/unit-policy-create tools/unit-tests/unit-sign-encrypted-output tools/unit-tests/unit-update-flash-delta tools/unit-tests/unit-update-flash-self-update +tools/unit-tests/unit-update-flash-self-update-monolithic tools/unit-tests/unit-update-flash-hook tools/unit-tests/unit-loader-tpm-init tools/unit-tests/unit-update-ram-nofixed diff --git a/docs/firmware_update.md b/docs/firmware_update.md index 814847b955..c9186b9412 100644 --- a/docs/firmware_update.md +++ b/docs/firmware_update.md @@ -257,6 +257,15 @@ bytes and the nested application image. Later calls to `fw_size` bytes starting at `ARCH_FLASH_OFFSET`, spanning into the BOOT partition. +The persisted header also sets the version a new payload must exceed. A +staged payload is installed only if its version is greater than both the +running bootloader's `WOLFBOOT_VERSION` and the version in the +self-header. The bootloader inside each payload can therefore keep the +same `WOLFBOOT_VERSION` across releases. Without the self-header only +`WOLFBOOT_VERSION` is checked, so the bootloader in each payload must be +built with `WOLFBOOT_VERSION` equal to the payload's signed version, +otherwise the update is rejected. + ##### Restrictions - **Not power-fail safe.** Like all self-updates, a monolithic update diff --git a/src/update_flash.c b/src/update_flash.c index b1cd03ee9e..976365a25c 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -287,7 +287,17 @@ void RAMFUNCTION wolfBoot_check_self_update(void) (wolfBoot_open_image(&update, PART_UPDATE) == 0) && wolfBoot_get_image_type(PART_UPDATE) == (HDR_IMG_TYPE_WOLFBOOT | HDR_IMG_TYPE_AUTH)) { uint32_t update_version = wolfBoot_update_firmware_version(); - if (update_version <= wolfboot_version) { + uint32_t current_version = wolfboot_version; +#if defined(WOLFBOOT_SELF_UPDATE_MONOLITHIC) && defined(WOLFBOOT_SELF_HEADER) + /* The self-header has the installed payload's version, which may be + * newer than the WOLFBOOT_VERSION this bootloader was built with */ + uint32_t self_version = wolfBoot_get_self_version(); + + if (self_version > current_version) { + current_version = self_version; + } +#endif + if (update_version <= current_version) { wolfBoot_erase_partition(PART_UPDATE); return; } diff --git a/tools/test.mk b/tools/test.mk index 8f39c6e66c..3700f0b313 100644 --- a/tools/test.mk +++ b/tools/test.mk @@ -304,6 +304,7 @@ test-sim-self-update-monolithic: wolfboot.bin test-app/image_v1_signed.bin FORCE # Same as test-sim-self-update-monolithic, but also verifies that the # self-header was persisted at WOLFBOOT_PARTITION_SELF_HEADER_ADDRESS and # matches the signing tool's --header-only output byte-for-byte. +# A second boot checks that the payload is not installed again. # test-sim-self-update-monolithic-self-header: wolfboot.bin test-app/image_v1_signed.bin FORCE @echo "=== Simulator Monolithic Self-Update + Self-Header Test ===" @@ -341,6 +342,11 @@ test-sim-self-update-monolithic-self-header: wolfboot.bin test-app/image_v1_sign $(Q)dd if=internal_flash.dd bs=1 skip=$$(($(WOLFBOOT_PARTITION_SELF_HEADER_ADDRESS) - $(ARCH_FLASH_OFFSET))) count=$$(($(WOLFBOOT_SECTOR_SIZE))) of=persisted_hdr.dd 2>/dev/null $(Q)cmp -n $$(($(IMAGE_HEADER_SIZE))) persisted_hdr.dd monolithic_payload_v2_header.bin @echo " Self-header persisted correctly: PASSED" + @# Boot again. The self-header shows the payload is already installed, so + @# wolfBoot should erase it from the update partition, not install it again. + $(Q)./wolfboot.elf get_version || true + $(Q)dd if=internal_flash.dd bs=1 skip=$$(($(WOLFBOOT_PARTITION_UPDATE_ADDRESS) - $(ARCH_FLASH_OFFSET))) count=4 2>/dev/null | od -An -tx1 | grep -q "ff ff ff ff" + @echo " Installed payload erased from UPDATE on next boot: PASSED" @echo "=== Monolithic Self-Update + Self-Header Test PASSED ===" # Test that an oversized monolithic self-update is rejected. The payload is diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index f06f10ece0..6bbd1b0b17 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -67,6 +67,7 @@ TESTS:=unit-parser unit-parser-large-header unit-fdt unit-extflash unit-string \ unit-update-flash-hook \ unit-update-flash-self-update \ unit-update-flash-self-update-ecc \ + unit-update-flash-self-update-monolithic \ unit-nsc-update \ unit-update-flash-enc unit-update-flash-enc-full unit-update-flash-enc-intswap unit-update-ram unit-update-ram-fit unit-update-ram-uboot unit-update-ram-enc unit-update-ram-enc-nopart unit-update-ram-nofixed unit-update-ram-nofixed-noramboot unit-update-ram-noramboot unit-update-ram-custom-trailer unit-custom-trailer-nopart unit-update-flash-hwswap unit-pkcs11_store unit-psa_store unit-wolfhsm_flash_hal unit-disk \ unit-update-disk unit-update-disk-confirm unit-update-disk-golden unit-update-disk-fsp unit-update-disk-oob unit-update-disk-fit unit-update-disk-fit-ramdisk unit-multiboot unit-boot-x86-fsp unit-loader-tpm-init unit-qspi-flash unit-fwtpm-stub unit-tpm-rsa-exp \ @@ -408,6 +409,17 @@ unit-update-flash-self-update-ecc:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN - -DNVM_FLASH_JOURNAL -DNVM_FLASH_ECC -DWOLFBOOT_FLASH_WRITE_UNIT=32 \ -DWOLFBOOT_SECTOR_SIZE=0x1000 -DWOLFBOOT_SELF_HEADER \ -DWOLFBOOT_PARTITION_SELF_HEADER_ADDRESS=0xCD004000 +# Same as unit-update-flash-self-update, plus monolithic mode and a self-header +# (in the unused SWAP sector), to check that an update is only installed if it +# is newer than the version in the self-header. Some addresses are plain +# numbers because image.c is built separately and cannot see MOCK_ADDRESS_*. +unit-update-flash-self-update-monolithic:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \ + -DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT -DPART_SWAP_EXT \ + -DRAM_CODE -DARCH_SIM -DUNIT_TEST_SELF_UPDATE_ONLY -DWOLFBOOT_SELF_UPDATE_MONOLITHIC \ + -DWOLFBOOT_SELF_HEADER -DWOLFBOOT_SELF_HEADER_EXT \ + -DWOLFBOOT_PARTITION_SELF_HEADER_ADDRESS=0xCE000000 \ + -DARCH_FLASH_OFFSET=0xCD000000 -DWOLFBOOT_VERSION=7 \ + -DWOLFBOOT_ORIGIN=MOCK_ADDRESS_BOOT -DBOOTLOADER_PARTITION_SIZE=WOLFBOOT_PARTITION_SIZE unit-update-ram-fit:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \ -DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT \ -DPART_SWAP_EXT -DPART_BOOT_EXT -DWOLFBOOT_DUALBOOT -DNO_XIP \ @@ -862,7 +874,8 @@ unit-otp-keystore-gen-zeroize: unit-otp-keystore-gen-zeroize.c \ gcc -o $@ unit-otp-keystore-gen-zeroize.c unit-keystore.c \ -DFLASH_OTP_KEYSTORE $(CFLAGS) $(LDFLAGS) -ldl -unit-update-flash-self-update: ../../include/target.h unit-update-flash.c +unit-update-flash-self-update unit-update-flash-self-update-monolithic: \ + ../../include/target.h unit-update-flash.c gcc -o $@ unit-update-flash.c ../../src/image.c \ $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c \ $(CFLAGS) $(LDFLAGS) diff --git a/tools/unit-tests/unit-update-flash.c b/tools/unit-tests/unit-update-flash.c index 0000d11a88..2eb87f8230 100644 --- a/tools/unit-tests/unit-update-flash.c +++ b/tools/unit-tests/unit-update-flash.c @@ -586,6 +586,91 @@ START_TEST (test_self_update_ecc_whole_units) } END_TEST #endif + +#if defined(WOLFBOOT_SELF_UPDATE_MONOLITHIC) && defined(WOLFBOOT_SELF_HEADER) +/* Write a self-header with only the magic, size and version fields */ +static void set_self_header_version(uint32_t version) +{ + uintptr_t hdr = WOLFBOOT_PARTITION_SELF_HEADER_ADDRESS; + uint32_t magic = WOLFBOOT_MAGIC; + uint32_t size_img = host_to_img_u32(TEST_SIZE_SMALL); + uint32_t word = 4 << 16 | HDR_VERSION; + uint32_t version_img = host_to_img_u32(version); + + ext_flash_unlock(); + ext_flash_erase(hdr, WOLFBOOT_SELF_HEADER_SIZE); + ext_flash_write(hdr, (void *)&magic, 4); + ext_flash_write(hdr + 4, (void *)&size_img, 4); + ext_flash_write(hdr + 8, (void *)&word, 4); + ext_flash_write(hdr + 12, (void *)&version_img, 4); + ext_flash_lock(); +} + +static void stage_self_update(uint32_t version) +{ + add_payload_type(PART_UPDATE, version, TEST_SIZE_SMALL, + HDR_IMG_TYPE_WOLFBOOT | HDR_IMG_TYPE_AUTH); + ext_flash_unlock(); + wolfBoot_set_partition_state(PART_UPDATE, IMG_STATE_UPDATING); + ext_flash_lock(); +} + +/* The update has the same version as the self-header, so it is already + * installed and should be erased, not installed again */ +START_TEST (test_self_update_self_header_sameversion_erased) +{ + reset_mock_stats(); + prepare_flash(); + clear_erase_stats(); + set_self_header_version(WOLFBOOT_VERSION + 2); + stage_self_update(WOLFBOOT_VERSION + 2); + + wolfBoot_check_self_update(); + + ck_assert_int_eq(arch_reboot_called, 0); + ck_assert_int_ge(erased_update, 1); + ck_assert_uint_eq(*(uint32_t *)(uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS, + 0xFFFFFFFFu); + cleanup_flash(); +} +END_TEST + +/* The update is older than the self-header version, so it should be erased + * even though it is newer than WOLFBOOT_VERSION */ +START_TEST (test_self_update_self_header_oldversion_erased) +{ + reset_mock_stats(); + prepare_flash(); + clear_erase_stats(); + set_self_header_version(WOLFBOOT_VERSION + 2); + stage_self_update(WOLFBOOT_VERSION + 1); + + wolfBoot_check_self_update(); + + ck_assert_int_eq(arch_reboot_called, 0); + ck_assert_int_ge(erased_update, 1); + ck_assert_uint_eq(*(uint32_t *)(uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS, + 0xFFFFFFFFu); + cleanup_flash(); +} +END_TEST + +START_TEST (test_self_update_self_header_newversion_installs) +{ + reset_mock_stats(); + prepare_flash(); + clear_erase_stats(); + set_self_header_version(WOLFBOOT_VERSION + 2); + stage_self_update(WOLFBOOT_VERSION + 3); + + wolfBoot_check_self_update(); + + ck_assert_int_eq(arch_reboot_called, 1); + ck_assert_uint_eq(wolfBoot_get_self_version(), WOLFBOOT_VERSION + 3); + cleanup_flash(); +} +END_TEST +#endif /* WOLFBOOT_SELF_UPDATE_MONOLITHIC && WOLFBOOT_SELF_HEADER */ #endif #ifndef UNIT_TEST_SELF_UPDATE_ONLY @@ -2284,11 +2369,21 @@ Suite *wolfboot_suite(void) #ifdef NVM_FLASH_ECC TCase *self_update_ecc = tcase_create("Self update on ECC flash"); #endif +#if defined(WOLFBOOT_SELF_UPDATE_MONOLITHIC) && defined(WOLFBOOT_SELF_HEADER) + TCase *self_header_sameversion = tcase_create("Self update self-header same version erased"); + TCase *self_header_oldversion = tcase_create("Self update self-header older version erased"); + TCase *self_header_newversion = tcase_create("Self update self-header newer version installs"); +#endif tcase_add_test(self_update_sameversion, test_self_update_sameversion_erased); tcase_add_test(self_update_oldversion, test_self_update_oldversion_erased); tcase_add_test(self_update_invalid_integrity, test_self_update_newversion_invalid_integrity_denied); tcase_add_test(self_update_success, test_self_update_newversion_copies_and_reboots); +#if defined(WOLFBOOT_SELF_UPDATE_MONOLITHIC) && defined(WOLFBOOT_SELF_HEADER) + tcase_add_test(self_header_sameversion, test_self_update_self_header_sameversion_erased); + tcase_add_test(self_header_oldversion, test_self_update_self_header_oldversion_erased); + tcase_add_test(self_header_newversion, test_self_update_self_header_newversion_installs); +#endif suite_add_tcase(s, self_update_sameversion); suite_add_tcase(s, self_update_oldversion); @@ -2298,6 +2393,11 @@ Suite *wolfboot_suite(void) tcase_add_test(self_update_ecc, test_self_update_ecc_whole_units); suite_add_tcase(s, self_update_ecc); #endif +#if defined(WOLFBOOT_SELF_UPDATE_MONOLITHIC) && defined(WOLFBOOT_SELF_HEADER) + suite_add_tcase(s, self_header_sameversion); + suite_add_tcase(s, self_header_oldversion); + suite_add_tcase(s, self_header_newversion); +#endif #endif return s; #else From 3d484f46b5ec3aaf33556cfcb268b59563f37ad0 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Tue, 27 Oct 2026 09:40:22 -0700 Subject: [PATCH 4/6] split monolithic test into its own rule --- tools/unit-tests/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index 6bbd1b0b17..83faf163fb 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -874,8 +874,7 @@ unit-otp-keystore-gen-zeroize: unit-otp-keystore-gen-zeroize.c \ gcc -o $@ unit-otp-keystore-gen-zeroize.c unit-keystore.c \ -DFLASH_OTP_KEYSTORE $(CFLAGS) $(LDFLAGS) -ldl -unit-update-flash-self-update unit-update-flash-self-update-monolithic: \ - ../../include/target.h unit-update-flash.c +unit-update-flash-self-update: ../../include/target.h unit-update-flash.c gcc -o $@ unit-update-flash.c ../../src/image.c \ $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c \ $(CFLAGS) $(LDFLAGS) @@ -885,6 +884,11 @@ unit-update-flash-self-update-ecc: ../../include/target.h unit-update-flash.c $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c \ $(CFLAGS) $(LDFLAGS) +unit-update-flash-self-update-monolithic: ../../include/target.h unit-update-flash.c + gcc -o $@ unit-update-flash.c ../../src/image.c \ + $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c \ + $(CFLAGS) $(LDFLAGS) + unit-sdhci-response-bits: ../../include/target.h unit-sdhci-response-bits.c gcc -o $@ $^ $(CFLAGS) -ffunction-sections -fdata-sections $(LDFLAGS) \ -Wl,--gc-sections From 3c56b4bac094166e979204954f90dc475b5bc03f Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Wed, 28 Oct 2026 14:25:29 -0700 Subject: [PATCH 5/6] Make wolfHSM cert chain name constraints optional, updates to support new wolfHSM keygen macro protection, further reducing codesize --- docs/compile.md | 1 + docs/wolfHSM.md | 1 + include/user_settings.h | 19 +++++++++++++------ options.mk | 5 +++++ tools/config.mk | 1 + 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/docs/compile.md b/docs/compile.md index 7f646e03f7..290cf85fbd 100644 --- a/docs/compile.md +++ b/docs/compile.md @@ -827,6 +827,7 @@ make CERT_CHAIN_VERIFY=1 \ - `USER_CERT_CHAIN` requires both `USER_PRIVATE_KEY` and `USER_PUBLIC_KEY` - The private and public keys must correspond to the leaf certificate identity in the chain +- If the chain uses X.509 name constraints and you are building as a wolfHSM server (`WOLFHSM_SERVER=1`), set `CERT_CHAIN_NAME_CONSTRAINTS=1`. When `CERT_CHAIN_VERIFY=1` is set without `USER_CERT_CHAIN`, the build auto-generates a dummy 3-tier certificate hierarchy in `test-dummy-ca/` for testing. This also applies to wolfHSM NVM image generation when applicable. diff --git a/docs/wolfHSM.md b/docs/wolfHSM.md index dd3b052a93..1188ddd787 100644 --- a/docs/wolfHSM.md +++ b/docs/wolfHSM.md @@ -95,6 +95,7 @@ This section describes the exposed configuration options available for wolfHSM i - `WOLFHSM_CFG_COMM_DATA_LEN` (default 5000): Size in bytes of the wolfHSM message data payload. The default fits a whole DER certificate chain or the largest ML-DSA keys/signatures in a single message. Targets with a smaller transport slot must lower it in their `.config`. In server mode the value is currently only applied to `SIGN=ML_DSA` builds; other server builds use the wolfHSM library default. - `WOLFHSM_CFG_CERT_MAX_VERIFY_ROOTS` (default 8): Maximum number of trusted root CA NVM IDs accepted for certificate chain verification; bounds the length of the HAL `hsmNvmIdCertRootCAList` and of `WOLFHSM_NVM_ROOT_CA_LIST`. Part of the client-server wire format (see note below). - `WOLFHSM_NVM_ROOT_CA_LIST`: Overrides the NVM IDs of the trusted root CA certificates used for certificate chain verification. Takes a comma-separated initializer with no quotes and no spaces, e.g. `WOLFHSM_NVM_ROOT_CA_LIST=1,2,3`. Client mode takes the client's cert IDs (e.g. `1`); server mode takes full NVM IDs (e.g. `0x6101`). The list length must not exceed `WOLFHSM_CFG_CERT_MAX_VERIFY_ROOTS`. Only used when `CERT_CHAIN_VERIFY=1`. +- `CERT_CHAIN_NAME_CONSTRAINTS` (default 0): Set to 1 to enforce X.509 name constraints during certificate chain verification. When 0, name constraint support is compiled out of wolfSSL (`IGNORE_NAME_CONSTRAINTS`), so a chain containing a certificate with a critical name constraints extension will be rejected whereas a non-critical one will be ignored. Only applies when wolfBoot is configured as a wolfHSM server. - `WOLFHSM_NVM_IMAGE` (default 1): Set to 0 to skip wolfHSM NVM image generation. Used by targets that do not provision keys from a pre-built NVM image, e.g. because the HAL loads the verification key into the server's key cache at boot (PIC32CZ). - `USER_NVM_INIT`: Path to a user-provided whnvmtool `.nvminit` file used to generate the wolfHSM NVM image in place of the default auto-generated one. Also re-enables NVM image generation when user-provided keys (`USER_PRIVATE_KEY`, `USER_PUBLIC_KEY`, `USER_CERT_CHAIN`) would otherwise skip it. diff --git a/include/user_settings.h b/include/user_settings.h index 01c57b1e4c..18c1087c43 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -344,7 +344,10 @@ extern int tolower(int c); # define WOLFSSL_SP_SMALL # endif # define WOLFSSL_HAVE_SP_ECC -# define WOLFSSL_KEY_GEN +# if !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ + !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) +# define WOLFSSL_KEY_GEN +# endif # define HAVE_ECC_KEY_EXPORT # define HAVE_ECC_KEY_IMPORT # endif @@ -423,8 +426,7 @@ extern int tolower(int c); * guard keeps it from satisfying the inner condition there. */ # ifndef WC_NO_RNG # if defined(WOLFCRYPT_SECURE_MODE) || defined(WOLFBOOT_TPM_PARMENC) || \ - defined(WOLFCRYPT_TEST) || defined(WOLFCRYPT_BENCHMARK) || \ - defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + defined(WOLFCRYPT_TEST) || defined(WOLFCRYPT_BENCHMARK) # define WC_RSA_BLINDING # endif # endif @@ -438,8 +440,7 @@ extern int tolower(int c); # endif # if !defined(WOLFBOOT_TPM) && !defined(WOLFCRYPT_SECURE_MODE) && \ !defined(WOLFCRYPT_TEST) && !defined(WOLFCRYPT_BENCHMARK) && \ - !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ - !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) # define WOLFSSL_RSA_VERIFY_INLINE # define WOLFSSL_RSA_VERIFY_ONLY # define WOLFSSL_RSA_PUBLIC_ONLY @@ -1029,7 +1030,10 @@ extern int tolower(int c); # define WOLF_CRYPTO_CB # undef HAVE_ANONYMOUS_INLINE_AGGREGATES # define HAVE_ANONYMOUS_INLINE_AGGREGATES 1 -# define WOLFSSL_KEY_GEN + /* wolfBoot's own client and server never generate keys */ +# ifdef WOLFCRYPT_TZ_WOLFHSM +# define WOLFSSL_KEY_GEN +# endif #endif /* Secure-side sizing common to any wolfHSM server build (TZ engine and @@ -1104,6 +1108,9 @@ extern int tolower(int c); # define WOLFSSL_USER_IO # define WOLFSSL_SP_MUL_D # define WOLFSSL_ALLOW_NO_SUITES +# ifndef WOLFBOOT_CERT_CHAIN_NAME_CONSTRAINTS +# define IGNORE_NAME_CONSTRAINTS +# endif #endif #ifdef WOLFSSL_STM32_PKA diff --git a/options.mk b/options.mk index 930a7f1872..c5d5ff7434 100644 --- a/options.mk +++ b/options.mk @@ -1992,6 +1992,11 @@ ifneq ($(CERT_CHAIN_VERIFY),) CFLAGS += '-DWOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST=$(WOLFHSM_NVM_ROOT_CA_LIST)' endif + # Optional: enforce X.509 name constraints. Off by default for code size. + ifeq ($(CERT_CHAIN_NAME_CONSTRAINTS),1) + CFLAGS += -DWOLFBOOT_CERT_CHAIN_NAME_CONSTRAINTS + endif + # User-provided cert chain takes precedence. Declare the chain's # algorithms via AUX_PK_ALGOS/AUX_HASH_ALGOS so the verifier has them. ifneq ($(USER_CERT_CHAIN),) diff --git a/tools/config.mk b/tools/config.mk index f9eac2bb53..968a32987c 100644 --- a/tools/config.mk +++ b/tools/config.mk @@ -166,4 +166,5 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO AUX_HASH_ALGOS \ CERT_CHAIN_GEN_CA_ALGO \ CERT_CHAIN_GEN_CA_HASH \ + CERT_CHAIN_NAME_CONSTRAINTS \ ENCRYPT_CACHE From 34efb39722804a3d4c3e74e84a51b61fa6a17c5e Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Fri, 30 Oct 2026 08:36:38 -0700 Subject: [PATCH 6/6] update wolfHSM submodule --- lib/wolfHSM | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wolfHSM b/lib/wolfHSM index 8bb2b0f0fd..4c3bfdec57 160000 --- a/lib/wolfHSM +++ b/lib/wolfHSM @@ -1 +1 @@ -Subproject commit 8bb2b0f0fdcc18a9e9898017139f7bdc1cc16ecb +Subproject commit 4c3bfdec57bb024a62a5a1792a6facfcbf0f106c