@@ -343,6 +343,49 @@ test-sim-self-update-monolithic-self-header: wolfboot.bin test-app/image_v1_sign
343343 @echo " Self-header persisted correctly: PASSED"
344344 @echo " === Monolithic Self-Update + Self-Header Test PASSED ==="
345345
346+ # Test that an oversized monolithic self-update is rejected. The payload is
347+ # signed and staged normally, but its firmware size exceeds the install span
348+ # (bootloader region + BOOT partition minus the trailer sector), so wolfBoot
349+ # must refuse it and leave the bootloader and BOOT partition untouched.
350+ # Requires a build with wolfBoot_printf output (e.g. DEBUG=1, as in the
351+ # sim-self-update-monolithic example config).
352+ test-sim-self-update-monolithic-oversize : wolfboot.bin test-app/image_v1_signed.bin FORCE
353+ @echo " === Simulator Monolithic Self-Update Oversize Rejection Test ==="
354+ @# Create dummy bootloader (0xAA pattern, exactly bootloader region size)
355+ $(Q ) dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_BOOT_ADDRESS ) - $(ARCH_FLASH_OFFSET ) ) ) count=1 2> /dev/null | tr ' \000' ' \252' > monolithic_dummy_bl.bin
356+ @# Build a payload 0x100 bytes past the max install span, padded with 0xFF.
357+ @# It still fits the UPDATE partition, so only the install-span check can
358+ @# reject it.
359+ $(Q ) dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_BOOT_ADDRESS ) - $(ARCH_FLASH_OFFSET ) + $(WOLFBOOT_PARTITION_SIZE ) - $(WOLFBOOT_SECTOR_SIZE ) + 0x100 ) ) count=1 2> /dev/null | tr ' \000' ' \377' > monolithic_oversize.bin
360+ $(Q ) cat monolithic_dummy_bl.bin test-app/image_v1_signed.bin | dd of=monolithic_oversize.bin conv=notrunc 2> /dev/null
361+ @# Sign with an inflated update partition size: the keytool refuses
362+ @# oversized images, and the point here is the bootloader's own guard
363+ $(Q )$(SIGN_ENV ) WOLFBOOT_PARTITION_UPDATE_SIZE=0x1000000 $(SIGN_TOOL ) $(SIGN_OPTIONS ) --wolfboot-update monolithic_oversize.bin $(PRIVATE_KEY ) 2
364+ @# Create update partition with signed oversized image and "pBOOT" trailer
365+ $(Q ) dd if=/dev/zero bs=$$(($(or $(WOLFBOOT_PARTITION_UPDATE_SIZE ) ,$(WOLFBOOT_PARTITION_SIZE ) ) ) ) count=1 2> /dev/null | tr ' \000' ' \377' > update_part.dd
366+ $(Q ) dd if=monolithic_oversize_v2_signed.bin of=update_part.dd bs=1 conv=notrunc
367+ $(Q ) printf " pBOOT" | dd of=update_part.dd bs=1 seek=$$(($(or $(WOLFBOOT_PARTITION_UPDATE_SIZE ) ,$(WOLFBOOT_PARTITION_SIZE ) ) - 5 ) ) conv=notrunc
368+ @# Create erased boot partition
369+ $(Q ) dd if=/dev/zero bs=$$(($(WOLFBOOT_PARTITION_SIZE ) ) ) count=1 2> /dev/null | tr ' \000' ' \377' > boot_part.dd
370+ @# Assemble flash: wolfboot.bin at 0, empty boot partition, update partition
371+ $(Q )$(BINASSEMBLE ) internal_flash.dd \
372+ 0 wolfboot.bin \
373+ $$(($(WOLFBOOT_PARTITION_BOOT_ADDRESS ) - $(ARCH_FLASH_OFFSET ) ) ) boot_part.dd \
374+ $$(($(WOLFBOOT_PARTITION_UPDATE_ADDRESS ) - $(ARCH_FLASH_OFFSET ) ) ) update_part.dd
375+ @# Run simulator - the self-update must be refused before any flash write
376+ $(Q ) ./wolfboot.elf get_version > monolithic_oversize.log 2>&1 || true
377+ $(Q ) grep -q " Self update image too large" monolithic_oversize.log || \
378+ { echo " Rejection message not found; simulator output:" ; \
379+ cat monolithic_oversize.log; false ; }
380+ @echo " Oversized self-update rejected: PASSED"
381+ @# Verify the bootloader region still contains the original wolfboot.bin
382+ $(Q ) cmp -n $$(wc -c < wolfboot.bin | awk '{print $$1}' ) wolfboot.bin internal_flash.dd
383+ @echo " Bootloader region untouched: PASSED"
384+ @# Verify the boot partition is still fully erased
385+ $(Q ) cmp -n $$(($(WOLFBOOT_PARTITION_SIZE ) ) ) boot_part.dd internal_flash.dd 0 $$(($(WOLFBOOT_PARTITION_BOOT_ADDRESS ) - $(ARCH_FLASH_OFFSET ) ) )
386+ @echo " Boot partition untouched: PASSED"
387+ @echo " === Monolithic Self-Update Oversize Rejection Test PASSED ==="
388+
346389# Test self-header cryptographic verification (hash + signature validation)
347390#
348391# Verifies that an application can cryptographically verify the bootloader using
0 commit comments