diff --git a/docs/wolfHSM.md b/docs/wolfHSM.md index b6fafbcb94..6bdc040cac 100644 --- a/docs/wolfHSM.md +++ b/docs/wolfHSM.md @@ -58,7 +58,7 @@ To use certificate verification with wolfHSM: 1. Enable `WOLFBOOT_CERT_CHAIN_VERIFY` in your wolfBoot configuration 2. Ensure the wolfHSM server is configured with certificate manager support (`WOLFHSM_CFG_CERTIFICATE_MANAGER`) -3. Pre-provision the root CA certificate on the wolfHSM server at the NVM ID specified by the HAL `hsmNvmIdCertRootCA` +3. Pre-provision one or more root CA certificates on the wolfHSM server at the NVM IDs listed in the HAL `hsmNvmIdCertRootCAList`. Verification succeeds if the embedded chain anchors to *any* root in the list (absent NVM IDs are silently skipped). The list length must not exceed `WOLFHSM_CFG_CERT_MAX_VERIFY_ROOTS` (default 8). 4. Sign firmware images with the `--cert-chain` option, providing a DER-encoded certificate chain To build the simulator using wolfHSM for certificate verification: @@ -96,6 +96,7 @@ In addition to the standard wolfBoot HAL functions, wolfHSM-enabled platforms mu - `hsmDevIdHash`: The HSM device ID for hash operations. This is used to identify the HSM device to wolfBoot. - `hsmDevIdPubKey`: The HSM device ID for public key operations. This is used to identify the HSM device to wolfBoot. - `hsmKeyIdPubKey`: The HSM key ID for public key operations. This is used to identify the key to use for public key operations. +- `hsmNvmIdCertRootCAList` / `hsmNvmIdCertRootCACount`: Array of NVM IDs identifying the trusted root CA certificate(s) and its element count. Only used when building with `WOLFBOOT_CERT_CHAIN_VERIFY`. The chain in the firmware header may anchor to any of the listed roots; the count is bounded by `WOLFHSM_CFG_CERT_MAX_VERIFY_ROOTS` (default 8). Each in-tree HAL provides a default of `{ 1 }`; override the list via the `WOLFHSM_NVM_ROOT_CA_LIST` build option, which takes a comma-separated initializer (no quotes, no spaces) and is propagated to the HAL as `-DWOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST=...`. Set it in `.config` (e.g. `WOLFHSM_NVM_ROOT_CA_LIST=1,2,3`) or on the make command line (`make WOLFHSM_NVM_ROOT_CA_LIST=1,2,3 ...`). ### Client HAL Functions diff --git a/hal/aurix_tc3xx.c b/hal/aurix_tc3xx.c index 5b5c9f2997..71cdc89f21 100644 --- a/hal/aurix_tc3xx.c +++ b/hal/aurix_tc3xx.c @@ -111,15 +111,29 @@ const int hsmDevIdCrypt = WH_DEV_ID; const int hsmKeyIdCrypt = 0xFF; #endif #ifdef WOLFBOOT_CERT_CHAIN_VERIFY -const whNvmId hsmNvmIdCertRootCA = 1; +/* Set WOLFHSM_NVM_ROOT_CA_LIST=1,2,3 in .config (or pass on the make command + * line) to override the default single-root list. */ +#ifndef WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST +#define WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST 1 +#endif +const whNvmId hsmNvmIdCertRootCAList[] = { WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST }; +const uint16_t hsmNvmIdCertRootCACount = + sizeof(hsmNvmIdCertRootCAList) / sizeof(hsmNvmIdCertRootCAList[0]); #endif #elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) /*WOLFBOOT_ENABLE_WOLFHSM_CLIENT*/ /* map wolfBoot HAL layer wofHSM exports to their tchsm config vals */ -const int hsmDevIdHash = HSM_DEVID; -const int hsmDevIdPubKey = HSM_DEVID; -const whNvmId hsmNvmIdCertRootCA = 1; +const int hsmDevIdHash = HSM_DEVID; +const int hsmDevIdPubKey = HSM_DEVID; +/* Set WOLFHSM_NVM_ROOT_CA_LIST=1,2,3 in .config (or pass on the make command + * line) to override the default single-root list. */ +#ifndef WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST +#define WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST 1 +#endif +const whNvmId hsmNvmIdCertRootCAList[] = { WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST }; +const uint16_t hsmNvmIdCertRootCACount = + sizeof(hsmNvmIdCertRootCAList) / sizeof(hsmNvmIdCertRootCAList[0]); #ifdef EXT_ENCRYPT #error "AURIX does not support firmware encryption with wolfHSM(yet)" const int hsmDevIdCrypt = INVALID_DEVID; /*HSM_DEVID once CCB enabled*/ diff --git a/hal/sim.c b/hal/sim.c index 702f381070..b799cdfaf0 100644 --- a/hal/sim.c +++ b/hal/sim.c @@ -191,7 +191,14 @@ const int hsmDevIdCrypt = WH_DEV_ID; const int hsmKeyIdCrypt = 0xFF; #endif #ifdef WOLFBOOT_CERT_CHAIN_VERIFY -const whNvmId hsmNvmIdCertRootCA = 1; +/* Set WOLFHSM_NVM_ROOT_CA_LIST=1,2,3 in .config (or pass on the make command + * line) to override the default single-root list. */ +#ifndef WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST +#define WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST 1 +#endif +const whNvmId hsmNvmIdCertRootCAList[] = { WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST }; +const uint16_t hsmNvmIdCertRootCACount = + sizeof(hsmNvmIdCertRootCAList) / sizeof(hsmNvmIdCertRootCAList[0]); #endif int hal_hsm_init_connect(void); @@ -257,9 +264,16 @@ whServerConfig s_conf[1] = {{ whServerContext hsmServerCtx = {0}; -const int hsmDevIdHash = INVALID_DEVID; -const int hsmDevIdPubKey = INVALID_DEVID; -const whNvmId hsmNvmIdCertRootCA = 1; +const int hsmDevIdHash = INVALID_DEVID; +const int hsmDevIdPubKey = INVALID_DEVID; +/* Set WOLFHSM_NVM_ROOT_CA_LIST=1,2,3 in .config (or pass on the make command + * line) to override the default single-root list. */ +#ifndef WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST +#define WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST 1 +#endif +const whNvmId hsmNvmIdCertRootCAList[] = { WOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST }; +const uint16_t hsmNvmIdCertRootCACount = + sizeof(hsmNvmIdCertRootCAList) / sizeof(hsmNvmIdCertRootCAList[0]); #ifdef EXT_ENCRYPT #error "Simulator does not support firmware encryption with wolfHSM(yet)" const int hsmDevIdCrypt = WH_DEV_ID; diff --git a/include/hal.h b/include/hal.h index 1082976591..a3a81bbdf9 100644 --- a/include/hal.h +++ b/include/hal.h @@ -221,8 +221,11 @@ extern const int hsmDevIdCrypt; /* devId for image (enc)decryption */ extern const int hsmKeyIdCrypt; /* KeyId for image (enc/dec)ryption */ #endif #ifdef WOLFBOOT_CERT_CHAIN_VERIFY -/* NvmId for trusted root CA certificate */ -extern const whNvmId hsmNvmIdCertRootCA; +/* List of NvmIds for trusted root CA certificates. Verification succeeds if + * the cert chain anchors to any root in the list. The list length must not + * exceed WOLFHSM_CFG_CERT_MAX_VERIFY_ROOTS. */ +extern const whNvmId hsmNvmIdCertRootCAList[]; +extern const uint16_t hsmNvmIdCertRootCACount; #endif #endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT || WOLFBOOT_ENABLE_WOLFHSM_SERVER */ diff --git a/lib/wolfHSM b/lib/wolfHSM index 977bf187e7..80ee2d59ec 160000 --- a/lib/wolfHSM +++ b/lib/wolfHSM @@ -1 +1 @@ -Subproject commit 977bf187e7a57a184493dcd216eb9a328f381865 +Subproject commit 80ee2d59ecbfd46bd4b7b6ab8ed742ca5dac3e0f diff --git a/options.mk b/options.mk index 442e20143a..dff203822b 100644 --- a/options.mk +++ b/options.mk @@ -1456,6 +1456,15 @@ ifneq ($(CERT_CHAIN_VERIFY),) # export the private key in DER format so it can be used with certificates KEYGEN_OPTIONS += --der + # Optional override for the wolfHSM trusted-root NVM ID list used during + # cert-chain verification. Expects a comma-separated initializer (no quotes, + # no spaces), e.g. WOLFHSM_NVM_ROOT_CA_LIST=1,2,3. Bounded by + # WOLFHSM_CFG_CERT_MAX_VERIFY_ROOTS. When unset, falls back to a HAL-specified + # default + ifneq ($(strip $(WOLFHSM_NVM_ROOT_CA_LIST)),) + CFLAGS += '-DWOLFBOOT_WOLFHSM_NVM_ROOT_CA_LIST=$(WOLFHSM_NVM_ROOT_CA_LIST)' + endif + # User-provided cert chain takes precedence ifneq ($(USER_CERT_CHAIN),) CERT_CHAIN_FILE = $(USER_CERT_CHAIN) diff --git a/src/image.c b/src/image.c index f7a0384a3f..92ef90391e 100644 --- a/src/image.c +++ b/src/image.c @@ -2319,25 +2319,28 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) #if defined(WOLFHSM_CFG_DMA) wolfBoot_printf( "verifying cert chain and caching leaf pubkey (using DMA)\n"); - hsm_ret = wh_Client_CertVerifyDmaAndCacheLeafPubKey( - &hsmClientCtx, cert_chain, cert_chain_size, hsmNvmIdCertRootCA, + hsm_ret = wh_Client_CertVerifyMultiRootDmaAndCacheLeafPubKey( + &hsmClientCtx, cert_chain, cert_chain_size, + hsmNvmIdCertRootCAList, hsmNvmIdCertRootCACount, WH_NVM_FLAGS_USAGE_VERIFY, &g_certLeafKeyId, &cert_verify_result); #else wolfBoot_printf("verifying cert chain and caching leaf pubkey\n"); - hsm_ret = wh_Client_CertVerifyAndCacheLeafPubKey( - &hsmClientCtx, cert_chain, cert_chain_size, hsmNvmIdCertRootCA, + hsm_ret = wh_Client_CertVerifyMultiRootAndCacheLeafPubKey( + &hsmClientCtx, cert_chain, cert_chain_size, + hsmNvmIdCertRootCAList, hsmNvmIdCertRootCACount, WH_NVM_FLAGS_USAGE_VERIFY, &g_certLeafKeyId, &cert_verify_result); #endif #elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) wolfBoot_printf("verifying cert chain and caching leaf pubkey\n"); - hsm_ret = wh_Server_CertVerify( - &hsmServerCtx, cert_chain, cert_chain_size, hsmNvmIdCertRootCA, + hsm_ret = wh_Server_CertVerifyMultiRoot( + &hsmServerCtx, cert_chain, cert_chain_size, + hsmNvmIdCertRootCAList, hsmNvmIdCertRootCACount, WH_CERT_FLAGS_CACHE_LEAF_PUBKEY, WH_NVM_FLAGS_USAGE_VERIFY, &g_certLeafKeyId); if (hsm_ret == WH_ERROR_OK) { cert_verify_result = 0; } - wolfBoot_printf("wh_Server_CertVerify returned %d\n", hsm_ret); + wolfBoot_printf("wh_Server_CertVerifyMultiRoot returned %d\n", hsm_ret); #endif /* Error or verification failure results in standard auth check failure diff --git a/tools/config.mk b/tools/config.mk index 15eefc3e01..42461aa781 100644 --- a/tools/config.mk +++ b/tools/config.mk @@ -132,4 +132,5 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO SIGN_SECONDARY \ WOLFHSM_CLIENT \ WOLFHSM_CLIENT_LOCAL_KEYS \ + WOLFHSM_NVM_ROOT_CA_LIST \ ENCRYPT_CACHE