Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
eaa6af2
Return UART flash read error on timeout
danielinux Apr 29, 2026
f86ffd8
Fix delta update cleanup on early errors
danielinux Apr 29, 2026
b0f1bf9
Handle library image malloc failure
danielinux Apr 29, 2026
bcd75b0
Fix multiboot debug header length guard
danielinux Apr 29, 2026
b6e6dc0
Harden local secret comparisons
danielinux Apr 29, 2026
1e6dd16
Harden encrypted key comparisons
danielinux Apr 29, 2026
74c0d29
Add single-partition disk boot tests
danielinux Apr 29, 2026
6e8e20c
Cap backward delta match length
danielinux Apr 29, 2026
dfc7656
Validate GPT partition array CRC
danielinux Apr 29, 2026
8eddbf3
zeroize ARM TEE PS buffers on reuse
danielinux Apr 29, 2026
98d1e77
Abort QSPI writes after WE failure
danielinux Apr 29, 2026
54b2ba3
Bound TPM name fallback copies
danielinux Apr 29, 2026
26cae31
Fix decrypted blob TLV parsing
danielinux Apr 29, 2026
cc6f52e
Add final sanity check after boot hook
danielinux Apr 29, 2026
c39522e
Add inverse delta version gate tests
danielinux Apr 29, 2026
47ef6b4
Add GPT single-sector partition test
danielinux Apr 29, 2026
afa9641
Add sector flag unit coverage
danielinux Apr 29, 2026
a60461f
Fix XMSS keygen param fallback
danielinux Apr 29, 2026
05f5f5c
Zeroize XMSS key readback buffer
danielinux Apr 29, 2026
47e1f77
Zero LMS key verify buffer
danielinux Apr 29, 2026
2a9aa60
Fixed test regressions
danielinux Apr 29, 2026
8eb7fa6
Addressed copilot's comments
danielinux Apr 29, 2026
8c0b44c
Fixed size-all thresholds
danielinux Apr 29, 2026
1226776
Modernize riscv build test
danielinux Apr 29, 2026
971f0c6
Improve readability of changes in disk.c
danielinux Apr 29, 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
3 changes: 3 additions & 0 deletions hal/library.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,16 @@ int main(int argc, const char* argv[])
if (((void*)gImage) == NULL) {
wolfBoot_printf("failed to malloc %zu bytes for image\n", sz);
ret = -1;
goto close_img;
}

bread = fread((void*)gImage, 1, sz, img);
if (bread != sz) {
ret = -2;
wolfBoot_printf("read %zu of %zu bytes from %s\n", bread, sz, argv[1]);
}

