Skip to content

Commit 8dfa951

Browse files
nordicjmjukkar
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 c3ba628) (cherry picked from commit 898b9bc)
1 parent 24bfc1a commit 8dfa951

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
@@ -51,6 +51,11 @@
5151
#include "swap_priv.h"
5252
#endif
5353

54+
#if defined(MCUBOOT_DECOMPRESS_IMAGES)
55+
#include <nrf_compress/implementation.h>
56+
#include <compression/decompression.h>
57+
#endif
58+
5459
BOOT_LOG_MODULE_DECLARE(mcuboot);
5560

5661
/* Currently only used by imgmgr */
@@ -487,35 +492,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
487492
fap = BOOT_IMG_AREA(state, slot);
488493
assert(fap != NULL);
489494

490-
off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
495+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
496+
if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) {
497+
uint32_t tmp_size = 0;
491498

492-
if (flash_area_read(fap, off, &info, sizeof(info))) {
493-
rc = BOOT_EFLASH;
494-
goto done;
495-
}
499+
rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size);
500+
501+
if (rc) {
502+
rc = BOOT_EBADIMAGE;
503+
goto done;
504+
}
505+
506+
off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size;
507+
508+
rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size);
496509

497-
protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
498-
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
499-
if (protect_tlv_size != info.it_tlv_tot) {
510+
if (rc) {
500511
rc = BOOT_EBADIMAGE;
501512
goto done;
502513
}
503514

504-
if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
515+
off += tmp_size;
516+
517+
if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) +
518+
boot_img_hdr(state, slot)->ih_protect_tlv_size), &info,
519+
sizeof(info))) {
505520
rc = BOOT_EFLASH;
506521
goto done;
507522
}
508-
} else if (protect_tlv_size != 0) {
509-
rc = BOOT_EBADIMAGE;
510-
goto done;
511-
}
512523

513-
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
514-
rc = BOOT_EBADIMAGE;
515-
goto done;
524+
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
525+
rc = BOOT_EBADIMAGE;
526+
goto done;
527+
}
528+
529+
*size = off + info.it_tlv_tot;
530+
} else {
531+
#else
532+
if (1) {
533+
#endif
534+
off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
535+
536+
if (flash_area_read(fap, off, &info, sizeof(info))) {
537+
rc = BOOT_EFLASH;
538+
goto done;
539+
}
540+
541+
protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
542+
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
543+
if (protect_tlv_size != info.it_tlv_tot) {
544+
rc = BOOT_EBADIMAGE;
545+
goto done;
546+
}
547+
548+
if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
549+
rc = BOOT_EFLASH;
550+
goto done;
551+
}
552+
} else if (protect_tlv_size != 0) {
553+
rc = BOOT_EBADIMAGE;
554+
goto done;
555+
}
556+
557+
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
558+
rc = BOOT_EBADIMAGE;
559+
goto done;
560+
}
561+
562+
*size = off + protect_tlv_size + info.it_tlv_tot;
516563
}
517564

518-
*size = off + protect_tlv_size + info.it_tlv_tot;
519565
rc = 0;
520566

521567
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
@@ -507,7 +512,7 @@ bootutil_img_validate(struct boot_loader_state *state,
507512
int seed_len, uint8_t *out_hash
508513
)
509514
{
510-
#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT)
515+
#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES)
511516
int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state));
512517
#endif
513518
uint32_t off;
@@ -552,6 +557,67 @@ bootutil_img_validate(struct boot_loader_state *state,
552557
#endif
553558

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

556622
#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
557623
rc = bootutil_img_hash(state, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len);
@@ -793,6 +859,161 @@ bootutil_img_validate(struct boot_loader_state *state,
793859
skip_security_counter_check:
794860
#endif
795861

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

0 commit comments

Comments
 (0)