Skip to content

Commit ca22d72

Browse files
committed
Add support for DICE attestation + PSA attestation
1 parent e380365 commit ca22d72

22 files changed

Lines changed: 2016 additions & 30 deletions

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,7 @@ set(WOLFBOOT_SOURCES "include/loader.h"
554554
"include/image.h"
555555
"src/string.c"
556556
"src/image.c"
557+
"src/dice/dice.c"
557558
"src/loader.c")
558559

559560
# build bin-assemble tool Windows

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ OBJS:= \
3434
./src/string.o \
3535
./src/image.o \
3636
./src/libwolfboot.o \
37+
./src/dice/dice.o \
3738
./hal/hal.o
3839

3940
ifneq ($(TARGET),library)

docs/STM32-TZ.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ The `WOLFCRYPT_TZ_PSA` option provides a standard PSA Crypto interface using
3333
wolfPSA in the secure domain. The key storage uses the same secure flash
3434
keystore backend as PKCS11, exposed through the wolfPSA store API.
3535

36+
### PSA Initial Attestation (DICE)
37+
38+
When `WOLFBOOT_TZ_PSA=1` is enabled, wolfBoot exposes the PSA Initial
39+
Attestation API to non-secure applications. The attestation token is built
40+
using the DICE flow in `src/dice/` and returned as a COSE_Sign1 token.
41+
42+
See [DICE Attestation](DICE.md) for the full protocol description, HAL hooks
43+
(UDS, UEID, lifecycle, implementation ID), and provisioned IAK support.
44+
3645
### Image header size
3746

3847
The `IMAGE_HEADER_SIZE` option has to be carefully tuned to accommodate for the

docs/Targets.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,10 @@ non-secure callables (NSC).
13791379

13801380
The example configuration for this scenario is available in [/config/examples/stm32h5-tz.config](/config/examples/stm32h5-tz.config).
13811381

1382+
When `WOLFBOOT_TZ_PSA=1` is enabled, the STM32H5 test application exercises PSA
1383+
Crypto, PSA Protected Storage, and PSA Initial Attestation from the non-secure
1384+
side. See [DICE Attestation](/docs/DICE.md) for details on the attestation flow
1385+
and APIs.
13821386
For more information, see [/docs/STM32-TZ.md](/docs/STM32-TZ.md).
13831387

13841388
### Scenario 3: DUALBANK mode

hal/hal.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "hal.h"
2626
#include "string.h"
2727
#include "printf.h"
28+
#include "wolfboot/wolfboot.h"
2829

2930
/* Test for internal flash erase/write */
3031
/* Use TEST_EXT_FLASH to test ext flash (see spi_flash.c or qspi_flash.c) */
@@ -280,3 +281,37 @@ int hal_flash_test_dualbank(void)
280281
#endif /* DUALBANK_SWAP */
281282

282283
#endif /* TEST_FLASH */
284+
285+
WEAKFUNCTION int hal_uds_derive_key(uint8_t *out, size_t out_len)
286+
{
287+
(void)out;
288+
(void)out_len;
289+
return -1;
290+
}
291+
292+
WEAKFUNCTION int hal_attestation_get_lifecycle(uint32_t *lifecycle)
293+
{
294+
(void)lifecycle;
295+
return -1;
296+
}
297+
298+
WEAKFUNCTION int hal_attestation_get_implementation_id(uint8_t *buf, size_t *len)
299+
{
300+
(void)buf;
301+
(void)len;
302+
return -1;
303+
}
304+
305+
WEAKFUNCTION int hal_attestation_get_ueid(uint8_t *buf, size_t *len)
306+
{
307+
(void)buf;
308+
(void)len;
309+
return -1;
310+
}
311+
312+
WEAKFUNCTION int hal_attestation_get_iak_private_key(uint8_t *buf, size_t *len)
313+
{
314+
(void)buf;
315+
(void)len;
316+
return -1;
317+
}

hal/stm32h5.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
*/
2121

2222
#include <stdint.h>
23+
#include <stddef.h>
2324
#include <image.h>
2425
#include <string.h>
2526

@@ -29,6 +30,12 @@
2930

3031
#include "uart_drv.h"
3132

33+
#if defined(WOLFBOOT_HASH_SHA256)
34+
#include <wolfssl/wolfcrypt/sha256.h>
35+
#elif defined(WOLFBOOT_HASH_SHA384) || defined(WOLFBOOT_HASH_SHA3_384)
36+
#include <wolfssl/wolfcrypt/sha512.h>
37+
#endif
38+
3239
#define PLL_SRC_HSE 1
3340

3441
#if TZ_SECURE()
@@ -152,6 +159,69 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
152159
return 0;
153160
}
154161

