Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
42c312e
Harden constant-time compare accumulators
danielinux Apr 14, 2026
00892c2
Clamp unaligned SDHCI disk I/O spans
danielinux Apr 14, 2026
e10d9c1
Fix RAM fallback partition reselection
danielinux Apr 14, 2026
dc7309c
Fix TPM unseal handle cleanup
danielinux Apr 14, 2026
9265fe7
loader: panic on TPM init failure
danielinux Apr 14, 2026
f8cbad0
Add final sanity checks to boot paths
danielinux Apr 14, 2026
41ffb2c
Add partition overlap guards
danielinux Apr 14, 2026
6ce320e
fix inverted emergency update branch hint
danielinux Apr 14, 2026
6c9a0a0
Add final sanity check in library boot path
danielinux Apr 14, 2026
b4b9ba3
Add rollback state assertion
danielinux Apr 14, 2026
7048dd6
Add update-size boundary coverage tests
danielinux Apr 14, 2026
249ebaa
Update .gitignore
danielinux Apr 14, 2026
c8a94d8
Add erased-trailer partition state regression test
danielinux Apr 14, 2026
9421355
Add delta base-version unit coverage
danielinux Apr 14, 2026
194b363
Reset hdr_ok when image open fails
danielinux Apr 14, 2026
6ef9e02
test nvm sector flag invalid magic guard
danielinux Apr 14, 2026
871f03c
Fix external image hdr_ok state on open failure
danielinux Apr 14, 2026
2bd6274
Fix endian handling for delta TLV consumers
danielinux Apr 14, 2026
bc4ec50
delta: reject sector sizes that overflow 16-bit match length
danielinux Apr 14, 2026
657e337
Reject oversized cert-chain TLVs in sign tool
danielinux Apr 14, 2026
46645a0
sign tool: encode header fields as little-endian
danielinux Apr 14, 2026
cc7c3bb
Reject oversized signature TLV lengths
danielinux Apr 14, 2026
af24164
Fix update sector flag index truncation
danielinux Apr 14, 2026
4c0f425
Fix WOLFBOOT_MAX_SPACE precedence and test
danielinux Apr 14, 2026
dd6444b
x86: zero ATA unlock secret on all sata_unlock_disk exits
danielinux Apr 14, 2026
76f0b3c
keygen_xmss: zeroize XmssKey after free
danielinux Apr 14, 2026
84562a4
dice: zero IAK stack key on all exits
danielinux Apr 14, 2026
8dbc7d6
dice: scrub non-IAK UDS buffer
danielinux Apr 14, 2026
da2c3dd
dice: zero ECC signing key context on cleanup
danielinux Apr 14, 2026
25668dd
zeroize OTP UDS in stm32h5 derive path
danielinux Apr 14, 2026
e48c1eb
zero entropy buffer in sata_get_random_base64
danielinux Apr 14, 2026
faebb62
Fixed test regressions
danielinux Apr 14, 2026
8976078
Adjusted footprint limits
danielinux Apr 14, 2026
9ac6b1f
Fixed more regressions
danielinux Apr 14, 2026
b007463
Addressed copilot comments
danielinux Apr 14, 2026
00342ac
Addressed more copilot's comments
danielinux Apr 14, 2026
a64fa8f
Addressed Fenrir's review comments + fixed more regressions
danielinux Apr 14, 2026
857cd36
Addressed another round of reviews (copilot)
danielinux Apr 14, 2026
e6c1976
Fixed wolfBoot_panic() visibility in lib + Fenrir comments
danielinux Apr 14, 2026
6540f17
Fixed more comments from copilot + fenrir
danielinux Apr 14, 2026
0809d83
Fix actual overlap in hifive config
danielinux Apr 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ include/target.h
.wolfboot-offset
.wolfboot-partition-size
.bootloader-partition-size
NVChip
MPLabX/wolfBoot-SAME51.X/.generated_files/
test-dummy-ca/**

Expand Down Expand Up @@ -181,6 +182,12 @@ tools/unit-tests/unit-policy-create
tools/unit-tests/unit-sign-encrypted-output
tools/unit-tests/unit-update-flash-delta
tools/unit-tests/unit-update-flash-self-update
tools/unit-tests/unit-loader-tpm-init
tools/unit-tests/unit-update-ram-nofixed
tools/unit-tests/unit-max-space
tools/unit-tests/unit-sdhci-disk-unaligned





Expand Down Expand Up @@ -373,4 +380,3 @@ system-default.dtb
test_output/
sdcard.img


2 changes: 1 addition & 1 deletion config/examples/hifive1.config
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ V?=0
SPMATH?=1
RAM_CODE?=1
DUALBANK_SWAP?=0
WOLFBOOT_PARTITION_SIZE?=0x80000
WOLFBOOT_PARTITION_SIZE?=0x40000
WOLFBOOT_SECTOR_SIZE?=0x1000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x20020000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x20060000
Expand Down
13 changes: 13 additions & 0 deletions hal/library.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ void hal_prepare_boot(void)
return;
}

void WEAKFUNCTION wolfBoot_panic(void)
{
wolfBoot_printf("wolfBoot: PANIC!\n");
exit('P');
}

int do_boot(uint32_t* v)
{
wolfBoot_printf("booting %p"
Expand Down Expand Up @@ -143,6 +149,13 @@ int wolfBoot_start(void)

wolfBoot_printf("Firmware Valid\n");

#ifndef WOLFBOOT_SKIP_BOOT_VERIFY
Comment thread
danielinux marked this conversation as resolved.
Comment thread
danielinux marked this conversation as resolved.
if ((os_image.hdr_ok != 1U) || (os_image.sha_ok != 1U) ||
(os_image.signature_ok != 1U)) {
wolfBoot_panic();
}
PART_SANITY_CHECK(&os_image);
#endif
Comment thread
danielinux marked this conversation as resolved.
do_boot((uint32_t*)os_image.fw_base);

exit:
Expand Down
10 changes: 10 additions & 0 deletions hal/stm32h5.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,14 @@ static int buffer_is_all_value(const uint8_t *buf, size_t len, uint8_t value)
return 1;
}

static NOINLINEFUNCTION void hal_secret_zeroize(void *ptr, size_t len)
{
volatile uint8_t *p = (volatile uint8_t *)ptr;
while (len-- > 0U) {
*p++ = 0U;
}
}

int hal_uds_derive_key(uint8_t *out, size_t out_len)
{
#if defined(FLASH_OTP_KEYSTORE)
Expand All @@ -272,9 +280,11 @@ int hal_uds_derive_key(uint8_t *out, size_t out_len)
copy_len = out_len;
}
memcpy(out, uds, copy_len);
hal_secret_zeroize(uds, sizeof(uds));
return 0;
}
}
hal_secret_zeroize(uds, sizeof(uds));
#endif

#ifdef WOLFBOOT_UDS_UID_FALLBACK_FORTEST
Expand Down
35 changes: 35 additions & 0 deletions include/MPLAB/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,41 @@
#define WOLFBOOT_DTS_BOOT_ADDRESS
#define WOLFBOOT_DTS_UPDATE_ADDRESS

#if !defined(WOLFBOOT_PART_USE_ARCH_OFFSET) && !defined(PULL_LINKER_DEFINES)
/*
* Only compare partitions that share the same internal flash address
* space. External partitions and runtime/linker-provided addresses are
* validated elsewhere.
*/
#if !defined(PART_BOOT_EXT) && !defined(PART_UPDATE_EXT) && \
(WOLFBOOT_PARTITION_UPDATE_ADDRESS != 0) && \
((WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE) > \
WOLFBOOT_PARTITION_UPDATE_ADDRESS) && \
(WOLFBOOT_PARTITION_BOOT_ADDRESS < \
(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE))
#error "Boot and update partitions overlap"
#endif

