diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 87fa2f713c..849fc1accd 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -468,7 +468,7 @@ jobs: uses: ./.github/workflows/test-build.yml with: arch: host - config-file: ./config/examples/sim-wolfHSM.config + config-file: ./config/examples/sim-wolfHSM-client.config rp2350_test: uses: ./.github/workflows/test-build-pico-sdk.yml diff --git a/.github/workflows/test-wolfhsm-simulator.yml b/.github/workflows/test-wolfhsm-simulator.yml index 211231be6a..cc34aa8796 100644 --- a/.github/workflows/test-wolfhsm-simulator.yml +++ b/.github/workflows/test-wolfhsm-simulator.yml @@ -15,11 +15,14 @@ jobs: matrix: config: - name: "Standard wolfHSM" - file: "config/examples/sim-wolfHSM.config" + file: "config/examples/sim-wolfHSM-client.config" - name: "wolfHSM ML-DSA" - file: "config/examples/sim-wolfHSM-mldsa.config" + file: "config/examples/sim-wolfHSM-client-mldsa.config" - name: "wolfHSM cert chain verify" - file: "config/examples/sim-wolfHSM-certchain.config" + file: "config/examples/sim-wolfHSM-client-certchain.config" + - name: "wolfHSM server cert chain verify" + file: "config/examples/sim-wolfHSM-server-certchain.config" + fail-fast: false runs-on: ubuntu-latest @@ -50,32 +53,35 @@ jobs: run: | make clean && make test-sim-internal-flash-with-update - # checkout and build wolfHSM examples repo - - name: Checkout wolfHSM-examples - uses: actions/checkout@v4 - with: - repository: wolfssl/wolfHSM-examples - # Make sure to update this when the wolfHSM submodule is updated! - ref: wolfHSM-examples-v1.2.0 - path: wolfHSM-examples - - name: Build example POSIX TCP server - run: cd wolfHSM-examples/posix/tcp/wh_server_tcp && make WOLFSSL_DIR=../../../../lib/wolfssl WOLFHSM_DIR=../../../../lib/wolfHSM + if: matrix.config.name != 'wolfHSM server cert chain verify' + run: cd lib/wolfHSM/examples/posix/tcp/wh_server_tcp && make WOLFSSL_DIR=../../../../../wolfssl # Start the server in the background - name: Run POSIX TCP server + if: matrix.config.name != 'wolfHSM server cert chain verify' run: | - cd wolfHSM-examples/posix/tcp/wh_server_tcp + cd lib/wolfHSM/examples/posix/tcp/wh_server_tcp if [ "${{ matrix.config.name }}" = "wolfHSM cert chain verify" ]; then tmpfile=$(mktemp) - echo "obj 1 0xFFFF 0x0000 \"cert CA\" ../../../../test-dummy-ca/root-cert.der" >> $tmpfile + echo "obj 1 0xFFFF 0x0000 \"cert CA\" ../../../../../../test-dummy-ca/root-cert.der" >> $tmpfile ./Build/wh_server_tcp.elf --nvminit $tmpfile & else - ./Build/wh_server_tcp.elf --client 12 --id 255 --key ../../../../wolfboot_signing_private_key_pub.der & + ./Build/wh_server_tcp.elf --client 12 --id 255 --key ../../../../../../wolfboot_signing_private_key_pub.der & fi TCP_SERVER_PID=$! echo "TCP_SERVER_PID=$TCP_SERVER_PID" >> $GITHUB_ENV + # For testing the wolfHSM server cert chain verify feature, we need to create an NVM image containing our root CA that + # the internal wolfHSM server can load. + - name: Create NVM image for wolfHSM server cert chain verify + if: matrix.config.name == 'wolfHSM server cert chain verify' + run: | + make -C lib/wolfHSM/tools/whnvmtool + tmpfile=$(mktemp) + echo "obj 1 0xFFFF 0x0000 \"cert CA\" test-dummy-ca/root-cert.der" >> $tmpfile + ./lib/wolfHSM/tools/whnvmtool/whnvmtool --image=wolfBoot_wolfHSM_NVM.bin --size=16348 --invert-erased-byte $tmpfile + # Run the sunny day update test against the server - name: Run sunny day update test run: | @@ -83,6 +89,6 @@ jobs: # Kill the server if it is still running - name: Kill POSIX TCP server - if: always() + if: always() && matrix.config.name != 'wolfHSM server cert chain verify' run: | kill $TCP_SERVER_PID || true diff --git a/Makefile b/Makefile index 5a9125cede..45e6493a6c 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,7 @@ endif WOLFCRYPT_OBJS:= SECURE_OBJS:= PUBLIC_KEY_OBJS:= -WOLFHSM_CLIENT_OBJS:= +WOLFHSM_OBJS:= ifneq ("$(NO_LOADER)","1") OBJS+=./src/loader.o endif @@ -67,7 +67,7 @@ include options.mk OBJS+=$(WOLFCRYPT_OBJS) OBJS+=$(PUBLIC_KEY_OBJS) -OBJS+=$(WOLFHSM_CLIENT_OBJS) +OBJS+=$(WOLFHSM_OBJS) CFLAGS+= \ -I"." -I"include/" -I"lib/wolfssl" \ diff --git a/arch.mk b/arch.mk index ea0b631ab9..885ba5cac8 100644 --- a/arch.mk +++ b/arch.mk @@ -1130,7 +1130,7 @@ ifeq ($(ARCH),sim) CFLAGS+=-DWOLFSSL_SP_DIV_WORD_HALF endif ifeq ($(WOLFHSM_CLIENT),1) - WOLFHSM_CLIENT_OBJS += $(LIBDIR)/wolfHSM/port/posix/posix_transport_tcp.o + WOLFHSM_OBJS += $(LIBDIR)/wolfHSM/port/posix/posix_transport_tcp.o endif endif diff --git a/config/examples/sim-wolfHSM-certchain.config b/config/examples/sim-wolfHSM-client-certchain.config similarity index 98% rename from config/examples/sim-wolfHSM-certchain.config rename to config/examples/sim-wolfHSM-client-certchain.config index 52b8d0ef7a..14639088f1 100644 --- a/config/examples/sim-wolfHSM-certchain.config +++ b/config/examples/sim-wolfHSM-client-certchain.config @@ -4,7 +4,8 @@ SIGN?=ECC256 HASH?=SHA256 WOLFBOOT_SMALL_STACK?=0 SPI_FLASH=0 -DEBUG=1 +DEBUG=0 +SPMATH=1 # Cert chain options CERT_CHAIN_VERIFY=1 diff --git a/config/examples/sim-wolfHSM-mldsa.config b/config/examples/sim-wolfHSM-client-mldsa.config similarity index 98% rename from config/examples/sim-wolfHSM-mldsa.config rename to config/examples/sim-wolfHSM-client-mldsa.config index 3e8c97007d..581a067f7c 100644 --- a/config/examples/sim-wolfHSM-mldsa.config +++ b/config/examples/sim-wolfHSM-client-mldsa.config @@ -4,7 +4,8 @@ SIGN?=ML_DSA HASH?=SHA256 WOLFBOOT_SMALL_STACK?=0 SPI_FLASH=0 -DEBUG=1 +DEBUG=0 +SPMATH=1 # # ML-DSA config examples: diff --git a/config/examples/sim-wolfHSM.config b/config/examples/sim-wolfHSM-client.config similarity index 98% rename from config/examples/sim-wolfHSM.config rename to config/examples/sim-wolfHSM-client.config index fba00791af..a13f407966 100644 --- a/config/examples/sim-wolfHSM.config +++ b/config/examples/sim-wolfHSM-client.config @@ -5,6 +5,7 @@ HASH?=SHA256 WOLFBOOT_SMALL_STACK?=0 SPI_FLASH=0 DEBUG=0 +SPMATH=1 # sizes should be multiple of system page size WOLFBOOT_PARTITION_SIZE=0x100000 diff --git a/config/examples/sim-wolfHSM-server-certchain.config b/config/examples/sim-wolfHSM-server-certchain.config new file mode 100644 index 0000000000..8ca5cfbc46 --- /dev/null +++ b/config/examples/sim-wolfHSM-server-certchain.config @@ -0,0 +1,37 @@ +ARCH=sim +TARGET=sim +SIGN?=ECC256 +HASH?=SHA256 +WOLFBOOT_SMALL_STACK?=0 +SPI_FLASH=0 +DEBUG=0 +SPMATH=1 + +# Cert chain options +CERT_CHAIN_VERIFY=1 +CERT_CHAIN_GEN=1 + +# Ensure header is large enough to hold the cert chain (check sign tool output) +# for actual length +IMAGE_HEADER_SIZE=2048 + +# If SIGN=RSA4096, use the below options +#WOLFBOOT_HUGE_STACK=1 +#IMAGE_HEADER_SIZE=4096 + +# wolfHSM options +WOLFHSM_SERVER=1 + +# sizes should be multiple of system page size +WOLFBOOT_PARTITION_SIZE=0x200000 +WOLFBOOT_SECTOR_SIZE=0x1000 +WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80000 +# if on external flash, it should be multiple of system page size +WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x280000 +WOLFBOOT_PARTITION_SWAP_ADDRESS=0x480000 + +# required for keytools +WOLFBOOT_FIXED_PARTITIONS=1 + +# For debugging XMALLOC/XFREE +#CFLAGS_EXTRA+=-DWOLFBOOT_DEBUG_MALLOC diff --git a/docs/HAL.md b/docs/HAL.md index 148deaad70..3aee817be6 100644 --- a/docs/HAL.md +++ b/docs/HAL.md @@ -145,3 +145,6 @@ implementation in new ports must return immediately without performing any actio if the content of the bootloader partition in the two banks already match. +### wolfHSM HAL extensions + +Refer to [wolfHSM.md](wolfHSM.md) for the wolfHSM-specific HAL functions and an overview of wolfHSM compatibility. diff --git a/docs/wolfHSM.md b/docs/wolfHSM.md index 4f9100736d..1ec50e29a6 100644 --- a/docs/wolfHSM.md +++ b/docs/wolfHSM.md @@ -1,7 +1,11 @@ -# wolfHSM Client Integration with wolfBoot +# wolfHSM Integration with wolfBoot -wolfBoot provides tight integration with wolfHSM when used on a select group of supported platforms. When used in this mode, wolfBoot acts as a wolfHSM client, with all cryptographic operations and key storage offloaded to the wolfHSM server as remote procedure calls (RPCs). +wolfBoot provides tight integration with wolfHSM when used on a select group of supported platforms. wolfBoot can operate in two modes with wolfHSM: + +1. **wolfHSM Client Mode**: wolfBoot acts as a wolfHSM client, with all cryptographic operations and key storage offloaded to an external wolfHSM server as remote procedure calls (RPCs). + +2. **wolfHSM Server Mode**: wolfBoot runs on the wolfHSM server, directly using the wolfHSM API for operations like secure key storage and certificate chain verification. For an introduction to wolfHSM, please refer to the [wolfHSM Manual](https://wolfSSL.com/https://www.wolfssl.com/documentation/manuals/wolfhsm/) and [wolfHSM GitHub Repository](https://github.com/wolfssl/wolfHSM.git). @@ -20,9 +24,9 @@ wolfBoot supports using wolfHSM on the following platforms: Details on configuring wolfBoot to use wolfHSM on each of these platforms can be found in the wolfBoot (and wolfHSM) documentation specific to that target, with the exception of the simulator, which is documented here. The remainder of this document focuses on the generic wolfHSM-related configuration options. -## Algorithm Support +## Client Algorithm Support -wolfBoot supports using wolfHSM for the following algorithms: +wolfBoot supports using wolfHSM to offlad the following algorithms to the HSM server: - RSA with 2048, 3072, and 4096-bit keys for image signature verification - ECDSA P-256, P-384, and P-521 for image signature verification @@ -47,29 +51,36 @@ The certificate verification process with wolfHSM works as follows: 4. A certificate chain is created consisting of the signing identity certificate and an optional number of intermediate certificates, where trust is chained back to the root CA. 5. During the signing process, the image is signed with the signer private key and the certificate chain is embedded in the firmware image header. 6. During boot, wolfBoot extracts the certificate chain from the firmware header -7. wolfBoot uses the wolfHSM server to verify the certificate chain against a pre-provisioned root CA certificate stored on the HSM and caches the public key of the leaf certificate if the chain verifies as trusted +7. wolfBoot uses the wolfHSM server (remotely or directly, depending on configuration) to verify the certificate chain against a pre-provisioned root CA certificate stored on the HSM and caches the public key of the leaf certificate if the chain verifies as trusted 8. If the chain is trusted, wolfBoot uses the cached public key from the leaf certificate to verify the firmware signature on the wolfHSM server 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 `hsmClientNvmIdCertRootCA` +3. Pre-provision the root CA certificate on the wolfHSM server at the NVM ID specified by the HAL `hsmNvmIdCertRootCA` 4. Sign firmware images with the `--cert-chain` option, providing a DER-encoded certificate chain -To build the simulator using wolfHSM for certificate verification, use [config/examples/sim-wolfHSM-certchain.config](config/examples/sim-wolfHSM-certchain.config). +To build the simulator using wolfHSM for certificate verification: + +- **Client Mode**: Use [config/examples/sim-wolfHSM-client-certchain.config](config/examples/sim-wolfHSM-client-certchain.config) +- **Server Mode**: Use [config/examples/sim-wolfHSM-server-certchain.config](config/examples/sim-wolfHSM-server-certchain.config) ## Configuration Options -This section describes the configuration options available for wolfHSM client integration. Note that these options should be configured automatically by the build system for each supported platform when wolfHSM support is enabled. Consult the platform-specific documentation for details on enabling wolfHSM support. +This section describes the configuration options available for wolfHSM integration. Note that these options should be configured automatically by the build system for each supported platform when wolfHSM support is enabled. Consult the platform-specific documentation for details on enabling wolfHSM support. ### `WOLFBOOT_ENABLE_WOLFHSM_CLIENT` -This option enables wolfHSM client support in wolfBoot. Without defining this option, support for wolfHSM is not compiled in and the remainder of the options have no effect. +This option enables wolfHSM client support in wolfBoot. Without defining this option, support for wolfHSM client mode is not compiled in. + +### `WOLFBOOT_ENABLE_WOLFHSM_SERVER` + +This option enables wolfHSM server support in wolfBoot. When defined, wolfBoot includes an embedded wolfHSM server that provides HSM functionality locally within the bootloader. This is mutually exclusive with `WOLFBOOT_ENABLE_WOLFHSM_CLIENT`. ### `WOLFBOOT_USE_WOLFHSM_PUBKEY_ID` -This option enables use of the reserved wolfHSM public key ID for firmware authentication, and is typically the desired behavior for using wolfHSM. When this option is defined, wolfBoot will use the reserved wolfHSM keyId defined by the HAL (`hsmClientKeyIdPubKey`). This option is meant to be used in conjunction with the `--nolocalkeys` keygen option, as the key material in the keystore will not be used. +This option enables use of the reserved wolfHSM public key ID for firmware authentication, and is typically the desired behavior for using wolfHSM. When this option is defined, wolfBoot will use the reserved wolfHSM keyId defined by the HAL (`hsmKeyIdPubKey`). This option is meant to be used in conjunction with the `--nolocalkeys` keygen option, as the key material in the keystore will not be used. If this option is not defined, cryptographic operations are still performed on the wolfHSM server, but wolfBoot assumes the key material is present in the keystore and NOT stored on the HSM. This means that wolfBoot will first load keys from the keystore, send the key material to the wolfHSM server at the time of use (cached as ephemeral keys), and finally evict the key from the HSM after usage. This behavior is typically only useful for debugging or testing scenarios, where the keys may not be pre-loaded onto the HSM. The keystore for use in this mode should not be generated with the `--nolocalkeys` option. @@ -79,52 +90,91 @@ In addition to the standard wolfBoot HAL functions, wolfHSM-enabled platforms mu ### HAL Global Variables -- `hsmClientCtx`: A global context for the wolfHSM client. This is initialized by the HAL and passed to wolfBoot, but should not be modified by wolfBoot. -- `hsmClientDevIdHash`: The HSM device ID for hash operations. This is used to identify the HSM device to wolfBoot. -- `hsmClientDevIdPubKey`: The HSM device ID for public key operations. This is used to identify the HSM device to wolfBoot. -- `hsmClientKeyIdPubKey`: The HSM key ID for public key operations. This is used to identify the key to use for public key operations. +- `hsmClientCtx`: A global context for the wolfHSM client. This is initialized by the HAL and passed to wolfBoot, but should not be modified by wolfBoot. Only used when building with `WOLFHSM_ENABLE_WOLFHSM_CLIENT`. +- `hsmServerCtx`: A global context for the wolfHSM server. This is initialized by the HAL and used by wolfBoot for all HSM operations. Only used when building with `WOLFHSM_ENABLE_WOLFHSM_SERVER` -### HAL Functions +- `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. + +### Client HAL Functions - `hal_hsm_init_connect()`: Initializes the connection to the wolfHSM server. This is called by wolfBoot during initialization. This should initialize the HSM client context (`hsmClientCtx`) with a valid configuration and initialize the wolfHSM client API. - `hal_hsm_disconnect()`: Disconnects from the wolfHSM server. This is called by wolfBoot during shutdown. This should clean up the HSM client context (`hsmClientCtx`) and invoke the wolfHSM client API's cleanup function, freeing any additional allocated resources. +### Server HAL Functions + +- `hal_hsm_server_init()`: Initializes the embedded wolfHSM server. This is called by wolfBoot during initialization. This should initialize the HSM server context (`hsmServerCtx`) with a valid configuration, initialize the NVM subsystem, and start the wolfHSM server. +- `hal_hsm_server_cleanup()`: Cleans up the embedded wolfHSM server. This is called by wolfBoot during shutdown. This should clean up the HSM server context and free any allocated resources. + ## wolfBoot Simulator and wolfHSM -The wolfBoot simulator supports wolfHSM with the POSIX TCP transport. It expects to communicate with the [wolfHSM example POSIX TCP server](https://github.com/wolfSSL/wolfHSM-examples/tree/main/posix/tcp/wh_server_tcp) at `127.0.0.1:1234`. See the [wolfHSM-examples README](https://github.com/wolfSSL/wolfHSM-examples/blob/main/README.md) for more information on the example POSIX TCP server. +The wolfBoot simulator supports using wolfHSM in both client and server modes: + +### wolfHSM Client Mode + +The simulator supports wolfHSM client mode with the POSIX TCP transport. It expects to communicate with the [wolfHSM example POSIX TCP server](https://github.com/wolfSSL/wolfHSM-examples/tree/main/posix/tcp/wh_server_tcp) at `127.0.0.1:1234`. See the [wolfHSM-examples README](https://github.com/wolfSSL/wolfHSM-examples/blob/main/README.md) for more information on the example POSIX TCP server. + +### wolfHSM Server Mode + +The simulator also supports an embedded wolfHSM server mode where wolfBoot includes the complete wolfHSM server functionality. In this mode, no external wolfHSM server is required, and all HSM operations are performed locally within wolfBoot using the file-based NVM simulator for storage. ### Building the simulator with wolfHSM support -The wolfBoot simulator supports using wolfHSM with all algorithms mentioned in [Algorithm Support](#algorithm-support). To build the simulator configured to use wolfHSM,, ensure you build with the `WOLFHSM_CLIENT=1` makefile option. This will automatically define `WOLFBOOT_USE_WOLFHSM_PUBKEY_ID`, and requires the public key corresponding to the private key that signed the image to be pre-loaded into the HSM at the keyId specified by `hsmClientKeyIdPubKey` in the simulator HAL (see the next section for details on loading keys into the HSM example server). +The wolfBoot simulator supports using wolfHSM with all algorithms mentioned in [Algorithm Support](#algorithm-support). + +#### wolfHSM Client Mode Build + +To build the simulator configured to use wolfHSM client mode, ensure you build with the `WOLFHSM_CLIENT=1` makefile option. This will automatically define `WOLFBOOT_USE_WOLFHSM_PUBKEY_ID`, and requires the public key corresponding to the private key that signed the image to be pre-loaded into the HSM at the keyId specified by `hsmKeyIdPubKey` in the simulator HAL. ```sh -# Grab the HSM simulator configuration -cp config/examples/sim-wolfHSM.config .config +# Grab the HSM client simulator configuration +cp config/examples/sim-wolfHSM-client.config .config -# Build wolfBoot with the simulator HAL configured to use wolfHSM, automatically generating keys +# Build wolfBoot with the simulator HAL configured to use wolfHSM client, automatically generating keys make # Build and sign the test applications used in the simulated update make test-sim-internal-flash-with-update # The generated wolfBoot public key can be found at `wolfboot_signing_private_key_pub.der`, and -# should be loaded into the HSM at the keyId specified by `hsmClientKeyIdPubKey` as described +# should be loaded into the HSM at the keyId specified by `hsmKeyIdPubKey` as described # in the next section ``` -### Running the simulator against a wolfHSM server +#### wolfHSM Server Mode Build + +To build the simulator configured to use embedded wolfHSM server mode, use the `WOLFHSM_SERVER=1` makefile option. In this mode, wolfBoot includes the complete wolfHSM server and no external HSM server is required. Currently the wolfHSM server only supporst the certificate chain verification mode of authentication. + +```sh +# Grab the HSM server simulator configuration (with certificate chain verification) +cp config/examples/sim-wolfHSM-server-certchain.config .config + +# Build wolfBoot with the embedded wolfHSM server. +make + +# Build and sign the test applications used in the simulated update. This generates a dummy CA and certificate chain for your public key. +make test-sim-internal-flash-with-update + +``` + +### Running the simulator with wolfHSM + +#### wolfHSM Client Mode -First, build the wolfHSM POSIX TCP server, following the instructions in the [wolfHSM-examples README](https://github.com/wolfSSL/wolfHSM-examples/blob/main/README.md). +When using wolfHSM client mode, you need to run an external wolfHSM server. + +First, build the wolfHSM POSIX TCP server, following the instructions in the [wolfHSM example README](github.com/wolfSSL/wolfHSM/blob/main/examples/README.md) Next, in a new terminal window, run the wolfHSM POSIX TCP server, loading the public key generated by the wolfBoot build process (`wolfboot_signing_private_key_pub.der`) ```sh # Build the example server -cd wolfHSM-examples/posix/tcp/wh_server_tcp -make WOLFHSM_DIR=/path/to/wolfHSM/install +cd lib/wolfHSM/examples/posix/tcp/wh_server_tcp +make WOLFSSL_DIR=../../../../../wolfssl -# Run the server, loading the wolfBoot public key and using keyId 0xFF (or modify keyId to match value of `hsmClientKeyIdPubKey` in `hal/sim.c`) -./Build/wh_server_tcp.elf --key /path/to/wolfboot_signing_private_key_pub.der --id 0xFF +# Run the server, loading the wolfBoot public key and using the client ID and keyId matching the values declared in `hal/sim.c`) +./Build/wh_server_tcp.elf --client 12 --id 255 --key ../../../../../../wolfboot_signing_private_key_pub.der & # The server will now be waiting for connections ``` @@ -146,12 +196,9 @@ hal_flash_erase addr 0x7f66658f7000 len 4091 1 ``` -Restart the wolfHSM server with the same arguments, then rerun the wolfBoot simulator to boot the new firmware and verify the update. +Rerun the wolfBoot simulator to boot the new firmware and verify the update. ```sh -# In the wolfHSM server terminal window -./Build/wh_server_tcp.elf --key /path/to/wolfboot_signing_private_key_pub.der --id 0xFF - # In the wolfBoot terminal window, run the following to update the image and confirm the update ./wolfboot.elf success get_version @@ -173,3 +220,21 @@ Simulator assigned ./internal_flash.dd to base 0x7fe902d2e000 2 ``` +#### wolfHSM Server Mode + +When using wolfHSM server mode, no external server is required. wolfBoot includes the embedded wolfHSM server functionality. The only requirement is a wolfHSM simulated NVM image must be created that the server can use with the root CA for certificate verification stored at the expected NVM ID. + +```sh +# Create a simulated NVM image for the POSIX flash file simulator containing the dummy root CA for cert chain verification. +# You must build whnvmtool first if you haven't already, and ensure the file name matches the simulated NVM image file +# name in hal/sim.c +./lib/wolfHSM/tools/whnvmtool/whnvmtool --image=wolfBoot_wolfHSM_NVM.bin --size 16348 --invert-erased-byte tools/scripts/wolfBoot-wolfHSM-sim-dummy-certchain.nvminit + +# Run the wolfBoot simulator with embedded wolfHSM server to stage an update +./wolfboot.elf update_trigger get_version + +# Run the simulator again to boot the new firmware and verify the update +./wolfboot.elf success get_version +``` + +The embedded wolfHSM server will automatically handle all cryptographic operations and key management using the file-based NVM storage(`wolfBoot_wolfHSM_NVM.bin`) that was generated above. diff --git a/hal/aurix_tc3xx.c b/hal/aurix_tc3xx.c index b637130903..c8fc82f615 100644 --- a/hal/aurix_tc3xx.c +++ b/hal/aurix_tc3xx.c @@ -652,21 +652,21 @@ static whTransportClientCb tmcCb[1] = {WH_TRANSPORT_MEM_CLIENT_CB}; /* Globally exported HAL symbols */ whClientContext hsmClientCtx = {0}; -const int hsmClientDevIdHash = WH_DEV_ID_DMA; +const int hsmDevIdHash = WH_DEV_ID_DMA; #ifdef WOLFBOOT_SIGN_ML_DSA /* Use DMA for massive ML DSA keys/signatures, too big for shm transport */ -const int hsmClientDevIdPubKey = WH_DEV_ID_DMA; +const int hsmDevIdPubKey = WH_DEV_ID_DMA; #else -const int hsmClientDevIdPubKey = WH_DEV_ID; +const int hsmDevIdPubKey = WH_DEV_ID; #endif -const int hsmClientKeyIdPubKey = 0xFF; +const int hsmKeyIdPubKey = 0xFF; #ifdef EXT_ENCRYPT #error "AURIX TC3xx does not support firmware encryption with wolfHSM (yet)" -const int hsmClientDevIdCrypt = WH_DEV_ID; -const int hsmClientKeyIdCrypt = 0xFF; +const int hsmDevIdCrypt = WH_DEV_ID; +const int hsmKeyIdCrypt = 0xFF; #endif #ifdef WOLFBOOT_CERT_CHAIN_VERIFY -const whNvmId hsmClientNvmIdCertRootCA = 1; +const whNvmId hsmNvmIdCertRootCA = 1; #endif diff --git a/hal/sim.c b/hal/sim.c index 3b4b3f8ef2..b5c387aad0 100644 --- a/hal/sim.c +++ b/hal/sim.c @@ -51,7 +51,15 @@ #include "wolfhsm/wh_error.h" #include "wolfhsm/wh_client.h" #include "port/posix/posix_transport_tcp.h" -#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT */ +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) /*WOLFBOOT_ENABLE_WOLFHSM_CLIENT*/ +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_server.h" +#include "wolfhsm/wh_server_keystore.h" +#include "wolfhsm/wh_nvm.h" +#include "wolfhsm/wh_nvm_flash.h" +#include "wolfhsm/wh_transport_mem.h" +#include "port/posix/posix_flash_file.h" +#endif /* WOLFBOOT_ENABLE_WOLFHSM_SERVER */ /* Global pointer to the internal and external flash base */ uint8_t *sim_ram_base; @@ -91,23 +99,97 @@ static whClientConfig c_conf[1] = {{ }}; /* Globally exported HAL symbols */ -whClientContext hsmClientCtx = {0}; -const int hsmClientDevIdHash = WH_DEV_ID; -const int hsmClientDevIdPubKey = WH_DEV_ID; -const int hsmClientKeyIdPubKey = 0xFF; +whClientContext hsmClientCtx = {0}; +const int hsmDevIdHash = WH_DEV_ID; +const int hsmDevIdPubKey = WH_DEV_ID; +const int hsmKeyIdPubKey = 0xFF; #ifdef EXT_ENCRYPT #error "Simulator does not support firmware encryption with wolfHSM(yet)" -const int hsmClientDevIdCrypt = WH_DEV_ID; -const int hsmClientKeyIdCrypt = 0xFF; +const int hsmDevIdCrypt = WH_DEV_ID; +const int hsmKeyIdCrypt = 0xFF; #endif #ifdef WOLFBOOT_CERT_CHAIN_VERIFY -const whNvmId hsmClientNvmIdCertRootCA = 1; +const whNvmId hsmNvmIdCertRootCA = 1; #endif int hal_hsm_init_connect(void); int hal_hsm_disconnect(void); -#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT */ +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) /*WOLFBOOT_ENABLE_WOLFHSM_CLIENT*/ + +/* HAL Flash state and configuration */ +const whFlashCb fcb[1] = {POSIX_FLASH_FILE_CB}; +posixFlashFileContext fc[1] = {0}; +posixFlashFileConfig fc_conf[1] = {{ + .filename = "wolfBoot_wolfHSM_NVM.bin", + .partition_size = 16384, + .erased_byte = (uint8_t)0, +}}; +/* NVM Configuration using PosixSim HAL Flash */ +whNvmFlashConfig nf_conf[1] = {{ + .cb = fcb, + .context = fc, + .config = fc_conf, +}}; +whNvmFlashContext nfc[1] = {0}; +whNvmCb nfcb[1] = {WH_NVM_FLASH_CB}; + +whNvmConfig n_conf[1] = {{ + .cb = nfcb, + .context = nfc, + .config = nf_conf, +}}; +whNvmContext nvm[1] = {{0}}; + +static uint8_t req[] = {0}; +static uint8_t resp[] = {0}; + +whTransportMemConfig tmcf[1] = {{ + .req = (whTransportMemCsr*)req, + .req_size = sizeof(req), + .resp = (whTransportMemCsr*)resp, + .resp_size = sizeof(resp), +}}; +whTransportServerCb tscb[1] = {WH_TRANSPORT_MEM_SERVER_CB}; +whTransportMemServerContext tmsc[1] = {0}; +/* Dummy comm server config */ +whCommServerConfig cs_conf[1] = {{ + .transport_cb = tscb, + .transport_context = &tmsc, + .transport_config = &tmcf, + .server_id = 0, +}}; + +/* Crypto context */ +whServerCryptoContext crypto[1] = {{ + .devId = INVALID_DEVID, +}}; + +#if defined(WOLFHSM_CFG_SHE_EXTENSION) +whServerSheContext she[1] = {{0}}; +#endif + +whServerConfig s_conf[1] = {{ + .comm_config = cs_conf, + .nvm = nvm, + .crypto = crypto, +}}; + +whServerContext hsmServerCtx = {0}; + +const int hsmDevIdHash = INVALID_DEVID; +const int hsmDevIdPubKey = INVALID_DEVID; +const whNvmId hsmNvmIdCertRootCA = 1; +#ifdef EXT_ENCRYPT +#error "Simulator does not support firmware encryption with wolfHSM(yet)" +const int hsmDevIdCrypt = WH_DEV_ID; +const int hsmKeyIdCrypt = 0xFF; +#endif + +int hal_hsm_server_init(void); +int hal_hsm_server_cleanup(void); + +#endif /* WOLFBOOT_ENABLE_WOLFHSM_SERVER*/ static int mmap_file(const char *path, uint8_t *address, uint8_t** ret_address) { @@ -410,7 +492,6 @@ int wolfBoot_dualboot_candidate(void) #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT - int hal_hsm_init_connect(void) { int rc = 0; @@ -449,4 +530,57 @@ int hal_hsm_disconnect(void) return rc; } -#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT */ +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) /*WOLFBOOT_ENABLE_WOLFHSM_CLIENT*/ + +int hal_hsm_server_init(void) +{ + int rc = 0; + + rc = wh_Nvm_Init(nvm, n_conf); + if (rc != 0) { + fprintf(stderr, "Failed to initialize NVM: %d\n", rc); + exit(-1); + } + + wolfCrypt_Init(); + + rc = wc_InitRng_ex(crypto->rng, NULL, INVALID_DEVID); + if (rc != 0) { + fprintf(stderr, "Failed to initialize RNG: %d\n", rc); + exit(-1); + } + + rc = wh_Server_Init(&hsmServerCtx, s_conf); + if (rc != 0) { + fprintf(stderr, "Failed to initialize HSM server: %d\n", rc); + exit(-1); + } + + return rc; +} + +int hal_hsm_server_cleanup(void) +{ + int rc = 0; + + rc = wh_Server_Cleanup(&hsmServerCtx); + if (rc != 0) { + fprintf(stderr, "Failed to cleanup HSM server: %d\n", rc); + exit(-1); + } + + rc = wc_FreeRng(crypto->rng); + if (rc != 0) { + fprintf(stderr, "Failed to cleanup RNG: %d\n", rc); + exit(-1); + } + + rc = wolfCrypt_Cleanup(); + if (rc != 0) { + fprintf(stderr, "Failed to cleanup wolfCrypt: %d\n", rc); + exit(-1); + } + + return rc; +} +#endif /* WOLFBOOT_ENABLE_WOLFHSM_SERVER */ diff --git a/include/hal.h b/include/hal.h index 2de7ea739c..c93f637ae2 100644 --- a/include/hal.h +++ b/include/hal.h @@ -144,33 +144,53 @@ int hal_flash_test(void); #endif -#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT -/* TODO: most of this should be moved to its own HSM shim header */ -#include "wolfhsm/wh_error.h" /* wolfHSM error codes */ -#include "wolfhsm/wh_client.h" /* For client API access */ +#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) + +#include "wolfhsm/wh_error.h" /* wolfHSM error codes */ +#include "wolfhsm/wh_client.h" /* For client API access */ #include "wolfhsm/wh_client_crypto.h" /* For client crypto helper API */ extern whClientContext hsmClientCtx; /* global wolfHSM client context */ -extern const int hsmClientDevIdHash; /* devId for image digest */ -extern const int hsmClientDevIdPubKey; /* devId for signature verification */ -#ifdef EXT_ENCRYPTED -extern const int hsmClientDevIdCrypt; /* devId for image (enc)decryption */ +int hal_hsm_init_connect(void); +int hal_hsm_disconnect(void); + +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) /*WOLFBOOT_ENABLE_WOLFHSM_CLIENT*/ + +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_server.h" +#include "wolfhsm/wh_server_crypto.h" +#include "wolfhsm/wh_server_keystore.h" +#if defined(WOLFBOOT_CERT_CHAIN_VERIFY) +#include "wolfhsm/wh_server_cert.h" #endif -extern const int hsmClientKeyIdPubKey; /* KeyId for public key operations */ +extern whServerContext hsmServerCtx; /* global wolfHSM server context */ + +int hal_hsm_server_init(void); +int hal_hsm_server_cleanup(void); + +#endif /* WOLFBOOT_ENABLE_WOLFHSM_SERVER */ + + +#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ + defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + +/* devId and KeyIds for wolfHSM operations */ + +extern const int hsmDevIdHash; /* devId for image digest */ +extern const int hsmDevIdPubKey; /* devId for signature verification */ +extern const int hsmKeyIdPubKey; /* KeyId for public key operations */ #ifdef EXT_ENCRYPTED -extern const int hsmClientKeyIdCrypt; /* KeyId for image (enc/dec)ryption */ +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 hsmClientNvmIdCertRootCA; +extern const whNvmId hsmNvmIdCertRootCA; #endif -/* Implementation of functions provided by HAL */ -int hal_hsm_init_connect(void); -int hal_hsm_disconnect(void); -#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT */ +#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT || WOLFBOOT_ENABLE_WOLFHSM_SERVER */ #ifdef __cplusplus } diff --git a/include/user_settings.h b/include/user_settings.h index 61b5cfab80..dc7c5f7fdc 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -35,7 +35,10 @@ #define WOLFSSL_GENERAL_ALIGNMENT 4 #define SINGLE_THREADED #define WOLFSSL_USER_MUTEX /* avoid wc_port.c wc_InitAndAllocMutex */ +#if !(defined WOLFBOOT_ENABLE_WOLFHSM_SERVER && \ + defined(WOLFBOOT_CERT_CHAIN_VERIFY)) #define WOLFCRYPT_ONLY +#endif #define SIZEOF_LONG_LONG 8 #define HAVE_EMPTY_AGGREGATES 0 #define HAVE_ANONYMOUS_INLINE_AGGREGATES 0 @@ -114,7 +117,9 @@ extern int tolower(int c); # endif /* Some ECC options are disabled to reduce size */ -# if !defined(WOLFCRYPT_SECURE_MODE) +# if !defined(WOLFCRYPT_SECURE_MODE) && \ + !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ + !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) # if !defined(WOLFBOOT_TPM) # define NO_ECC_SIGN # define NO_ECC_DHE @@ -123,7 +128,8 @@ extern int tolower(int c); # if defined(__RX__) # define WOLFSSL_NO_CT_OPS /* don't use constant time ops in misc.c */ # endif -# if !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) +# if !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ + !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) # define NO_ECC_EXPORT # define NO_ECC_KEY_EXPORT # endif @@ -270,7 +276,8 @@ extern int tolower(int c); # define WOLFSSL_DILITHIUM_SMALL # define WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM # define WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC -# ifndef WOLFBOOT_ENABLE_WOLFHSM_CLIENT +# if !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ + !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) # define WOLFSSL_DILITHIUM_NO_ASN1 # endif /* dilithium needs these sha functions. */ @@ -349,7 +356,8 @@ extern int tolower(int c); #endif #if (defined(WOLFBOOT_TPM_SEAL) && defined(WOLFBOOT_ATA_DISK_LOCK)) || \ - defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) + defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ + defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) # define WOLFSSL_BASE64_ENCODE #else # define NO_CODING @@ -403,8 +411,10 @@ extern int tolower(int c); #endif #if !defined(WOLFCRYPT_SECURE_MODE) && !defined(WOLFBOOT_TPM_PARMENC) -#if !(defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && defined(WOLFBOOT_SIGN_ML_DSA)) - #define WC_NO_RNG +#if !(defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ + defined(WOLFBOOT_SIGN_ML_DSA)) && \ + !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) +#define WC_NO_RNG #endif #define WC_NO_HASHDRBG #define NO_AES_CBC @@ -421,12 +431,15 @@ extern int tolower(int c); #if !defined(WOLFBOOT_TPM) && !defined(WOLFCRYPT_SECURE_MODE) # define NO_HMAC -#if !(defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && defined(WOLFBOOT_SIGN_ML_DSA)) - #define WC_NO_RNG +#if !(defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ + defined(WOLFBOOT_SIGN_ML_DSA)) && \ + !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) +#define WC_NO_RNG #endif # define WC_NO_HASHDRBG # define NO_DEV_RANDOM -# if !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) +# if !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ + !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) # define NO_ECC_KEY_EXPORT # if defined(NO_RSA) # define NO_ASN @@ -478,7 +491,7 @@ extern int tolower(int c); # define WOLFSSL_SP_NO_DYN_STACK #endif -#ifndef WOLFBOOT_SMALL_STACK +#if !defined(WOLFBOOT_SMALL_STACK) && !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) # if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) # define WOLFSSL_SP_NO_MALLOC # define WOLFSSL_SP_NO_DYN_STACK @@ -544,11 +557,21 @@ extern int tolower(int c); #define XTOLOWER(x) (x) #endif -#ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT +#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ + defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) # define WOLF_CRYPTO_CB # undef HAVE_ANONYMOUS_INLINE_AGGREGATES # define HAVE_ANONYMOUS_INLINE_AGGREGATES 1 # define WOLFSSL_KEY_GEN -#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT */ +#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT || WOLFBOOT_ENABLE_WOLFHSM_SERVER */ + +#if defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) && \ + defined(WOLFBOOT_CERT_CHAIN_VERIFY) +# define NO_TLS +# define NO_OLD_TLS +# define WOLFSSL_NO_TLS12 +# define WOLFSSL_USER_IO +# define WOLFSSL_SP_MUL_D +#endif #endif /* !_WOLFBOOT_USER_SETTINGS_H_ */ diff --git a/lib/wolfHSM b/lib/wolfHSM index f76701294b..fda4b62e91 160000 --- a/lib/wolfHSM +++ b/lib/wolfHSM @@ -1 +1 @@ -Subproject commit f76701294bb8be47c7a9364a1061483c9ed7b3af +Subproject commit fda4b62e917a1382363079b19261a6a79290bbf9 diff --git a/options.mk b/options.mk index 8399bc33f3..4997971ece 100644 --- a/options.mk +++ b/options.mk @@ -868,7 +868,7 @@ ifneq ($(WOLFBOOT_PART_ID),) SIGN_OPTIONS+=--id $(WOLFBOOT_PART_ID) endif -# wolfHSM options +# wolfHSM client options ifeq ($(WOLFHSM_CLIENT),1) LIBDIR := $(dir $(lastword $(MAKEFILE_LIST)))lib WOLFCRYPT_OBJS += \ @@ -876,16 +876,16 @@ ifeq ($(WOLFHSM_CLIENT),1) $(LIBDIR)/wolfssl/wolfcrypt/src/coding.o ifeq ($(SIGN),ML_DSA) + WOLFCRYPT_OBJS += $(MATH_OBJS) # Dilithium asn.c decode/encode requires mp_xxx functions WOLFCRYPT_OBJS += \ - $(LIBDIR)/wolfssl/wolfcrypt/src/tfm.o \ $(LIBDIR)/wolfssl/wolfcrypt/src/random.o # Large enough to handle the largest Dilithium key/signature CFLAGS += -DWOLFHSM_CFG_COMM_DATA_LEN=5000 endif - WOLFHSM_CLIENT_OBJS += \ + WOLFHSM_OBJS += \ $(LIBDIR)/wolfHSM/src/wh_client.o \ $(LIBDIR)/wolfHSM/src/wh_client_nvm.o \ $(LIBDIR)/wolfHSM/src/wh_client_cryptocb.o \ @@ -899,7 +899,7 @@ ifeq ($(WOLFHSM_CLIENT),1) #includes CFLAGS += -I"$(LIBDIR)/wolfHSM" # defines - CFLAGS += -DWOLFBOOT_ENABLE_WOLFHSM_CLIENT + CFLAGS += -DWOLFBOOT_ENABLE_WOLFHSM_CLIENT -DWOLFHSM_CFG_ENABLE_CLIENT # Make sure we export generated public keys so they can be used to load into # HSM out-of-band KEYGEN_OPTIONS += --exportpubkey --der @@ -915,13 +915,70 @@ ifeq ($(WOLFHSM_CLIENT),1) # Ensure wolfHSM is configured to use certificate manager if we are # doing cert chain verification ifneq ($(CERT_CHAIN_VERIFY),) - WOLFHSM_CLIENT_OBJS += \ + WOLFHSM_OBJS += \ $(LIBDIR)/wolfHSM/src/wh_client_cert.o \ $(LIBDIR)/wolfHSM/src/wh_message_cert.o CFLAGS += -DWOLFHSM_CFG_CERTIFICATE_MANAGER endif endif +# wolfHSM server options +ifeq ($(WOLFHSM_SERVER),1) + LIBDIR := $(dir $(lastword $(MAKEFILE_LIST)))lib + WOLFCRYPT_OBJS += \ + $(LIBDIR)/wolfssl/wolfcrypt/src/cryptocb.o \ + $(LIBDIR)/wolfssl/wolfcrypt/src/coding.o \ + $(LIBDIR)/wolfssl/wolfcrypt/src/random.o + + ifeq ($(SIGN),ML_DSA) + WOLFCRYPT_OBJS += $(MATH_OBJS) + # Large enough to handle the largest Dilithium key/signature + CFLAGS += -DWOLFHSM_CFG_COMM_DATA_LEN=5000 + endif + + WOLFHSM_OBJS += \ + $(LIBDIR)/wolfHSM/src/wh_utils.o \ + $(LIBDIR)/wolfHSM/src/wh_comm.o \ + $(LIBDIR)/wolfHSM/src/wh_nvm.o \ + $(LIBDIR)/wolfHSM/src/wh_nvm_flash.o \ + $(LIBDIR)/wolfHSM/src/wh_flash_unit.o \ + $(LIBDIR)/wolfHSM/src/wh_crypto.o \ + $(LIBDIR)/wolfHSM/src/wh_server.o \ + $(LIBDIR)/wolfHSM/src/wh_server_nvm.o \ + $(LIBDIR)/wolfHSM/src/wh_server_crypto.o \ + $(LIBDIR)/wolfHSM/src/wh_server_counter.o \ + $(LIBDIR)/wolfHSM/src/wh_server_keystore.o \ + $(LIBDIR)/wolfHSM/src/wh_server_customcb.o \ + $(LIBDIR)/wolfHSM/src/wh_message_customcb.o \ + $(LIBDIR)/wolfHSM/src/wh_message_keystore.o \ + $(LIBDIR)/wolfHSM/src/wh_message_crypto.o \ + $(LIBDIR)/wolfHSM/src/wh_message_counter.o \ + $(LIBDIR)/wolfHSM/src/wh_message_nvm.o \ + $(LIBDIR)/wolfHSM/src/wh_message_comm.o \ + $(LIBDIR)/wolfHSM/src/wh_transport_mem.o \ + $(LIBDIR)/wolfHSM/port/posix/posix_flash_file.o + + #includes + CFLAGS += -I"$(LIBDIR)/wolfHSM" + # defines' + CFLAGS += -DWOLFBOOT_ENABLE_WOLFHSM_SERVER -DWOLFHSM_CFG_ENABLE_SERVER + + # Ensure wolfHSM is configured to use certificate manager if we are + # doing cert chain verification + ifneq ($(CERT_CHAIN_VERIFY),) + CFLAGS += -I"$(LIBDIR)/wolfssl" + WOLFCRYPT_OBJS += \ + $(LIBDIR)/wolfssl/src/internal.o \ + $(LIBDIR)/wolfssl/src/ssl.o \ + $(LIBDIR)/wolfssl/src/ssl_certman.o + + WOLFHSM_OBJS += \ + $(LIBDIR)/wolfHSM/src/wh_message_cert.o \ + $(LIBDIR)/wolfHSM/src/wh_server_cert.o + CFLAGS += -DWOLFHSM_CFG_CERTIFICATE_MANAGER + endif +endif + # Cert chain verification options ifneq ($(CERT_CHAIN_VERIFY),) CFLAGS += -DWOLFBOOT_CERT_CHAIN_VERIFY diff --git a/src/image.c b/src/image.c index d47ec4a4cb..2388caef62 100644 --- a/src/image.c +++ b/src/image.c @@ -56,7 +56,8 @@ static uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE] XALIGNED(4); #if defined(WOLFBOOT_CERT_CHAIN_VERIFY) && \ - defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) + (defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ + defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER)) static whKeyId g_certLeafKeyId = WH_KEYID_ERASED; static int g_leafKeyIdValid = 0; #endif @@ -197,8 +198,9 @@ static void wolfBoot_verify_signature_ecc(uint8_t key_slot, int ret, verify_res = 0; ecc_key ecc; mp_int r, s; -#if !defined WOLFBOOT_ENABLE_WOLFHSM_CLIENT || \ - (defined WOLFBOOT_ENABLE_WOLFHSM_CLIENT && \ +#if (!defined WOLFBOOT_ENABLE_WOLFHSM_CLIENT && \ + !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER)) || \ + (defined WOLFBOOT_ENABLE_WOLFHSM_CLIENT && \ !defined(WOLFBOOT_USE_WOLFHSM_PUBKEY_ID)) uint8_t* pubkey = keystore_get_buffer(key_slot); int pubkey_sz = keystore_get_size(key_slot); @@ -213,8 +215,9 @@ static void wolfBoot_verify_signature_ecc(uint8_t key_slot, defined(WOLFBOOT_RENESAS_TSIP) || \ defined(WOLFBOOT_RENESAS_RSIP) ret = wc_ecc_init_ex(&ecc, NULL, RENESAS_DEVID); -#elif defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) - ret = wc_ecc_init_ex(&ecc, NULL, hsmClientDevIdPubKey); +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ + defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + ret = wc_ecc_init_ex(&ecc, NULL, hsmDevIdPubKey); #else ret = wc_ecc_init(&ecc); #endif @@ -235,12 +238,15 @@ static void wolfBoot_verify_signature_ecc(uint8_t key_slot, sig, ECC_IMAGE_SIGNATURE_SIZE, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, &verify_res, &ecc) - #elif defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) + #elif defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ + defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) uint8_t tmpSigBuf[ECC_MAX_SIG_SIZE] = {0}; size_t tmpSigSz = sizeof(tmpSigBuf); - #if defined(WOLFBOOT_USE_WOLFHSM_PUBKEY_ID) + #if defined(WOLFBOOT_USE_WOLFHSM_PUBKEY_ID) || \ + (defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) && \ + defined(WOLFBOOT_CERT_CHAIN_VERIFY)) (void)key_slot; /* hardcoded, since not using keystore */ @@ -252,18 +258,27 @@ static void wolfBoot_verify_signature_ecc(uint8_t key_slot, * key ID */ if (g_leafKeyIdValid) { /* Use the leaf key ID from certificate verification */ + #if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) ret = wh_Client_EccSetKeyId(&ecc, g_certLeafKeyId); + #elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + ret = wh_Server_EccKeyCacheExport(&hsmServerCtx, g_certLeafKeyId, + &ecc); + #endif wolfBoot_printf( "Using leaf cert public key (ID: %08x) for ECC verification\n", (unsigned int)g_certLeafKeyId); } else { /* Default behavior: use the pre-configured public key ID */ - ret = wh_Client_EccSetKeyId(&ecc, hsmClientKeyIdPubKey); + #if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) + ret = wh_Client_EccSetKeyId(&ecc, hsmKeyIdPubKey); + #endif } #else - ret = wh_Client_EccSetKeyId(&ecc, hsmClientKeyIdPubKey); - #endif + #if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) + ret = wh_Client_EccSetKeyId(&ecc, hsmKeyIdPubKey); + #endif + #endif /* WOLFBOOT_USE_WOLFHSM_PUBKEY_ID */ if (ret != 0) { return; } @@ -297,7 +312,11 @@ static void wolfBoot_verify_signature_ecc(uint8_t key_slot, } #if defined(WOLFBOOT_CERT_CHAIN_VERIFY) if (g_leafKeyIdValid) { + #if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) (void)wh_Client_KeyEvict(&hsmClientCtx, g_certLeafKeyId); + #elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + (void)wh_Server_KeystoreEvictKey(&hsmServerCtx, g_certLeafKeyId); + #endif g_leafKeyIdValid = 0; } #endif @@ -395,7 +414,8 @@ static void wolfBoot_verify_signature_rsa(uint8_t key_slot, word32 inOutIdx = 0; struct RsaKey rsa; -#if !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ +#if (!defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ + !defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER)) || \ (defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \ !defined(WOLFBOOT_USE_WOLFHSM_PUBKEY_ID)) uint8_t *pubkey = keystore_get_buffer(key_slot); @@ -420,30 +440,39 @@ static void wolfBoot_verify_signature_rsa(uint8_t key_slot, wolfBoot_image_confirm_signature_ok(img); } (void)digest_out; -#elif defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) - ret = wc_InitRsaKey_ex(&rsa, NULL, hsmClientDevIdPubKey); +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ + defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + ret = wc_InitRsaKey_ex(&rsa, NULL, hsmDevIdPubKey); if (ret != 0) { return; } -#if defined(WOLFBOOT_USE_WOLFHSM_PUBKEY_ID) +#if defined(WOLFBOOT_USE_WOLFHSM_PUBKEY_ID) || \ + (defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) && \ + defined(WOLFBOOT_CERT_CHAIN_VERIFY)) (void)key_slot; - /* public key is stored on server at hsmClientKeyIdPubKey*/ + /* public key is stored on server at hsmKeyIdPubKey*/ #if defined(WOLFBOOT_CERT_CHAIN_VERIFY) /* If using certificate chain verification and we have a verified leaf key * ID */ if (g_leafKeyIdValid) { /* Use the leaf key ID from certificate verification */ +#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) ret = wh_Client_RsaSetKeyId(&rsa, g_certLeafKeyId); +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + ret = wh_Server_CacheExportRsaKey(&hsmServerCtx, g_certLeafKeyId, &rsa); +#endif wolfBoot_printf( "Using leaf cert public key (ID: %08x) for RSA verification\n", (unsigned int)g_certLeafKeyId); } else { +#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) /* Default behavior: use the pre-configured public key ID */ - ret = wh_Client_RsaSetKeyId(&rsa, hsmClientKeyIdPubKey); + ret = wh_Client_RsaSetKeyId(&rsa, hsmKeyIdPubKey); +#endif } #else - ret = wh_Client_RsaSetKeyId(&rsa, hsmClientKeyIdPubKey); + ret = wh_Client_RsaSetKeyId(&rsa, hsmKeyIdPubKey); #endif if (ret != 0) { return; @@ -472,7 +501,11 @@ static void wolfBoot_verify_signature_rsa(uint8_t key_slot, } #elif defined(WOLFBOOT_CERT_CHAIN_VERIFY) if (g_leafKeyIdValid) { +#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) (void)wh_Client_KeyEvict(&hsmClientCtx, g_certLeafKeyId); +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + (void)wh_Server_KeystoreEvictKey(&hsmServerCtx, g_certLeafKeyId); +#endif g_leafKeyIdValid = 0; } #endif /* !WOLFBOOT_USE_WOLFHSM_PUBKEY_ID */ @@ -671,7 +704,7 @@ static void wolfBoot_verify_signature_ml_dsa(uint8_t key_slot, #endif #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT - ret = wc_MlDsaKey_Init(&ml_dsa, NULL, hsmClientDevIdPubKey); + ret = wc_MlDsaKey_Init(&ml_dsa, NULL, hsmDevIdPubKey); #else ret = wc_MlDsaKey_Init(&ml_dsa, NULL, INVALID_DEVID); #endif @@ -705,10 +738,10 @@ static void wolfBoot_verify_signature_ml_dsa(uint8_t key_slot, } else { /* Default behavior: use the pre-configured public key ID */ - ret = wh_Client_MlDsaSetKeyId(&ml_dsa, hsmClientKeyIdPubKey); + ret = wh_Client_MlDsaSetKeyId(&ml_dsa, hsmKeyIdPubKey); } #else - ret = wh_Client_MlDsaSetKeyId(&ml_dsa, hsmClientKeyIdPubKey); + ret = wh_Client_MlDsaSetKeyId(&ml_dsa, hsmKeyIdPubKey); #endif if (ret != 0) { wolfBoot_printf("error: wh_Client_MlDsaSetKeyId returned %d\n", ret); @@ -898,7 +931,7 @@ static int header_sha256(wc_Sha256 *sha256_ctx, struct wolfBoot_image *img) if (stored_sha_len != WOLFBOOT_SHA_DIGEST_SIZE) return -1; #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT - (void)wc_InitSha256_ex(sha256_ctx, NULL, hsmClientDevIdHash); + (void)wc_InitSha256_ex(sha256_ctx, NULL, hsmDevIdHash); #else wc_InitSha256(sha256_ctx); #endif @@ -989,7 +1022,7 @@ static int header_sha384(wc_Sha384 *sha384_ctx, struct wolfBoot_image *img) if (stored_sha_len != WOLFBOOT_SHA_DIGEST_SIZE) return -1; #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT - (void)wc_InitSha384_ex(sha384_ctx, NULL, hsmClientDevIdHash); + (void)wc_InitSha384_ex(sha384_ctx, NULL, hsmDevIdHash); #else wc_InitSha384(sha384_ctx); #endif @@ -1967,7 +2000,8 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) uint32_t image_part = 1U; int key_slot; #if defined(WOLFBOOT_CERT_CHAIN_VERIFY) && \ - defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) + (defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ + defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER)) uint8_t* cert_chain; uint16_t cert_chain_size; int32_t cert_verify_result; @@ -2038,7 +2072,8 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) CONFIRM_MASK_VALID(image_part, key_mask); #if defined(WOLFBOOT_CERT_CHAIN_VERIFY) && \ - defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) + (defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ + defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER)) /* Check for certificate chain in the image header */ cert_chain_size = get_header(img, HDR_CERT_CHAIN, &cert_chain); if (cert_chain_size > 0) { @@ -2047,17 +2082,28 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) /* Verify certificate chain using wolfHSM's verification API. Use DMA if * available in the wolfHSM configuration */ +#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) #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, - hsmClientNvmIdCertRootCA, &g_certLeafKeyId, &cert_verify_result); + &hsmClientCtx, cert_chain, cert_chain_size, hsmNvmIdCertRootCA, + &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, - hsmClientNvmIdCertRootCA, &g_certLeafKeyId, &cert_verify_result); + &hsmClientCtx, cert_chain, cert_chain_size, hsmNvmIdCertRootCA, + &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, + WH_CERT_FLAGS_CACHE_LEAF_PUBKEY, &g_certLeafKeyId); + if (hsm_ret == WH_ERROR_OK) { + cert_verify_result = 0; + } + wolfBoot_printf("wh_Server_CertVerify returned %d\n", hsm_ret); #endif /* Error or verification failure results in standard auth check failure diff --git a/src/loader.c b/src/loader.c index 5b0b6aecff..2dd79648e3 100644 --- a/src/loader.c +++ b/src/loader.c @@ -109,6 +109,10 @@ int main(void) if (0 != hal_hsm_init_connect()) { wolfBoot_panic(); } +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + if (0 != hal_hsm_server_init()) { + wolfBoot_panic(); + } #endif spi_flash_probe(); #ifdef UART_FLASH diff --git a/src/update_disk.c b/src/update_disk.c index a90cf4829f..39cb359871 100644 --- a/src/update_disk.c +++ b/src/update_disk.c @@ -223,6 +223,8 @@ void RAMFUNCTION wolfBoot_start(void) wolfBoot_printf("Booting at %08lx\r\n", os_image.fw_base); #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT (void)hal_hsm_disconnect(); +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + (void)hal_hsm_server_cleanup(); #endif hal_prepare_boot(); do_boot((uint32_t*)os_image.fw_base); diff --git a/src/update_flash.c b/src/update_flash.c index c1d339014d..5ea4baf23d 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -1132,6 +1132,8 @@ void RAMFUNCTION wolfBoot_start(void) #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT (void)hal_hsm_disconnect(); +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + (void)hal_hsm_server_cleanup(); #endif hal_prepare_boot(); do_boot((void *)boot.fw_base); diff --git a/src/update_flash_hwswap.c b/src/update_flash_hwswap.c index 045cb182e6..de0fecbbeb 100644 --- a/src/update_flash_hwswap.c +++ b/src/update_flash_hwswap.c @@ -100,6 +100,8 @@ void RAMFUNCTION wolfBoot_start(void) #endif #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT (void)hal_hsm_disconnect(); +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + (void)hal_hsm_server_cleanup(); #endif hal_prepare_boot(); do_boot((void *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + IMAGE_HEADER_SIZE)); diff --git a/src/update_ram.c b/src/update_ram.c index 6237d72069..c314ffadac 100644 --- a/src/update_ram.c +++ b/src/update_ram.c @@ -344,6 +344,8 @@ void RAMFUNCTION wolfBoot_start(void) #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT (void)hal_hsm_disconnect(); +#elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) + (void)hal_hsm_server_cleanup(); #endif hal_prepare_boot(); diff --git a/test-app/Makefile b/test-app/Makefile index 06e6dddd5a..4e4acab52c 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -463,7 +463,13 @@ CFLAGS+=-I../lib/wolfssl ifeq ($(WOLFHSM_CLIENT),1) CFLAGS += -DWOLFSSL_USER_SETTINGS -DSTRING_USER -I../lib/wolfssl - APP_OBJS += $(WOLFHSM_CLIENT_OBJS) + APP_OBJS += $(WOLFHSM_OBJS) + APP_OBJS += $(sort $(patsubst ./lib/wolfssl/%, ../lib/wolfssl/%, $(WOLFCRYPT_OBJS))) +endif + +ifeq ($(WOLFHSM_SERVER),1) + CFLAGS += -DWOLFSSL_USER_SETTINGS -DSTRING_USER -I../lib/wolfssl + APP_OBJS += $(WOLFHSM_OBJS) APP_OBJS += $(sort $(patsubst ./lib/wolfssl/%, ../lib/wolfssl/%, $(WOLFCRYPT_OBJS))) endif