close_img:
fclose(img);
} else {
wolfBoot_printf("usage: %s image_file.bin\n", argv[0]);
Expand Down
34 changes: 33 additions & 1 deletion include/gpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ struct gpt_part_info {
uint16_t name[GPT_PART_NAME_SIZE];
};

/**
* @brief CRC32 context for GPT header and partition-array validation.
*/
struct gpt_crc32_ctx {
uint32_t value;
};

/**
* @brief Check MBR for protective GPT partition entry.
*
Expand Down Expand Up @@ -139,6 +146,32 @@ int gpt_parse_header(const uint8_t *sector, struct guid_ptable *hdr);
int gpt_parse_partition(const uint8_t *entry_data, uint32_t entry_size,
struct gpt_part_info *part);

/**
* @brief Initialize a GPT CRC32 calculation.
*
* @param[out] ctx Pointer to CRC32 context.
*/
void gpt_crc32_init(struct gpt_crc32_ctx *ctx);

/**
* @brief Accumulate bytes into a GPT CRC32 calculation.
*
* @param[in,out] ctx Pointer to CRC32 context.
* @param[in] data Pointer to input bytes.
* @param[in] len Number of bytes to process.
*/
void gpt_crc32_update(struct gpt_crc32_ctx *ctx, const uint8_t *data,
uint32_t len);

/**
* @brief Finalize a GPT CRC32 calculation.
*
* @param[in] ctx Pointer to CRC32 context.
*
* @return Final CRC32 value.
*/
uint32_t gpt_crc32_final(const struct gpt_crc32_ctx *ctx);

/**
* @brief Compare UTF-16 partition name with ASCII string.
*
Expand All @@ -152,4 +185,3 @@ int gpt_parse_partition(const uint8_t *entry_data, uint32_t entry_size,
int gpt_part_name_eq(const uint16_t *utf16_name, const char *ascii_label);

#endif /* GPT_H */

3 changes: 3 additions & 0 deletions src/arm_tee_psa_ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <psa/crypto.h>
#include <psa/error.h>

#include <wolfssl/wolfcrypt/memory.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfboot/arm_tee_api.h>
#include <wolfboot/dice.h>
Expand Down Expand Up @@ -240,6 +241,7 @@ static struct wolfboot_ps_entry *wolfboot_ps_alloc(psa_storage_uid_t uid)
{
for (size_t i = 0; i < WOLFBOOT_PS_MAX_ENTRIES; i++) {
if (!g_ps_entries[i].in_use) {
wc_ForceZero(g_ps_entries[i].data, sizeof(g_ps_entries[i].data));
g_ps_entries[i].in_use = 1;
g_ps_entries[i].uid = uid;
g_ps_entries[i].size = 0;
Expand Down Expand Up @@ -844,6 +846,7 @@ int32_t arm_tee_psa_call(psa_handle_t handle, int32_t type,
if (entry == NULL) {
return PSA_ERROR_DOES_NOT_EXIST;
}
wc_ForceZero(entry->data, sizeof(entry->data));
entry->in_use = 0;
entry->uid = 0;
entry->size = 0;
Expand Down
1 change: 1 addition & 0 deletions src/delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ int wb_diff(WB_DIFF_CTX *ctx, uint8_t *patch, uint32_t len)
pb+= BLOCK_HDR_SIZE;
ctx->off_b += BLOCK_HDR_SIZE;
while ((pb < pb_limit) &&
(match_len < UINT16_MAX) &&
(ctx->off_b < ctx->size_b) &&
(*pb == *(ctx->src_b + ctx->off_b))) {
/* Extend match as long as the areas have the
Expand Down
31 changes: 31 additions & 0 deletions src/disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,37 @@ int disk_open(int drv)
wolfBoot_printf("Valid GPT partition table\r\n");
wolfBoot_printf("Max number of partitions: %d\r\n", ptable.n_part);

{
Comment thread
dgarske marked this conversation as resolved.
Outdated
struct gpt_crc32_ctx part_crc;
uint64_t array_addr = ptable.start_array * GPT_SECTOR_SIZE;
uint64_t bytes_left = (uint64_t)ptable.n_part * ptable.array_sz;

gpt_crc32_init(&part_crc);
while (bytes_left > 0) {
uint32_t chunk = GPT_SECTOR_SIZE;

if (bytes_left < chunk) {
chunk = (uint32_t)bytes_left;
}

r = disk_read(drv, array_addr, chunk, sector);
if (r < 0) {
Drives[drv].is_open = 0;
return -1;
}

gpt_crc32_update(&part_crc, sector, chunk);
array_addr += chunk;
bytes_left -= chunk;
}

if (gpt_crc32_final(&part_crc) != ptable.part_crc) {
wolfBoot_printf("Invalid GPT partition entry array CRC\r\n");
Drives[drv].is_open = 0;
return -1;
}
}

n_parts = ptable.n_part;
if (n_parts > MAX_PARTITIONS)
n_parts = MAX_PARTITIONS;
Expand Down
35 changes: 28 additions & 7 deletions src/gpt.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,39 @@

#include "gpt.h"

static uint32_t gpt_crc32(const uint8_t *data, uint32_t len)
void gpt_crc32_init(struct gpt_crc32_ctx *ctx)
{
if (ctx != NULL) {
ctx->value = 0xFFFFFFFFU;
}
}

void gpt_crc32_update(struct gpt_crc32_ctx *ctx, const uint8_t *data,
uint32_t len)
{
uint32_t crc = 0xFFFFFFFFU;
uint32_t i;
uint32_t j;

if (ctx == NULL || data == NULL) {
return;
}

for (i = 0; i < len; i++) {
crc ^= data[i];
ctx->value ^= data[i];
for (j = 0; j < 8; j++) {
uint32_t mask = -(crc & 1U);
crc = (crc >> 1) ^ (0xEDB88320U & mask);
uint32_t mask = -(ctx->value & 1U);
ctx->value = (ctx->value >> 1) ^ (0xEDB88320U & mask);
}
}
}

uint32_t gpt_crc32_final(const struct gpt_crc32_ctx *ctx)
{
if (ctx == NULL) {
return 0;
}

return ~crc;
return ~ctx->value;
}

/**
Expand Down Expand Up @@ -116,6 +134,7 @@ int gpt_parse_header(const uint8_t *sector, struct guid_ptable *hdr)
{
const struct guid_ptable *src;
struct guid_ptable tmp;
struct gpt_crc32_ctx crc;

if (sector == NULL || hdr == NULL) {
return -1;
Expand All @@ -134,7 +153,9 @@ int gpt_parse_header(const uint8_t *sector, struct guid_ptable *hdr)

memcpy(&tmp, src, sizeof(tmp));
tmp.hdr_crc32 = 0;
if (gpt_crc32((const uint8_t *)&tmp, src->hdr_size) != src->hdr_crc32) {
gpt_crc32_init(&crc);
gpt_crc32_update(&crc, (const uint8_t *)&tmp, src->hdr_size);
if (gpt_crc32_final(&crc) != src->hdr_crc32) {
return -1;
}

Expand Down
8 changes: 5 additions & 3 deletions src/libwolfboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@
#ifdef EXT_ENCRYPTED
static int encrypt_key_is_erased(const uint8_t *key, uint32_t len)
{
const volatile uint8_t *vkey = key;
uint8_t diff = 0;
uint32_t i;

for (i = 0; i < len; i++)
diff |= key[i] ^ FLASH_BYTE_ERASED;
diff |= vkey[i] ^ FLASH_BYTE_ERASED;

return diff == 0;
}
Expand All @@ -85,13 +86,14 @@ static int fallback_iv_forced = 0;

static int encrypt_key_is_valid(const uint8_t *key, uint32_t len)
{
const volatile uint8_t *vkey = key;
uint8_t has_one = 0;
uint8_t has_zero = 0;
uint32_t i;

for (i = 0; i < len; i++) {
has_one |= key[i];
has_zero |= (uint8_t)~key[i];
has_one |= vkey[i];
has_zero |= (uint8_t)~vkey[i];
}

return (has_one != 0) && (has_zero != 0);
Expand Down
4 changes: 3 additions & 1 deletion src/multiboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,10 @@ static void mb2_dump_header(void* mbHeader) {
MB2_DEBUG_PRINTF("Checksum: 0x%x\r\n", header->checksum);

tags = (uint8_t*)header + sizeof(*header);
if (header->header_length < sizeof(struct mb2_header))
if (header->header_length < sizeof(struct mb2_header)) {
MB2_DEBUG_PRINTF("Invalid header length\r\n");
return;
}
mb2_dump_tags(tags, header->header_length - sizeof(*header));
}
#endif /* DEBUG_MB2 */
Expand Down
58 changes: 30 additions & 28 deletions src/qspi_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,38 +431,40 @@ int spi_flash_write(uint32_t address, const void *data, int len)
pages = ((len + (FLASH_PAGE_SIZE-1)) / FLASH_PAGE_SIZE);
for (page = 0; page < pages; page++) {
ret = qspi_write_enable();
if (ret == 0) {
xferSz = (uint32_t)remaining;
if (xferSz > FLASH_PAGE_SIZE) {
xferSz = FLASH_PAGE_SIZE;
}

addr = address + (page * FLASH_PAGE_SIZE);

/* ------ Write Flash (page at a time) ------ */
ret = qspi_transfer(QSPI_MODE_WRITE, FLASH_WRITE_CMD,
addr, QSPI_ADDR_SZ, QSPI_DATA_MODE_SPI, /* Address */
0, 0, QSPI_DATA_MODE_NONE, /* Alternate Bytes */
0, /* Dummy */
ptr, /* Destination Ptr */
xferSz, QSPI_DATA_MODE /* Data */
);
if (ret != 0) {
break;
}

xferSz = (uint32_t)remaining;
if (xferSz > FLASH_PAGE_SIZE) {
xferSz = FLASH_PAGE_SIZE;
}

addr = address + (page * FLASH_PAGE_SIZE);

/* ------ Write Flash (page at a time) ------ */
ret = qspi_transfer(QSPI_MODE_WRITE, FLASH_WRITE_CMD,
addr, QSPI_ADDR_SZ, QSPI_DATA_MODE_SPI, /* Address */
0, 0, QSPI_DATA_MODE_NONE, /* Alternate Bytes */
0, /* Dummy */
ptr, /* Destination Ptr */
xferSz, QSPI_DATA_MODE /* Data */
);
#ifdef DEBUG_QSPI
wolfBoot_printf("QSPI Flash Sector Write: "
"Ret %d, Cmd 0x%x, Len %d, %p -> 0x%x\n",
ret, FLASH_WRITE_CMD, xferSz, ptr, address);
wolfBoot_printf("QSPI Flash Sector Write: "
"Ret %d, Cmd 0x%x, Len %d, %p -> 0x%x\n",
ret, FLASH_WRITE_CMD, xferSz, ptr, address);
#endif
if (ret != 0)
break;
if (ret != 0)
break;

ret = qspi_wait_ready(); /* Wait for not busy */
if (ret != 0) {
break;
}
/* write disable is automatic */
remaining -= (int)xferSz;
ptr += xferSz;
ret = qspi_wait_ready(); /* Wait for not busy */
if (ret != 0) {
break;
}
/* write disable is automatic */
remaining -= (int)xferSz;
ptr += xferSz;
}

return ret;
Expand Down
6 changes: 4 additions & 2 deletions src/tpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1255,7 +1255,8 @@ const char* CSME_NSE_API wolfBoot_tpm2_get_alg_name(TPM_ALG_ID alg,
name[name_sz - 1] = '\0';
}
else {
strcpy(name, "Unknown");
strncpy(name, "Unknown", name_sz - 1);
name[name_sz - 1] = '\0';
}
return (const char*)name;
}
Expand All @@ -1272,7 +1273,8 @@ const char* CSME_NSE_API wolfBoot_tpm2_get_rc_string(int rc, char* error, int er
error[error_sz - 1] = '\0';
}
else {
strcpy(error, "Unknown");
strncpy(error, "Unknown", error_sz - 1);
error[error_sz - 1] = '\0';
}
return (const char*)error;
}
Expand Down
2 changes: 1 addition & 1 deletion src/uart_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len)
}
for (i = 0; i < len; i++) {
if (uart_rx_timeout(&data[i]) != 0)
return 0;
return -1;
uart_tx(CMD_ACK);
}
return i;
Expand Down
Loading
Loading