Skip to content

Commit 4399de2

Browse files
nordicjmnvlsianpu
authored andcommitted
[nrf noup] zephyr: Add support for compressed image updates
Adds support for LZMA-compressed firmware updates Signed-off-by: Jamie McCrae <[email protected]> Signed-off-by: Dominik Ermel <[email protected]> (cherry picked from commit 474a922) (cherry picked from commit 655eeac)
1 parent a1a093a commit 4399de2

File tree

7 files changed

+1545
-23
lines changed

7 files changed

+1545
-23
lines changed

boot/bootutil/src/bootutil_misc.c

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

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

4752
/* Currently only used by imgmgr */
@@ -384,35 +389,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
384389
goto done;
385390
}
386391

387-
off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
392+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
393+
if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) {
394+
uint32_t tmp_size = 0;
388395

389-
if (flash_area_read(fap, off, &info, sizeof(info))) {
390-
rc = BOOT_EFLASH;
391-
goto done;
392-
}
396+
rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size);
393397

394-
protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
395-
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
396-
if (protect_tlv_size != info.it_tlv_tot) {
398+
if (rc) {
397399
rc = BOOT_EBADIMAGE;
398400
goto done;
399401
}
400402

401-
if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
403+
off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size;
404+
405+
rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size);
406+
407+
if (rc) {
408+
rc = BOOT_EBADIMAGE;
409+
goto done;
410+
}
411+
412+
off += tmp_size;
413+
414+
if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) +
415+
boot_img_hdr(state, slot)->ih_protect_tlv_size), &info,
416+
sizeof(info))) {
402417
rc = BOOT_EFLASH;
403418
goto done;
404419
}
405-
} else if (protect_tlv_size != 0) {
406-
rc = BOOT_EBADIMAGE;
407-
goto done;
408-
}
409420

410-
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
411-
rc = BOOT_EBADIMAGE;
412-
goto done;
421+
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
422+
rc = BOOT_EBADIMAGE;
423+
goto done;
424+
}
425+
426+
*size = off + info.it_tlv_tot;
427+
} else {
428+
#else
429+
if (1) {
430+
#endif
431+
off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
432+
433+
if (flash_area_read(fap, off, &info, sizeof(info))) {
434+
rc = BOOT_EFLASH;
435+
goto done;
436+
}
437+
438+
protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
439+
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
440+
if (protect_tlv_size != info.it_tlv_tot) {
441+
rc = BOOT_EBADIMAGE;
442+
goto done;
443+
}
444+
445+
if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
446+
rc = BOOT_EFLASH;
447+
goto done;
448+
}
449+
} else if (protect_tlv_size != 0) {
450+
rc = BOOT_EBADIMAGE;
451+
goto done;
452+
}
453+
454+
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
455+
rc = BOOT_EBADIMAGE;
456+
goto done;
457+
}
458+
459+
*size = off + protect_tlv_size + info.it_tlv_tot;
413460
}
414461

415-
*size = off + protect_tlv_size + info.it_tlv_tot;
416462
rc = 0;
417463

418464
done:

boot/bootutil/src/image_validate.c

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@
4040

4141
#include "mcuboot_config/mcuboot_config.h"
4242

43+
#if defined(MCUBOOT_DECOMPRESS_IMAGES)
44+
#include <nrf_compress/implementation.h>
45+
#include <compression/decompression.h>
46+
#endif
47+
48+
#include "bootutil/bootutil_log.h"
49+
50+
BOOT_LOG_MODULE_DECLARE(mcuboot);
51+
4352
#ifdef MCUBOOT_ENC_IMAGES
4453
#include "bootutil/enc_key.h"
4554
#endif
@@ -470,6 +479,68 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
470479
FIH_DECLARE(security_counter_valid, FIH_FAILURE);
471480
#endif
472481

482+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
483+
/* If the image is compressed, the integrity of the image must also be validated */
484+
if (MUST_DECOMPRESS(fap, image_index, hdr)) {
485+
bool found_decompressed_size = false;
486+
bool found_decompressed_sha = false;
487+
bool found_decompressed_signature = false;
488+
489+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true);
490+
if (rc) {
491+
goto out;
492+
}
493+
494+
if (it.tlv_end > bootutil_max_image_size(fap)) {
495+
rc = -1;
496+
goto out;
497+
}
498+
499+
while (true) {
500+
uint16_t expected_size = 0;
501+
bool *found_flag = NULL;
502+
503+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
504+
if (rc < 0) {
505+
goto out;
506+
} else if (rc > 0) {
507+
break;
508+
}
509+
510+
switch (type) {
511+
case IMAGE_TLV_DECOMP_SIZE:
512+
expected_size = sizeof(size_t);
513+
found_flag = &found_decompressed_size;
514+
break;
515+
case IMAGE_TLV_DECOMP_SHA:
516+
expected_size = IMAGE_HASH_SIZE;
517+
found_flag = &found_decompressed_sha;
518+
break;
519+
case IMAGE_TLV_DECOMP_SIGNATURE:
520+
found_flag = &found_decompressed_signature;
521+
break;
522+
default:
523+
continue;
524+
};
525+
526+
if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) {
527+
rc = -1;
528+
goto out;
529+
} else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) {
530+
rc = -1;
531+
goto out;
532+
}
533+
534+
*found_flag = true;
535+
}
536+
537+
rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature);
538+
if (rc) {
539+
goto out;
540+
}
541+
}
542+
#endif
543+
473544
#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
474545
rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf,
475546
tmp_buf_sz, hash, seed, seed_len);
@@ -680,6 +751,161 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
680751
}
681752
#endif
682753

