Skip to content

Commit 7660bf6

Browse files
committed
Add wolfHSM cert chain verification for ECC and RSA
1 parent 2b996f8 commit 7660bf6

File tree

17 files changed

+750
-70
lines changed

17 files changed

+750
-70
lines changed

.github/workflows/test-wolfhsm-simulator.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ jobs:
1818
file: "config/examples/sim-wolfHSM.config"
1919
- name: "wolfHSM ML-DSA"
2020
file: "config/examples/sim-wolfHSM-mldsa.config"
21+
- name: "wolfHSM cert chain verify"
22+
file: "config/examples/sim-wolfHSM-certchain.config"
2123
fail-fast: false
2224

2325
runs-on: ubuntu-latest
@@ -54,8 +56,7 @@ jobs:
5456
with:
5557
repository: wolfssl/wolfHSM-examples
5658
# Make sure to update this when the wolfHSM submodule is updated!
57-
#ref: wolfHSM-v1.1.0
58-
ref: 3e03bd4d4a8439ed4a8a9577823c89e4c37eb9be
59+
ref: wolfHSM-examples-v1.2.0
5960
path: wolfHSM-examples
6061

6162
- name: Build example POSIX TCP server
@@ -65,7 +66,13 @@ jobs:
6566
- name: Run POSIX TCP server
6667
run: |
6768
cd wolfHSM-examples/posix/tcp/wh_server_tcp
68-
./Build/wh_server_tcp.elf --client 12 --id 255 --key ../../../../wolfboot_signing_private_key_pub.der &
69+
if [ "${{ matrix.config.name }}" = "wolfHSM cert chain verify" ]; then
70+
tmpfile=$(mktemp)
71+
echo "obj 1 0xFFFF 0x0000 \"cert CA\" ../../../../test-dummy-ca/root-cert.der" >> $tmpfile
72+
./Build/wh_server_tcp.elf --nvminit $tmpfile &
73+
else
74+
./Build/wh_server_tcp.elf --client 12 --id 255 --key ../../../../wolfboot_signing_private_key_pub.der --cert ../../../../wolfboot_signing_cert_chain.der &
75+
fi
6976
TCP_SERVER_PID=$!
7077
echo "TCP_SERVER_PID=$TCP_SERVER_PID" >> $GITHUB_ENV
7178

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ include/target.h
9999
.wolfboot-partition-size
100100
.bootloader-partition-size
101101
MPLabX/wolfBoot-SAME51.X/.generated_files/
102+
test-dummy-ca/**
102103

103104
# Test tools
104105
tools/check_config/check_config

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ $(PRIVATE_KEY):
229229
$(Q)(test $(SIGN) = NONE) || ($(SIGN_ENV) "$(KEYGEN_TOOL)" $(KEYGEN_OPTIONS) -g $(PRIVATE_KEY)) || true
230230
$(Q)(test $(SIGN) = NONE) && (echo "// SIGN=NONE" > src/keystore.c) || true
231231
$(Q)(test "$(FLASH_OTP_KEYSTORE)" = "1") && (make -C tools/keytools/otp) || true
232+
$(Q)(test $(SIGN) = NONE) || (test "$(CERT_CHAIN_VERIFY)" = "") || (test "$(CERT_CHAIN_GEN)" = "") || (tools/scripts/sim-gen-dummy-chain.sh --algo $(CERT_CHAIN_GEN_ALGO) --leaf $(PRIVATE_KEY))
232233

233234
$(SECONDARY_PRIVATE_KEY): $(PRIVATE_KEY) keystore.der
234235
$(Q)$(MAKE) keytools_check
@@ -390,6 +391,7 @@ utilsclean: clean
390391

391392
keysclean: clean
392393
$(Q)rm -f *.pem *.der tags ./src/*_pub_key.c ./src/keystore.c include/target.h
394+
$(Q)(test "$(CERT_CHAIN_GEN)" = "") || rm -rf test-dummy-ca || true
393395

394396
distclean: clean keysclean utilsclean
395397
$(Q)rm -f *.bin *.elf
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
ARCH=sim
2+
TARGET=sim
3+
SIGN?=ECC256
4+
HASH?=SHA256
5+
WOLFBOOT_SMALL_STACK?=0
6+
SPI_FLASH=0
7+
DEBUG=1
8+
9+
# Cert chain options
10+
CERT_CHAIN_VERIFY=1
11+
CERT_CHAIN_GEN=1
12+
13+
# Ensure header is large enough to hold the cert chain (check sign tool output)
14+
# for actual length
15+
IMAGE_HEADER_SIZE=2048
16+
17+
# If SIGN=RSA4096, use the below options
18+
#WOLFBOOT_HUGE_STACK=1
19+
#IMAGE_HEADER_SIZE=4096
20+
21+
# wolfHSM options
22+
WOLFHSM_CLIENT=1
23+
24+
# sizes should be multiple of system page size
25+
#WOLFBOOT_PARTITION_SIZE=0x40000
26+
WOLFBOOT_PARTITION_SIZE=0x100000
27+
WOLFBOOT_SECTOR_SIZE=0x1000
28+
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80000
29+
# if on external flash, it should be multiple of system page size
30+
#WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x100000
31+
#WOLFBOOT_PARTITION_SWAP_ADDRESS=0x180000
32+
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x180000
33+
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x280000
34+
35+
# required for keytools
36+
WOLFBOOT_FIXED_PARTITIONS=1
37+
38+
# For debugging XMALLOC/XFREE
39+
#CFLAGS_EXTRA+=-DWOLFBOOT_DEBUG_MALLOC

docs/Signing.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ If none of the following is used, '--sha256' is assumed by default.
119119

120120
* `--sha3` Use sha3-384 for digest calculation on binary images and public keys.
121121

122+
#### Certificate Chain Options
123+
124+
wolfBoot also supports verifying firmware images using certificate chains instead of raw public keys. In this mode of operation, a certificate chain is included in the image manifest header, and the image is signed with the private key corresponding to the leaf certificate identity (signer cert). On boot, wolfBoot verifies the trust of the certificate chain (and therefore the signer cert) against a trusted root CA stored in the wolfHSM server, and if the chain is trusted, verifies the authenticity of the firmware image using the public key from the image signer certificate.
125+
126+
To generate an image for use with this mode, pass the `--cert-chain CERT_CHAIN.der` option to the sign tool, where `CERT_CHAIN.der` is a der encoded certificate chain containing one or more certificates in SSL order (leaf/signer cert last). Note that the sign tool still expects a signing private key to be provided as described above, and assumes that the public key of the signer cert in the chain corresponds to the signing private key.
127+
128+
Certificate chain verification of images is currently limited to use in conjuction with wolfHSM. See [wolfHSM.md](wolfHSM.md) for more details.
129+
122130
#### Target partition id (Multiple partition images, "self-update" feature)
123131

124132
If none of the following is used, "--id=1" is assumed by default. On systems
@@ -257,7 +265,7 @@ For a real-life example, see the section below.
257265
./tools/keytools/sign --rsa2048 --sha256 test-app/image.bin wolfboot_signing_private_key.der 1
258266
```
259267

260-
Note: The last argument is the version number.
268+
Note: The last argument is the "version" number.
261269

262270
### Signing Firmware with External Private Key (HSM)
263271

docs/firmware_update.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,26 @@ Note: When using scattered ELF images, ensure that:
221221

222222
- The ELF file adheres to the ELF file specification and was generated by a toolchain supporting the target architecture
223223
- All section addresses are within valid executable memory regions and **do not overlap with the wolfBoot image, nor the BOOT, UPDATE and SWAP partitions**.
224+
225+
## Certificate Verification
226+
227+
wolfBoot supports authenticating images using certificate chains instead of raw public keys. in this mode of operation, a certificate chain is included in the image manifest header, and the image is signed with the private key corresponding to the leaf certificate identity (signer cert). On boot, wolfBoot verifies the trust of the certificate chain (and therefore the signer cert) against a trusted root CA stored in the wolfHSM server, and if the chain is trusted, verifies the authenticity of the firmware image using the public key from the image signer certificate.
228+
229+
To use this feature:
230+
231+
1. Enable the feature in your wolfBoot configuration by defining `WOLFBOOT_CERT_CHAIN_VERIFY`
232+
2. When signing firmware, include the certificate chain using the `--cert-chain` option:
233+
234+
```sh
235+
./tools/keytools/sign --rsa2048 --sha256 --cert-chain cert_chain.der test-app/image.bin private_key.der 1
236+
```
237+
238+
When verifying firmware, wolfBoot will:
239+
240+
1. Extract the certificate chain from the firmware header
241+
2. Verify the chain using the pre-provisioned root certificate
242+
3. Use the public key from the leaf certificate to verify the firmware signature
243+
244+
This feature is particularly useful in scenarios where you want to rotate signing keys without updating the bootloader, as you can simply resign the image with a new key, create a new certificate chain, then update the certificate chain in the firmware header.
245+
246+
Note: Currently, support for certificate verification is limited to use in conjuction with wolfHSM. Fore more information see [wolfHSM.md](wolfHSM.md).

docs/wolfHSM.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,34 @@ wolfBoot supports using wolfHSM for the following algorithms:
3131

3232
Encrypted images with wolfHSM is not yet supported in wolfBoot. Note that every HAL target may not support all of these algorithms. Consult the platform-specific wolfBoot documentation for details.
3333

34+
## Additional Features
35+
36+
wolfBoot with wolfHSM also supports the following features:
37+
38+
### Certificate Verification
39+
40+
wolfBoot with wolfHSM supports certificate chain verification for firmware images. In this mode, instead of using raw public keys for signature verification, wolfBoot verifies firmware images using wolfHSM with a public key embedded in a certificate chain that is included in the image manifest header.
41+
42+
The certificate verification process with wolfHSM works as follows:
43+
44+
1. A root CA is created serving as the root of trust for the entire PKI system
45+
2. A signing keypair and corresponding identity certificate is created for signing firmware images
46+
3. The firmware image is signed with the signing private key
47+
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.
48+
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.
49+
6. During boot, wolfBoot extracts the certificate chain from the firmware header
50+
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
51+
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
52+
53+
To use certificate verification with wolfHSM:
54+
55+
1. Enable `WOLFBOOT_CERT_CHAIN_VERIFY` in your wolfBoot configuration
56+
2. Ensure the wolfHSM server is configured with certificate manager support (`WOLFHSM_CFG_CERTIFICATE_MANAGER`)
57+
3. Pre-provision the root CA certificate on the wolfHSM server at the NVM ID specified by the HAL `hsmClientNvmIdCertRootCA`
58+
4. Sign firmware images with the `--cert-chain` option, providing a DER-encoded certificate chain
59+
60+
To build the simulator using wolfHSM for certificate verification, use [config/examples/sim-wolfHSM-certchain.config](config/examples/sim-wolfHSM-certchain.config).
61+
3462
## Configuration Options
3563

3664
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.

hal/sim.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ const int hsmClientKeyIdPubKey = 0xFF;
100100
const int hsmClientDevIdCrypt = WH_DEV_ID;
101101
const int hsmClientKeyIdCrypt = 0xFF;
102102
#endif
103+
#ifdef WOLFBOOT_CERT_CHAIN_VERIFY
104+
const int hsmClientNvmIdCertRootCA = 1;
105+
#endif
103106

104107
int hal_hsm_init_connect(void);
105108
int hal_hsm_disconnect(void);

include/hal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ extern const int hsmClientKeyIdPubKey; /* KeyId for public key operations */
161161
#ifdef EXT_ENCRYPTED
162162
extern const int hsmClientKeyIdCrypt; /* KeyId for image (enc/dec)ryption */
163163
#endif
164+
#ifdef WOLFBOOT_CERT_CHAIN_VERIFY
165+
/* NvmId for trusted root CA certificate */
166+
extern const whNvmId hsmClientNvmIdCertRootCA;
167+
#endif
164168

165169
/* Implementation of functions provided by HAL */
166170
int hal_hsm_init_connect(void);

include/wolfboot/wolfboot.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ extern "C" {
7979
#define HDR_SIGNATURE 0x20
8080
#define HDR_POLICY_SIGNATURE 0x21
8181
#define HDR_SECONDARY_SIGNATURE 0x22
82+
#define HDR_CERT_CHAIN 0x23
8283
#define HDR_PADDING 0xFF
8384

8485
/* Auth Key types */

0 commit comments

Comments
 (0)