|
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
|
@@ -494,7 +499,7 @@ bootutil_img_validate(struct boot_loader_state *state,
|
494 | 499 | #endif
|
495 | 500 | )
|
496 | 501 | {
|
497 |
| -#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) |
| 502 | +#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES) |
498 | 503 | int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state));
|
499 | 504 | #endif
|
500 | 505 | uint32_t off;
|
@@ -539,6 +544,67 @@ bootutil_img_validate(struct boot_loader_state *state,
|
539 | 544 | #endif
|
540 | 545 |
|
541 | 546 | BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap);
|
| 547 | +#ifdef MCUBOOT_DECOMPRESS_IMAGES |
| 548 | + /* If the image is compressed, the integrity of the image must also be validated */ |
| 549 | + if (MUST_DECOMPRESS(fap, image_index, hdr)) { |
| 550 | + bool found_decompressed_size = false; |
| 551 | + bool found_decompressed_sha = false; |
| 552 | + bool found_decompressed_signature = false; |
| 553 | + |
| 554 | + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); |
| 555 | + if (rc) { |
| 556 | + goto out; |
| 557 | + } |
| 558 | + |
| 559 | + if (it.tlv_end > bootutil_max_image_size(state, fap)) { |
| 560 | + rc = -1; |
| 561 | + goto out; |
| 562 | + } |
| 563 | + |
| 564 | + while (true) { |
| 565 | + uint16_t expected_size = 0; |
| 566 | + bool *found_flag = NULL; |
| 567 | + |
| 568 | + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); |
| 569 | + if (rc < 0) { |
| 570 | + goto out; |
| 571 | + } else if (rc > 0) { |
| 572 | + break; |
| 573 | + } |
| 574 | + |
| 575 | + switch (type) { |
| 576 | + case IMAGE_TLV_DECOMP_SIZE: |
| 577 | + expected_size = sizeof(size_t); |
| 578 | + found_flag = &found_decompressed_size; |
| 579 | + break; |
| 580 | + case IMAGE_TLV_DECOMP_SHA: |
| 581 | + expected_size = IMAGE_HASH_SIZE; |
| 582 | + found_flag = &found_decompressed_sha; |
| 583 | + break; |
| 584 | + case IMAGE_TLV_DECOMP_SIGNATURE: |
| 585 | + found_flag = &found_decompressed_signature; |
| 586 | + break; |
| 587 | + default: |
| 588 | + continue; |
| 589 | + }; |
| 590 | + |
| 591 | + if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { |
| 592 | + rc = -1; |
| 593 | + goto out; |
| 594 | + } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { |
| 595 | + rc = -1; |
| 596 | + goto out; |
| 597 | + } |
| 598 | + |
| 599 | + *found_flag = true; |
| 600 | + } |
| 601 | + |
| 602 | + rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); |
| 603 | + if (rc) { |
| 604 | + goto out; |
| 605 | + } |
| 606 | + } |
| 607 | +#endif |
542 | 608 |
|
543 | 609 | #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
|
544 | 610 | #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
|
@@ -787,6 +853,161 @@ bootutil_img_validate(struct boot_loader_state *state,
|
787 | 853 | skip_security_counter_check:
|
788 | 854 | #endif
|
789 | 855 |
|
| 856 | +#ifdef MCUBOOT_DECOMPRESS_IMAGES |
| 857 | + /* Only after all previous verifications have passed, perform a dry-run of the decompression |
| 858 | + * and ensure the image is valid |
| 859 | + */ |
| 860 | + if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { |
| 861 | + image_hash_valid = 0; |
| 862 | + FIH_SET(valid_signature, FIH_FAILURE); |
| 863 | + |
| 864 | + rc = bootutil_img_hash_decompress(state, hdr, fap, tmp_buf, tmp_buf_sz, |
| 865 | + hash, seed, seed_len); |
| 866 | + if (rc) { |
| 867 | + goto out; |
| 868 | + } |
| 869 | + |
| 870 | + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); |
| 871 | + if (rc) { |
| 872 | + goto out; |
| 873 | + } |
| 874 | + |
| 875 | + if (it.tlv_end > bootutil_max_image_size(state, fap)) { |
| 876 | + rc = -1; |
| 877 | + goto out; |
| 878 | + } |
| 879 | + |
| 880 | + while (true) { |
| 881 | + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); |
| 882 | + if (rc < 0) { |
| 883 | + goto out; |
| 884 | + } else if (rc > 0) { |
| 885 | + break; |
| 886 | + } |
| 887 | + |
| 888 | + if (type == IMAGE_TLV_DECOMP_SHA) { |
| 889 | + /* Verify the image hash. This must always be present. */ |
| 890 | + if (len != sizeof(hash)) { |
| 891 | + rc = -1; |
| 892 | + goto out; |
| 893 | + } |
| 894 | + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); |
| 895 | + if (rc) { |
| 896 | + goto out; |
| 897 | + } |
| 898 | + |
| 899 | + FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); |
| 900 | + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { |
| 901 | + FIH_SET(fih_rc, FIH_FAILURE); |
| 902 | + goto out; |
| 903 | + } |
| 904 | + |
| 905 | + image_hash_valid = 1; |
| 906 | + } |
| 907 | + } |
| 908 | + |
| 909 | + rc = !image_hash_valid; |
| 910 | + if (rc) { |
| 911 | + goto out; |
| 912 | + } |
| 913 | + |
| 914 | +#ifdef EXPECTED_SIG_TLV |
| 915 | +#ifdef EXPECTED_KEY_TLV |
| 916 | + rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); |
| 917 | + if (rc) { |
| 918 | + goto out; |
| 919 | + } |
| 920 | + |
| 921 | + if (it.tlv_end > bootutil_max_image_size(state, fap)) { |
| 922 | + rc = -1; |
| 923 | + goto out; |
| 924 | + } |
| 925 | + |
| 926 | + while (true) { |
| 927 | + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); |
| 928 | + if (rc < 0) { |
| 929 | + goto out; |
| 930 | + } else if (rc > 0) { |
| 931 | + break; |
| 932 | + } |
| 933 | + |
| 934 | + if (type == EXPECTED_KEY_TLV) { |
| 935 | + /* |
| 936 | + * Determine which key we should be checking. |
| 937 | + */ |
| 938 | + if (len > KEY_BUF_SIZE) { |
| 939 | + rc = -1; |
| 940 | + goto out; |
| 941 | + } |
| 942 | +#ifndef MCUBOOT_HW_KEY |
| 943 | + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); |
| 944 | + if (rc) { |
| 945 | + goto out; |
| 946 | + } |
| 947 | + key_id = bootutil_find_key(buf, len); |
| 948 | +#else |
| 949 | + rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); |
| 950 | + if (rc) { |
| 951 | + goto out; |
| 952 | + } |
| 953 | + key_id = bootutil_find_key(image_index, key_buf, len); |
| 954 | +#endif /* !MCUBOOT_HW_KEY */ |
| 955 | + /* |
| 956 | + * The key may not be found, which is acceptable. There |
| 957 | + * can be multiple signatures, each preceded by a key. |
| 958 | + */ |
| 959 | + } |
| 960 | + } |
| 961 | +#endif /* EXPECTED_KEY_TLV */ |
| 962 | + |
| 963 | + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); |
| 964 | + if (rc) { |
| 965 | + goto out; |
| 966 | + } |
| 967 | + |
| 968 | + if (it.tlv_end > bootutil_max_image_size(state, fap)) { |
| 969 | + rc = -1; |
| 970 | + goto out; |
| 971 | + } |
| 972 | + |
| 973 | + while (true) { |
| 974 | + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); |
| 975 | + if (rc < 0) { |
| 976 | + goto out; |
| 977 | + } else if (rc > 0) { |
| 978 | + rc = 0; |
| 979 | + break; |
| 980 | + } |
| 981 | + |
| 982 | + if (type == IMAGE_TLV_DECOMP_SIGNATURE) { |
| 983 | + /* Ignore this signature if it is out of bounds. */ |
| 984 | + if (key_id < 0 || key_id >= bootutil_key_cnt) { |
| 985 | + key_id = -1; |
| 986 | + continue; |
| 987 | + } |
| 988 | + |
| 989 | + if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { |
| 990 | + rc = -1; |
| 991 | + goto out; |
| 992 | + } |
| 993 | + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); |
| 994 | + if (rc) { |
| 995 | + goto out; |
| 996 | + } |
| 997 | + |
| 998 | + FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), |
| 999 | + buf, len, key_id); |
| 1000 | + key_id = -1; |
| 1001 | + } |
| 1002 | + } |
| 1003 | +#endif /* EXPECTED_SIG_TLV */ |
| 1004 | + } |
| 1005 | +#endif |
| 1006 | + |
| 1007 | +#ifdef EXPECTED_SIG_TLV |
| 1008 | + FIH_SET(fih_rc, valid_signature); |
| 1009 | +#endif |
| 1010 | + |
790 | 1011 | out:
|
791 | 1012 | if (rc) {
|
792 | 1013 | FIH_SET(fih_rc, FIH_FAILURE);
|
|
0 commit comments