Skip to content

Commit 2f691b7

Browse files
nordicjmrlubos
authored andcommitted
[nrf noup] zephyr: Add support for compressed image updates
Adds support for LZMA-compressed firmware updates which also supports encrypted images and supports more than 1 updateable image Signed-off-by: Jamie McCrae <[email protected]> Signed-off-by: Dominik Ermel <[email protected]> (cherry picked from commit eb5056a)
1 parent ab3b5d7 commit 2f691b7

File tree

7 files changed

+1877
-24
lines changed

7 files changed

+1877
-24
lines changed

boot/bootutil/src/bootutil_misc.c

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@
4343
#include "bootutil/enc_key.h"
4444
#endif
4545

46+
#if defined(MCUBOOT_DECOMPRESS_IMAGES)
47+
#include <nrf_compress/implementation.h>
48+
#include <compression/decompression.h>
49+
#endif
50+
4651
BOOT_LOG_MODULE_DECLARE(mcuboot);
4752

4853
/* Currently only used by imgmgr */
@@ -523,35 +528,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
523528
fap = BOOT_IMG_AREA(state, slot);
524529
assert(fap != NULL);
525530

526-
off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
531+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
532+
if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) {
533+
uint32_t tmp_size = 0;
527534

528-
if (flash_area_read(fap, off, &info, sizeof(info))) {
529-
rc = BOOT_EFLASH;
530-
goto done;
531-
}
535+
rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size);
536+
537+
if (rc) {
538+
rc = BOOT_EBADIMAGE;
539+
goto done;
540+
}
541+
542+
off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size;
543+
544+
rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size);
532545

533-
protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
534-
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
535-
if (protect_tlv_size != info.it_tlv_tot) {
546+
if (rc) {
536547
rc = BOOT_EBADIMAGE;
537548
goto done;
538549
}
539550

540-
if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
551+
off += tmp_size;
552+
553+
if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) +
554+
boot_img_hdr(state, slot)->ih_protect_tlv_size), &info,
555+
sizeof(info))) {
541556
rc = BOOT_EFLASH;
542557
goto done;
543558
}
544-
} else if (protect_tlv_size != 0) {
545-
rc = BOOT_EBADIMAGE;
546-
goto done;
547-
}
548559

549-
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
550-
rc = BOOT_EBADIMAGE;
551-
goto done;
560+
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
561+
rc = BOOT_EBADIMAGE;
562+
goto done;
563+
}
564+
565+
*size = off + info.it_tlv_tot;
566+
} else {
567+
#else
568+
if (1) {
569+
#endif
570+
off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
571+
572+
if (flash_area_read(fap, off, &info, sizeof(info))) {
573+
rc = BOOT_EFLASH;
574+
goto done;
575+
}
576+
577+
protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
578+
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
579+
if (protect_tlv_size != info.it_tlv_tot) {
580+
rc = BOOT_EBADIMAGE;
581+
goto done;
582+
}
583+
584+
if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
585+
rc = BOOT_EFLASH;
586+
goto done;
587+
}
588+
} else if (protect_tlv_size != 0) {
589+
rc = BOOT_EBADIMAGE;
590+
goto done;
591+
}
592+
593+
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
594+
rc = BOOT_EBADIMAGE;
595+
goto done;
596+
}
597+
598+
*size = off + protect_tlv_size + info.it_tlv_tot;
552599
}
553600

554-
*size = off + protect_tlv_size + info.it_tlv_tot;
555601
rc = 0;
556602

557603
done:

boot/bootutil/src/image_validate.c

Lines changed: 227 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@
4242

4343
#include "mcuboot_config/mcuboot_config.h"
4444

45+
#if defined(MCUBOOT_DECOMPRESS_IMAGES)
46+
#include <nrf_compress/implementation.h>
47+
#include <compression/decompression.h>
48+
#endif
49+
50+
#include "bootutil/bootutil_log.h"
51+
52+
BOOT_LOG_MODULE_DECLARE(mcuboot);
53+
4554
#ifdef MCUBOOT_ENC_IMAGES
4655
#include "bootutil/enc_key.h"
4756
#endif
@@ -484,7 +493,7 @@ bootutil_img_validate(struct boot_loader_state *state,
484493
#endif
485494
)
486495
{
487-
#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT)
496+
#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES)
488497
int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state));
489498
#endif
490499
uint32_t off;
@@ -527,6 +536,68 @@ bootutil_img_validate(struct boot_loader_state *state,
527536
}
528537
#endif
529538