162+
#define STM32H5_BSEC_BASE 0x46009000u
163+
#define STM32H5_BSEC_UID0 (*(volatile uint32_t *)(STM32H5_BSEC_BASE + 0x14))
164+
#define STM32H5_BSEC_UID1 (*(volatile uint32_t *)(STM32H5_BSEC_BASE + 0x18))
165+
#define STM32H5_BSEC_UID2 (*(volatile uint32_t *)(STM32H5_BSEC_BASE + 0x1C))
166+
167+
int hal_uds_derive_key(uint8_t *out, size_t out_len)
168+
{
169+
uint8_t uid[12];
170+
#if defined(WOLFBOOT_HASH_SHA256)
171+
uint8_t digest[SHA256_DIGEST_SIZE];
172+
wc_Sha256 hash;
173+
#else
174+
uint8_t digest[SHA384_DIGEST_SIZE];
175+
wc_Sha384 hash;
176+
#endif
177+
size_t copy_len;
178+
179+
if (out == NULL || out_len == 0) {
180+
return -1;
181+
}
182+
183+
uid[0] = (uint8_t)(STM32H5_BSEC_UID0 >> 0);
184+
uid[1] = (uint8_t)(STM32H5_BSEC_UID0 >> 8);
185+
uid[2] = (uint8_t)(STM32H5_BSEC_UID0 >> 16);
186+
uid[3] = (uint8_t)(STM32H5_BSEC_UID0 >> 24);
187+
uid[4] = (uint8_t)(STM32H5_BSEC_UID1 >> 0);
188+
uid[5] = (uint8_t)(STM32H5_BSEC_UID1 >> 8);
189+
uid[6] = (uint8_t)(STM32H5_BSEC_UID1 >> 16);
190+
uid[7] = (uint8_t)(STM32H5_BSEC_UID1 >> 24);
191+
uid[8] = (uint8_t)(STM32H5_BSEC_UID2 >> 0);
192+
uid[9] = (uint8_t)(STM32H5_BSEC_UID2 >> 8);
193+
uid[10] = (uint8_t)(STM32H5_BSEC_UID2 >> 16);
194+
uid[11] = (uint8_t)(STM32H5_BSEC_UID2 >> 24);
195+
196+
#if defined(WOLFBOOT_HASH_SHA256)
197+
wc_InitSha256(&hash);
198+
wc_Sha256Update(&hash, uid, sizeof(uid));
199+
wc_Sha256Final(&hash, digest);
200+
copy_len = sizeof(digest);
201+
#else
202+
wc_InitSha384(&hash);
203+
wc_Sha384Update(&hash, uid, sizeof(uid));
204+
wc_Sha384Final(&hash, digest);
205+
copy_len = sizeof(digest);
206+
#endif
207+
208+
if (copy_len > out_len) {
209+
copy_len = out_len;
210+
}
211+
memcpy(out, digest, copy_len);
212+
return 0;
213+
}
214+
215+
int hal_attestation_get_lifecycle(uint32_t *lifecycle)
216+
{
217+
if (lifecycle == NULL) {
218+
return -1;
219+
}
220+
221+
*lifecycle = 0x3000u; /* PSA_LIFECYCLE_SECURED (default) */
222+
return 0;
223+
}
224+
155225
void RAMFUNCTION hal_flash_unlock(void)
156226
{
157227
hal_flash_wait_complete(0);

hal/stm32l5.c

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,16 @@
2020
*/
2121

2222
#include <stdint.h>
23+
#include <stddef.h>
2324
#include <image.h>
2425
#include <string.h>
2526

27+
#if defined(WOLFBOOT_HASH_SHA256)
28+
#include <wolfssl/wolfcrypt/sha256.h>
29+
#elif defined(WOLFBOOT_HASH_SHA384) || defined(WOLFBOOT_HASH_SHA3_384)
30+
#include <wolfssl/wolfcrypt/sha512.h>
31+
#endif
32+
2633
#include "hal.h"
2734
#include "hal/stm32l5.h"
2835

@@ -103,6 +110,69 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
103110
return 0;
104111
}
105112

