From 98cae9a3e8ebda514b88b416ce86ba955600bf34 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 7 Oct 2025 13:52:10 +0000 Subject: [PATCH 1/2] bootutil: Add MCUBOOT_CHECK_HEADER_LOAD_ADDRESS Adding MCUBOOT_CHECK_HEADER_LOAD_ADDRESS that allows to verify header stored ih_load_addr against target boot slot, to allow MCUboot to reject firmware uploaded for incorrect slot. This option works with encrypted software, as it does not require decrypting image. This option takes precedence over MCUBOOT_VERIFY_IMG_ADDRESS. Note that the change leaves MCUBOOT_VERIFY_IMG_ADDRESS with the bug reported here https://github.com/mcu-tools/mcuboot/issues/2473. This commit also removes dependency on having more then one image to have the check enabled, as it makes no point to block using it on single image. Co-authored-by: Andrzej Puzdrowski Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index fcb5de410..1989c86d7 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -81,6 +81,13 @@ static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; #define TARGET_STATIC #endif +#if defined(MCUBOOT_VERIFY_IMG_ADDRESS) && defined(MCUBOOT_CHECK_HEADER_LOAD_ADDRESS) +#warning MCUBOOT_CHECK_HEADER_LOAD_ADDRESS takes precedence over MCUBOOT_VERIFY_IMG_ADDRESS +#endif + +/* Valid only for ARM Cortext M */ +#define RESET_OFFSET (2 * sizeof(uin32_t)) + #if BOOT_MAX_ALIGN > 1024 #define BUF_SZ BOOT_MAX_ALIGN #else @@ -1002,24 +1009,41 @@ boot_validate_slot(struct boot_loader_state *state, int slot, goto out; } -#if MCUBOOT_IMAGE_NUMBER > 1 && !defined(MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_VERIFY_IMG_ADDRESS) +#if defined(MCUBOOT_VERIFY_IMG_ADDRESS) && !defined(MCUBOOT_ENC_IMAGES) || \ + defined(MCUBOOT_CHECK_HEADER_LOAD_ADDRESS) /* Verify that the image in the secondary slot has a reset address * located in the primary slot. This is done to avoid users incorrectly * overwriting an application written to the incorrect slot. * This feature is only supported by ARM platforms. */ if (fap == BOOT_IMG_AREA(state, BOOT_SLOT_SECONDARY)) { - const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY); struct image_header *secondary_hdr = boot_img_hdr(state, slot); - uint32_t reset_value = 0; - uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); + uint32_t internal_img_addr = 0; /* either the reset handler addres or the image beginning addres */ + uint32_t min_addr; + uint32_t max_addr; - if (flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)) != 0) { + min_addr = flash_area_get_off(BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY)); + max_addr = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY)) + min_addr; + +/* MCUBOOT_CHECK_HEADER_LOAD_ADDRESS takes priority over MCUBOOT_VERIFY_IMG_ADDRESS */ +#ifdef MCUBOOT_CHECK_HEADER_LOAD_ADDRESS + internal_img_addr = secondary_hdr->ih_load_addr; +#else + /* This is platform specific code that should not be here */ + const uint32_t offset = secondary_hdr->ih_hdr_size + RESET_OFFSET; + BOOT_LOG_DBG("Getting image %d internal addr from offset %u", + BOOT_CURR_IMG(state), offset); + if (flash_area_read(fap, offset, &internal_img_addr, sizeof(internal_img_addr)) != 0) + BOOT_LOG_ERR("Failed to read image %d load address", BOOT_CURR_IMG(state)); fih_rc = FIH_NO_BOOTABLE_IMAGE; goto out; } +#endif - if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) { + BOOT_LOG_DBG("Image %d expected load address 0x%x", BOOT_CURR_IMG(state), internal_img_addr); + BOOT_LOG_DBG("Check 0x%x is within [min_addr, max_addr] = [0x%x, 0x%x)", + internal_img_addr, min_addr, max_addr); + if (internal_img_addr < min_addr || internal_img_addr >= max_addr) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); From 1b8b1988e7baf884f08592c88837c006c327eb69 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 7 Oct 2025 14:00:24 +0000 Subject: [PATCH 2/2] zephyr: Added MCUBOOT_CHECK_HEADER_LOAD_ADDRESS Kconfig Allows to enable MCUboot config MCUBOOT_CHECK_HEADER_LOAD_ADDRESS. Co-authored-by: Andrzej Puzdrowski Signed-off-by: Dominik Ermel --- boot/zephyr/Kconfig | 8 ++++++++ boot/zephyr/include/mcuboot_config/mcuboot_config.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 467b848dc..d264a088f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1308,6 +1308,14 @@ config USB_DEVICE_PRODUCT config MCUBOOT_BOOTUTIL_LIB_OWN_LOG bool +config MCUBOOT_CHECK_HEADER_LOAD_ADDRESS + bool "Use load address to verify application is in proper slot" + help + The bootloader will use the load address, from the image header, + to verify that binary is in slot designated for its execution. + When not selected reset vector, read from image, is used for + the same purpose. + config MCUBOOT_VERIFY_IMG_ADDRESS bool "Verify reset address of image in secondary slot" depends on UPDATEABLE_IMAGE_NUMBER > 1 diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index b35a11f97..4feca5b1a 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -307,6 +307,10 @@ #define MCUBOOT_FIND_NEXT_SLOT_HOOKS #endif +#ifdef CONFIG_MCUBOOT_CHECK_HEADER_LOAD_ADDRESS +#define MCUBOOT_CHECK_HEADER_LOAD_ADDRESS +#endif + #ifdef CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS #define MCUBOOT_VERIFY_IMG_ADDRESS #endif