#if !defined(PART_BOOT_EXT) && !defined(PART_SWAP_EXT) && \
(WOLFBOOT_PARTITION_SWAP_ADDRESS != 0) && \
((WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE) > \
WOLFBOOT_PARTITION_SWAP_ADDRESS) && \
(WOLFBOOT_PARTITION_BOOT_ADDRESS < \
(WOLFBOOT_PARTITION_SWAP_ADDRESS + WOLFBOOT_SECTOR_SIZE))
#error "Boot and swap partitions overlap"
#endif

#if !defined(PART_UPDATE_EXT) && !defined(PART_SWAP_EXT) && \
(WOLFBOOT_PARTITION_UPDATE_ADDRESS != 0) && \
(WOLFBOOT_PARTITION_SWAP_ADDRESS != 0) && \
((WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE) > \
WOLFBOOT_PARTITION_SWAP_ADDRESS) && \
(WOLFBOOT_PARTITION_UPDATE_ADDRESS < \
(WOLFBOOT_PARTITION_SWAP_ADDRESS + WOLFBOOT_SECTOR_SIZE))
#error "Update and swap partitions overlap"
#endif
#endif

#endif /* WOLFBOOT_FIXED_PARTITIONS */

/* Load address in RAM for staged OS (update_ram only) */
Expand Down
2 changes: 1 addition & 1 deletion include/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,7 @@ static inline int wb_flash_write_verify_word(struct wolfBoot_image *img,
#ifndef EXT_ENCRYPTED
#define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - \
(TRAILER_SKIP + sizeof(uint32_t) + \
(WOLFBOOT_PARTITION_SIZE + 1 / (WOLFBOOT_SECTOR_SIZE * 8))))
((WOLFBOOT_PARTITION_SIZE + 1) / (WOLFBOOT_SECTOR_SIZE * 8))))
#else
#define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - ENCRYPT_TMP_SECRET_OFFSET)
#endif
Expand Down
36 changes: 36 additions & 0 deletions include/target.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,42 @@
#define WOLFBOOT_DTS_BOOT_ADDRESS @WOLFBOOT_DTS_BOOT_ADDRESS@
#define WOLFBOOT_DTS_UPDATE_ADDRESS @WOLFBOOT_DTS_UPDATE_ADDRESS@