113+
#define STM32L5_UID_BASE 0x1FFF7590u
114+
#define STM32L5_UID0 (*(volatile uint32_t *)(STM32L5_UID_BASE + 0x0))
115+
#define STM32L5_UID1 (*(volatile uint32_t *)(STM32L5_UID_BASE + 0x4))
116+
#define STM32L5_UID2 (*(volatile uint32_t *)(STM32L5_UID_BASE + 0x8))
117+
118+
int hal_uds_derive_key(uint8_t *out, size_t out_len)
119+
{
120+
uint8_t uid[12];
121+
#if defined(WOLFBOOT_HASH_SHA256)
122+
uint8_t digest[SHA256_DIGEST_SIZE];
123+
wc_Sha256 hash;
124+
#else
125+
uint8_t digest[SHA384_DIGEST_SIZE];
126+
wc_Sha384 hash;
127+
#endif
128+
size_t copy_len;
129+
130+
if (out == NULL || out_len == 0) {
131+
return -1;
132+
}
133+
134+
uid[0] = (uint8_t)(STM32L5_UID0 >> 0);
135+
uid[1] = (uint8_t)(STM32L5_UID0 >> 8);
136+
uid[2] = (uint8_t)(STM32L5_UID0 >> 16);
137+
uid[3] = (uint8_t)(STM32L5_UID0 >> 24);
138+
uid[4] = (uint8_t)(STM32L5_UID1 >> 0);
139+
uid[5] = (uint8_t)(STM32L5_UID1 >> 8);
140+
uid[6] = (uint8_t)(STM32L5_UID1 >> 16);
141+
uid[7] = (uint8_t)(STM32L5_UID1 >> 24);
142+
uid[8] = (uint8_t)(STM32L5_UID2 >> 0);
143+
uid[9] = (uint8_t)(STM32L5_UID2 >> 8);
144+
uid[10] = (uint8_t)(STM32L5_UID2 >> 16);
145+
uid[11] = (uint8_t)(STM32L5_UID2 >> 24);
146+
147+
#if defined(WOLFBOOT_HASH_SHA256)
148+
wc_InitSha256(&hash);
149+
wc_Sha256Update(&hash, uid, sizeof(uid));
150+
wc_Sha256Final(&hash, digest);
151+
copy_len = sizeof(digest);
152+
#else
153+
wc_InitSha384(&hash);
154+
wc_Sha384Update(&hash, uid, sizeof(uid));
155+
wc_Sha384Final(&hash, digest);
156+
copy_len = sizeof(digest);
157+
#endif
158+
159+
if (copy_len > out_len) {
160+
copy_len = out_len;
161+
}
162+
memcpy(out, digest, copy_len);
163+
return 0;
164+
}
165+
166+
int hal_attestation_get_lifecycle(uint32_t *lifecycle)
167+
{
168+
if (lifecycle == NULL) {
169+
return -1;
170+
}
171+
172+
*lifecycle = 0x3000u; /* PSA_LIFECYCLE_SECURED (default) */
173+
return 0;
174+
}
175+
106176
void RAMFUNCTION hal_flash_unlock(void)
107177
{
108178
hal_flash_wait_complete(0);
@@ -412,4 +482,3 @@ void hal_prepare_boot(void)
412482
periph_unsecure();
413483
#endif
414484
}
415-

include/hal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ extern "C" {
2929
#endif
3030

3131
#include "target.h"
32+
#include <stddef.h>
3233
#include <stdint.h>
3334

3435
/* Architecture specific calls */
@@ -137,6 +138,13 @@ int hal_trng_get_entropy(unsigned char *out, unsigned len);
137138

138139
#endif
139140

141+
/* Attestation helpers (optional, weak stubs available). */
142+
int hal_uds_derive_key(uint8_t *out, size_t out_len);
143+
int hal_attestation_get_lifecycle(uint32_t *lifecycle);
144+
int hal_attestation_get_implementation_id(uint8_t *buf, size_t *len);
145+
int hal_attestation_get_ueid(uint8_t *buf, size_t *len);
146+
int hal_attestation_get_iak_private_key(uint8_t *buf, size_t *len);
147+
140148
#ifdef FLASH_OTP_KEYSTORE
141149

142150
int hal_flash_otp_write(uint32_t flashAddress, const void* data, uint16_t length);

include/wolfboot/dice.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* dice.h
2+
*
3+
* DICE helpers and PSA attestation token builder.
4+
*
5+
* Copyright (C) 2026 wolfSSL Inc.
6+
*
7+
* This file is part of wolfBoot.
8+
*/
9+
10+
#ifndef WOLFBOOT_DICE_H
11+
#define WOLFBOOT_DICE_H
12+
13+
#include <stddef.h>
14+
#include <stdint.h>
15+
16+
#ifdef __cplusplus
17+
extern "C" {
18+
#endif
19+
20+
int wolfBoot_dice_get_token(const uint8_t *challenge,
21+
size_t challenge_size,
22+
uint8_t *token_buf,
23+
size_t token_buf_size,
24+
size_t *token_size);
25+
26+
int wolfBoot_dice_get_token_size(size_t challenge_size, size_t *token_size);
27+
28+
#ifdef __cplusplus
29+
}
30+
#endif
31+
32+
#endif /* WOLFBOOT_DICE_H */

options.mk

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ ifeq ($(WOLFBOOT_TPM_KEYSTORE),1)
3131
endif
3232
endif
3333

34+
ifeq ($(WOLFBOOT_ATTESTATION_IAK),1)
35+
CFLAGS+=-D"WOLFBOOT_ATTESTATION_IAK"
36+
endif
37+
3438
## Sealing a secret into the TPM
3539
ifeq ($(WOLFBOOT_TPM_SEAL),1)
3640
WOLFTPM:=1
@@ -744,6 +748,8 @@ ifeq ($(WOLFCRYPT_TZ_PSA),1)
744748
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/pwdbased.o
745749
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hmac.o
746750
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/dh.o
751+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/chacha.o
752+
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/des3.o
747753
ifeq ($(findstring random.o,$(WOLFCRYPT_OBJS)),)
748754
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/random.o
749755
endif

0 commit comments

Comments
 (0)