mirror of https://github.com/wolfSSL/wolfBoot.git
Add wolfCOSE DICE attestation
parent
9232a95033
commit
db0801b9b4
|
|
@ -89,4 +89,5 @@ jobs:
|
|||
WOLFBOOT_LIB_WOLFPKCS11="$(realpath ../external-libs/wolfPKCS11)" \
|
||||
WOLFBOOT_LIB_WOLFPSA="$(realpath ../external-libs/wolfPSA)" \
|
||||
WOLFBOOT_LIB_WOLFTPM="$(realpath ../external-libs/wolfTPM)" \
|
||||
WOLFBOOT_LIB_WOLFHSM="$(realpath ../external-libs/wolfHSM)"
|
||||
WOLFBOOT_LIB_WOLFHSM="$(realpath ../external-libs/wolfHSM)" \
|
||||
WOLFBOOT_LIB_WOLFCOSE="$(realpath ../external-libs/wolfCOSE)"
|
||||
|
|
|
|||
|
|
@ -101,10 +101,16 @@ jobs:
|
|||
|
||||
- name: Clean and build test with DICE attestation (stm32h5)
|
||||
run: |
|
||||
set -o pipefail
|
||||
make clean distclean
|
||||
cp config/examples/stm32h5-tz-psa.config .config
|
||||
make
|
||||
m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 600
|
||||
m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 600 \
|
||||
| tee /tmp/m33mu-dice.log
|
||||
grep -q "IAT size match: challenge=64 token=" /tmp/m33mu-dice.log
|
||||
grep -q "PSA boot attestation: success" /tmp/m33mu-dice.log
|
||||
grep -q "\\[BKPT\\] imm=0x7f" /tmp/m33mu-dice.log
|
||||
grep -q "\\[EXPECT BKPT\\] Success" /tmp/m33mu-dice.log
|
||||
|
||||
- name: Clean and build test with fwTPM (stm32h5)
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -16,3 +16,6 @@
|
|||
[submodule "lib/wolfHAL"]
|
||||
path = lib/wolfHAL
|
||||
url = https://github.com/wolfSSL/wolfHAL.git
|
||||
[submodule "lib/wolfCOSE"]
|
||||
path = lib/wolfCOSE
|
||||
url = https://github.com/wolfSSL/wolfCOSE.git
|
||||
|
|
|
|||
|
|
@ -566,6 +566,10 @@ endif()
|
|||
|
||||
if(DEFINED WOLFCRYPT_TZ_PSA AND NOT WOLFCRYPT_TZ_PSA STREQUAL "0")
|
||||
list(APPEND WOLFBOOT_SOURCES "src/dice/dice.c")
|
||||
list(APPEND WOLFBOOT_SOURCES "lib/wolfCOSE/src/wolfcose.c")
|
||||
list(APPEND WOLFBOOT_SOURCES "lib/wolfCOSE/src/wolfcose_cbor.c")
|
||||
list(APPEND WOLFBOOT_INCLUDE_DIRS ${WOLFBOOT_ROOT}/lib/wolfCOSE/include)
|
||||
list(APPEND WOLFBOOT_DEFS WOLFCOSE_LEAN WOLFCOSE_ENABLE_EXT_SIGN)
|
||||
endif()
|
||||
|
||||
# build bin-assemble tool Windows
|
||||
|
|
|
|||
3
Makefile
3
Makefile
|
|
@ -191,6 +191,7 @@ WOLFBOOT_LIB_WOLFTPM?=lib/wolfTPM
|
|||
WOLFBOOT_LIB_WOLFPKCS11?=lib/wolfPKCS11
|
||||
WOLFBOOT_LIB_WOLFPSA?=lib/wolfPSA
|
||||
WOLFBOOT_LIB_WOLFHSM?=lib/wolfHSM
|
||||
WOLFBOOT_LIB_WOLFCOSE?=lib/wolfCOSE
|
||||
|
||||
# Convert to absolute paths using abspath function
|
||||
WOLFBOOT_LIB_WOLFSSL:=$(abspath $(WOLFBOOT_LIB_WOLFSSL))
|
||||
|
|
@ -198,6 +199,7 @@ WOLFBOOT_LIB_WOLFTPM:=$(abspath $(WOLFBOOT_LIB_WOLFTPM))
|
|||
WOLFBOOT_LIB_WOLFPKCS11:=$(abspath $(WOLFBOOT_LIB_WOLFPKCS11))
|
||||
WOLFBOOT_LIB_WOLFPSA:=$(abspath $(WOLFBOOT_LIB_WOLFPSA))
|
||||
WOLFBOOT_LIB_WOLFHSM:=$(abspath $(WOLFBOOT_LIB_WOLFHSM))
|
||||
WOLFBOOT_LIB_WOLFCOSE:=$(abspath $(WOLFBOOT_LIB_WOLFCOSE))
|
||||
|
||||
# Export variables so they are available to sub-makefiles
|
||||
export WOLFBOOT_LIB_WOLFSSL
|
||||
|
|
@ -205,6 +207,7 @@ export WOLFBOOT_LIB_WOLFTPM
|
|||
export WOLFBOOT_LIB_WOLFPKCS11
|
||||
export WOLFBOOT_LIB_WOLFPSA
|
||||
export WOLFBOOT_LIB_WOLFHSM
|
||||
export WOLFBOOT_LIB_WOLFCOSE
|
||||
|
||||
## Architecture/CPU configuration
|
||||
include arch.mk
|
||||
|
|
|
|||
15
docs/DICE.md
15
docs/DICE.md
|
|
@ -22,15 +22,24 @@ an attestation key derived by DICE or supplied as a provisioned IAK.
|
|||
|
||||
The implementation lives under `src/dice/` and is shared across targets. The
|
||||
service is invoked through the PSA Initial Attestation API and builds the
|
||||
COSE_Sign1 token using a minimal CBOR encoder.
|
||||
EAT claim set with wolfCOSE's CBOR API. wolfCOSE then wraps and signs the
|
||||
payload as an untagged COSE_Sign1 object using ES256. Hardware DICE targets use
|
||||
wolfCOSE's external-signer callback so the attestation private key never leaves
|
||||
the platform security boundary. Token-size queries use wolfCOSE's prediction
|
||||
API and do not derive a key, advance the CDI, or invoke a signer.
|
||||
|
||||
- Claim construction and COSE_Sign1 encoding: `src/dice/dice.c`.
|
||||
- PSA Initial Attestation service dispatch: `src/arm_tee_psa_ipc.c`.
|
||||
- NSC wrappers for the PSA Initial Attestation API: `zephyr/src/arm_tee_attest_api.c`.
|
||||
|
||||
Measured boot claims reuse the image hashing pipeline already used by
|
||||
wolfBoot to validate images. Component claims include a measurement type,
|
||||
measurement value, and a description string.
|
||||
wolfBoot to validate images. Each software-component map includes measurement
|
||||
type (key 1), measurement value (key 2), signer ID (key 5), and measurement
|
||||
description (key 6). The boot-image signer ID is the authenticated `HDR_PUBKEY`
|
||||
hash from its wolfBoot image header. The running wolfBoot image has no retained
|
||||
signing manifest, so its signer ID is the zero-filled unknown-signer value used
|
||||
by TF-M for the same case. Unsigned `WOLFBOOT_NO_SIGN` boot images also use the
|
||||
unknown-signer value because no signing authority exists.
|
||||
|
||||
## Keying model
|
||||
|
||||
|
|
|
|||
|
|
@ -167,10 +167,11 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define STM32H5_BSEC_BASE 0x46009000u
|
||||
#define STM32H5_BSEC_UID0 (*(volatile uint32_t *)(STM32H5_BSEC_BASE + 0x14))
|
||||
#define STM32H5_BSEC_UID1 (*(volatile uint32_t *)(STM32H5_BSEC_BASE + 0x18))
|
||||
#define STM32H5_BSEC_UID2 (*(volatile uint32_t *)(STM32H5_BSEC_BASE + 0x1C))
|
||||
/* STM32H5 96-bit unique device ID, factory-programmed (RM0481). */
|
||||
#define STM32H5_UID_BASE 0x08FFF800u
|
||||
#define STM32H5_UID0 (*(volatile uint32_t *)(STM32H5_UID_BASE + 0x0u))
|
||||
#define STM32H5_UID1 (*(volatile uint32_t *)(STM32H5_UID_BASE + 0x4u))
|
||||
#define STM32H5_UID2 (*(volatile uint32_t *)(STM32H5_UID_BASE + 0x8u))
|
||||
|
||||
#ifdef WOLFBOOT_UDS_OBKEYS
|
||||
__attribute__((weak)) int stm32h5_obkeys_read_uds(uint8_t *out, size_t out_len)
|
||||
|
|
@ -205,18 +206,18 @@ static int uds_from_uid(uint8_t *out, size_t out_len)
|
|||
#endif
|
||||
size_t copy_len;
|
||||
|
||||
uid[0] = (uint8_t)(STM32H5_BSEC_UID0 >> 0);
|
||||
uid[1] = (uint8_t)(STM32H5_BSEC_UID0 >> 8);
|
||||
uid[2] = (uint8_t)(STM32H5_BSEC_UID0 >> 16);
|
||||
uid[3] = (uint8_t)(STM32H5_BSEC_UID0 >> 24);
|
||||
uid[4] = (uint8_t)(STM32H5_BSEC_UID1 >> 0);
|
||||
uid[5] = (uint8_t)(STM32H5_BSEC_UID1 >> 8);
|
||||
uid[6] = (uint8_t)(STM32H5_BSEC_UID1 >> 16);
|
||||
uid[7] = (uint8_t)(STM32H5_BSEC_UID1 >> 24);
|
||||
uid[8] = (uint8_t)(STM32H5_BSEC_UID2 >> 0);
|
||||
uid[9] = (uint8_t)(STM32H5_BSEC_UID2 >> 8);
|
||||
uid[10] = (uint8_t)(STM32H5_BSEC_UID2 >> 16);
|
||||
uid[11] = (uint8_t)(STM32H5_BSEC_UID2 >> 24);
|
||||
uid[0] = (uint8_t)(STM32H5_UID0 >> 0);
|
||||
uid[1] = (uint8_t)(STM32H5_UID0 >> 8);
|
||||
uid[2] = (uint8_t)(STM32H5_UID0 >> 16);
|
||||
uid[3] = (uint8_t)(STM32H5_UID0 >> 24);
|
||||
uid[4] = (uint8_t)(STM32H5_UID1 >> 0);
|
||||
uid[5] = (uint8_t)(STM32H5_UID1 >> 8);
|
||||
uid[6] = (uint8_t)(STM32H5_UID1 >> 16);
|
||||
uid[7] = (uint8_t)(STM32H5_UID1 >> 24);
|
||||
uid[8] = (uint8_t)(STM32H5_UID2 >> 0);
|
||||
uid[9] = (uint8_t)(STM32H5_UID2 >> 8);
|
||||
uid[10] = (uint8_t)(STM32H5_UID2 >> 16);
|
||||
uid[11] = (uint8_t)(STM32H5_UID2 >> 24);
|
||||
|
||||
#if defined(WOLFBOOT_HASH_SHA256)
|
||||
wc_InitSha256(&hash);
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 588232e6f2213133b48976f5cf3153b21fc7199c
|
||||
|
|
@ -1139,6 +1139,8 @@ ifeq ($(WOLFCRYPT_TZ_PSA),1)
|
|||
CFLAGS+=-DWOLFSSL_PSA_ENGINE
|
||||
CFLAGS+=-DWOLFPSA_CUSTOM_STORE
|
||||
CFLAGS+=-DNO_DES3 -DNO_DES3_TLS_SUITES
|
||||
CFLAGS+=-I$(WOLFBOOT_LIB_WOLFCOSE)/include
|
||||
CFLAGS+=-DWOLFCOSE_LEAN -DWOLFCOSE_ENABLE_EXT_SIGN
|
||||
WOLFPSA_CFLAGS+=-I$(WOLFBOOT_LIB_WOLFPSA)
|
||||
WOLFPSA_CFLAGS+=-I$(WOLFBOOT_LIB_WOLFPSA)/wolfpsa
|
||||
ifeq ($(USE_CLANG),1)
|
||||
|
|
@ -1152,6 +1154,8 @@ ifeq ($(WOLFCRYPT_TZ_PSA),1)
|
|||
WOLFCRYPT_OBJS+=src/psa_store.o
|
||||
WOLFCRYPT_OBJS+=src/arm_tee_psa_veneer.o
|
||||
WOLFCRYPT_OBJS+=src/arm_tee_psa_ipc.o
|
||||
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFCOSE)/src/wolfcose.o
|
||||
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFCOSE)/src/wolfcose_cbor.o
|
||||
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/pwdbased.o
|
||||
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hmac.o
|
||||
WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/dh.o
|
||||
|
|
|
|||
652
src/dice/dice.c
652
src/dice/dice.c
|
|
@ -42,6 +42,8 @@
|
|||
#include <wolfssl/wolfcrypt/sha3.h>
|
||||
#endif
|
||||
|
||||
#include <wolfcose/wolfcose.h>
|
||||
|
||||
#ifndef PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32
|
||||
#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 (32u)
|
||||
#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 (48u)
|
||||
|
|
@ -59,7 +61,6 @@
|
|||
#define WOLFBOOT_DICE_CDI_LEN 32
|
||||
#define WOLFBOOT_DICE_KEY_LEN 32
|
||||
#define WOLFBOOT_DICE_UEID_LEN 33
|
||||
#define WOLFBOOT_DICE_SIG_LEN 64
|
||||
|
||||
#define WOLFBOOT_DICE_SUCCESS 0
|
||||
#define WOLFBOOT_DICE_ERR_INVALID_ARGUMENT -1
|
||||
|
|
@ -76,19 +77,17 @@ static NOINLINEFUNCTION void wolfboot_dice_zeroize(void *ptr, size_t len)
|
|||
}
|
||||
}
|
||||
|
||||
#define COSE_LABEL_ALG 1
|
||||
#define COSE_ALG_ES256 (-7)
|
||||
|
||||
#define EAT_CLAIM_NONCE 10
|
||||
#define EAT_CLAIM_UEID 256
|
||||
|
||||
#define PSA_IAT_CLAIM_IMPLEMENTATION_ID 2396
|
||||
#define PSA_IAT_CLAIM_LIFECYCLE 2398
|
||||
#define PSA_IAT_CLAIM_LIFECYCLE 2395
|
||||
#define PSA_IAT_CLAIM_SW_COMPONENTS 2399
|
||||
|
||||
#define PSA_SW_COMPONENT_MEASUREMENT_TYPE 1
|
||||
#define PSA_SW_COMPONENT_MEASUREMENT_VALUE 2
|
||||
#define PSA_SW_COMPONENT_MEASUREMENT_DESCRIPTION 5
|
||||
#define PSA_SW_COMPONENT_SIGNER_ID 5
|
||||
#define PSA_SW_COMPONENT_MEASUREMENT_DESCRIPTION 6
|
||||
|
||||
#define WOLFBOOT_UEID_TYPE_RANDOM 0x01
|
||||
|
||||
|
|
@ -115,6 +114,8 @@ struct wolfboot_dice_component {
|
|||
size_t measurement_desc_len;
|
||||
uint8_t measurement[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||
size_t measurement_len;
|
||||
uint8_t signer_id[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||
size_t signer_id_len;
|
||||
};
|
||||
|
||||
struct wolfboot_dice_claims {
|
||||
|
|
@ -130,145 +131,6 @@ struct wolfboot_dice_claims {
|
|||
size_t component_count;
|
||||
};
|
||||
|
||||
struct wolfboot_cbor_writer {
|
||||
uint8_t *buf;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
int error;
|
||||
};
|
||||
|
||||
static void wolfboot_cbor_init(struct wolfboot_cbor_writer *w,
|
||||
uint8_t *buf,
|
||||
size_t size)
|
||||
{
|
||||
w->buf = buf;
|
||||
w->size = size;
|
||||
w->offset = 0;
|
||||
w->error = 0;
|
||||
}
|
||||
|
||||
static void wolfboot_cbor_reserve(struct wolfboot_cbor_writer *w, size_t len)
|
||||
{
|
||||
if (w->error != 0) {
|
||||
return;
|
||||
}
|
||||
if (w->buf == NULL || w->size == 0) {
|
||||
w->offset += len;
|
||||
return;
|
||||
}
|
||||
if (w->offset + len > w->size) {
|
||||
w->error = WOLFBOOT_DICE_ERR_BUFFER_TOO_SMALL;
|
||||
return;
|
||||
}
|
||||
w->offset += len;
|
||||
}
|
||||
|
||||
static void wolfboot_cbor_put_type_val(struct wolfboot_cbor_writer *w,
|
||||
uint8_t major,
|
||||
uint64_t val)
|
||||
{
|
||||
uint8_t tmp[9];
|
||||
size_t len = 0;
|
||||
|
||||
if (val <= 23) {
|
||||
tmp[len++] = (uint8_t)((major << 5) | (uint8_t)val);
|
||||
}
|
||||
else if (val <= 0xFF) {
|
||||
tmp[len++] = (uint8_t)((major << 5) | 24);
|
||||
tmp[len++] = (uint8_t)val;
|
||||
}
|
||||
else if (val <= 0xFFFF) {
|
||||
tmp[len++] = (uint8_t)((major << 5) | 25);
|
||||
tmp[len++] = (uint8_t)(val >> 8);
|
||||
tmp[len++] = (uint8_t)(val & 0xFF);
|
||||
}
|
||||
else if (val <= 0xFFFFFFFFu) {
|
||||
tmp[len++] = (uint8_t)((major << 5) | 26);
|
||||
tmp[len++] = (uint8_t)(val >> 24);
|
||||
tmp[len++] = (uint8_t)(val >> 16);
|
||||
tmp[len++] = (uint8_t)(val >> 8);
|
||||
tmp[len++] = (uint8_t)(val & 0xFF);
|
||||
}
|
||||
else {
|
||||
tmp[len++] = (uint8_t)((major << 5) | 27);
|
||||
tmp[len++] = (uint8_t)(val >> 56);
|
||||
tmp[len++] = (uint8_t)(val >> 48);
|
||||
tmp[len++] = (uint8_t)(val >> 40);
|
||||
tmp[len++] = (uint8_t)(val >> 32);
|
||||
tmp[len++] = (uint8_t)(val >> 24);
|
||||
tmp[len++] = (uint8_t)(val >> 16);
|
||||
tmp[len++] = (uint8_t)(val >> 8);
|
||||
tmp[len++] = (uint8_t)(val & 0xFF);
|
||||
}
|
||||
|
||||
wolfboot_cbor_reserve(w, len);
|
||||
if (w->error != 0) {
|
||||
return;
|
||||
}
|
||||
if (w->buf == NULL || w->size == 0) {
|
||||
return;
|
||||
}
|
||||
XMEMCPY(w->buf + (w->offset - len), tmp, len);
|
||||
}
|
||||
|
||||
static void wolfboot_cbor_put_uint(struct wolfboot_cbor_writer *w, uint64_t val)
|
||||
{
|
||||
wolfboot_cbor_put_type_val(w, 0, val);
|
||||
}
|
||||
|
||||
static void wolfboot_cbor_put_int(struct wolfboot_cbor_writer *w, int64_t val)
|
||||
{
|
||||
if (val >= 0) {
|
||||
wolfboot_cbor_put_uint(w, (uint64_t)val);
|
||||
}
|
||||
else {
|
||||
uint64_t n = (uint64_t)(-1 - val);
|
||||
wolfboot_cbor_put_type_val(w, 1, n);
|
||||
}
|
||||
}
|
||||
|
||||
static void wolfboot_cbor_put_bstr(struct wolfboot_cbor_writer *w,
|
||||
const uint8_t *data,
|
||||
size_t len)
|
||||
{
|
||||
wolfboot_cbor_put_type_val(w, 2, len);
|
||||
wolfboot_cbor_reserve(w, len);
|
||||
if (w->error != 0) {
|
||||
return;
|
||||
}
|
||||
if (w->buf == NULL || w->size == 0) {
|
||||
return;
|
||||
}
|
||||
XMEMCPY(w->buf + (w->offset - len), data, len);
|
||||
}
|
||||
|
||||
static void wolfboot_cbor_put_tstr(struct wolfboot_cbor_writer *w,
|
||||
const char *data,
|
||||
size_t len)
|
||||
{
|
||||
wolfboot_cbor_put_type_val(w, 3, len);
|
||||
wolfboot_cbor_reserve(w, len);
|
||||
if (w->error != 0) {
|
||||
return;
|
||||
}
|
||||
if (w->buf == NULL || w->size == 0) {
|
||||
return;
|
||||
}
|
||||
XMEMCPY(w->buf + (w->offset - len), data, len);
|
||||
}
|
||||
|
||||
static void wolfboot_cbor_put_array_start(struct wolfboot_cbor_writer *w,
|
||||
size_t count)
|
||||
{
|
||||
wolfboot_cbor_put_type_val(w, 4, count);
|
||||
}
|
||||
|
||||
static void wolfboot_cbor_put_map_start(struct wolfboot_cbor_writer *w,
|
||||
size_t count)
|
||||
{
|
||||
wolfboot_cbor_put_type_val(w, 5, count);
|
||||
}
|
||||
|
||||
static int wolfboot_hash_region(uintptr_t address, uint32_t size, uint8_t *out)
|
||||
{
|
||||
#if defined(WOLFBOOT_HASH_SHA256)
|
||||
|
|
@ -336,13 +198,25 @@ static int wolfboot_hash_region(uintptr_t address, uint32_t size, uint8_t *out)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int wolfboot_get_boot_image_hash(uint8_t *out, size_t *out_len)
|
||||
static int wolfboot_get_boot_image_claims(uint8_t *measurement,
|
||||
size_t *measurement_len,
|
||||
uint8_t *signer_id,
|
||||
size_t *signer_id_len)
|
||||
{
|
||||
struct wolfBoot_image img;
|
||||
uint8_t *hash_ptr = NULL;
|
||||
#ifndef WOLFBOOT_NO_SIGN
|
||||
uint8_t *signer_ptr = NULL;
|
||||
#endif
|
||||
uint16_t hash_len = 0;
|
||||
#ifndef WOLFBOOT_NO_SIGN
|
||||
uint16_t signer_len = 0;
|
||||
#endif
|
||||
|
||||
if (out == NULL || out_len == NULL || *out_len < WOLFBOOT_SHA_DIGEST_SIZE) {
|
||||
if (measurement == NULL || measurement_len == NULL || signer_id == NULL ||
|
||||
signer_id_len == NULL ||
|
||||
*measurement_len < WOLFBOOT_SHA_DIGEST_SIZE ||
|
||||
*signer_id_len < WOLFBOOT_SHA_DIGEST_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -355,8 +229,19 @@ static int wolfboot_get_boot_image_hash(uint8_t *out, size_t *out_len)
|
|||
return -1;
|
||||
}
|
||||
|
||||
XMEMCPY(out, hash_ptr, hash_len);
|
||||
*out_len = hash_len;
|
||||
XMEMCPY(measurement, hash_ptr, hash_len);
|
||||
*measurement_len = hash_len;
|
||||
#ifdef WOLFBOOT_NO_SIGN
|
||||
XMEMSET(signer_id, 0, WOLFBOOT_SHA_DIGEST_SIZE);
|
||||
*signer_id_len = WOLFBOOT_SHA_DIGEST_SIZE;
|
||||
#else
|
||||
signer_len = wolfBoot_get_header(&img, HDR_PUBKEY, &signer_ptr);
|
||||
if (signer_len != WOLFBOOT_SHA_DIGEST_SIZE || signer_ptr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
XMEMCPY(signer_id, signer_ptr, signer_len);
|
||||
*signer_id_len = signer_len;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -527,6 +412,8 @@ static int wolfboot_dice_collect_claims(struct wolfboot_dice_claims *claims)
|
|||
size_t wb_hash_len = sizeof(wb_hash);
|
||||
uint8_t boot_hash[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||
size_t boot_hash_len = sizeof(boot_hash);
|
||||
uint8_t boot_signer_id[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||
size_t boot_signer_id_len = sizeof(boot_signer_id);
|
||||
|
||||
XMEMSET(claims, 0, sizeof(*claims));
|
||||
|
||||
|
|
@ -569,35 +456,53 @@ static int wolfboot_dice_collect_claims(struct wolfboot_dice_claims *claims)
|
|||
claims->has_lifecycle = 1;
|
||||
}
|
||||
|
||||
if (wolfboot_get_wolfboot_hash(wb_hash, &wb_hash_len) == 0) {
|
||||
claims->components[claims->component_count].measurement_type =
|
||||
WOLFBOOT_MEASUREMENT_HASH_NAME;
|
||||
claims->components[claims->component_count].measurement_type_len =
|
||||
XSTRLEN(WOLFBOOT_MEASUREMENT_HASH_NAME);
|
||||
claims->components[claims->component_count].measurement_desc =
|
||||
WOLFBOOT_DICE_COMPONENT_WOLFBOOT;
|
||||
claims->components[claims->component_count].measurement_desc_len =
|
||||
XSTRLEN(WOLFBOOT_DICE_COMPONENT_WOLFBOOT);
|
||||
XMEMCPY(claims->components[claims->component_count].measurement,
|
||||
wb_hash, wb_hash_len);
|
||||
claims->components[claims->component_count].measurement_len = wb_hash_len;
|
||||
claims->component_count++;
|
||||
/* A measurement that silently vanishes leaves a token a verifier cannot
|
||||
* tell from one for a device with nothing to measure. */
|
||||
if (wolfboot_get_wolfboot_hash(wb_hash, &wb_hash_len) != 0) {
|
||||
#ifndef WOLFBOOT_DICE_HW
|
||||
wc_ForceZero(uds, sizeof(uds));
|
||||
#endif
|
||||
return WOLFBOOT_DICE_ERR_HW;
|
||||
}
|
||||
claims->components[claims->component_count].measurement_type =
|
||||
WOLFBOOT_MEASUREMENT_HASH_NAME;
|
||||
claims->components[claims->component_count].measurement_type_len =
|
||||
XSTRLEN(WOLFBOOT_MEASUREMENT_HASH_NAME);
|
||||
claims->components[claims->component_count].measurement_desc =
|
||||
WOLFBOOT_DICE_COMPONENT_WOLFBOOT;
|
||||
claims->components[claims->component_count].measurement_desc_len =
|
||||
XSTRLEN(WOLFBOOT_DICE_COMPONENT_WOLFBOOT);
|
||||
XMEMCPY(claims->components[claims->component_count].measurement,
|
||||
wb_hash, wb_hash_len);
|
||||
claims->components[claims->component_count].measurement_len = wb_hash_len;
|
||||
claims->components[claims->component_count].signer_id_len =
|
||||
WOLFBOOT_SHA_DIGEST_SIZE;
|
||||
claims->component_count++;
|
||||
|
||||
if (wolfboot_get_boot_image_hash(boot_hash, &boot_hash_len) == 0) {
|
||||
claims->components[claims->component_count].measurement_type =
|
||||
WOLFBOOT_MEASUREMENT_HASH_NAME;
|
||||
claims->components[claims->component_count].measurement_type_len =
|
||||
XSTRLEN(WOLFBOOT_MEASUREMENT_HASH_NAME);
|
||||
claims->components[claims->component_count].measurement_desc =
|
||||
WOLFBOOT_DICE_COMPONENT_BOOTIMAGE;
|
||||
claims->components[claims->component_count].measurement_desc_len =
|
||||
XSTRLEN(WOLFBOOT_DICE_COMPONENT_BOOTIMAGE);
|
||||
XMEMCPY(claims->components[claims->component_count].measurement,
|
||||
boot_hash, boot_hash_len);
|
||||
claims->components[claims->component_count].measurement_len = boot_hash_len;
|
||||
claims->component_count++;
|
||||
if (wolfboot_get_boot_image_claims(boot_hash, &boot_hash_len,
|
||||
boot_signer_id,
|
||||
&boot_signer_id_len) != 0) {
|
||||
#ifndef WOLFBOOT_DICE_HW
|
||||
wc_ForceZero(uds, sizeof(uds));
|
||||
#endif
|
||||
return WOLFBOOT_DICE_ERR_HW;
|
||||
}
|
||||
claims->components[claims->component_count].measurement_type =
|
||||
WOLFBOOT_MEASUREMENT_HASH_NAME;
|
||||
claims->components[claims->component_count].measurement_type_len =
|
||||
XSTRLEN(WOLFBOOT_MEASUREMENT_HASH_NAME);
|
||||
claims->components[claims->component_count].measurement_desc =
|
||||
WOLFBOOT_DICE_COMPONENT_BOOTIMAGE;
|
||||
claims->components[claims->component_count].measurement_desc_len =
|
||||
XSTRLEN(WOLFBOOT_DICE_COMPONENT_BOOTIMAGE);
|
||||
XMEMCPY(claims->components[claims->component_count].measurement,
|
||||
boot_hash, boot_hash_len);
|
||||
claims->components[claims->component_count].measurement_len = boot_hash_len;
|
||||
XMEMCPY(claims->components[claims->component_count].signer_id,
|
||||
boot_signer_id, boot_signer_id_len);
|
||||
claims->components[claims->component_count].signer_id_len =
|
||||
boot_signer_id_len;
|
||||
claims->component_count++;
|
||||
#ifndef WOLFBOOT_DICE_HW
|
||||
wc_ForceZero(uds, sizeof(uds));
|
||||
#endif
|
||||
|
|
@ -750,6 +655,11 @@ static int wolfboot_attest_get_private_key(ecc_key *key,
|
|||
key, ECC_SECP256R1) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
/* Import leaves the key ECC_PRIVATEKEY_ONLY; wolfCOSE treats a key as
|
||||
* sign-capable only once the public point is present. */
|
||||
if (wc_ecc_make_pub(key, NULL) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
|
|
@ -773,9 +683,10 @@ static int wolfboot_dice_encode_payload(uint8_t *buf,
|
|||
const struct wolfboot_dice_claims *claims,
|
||||
size_t *payload_len)
|
||||
{
|
||||
struct wolfboot_cbor_writer w;
|
||||
WOLFCOSE_CBOR_CTX ctx;
|
||||
size_t map_count = 2;
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
if (claims->implementation_id_len > 0) {
|
||||
map_count++;
|
||||
|
|
@ -787,195 +698,163 @@ static int wolfboot_dice_encode_payload(uint8_t *buf,
|
|||
map_count++;
|
||||
}
|
||||
|
||||
wolfboot_cbor_init(&w, buf, buf_len);
|
||||
wolfboot_cbor_put_map_start(&w, map_count);
|
||||
XMEMSET(&ctx, 0, sizeof(ctx));
|
||||
ctx.buf = buf;
|
||||
ctx.bufSz = buf_len;
|
||||
|
||||
wolfboot_cbor_put_int(&w, EAT_CLAIM_NONCE);
|
||||
wolfboot_cbor_put_bstr(&w, claims->challenge, claims->challenge_len);
|
||||
|
||||
wolfboot_cbor_put_int(&w, EAT_CLAIM_UEID);
|
||||
wolfboot_cbor_put_bstr(&w, claims->ueid, claims->ueid_len);
|
||||
|
||||
if (claims->implementation_id_len > 0) {
|
||||
wolfboot_cbor_put_int(&w, PSA_IAT_CLAIM_IMPLEMENTATION_ID);
|
||||
wolfboot_cbor_put_bstr(&w,
|
||||
claims->implementation_id,
|
||||
claims->implementation_id_len);
|
||||
ret = wc_CBOR_EncodeMapStart(&ctx, map_count);
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeInt(&ctx, EAT_CLAIM_NONCE);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeBstr(&ctx, claims->challenge, claims->challenge_len);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeInt(&ctx, EAT_CLAIM_UEID);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeBstr(&ctx, claims->ueid, claims->ueid_len);
|
||||
}
|
||||
|
||||
if (claims->has_lifecycle) {
|
||||
wolfboot_cbor_put_int(&w, PSA_IAT_CLAIM_LIFECYCLE);
|
||||
wolfboot_cbor_put_uint(&w, claims->lifecycle);
|
||||
}
|
||||
|
||||
if (claims->component_count > 0) {
|
||||
wolfboot_cbor_put_int(&w, PSA_IAT_CLAIM_SW_COMPONENTS);
|
||||
wolfboot_cbor_put_array_start(&w, claims->component_count);
|
||||
for (i = 0; i < claims->component_count; i++) {
|
||||
wolfboot_cbor_put_map_start(&w, 3);
|
||||
wolfboot_cbor_put_uint(&w, PSA_SW_COMPONENT_MEASUREMENT_TYPE);
|
||||
wolfboot_cbor_put_tstr(&w,
|
||||
claims->components[i].measurement_type,
|
||||
claims->components[i].measurement_type_len);
|
||||
wolfboot_cbor_put_uint(&w, PSA_SW_COMPONENT_MEASUREMENT_VALUE);
|
||||
wolfboot_cbor_put_bstr(&w,
|
||||
claims->components[i].measurement,
|
||||
claims->components[i].measurement_len);
|
||||
wolfboot_cbor_put_uint(&w, PSA_SW_COMPONENT_MEASUREMENT_DESCRIPTION);
|
||||
wolfboot_cbor_put_tstr(&w,
|
||||
claims->components[i].measurement_desc,
|
||||
claims->components[i].measurement_desc_len);
|
||||
if ((ret == 0) && (claims->implementation_id_len > 0)) {
|
||||
ret = wc_CBOR_EncodeInt(&ctx, PSA_IAT_CLAIM_IMPLEMENTATION_ID);
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeBstr(&ctx, claims->implementation_id,
|
||||
claims->implementation_id_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (w.error != 0) {
|
||||
return w.error;
|
||||
if ((ret == 0) && claims->has_lifecycle) {
|
||||
ret = wc_CBOR_EncodeInt(&ctx, PSA_IAT_CLAIM_LIFECYCLE);
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeUint(&ctx, claims->lifecycle);
|
||||
}
|
||||
}
|
||||
|
||||
*payload_len = w.offset;
|
||||
if ((ret == 0) && (claims->component_count > 0)) {
|
||||
ret = wc_CBOR_EncodeInt(&ctx, PSA_IAT_CLAIM_SW_COMPONENTS);
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeArrayStart(&ctx, claims->component_count);
|
||||
}
|
||||
for (i = 0; (ret == 0) && (i < claims->component_count); i++) {
|
||||
ret = wc_CBOR_EncodeMapStart(&ctx, 4);
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeUint(&ctx,
|
||||
PSA_SW_COMPONENT_MEASUREMENT_TYPE);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeTstr(&ctx,
|
||||
(const uint8_t *)claims->components[i].measurement_type,
|
||||
claims->components[i].measurement_type_len);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeUint(&ctx,
|
||||
PSA_SW_COMPONENT_MEASUREMENT_VALUE);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeBstr(&ctx,
|
||||
claims->components[i].measurement,
|
||||
claims->components[i].measurement_len);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeUint(&ctx, PSA_SW_COMPONENT_SIGNER_ID);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeBstr(&ctx,
|
||||
claims->components[i].signer_id,
|
||||
claims->components[i].signer_id_len);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeUint(&ctx,
|
||||
PSA_SW_COMPONENT_MEASUREMENT_DESCRIPTION);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CBOR_EncodeTstr(&ctx,
|
||||
(const uint8_t *)claims->components[i].measurement_desc,
|
||||
claims->components[i].measurement_desc_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
return WOLFBOOT_DICE_ERR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*payload_len = ctx.idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wolfboot_dice_encode_protected(uint8_t *buf,
|
||||
size_t buf_len,
|
||||
size_t *prot_len)
|
||||
{
|
||||
struct wolfboot_cbor_writer w;
|
||||
|
||||
wolfboot_cbor_init(&w, buf, buf_len);
|
||||
wolfboot_cbor_put_map_start(&w, 1);
|
||||
wolfboot_cbor_put_uint(&w, COSE_LABEL_ALG);
|
||||
wolfboot_cbor_put_int(&w, COSE_ALG_ES256);
|
||||
|
||||
if (w.error != 0) {
|
||||
return w.error;
|
||||
}
|
||||
|
||||
*prot_len = w.offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wolfboot_dice_build_sig_structure(uint8_t *buf,
|
||||
size_t buf_len,
|
||||
const uint8_t *prot,
|
||||
size_t prot_len,
|
||||
const uint8_t *payload,
|
||||
size_t payload_len,
|
||||
size_t *tbs_len)
|
||||
{
|
||||
struct wolfboot_cbor_writer w;
|
||||
|
||||
wolfboot_cbor_init(&w, buf, buf_len);
|
||||
wolfboot_cbor_put_array_start(&w, 4);
|
||||
wolfboot_cbor_put_tstr(&w, "Signature1", 10);
|
||||
wolfboot_cbor_put_bstr(&w, prot, prot_len);
|
||||
wolfboot_cbor_put_bstr(&w, (const uint8_t *)"", 0);
|
||||
wolfboot_cbor_put_bstr(&w, payload, payload_len);
|
||||
|
||||
if (w.error != 0) {
|
||||
return w.error;
|
||||
}
|
||||
|
||||
*tbs_len = w.offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wolfboot_dice_sign_tbs(const uint8_t *tbs,
|
||||
size_t tbs_len,
|
||||
uint8_t *sig,
|
||||
size_t *sig_len,
|
||||
const struct wolfboot_dice_claims *claims)
|
||||
{
|
||||
int ret = WOLFBOOT_DICE_ERR_CRYPTO;
|
||||
uint8_t hash[SHA256_DIGEST_SIZE];
|
||||
#ifndef WOLFBOOT_DICE_HW
|
||||
ecc_key key;
|
||||
int key_inited = 0;
|
||||
WC_RNG rng;
|
||||
int wc_ret;
|
||||
int rng_inited = 0;
|
||||
uint8_t der_sig[128];
|
||||
word32 der_sig_len = sizeof(der_sig);
|
||||
uint8_t r[WOLFBOOT_DICE_SIG_LEN / 2];
|
||||
uint8_t s[WOLFBOOT_DICE_SIG_LEN / 2];
|
||||
word32 r_len = sizeof(r);
|
||||
word32 s_len = sizeof(s);
|
||||
#endif /* !WOLFBOOT_DICE_HW */
|
||||
|
||||
if (sig == NULL || sig_len == NULL || *sig_len < WOLFBOOT_DICE_SIG_LEN) {
|
||||
return WOLFBOOT_DICE_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
#ifdef WOLFBOOT_DICE_HW
|
||||
if (wolfboot_attest_get_private_key_hw(claims) != 0) {
|
||||
ret = WOLFBOOT_DICE_ERR_HW;
|
||||
goto cleanup;
|
||||
static int wolfboot_dice_hw_sign_cb(void *cbCtx, int32_t alg,
|
||||
const uint8_t *tbs, size_t tbs_len,
|
||||
uint8_t *sig, size_t sig_sz,
|
||||
size_t *sig_len)
|
||||
{
|
||||
int *sign_failed = (int *)cbCtx;
|
||||
size_t out_len = sig_sz;
|
||||
|
||||
(void)alg;
|
||||
|
||||
/* wolfCOSE pre-hashes the Sig_structure for ES256, so tbs is the 32-byte
|
||||
* digest. hal_dice_sign_hash() outputs 64-byte raw R||S and keeps the
|
||||
* private key inside the platform boundary. */
|
||||
if (hal_dice_sign_hash(tbs, tbs_len, sig, &out_len) != 0) {
|
||||
if (sign_failed != NULL) {
|
||||
*sign_failed = 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
*sig_len = out_len;
|
||||
return 0;
|
||||
}
|
||||
#endif /* WOLFBOOT_DICE_HW */
|
||||
|
||||
#ifndef WOLFBOOT_DICE_HW
|
||||
/* Kept out of line so the secure-world sign path does not widen the caller's
|
||||
* frame, which the size query also pays for. */
|
||||
static int NOINLINEFUNCTION wolfboot_dice_sign_payload(
|
||||
WOLFCOSE_KEY *cose_key,
|
||||
struct wolfboot_dice_claims *claims,
|
||||
const uint8_t *payload,
|
||||
size_t payload_len,
|
||||
uint8_t *scratch,
|
||||
size_t scratch_len,
|
||||
uint8_t *token_buf,
|
||||
size_t token_buf_size,
|
||||
size_t *out_len)
|
||||
{
|
||||
ecc_key key;
|
||||
WC_RNG rng;
|
||||
int key_inited = 0;
|
||||
int rng_inited = 0;
|
||||
int ret;
|
||||
|
||||
wc_ecc_init(&key);
|
||||
key_inited = 1;
|
||||
if (wolfboot_attest_get_private_key(&key, claims) != 0) {
|
||||
ret = WOLFBOOT_DICE_ERR_HW;
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WOLFBOOT_DICE_HW
|
||||
(void)wc_ecc_set_deterministic(&key, 1);
|
||||
if (wc_InitRng(&rng) != 0) {
|
||||
ret = WOLFBOOT_DICE_ERR_HW;
|
||||
goto cleanup;
|
||||
}
|
||||
rng_inited = 1;
|
||||
#endif /* !WOLFBOOT_DICE_HW */
|
||||
|
||||
{
|
||||
wc_Sha256 sha;
|
||||
ret = wc_InitSha256(&sha);
|
||||
if (ret == 0) {
|
||||
ret = wc_Sha256Update(&sha, tbs, (word32)tbs_len);
|
||||
if (ret == 0) {
|
||||
ret = wc_Sha256Final(&sha, hash);
|
||||
}
|
||||
wc_Sha256Free(&sha);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
ret = WOLFBOOT_DICE_ERR_CRYPTO;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WOLFBOOT_DICE_HW
|
||||
/* Platform attestation key is ready. Sign pre-computed hash via HAL.
|
||||
* hal_dice_sign_hash() MUST output 64-byte raw R||S (big-endian), NOT DER.
|
||||
* This matches WOLFBOOT_DICE_SIG_LEN and the COSE_Sign1 signature field directly,
|
||||
* bypassing the wc_ecc_sig_to_rs DER->raw conversion that the software path needs. */
|
||||
ret = hal_dice_sign_hash(hash, sizeof(hash), sig, sig_len);
|
||||
if (ret != 0)
|
||||
ret = WOLFBOOT_DICE_ERR_HW;
|
||||
#else /* !WOLFBOOT_DICE_HW */
|
||||
wc_ret = wc_ecc_sign_hash(hash, sizeof(hash), der_sig, &der_sig_len, &rng, &key);
|
||||
if (wc_ret != 0) {
|
||||
ret = wc_CoseKey_SetEcc(cose_key, WOLFCOSE_CRV_P256, &key);
|
||||
if (ret != 0) {
|
||||
ret = WOLFBOOT_DICE_ERR_CRYPTO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
wc_ret = wc_ecc_sig_to_rs(der_sig, der_sig_len, r, &r_len, s, &s_len);
|
||||
if (wc_ret != 0 || r_len > sizeof(r) || s_len > sizeof(s)) {
|
||||
ret = wc_CoseSign1_Sign_ex(cose_key, WOLFCOSE_ALG_ES256, NULL, 0,
|
||||
payload, payload_len, NULL, 0, NULL, 0,
|
||||
scratch, scratch_len, token_buf, token_buf_size,
|
||||
out_len, &rng, WOLFCOSE_SIGN1_UNTAGGED);
|
||||
if (ret != 0) {
|
||||
ret = WOLFBOOT_DICE_ERR_CRYPTO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
XMEMSET(sig, 0, WOLFBOOT_DICE_SIG_LEN);
|
||||
XMEMCPY(sig + (sizeof(r) - r_len), r, r_len);
|
||||
XMEMCPY(sig + sizeof(r) + (sizeof(s) - s_len), s, s_len);
|
||||
*sig_len = WOLFBOOT_DICE_SIG_LEN;
|
||||
ret = WOLFBOOT_DICE_SUCCESS;
|
||||
#endif /* !WOLFBOOT_DICE_HW */
|
||||
|
||||
cleanup:
|
||||
#ifndef WOLFBOOT_DICE_HW
|
||||
if (key_inited) {
|
||||
wc_ecc_free(&key);
|
||||
wolfboot_dice_zeroize(&key, sizeof(key));
|
||||
|
|
@ -983,11 +862,9 @@ cleanup:
|
|||
if (rng_inited) {
|
||||
wc_FreeRng(&rng);
|
||||
}
|
||||
wolfboot_dice_zeroize(der_sig, sizeof(der_sig));
|
||||
#endif /* !WOLFBOOT_DICE_HW */
|
||||
wolfboot_dice_zeroize(hash, sizeof(hash));
|
||||
return ret;
|
||||
}
|
||||
#endif /* !WOLFBOOT_DICE_HW */
|
||||
|
||||
static int wolfboot_dice_build_token(uint8_t *token_buf,
|
||||
size_t token_buf_size,
|
||||
|
|
@ -998,13 +875,13 @@ static int wolfboot_dice_build_token(uint8_t *token_buf,
|
|||
struct wolfboot_dice_claims claims;
|
||||
uint8_t payload[WOLFBOOT_DICE_MAX_PAYLOAD];
|
||||
size_t payload_len = 0;
|
||||
uint8_t protected_hdr[32];
|
||||
size_t protected_len = 0;
|
||||
uint8_t tbs[WOLFBOOT_DICE_MAX_TBS];
|
||||
size_t tbs_len = 0;
|
||||
uint8_t sig[WOLFBOOT_DICE_SIG_LEN];
|
||||
size_t sig_len = sizeof(sig);
|
||||
struct wolfboot_cbor_writer w;
|
||||
uint8_t scratch[WOLFBOOT_DICE_MAX_TBS];
|
||||
WOLFCOSE_KEY cose_key;
|
||||
int cose_key_inited = 0;
|
||||
#ifdef WOLFBOOT_DICE_HW
|
||||
int hw_sign_failed = 0;
|
||||
#endif
|
||||
size_t out_len = 0;
|
||||
int ret;
|
||||
|
||||
ret = wolfboot_dice_collect_claims(&claims);
|
||||
|
|
@ -1018,48 +895,71 @@ static int wolfboot_dice_build_token(uint8_t *token_buf,
|
|||
ret = wolfboot_dice_encode_payload(payload, sizeof(payload), &claims,
|
||||
&payload_len);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = wolfboot_dice_encode_protected(protected_hdr, sizeof(protected_hdr),
|
||||
&protected_len);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wolfboot_dice_build_sig_structure(tbs, sizeof(tbs),
|
||||
protected_hdr, protected_len,
|
||||
payload, payload_len, &tbs_len);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (token_buf != NULL) {
|
||||
ret = wolfboot_dice_sign_tbs(tbs, tbs_len, sig, &sig_len, &claims);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
/* Size query returns the exact untagged COSE_Sign1 length without signing:
|
||||
* the HW DICE engine must not run and the CDI must not advance while sizing. */
|
||||
if (token_buf == NULL) {
|
||||
ret = wc_CoseSign1_SignSize_ex(NULL, WOLFCOSE_ALG_ES256, 0,
|
||||
payload_len, 0,
|
||||
WOLFCOSE_SIGN1_UNTAGGED, &out_len);
|
||||
if (ret == 0) {
|
||||
*token_len = out_len;
|
||||
}
|
||||
else {
|
||||
ret = WOLFBOOT_DICE_ERR_CRYPTO;
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
wolfboot_cbor_init(&w, token_buf, token_buf_size);
|
||||
wolfboot_cbor_put_array_start(&w, 4);
|
||||
wolfboot_cbor_put_bstr(&w, protected_hdr, protected_len);
|
||||
wolfboot_cbor_put_map_start(&w, 0);
|
||||
wolfboot_cbor_put_bstr(&w, payload, payload_len);
|
||||
if (token_buf != NULL) {
|
||||
wolfboot_cbor_put_bstr(&w, sig, sig_len);
|
||||
}
|
||||
else {
|
||||
wolfboot_cbor_put_type_val(&w, 2, WOLFBOOT_DICE_SIG_LEN);
|
||||
wolfboot_cbor_reserve(&w, WOLFBOOT_DICE_SIG_LEN);
|
||||
ret = wc_CoseKey_Init(&cose_key);
|
||||
if (ret != 0) {
|
||||
ret = WOLFBOOT_DICE_ERR_CRYPTO;
|
||||
goto cleanup;
|
||||
}
|
||||
cose_key_inited = 1;
|
||||
|
||||
if (w.error != 0) {
|
||||
return w.error;
|
||||
#ifdef WOLFBOOT_DICE_HW
|
||||
if (wolfboot_attest_get_private_key_hw(&claims) != 0) {
|
||||
ret = WOLFBOOT_DICE_ERR_HW;
|
||||
goto cleanup;
|
||||
}
|
||||
ret = wc_CoseKey_SetExtSigner(&cose_key, wolfboot_dice_hw_sign_cb,
|
||||
&hw_sign_failed);
|
||||
if (ret != 0) {
|
||||
ret = WOLFBOOT_DICE_ERR_CRYPTO;
|
||||
goto cleanup;
|
||||
}
|
||||
ret = wc_CoseSign1_Sign_ex(&cose_key, WOLFCOSE_ALG_ES256, NULL, 0,
|
||||
payload, payload_len, NULL, 0, NULL, 0,
|
||||
scratch, sizeof(scratch), token_buf,
|
||||
token_buf_size, &out_len, NULL,
|
||||
WOLFCOSE_SIGN1_UNTAGGED);
|
||||
if (ret != 0) {
|
||||
ret = hw_sign_failed ? WOLFBOOT_DICE_ERR_HW :
|
||||
WOLFBOOT_DICE_ERR_CRYPTO;
|
||||
goto cleanup;
|
||||
}
|
||||
#else
|
||||
ret = wolfboot_dice_sign_payload(&cose_key, &claims, payload, payload_len,
|
||||
scratch, sizeof(scratch),
|
||||
token_buf, token_buf_size, &out_len);
|
||||
if (ret != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
#endif /* WOLFBOOT_DICE_HW */
|
||||
|
||||
*token_len = w.offset;
|
||||
return WOLFBOOT_DICE_SUCCESS;
|
||||
*token_len = out_len;
|
||||
ret = WOLFBOOT_DICE_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
if (cose_key_inited) {
|
||||
wc_CoseKey_Free(&cose_key);
|
||||
}
|
||||
wolfboot_dice_zeroize(payload, sizeof(payload));
|
||||
wolfboot_dice_zeroize(scratch, sizeof(scratch));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wolfBoot_dice_get_token(const uint8_t *challenge,
|
||||
|
|
|
|||
|
|
@ -754,7 +754,8 @@ static int run_psa_boot_attestation(void)
|
|||
#if (APP_HASH_SIZE > 0u)
|
||||
uint8_t hash_buf[APP_HASH_SIZE];
|
||||
#endif
|
||||
size_t token_size = 0;
|
||||
size_t queried_token_size;
|
||||
size_t emitted_token_size;
|
||||
int ret = 0;
|
||||
size_t i;
|
||||
|
||||
|
|
@ -802,30 +803,39 @@ static int run_psa_boot_attestation(void)
|
|||
}
|
||||
|
||||
printf(" step 5: request IAT token size\r\n");
|
||||
status = psa_initial_attest_get_token_size(sizeof(challenge), &token_size);
|
||||
queried_token_size = 0;
|
||||
status = psa_initial_attest_get_token_size(sizeof(challenge),
|
||||
&queried_token_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printf(" step 5: token size failed (%ld)\r\n", (long)status);
|
||||
ret = -1;
|
||||
} else {
|
||||
printf(" step 5: token size %lu bytes\r\n",
|
||||
(unsigned long)token_size);
|
||||
(unsigned long)queried_token_size);
|
||||
}
|
||||
|
||||
printf(" step 6: request IAT token\r\n");
|
||||
if (ret == 0 && token_size <= sizeof(token)) {
|
||||
printf(" step 6: request exact-size IAT token\r\n");
|
||||
if (ret == 0 && queried_token_size <= sizeof(token)) {
|
||||
emitted_token_size = 0;
|
||||
status = psa_initial_attest_get_token(challenge, sizeof(challenge),
|
||||
token, sizeof(token), &token_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printf(" step 6: token failed (%ld)\r\n", (long)status);
|
||||
token, queried_token_size,
|
||||
&emitted_token_size);
|
||||
if (status != PSA_SUCCESS ||
|
||||
emitted_token_size != queried_token_size) {
|
||||
printf(" step 6: size mismatch (status=%ld size=%lu "
|
||||
"expected=%lu)\r\n", (long)status,
|
||||
(unsigned long)emitted_token_size,
|
||||
(unsigned long)queried_token_size);
|
||||
ret = -1;
|
||||
} else {
|
||||
printf(" step 6: token received (%lu bytes)\r\n",
|
||||
(unsigned long)token_size);
|
||||
print_hex(token, (uint32_t)token_size, 1);
|
||||
printf(" IAT size match: challenge=64 token=%lu\r\n",
|
||||
(unsigned long)emitted_token_size);
|
||||
print_hex(token, (uint32_t)emitted_token_size, 1);
|
||||
}
|
||||
} else if (ret == 0) {
|
||||
printf(" step 6: token buffer too small (%lu > %lu)\r\n",
|
||||
(unsigned long)token_size, (unsigned long)sizeof(token));
|
||||
(unsigned long)queried_token_size,
|
||||
(unsigned long)sizeof(token));
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ WOLFBOOT_LIB_WOLFPKCS11?=../../lib/wolfPKCS11
|
|||
WOLFBOOT_LIB_WOLFPSA?=../../lib/wolfPSA
|
||||
WOLFBOOT_LIB_WOLFTPM?=../../lib/wolfTPM
|
||||
WOLFBOOT_LIB_WOLFHSM?=../../lib/wolfHSM
|
||||
WOLFBOOT_LIB_WOLFCOSE?=../../lib/wolfCOSE
|
||||
|
||||
ifeq ($(wildcard $(WOLFBOOT_LIB_WOLFPSA)),)
|
||||
WOLFBOOT_LIB_WOLFPSA=../../../external-libs/wolfPSA
|
||||
|
|
@ -21,6 +22,9 @@ endif
|
|||
ifeq ($(wildcard $(WOLFBOOT_LIB_WOLFHSM)),)
|
||||
WOLFBOOT_LIB_WOLFHSM=../../../external-libs/wolfHSM
|
||||
endif
|
||||
ifeq ($(wildcard $(WOLFBOOT_LIB_WOLFCOSE)),)
|
||||
WOLFBOOT_LIB_WOLFCOSE=../../../external-libs/wolfCOSE
|
||||
endif
|
||||
|
||||
# Convert to absolute paths for standalone usage
|
||||
WOLFBOOT_LIB_WOLFSSL:=$(abspath $(WOLFBOOT_LIB_WOLFSSL))
|
||||
|
|
@ -28,6 +32,7 @@ WOLFBOOT_LIB_WOLFPKCS11:=$(abspath $(WOLFBOOT_LIB_WOLFPKCS11))
|
|||
WOLFBOOT_LIB_WOLFPSA:=$(abspath $(WOLFBOOT_LIB_WOLFPSA))
|
||||
WOLFBOOT_LIB_WOLFTPM:=$(abspath $(WOLFBOOT_LIB_WOLFTPM))
|
||||
WOLFBOOT_LIB_WOLFHSM:=$(abspath $(WOLFBOOT_LIB_WOLFHSM))
|
||||
WOLFBOOT_LIB_WOLFCOSE:=$(abspath $(WOLFBOOT_LIB_WOLFCOSE))
|
||||
|
||||
CFLAGS=-I. -I../../src -I../../include -I$(WOLFBOOT_LIB_WOLFSSL)
|
||||
CFLAGS+=-g -ggdb
|
||||
|
|
@ -88,6 +93,8 @@ TESTS+=unit-fwtpm-nv-oob
|
|||
TESTS+=unit-elf-bss-guard
|
||||
TESTS+=unit-image-elf-scatter
|
||||
TESTS+=unit-arm-tee-psa-ipc
|
||||
TESTS+=unit-dice-token-size
|
||||
TESTS+=unit-dice-token-nosign
|
||||
TESTS+=unit-va416x0-fram
|
||||
TESTS+=unit-flash-write-mcxa
|
||||
TESTS+=unit-flash-write-samr21
|
||||
|
|
@ -376,6 +383,24 @@ unit-arm-tee-psa-ipc: ../../include/target.h unit-arm-tee-psa-ipc.c ../../src/ar
|
|||
-ffunction-sections -fdata-sections \
|
||||
$(LDFLAGS) -Wl,--gc-sections
|
||||
|
||||
DICE_TOKEN_TEST_CFLAGS=-I$(WOLFBOOT_LIB_WOLFCOSE)/include \
|
||||
-I$(WOLFBOOT_LIB_WOLFSSL) -DUNIT_TEST_AUTH -DWOLFBOOT_SIGN_ECC256 \
|
||||
-DWOLFCRYPT_SECURE_MODE -DHAVE_HKDF -DWOLFBOOT_NO_PARTITIONS \
|
||||
-DWOLFCOSE_LEAN -DWOLFCOSE_ENABLE_EXT_SIGN \
|
||||
-ffunction-sections -fdata-sections
|
||||
unit-dice-token-size:CFLAGS+=$(DICE_TOKEN_TEST_CFLAGS)
|
||||
unit-dice-token-nosign:CFLAGS+=$(DICE_TOKEN_TEST_CFLAGS) -DWOLFBOOT_NO_SIGN
|
||||
DICE_TOKEN_TEST_SRC=unit-dice-token-size.c \
|
||||
$(WOLFBOOT_LIB_WOLFCOSE)/src/wolfcose.c \
|
||||
$(WOLFBOOT_LIB_WOLFCOSE)/src/wolfcose_cbor.c \
|
||||
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c \
|
||||
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/hash.c \
|
||||
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/memory.c
|
||||
unit-dice-token-size unit-dice-token-nosign: ../../include/target.h \
|
||||
$(DICE_TOKEN_TEST_SRC)
|
||||
gcc -o $@ $(DICE_TOKEN_TEST_SRC) $(CFLAGS) $(LDFLAGS) \
|
||||
-Wl,--gc-sections
|
||||
|
||||
unit-va416x0-fram: unit-va416x0-fram.c ../../hal/va416x0.c
|
||||
gcc -o $@ unit-va416x0-fram.c $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,366 @@
|
|||
/* unit-dice-token-size.c
|
||||
*
|
||||
* DICE COSE_Sign1 token sizing tests.
|
||||
*
|
||||
* Copyright (C) 2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
*
|
||||
* wolfBoot is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static uint8_t test_wolfboot_region[64];
|
||||
|
||||
#define ARCH_FLASH_OFFSET 0x1000u
|
||||
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x1040u
|
||||
#define EXT_FLASH
|
||||
#define NO_XIP
|
||||
#define WOLFBOOT_DICE_HW
|
||||
#define WOLFBOOT_HASH_SHA256
|
||||
|
||||
#include "../../src/dice/dice.c"
|
||||
|
||||
static uint8_t test_boot_hash[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||
static uint8_t test_boot_signer_id[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||
static unsigned int test_cdi_update_calls;
|
||||
static unsigned int test_key_create_calls;
|
||||
static unsigned int test_sign_calls;
|
||||
static int test_sign_result;
|
||||
|
||||
/* Local ECC signing must never be reached: this test exercises the delegated
|
||||
* hardware-signing path. These stubs keep that failure mode link-visible. */
|
||||
int wc_ecc_sign_hash(const byte *in, word32 in_len, byte *out,
|
||||
word32 *out_len, WC_RNG *rng, ecc_key *key)
|
||||
{
|
||||
(void)in;
|
||||
(void)in_len;
|
||||
(void)out;
|
||||
(void)out_len;
|
||||
(void)rng;
|
||||
(void)key;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int wc_ecc_sig_to_rs(const byte *sig, word32 sig_len, byte *r,
|
||||
word32 *r_len, byte *s, word32 *s_len)
|
||||
{
|
||||
(void)sig;
|
||||
(void)sig_len;
|
||||
(void)r;
|
||||
(void)r_len;
|
||||
(void)s;
|
||||
(void)s_len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ext_flash_read(uintptr_t address, uint8_t *data, int len)
|
||||
{
|
||||
size_t offset;
|
||||
|
||||
if (address < ARCH_FLASH_OFFSET || data == NULL || len < 0) {
|
||||
return -1;
|
||||
}
|
||||
offset = (size_t)(address - ARCH_FLASH_OFFSET);
|
||||
if (offset > sizeof(test_wolfboot_region) ||
|
||||
(size_t)len > sizeof(test_wolfboot_region) - offset) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(data, test_wolfboot_region + offset, (size_t)len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part)
|
||||
{
|
||||
(void)img;
|
||||
return part == PART_BOOT ? 0 : -1;
|
||||
}
|
||||
|
||||
uint16_t wolfBoot_get_header(struct wolfBoot_image *img, uint16_t type,
|
||||
uint8_t **ptr)
|
||||
{
|
||||
(void)img;
|
||||
if (ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (type == HDR_HASH) {
|
||||
*ptr = test_boot_hash;
|
||||
}
|
||||
else if (type == HDR_PUBKEY) {
|
||||
*ptr = test_boot_signer_id;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
return (uint16_t)sizeof(test_boot_hash);
|
||||
}
|
||||
|
||||
int hal_attestation_get_ueid(uint8_t *buf, size_t *len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (buf == NULL || len == NULL || *len < WOLFBOOT_DICE_UEID_LEN) {
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < WOLFBOOT_DICE_UEID_LEN; i++) {
|
||||
buf[i] = (uint8_t)(i + 1u);
|
||||
}
|
||||
*len = WOLFBOOT_DICE_UEID_LEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_attestation_get_implementation_id(uint8_t *buf, size_t *len)
|
||||
{
|
||||
if (buf == NULL || len == NULL || *len < WOLFBOOT_SHA_DIGEST_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
memset(buf, 0xA5, WOLFBOOT_SHA_DIGEST_SIZE);
|
||||
*len = WOLFBOOT_SHA_DIGEST_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_attestation_get_lifecycle(uint32_t *lifecycle)
|
||||
{
|
||||
if (lifecycle == NULL) {
|
||||
return -1;
|
||||
}
|
||||
*lifecycle = 0x3000u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_dice_update_cdi(const uint8_t *measurement, size_t meas_len,
|
||||
const char *measurement_desc,
|
||||
size_t measurement_desc_len)
|
||||
{
|
||||
test_cdi_update_calls++;
|
||||
return measurement != NULL && meas_len > 0u &&
|
||||
measurement_desc != NULL && measurement_desc_len > 0u ? 0 : -1;
|
||||
}
|
||||
|
||||
int hal_dice_create_attest_key(void)
|
||||
{
|
||||
test_key_create_calls++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_dice_sign_hash(const uint8_t *hash, size_t hash_len,
|
||||
uint8_t *sig, size_t *sig_len)
|
||||
{
|
||||
test_sign_calls++;
|
||||
if (hash == NULL || hash_len != SHA256_DIGEST_SIZE || sig == NULL ||
|
||||
sig_len == NULL || *sig_len < 64u) {
|
||||
return -1;
|
||||
}
|
||||
if (test_sign_result != 0) {
|
||||
return test_sign_result;
|
||||
}
|
||||
memset(sig, 0x5A, 64u);
|
||||
*sig_len = 64u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hal_dice_get_attest_pubkey(uint8_t *buf, size_t *len)
|
||||
{
|
||||
(void)buf;
|
||||
(void)len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void check_component_signer_ids(const uint8_t *token, size_t token_size)
|
||||
{
|
||||
WOLFCOSE_CBOR_CTX token_ctx;
|
||||
WOLFCOSE_CBOR_CTX payload_ctx;
|
||||
const uint8_t *payload;
|
||||
const uint8_t *value;
|
||||
size_t array_count;
|
||||
size_t map_count;
|
||||
size_t payload_len;
|
||||
size_t value_len;
|
||||
size_t i;
|
||||
size_t j;
|
||||
uint8_t unknown_signer[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||
int64_t label;
|
||||
int found_components = 0;
|
||||
int found_signer;
|
||||
|
||||
memset(&token_ctx, 0, sizeof(token_ctx));
|
||||
memset(unknown_signer, 0, sizeof(unknown_signer));
|
||||
token_ctx.cbuf = token;
|
||||
token_ctx.bufSz = token_size;
|
||||
|
||||
ck_assert_int_eq(wc_CBOR_DecodeArrayStart(&token_ctx, &array_count), 0);
|
||||
ck_assert_uint_eq(array_count, 4u);
|
||||
ck_assert_int_eq(wc_CBOR_DecodeBstr(&token_ctx, &value, &value_len), 0);
|
||||
ck_assert_int_eq(wc_CBOR_DecodeMapStart(&token_ctx, &map_count), 0);
|
||||
ck_assert_uint_eq(map_count, 0u);
|
||||
ck_assert_int_eq(wc_CBOR_DecodeBstr(&token_ctx, &payload, &payload_len), 0);
|
||||
ck_assert_int_eq(wc_CBOR_DecodeBstr(&token_ctx, &value, &value_len), 0);
|
||||
ck_assert_uint_eq(token_ctx.idx, token_ctx.bufSz);
|
||||
|
||||
memset(&payload_ctx, 0, sizeof(payload_ctx));
|
||||
payload_ctx.cbuf = payload;
|
||||
payload_ctx.bufSz = payload_len;
|
||||
ck_assert_int_eq(wc_CBOR_DecodeMapStart(&payload_ctx, &map_count), 0);
|
||||
for (i = 0; i < map_count; i++) {
|
||||
ck_assert_int_eq(wc_CBOR_DecodeInt(&payload_ctx, &label), 0);
|
||||
if (label != PSA_IAT_CLAIM_SW_COMPONENTS) {
|
||||
ck_assert_int_eq(wc_CBOR_Skip(&payload_ctx), 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
found_components = 1;
|
||||
ck_assert_int_eq(wc_CBOR_DecodeArrayStart(&payload_ctx,
|
||||
&array_count), 0);
|
||||
ck_assert_uint_eq(array_count, 2u);
|
||||
for (j = 0; j < array_count; j++) {
|
||||
size_t component_fields;
|
||||
size_t k;
|
||||
|
||||
found_signer = 0;
|
||||
ck_assert_int_eq(wc_CBOR_DecodeMapStart(&payload_ctx,
|
||||
&component_fields), 0);
|
||||
ck_assert_uint_eq(component_fields, 4u);
|
||||
for (k = 0; k < component_fields; k++) {
|
||||
ck_assert_int_eq(wc_CBOR_DecodeInt(&payload_ctx, &label), 0);
|
||||
if (label != PSA_SW_COMPONENT_SIGNER_ID) {
|
||||
ck_assert_int_eq(wc_CBOR_Skip(&payload_ctx), 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
ck_assert_int_eq(wc_CBOR_DecodeBstr(&payload_ctx, &value,
|
||||
&value_len), 0);
|
||||
ck_assert_uint_eq(value_len, WOLFBOOT_SHA_DIGEST_SIZE);
|
||||
if (j == 0u) {
|
||||
ck_assert_mem_eq(value, unknown_signer,
|
||||
sizeof(unknown_signer));
|
||||
}
|
||||
else {
|
||||
#ifdef WOLFBOOT_NO_SIGN
|
||||
ck_assert_mem_eq(value, unknown_signer,
|
||||
sizeof(unknown_signer));
|
||||
#else
|
||||
ck_assert_mem_eq(value, test_boot_signer_id,
|
||||
sizeof(test_boot_signer_id));
|
||||
#endif
|
||||
}
|
||||
found_signer = 1;
|
||||
}
|
||||
ck_assert_int_eq(found_signer, 1);
|
||||
}
|
||||
}
|
||||
ck_assert_int_eq(found_components, 1);
|
||||
ck_assert_uint_eq(payload_ctx.idx, payload_ctx.bufSz);
|
||||
}
|
||||
|
||||
static void check_token_size(size_t challenge_size)
|
||||
{
|
||||
uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64];
|
||||
uint8_t token[WOLFBOOT_DICE_MAX_PAYLOAD + 128u];
|
||||
size_t queried_size = 0;
|
||||
size_t actual_size = 0;
|
||||
size_t short_size = 0;
|
||||
int ret;
|
||||
|
||||
memset(challenge, 0x3C, sizeof(challenge));
|
||||
memset(test_boot_signer_id, 0xA7, sizeof(test_boot_signer_id));
|
||||
test_cdi_update_calls = 0;
|
||||
test_key_create_calls = 0;
|
||||
test_sign_calls = 0;
|
||||
test_sign_result = 0;
|
||||
|
||||
ret = wolfBoot_dice_get_token_size(challenge_size, &queried_size);
|
||||
ck_assert_int_eq(ret, WOLFBOOT_DICE_SUCCESS);
|
||||
ck_assert_uint_gt(queried_size, 0u);
|
||||
ck_assert_uint_le(queried_size, sizeof(token));
|
||||
ck_assert_uint_eq(test_cdi_update_calls, 0u);
|
||||
ck_assert_uint_eq(test_key_create_calls, 0u);
|
||||
ck_assert_uint_eq(test_sign_calls, 0u);
|
||||
|
||||
ret = wolfBoot_dice_get_token(challenge, challenge_size, token,
|
||||
queried_size - 1u, &short_size);
|
||||
ck_assert_int_eq(ret, WOLFBOOT_DICE_ERR_BUFFER_TOO_SMALL);
|
||||
ck_assert_uint_eq(short_size, queried_size);
|
||||
ck_assert_uint_eq(test_cdi_update_calls, 0u);
|
||||
ck_assert_uint_eq(test_key_create_calls, 0u);
|
||||
ck_assert_uint_eq(test_sign_calls, 0u);
|
||||
|
||||
ret = wolfBoot_dice_get_token(challenge, challenge_size, token,
|
||||
queried_size, &actual_size);
|
||||
ck_assert_int_eq(ret, WOLFBOOT_DICE_SUCCESS);
|
||||
ck_assert_uint_eq(actual_size, queried_size);
|
||||
ck_assert_uint_eq(test_cdi_update_calls, 2u);
|
||||
ck_assert_uint_eq(test_key_create_calls, 1u);
|
||||
ck_assert_uint_eq(test_sign_calls, 1u);
|
||||
check_component_signer_ids(token, actual_size);
|
||||
}
|
||||
|
||||
START_TEST(test_dice_token_size_32)
|
||||
{
|
||||
check_token_size(PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_dice_hw_sign_failure)
|
||||
{
|
||||
uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32];
|
||||
uint8_t token[WOLFBOOT_DICE_MAX_PAYLOAD + 128u];
|
||||
size_t token_size = 0;
|
||||
int ret;
|
||||
|
||||
memset(challenge, 0x3C, sizeof(challenge));
|
||||
memset(test_boot_signer_id, 0xA7, sizeof(test_boot_signer_id));
|
||||
test_cdi_update_calls = 0;
|
||||
test_key_create_calls = 0;
|
||||
test_sign_calls = 0;
|
||||
test_sign_result = -1;
|
||||
|
||||
ret = wolfBoot_dice_get_token(challenge, sizeof(challenge), token,
|
||||
sizeof(token), &token_size);
|
||||
ck_assert_int_eq(ret, WOLFBOOT_DICE_ERR_HW);
|
||||
ck_assert_uint_eq(test_sign_calls, 1u);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_dice_token_size_48)
|
||||
{
|
||||
check_token_size(PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_dice_token_size_64)
|
||||
{
|
||||
check_token_size(PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Suite *dice_token_size_suite(void)
|
||||
{
|
||||
Suite *suite = suite_create("dice-token-size");
|
||||
TCase *test_case = tcase_create("size-consistency");
|
||||
|
||||
tcase_add_test(test_case, test_dice_token_size_32);
|
||||
tcase_add_test(test_case, test_dice_token_size_48);
|
||||
tcase_add_test(test_case, test_dice_token_size_64);
|
||||
tcase_add_test(test_case, test_dice_hw_sign_failure);
|
||||
suite_add_tcase(suite, test_case);
|
||||
return suite;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int failures;
|
||||
Suite *suite = dice_token_size_suite();
|
||||
SRunner *runner = srunner_create(suite);
|
||||
|
||||
srunner_run_all(runner, CK_NORMAL);
|
||||
failures = srunner_ntests_failed(runner);
|
||||
srunner_free(runner);
|
||||
return failures;
|
||||
}
|
||||
Loading…
Reference in New Issue