Skip to content

Commit 8809820

Browse files
nordicjmrlubos
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]> (cherry picked from commit a242e91)
1 parent 4786da4 commit 8809820

File tree

6 files changed

+1528
-21
lines changed

6 files changed

+1528
-21
lines changed

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
@@ -416,6 +425,68 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
416425
FIH_DECLARE(security_counter_valid, FIH_FAILURE);
417426
#endif
418427

428+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
429+
/* If the image is compressed, the integrity of the image must also be validated */
430+
if (MUST_DECOMPRESS(fap, image_index, hdr)) {
431+
bool found_decompressed_size = false;
432+
bool found_decompressed_sha = false;
433+
bool found_decompressed_signature = false;
434+
435+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true);
436+
if (rc) {
437+
goto out;
438+
}
439+
440+
if (it.tlv_end > bootutil_max_image_size(fap)) {
441+
rc = -1;
442+
goto out;
443+
}
444+
445+
while (true) {
446+
uint16_t expected_size = 0;
447+
bool *found_flag = NULL;
448+
449+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
450+
if (rc < 0) {
451+
goto out;
452+
} else if (rc > 0) {
453+
break;
454+
}
455+
456+
switch (type) {
457+
case IMAGE_TLV_DECOMP_SIZE:
458+
expected_size = sizeof(size_t);
459+
found_flag = &found_decompressed_size;
460+
break;
461+
case IMAGE_TLV_DECOMP_SHA:
462+
expected_size = IMAGE_HASH_SIZE;
463+
found_flag = &found_decompressed_sha;
464+
break;
465+
case IMAGE_TLV_DECOMP_SIGNATURE:
466+
found_flag = &found_decompressed_signature;
467+
break;
468+
default:
469+
continue;
470+
};
471+
472+
if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) {
473+
rc = -1;
474+
goto out;
475+
} else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) {
476+
rc = -1;
477+
goto out;
478+
}
479+
480+
*found_flag = true;
481+
}
482+
483+
rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature);
484+
if (rc) {
485+
goto out;
486+
}
487+
}
488+
#endif
489+
419490
rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf,
420491
tmp_buf_sz, hash, seed, seed_len);
421492
if (rc) {
@@ -587,6 +658,161 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
587658
}
588659
#endif
589660

661+
#ifdef MCUBOOT_DECOMPRESS_IMAGES
662+
/* Only after all previous verifications have passed, perform a dry-run of the decompression
663+
* and ensure the image is valid
664+
*/
665+
if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) {
666+
image_hash_valid = 0;
667+
FIH_SET(valid_signature, FIH_FAILURE);
668+
669+
rc = bootutil_img_hash_decompress(enc_state, image_index, hdr, fap, tmp_buf, tmp_buf_sz,
670+
hash, seed, seed_len);
671+
if (rc) {
672+
goto out;
673+
}
674+
675+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true);
676+
if (rc) {
677+
goto out;
678+
}
679+
680+
if (it.tlv_end > bootutil_max_image_size(fap)) {
681+
rc = -1;
682+
goto out;
683+
}
684+
685+
while (true) {
686+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
687+
if (rc < 0) {
688+
goto out;
689+
} else if (rc > 0) {
690+
break;
691+
}
692+
693+
if (type == IMAGE_TLV_DECOMP_SHA) {
694+
/* Verify the image hash. This must always be present. */
695+
if (len != sizeof(hash)) {
696+
rc = -1;
697+
goto out;
698+
}
699+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash));
700+
if (rc) {
701+
goto out;
702+
}
703+
704+
FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash));
705+
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
706+
FIH_SET(fih_rc, FIH_FAILURE);
707+
goto out;
708+
}
709+
710+
image_hash_valid = 1;
711+
}
712+
}
713+
714+
rc = !image_hash_valid;
715+
if (rc) {
716+
goto out;
717+
}
718+
719+
#ifdef EXPECTED_SIG_TLV
720+
#ifdef EXPECTED_KEY_TLV
721+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false);
722+
if (rc) {
723+
goto out;
724+
}
725+
726+
if (it.tlv_end > bootutil_max_image_size(fap)) {
727+
rc = -1;
728+
goto out;
729+
}
730+
731+
while (true) {
732+
rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
733+
if (rc < 0) {
734+
goto out;
735+
} else if (rc > 0) {
736+
break;
737+
}
738+
739+
if (type == EXPECTED_KEY_TLV) {
740+
/*
741+
* Determine which key we should be checking.
742+
*/
743+
if (len > KEY_BUF_SIZE) {
744+
rc = -1;
745+
goto out;
746+
}
747+
#ifndef MCUBOOT_HW_KEY
748+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len);
749+
if (rc) {
750+
goto out;
751+
}
752+
key_id = bootutil_find_key(buf, len);
753+
#else
754+
rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
755+
if (rc) {
756+
goto out;
757+
}
758+
key_id = bootutil_find_key(image_index, key_buf, len);
759+
#endif /* !MCUBOOT_HW_KEY */
760+
/*
761+
* The key may not be found, which is acceptable. There
762+
* can be multiple signatures, each preceded by a key.
763+
*/
764+
}
765+
}
766+
#endif /* EXPECTED_KEY_TLV */
767+
768+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, 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+
rc = 0;
784+
break;
785+
}
786+
787+
if (type == IMAGE_TLV_DECOMP_SIGNATURE) {
788+
/* Ignore this signature if it is out of bounds. */
789+
if (key_id < 0 || key_id >= bootutil_key_cnt) {
790+
key_id = -1;
791+
continue;
792+
}
793+
794+
if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) {
795+
rc = -1;
796+
goto out;
797+
}
798+
rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len);
799+
if (rc) {
800+
goto out;
801+
}
802+
803+
FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash),
804+
buf, len, key_id);
805+
key_id = -1;
806+
}
807+
}
808+
#endif /* EXPECTED_SIG_TLV */
809+
}
810+
#endif
811+
812+
#ifdef EXPECTED_SIG_TLV
813+
FIH_SET(fih_rc, valid_signature);
814+
#endif
815+
590816
out:
591817
if (rc) {
592818
FIH_SET(fih_rc, FIH_FAILURE);

0 commit comments

Comments
 (0)