From ddc4d89d3666afe4ab4f54b7e4640aac30b2c1f9 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 31 Jul 2024 08:58:15 +0100 Subject: [PATCH 1/7] bootutil: Add compressed image flags and TLV Adds some flags to indicate if the data of an image is compressed (lzma1 and lzma2) and adds new TLVs for compressed images relating to the hash, signature and size of the decompressed image data, this allows the image to be validated before decompressing, then validated after decompression to ensure an image is always valid for a device Signed-off-by: Jamie McCrae --- boot/bootutil/include/bootutil/image.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 1f12d9512..3e03f80dd 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -71,6 +71,13 @@ struct flash_area; */ #define IMAGE_F_ROM_FIXED 0x00000100 +/* + * Flags that indicate if the image data is compressed + */ +#define IMAGE_F_COMPRESSED_LZMA1 0x00000200 +#define IMAGE_F_COMPRESSED_LZMA2 0x00000400 +#define IMAGE_F_COMPRESSED_ARM_THUMB_FLT 0x00000800 + /* * ECSDA224 is with NIST P-224 * ECSDA256 is with NIST P-256 @@ -101,6 +108,18 @@ struct flash_area; #define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ #define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ #define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */ +/* The following flags relate to compressed images and are for the decompressed image data */ +#define IMAGE_TLV_DECOMP_SIZE 0x70 /* Decompressed image size excluding header/TLVs */ +#define IMAGE_TLV_DECOMP_SHA 0x71 /* + * Decompressed image shaX hash, this field must match + * the format and size of the raw slot (compressed) + * shaX hash + */ +#define IMAGE_TLV_DECOMP_SIGNATURE 0x72 /* + * Decompressed image signature, this field must match + * the format and size of the raw slot (compressed) + * signature + */ /* * vendor reserved TLVs at xxA0-xxFF, * where xx denotes the upper byte @@ -160,6 +179,12 @@ struct image_tlv { #define MUST_DECRYPT(fap, idx, hdr) \ (flash_area_get_id(fap) == FLASH_AREA_IMAGE_SECONDARY(idx) && IS_ENCRYPTED(hdr)) +#define COMPRESSIONFLAGS (IMAGE_F_COMPRESSED_LZMA1 | IMAGE_F_COMPRESSED_LZMA2 \ + | IMAGE_F_COMPRESSED_ARM_THUMB_FLT) +#define IS_COMPRESSED(hdr) ((hdr)->ih_flags & COMPRESSIONFLAGS) +#define MUST_DECOMPRESS(fap, idx, hdr) \ + (flash_area_get_id(fap) == FLASH_AREA_IMAGE_SECONDARY(idx) && IS_COMPRESSED(hdr)) + _Static_assert(sizeof(struct image_header) == IMAGE_HEADER_SIZE, "struct image_header not required size"); From f3db7445278ff76b9c3631a0d5cf125617541991 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 23 Aug 2024 08:13:00 +0100 Subject: [PATCH 2/7] zephyr: Add Kconfig for decompression Adds a Kconfig allowing the decompression option to be selected Signed-off-by: Jamie McCrae --- boot/zephyr/Kconfig | 27 +++++++++++++++++++ .../include/mcuboot_config/mcuboot_config.h | 4 +++ 2 files changed, 31 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index bf772cac7..64e23ac6d 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -729,6 +729,33 @@ config MCUBOOT_BOOT_BANNER config BOOT_BANNER_STRING default "Using Zephyr OS build" if MCUBOOT_BOOT_BANNER +config BOOT_DECOMPRESSION_SUPPORT + bool + help + Hidden symbol which should be selected if a system provided decompression support. + +if BOOT_DECOMPRESSION_SUPPORT + +menuconfig BOOT_DECOMPRESSION + bool "Decompression" + help + If enabled, will include support for compressed images being loaded to the secondary slot + which then get decompressed into the primary slot. This mode allows the secondary slot to + be smaller than primary slot which otherwise would not be allowed. + +if BOOT_DECOMPRESSION + +config BOOT_DECOMPRESSION_BUFFER_SIZE + int "Write buffer size" + range 16 16384 + default 4096 + help + The size of a secondary buffer used for writing decompressed data to the storage device. + +endif # BOOT_DECOMPRESSION + +endif # BOOT_DECOMPRESSION_SUPPORT + endmenu config MCUBOOT_DEVICE_SETTINGS diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index bb30ce298..0891a4b11 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -127,6 +127,10 @@ #define MCUBOOT_ENCRYPT_X25519 #endif +#ifdef CONFIG_BOOT_DECOMPRESSION +#define MCUBOOT_DECOMPRESS_IMAGES +#endif + #ifdef CONFIG_BOOT_BOOTSTRAP #define MCUBOOT_BOOTSTRAP 1 #endif From 0f141e3550c633b1f2e0a2daab3bf8377c8d1fe8 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 23 Aug 2024 08:13:26 +0100 Subject: [PATCH 3/7] bootutil: loader: Remove encrypted/compressed images without support Checks if images have compressed or encrypted image flags and, if so, and those options are not enabled in that MCUboot build, will class the images as invalid and delete them (these images cannot be used without support anyway) Signed-off-by: Jamie McCrae --- boot/bootutil/src/loader.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 8663fbf2a..60a78a1cd 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -860,7 +860,9 @@ split_image_check(struct image_header *app_hdr, * Check that this is a valid header. Valid means that the magic is * correct, and that the sizes/offsets are "sane". Sane means that * there is no overflow on the arithmetic, and that the result fits - * within the flash area we are in. + * within the flash area we are in. Also check the flags in the image + * and class the image as invalid if flags for encryption/compression + * are present but these features are not enabled. */ static bool boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fap) @@ -879,6 +881,18 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } +#if !defined(MCUBOOT_ENC_IMAGES) + if (IS_ENCRYPTED(hdr)) { + return false; + } +#endif + +#if !defined(MCUBOOT_DECOMPRESS_IMAGES) + if (IS_COMPRESSED(hdr)) { + return false; + } +#endif + return true; } From 4a95b3860dac6ed84aa443b1ca7729a168f6f64f Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 23 Aug 2024 08:25:24 +0100 Subject: [PATCH 4/7] bootutil: loader: Remove images with conflicting flags Marks images as invalid if they have conflicting flags, e.g. more than one type of LZMA compression or more than one type of encryption Signed-off-by: Jamie McCrae --- boot/bootutil/src/loader.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 60a78a1cd..327d3782e 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -885,12 +885,24 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa if (IS_ENCRYPTED(hdr)) { return false; } +#else + if ((hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) && + (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256)) + { + return false; + } #endif #if !defined(MCUBOOT_DECOMPRESS_IMAGES) if (IS_COMPRESSED(hdr)) { return false; } +#else + if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && + (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) + { + return false; + } #endif return true; From cf0b103e76242e8f40f3aebe4731aacd8687cfa5 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 23 Aug 2024 08:16:47 +0100 Subject: [PATCH 5/7] bootutil: loader: Add protected TLV size to image size check The protected TLV section was not included in the size check of if an image could fit into a slot, which means that it was possible for file to be deemed as OK for storing but then failing due to insufficient flash space during the update Signed-off-by: Jamie McCrae --- boot/bootutil/src/loader.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 327d3782e..d780d8541 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -877,6 +877,16 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } +#ifdef MCUBOOT_DECOMPRESS_IMAGES + if (!MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { +#else + if (1) { +#endif + if (!boot_u32_safe_add(&size, size, hdr->ih_protect_tlv_size)) { + return false; + } + } + if (size >= flash_area_get_size(fap)) { return false; } From 394df160fec1998f06fd789eb1067c9474343741 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 23 Aug 2024 08:51:11 +0100 Subject: [PATCH 6/7] booutil: swap_scratch: Do not check sectors with compression When compression is used, it allows for the secondary slot to be smaller than the primary slot, therefore do not ensure that the number of sectors in each slot are the same Signed-off-by: Jamie McCrae --- boot/bootutil/src/swap_scratch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index 2cdb91a49..2fcf76f69 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -218,12 +218,14 @@ boot_slots_compatible(struct boot_loader_state *state) #endif } +#ifndef MCUBOOT_DECOMPRESS_IMAGES if ((i != num_sectors_primary) || (j != num_sectors_secondary) || (primary_slot_sz != secondary_slot_sz)) { BOOT_LOG_WRN("Cannot upgrade: slots are not compatible"); return 0; } +#endif return 1; } From bb116156ed278743ee87dcd59c89798e75784db6 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 23 Aug 2024 08:28:40 +0100 Subject: [PATCH 7/7] docs: release-notes: Add note on changes Adds release notes based on these changes Signed-off-by: Jamie McCrae --- docs/release-notes.d/zephyr-compression.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 docs/release-notes.d/zephyr-compression.md diff --git a/docs/release-notes.d/zephyr-compression.md b/docs/release-notes.d/zephyr-compression.md new file mode 100644 index 000000000..ba9ec2a7a --- /dev/null +++ b/docs/release-notes.d/zephyr-compression.md @@ -0,0 +1,7 @@ +- Added protected TLV size to image size check in bootutil +- Added Kconfig for decompression support in Zephyr +- Added compressed image flags and TLV to bootutil +- Added support for removing images with conflicting flags in + bootutil +- Added support for removing encrypted/compressed images when + MCUboot is compiled without support for them