#if defined(WOLFBOOT_FIXED_PARTITIONS) && \
!defined(WOLFBOOT_PART_USE_ARCH_OFFSET) && !defined(PULL_LINKER_DEFINES)
/*
* Only compare partitions that share the same internal flash address
* space. External partitions and runtime/linker-provided addresses are
* validated elsewhere.
*/
#if !defined(PART_BOOT_EXT) && !defined(PART_UPDATE_EXT) && \
((WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0) != 0) && \
((WOLFBOOT_PARTITION_BOOT_ADDRESS + 0 + WOLFBOOT_PARTITION_SIZE + 0) > \
(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0)) && \
((WOLFBOOT_PARTITION_BOOT_ADDRESS + 0) < \
(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0 + WOLFBOOT_PARTITION_SIZE + 0))
#error "Boot and update partitions overlap"
#endif

#if !defined(PART_BOOT_EXT) && !defined(PART_SWAP_EXT) && \
((WOLFBOOT_PARTITION_SWAP_ADDRESS + 0) != 0) && \
((WOLFBOOT_PARTITION_BOOT_ADDRESS + 0 + WOLFBOOT_PARTITION_SIZE + 0) > \
(WOLFBOOT_PARTITION_SWAP_ADDRESS + 0)) && \
((WOLFBOOT_PARTITION_BOOT_ADDRESS + 0) < \
(WOLFBOOT_PARTITION_SWAP_ADDRESS + 0 + WOLFBOOT_SECTOR_SIZE))
#error "Boot and swap partitions overlap"
#endif

