|
45 | 45 |
|
46 | 46 | BOOT_LOG_MODULE_DECLARE(mcuboot);
|
47 | 47 |
|
| 48 | +#if defined(MCUBOOT_DECOMPRESS_IMAGES) |
| 49 | +#include <nrf_compress/implementation.h> |
| 50 | +#include <compression/decompression.h> |
| 51 | +#endif |
| 52 | + |
48 | 53 | #ifdef MCUBOOT_ENC_IMAGES
|
49 | 54 | #include "bootutil/enc_key.h"
|
50 | 55 | #endif
|
@@ -507,7 +512,7 @@ bootutil_img_validate(struct boot_loader_state *state,
|
507 | 512 | #endif
|
508 | 513 | )
|
509 | 514 | {
|
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) |
511 | 516 | int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state));
|
512 | 517 | #endif
|
513 | 518 | uint32_t off;
|
@@ -552,6 +557,67 @@ bootutil_img_validate(struct boot_loader_state *state,
|
552 | 557 | #endif
|
553 | 558 |
|
554 | 559 | 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 |
555 | 621 |
|
556 | 622 | #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
|
557 | 623 | #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
|
@@ -800,6 +866,161 @@ bootutil_img_validate(struct boot_loader_state *state,
|
800 | 866 | skip_security_counter_check:
|
801 | 867 | #endif
|
802 | 868 |
|
| 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 | + |
803 | 1024 | out:
|
804 | 1025 | if (rc) {
|
805 | 1026 | FIH_SET(fih_rc, FIH_FAILURE);
|
|
0 commit comments