Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f598b3f
F-6878: delta: reject non-multiple SECTOR_SIZE/DELTA_BLOCK_SIZE at build
danielinux Sep 4, 2026
455c1c6
F-7067: elf scatter: fix PART_IS_EXT arg and check load result
danielinux Sep 4, 2026
88af5b6
F-7390: x86 fsp: drop dead FSP auth scaffolding, fix comment
danielinux Sep 4, 2026
77fe733
F-7391: library hal: reject undersized files, bound hash to loaded size
danielinux Sep 4, 2026
a2d5543
F-9740: update_disk: FSP low-mem rejection falls back to other slot
danielinux Sep 4, 2026
d244fd9
F-9745: x86_64_efi: inclusive mem path end, reject zero-size image
danielinux Sep 4, 2026
eb3d587
F-9746: x86_64_efi: fix do_boot prototype mismatch, drop unused param
danielinux Sep 4, 2026
785a285
F-11025: update_flash: document deliberately inert PCR extend block
danielinux Sep 4, 2026
5571124
F-11026: image: declare wolfHSM DER sig length as word32
danielinux Sep 4, 2026
0e2a463
F-11047: image: validate ELF scatter segments before flash writes
danielinux Sep 4, 2026
a6628a3
F-12108: image: clamp sha block/peek to fw_size
danielinux Sep 4, 2026
b5ab88a
F-9744: store: reject negative length before unsigned arithmetic
danielinux Sep 4, 2026
b9068ce
F-12105: tpm: keep keystore size as int in load_pubkey
danielinux Sep 4, 2026
d64f15a
F-7392: stm32h7: document inherent OTP immutability in set_readonly
danielinux Sep 4, 2026
62918f2
F-12107: pkcs11 nsc: zero work buffer before it can be freed
danielinux Sep 4, 2026
58e79da
F-11047: image: drop incorrect boot-partition destination check
danielinux Sep 4, 2026
01a71c7
x86_64_efi: return after LoadImage-failure panic under UNIT_TEST
danielinux Sep 4, 2026
b0209d0
image: use uint64_t for ELF scatter program-header locals
danielinux Sep 4, 2026
faaad37
Address minor PR 882 review nits
danielinux Sep 4, 2026
2dbb8ae
image: cast ELF scatter log fields to unsigned long
danielinux Sep 4, 2026
c291639
x86_64_efi: early-return after remaining panic() sites under UNIT_TEST
danielinux Sep 4, 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
12 changes: 12 additions & 0 deletions .github/workflows/test-library.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,18 @@ jobs:

echo "./test-lib test_v1_signed.bin"
./test-lib test_v1_signed.bin

# A file smaller than the image header must be rejected up front
# instead of being parsed (header fields would be read past the
# end of the allocation).
printf 'WOLF' > tiny.bin
./test-lib tiny.bin > tiny.out 2>&1 || true
if ! grep -q "too small" tiny.out; then
echo "FAIL: undersized file was not rejected before parsing"
cat tiny.out
exit 1
fi
echo "PASS: undersized file rejected"
./test-lib test_v1_signed.bin 2>&1 | grep "Firmware Valid"

- name: Run test-lib (expect failure)
Expand Down
28 changes: 27 additions & 1 deletion hal/library.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ int do_boot(uint32_t* v)
}

