Skip to content

Commit 898b9bc

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: Michal Kozikowski <[email protected]> Signed-off-by: Dominik Ermel <[email protected]> (cherry picked from commit c3ba628)
1 parent b6c992e commit 898b9bc

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
@@ -47,6 +47,11 @@
4747
#include "swap_priv.h"
4848
#endif
4949

50+
#if defined(MCUBOOT_DECOMPRESS_IMAGES)
51+
#include <nrf_compress/implementation.h>
52+
#include <compression/decompression.h>
53+
#endif
54+
5055
BOOT_LOG_MODULE_DECLARE(mcuboot);
5156

5257
/* Currently only used by imgmgr */
@@ -482,35 +487,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
482487
fap = BOOT_IMG_AREA(state, slot);
483488
assert(fap != NULL);
484489

485-
off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
490+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
491+
if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) {
492+
uint32_t tmp_size = 0;
486493

487-
if (flash_area_read(fap, off, &info, sizeof(info))) {
488-
rc = BOOT_EFLASH;
489-
goto done;
490-
}
494+
rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size);
495+
496+
if (rc) {
497+
rc = BOOT_EBADIMAGE;
498+
goto done;
499+
}
500+
501+
off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size;
502+
503+
rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size);
491504

492-
protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
493-
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
494-
if (protect_tlv_size != info.it_tlv_tot) {
505+
if (rc) {
495506
rc = BOOT_EBADIMAGE;
496507
goto done;
497508
}
498509

499-
if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
510+
off += tmp_size;
511+
512+
if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) +
513+
boot_img_hdr(state, slot)->ih_protect_tlv_size), &info,
514+
sizeof(info))) {
500515
rc = BOOT_EFLASH;
501516
goto done;
502517
}
503-
} else if (protect_tlv_size != 0) {
504-
rc = BOOT_EBADIMAGE;
505-
goto done;
506-
}
507518

508-
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
509-
rc = BOOT_EBADIMAGE;
510-
goto done;
519+
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
520+
rc = BOOT_EBADIMAGE;
521+
goto done;
522+
}
523+
524+
*size = off + info.it_tlv_tot;
525+
} else {
526+
#else
527+
if (1) {
528+
#endif
529+
off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
530+
531+
if (flash_area_read(fap, off, &info, sizeof(info))) {
532+
rc = BOOT_EFLASH;
533+
goto done;
534+
}
535+
536+
protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
537+
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
538+
if (protect_tlv_size != info.it_tlv_tot) {
539+
rc = BOOT_EBADIMAGE;
540+
goto done;
541+
}
542+
543+
if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
544+
rc = BOOT_EFLASH;
545+
goto done;
546+
}
547+
} else if (protect_tlv_size != 0) {
548+
rc = BOOT_EBADIMAGE;
549+
goto done;
550+
}
551+
552+
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
553+
rc = BOOT_EBADIMAGE;
554+
goto done;
555+
}
556+
557+
*size = off + protect_tlv_size + info.it_tlv_tot;
511558
}
512559

513-
*size = off + protect_tlv_size + info.it_tlv_tot;
514560
rc = 0;
515561

516562
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
#endif
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
#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
@@ -800,6 +866,161 @@ bootutil_img_validate(struct boot_loader_state *state,
800866
skip_security_counter_check:
801867
#endif
802868

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

0 commit comments

Comments
 (0)