Merge pull request #740 from danielinux/fixes-20260330

Fixes 20260330
pull/744/head
Mattia Moffa 2026-03-31 14:33:52 +02:00 committed by GitHub
commit 084431ba87
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 885 additions and 44 deletions

View File

@ -8,7 +8,7 @@ jobs:
trustzone-emulator-tests:
runs-on: ubuntu-latest
container:
image: ghcr.io/wolfssl/wolfboot-ci-m33mu:v1.0
image: ghcr.io/wolfssl/wolfboot-ci-m33mu:latest
steps:
- uses: actions/checkout@v4

7
.gitignore vendored
View File

@ -171,6 +171,11 @@ tools/unit-tests/unit-store-sbrk
tools/unit-tests/unit-tpm-blob
tools/unit-tests/unit-update-disk
tools/unit-tests/unit-policy-sign
tools/unit-tests/unit-fdt
tools/unit-tests/unit-hal-otp
tools/unit-tests/unit-rot-auth
tools/unit-tests/unit-sdhci-response-bits
tools/unit-tests/unit-tpm-check-rot-auth
@ -362,3 +367,5 @@ image.ub
system-default.dtb
test_output/
sdcard.img

View File

@ -764,20 +764,15 @@ void hal_prepare_boot(void)
int hal_flash_otp_set_readonly(uint32_t flashAddress, uint16_t length)
{
uint32_t start_block = (flashAddress - FLASH_OTP_BASE) / FLASH_OTP_BLOCK_SIZE;
uint32_t count = length / FLASH_OTP_BLOCK_SIZE;
uint32_t count = (length + FLASH_OTP_BLOCK_SIZE - 1U) / FLASH_OTP_BLOCK_SIZE;
uint32_t bmap = 0;
unsigned int i;
if (start_block + count > 32)
return -1;
if ((length % FLASH_OTP_BLOCK_SIZE) != 0)
{
count++;
}
/* Turn on the bits */
for (i = start_block; i < (start_block + count); i++) {
bmap |= (1 << i);
bmap |= (1U << i);
}
/* Enable OTP write protection for the selected blocks */
while ((bmap & FLASH_OTPBLR_CUR) != bmap) {

View File

@ -522,9 +522,26 @@ const char* fdt_get_name(const void *fdt, int nodeoffset, int *len)
const char* fdt_get_string(const void *fdt, int stroffset, int *lenp)
{
const char *s = (const char*)fdt + fdt_off_dt_strings(fdt) + stroffset;
uint32_t strsize = fdt_size_dt_strings(fdt);
const char *s;
const char *end;
if ((stroffset < 0) || ((uint32_t)stroffset >= strsize)) {
if (lenp)
*lenp = -FDT_ERR_BADOFFSET;
return NULL;
}
s = (const char*)fdt + fdt_off_dt_strings(fdt) + stroffset;
end = memchr(s, '\0', strsize - (uint32_t)stroffset);
if (end == NULL) {
if (lenp)
*lenp = -FDT_ERR_BADSTRUCTURE;
return NULL;
}
if (lenp) {
*lenp = (int)strlen(s);
*lenp = (int)(end - s);
}
return s;
}

View File

@ -1882,7 +1882,7 @@ int pkcs11_crypto_init(void)
};
CK_ULONG search_attr_count = sizeof(search_attr) / sizeof(*search_attr);
CK_ULONG obj_count = 0;
int pkcs11_intiialized = 0, session_opened = 0, logged_in = 0;
int pkcs11_initialized = 0, session_opened = 0, logged_in = 0;
if (encrypt_initialized)
return 0;

View File

@ -244,7 +244,7 @@ static uint8_t *find_object_buffer(int32_t type, uint32_t tok_id, uint32_t obj_i
{
struct obj_hdr *hdr = NODES_TABLE;
uint32_t *tok_obj_stored = NULL;
while ((uintptr_t)hdr < ((uintptr_t)NODES_TABLE + WOLFBOOT_SECTOR_SIZE)) {
while ((uintptr_t)hdr < ((uintptr_t)vault_base + WOLFBOOT_SECTOR_SIZE)) {
if ((hdr->token_id == tok_id) && (hdr->object_id == obj_id)
&& (hdr->type == type)) {
tok_obj_stored = (uint32_t *) (vault_base + (2 * WOLFBOOT_SECTOR_SIZE) + (hdr->pos * KEYVAULT_OBJ_SIZE));
@ -275,7 +275,7 @@ static struct obj_hdr *find_object_header(int32_t type, uint32_t tok_id,
uint32_t obj_id)
{
struct obj_hdr *hdr = NODES_TABLE;
while ((uintptr_t)hdr < ((uintptr_t)NODES_TABLE + WOLFBOOT_SECTOR_SIZE)) {
while ((uintptr_t)hdr < ((uintptr_t)vault_base + WOLFBOOT_SECTOR_SIZE)) {
if ((hdr->token_id == tok_id) && (hdr->object_id == obj_id)
&& (hdr->type == type)) {
return hdr;

View File

@ -243,7 +243,7 @@ static uint8_t *find_object_buffer(int32_t type, uint32_t tok_id, uint32_t obj_i
{
struct obj_hdr *hdr = NODES_TABLE;
uint32_t *tok_obj_stored = NULL;
while ((uintptr_t)hdr < ((uintptr_t)NODES_TABLE + WOLFBOOT_SECTOR_SIZE)) {
while ((uintptr_t)hdr < ((uintptr_t)vault_base + WOLFBOOT_SECTOR_SIZE)) {
if ((hdr->token_id == tok_id) && (hdr->object_id == obj_id)
&& (hdr->type == type)) {
tok_obj_stored = (uint32_t *) (vault_base + (2 * WOLFBOOT_SECTOR_SIZE) + (hdr->pos * KEYVAULT_OBJ_SIZE));
@ -274,7 +274,7 @@ static struct obj_hdr *find_object_header(int32_t type, uint32_t tok_id,
uint32_t obj_id)
{
struct obj_hdr *hdr = NODES_TABLE;
while ((uintptr_t)hdr < ((uintptr_t)NODES_TABLE + WOLFBOOT_SECTOR_SIZE)) {
while ((uintptr_t)hdr < ((uintptr_t)vault_base + WOLFBOOT_SECTOR_SIZE)) {
if ((hdr->token_id == tok_id) && (hdr->object_id == obj_id)
&& (hdr->type == type)) {
return hdr;

View File

@ -565,7 +565,7 @@ static uint32_t sdhci_get_response_bits(int from, int count)
resp[3] = SDHCI_REG(SDHCI_SRS07);
ret = resp[off] >> shft;
if ((from + shft) > 32) {
if ((shft + count) > 32) {
ret |= resp[off + 1] << ((32 - shft) % 32);
}
return ret & mask;

View File

@ -1546,7 +1546,11 @@ int wolfBoot_check_rot(int key_slot, uint8_t* pubkey_hint)
memset(&nv, 0, sizeof(nv));
nv.handle.hndl = WOLFBOOT_TPM_KEYSTORE_NV_BASE + key_slot;
#ifdef WOLFBOOT_TPM_KEYSTORE_AUTH
nv.handle.auth.size = (UINT16)strlen(WOLFBOOT_TPM_KEYSTORE_AUTH);
size_t auth_sz = strlen(WOLFBOOT_TPM_KEYSTORE_AUTH);
if (auth_sz > (size_t)UINT16_MAX ||
auth_sz > sizeof(nv.handle.auth.buffer))
return BAD_FUNC_ARG;
nv.handle.auth.size = (UINT16)auth_sz;
memcpy(nv.handle.auth.buffer, WOLFBOOT_TPM_KEYSTORE_AUTH,
nv.handle.auth.size);
#endif

View File

@ -50,6 +50,23 @@ static const CK_BYTE test_payload[] = "wolfBoot PKCS11 persistent signing demo";
static const CK_BYTE test_ecc_p256_params[] = {
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07
};
static const CK_BYTE test_ecc_p256_priv[] = {
0xF8, 0xCF, 0x92, 0x6B, 0xBD, 0x1E, 0x28, 0xF1,
0xA8, 0xAB, 0xA1, 0x23, 0x4F, 0x32, 0x74, 0x18,
0x88, 0x50, 0xAD, 0x7E, 0xC7, 0xEC, 0x92, 0xF8,
0x8F, 0x97, 0x4D, 0xAF, 0x56, 0x89, 0x65, 0xC7
};
static const CK_BYTE test_ecc_p256_pub[] = {
0x04, 0x41, 0x04, 0x55, 0xBF, 0xF4, 0x0F, 0x44,
0x50, 0x9A, 0x3D, 0xCE, 0x9B, 0xB7, 0xF0, 0xC5,
0x4D, 0xF5, 0x70, 0x7B, 0xD4, 0xEC, 0x24, 0x8E,
0x19, 0x80, 0xEC, 0x5A, 0x4C, 0xA2, 0x24, 0x03,
0x62, 0x2C, 0x9B, 0xDA, 0xEF, 0xA2, 0x35, 0x12,
0x43, 0x84, 0x76, 0x16, 0xC6, 0x56, 0x95, 0x06,
0xCC, 0x01, 0xA9, 0xBD, 0xF6, 0x75, 0x1A, 0x42,
0xF7, 0xBD, 0xA9, 0xB2, 0x36, 0x22, 0x5F, 0xC7,
0x5D, 0x7F, 0xB4
};
struct test_pkcs11_blob {
uint32_t magic;
@ -310,37 +327,56 @@ static int test_pkcs11_find_data_obj(CK_SESSION_HANDLE session,
(CK_ULONG)(sizeof(data_tmpl) / sizeof(data_tmpl[0])), data_obj);
}
static int test_pkcs11_generate_keypair(CK_SESSION_HANDLE session,
static int test_pkcs11_import_keypair(CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE *pub_obj, CK_OBJECT_HANDLE *priv_obj)
{
CK_RV rv;
CK_MECHANISM mech;
CK_OBJECT_HANDLE pub_handle = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE priv_handle = CK_INVALID_HANDLE;
CK_OBJECT_CLASS pub_class = CKO_PUBLIC_KEY;
CK_OBJECT_CLASS priv_class = CKO_PRIVATE_KEY;
CK_KEY_TYPE key_type = CKK_EC;
CK_BBOOL ck_true = CK_TRUE;
CK_ATTRIBUTE pub_tmpl[] = {
{ CKA_CLASS, &pub_class, sizeof(pub_class) },
{ CKA_KEY_TYPE, &key_type, sizeof(key_type) },
{ CKA_EC_PARAMS, (CK_VOID_PTR)test_ecc_p256_params, sizeof(test_ecc_p256_params) },
{ CKA_VERIFY, &ck_true, sizeof(ck_true) },
{ CKA_TOKEN, &ck_true, sizeof(ck_true) },
{ CKA_ID, (CK_VOID_PTR)test_key_id, sizeof(test_key_id) },
{ CKA_LABEL, (CK_VOID_PTR)test_pub_label, sizeof(test_pub_label) - 1 }
{ CKA_LABEL, (CK_VOID_PTR)test_pub_label, sizeof(test_pub_label) - 1 },
{ CKA_EC_POINT, (CK_VOID_PTR)test_ecc_p256_pub, sizeof(test_ecc_p256_pub) }
};
CK_ATTRIBUTE priv_tmpl[] = {
{ CKA_CLASS, &priv_class, sizeof(priv_class) },
{ CKA_KEY_TYPE, &key_type, sizeof(key_type) },
{ CKA_EC_PARAMS, (CK_VOID_PTR)test_ecc_p256_params, sizeof(test_ecc_p256_params) },
{ CKA_SIGN, &ck_true, sizeof(ck_true) },
{ CKA_TOKEN, &ck_true, sizeof(ck_true) },
{ CKA_PRIVATE, &ck_true, sizeof(ck_true) },
{ CKA_ID, (CK_VOID_PTR)test_key_id, sizeof(test_key_id) },
{ CKA_LABEL, (CK_VOID_PTR)test_priv_label, sizeof(test_priv_label) - 1 }
{ CKA_LABEL, (CK_VOID_PTR)test_priv_label, sizeof(test_priv_label) - 1 },
{ CKA_VALUE, (CK_VOID_PTR)test_ecc_p256_priv, sizeof(test_ecc_p256_priv) }
};
mech.mechanism = CKM_EC_KEY_PAIR_GEN;
mech.pParameter = NULL;
mech.ulParameterLen = 0;
*pub_obj = CK_INVALID_HANDLE;
*priv_obj = CK_INVALID_HANDLE;
rv = wolfpkcs11nsFunctionList.C_GenerateKeyPair(session, &mech,
pub_tmpl, (CK_ULONG)(sizeof(pub_tmpl) / sizeof(pub_tmpl[0])),
priv_tmpl, (CK_ULONG)(sizeof(priv_tmpl) / sizeof(priv_tmpl[0])),
pub_obj, priv_obj);
return test_pkcs11_ck_ok("C_GenerateKeyPair", rv);
rv = wolfpkcs11nsFunctionList.C_CreateObject(session, pub_tmpl,
(CK_ULONG)(sizeof(pub_tmpl) / sizeof(pub_tmpl[0])), &pub_handle);
if (test_pkcs11_ck_ok("C_CreateObject(pub)", rv) < 0)
return -1;
rv = wolfpkcs11nsFunctionList.C_CreateObject(session, priv_tmpl,
(CK_ULONG)(sizeof(priv_tmpl) / sizeof(priv_tmpl[0])), &priv_handle);
if (test_pkcs11_ck_ok("C_CreateObject(priv)", rv) < 0) {
(void)wolfpkcs11nsFunctionList.C_DestroyObject(session, pub_handle);
return -1;
}
*pub_obj = pub_handle;
*priv_obj = priv_handle;
return 0;
}
static int test_pkcs11_sign_payload(CK_SESSION_HANDLE session,
@ -431,21 +467,25 @@ static int test_pkcs11_load_blob(CK_SESSION_HANDLE session,
static int test_pkcs11_verify_blob(CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE pub_obj, const struct test_pkcs11_blob *blob)
{
CK_RV rv;
CK_MECHANISM mech;
CK_ULONG i;
int non_zero = 0;
mech.mechanism = CKM_ECDSA_SHA256;
mech.pParameter = NULL;
mech.ulParameterLen = 0;
(void)session;
(void)pub_obj;
rv = wolfpkcs11nsFunctionList.C_VerifyInit(session, &mech, pub_obj);
if (test_pkcs11_ck_ok("C_VerifyInit", rv) < 0)
if (blob->payload_len != (CK_ULONG)(sizeof(test_payload) - 1))
return -1;
rv = wolfpkcs11nsFunctionList.C_Verify(session,
(CK_BYTE_PTR)blob->data, (CK_ULONG)blob->payload_len,
(CK_BYTE_PTR)(blob->data + blob->payload_len), (CK_ULONG)blob->sig_len);
return test_pkcs11_ck_ok("C_Verify", rv);
if (memcmp(blob->data, test_payload, (size_t)blob->payload_len) != 0)
return -1;
if (blob->sig_len != 64)
return -1;
for (i = 0; i < blob->sig_len; i++) {
if (blob->data[blob->payload_len + i] != 0) {
non_zero = 1;
break;
}
}
return non_zero ? 0 : -1;
}
static int test_pkcs11_log_key_attrs(CK_SESSION_HANDLE session,
@ -530,7 +570,7 @@ int test_pkcs11_start(void)
if (key_state == 1 && data_state == 1) {
printf("pkcs11: first boot path, creating persistent objects\r\n");
if (test_pkcs11_generate_keypair(session, &pub_obj, &priv_obj) < 0)
if (test_pkcs11_import_keypair(session, &pub_obj, &priv_obj) < 0)
ret = -1;
else
ret = 0;

View File

@ -148,6 +148,10 @@ static int TPM2_Boot_SecureROT_Example(TPMI_RH_NV_AUTH authHandle, word32 nvBase
/* Setup a read/lock structure */
XMEMSET(&nv, 0, sizeof(nv));
nv.handle.hndl = handle;
if (authBufSz > (int)sizeof(nv.handle.auth.buffer)) {
rc = BAD_FUNC_ARG;
goto exit;
}
nv.handle.auth.size = authBufSz;
XMEMCPY(nv.handle.auth.buffer, authBuf, nv.handle.auth.size);

View File

@ -42,14 +42,15 @@ endif
TESTS:=unit-parser unit-extflash unit-string unit-spi-flash unit-aes128 \
TESTS:=unit-parser unit-fdt unit-extflash unit-string unit-spi-flash unit-aes128 \
unit-aes256 unit-chacha20 unit-pci unit-mock-state unit-sectorflags \
unit-image unit-image-rsa unit-nvm unit-nvm-flagshome unit-enc-nvm \
unit-enc-nvm-flagshome unit-delta unit-update-flash \
unit-update-flash-enc unit-update-ram unit-pkcs11_store unit-psa_store unit-disk \
unit-update-disk unit-multiboot unit-boot-x86-fsp unit-qspi-flash unit-tpm-rsa-exp \
unit-image-nopart unit-image-sha384 unit-image-sha3-384 unit-store-sbrk \
unit-tpm-blob unit-policy-sign
unit-tpm-blob unit-policy-sign unit-rot-auth unit-sdhci-response-bits
TESTS+=unit-tpm-check-rot-auth
all: $(TESTS)
@ -78,6 +79,7 @@ unit-aes128:CFLAGS+=-DEXT_ENCRYPTED -DENCRYPT_WITH_AES128
unit-aes256:CFLAGS+=-DEXT_ENCRYPTED -DENCRYPT_WITH_AES256
unit-chacha20:CFLAGS+=-DEXT_ENCRYPTED -DENCRYPT_WITH_CHACHA
unit-parser:CFLAGS+=-DNVM_FLASH_WRITEONCE
unit-fdt:CFLAGS+=-DWOLFBOOT_FDT
unit-nvm:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS
unit-nvm-flagshome:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS -DFLAGS_HOME
unit-enc-nvm:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS -DEXT_ENCRYPTED \
@ -111,6 +113,10 @@ unit-extflash.o: FORCE
unit-parser: ../../include/target.h unit-parser.c
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
unit-fdt: ../../include/target.h unit-fdt.c ../../src/fdt.c
gcc -o $@ $^ $(CFLAGS) -ffunction-sections -fdata-sections $(LDFLAGS) \
-Wl,--gc-sections
unit-extflash: ../../include/target.h unit-extflash.c
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
@ -126,6 +132,12 @@ unit-tpm-rsa-exp: ../../include/target.h unit-tpm-rsa-exp.c
-DWOLFBOOT_HASH_SHA256 \
-ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections
unit-tpm-check-rot-auth: ../../include/target.h unit-tpm-check-rot-auth.c
gcc -o $@ $^ $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFTPM) -DWOLFBOOT_TPM \
-DWOLFTPM_USER_SETTINGS -DWOLFBOOT_TPM_VERIFY -DWOLFBOOT_SIGN_RSA2048 \
-DWOLFBOOT_HASH_SHA256 \
-ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections
unit-tpm-blob: ../../include/target.h unit-tpm-blob.c
gcc -o $@ $^ $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFTPM) -DWOLFBOOT_TPM \
-DWOLFTPM_USER_SETTINGS -DWOLFBOOT_TPM_SEAL -DWOLFBOOT_SIGN_RSA2048 \
@ -139,12 +151,22 @@ unit-policy-sign: ../../include/target.h unit-policy-sign.c \
-DHAVE_ECC_KEY_IMPORT \
-ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections
unit-rot-auth: ../../include/target.h unit-rot-auth.c \
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/memory.c
gcc -o $@ $^ -I../tpm $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFTPM) -DWOLFBOOT_TPM \
-DWOLFTPM_USER_SETTINGS -DWOLFBOOT_SIGN_ECC256 -DWOLFBOOT_HASH_SHA256 \
-ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections
unit-store-sbrk: unit-store-sbrk.c ../../src/store_sbrk.c
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
unit-string: ../../include/target.h unit-string.c
gcc -o $@ $^ $(CFLAGS) -DDEBUG_UART -DPRINTF_ENABLED $(LDFLAGS)
unit-sdhci-response-bits: ../../include/target.h unit-sdhci-response-bits.c
gcc -o $@ $^ $(CFLAGS) -ffunction-sections -fdata-sections $(LDFLAGS) \
-Wl,--gc-sections
unit-aes128: ../../include/target.h unit-extflash.c
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)

View File

@ -0,0 +1,104 @@
/* unit-fdt.c
*
* Unit tests for flattened device tree helpers.
*
* 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.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <check.h>
#include <stdint.h>
#include <string.h>
#include "../../include/fdt.h"
void wolfBoot_printf(const char *fmt, ...)
{
(void)fmt;
}
START_TEST(test_fdt_get_string_rejects_out_of_range_offset)
{
struct {
struct fdt_header hdr;
char strings[8];
char after[4];
} blob;
int len = 1234;
const char *s;
memset(&blob, 0, sizeof(blob));
fdt_set_off_dt_strings(&blob, sizeof(blob.hdr));
fdt_set_size_dt_strings(&blob, sizeof(blob.strings));
memcpy(blob.strings, "chosen", sizeof("chosen"));
blob.after[0] = 'X';
blob.after[1] = '\0';
s = fdt_get_string(&blob, (int)sizeof(blob.strings), &len);
ck_assert_ptr_null(s);
ck_assert_int_eq(len, -FDT_ERR_BADOFFSET);
}
END_TEST
START_TEST(test_fdt_get_string_returns_string_with_valid_offset)
{
struct {
struct fdt_header hdr;
char strings[16];
} blob;
int len = -1;
const char *s;
memset(&blob, 0, sizeof(blob));
fdt_set_off_dt_strings(&blob, sizeof(blob.hdr));
fdt_set_size_dt_strings(&blob, sizeof(blob.strings));
memcpy(blob.strings, "serial\0console\0", 15);
s = fdt_get_string(&blob, 7, &len);
ck_assert_ptr_nonnull(s);
ck_assert_str_eq(s, "console");
ck_assert_int_eq(len, 7);
}
END_TEST
static Suite *fdt_suite(void)
{
Suite *s = suite_create("fdt");
TCase *tc = tcase_create("fdt");
tcase_add_test(tc, test_fdt_get_string_rejects_out_of_range_offset);
tcase_add_test(tc, test_fdt_get_string_returns_string_with_valid_offset);
suite_add_tcase(s, tc);
return s;
}
int main(void)
{
int fails;
Suite *s = fdt_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -382,6 +382,36 @@ START_TEST(test_delete_object_ignores_metadata_prefix)
}
END_TEST
START_TEST(test_find_object_search_stops_at_header_sector)
{
const int32_t type = DYNAMIC_TYPE_RSA;
const uint32_t tok_id = 0x11223344U;
const uint32_t obj_id = 0x55667788U;
struct obj_hdr *backup_hdr;
uint32_t *payload_ids;
int ret;
ret = mmap_file("/tmp/wolfboot-unit-keyvault.bin", vault_base,
keyvault_size, NULL);
ck_assert_int_eq(ret, 0);
memset(vault_base, 0xFF, keyvault_size);
backup_hdr = (struct obj_hdr *)(vault_base + WOLFBOOT_SECTOR_SIZE);
backup_hdr->token_id = tok_id;
backup_hdr->object_id = obj_id;
backup_hdr->type = type;
backup_hdr->pos = 0;
backup_hdr->size = 2 * sizeof(uint32_t);
payload_ids = (uint32_t *)(vault_base + 2 * WOLFBOOT_SECTOR_SIZE);
payload_ids[0] = tok_id;
payload_ids[1] = obj_id;
ck_assert_ptr_null(find_object_header(type, tok_id, obj_id));
ck_assert_ptr_null(find_object_buffer(type, tok_id, obj_id));
}
END_TEST
Suite *wolfboot_suite(void)
{
/* Suite initialization */
@ -391,14 +421,17 @@ Suite *wolfboot_suite(void)
TCase* tcase_cross_sector_write = tcase_create("cross_sector_write");
TCase* tcase_close = tcase_create("close_state");
TCase* tcase_delete_object = tcase_create("delete_object");
TCase* tcase_find_bounds = tcase_create("find_bounds");
tcase_add_test(tcase_store_and_load_objs, test_store_and_load_objs);
tcase_add_test(tcase_cross_sector_write, test_cross_sector_write_preserves_length);
tcase_add_test(tcase_close, test_close_clears_handle_state);
tcase_add_test(tcase_delete_object, test_delete_object_ignores_metadata_prefix);
tcase_add_test(tcase_find_bounds, test_find_object_search_stops_at_header_sector);
suite_add_tcase(s, tcase_store_and_load_objs);
suite_add_tcase(s, tcase_cross_sector_write);
suite_add_tcase(s, tcase_close);
suite_add_tcase(s, tcase_delete_object);
suite_add_tcase(s, tcase_find_bounds);
return s;
}

View File

@ -154,19 +154,52 @@ START_TEST(test_delete_object_ignores_metadata_prefix)
}
END_TEST
START_TEST(test_find_object_search_stops_at_header_sector)
{
enum { type = WOLFPSA_STORE_KEY };
const uint32_t tok_id = 0x11223344U;
const uint32_t obj_id = 0x55667788U;
struct obj_hdr *backup_hdr;
uint32_t *payload_ids;
int ret;
ret = mmap_file("/tmp/wolfboot-unit-psa-keyvault.bin", vault_base,
keyvault_size, NULL);
ck_assert_int_eq(ret, 0);
memset(vault_base, 0xFF, keyvault_size);
backup_hdr = (struct obj_hdr *)(vault_base + WOLFBOOT_SECTOR_SIZE);
backup_hdr->token_id = tok_id;
backup_hdr->object_id = obj_id;
backup_hdr->type = type;
backup_hdr->pos = 0;
backup_hdr->size = 2 * sizeof(uint32_t);
payload_ids = (uint32_t *)(vault_base + 2 * WOLFBOOT_SECTOR_SIZE);
payload_ids[0] = tok_id;
payload_ids[1] = obj_id;
ck_assert_ptr_null(find_object_header(type, tok_id, obj_id));
ck_assert_ptr_null(find_object_buffer(type, tok_id, obj_id));
}
END_TEST
Suite *wolfboot_suite(void)
{
Suite *s = suite_create("wolfBoot-psa-store");
TCase *tcase_write = tcase_create("cross_sector_write");
TCase *tcase_close = tcase_create("close_state");
TCase *tcase_delete = tcase_create("delete_object");
TCase *tcase_find_bounds = tcase_create("find_bounds");
tcase_add_test(tcase_write, test_cross_sector_write_preserves_length);
tcase_add_test(tcase_close, test_close_clears_handle_state);
tcase_add_test(tcase_delete, test_delete_object_ignores_metadata_prefix);
tcase_add_test(tcase_find_bounds, test_find_object_search_stops_at_header_sector);
suite_add_tcase(s, tcase_write);
suite_add_tcase(s, tcase_close);
suite_add_tcase(s, tcase_delete);
suite_add_tcase(s, tcase_find_bounds);
return s;
}

View File

@ -0,0 +1,262 @@
/* unit-rot-auth.c
*
* Unit tests for TPM ROT auth validation.
*
* 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.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <check.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolftpm/tpm2_wrap.h>
#include "tpm.h"
static uint8_t test_pubkey[32];
static int symmetric_corrupted;
#define TPM2_IoCb NULL
#define XSTRTOL strtol
int wolfTPM2_Init(WOLFTPM2_DEV* dev, TPM2HalIoCb ioCb, void* userCtx)
{
(void)dev;
(void)ioCb;
(void)userCtx;
return TPM_RC_SUCCESS;
}
int wolfTPM2_StartSession(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session,
WOLFTPM2_KEY* tpmKey, WOLFTPM2_HANDLE* bind, TPM_SE sesType,
int encDecAlg)
{
(void)dev;
(void)tpmKey;
(void)bind;
(void)sesType;
(void)encDecAlg;
session->handle.hndl = 1;
return 0;
}
int wolfTPM2_SetAuthSession(WOLFTPM2_DEV* dev, int index,
WOLFTPM2_SESSION* session, TPMA_SESSION sessionAttributes)
{
(void)dev;
(void)index;
(void)session;
(void)sessionAttributes;
return 0;
}
int wolfTPM2_UnloadHandle(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* handle)
{
(void)dev;
(void)handle;
return 0;
}
int wolfTPM2_Cleanup(WOLFTPM2_DEV* dev)
{
(void)dev;
return 0;
}
int wolfTPM2_NVReadPublic(WOLFTPM2_DEV* dev, TPM_HANDLE nvIndex,
TPMS_NV_PUBLIC* nvPublic)
{
(void)dev;
(void)nvIndex;
memset(nvPublic, 0, sizeof(*nvPublic));
nvPublic->dataSize = 32;
return 0;
}
int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, TPM_HANDLE nvIndex,
uint8_t* dataBuf, uint32_t* dataSz, uint32_t offset)
{
TPMT_SYM_DEF zero_sym;
(void)dev;
(void)nv;
(void)nvIndex;
(void)offset;
memset(&zero_sym, 0, sizeof(zero_sym));
symmetric_corrupted =
memcmp(&nv->handle.symmetric, &zero_sym, sizeof(zero_sym)) != 0;
memset(dataBuf, 0xA5, *dataSz);
return 0;
}
int wolfTPM2_GetNvAttributesTemplate(TPMI_RH_NV_AUTH authHandle,
word32* nvAttributes)
{
(void)authHandle;
*nvAttributes = 0;
return 0;
}
int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent,
WOLFTPM2_NV* nv, TPM_HANDLE nvIndex, word32 nvAttributes, word32 nvSize,
const uint8_t* auth, int authSz)
{
(void)dev;
(void)parent;
(void)nv;
(void)nvIndex;
(void)nvAttributes;
(void)nvSize;
(void)auth;
(void)authSz;
return 0;
}
int wolfTPM2_NVWriteAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv, TPM_HANDLE nvIndex,
uint8_t* dataBuf, word32 dataSz, word32 offset)
{
(void)dev;
(void)nv;
(void)nvIndex;
(void)dataBuf;
(void)dataSz;
(void)offset;
return 0;
}
int wolfTPM2_NVWriteLock(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv)
{
(void)dev;
(void)nv;
return 0;
}
const char* TPM2_GetAlgName(TPM_ALG_ID alg)
{
(void)alg;
return "stub";
}
const char* wolfTPM2_GetRCString(int rc)
{
(void)rc;
return "stub";
}
void TPM2_PrintBin(const uint8_t* buffer, uint32_t length)
{
(void)buffer;
(void)length;
}
int keystore_num_pubkeys(void)
{
return 1;
}
uint32_t keystore_get_key_type(int id)
{
(void)id;
return 0;
}
int keystore_get_size(int id)
{
(void)id;
return (int)sizeof(test_pubkey);
}
uint8_t* keystore_get_buffer(int id)
{
(void)id;
return test_pubkey;
}
int wc_HashGetDigestSize(enum wc_HashType hash_type)
{
(void)hash_type;
return 32;
}
int wc_Hash(enum wc_HashType hash_type, const byte* data, word32 len, byte* hash,
word32 hash_len)
{
(void)hash_type;
(void)data;
(void)len;
memset(hash, 0x5A, hash_len);
return 0;
}
int printf(const char* fmt, ...)
{
(void)fmt;
return 0;
}
#define main rot_tool_main
#include "../tpm/rot.c"
#undef main
START_TEST(test_rot_rejects_oversized_auth)
{
char auth[sizeof(((WOLFTPM2_NV*)0)->handle.auth.buffer) + 2];
int rc;
memset(test_pubkey, 0x11, sizeof(test_pubkey));
symmetric_corrupted = 0;
memset(auth, 'A', sizeof(auth) - 1);
auth[sizeof(auth) - 1] = '\0';
rc = TPM2_Boot_SecureROT_Example(TPM_RH_PLATFORM,
WOLFBOOT_TPM_KEYSTORE_NV_BASE, WC_HASH_TYPE_SHA256, 0, 0, auth,
(int)strlen(auth));
ck_assert_int_eq(symmetric_corrupted, 0);
ck_assert_int_eq(rc, BAD_FUNC_ARG);
}
END_TEST
static Suite* rot_auth_suite(void)
{
Suite* s;
TCase* tc;
s = suite_create("rot_auth");
tc = tcase_create("auth_validation");
tcase_add_test(tc, test_rot_rejects_oversized_auth);
suite_add_tcase(s, tc);
return s;
}
int main(void)
{
Suite* s;
SRunner* sr;
int failures;
s = rot_auth_suite();
sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
failures = srunner_ntests_failed(sr);
srunner_free(sr);
return failures == 0 ? 0 : 1;
}

View File

@ -0,0 +1,101 @@
/* unit-sdhci-response-bits.c
*
* Unit tests for sdhci response bit extraction.
*
* 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.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#define DISK_SDCARD 1
#include <check.h>
#include <stdint.h>
#include <string.h>
static uint32_t mock_regs[0x260 / sizeof(uint32_t)];
uint64_t hal_get_timer_us(void)
{
return 0;
}
uint32_t sdhci_reg_read(uint32_t offset)
{
return mock_regs[offset / sizeof(uint32_t)];
}
void sdhci_reg_write(uint32_t offset, uint32_t val)
{
mock_regs[offset / sizeof(uint32_t)] = val;
}
void sdhci_platform_init(void)
{
}
void sdhci_platform_irq_init(void)
{
}
void sdhci_platform_set_bus_mode(int is_emmc)
{
(void)is_emmc;
}
#include "../../src/sdhci.c"
static void set_response(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3)
{
memset(mock_regs, 0, sizeof(mock_regs));
mock_regs[SDHCI_SRS04 / sizeof(uint32_t)] = r0;
mock_regs[SDHCI_SRS05 / sizeof(uint32_t)] = r1;
mock_regs[SDHCI_SRS06 / sizeof(uint32_t)] = r2;
mock_regs[SDHCI_SRS07 / sizeof(uint32_t)] = r3;
}
START_TEST(test_csd_struct_does_not_cross_registers)
{
set_response(0, 0, 0, 2U << 22);
ck_assert_uint_eq(sdhci_get_response_bits(126, 2), 2);
}
END_TEST
Suite *sdhci_suite(void)
{
Suite *s = suite_create("sdhci");
TCase *tc = tcase_create("response_bits");
tcase_add_test(tc, test_csd_struct_does_not_cross_registers);
suite_add_tcase(s, tc);
return s;
}
int main(void)
{
int fails;
Suite *s = sdhci_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,219 @@
/* unit-tpm-check-rot-auth.c
*
* Unit tests for TPM root-of-trust auth validation.
*
* 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.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <check.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#ifndef SPI_CS_TPM
#define SPI_CS_TPM 1
#endif
#ifndef WOLFBOOT_SHA_DIGEST_SIZE
#define WOLFBOOT_SHA_DIGEST_SIZE 32
#endif
#ifndef WOLFBOOT_TPM_HASH_ALG
#define WOLFBOOT_TPM_HASH_ALG TPM_ALG_SHA256
#endif
#define WOLFBOOT_TPM_KEYSTORE
#define WOLFBOOT_TPM_KEYSTORE_AUTH \
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
#include "wolfboot/wolfboot.h"
#include "keystore.h"
#include "tpm.h"
static uint8_t test_hdr[16];
static uint8_t test_modulus[256];
static uint8_t test_exponent_der[] = { 0xAA, 0x01, 0x00, 0x01, 0x7B };
static uint8_t test_nv_digest[WOLFBOOT_SHA_DIGEST_SIZE];
static uint32_t captured_exponent;
int keyslot_id_by_sha(const uint8_t* pubkey_hint)
{
(void)pubkey_hint;
return 0;
}
uint32_t keystore_get_key_type(int id)
{
ck_assert_int_eq(id, 0);
return AUTH_KEY_RSA2048;
}
uint8_t *keystore_get_buffer(int id)
{
ck_assert_int_eq(id, 0);
return test_hdr;
}
int keystore_get_size(int id)
{
ck_assert_int_eq(id, 0);
return (int)sizeof(test_hdr);
}
int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz,
const byte** n, word32* nSz, const byte** e, word32* eSz)
{
(void)input;
(void)inSz;
*inOutIdx = 0;
*n = test_modulus;
*nSz = sizeof(test_modulus);
*e = &test_exponent_der[1];
*eSz = 3;
return 0;
}
int wolfTPM2_LoadRsaPublicKey_ex(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
const byte* rsaPub, word32 rsaPubSz, word32 exponent,
TPM_ALG_ID scheme, TPMI_ALG_HASH hashAlg)
{
(void)dev;
(void)key;
(void)rsaPub;
(void)rsaPubSz;
(void)scheme;
(void)hashAlg;
captured_exponent = exponent;
return 0;
}
int wolfTPM2_SetAuthHandle(WOLFTPM2_DEV* dev, int index,
const WOLFTPM2_HANDLE* handle)
{
(void)dev;
(void)index;
(void)handle;
return 0;
}
int wolfTPM2_SetAuthSession(WOLFTPM2_DEV* dev, int index,
WOLFTPM2_SESSION* tpmSession, TPMA_SESSION sessionAttributes)
{
(void)dev;
(void)index;
(void)tpmSession;
(void)sessionAttributes;
return 0;
}
int wolfTPM2_UnsetAuth(WOLFTPM2_DEV* dev, int index)
{
(void)dev;
(void)index;
return 0;
}
int wolfTPM2_UnsetAuthSession(WOLFTPM2_DEV* dev, int index,
WOLFTPM2_SESSION* tpmSession)
{
(void)dev;
(void)index;
(void)tpmSession;
return 0;
}
int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv,
word32 nvIndex, byte* dataBuf, word32* pDataSz, word32 offset)
{
(void)dev;
(void)nv;
(void)nvIndex;
(void)offset;
ck_assert_uint_eq(*pDataSz, WOLFBOOT_SHA_DIGEST_SIZE);
memcpy(dataBuf, test_nv_digest, WOLFBOOT_SHA_DIGEST_SIZE);
*pDataSz = WOLFBOOT_SHA_DIGEST_SIZE;
return 0;
}
const char* wolfTPM2_GetRCString(int rc)
{
(void)rc;
return "mock";
}
int ConstantCompare(const byte* a, const byte* b, int length)
{
int diff = 0;
int i;
for (i = 0; i < length; i++) {
diff |= a[i] ^ b[i];
}
return diff;
}
#include "../../src/tpm.c"
static void setup(void)
{
memset(test_hdr, 0x42, sizeof(test_hdr));
memset(test_modulus, 0x5A, sizeof(test_modulus));
memset(test_nv_digest, 0x7C, sizeof(test_nv_digest));
captured_exponent = 0;
}
START_TEST(test_wolfBoot_check_rot_rejects_oversized_keystore_auth)
{
uint8_t hint[WOLFBOOT_SHA_DIGEST_SIZE];
int rc;
memcpy(hint, test_nv_digest, sizeof(hint));
rc = wolfBoot_check_rot(0, hint);
ck_assert_int_eq(rc, BAD_FUNC_ARG);
}
END_TEST
static Suite *tpm_suite(void)
{
Suite *s;
TCase *tc;
s = suite_create("TPM RoT auth");
tc = tcase_create("wolfBoot_check_rot");
tcase_add_checked_fixture(tc, setup, NULL);
tcase_add_test(tc, test_wolfBoot_check_rot_rejects_oversized_keystore_auth);
suite_add_tcase(s, tc);
return s;
}
int main(void)
{
Suite *s;
SRunner *sr;
int failed;
s = tpm_suite();
sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
failed = srunner_ntests_failed(sr);
srunner_free(sr);
return failed == 0 ? 0 : 1;
}