754+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
755+
/* Only after all previous verifications have passed, perform a dry-run of the decompression
756+
* and ensure the image is valid
757+
*/
758+
if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) {
759+
image_hash_valid = 0;
760+
FIH_SET(valid_signature, FIH_FAILURE);
761+
762+
rc = bootutil_img_hash_decompress(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz,
763+
hash, seed, seed_len);
764+
if (rc) {
765+
goto out;
766+
}
767+
768+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true);
769+
if (rc) {
770+
goto out;
771+
}
772+
773+
if (it.tlv_end > bootutil_max_image_size(fap)) {
774+
rc = -1;
775+
goto out;
776+
}
777+
778+
while (true) {
779+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
780+
if (rc < 0) {
781+
goto out;
782+
} else if (rc > 0) {
783+
break;
784+
}
785+
786+
if (type == IMAGE_TLV_DECOMP_SHA) {
787+
/* Verify the image hash. This must always be present. */
788+
if (len != sizeof(hash)) {
789+
rc = -1;
790+
goto out;
791+
}
792+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash));
793+
if (rc) {
794+
goto out;
795+
}
796+
797+
FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash));
798+
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
799+
FIH_SET(fih_rc, FIH_FAILURE);
800+
goto out;
801+
}
802+
803+
image_hash_valid = 1;
804+
}
805+
}
806+
807+
rc = !image_hash_valid;
808+
if (rc) {
809+
goto out;
810+
}
811+
812+
#ifdef EXPECTED_SIG_TLV
813+
#ifdef EXPECTED_KEY_TLV
814+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false);
815+
if (rc) {
816+
goto out;
817+
}
818+
819+
if (it.tlv_end > bootutil_max_image_size(fap)) {
820+
rc = -1;
821+
goto out;
822+
}
823+
824+
while (true) {
825+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
826+
if (rc < 0) {
827+
goto out;
828+
} else if (rc > 0) {
829+
break;
830+
}
831+
832+
if (type == EXPECTED_KEY_TLV) {
833+
/*
834+
* Determine which key we should be checking.
835+
*/
836+
if (len > KEY_BUF_SIZE) {
837+
rc = -1;
838+
goto out;
839+
}
840+
#ifndef MCUBOOT_HW_KEY
841+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len);
842+
if (rc) {
843+
goto out;
844+
}
845+
key_id = bootutil_find_key(buf, len);
846+
#else
847+
rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
848+
if (rc) {
849+
goto out;
850+
}
851+
key_id = bootutil_find_key(image_index, key_buf, len);
852+
#endif /* !MCUBOOT_HW_KEY */
853+
/*
854+
* The key may not be found, which is acceptable. There
855+
* can be multiple signatures, each preceded by a key.
856+
*/
857+
}
858+
}
859+
#endif /* EXPECTED_KEY_TLV */
860+
861+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true);
862+
if (rc) {
863+
goto out;
864+
}
865+
866+
if (it.tlv_end > bootutil_max_image_size(fap)) {
867+
rc = -1;
868+
goto out;
869+
}
870+
871+
while (true) {
872+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
873+
if (rc < 0) {
874+
goto out;
875+
} else if (rc > 0) {
876+
rc = 0;
877+
break;
878+
}
879+
880+
if (type == IMAGE_TLV_DECOMP_SIGNATURE) {
881+
/* Ignore this signature if it is out of bounds. */
882+
if (key_id < 0 || key_id >= bootutil_key_cnt) {
883+
key_id = -1;
884+
continue;
885+
}
886+
887+
if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) {
888+
rc = -1;
889+
goto out;
890+
}
891+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len);
892+
if (rc) {
893+
goto out;
894+
}
895+
896+
FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash),
897+
buf, len, key_id);
898+
key_id = -1;
899+
}
900+
}
901+
#endif /* EXPECTED_SIG_TLV */
902+
}
903+
#endif
904+
905+
#ifdef EXPECTED_SIG_TLV
906+
FIH_SET(fih_rc, valid_signature);
907+
#endif
908+
683909
out:
684910
if (rc) {
685911
FIH_SET(fih_rc, FIH_FAILURE);

0 commit comments

Comments
 (0)