From 64a7b8a062d1e1e5a662a9939514177ebb5247f8 Mon Sep 17 00:00:00 2001 From: aidan garske Date: Thu, 9 Jul 2026 17:37:15 -0700 Subject: [PATCH 1/5] 6561 - Restore upper 64-bit BAR register on pci_program_bar error paths --- src/pci.c | 5 ++-- tools/unit-tests/unit-pci.c | 59 +++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/pci.c b/src/pci.c index 86f47a595a..357bf9cc1d 100644 --- a/src/pci.c +++ b/src/pci.c @@ -417,7 +417,7 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun, { uint32_t bar_align, bar_value; - uint32_t orig_bar, orig_bar2; + uint32_t orig_bar, orig_bar2 = 0; uint32_t length, align; uint8_t bar_off; int is_prefetch; @@ -464,7 +464,6 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun, PCI_DEBUG_PRINTF("bar high 32bit: %d\r\n", reg); if (reg != 0xffffffff) { PCI_DEBUG_PRINTF("Device wants too much memory, skipping\r\n"); - pci_config_write32(bus, dev, fun, bar_off + 4, orig_bar2); goto restore_bar; } } @@ -534,6 +533,8 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun, return 0; restore_bar: + if (*is_64bit) + pci_config_write32(bus, dev, fun, bar_off + 4, orig_bar2); pci_config_write32(bus, dev, fun, bar_off, orig_bar); return ret; diff --git a/tools/unit-tests/unit-pci.c b/tools/unit-tests/unit-pci.c index 9d4cc222ec..3dd28c0e2b 100644 --- a/tools/unit-tests/unit-pci.c +++ b/tools/unit-tests/unit-pci.c @@ -957,6 +957,61 @@ START_TEST(test_program_bar_64bit_upper_reject) } END_TEST +/* test_program_bar_64bit_restore_high: a 64-bit BAR that fails on a + * non-"too much memory" error path must restore BOTH the low and high dword. */ +START_TEST(test_program_bar_64bit_restore_high) +{ + struct test_pci_topology t; + struct pci_enum_info info; + uint8_t is_64bit = 0; + int dev_node; + int ret; + uint32_t bar0_val, bar1_val; + + test_pci_init(&t); + dev_node = test_pci_add_dev(&t, 0, 0, 0x1234, 0x5678, TEST_PCI_ROOT_BUS); + /* 64-bit prefetchable MMIO BAR, 1MB, valid upper half (default probe mask + * 0xFFFFFFFF) so the "too much memory" branch is not taken. */ + test_pci_dev_set_bar(&t, dev_node, 0, 0x100000, + TEST_PCI_BAR_64BIT | TEST_PCI_BAR_PF); + test_pci_commit(&t); + + /* Pre-fill BAR0/BAR1 with known original values. */ + { + uint32_t orig0 = 0xAABB0000, orig1 = 0xCCDD0000; + memcpy(&t.nodes[dev_node].cfg[PCI_BAR0_OFFSET], &orig0, 4); + memcpy(&t.nodes[dev_node].cfg[PCI_BAR0_OFFSET + 4], &orig1, 4); + } + + memset(&info, 0, sizeof(info)); + info.mem = 0x80000000; + info.mem_limit = 0x88000000; + /* Aligned start 0x90000000 is below the limit (passes the start-only + * check) but start + 1MB overruns it, taking the region-does-not-fit + * path rather than the "too much memory" path. */ + info.mem_pf = 0x90000000; + info.mem_pf_limit = 0x90080000; + info.io = 0x2000; + + ret = pci_program_bar(0, 0, 0, 0, &info, &is_64bit); + /* region-does-not-fit path sets ret = -1 */ + ck_assert_int_ne(ret, 0); + ck_assert_uint_eq(is_64bit, 1); + + /* Both BAR dwords must be restored; with the incomplete cleanup the high + * dword stays at 0xFFFFFFFF from probing. */ + bar0_val = pci_config_read32(0, 0, 0, PCI_BAR0_OFFSET); + ck_assert_uint_eq(bar0_val, 0xAABB0000); + bar1_val = pci_config_read32(0, 0, 0, PCI_BAR0_OFFSET + 4); + ck_assert_uint_eq(bar1_val, 0xCCDD0000); + + /* Allocator untouched */ + ck_assert_uint_eq(info.mem_pf, 0x90000000); + + test_pci_cleanup(&t); +} +END_TEST + /* test_program_bar_no_space: limit exceeded → restore_bar */ START_TEST(test_program_bar_no_space) { @@ -1833,6 +1888,10 @@ Suite *wolfboot_suite(void) tcase_add_test(tc_bar_ureject, test_program_bar_64bit_upper_reject); suite_add_tcase(s, tc_bar_ureject); + TCase *tc_bar_rhi = tcase_create("program-bar-64bit-restore-high"); + tcase_add_test(tc_bar_rhi, test_program_bar_64bit_restore_high); + suite_add_tcase(s, tc_bar_rhi); + TCase *tc_bar_nospace = tcase_create("program-bar-no-space"); tcase_add_test(tc_bar_nospace, test_program_bar_no_space); suite_add_tcase(s, tc_bar_nospace); From 034b6668a2d0e86cf9ab9bd8cee1242c292b26d1 Mon Sep 17 00:00:00 2001 From: aidan garske Date: Thu, 9 Jul 2026 17:41:54 -0700 Subject: [PATCH 2/5] 6568 - Zeroize DICE UEID digest and hash context before return --- src/dice/dice.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dice/dice.c b/src/dice/dice.c index 39f1cd3235..63dd2e0b4b 100644 --- a/src/dice/dice.c +++ b/src/dice/dice.c @@ -432,6 +432,7 @@ static int wolfboot_dice_get_ueid(uint8_t *ueid, size_t *ueid_len, wc_InitSha256(&hash); wc_Sha256Update(&hash, uds, (word32)uds_len); wc_Sha256Final(&hash, digest); + wolfboot_dice_zeroize(&hash, sizeof(hash)); } #elif defined(WOLFBOOT_HASH_SHA384) { @@ -439,6 +440,7 @@ static int wolfboot_dice_get_ueid(uint8_t *ueid, size_t *ueid_len, wc_InitSha384(&hash); wc_Sha384Update(&hash, uds, (word32)uds_len); wc_Sha384Final(&hash, digest); + wolfboot_dice_zeroize(&hash, sizeof(hash)); } #elif defined(WOLFBOOT_HASH_SHA3_384) { @@ -446,6 +448,7 @@ static int wolfboot_dice_get_ueid(uint8_t *ueid, size_t *ueid_len, wc_InitSha3_384(&hash, NULL, INVALID_DEVID); wc_Sha3_384_Update(&hash, uds, (word32)uds_len); wc_Sha3_384_Final(&hash, digest); + wolfboot_dice_zeroize(&hash, sizeof(hash)); } #endif @@ -453,6 +456,7 @@ static int wolfboot_dice_get_ueid(uint8_t *ueid, size_t *ueid_len, XMEMCPY(&ueid[1], digest, (WOLFBOOT_DICE_UEID_LEN - 1)); *ueid_len = WOLFBOOT_DICE_UEID_LEN; + wolfboot_dice_zeroize(digest, sizeof(digest)); return 0; } From 29f3960b0f4ff113364fde2efe26f5fb945ca210 Mon Sep 17 00:00:00 2001 From: aidan garske Date: Thu, 9 Jul 2026 17:46:03 -0700 Subject: [PATCH 3/5] 6593 - Bound uncompressed FIT subimage copy by staging buffer size --- src/fdt.c | 7 +++++-- tools/unit-tests/unit-fit-gzip.c | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/fdt.c b/src/fdt.c index 85e069cd6f..f48ab6febd 100644 --- a/src/fdt.c +++ b/src/fdt.c @@ -1149,8 +1149,6 @@ static void* fit_load_image_inner(void* fdt, const char* image, int* lenp, int complen = 0; #ifdef WOLFBOOT_GZIP BENCHMARK_DECLARE(); -#else - (void)out_max; #endif off = fdt_find_node_offset(fdt, -1, image); @@ -1221,6 +1219,11 @@ static void* fit_load_image_inner(void* fdt, const char* image, int* lenp, return NULL; } else { + if (len < 0 || (uint32_t)len > out_max) { + wolfBoot_printf("FIT: subimage '%s' size %d exceeds " + "staging bound %u\n", image, len, out_max); + return NULL; + } wolfBoot_printf("Loading Image %s: %p -> %p " "(%d bytes)\n", image, data, load, len); memcpy(load, data, len); diff --git a/tools/unit-tests/unit-fit-gzip.c b/tools/unit-tests/unit-fit-gzip.c index f5a3b54cda..373a4be81d 100644 --- a/tools/unit-tests/unit-fit-gzip.c +++ b/tools/unit-tests/unit-fit-gzip.c @@ -285,6 +285,25 @@ START_TEST(test_fit_to_lzma_unknown_returns_null) } END_TEST +/* An uncompressed ("none") subimage larger than the staging bound must be + * rejected instead of overflowing the destination. */ +START_TEST(test_fit_to_none_oversized_rejected) +{ + uint8_t buf[64]; + int len = -1; + void *ret; + static uint8_t fit_scratch[sizeof(fit_with_none_comp)]; + memcpy(fit_scratch, fit_with_none_comp, sizeof(fit_scratch)); + + memset(buf, 0xA5, sizeof(buf)); + /* payload is FIT_PLAIN_LEN (23) bytes; bound the destination below it */ + ret = fit_load_image_to(fit_scratch, "kernel-1", buf, 8, &len); + ck_assert_ptr_null(ret); + /* nothing may be written at or past the out_max bound */ + ck_assert_uint_eq(buf[8], 0xA5); +} +END_TEST + /* ------------------------------------------------------------------------- */ static Suite *fit_gzip_suite(void) @@ -301,6 +320,7 @@ static Suite *fit_gzip_suite(void) tcase_add_test(tc, test_fit_to_gzip_disabled_returns_null); #endif tcase_add_test(tc, test_fit_to_lzma_unknown_returns_null); + tcase_add_test(tc, test_fit_to_none_oversized_rejected); suite_add_tcase(s, tc); return s; From b3c2c2dc2479fcf0ea7e45201db2a2e48e022ea2 Mon Sep 17 00:00:00 2001 From: aidan garske Date: Thu, 9 Jul 2026 17:47:46 -0700 Subject: [PATCH 4/5] 6562 - Emit build-time warning for WOLFBOOT_SKIP_BOOT_VERIFY --- options.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/options.mk b/options.mk index b6adb4a588..68f7bec926 100644 --- a/options.mk +++ b/options.mk @@ -899,6 +899,7 @@ ifeq ($(WOLFBOOT_SKIP_BOOT_VERIFY),1) ifneq ($(SELF_UPDATE_MONOLITHIC),1) $(error WOLFBOOT_SKIP_BOOT_VERIFY=1 requires WOLFBOOT_SELF_UPDATE_MONOLITHIC (set SELF_UPDATE_MONOLITHIC=1)) endif + $(warning WOLFBOOT_SKIP_BOOT_VERIFY=1 disables ALL boot-time firmware signature and integrity verification; only safe when an external verifier authenticates the full monolithic payload before boot. Do not use in production.) CFLAGS+=-D"WOLFBOOT_SKIP_BOOT_VERIFY" endif From 1f55b08c0b7d5874d735074ae2b3310af8967ccc Mon Sep 17 00:00:00 2001 From: aidan garske Date: Thu, 9 Jul 2026 17:52:30 -0700 Subject: [PATCH 5/5] 6589 - Use volatile accumulator in whFlashH5_Verify CT compare --- src/wolfhsm_flash_hal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wolfhsm_flash_hal.c b/src/wolfhsm_flash_hal.c index 13caab7b90..eeb7016aff 100644 --- a/src/wolfhsm_flash_hal.c +++ b/src/wolfhsm_flash_hal.c @@ -196,7 +196,7 @@ static int whFlashH5_Verify(void *context, uint32_t offset, uint32_t size, { whFlashH5Ctx *ctx = (whFlashH5Ctx *)context; const uint8_t *p; - uint8_t acc = 0; + volatile uint8_t acc = 0; uint32_t i; if (ctx == NULL || (size != 0U && data == NULL)) {