539+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
540+
/* If the image is compressed, the integrity of the image must also be validated */
541+
if (MUST_DECOMPRESS(fap, image_index, hdr)) {
542+
bool found_decompressed_size = false;
543+
bool found_decompressed_sha = false;
544+
bool found_decompressed_signature = false;
545+
546+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true);
547+
if (rc) {
548+
goto out;
549+
}
550+
551+
if (it.tlv_end > bootutil_max_image_size(state, fap)) {
552+
rc = -1;
553+
goto out;
554+
}
555+
556+
while (true) {
557+
uint16_t expected_size = 0;
558+
bool *found_flag = NULL;
559+
560+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
561+
if (rc < 0) {
562+
goto out;
563+
} else if (rc > 0) {
564+
break;
565+
}
566+
567+
switch (type) {
568+
case IMAGE_TLV_DECOMP_SIZE:
569+
expected_size = sizeof(size_t);
570+
found_flag = &found_decompressed_size;
571+
break;
572+
case IMAGE_TLV_DECOMP_SHA:
573+
expected_size = IMAGE_HASH_SIZE;
574+
found_flag = &found_decompressed_sha;
575+
break;
576+
case IMAGE_TLV_DECOMP_SIGNATURE:
577+
found_flag = &found_decompressed_signature;
578+
break;
579+
default:
580+
continue;
581+
};
582+
583+
if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) {
584+
rc = -1;
585+
goto out;
586+
} else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) {
587+
rc = -1;
588+
goto out;
589+
}
590+
591+
*found_flag = true;
592+
}
593+
594+
rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature);
595+
if (rc) {
596+
goto out;
597+
}
598+
}
599+
#endif
600+
530601
#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
531602
#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
532603
rc = bootutil_img_hash(state, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len,
@@ -760,6 +831,161 @@ bootutil_img_validate(struct boot_loader_state *state,
760831
skip_security_counter_check:
761832
#endif
762833

834+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
835+
/* Only after all previous verifications have passed, perform a dry-run of the decompression
836+
* and ensure the image is valid
837+
*/
838+
if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) {
839+
image_hash_valid = 0;
840+
FIH_SET(valid_signature, FIH_FAILURE);
841+
842+
rc = bootutil_img_hash_decompress(state, hdr, fap, tmp_buf, tmp_buf_sz,
843+
hash, seed, seed_len);
844+
if (rc) {
845+
goto out;
846+
}
847+
848+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true);
849+
if (rc) {
850+
goto out;
851+
}
852+
853+
if (it.tlv_end > bootutil_max_image_size(state, fap)) {
854+
rc = -1;
855+
goto out;
856+
}
857+
858+
while (true) {
859+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
860+
if (rc < 0) {
861+
goto out;
862+
} else if (rc > 0) {
863+
break;
864+
}
865+
866+
if (type == IMAGE_TLV_DECOMP_SHA) {
867+
/* Verify the image hash. This must always be present. */
868+
if (len != sizeof(hash)) {
869+
rc = -1;
870+
goto out;
871+
}
872+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash));
873+
if (rc) {
874+
goto out;
875+
}
876+
877+
FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash));
878+
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
879+
FIH_SET(fih_rc, FIH_FAILURE);
880+
goto out;
881+
}
882+
883+
image_hash_valid = 1;
884+
}
885+
}
886+
887+
rc = !image_hash_valid;
888+
if (rc) {
889+
goto out;
890+
}
891+
892+
#ifdef EXPECTED_SIG_TLV
893+
#ifdef EXPECTED_KEY_TLV
894+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false);
895+
if (rc) {
896+
goto out;
897+
}
898+
899+
if (it.tlv_end > bootutil_max_image_size(state, fap)) {
900+
rc = -1;
901+
goto out;
902+
}
903+
904+
while (true) {
905+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
906+
if (rc < 0) {
907+
goto out;
908+
} else if (rc > 0) {
909+
break;
910+
}
911+
912+
if (type == EXPECTED_KEY_TLV) {
913+
/*
914+
* Determine which key we should be checking.
915+
*/
916+
if (len > KEY_BUF_SIZE) {
917+
rc = -1;
918+
goto out;
919+
}
920+
#ifndef MCUBOOT_HW_KEY
921+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len);
922+
if (rc) {
923+
goto out;
924+
}
925+
key_id = bootutil_find_key(buf, len);
926+
#else
927+
rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
928+
if (rc) {
929+
goto out;
930+
}
931+
key_id = bootutil_find_key(image_index, key_buf, len);
932+
#endif /* !MCUBOOT_HW_KEY */
933+
/*
934+
* The key may not be found, which is acceptable. There
935+
* can be multiple signatures, each preceded by a key.
936+
*/
937+
}
938+
}
939+
#endif /* EXPECTED_KEY_TLV */
940+
941+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true);
942+
if (rc) {
943+
goto out;
944+
}
945+
946+
if (it.tlv_end > bootutil_max_image_size(state, fap)) {
947+
rc = -1;
948+
goto out;
949+
}
950+
951+
while (true) {
952+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
953+
if (rc < 0) {
954+
goto out;
955+
} else if (rc > 0) {
956+
rc = 0;
957+
break;
958+
}
959+
960+
if (type == IMAGE_TLV_DECOMP_SIGNATURE) {
961+
/* Ignore this signature if it is out of bounds. */
962+
if (key_id < 0 || key_id >= bootutil_key_cnt) {
963+
key_id = -1;
964+
continue;
965+
}
966+
967+
if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) {
968+
rc = -1;
969+
goto out;
970+
}
971+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len);
972+
if (rc) {
973+
goto out;
974+
}
975+
976+
FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash),
977+
buf, len, key_id);
978+
key_id = -1;
979+
}
980+
}
981+
#endif /* EXPECTED_SIG_TLV */
982+
}
983+
#endif
984+
985+
#ifdef EXPECTED_SIG_TLV
986+
FIH_SET(fih_rc, valid_signature);
987+
#endif
988+
763989
out:
764990
if (rc) {
765991
FIH_SET(fih_rc, FIH_FAILURE);

0 commit comments

Comments
 (0)