Skip to content

Commit c3ba628

Browse files
nordicjmnvlsianpu
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: Michal Kozikowski <[email protected]> Signed-off-by: Dominik Ermel <[email protected]> (cherry picked from commit 38e8159) (cherry picked from commit 2f691b7) (cherry picked from commit d20d66d)
1 parent ca61577 commit c3ba628

File tree

7 files changed

+1929
-24
lines changed

7 files changed

+1929
-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 */
@@ -568,35 +573,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
568573
fap = BOOT_IMG_AREA(state, slot);
569574
assert(fap != NULL);
570575

571-
off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
576+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
577+
if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) {
578+
uint32_t tmp_size = 0;
572579

573-
if (flash_area_read(fap, off, &info, sizeof(info))) {
574-
rc = BOOT_EFLASH;
575-
goto done;
576-
}
580+
rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size);
581+
582+
if (rc) {
583+
rc = BOOT_EBADIMAGE;
584+
goto done;
585+
}
586+
587+
off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size;
588+
589+
rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size);
577590

578-
protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
579-
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
580-
if (protect_tlv_size != info.it_tlv_tot) {
591+
if (rc) {
581592
rc = BOOT_EBADIMAGE;
582593
goto done;
583594
}
584595

585-
if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
596+
off += tmp_size;
597+
598+
if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) +
599+
boot_img_hdr(state, slot)->ih_protect_tlv_size), &info,
600+
sizeof(info))) {
586601
rc = BOOT_EFLASH;
587602
goto done;
588603
}
589-
} else if (protect_tlv_size != 0) {
590-
rc = BOOT_EBADIMAGE;
591-
goto done;
592-
}
593604

594-
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
595-
rc = BOOT_EBADIMAGE;
596-
goto done;
605+
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
606+
rc = BOOT_EBADIMAGE;
607+
goto done;
608+
}
609+
610+
*size = off + info.it_tlv_tot;
611+
} else {
612+
#else
613+
if (1) {
614+
#endif
615+
off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
616+
617+
if (flash_area_read(fap, off, &info, sizeof(info))) {
618+
rc = BOOT_EFLASH;
619+
goto done;
620+
}
621+
622+
protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
623+
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
624+
if (protect_tlv_size != info.it_tlv_tot) {
625+
rc = BOOT_EBADIMAGE;
626+
goto done;
627+
}
628+
629+
if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
630+
rc = BOOT_EFLASH;
631+
goto done;
632+
}
633+
} else if (protect_tlv_size != 0) {
634+
rc = BOOT_EBADIMAGE;
635+
goto done;
636+
}
637+
638+
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
639+
rc = BOOT_EBADIMAGE;
640+
goto done;
641+
}
642+
643+
*size = off + protect_tlv_size + info.it_tlv_tot;
597644
}
598645

599-
*size = off + protect_tlv_size + info.it_tlv_tot;
600646
rc = 0;
601647

602648
done:

boot/bootutil/src/image_validate.c

Lines changed: 222 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@
4545

4646
BOOT_LOG_MODULE_DECLARE(mcuboot);
4747

48+
#if defined(MCUBOOT_DECOMPRESS_IMAGES)
49+
#include <nrf_compress/implementation.h>
50+
#include <compression/decompression.h>
51+
#endif
52+
4853
#ifdef MCUBOOT_ENC_IMAGES
4954
#include "bootutil/enc_key.h"
5055
#endif
@@ -494,7 +499,7 @@ bootutil_img_validate(struct boot_loader_state *state,
494499
#endif
495500
)
496501
{
497-
#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT)
502+
#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES)
498503
int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state));
499504
#endif
500505
uint32_t off;
@@ -539,6 +544,67 @@ bootutil_img_validate(struct boot_loader_state *state,
539544
#endif
540545

541546
BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap);
547+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
548+
/* If the image is compressed, the integrity of the image must also be validated */
549+
if (MUST_DECOMPRESS(fap, image_index, hdr)) {
550+
bool found_decompressed_size = false;
551+
bool found_decompressed_sha = false;
552+
bool found_decompressed_signature = false;
553+
554+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true);
555+
if (rc) {
556+
goto out;
557+
}
558+
559+
if (it.tlv_end > bootutil_max_image_size(state, fap)) {
560+
rc = -1;
561+
goto out;
562+
}
563+
564+
while (true) {
565+
uint16_t expected_size = 0;
566+
bool *found_flag = NULL;
567+
568+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
569+
if (rc < 0) {
570+
goto out;
571+
} else if (rc > 0) {
572+
break;
573+
}
574+
575+
switch (type) {
576+
case IMAGE_TLV_DECOMP_SIZE:
577+
expected_size = sizeof(size_t);
578+
found_flag = &found_decompressed_size;
579+
break;
580+
case IMAGE_TLV_DECOMP_SHA:
581+
expected_size = IMAGE_HASH_SIZE;
582+
found_flag = &found_decompressed_sha;
583+
break;
584+
case IMAGE_TLV_DECOMP_SIGNATURE:
585+
found_flag = &found_decompressed_signature;
586+
break;
587+
default:
588+
continue;
589+
};
590+
591+
if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) {
592+
rc = -1;
593+
goto out;
594+
} else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) {
595+
rc = -1;
596+
goto out;
597+
}
598+
599+
*found_flag = true;
600+
}
601+
602+
rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature);
603+
if (rc) {
604+
goto out;
605+
}
606+
}
607+
#endif
542608

543609
#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
544610
#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
@@ -787,6 +853,161 @@ bootutil_img_validate(struct boot_loader_state *state,
787853
skip_security_counter_check:
788854
#endif
789855

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

0 commit comments

Comments
 (0)