#if !defined(PART_UPDATE_EXT) && !defined(PART_SWAP_EXT) && \
((WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0) != 0) && \
((WOLFBOOT_PARTITION_SWAP_ADDRESS + 0) != 0) && \
((WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0 + WOLFBOOT_PARTITION_SIZE + 0) > \
(WOLFBOOT_PARTITION_SWAP_ADDRESS + 0)) && \
((WOLFBOOT_PARTITION_UPDATE_ADDRESS + 0) < \
(WOLFBOOT_PARTITION_SWAP_ADDRESS + 0 + WOLFBOOT_SECTOR_SIZE))
#error "Update and swap partitions overlap"
#endif
#endif

#endif /* WOLFBOOT_FIXED_PARTITIONS */

#if !defined(WOLFBOOT_NO_LOAD_ADDRESS)
Expand Down
8 changes: 4 additions & 4 deletions src/delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h> /* INT_MAX */
#include <inttypes.h> /* PRIu32 */

static uint32_t wolfboot_sector_size = 0;
Expand Down Expand Up @@ -233,9 +232,10 @@ int wb_diff_get_sector_size(void)
fprintf(stderr, "WOLFBOOT_SECTOR_SIZE cannot be 0\n");
exit(6);
}
if (sec_sz > (uint32_t)INT_MAX) {
fprintf(stderr, "WOLFBOOT_SECTOR_SIZE (%" PRIu32 ") exceeds INT_MAX (%d)\n",
sec_sz, INT_MAX);
if (sec_sz > 0xFFFFU) {
fprintf(stderr,
"WOLFBOOT_SECTOR_SIZE (%" PRIu32 ") exceeds delta encoding limit (65535)\n",
sec_sz);
exit(6);
}
return (int)sec_sz;
Expand Down
87 changes: 58 additions & 29 deletions src/dice/dice.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/integer.h>
#include <wolfssl/wolfcrypt/memory.h>

#if defined(WOLFBOOT_HASH_SHA384)
#include <wolfssl/wolfcrypt/sha512.h>
Expand Down Expand Up @@ -68,6 +67,14 @@
#define WOLFBOOT_DICE_ERR_HW -3
#define WOLFBOOT_DICE_ERR_CRYPTO -4

static NOINLINEFUNCTION void wolfboot_dice_zeroize(void *ptr, size_t len)
{
volatile uint8_t *p = (volatile uint8_t *)ptr;
while (len-- > 0U) {
*p++ = 0U;
}
}

#define COSE_LABEL_ALG 1
#define COSE_ALG_ES256 (-7)

Expand Down Expand Up @@ -621,7 +628,7 @@ static int wolfboot_dice_derive_attestation_key(ecc_key *key,
goto cleanup;
}
/* CDI is no longer needed once the seed has been derived. */
wc_ForceZero(cdi, sizeof(cdi));
wolfboot_dice_zeroize(cdi, sizeof(cdi));

if (wolfboot_dice_hkdf(seed, sizeof(seed),
(const uint8_t *)"WOLFBOOT-IAK", 12,
Expand All @@ -630,7 +637,7 @@ static int wolfboot_dice_derive_attestation_key(ecc_key *key,
goto cleanup;
}
/* Seed is no longer needed once the private key material is derived. */
wc_ForceZero(seed, sizeof(seed));
wolfboot_dice_zeroize(seed, sizeof(seed));

if (wolfboot_dice_fixup_priv(priv, sizeof(priv)) != 0) {
goto cleanup;
Expand All @@ -644,9 +651,9 @@ static int wolfboot_dice_derive_attestation_key(ecc_key *key,
ret = 0;

cleanup:
wc_ForceZero(priv, sizeof(priv));
wc_ForceZero(seed, sizeof(seed));
wc_ForceZero(cdi, sizeof(cdi));
wolfboot_dice_zeroize(priv, sizeof(priv));
wolfboot_dice_zeroize(seed, sizeof(seed));
wolfboot_dice_zeroize(cdi, sizeof(cdi));
Comment thread
danielinux marked this conversation as resolved.
return ret;
}

Expand All @@ -660,24 +667,32 @@ static int wolfboot_attest_get_private_key(ecc_key *key,
{
uint8_t priv[WOLFBOOT_DICE_KEY_LEN];
size_t priv_len = sizeof(priv);
int ret = -1;

if (hal_attestation_get_iak_private_key(priv, &priv_len) != 0) {
return -1;
goto cleanup;
}
if (priv_len != WOLFBOOT_DICE_KEY_LEN) {
return -1;
goto cleanup;
}
if (wc_ecc_import_private_key_ex(priv, (word32)priv_len, NULL, 0,
key, ECC_SECP256R1) != 0) {
return -1;
goto cleanup;
}
return 0;
ret = 0;

cleanup:
wolfboot_dice_zeroize(priv, sizeof(priv));
return ret;
}
#else
Comment thread
danielinux marked this conversation as resolved.
if (hal_uds_derive_key(uds, uds_len) != 0) {
return -1;
int ret = -1;

if (hal_uds_derive_key(uds, uds_len) == 0) {
ret = wolfboot_dice_derive_attestation_key(key, uds, uds_len, claims);
}
return wolfboot_dice_derive_attestation_key(key, uds, uds_len, claims);
wolfboot_dice_zeroize(uds, sizeof(uds));
return ret;
#endif
}

Expand Down Expand Up @@ -801,7 +816,10 @@ static int wolfboot_dice_sign_tbs(const uint8_t *tbs,
{
ecc_key key;
WC_RNG rng;
int ret;
int ret = WOLFBOOT_DICE_ERR_CRYPTO;
int wc_ret;
int key_inited = 0;
int rng_inited = 0;
uint8_t hash[SHA256_DIGEST_SIZE];
uint8_t der_sig[128];
word32 der_sig_len = sizeof(der_sig);
Expand All @@ -815,16 +833,18 @@ static int wolfboot_dice_sign_tbs(const uint8_t *tbs,
}

wc_ecc_init(&key);
key_inited = 1;
if (wolfboot_attest_get_private_key(&key, claims) != 0) {
wc_ecc_free(&key);
return WOLFBOOT_DICE_ERR_HW;
ret = WOLFBOOT_DICE_ERR_HW;
goto cleanup;
}

(void)wc_ecc_set_deterministic(&key, 1);
if (wc_InitRng(&rng) != 0) {
wc_ecc_free(&key);
return WOLFBOOT_DICE_ERR_HW;
ret = WOLFBOOT_DICE_ERR_HW;
goto cleanup;
}
rng_inited = 1;

{
wc_Sha256 sha;
Expand All @@ -833,26 +853,35 @@ static int wolfboot_dice_sign_tbs(const uint8_t *tbs,
wc_Sha256Final(&sha, hash);
}

ret = wc_ecc_sign_hash(hash, sizeof(hash), der_sig, &der_sig_len, &rng, &key);
wc_FreeRng(&rng);
if (ret != 0) {
wc_ecc_free(&key);
return WOLFBOOT_DICE_ERR_CRYPTO;
wc_ret = wc_ecc_sign_hash(hash, sizeof(hash), der_sig, &der_sig_len, &rng, &key);
if (wc_ret != 0) {
ret = WOLFBOOT_DICE_ERR_CRYPTO;
goto cleanup;
}

ret = wc_ecc_sig_to_rs(der_sig, der_sig_len, r, &r_len, s, &s_len);
if (ret != 0 || r_len > sizeof(r) || s_len > sizeof(s)) {
wc_ecc_free(&key);
return WOLFBOOT_DICE_ERR_CRYPTO;
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 = 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;

wc_ecc_free(&key);
return WOLFBOOT_DICE_SUCCESS;
cleanup:
if (rng_inited) {
wc_FreeRng(&rng);
}
if (key_inited) {
wc_ecc_free(&key);
wolfboot_dice_zeroize(&key, sizeof(key));
}
wolfboot_dice_zeroize(hash, sizeof(hash));
wolfboot_dice_zeroize(der_sig, sizeof(der_sig));
return ret;
}

static int wolfboot_dice_build_token(uint8_t *token_buf,
Expand Down
Loading
Loading