static uintptr_t gImage;
static size_t gImageSize;
#ifdef NO_FILESYSTEM
static const uint8_t test_img[] = {
0x57, 0x4F, 0x4C, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01,
Expand Down Expand Up @@ -130,6 +131,7 @@ static const uint8_t test_img[] = {
int wolfBoot_start(void)
{
struct wolfBoot_image os_image;
size_t max_payload;
int ret = 0;
memset(&os_image, 0, sizeof(os_image));

Expand All @@ -139,6 +141,19 @@ int wolfBoot_start(void)
goto exit;
}

/* The loaded file may be shorter than the firmware size the header
* claims; bound the hash range to the bytes actually loaded. Compute
* the payload in size_t and cap at UINT32_MAX so a > 4 GiB file
* clamps to the maximum firmware size rather than truncating to a
* small value. */
max_payload = gImageSize - IMAGE_HEADER_SIZE;
if (max_payload > UINT32_MAX) {
max_payload = UINT32_MAX;
}
if (os_image.fw_size > (uint32_t)max_payload) {
os_image.fw_size = (uint32_t)max_payload;
}
Comment thread
danielinux marked this conversation as resolved.

if ((ret = wolfBoot_verify_integrity(&os_image)) < 0) {
goto exit;
}
Expand Down Expand Up @@ -177,24 +192,35 @@ int main(int argc, const char* argv[])

#ifdef NO_FILESYSTEM
gImage = (uintptr_t)test_img;
gImageSize = sizeof(test_img);
#else
if (argc > 1) {
size_t sz = 0, bread;
long fsz;
FILE* img = fopen(argv[1], "rb");
if (img == NULL) {
wolfBoot_printf("failed to open %s!\n", argv[1]);
return -3;
}
fseek(img, 0, SEEK_END);
sz = ftell(img);
fsz = ftell(img);
fseek(img, 0, SEEK_SET);

if ((fsz < 0) || ((size_t)fsz < IMAGE_HEADER_SIZE)) {
wolfBoot_printf("image file too small: %ld bytes "
"(minimum %d)\n", fsz, IMAGE_HEADER_SIZE);
ret = -4;
goto close_img;
}
sz = (size_t)fsz;

gImage = (uintptr_t)malloc(sz);
if (((void*)gImage) == NULL) {
wolfBoot_printf("failed to malloc %zu bytes for image\n", sz);
ret = -1;
goto close_img;
}
gImageSize = sz;

bread = fread((void*)gImage, 1, sz, img);
if (bread != sz) {
Expand Down
6 changes: 5 additions & 1 deletion hal/stm32h7.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,11 @@ static void hal_flash_otp_lock(void)

int hal_flash_otp_set_readonly(uint32_t flashAddress, uint16_t length)
{
/* TODO: set WP on OTP if needed */
/* The STM32H7 OTP memory is one-time programmable: once the keystore
* and UDS are written, the data is permanent and cannot be overwritten.
* Unlike the STM32H5, the H7 has no OTP block-lock register, so there
* is no explicit write-protection step to perform. The anchor is
* protected by the inherent immutability of the programmed OTP. */
return 0;
}

Expand Down
49 changes: 37 additions & 12 deletions hal/x86_64_efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,20 @@ void *hal_get_dts_update_address(void)

static void panic()
{
#ifdef UNIT_TEST
/* The unit test observes wolfBoot_panicked and needs to get back;
* on target this never returns. */
wolfBoot_panic();
return;
#else
while(1) {}
#endif
}

void RAMFUNCTION x86_64_efi_do_boot(uint32_t *boot_addr, uint8_t *dts_address)
void RAMFUNCTION x86_64_efi_do_boot(const uint32_t *boot_addr)
{
uint32_t *size;
uint8_t* manifest = ((uint8_t*)boot_addr) - IMAGE_HEADER_SIZE;

(void)dts_address; /* Unused for now */
const uint32_t *size;
const uint8_t* manifest = ((const uint8_t*)boot_addr) - IMAGE_HEADER_SIZE;

MEMMAP_DEVICE_PATH mem_path_device[2];
EFI_HANDLE kernelImageHandle;
Expand All @@ -114,7 +119,15 @@ void RAMFUNCTION x86_64_efi_do_boot(uint32_t *boot_addr, uint8_t *dts_address)
EFI_LOADED_IMAGE *kernel_li = NULL;
EFI_GUID lipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;

size = (uint32_t *)(manifest + 4);
size = (const uint32_t *)(manifest + 4);

/* Guard against a zero-size image: EndingAddress below would underflow
* and an empty range would be handed to LoadImage. */
if (*size == 0) {
wolfBoot_printf("invalid zero-size image\n");
panic();
return; /* Never reached on target, where panic() does not return */
}

/* Authenticated kernel command line from the verified image's HDR_CMDLINE
* TLV (covered by the signature); NULL if the image carries none. */
Expand All @@ -123,8 +136,11 @@ void RAMFUNCTION x86_64_efi_do_boot(uint32_t *boot_addr, uint8_t *dts_address)
mem_path_device->Header.Type = EFI_DEVICE_PATH_PROTOCOL_HW_TYPE;
mem_path_device->Header.SubType = EFI_DEVICE_PATH_PROTOCOL_MEM_SUBTYPE;
mem_path_device->MemoryType = EfiLoaderData;
mem_path_device->StartingAddress = (EFI_PHYSICAL_ADDRESS)boot_addr;
mem_path_device->EndingAddress = (EFI_PHYSICAL_ADDRESS)((uint8_t*)boot_addr+*size);
mem_path_device->StartingAddress =
(EFI_PHYSICAL_ADDRESS)(uintptr_t)boot_addr;
/* MEMMAP_DEVICE_PATH EndingAddress is inclusive (last valid byte). */
mem_path_device->EndingAddress =
(EFI_PHYSICAL_ADDRESS)((uintptr_t)boot_addr + *size - 1);
SetDevicePathNodeLength(&mem_path_device->Header,
sizeof(MEMMAP_DEVICE_PATH));

Expand All @@ -136,12 +152,13 @@ void RAMFUNCTION x86_64_efi_do_boot(uint32_t *boot_addr, uint8_t *dts_address)
0, /* bool */
gImageHandle,
(EFI_DEVICE_PATH*)mem_path_device,
boot_addr,
(void*)(uintptr_t)boot_addr,
*size,
&kernelImageHandle);
if (status != EFI_SUCCESS) {
wolfBoot_printf("can't load kernel image from memory\n");
panic();
return; /* Never reached on target, where panic() does not return */
}

/* Hand the authenticated command line to the loaded image via LoadOptions
Expand Down Expand Up @@ -193,19 +210,25 @@ static EFI_FILE_HANDLE GetVolume(EFI_HANDLE image)

status = uefi_call_wrapper(BS->HandleProtocol, 3,
image, &lipGuid, (void **) &loaded_image);
if (status != EFI_SUCCESS)
if (status != EFI_SUCCESS) {
panic();
return NULL; /* Never reached on target (panic() does not return) */
}

status = uefi_call_wrapper(BS->HandleProtocol, 3,
loaded_image->DeviceHandle,
&fsGuid, (VOID*)&IOVolume);
if (status != EFI_SUCCESS)
if (status != EFI_SUCCESS) {
panic();
return NULL; /* Never reached on target (panic() does not return) */
}

status = uefi_call_wrapper(IOVolume->OpenVolume, 2, IOVolume, &Volume);

if (status != EFI_SUCCESS)
if (status != EFI_SUCCESS) {
panic();
return NULL; /* Never reached on target (panic() does not return) */
}

return Volume;
}
Expand Down Expand Up @@ -336,6 +359,8 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
if (kernel_addr == 0 && update_addr == 0) {
wolfBoot_printf("No image to load\n");
panic();
return EFI_LOAD_ERROR; /* Never reached on target (panic() does not
* return) */
}

wolfBoot_start();
Expand Down
4 changes: 2 additions & 2 deletions src/boot_x86_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ extern unsigned int __bss_end__;
static volatile unsigned int cpu_id;
extern unsigned int *END_STACK;

extern void RAMFUNCTION x86_64_efi_do_boot(uint8_t *kernel);
extern void RAMFUNCTION x86_64_efi_do_boot(const uint32_t *boot_addr);

#if defined(MMU) || defined(WOLFBOOT_FDT)
void RAMFUNCTION do_boot(const uint32_t *app_offset, const uint32_t* dts_offset)
#else
void RAMFUNCTION do_boot(const uint32_t *app_offset)
#endif
{
x86_64_efi_do_boot((uint8_t *)app_offset);
x86_64_efi_do_boot(app_offset);
}

#endif /* TARGET_X86_64_EFI */
13 changes: 4 additions & 9 deletions src/boot_x86_fsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@


#ifndef STAGE1_AUTH
/* When STAGE1_AUTH is disabled, create dummy images to fill
* the space used by wolfBoot manifest headers to authenticate FSPs
/* When STAGE1_AUTH is disabled, fill the stage2 manifest header slot with
* a zeroed placeholder so the image layout matches the authenticated build.
* Only the stage2 wolfBoot payload is authenticated; the FSP-M and FSP-S
* blobs are outside the scope of STAGE1_AUTH.
*/
#define HEADER_SIZE IMAGE_HEADER_SIZE
const uint8_t __attribute__((section(".sig_fsp_s")))
empty_sig_fsp_s[HEADER_SIZE] = {};
const uint8_t __attribute__((section(".sig_wolfboot_raw")))
empty_sig_wolfboot_raw[HEADER_SIZE] = {};
#endif
Expand Down Expand Up @@ -543,11 +543,6 @@ void start(uint32_t stack_base, uint32_t stack_top, uint64_t timestamp,
uint16_t type;
uint32_t esp;

#ifdef STAGE1_AUTH
int ret;
struct wolfBoot_image fsp_m;
#endif

(void)stack_top;
(void)timestamp;
(void)bist;
Expand Down
Loading
Loading