Skip to content

Commit 40f13e4

Browse files
nordicjmtomchy
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 27758d7)
1 parent 43a12ac commit 40f13e4

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
@@ -48,6 +48,11 @@ BOOT_LOG_MODULE_DECLARE(mcuboot);
4848
#include "bootutil/mcuboot_uuid.h"
4949
#endif /* MCUBOOT_UUID_VID || MCUBOOT_UUID_CID */
5050

51+
#if defined(MCUBOOT_DECOMPRESS_IMAGES)
52+
#include <nrf_compress/implementation.h>
53+
#include <compression/decompression.h>
54+
#endif
55+
5156
#ifdef MCUBOOT_ENC_IMAGES
5257
#include "bootutil/enc_key.h"
5358
#endif
@@ -511,7 +516,7 @@ bootutil_img_validate(struct boot_loader_state *state,
511516
)
512517
{
513518
#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) \
514-
|| defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID)
519+
|| defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) || defined(MCUBOOT_DECOMPRESS_IMAGES)
515520
int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state));
516521
#endif
517522
uint32_t off;
@@ -564,6 +569,67 @@ bootutil_img_validate(struct boot_loader_state *state,
564569
#endif
565570

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

568634
#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
569635
#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
@@ -883,6 +949,161 @@ bootutil_img_validate(struct boot_loader_state *state,
883949
}
884950
#endif
885951

952+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
953+
/* Only after all previous verifications have passed, perform a dry-run of the decompression
954+
* and ensure the image is valid
955+
*/
956+
if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) {
957+
image_hash_valid = 0;
958+
FIH_SET(valid_signature, FIH_FAILURE);
959+
960+
rc = bootutil_img_hash_decompress(state, hdr, fap, tmp_buf, tmp_buf_sz,
961+
hash, seed, seed_len);
962+
if (rc) {
963+
goto out;
964+
}
965+
966+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true);
967+
if (rc) {
968+
goto out;
969+
}
970+
971+
if (it.tlv_end > bootutil_max_image_size(state, fap)) {
972+
rc = -1;
973+
goto out;
974+
}
975+
976+
while (true) {
977+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
978+
if (rc < 0) {
979+
goto out;
980+
} else if (rc > 0) {
981+
break;
982+
}
983+
984+
if (type == IMAGE_TLV_DECOMP_SHA) {
985+
/* Verify the image hash. This must always be present. */
986+
if (len != sizeof(hash)) {
987+
rc = -1;
988+
goto out;
989+
}
990+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash));
991+
if (rc) {
992+
goto out;
993+
}
994+
995+
FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash));
996+
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
997+
FIH_SET(fih_rc, FIH_FAILURE);
998+
goto out;
999+
}
1000+
1001+
image_hash_valid = 1;
1002+
}
1003+
}
1004+
1005+
rc = !image_hash_valid;
1006+
if (rc) {
1007+
goto out;
1008+
}
1009+
1010+
#ifdef EXPECTED_SIG_TLV
1011+
#ifdef EXPECTED_KEY_TLV
1012+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false);
1013+
if (rc) {
1014+
goto out;
1015+
}
1016+
1017+
if (it.tlv_end > bootutil_max_image_size(state, fap)) {
1018+
rc = -1;
1019+
goto out;
1020+
}
1021+
1022+
while (true) {
1023+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
1024+
if (rc < 0) {
1025+
goto out;
1026+
} else if (rc > 0) {
1027+
break;
1028+
}
1029+
1030+
if (type == EXPECTED_KEY_TLV) {
1031+
/*
1032+
* Determine which key we should be checking.
1033+
*/
1034+
if (len > KEY_BUF_SIZE) {
1035+
rc = -1;
1036+
goto out;
1037+
}
1038+
#ifndef MCUBOOT_HW_KEY
1039+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len);
1040+
if (rc) {
1041+
goto out;
1042+
}
1043+
key_id = bootutil_find_key(buf, len);
1044+
#else
1045+
rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
1046+
if (rc) {
1047+
goto out;
1048+
}
1049+
key_id = bootutil_find_key(image_index, key_buf, len);
1050+
#endif /* !MCUBOOT_HW_KEY */
1051+
/*
1052+
* The key may not be found, which is acceptable. There
1053+
* can be multiple signatures, each preceded by a key.
1054+
*/
1055+
}
1056+
}
1057+
#endif /* EXPECTED_KEY_TLV */
1058+
1059+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true);
1060+
if (rc) {
1061+
goto out;
1062+
}
1063+
1064+
if (it.tlv_end > bootutil_max_image_size(state, fap)) {
1065+
rc = -1;
1066+
goto out;
1067+
}
1068+
1069+
while (true) {
1070+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
1071+
if (rc < 0) {
1072+
goto out;
1073+
} else if (rc > 0) {
1074+
rc = 0;
1075+
break;
1076+
}
1077+
1078+
if (type == IMAGE_TLV_DECOMP_SIGNATURE) {
1079+
/* Ignore this signature if it is out of bounds. */
1080+
if (key_id < 0 || key_id >= bootutil_key_cnt) {
1081+
key_id = -1;
1082+
continue;
1083+
}
1084+
1085+
if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) {
1086+
rc = -1;
1087+
goto out;
1088+
}
1089+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len);
1090+
if (rc) {
1091+
goto out;
1092+
}
1093+
1094+
FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash),
1095+
buf, len, key_id);
1096+
key_id = -1;
1097+
}
1098+
}
1099+
#endif /* EXPECTED_SIG_TLV */
1100+
}
1101+
#endif
1102+
1103+
#ifdef EXPECTED_SIG_TLV
1104+
FIH_SET(fih_rc, valid_signature);
1105+
#endif
1106+
8861107
out:
8871108
if (rc) {
8881109
FIH_SET(fih_rc, FIH_FAILURE);

0 commit comments

Comments
 (0)