Skip to content

Commit 32a81dd

Browse files
Add hardware-based DICE on mcxn
1 parent c3d255d commit 32a81dd

20 files changed

Lines changed: 1333 additions & 32 deletions

File tree

.github/workflows/test-configs.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,20 @@ jobs:
273273
config-file: ./config/examples/mcxn-wolfcrypt-tz.config
274274
board-name: frdmmcxn947
275275

276+
nxp_mcxn_tz_psa_test:
277+
uses: ./.github/workflows/test-build-mcux-sdk-manifests.yml
278+
with:
279+
arch: arm
280+
config-file: ./config/examples/mcxn-tz-psa.config
281+
board-name: frdmmcxn947
282+
283+
nxp_mcxn_tz_psa_hw_test:
284+
uses: ./.github/workflows/test-build-mcux-sdk-manifests.yml
285+
with:
286+
arch: arm
287+
config-file: ./config/examples/mcxn-tz-psa-hw.config
288+
board-name: frdmmcxn947
289+
276290
nxp_s32k142_test:
277291
uses: ./.github/workflows/test-build.yml
278292
with:

arch.mk

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,20 @@ ifeq ($(TARGET),mcxn)
974974
$(MCUXPRESSO)/drivers/lpuart/fsl_lpuart.o \
975975
$(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o
976976
endif
977+
978+
ifeq ($(WOLFCRYPT_TZ_PSA),1)
979+
ELS_PKC=$(MCUXPRESSO)/components/els_pkc
980+
CFLAGS+=\
981+
-I$(ELS_PKC)/includes \
982+
-I$(ELS_PKC)/src/comps/mcuxClEls/inc \
983+
-I$(ELS_PKC)/src/platforms/mcxn \
984+
-I$(ELS_PKC)/src/platforms/mcxn/inc
985+
OBJS+=\
986+
$(ELS_PKC)/src/comps/mcuxClEls/src/mcuxClEls_Common.o \
987+
$(ELS_PKC)/src/comps/mcuxClEls/src/mcuxClEls_Kdf.o \
988+
$(ELS_PKC)/src/comps/mcuxClEls/src/mcuxClEls_KeyManagement.o \
989+
$(ELS_PKC)/src/comps/mcuxClEls/src/mcuxClEls_Ecc.o
990+
endif
977991
endif
978992

979993
ifeq ($(TARGET),nrf5340)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
ARCH?=ARM
2+
TZEN?=1
3+
TARGET?=mcxn
4+
SIGN?=ECC384
5+
HASH?=SHA384
6+
MCUXSDK?=1
7+
MCUXPRESSO?=$(PWD)/../NXP/mcuxpresso-sdk/mcuxsdk
8+
MCUXPRESSO_CMSIS?=$(PWD)/../NXP/CMSIS_5/CMSIS
9+
MCUXPRESSO_CPU?=MCXN947VDF_cm33_core0
10+
MCUXPRESSO_DRIVERS?=$(MCUXPRESSO)/devices/MCX/MCXN/MCXN947
11+
MCUXPRESSO_PROJECT_TEMPLATE?=$(MCUXPRESSO)/examples/_boards/frdmmcxn947/project_template
12+
DEBUG?=0
13+
DEBUG_UART?=1
14+
VTOR?=1
15+
CORTEX_M0?=0
16+
CORTEX_M33?=1
17+
NO_ASM?=0
18+
NO_MPU=1
19+
EXT_FLASH?=0
20+
SPI_FLASH?=0
21+
ALLOW_DOWNGRADE?=0
22+
NVM_FLASH_WRITEONCE?=1
23+
NO_ARM_ASM=1
24+
WOLFBOOT_VERSION?=0
25+
V?=0
26+
SPMATH?=1
27+
RAM_CODE?=1
28+
DUALBANK_SWAP?=0
29+
PKA?=1
30+
WOLFCRYPT_TZ?=1
31+
WOLFCRYPT_TZ_PSA?=1
32+
WOLFCRYPT_SECURE_MODE?=1
33+
WOLFBOOT_DICE_HW?=1
34+
IMAGE_HEADER_SIZE?=1024
35+
WOLFBOOT_ATTESTATION_TEST?=1
36+
WOLFBOOT_UDS_UID_FALLBACK_FORTEST?=0
37+
38+
# 8KB sectors
39+
WOLFBOOT_SECTOR_SIZE?=0x2000
40+
41+
# Default configuration
42+
# 192KB boot, 96KB keyvault, 8KB NSC, 72KB partitions, 8KB swap
43+
WOLFBOOT_KEYVAULT_ADDRESS?=0x30000
44+
WOLFBOOT_KEYVAULT_SIZE?=0x18000
45+
WOLFBOOT_NSC_ADDRESS?=0x48000
46+
WOLFBOOT_NSC_SIZE?=0x2000
47+
WOLFBOOT_PARTITION_SIZE?=0x12000
48+
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x60000
49+
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x72000
50+
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x84000

config/examples/mcxn-tz-psa.config

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
ARCH?=ARM
2+
TZEN?=1
3+
TARGET?=mcxn
4+
SIGN?=ECC384
5+
HASH?=SHA384
6+
MCUXSDK?=1
7+
MCUXPRESSO?=$(PWD)/../NXP/mcuxpresso-sdk/mcuxsdk
8+
MCUXPRESSO_CMSIS?=$(PWD)/../NXP/CMSIS_5/CMSIS
9+
MCUXPRESSO_CPU?=MCXN947VDF_cm33_core0
10+
MCUXPRESSO_DRIVERS?=$(MCUXPRESSO)/devices/MCX/MCXN/MCXN947
11+
MCUXPRESSO_PROJECT_TEMPLATE?=$(MCUXPRESSO)/examples/_boards/frdmmcxn947/project_template
12+
DEBUG?=0
13+
DEBUG_UART?=1
14+
VTOR?=1
15+
CORTEX_M0?=0
16+
CORTEX_M33?=1
17+
NO_ASM?=0
18+
NO_MPU=1
19+
EXT_FLASH?=0
20+
SPI_FLASH?=0
21+
ALLOW_DOWNGRADE?=0
22+
NVM_FLASH_WRITEONCE?=1
23+
NO_ARM_ASM=1
24+
WOLFBOOT_VERSION?=0
25+
V?=0
26+
SPMATH?=1
27+
RAM_CODE?=1
28+
DUALBANK_SWAP?=0
29+
PKA?=1
30+
WOLFCRYPT_TZ?=1
31+
WOLFCRYPT_TZ_PSA?=1
32+
WOLFCRYPT_SECURE_MODE?=1
33+
WOLFBOOT_DICE_HW?=0
34+
IMAGE_HEADER_SIZE?=1024
35+
WOLFBOOT_ATTESTATION_TEST?=1
36+
WOLFBOOT_UDS_UID_FALLBACK_FORTEST?=1
37+
38+
# 8KB sectors
39+
WOLFBOOT_SECTOR_SIZE?=0x2000
40+
41+
# Default configuration
42+
# 192KB boot, 96KB keyvault, 8KB NSC, 72KB partitions, 8KB swap
43+
WOLFBOOT_KEYVAULT_ADDRESS?=0x30000
44+
WOLFBOOT_KEYVAULT_SIZE?=0x18000
45+
WOLFBOOT_NSC_ADDRESS?=0x48000
46+
WOLFBOOT_NSC_SIZE?=0x2000
47+
WOLFBOOT_PARTITION_SIZE?=0x12000
48+
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x60000
49+
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x72000
50+
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x84000

docs/DICE.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ measurement value, and a description string.
3434

3535
## Keying model
3636

37-
wolfBoot supports two keying modes selected at build time.
37+
wolfBoot supports three keying modes selected at build time.
3838

3939
### DICE derived key (default for no provisioning)
4040

@@ -55,6 +55,17 @@ The attestation service calls `hal_attestation_get_iak_private_key()` to
5555
retrieve the private key material from secure storage (or a manufacturer
5656
injection flow). The IAK is used instead of the DICE derived key.
5757

58+
### Hardware-based DICE derived key
59+
60+
Some platforms have secure subsystem which supports hardware engines for DICE functionality.
61+
Some of them don't expose the secrets like UDS, CDI and attestation key.
62+
In that case, You can enable hardware-based DICE using `WOLFBOOT_DICE_HW` option.
63+
64+
wolfBoot calls `hal_dice_update_cdi()` to update CDI inside secure subsystem for each component.
65+
Also, `hal_dice_create_attest_key()` is called to derive the attestation key from updated CDI as well.
66+
Then, wolfBoot uses `hal_dice_sign_hash` to sign the token.
67+
User can implement hardware-specific procedures inside the hooks.
68+
5869
## HAL integration (per-target)
5970

6071
These HAL hooks are optional and have weak stubs for non-TZ boards. Target
@@ -76,6 +87,21 @@ families must implement the appropriate subset based on hardware support.
7687
- `hal_attestation_get_iak_private_key(uint8_t *buf, size_t *len)`
7788
- Optional provisioned IAK private key (used in IAK mode only).
7889

90+
If you enable hardware-based DICE, additional hooks are necessary.
91+
92+
- ` hal_dice_update_cdi(const uint8_t *measurement, size_t meas_len, const char *measurement_desc, size_t measurement_desc_len)`
93+
- Mixes one boot-component measurement into the platform CDI chain.
94+
- measurement_desc identifies the component (e.g. "wolfboot", "boot-image").
95+
- `hal_dice_create_attest_key(void)`
96+
- Derive and store the attestation key pair from the current CDI state.
97+
- The private key must not be exposed outside the platform security boundary.
98+
- `hal_dice_sign_hash(const uint8_t *hash, size_t hash_len, uint8_t *sig, size_t *sig_len)`
99+
- Sign a pre-computed SHA-256 hash with the platform private attestation key during token generation.
100+
- Output: 64-byte raw R||S (big-endian), same format as wolfCrypt ES256.
101+
- `hal_dice_get_attest_pubkey(uint8_t *buf, size_t *len)`
102+
- Optional hook to get the public part of attestation key.
103+
- This is called via PSA Initial Attestation dispatch `psa_initial_attest_get_iak_pubkey()`.
104+
79105
## STM32H5 OBKeys UDS (optional)
80106

81107
STM32H5 devices provide OBKeys secure storage areas tied to temporal isolation
@@ -103,6 +129,7 @@ The non-secure application calls the PSA Initial Attestation API wrappers:
103129

104130
- `psa_initial_attest_get_token_size()`
105131
- `psa_initial_attest_get_token()`
132+
- `psa_initial_attest_get_iak_pubkey()`
106133

107134
These are provided in `zephyr/include/psa/initial_attestation.h` and are
108135
implemented as NSC calls in `zephyr/src/arm_tee_attest_api.c`.
@@ -114,9 +141,15 @@ When `WOLFCRYPT_TZ_PSA=1`, the NS application can also use PSA Crypto through
114141

115142
## Test application
116143

144+
### STM32H5
117145
The STM32H5 TrustZone test application in `test-app/` exercises PSA crypto,
118146
attestation, and store access. It requests a token at boot and can perform
119147
PSA crypto operations from the non-secure side.
120148

121149
See `docs/Targets.md` for the STM32H5 TrustZone scenarios and how to enable
122150
PSA mode.
151+
152+
### MCXN
153+
MCXN has TrustZone test application in `test-app/` exercises PSA attestation.
154+
Default setting is based on hardware secure subsystem called EdgeLock Secure Subsystem.
155+
See `docs/Targets.md` and `docs/MCXN947-DICE.md` for details.

docs/MCXN947-DICE.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# DICE attestation sample on MCXN947
2+
3+
General concept of wolfBoot in TrustZone secure domain is explained in `docs/STM32-TZ.md`.
4+
This focuses on a sample of PSA initial attestation for MCXN947.
5+
Sample application is implemented in `test-app/app_mcxn.c`.
6+
This supports hardware-based DICE using EdgeLock Secure Subsystem.
7+
8+
## How to build
9+
Please use `config/examples/mcxn-tz-psa-hw.config` to build wolfBoot.
10+
You need to update the path of SDK inside the config for your build environment.
11+
```
12+
cp config/examples/mcxn-tz-psa-hw.config .config
13+
make
14+
```
15+
16+
## How to run
17+
MCXN947 requires us to enable secure boot to use DICE functionality of ELS.
18+
So, We need to prepare the specific image file of wolfBoot binary and configuration files of CMPA/CFPA for secure bootROM and ELS.
19+
Fortunately NXP provides the [secure provisioning tool](https://www.nxp.com/design/design-center/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-secure-provisioning-tool:MCUXPRESSO-SECURE-PROVISIONING) for such purpose.
20+
21+
At a minimum, you shall configure the following settings and encode the image with signature:
22+
- Enable Image verification for secure boot (SEC_BOOT_EN == 0b10)
23+
- Enable DICE (SKIP_DICE == 0b0)
24+
All of these can be done using the NXP secure provisioning tool.
25+
26+
If you use secure provisioning tool, you can download the prepared image with configuration files to hardware as well.
27+
Regarding to application image like image_v1_signed.bin, we don't need to encode it like the wolfBoot binary because it's verified by wolfBoot as usual.
28+
But, we still recommend you to download the application image using the flash programmer tool in the secure provisioning tool for a safe download. You can access it via `Tools > Flash Programmer` on GUI.
29+
30+
Once both images are downloaded successfully, you'll see the log after reboot:
31+
```
32+
Boot partition: 0x60000 (sz 31508, ver 0x1, type 0x601)
33+
Partition 1 header magic 0xFFFFFFFF invalid at 0x72000
34+
Boot partition: 0x60000 (sz 31508, ver 0x1, type 0x601)
35+
Booting version: 0x1
36+
Checking integrity...done
37+
Verifying signature...done
38+
Hello from firmware version 1
39+
Today's lucky number: 0xAF
40+
PSA crypto init ok
41+
Start attestation verify test
42+
[ATTEST] GET_TOKEN: challenge_len=32 out_len=1024
43+
Boot partition: 0x60000 (sz 31508, ver 0x1, type 0x601)
44+
Boot partition: 0x60000 (sz 31508, ver 0x1, type 0x601)
45+
[ATTEST] GET_TOKEN: dice_rc=0 token_len=356
46+
attest_verify: token_len=356
47+
84 43 A1 01 26 A0 59 01 19 A5 0A 58 20 01 02 03 | .C..&.Y....X ...
48+
04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 | ................
49+
14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 19 01 00 | ............ ...
50+
58 21 01 AD 74 46 22 0C D0 5B 7A 1B 33 5E 37 28 | X!..tF"..[z.3^7(
51+
0A 54 E6 DF 55 5B 40 A4 57 A0 43 0A 6D A5 AB E7 | .T..U[@.W.C.m...
52+
5A 2B 5F 19 09 5C 58 30 E4 F9 83 72 7F A9 C5 CE | Z+_..\X0...r....
53+
DD E0 79 A0 AD 0E 32 59 0A EA D3 10 43 BA 12 DD | ..y...2Y....C...
54+
76 47 59 D1 42 8B 3A 75 F2 7E 75 CF 7D EE A2 B9 | vGY.B.:u.~u.}...
55+
AA AB 7E E9 91 27 F7 21 19 09 5E 19 30 00 19 09 | ..~..'.!..^.0...
56+
5F 82 A3 01 67 73 68 61 2D 33 38 34 02 58 30 E4 | _...gsha-384.X0.
57+
F9 83 72 7F A9 C5 CE DD E0 79 A0 AD 0E 32 59 0A | ..r......y...2Y.
58+
EA D3 10 43 BA 12 DD 76 47 59 D1 42 8B 3A 75 F2 | ...C...vGY.B.:u.
59+
7E 75 CF 7D EE A2 B9 AA AB 7E E9 91 27 F7 21 05 | ~u.}.....~..'.!.
60+
68 77 6F 6C 66 62 6F 6F 74 A3 01 67 73 68 61 2D | hwolfboot..gsha-
61+
33 38 34 02 58 30 D4 F2 89 AD E4 4E 6E EB F4 C6 | 384.X0.....Nn...
62+
7D 24 13 AD 6C E6 DC A6 E9 FC 67 4F CC CB DE 52 | }$..l.....gO...R
63+
4D FD E2 73 9D 2A D7 B3 DD DF B8 51 F4 43 C5 59 | M..s.*.....Q.C.Y
64+
48 8A 30 46 D7 E3 05 6A 62 6F 6F 74 2D 69 6D 61 | H.0F...jboot-ima
65+
67 65 58 40 E8 3F 76 44 15 7C 62 76 33 56 6D F7 | geX@.?vD.|bv3Vm.
66+
2B E1 57 40 C4 F1 7D 21 D3 E9 90 57 25 8F A3 14 | +.W@..}!...W%...
67+
44 ED 1B CE 01 CA EF 52 6B 41 4C 44 DF 4E 04 D4 | D......RkALD.N..
68+
AA CC A8 7F 20 3D AA 39 CA 3A 9F C2 B1 C0 28 43 | .... =.9.:....(C
69+
DF BB 82 53 | ...S
70+
[ATTEST] GET_IAK_PUBKEY: out_len=65
71+
[ATTEST] GET_IAK_PUBKEY: dice_rc=0 key_len=65
72+
attest_verify: IAK pubkey (65 bytes):
73+
04 42 9B 43 75 BE B0 E9 A0 39 61 64 68 20 1E FC | .B.Cu....9adh ..
74+
B6 68 F4 3E 25 74 F1 E2 CB 3D BD 09 A6 45 A7 E2 | .h.>%t...=...E..
75+
6F E1 54 B8 20 61 96 79 6A E8 31 83 3A 82 DE 1C | o.T. a.yj.1.:...
76+
87 46 E1 45 49 3D 6F 56 78 F4 14 B6 42 47 DD F1 | .F.EI=oVx...BG..
77+
AC | .
78+
attest_verify: IAK signature verified OK
79+
```

docs/Targets.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6107,6 +6107,9 @@ mon reset
61076107
c
61086108
```
61096109
6110+
### MCX N: DICE attestation
6111+
Sample application for DICE attestation is available on MCXN947.
6112+
Please find the details in `docs/MCXN947-DICE.md`.
61106113
61116114
## NXP S32K1XX
61126115

hal/hal.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,38 @@ WEAKFUNCTION int hal_attestation_get_iak_private_key(uint8_t *buf, size_t *len)
321321
(void)len;
322322
return -1;
323323
}
324+
325+
#ifdef WOLFBOOT_DICE_HW
326+
WEAKFUNCTION int hal_dice_update_cdi(const uint8_t *measurement, size_t meas_len,
327+
const char *measurement_desc,
328+
size_t measurement_desc_len)
329+
{
330+
(void)measurement;
331+
(void)meas_len;
332+
(void)measurement_desc;
333+
(void)measurement_desc_len;
334+
return -1;
335+
}
336+
337+
WEAKFUNCTION int hal_dice_create_attest_key(void)
338+
{
339+
return -1;
340+
}
341+
342+
WEAKFUNCTION int hal_dice_sign_hash(const uint8_t *hash, size_t hash_len,
343+
uint8_t *sig, size_t *sig_len)
344+
{
345+
(void)hash;
346+
(void)hash_len;
347+
(void)sig;
348+
(void)sig_len;
349+
return -1;
350+
}
351+
352+
WEAKFUNCTION int hal_dice_get_attest_pubkey(uint8_t *buf, size_t *len)
353+
{
354+
(void)buf;
355+
(void)len;
356+
return -1;
357+
}
358+
#endif /* WOLFBOOT_DICE_HW */

0 commit comments

Comments
 (0)