From 9d32acf540fd4955b7ce2c8d951ae0670676d725 Mon Sep 17 00:00:00 2001 From: Maulik Patel Date: Thu, 10 Jul 2025 18:27:13 +0100 Subject: [PATCH] bootutil: (refactor) split image_validate.c into separate files Move bootutil_find_key(), bootutil_img_hash(), and bootutil_img_security_cnt() into their own source files for cleaner No functional changes have been made. Signed-off-by: Maulik Patel Change-Id: I5d3f4a1327356238e5865dba91b4ec251ffcf1aa --- boot/bootutil/CMakeLists.txt | 3 + boot/bootutil/include/bootutil/image.h | 15 + boot/bootutil/src/bootutil_find_key.c | 132 ++++++++ boot/bootutil/src/bootutil_img_hash.c | 200 ++++++++++++ boot/bootutil/src/bootutil_img_security_cnt.c | 100 ++++++ boot/bootutil/src/image_validate.c | 295 ------------------ boot/espressif/CMakeLists.txt | 3 + boot/zephyr/CMakeLists.txt | 3 + sim/mcuboot-sys/build.rs | 3 + 9 files changed, 459 insertions(+), 295 deletions(-) create mode 100644 boot/bootutil/src/bootutil_find_key.c create mode 100644 boot/bootutil/src/bootutil_img_hash.c create mode 100644 boot/bootutil/src/bootutil_img_security_cnt.c diff --git a/boot/bootutil/CMakeLists.txt b/boot/bootutil/CMakeLists.txt index 3d1b32717e..950a4c1528 100644 --- a/boot/bootutil/CMakeLists.txt +++ b/boot/bootutil/CMakeLists.txt @@ -17,6 +17,9 @@ target_include_directories(bootutil target_sources(bootutil PRIVATE src/boot_record.c + src/bootutil_find_key.c + src/bootutil_img_hash.c + src/bootutil_img_security_cnt.c src/bootutil_misc.c src/bootutil_public.c src/caps.c diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 57be8b1c45..33f2704929 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -235,6 +235,21 @@ int32_t bootutil_get_img_security_cnt(struct boot_loader_state *state, int slot, const struct flash_area *fap, uint32_t *img_security_cnt); +#if !defined(MCUBOOT_HW_KEY) +int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len); +#else +int bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len); +#endif + +int bootutil_img_hash(struct boot_loader_state *state, + struct image_header *hdr, const struct flash_area *fap, + uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *hash_result, + uint8_t *seed, int seed_len +#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) + , uint32_t start_offset +#endif +); + #ifdef __cplusplus } #endif diff --git a/boot/bootutil/src/bootutil_find_key.c b/boot/bootutil/src/bootutil_find_key.c new file mode 100644 index 0000000000..c80b8d8ba2 --- /dev/null +++ b/boot/bootutil/src/bootutil_find_key.c @@ -0,0 +1,132 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2017-2019 Linaro LTD + * Copyright (c) 2016-2019 JUUL Labs + * Copyright (c) 2019-2025 Arm Limited + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * Original license: + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +#include "bootutil/crypto/sha.h" +#include "bootutil/fault_injection_hardening.h" +#include "bootutil/image.h" +#include "bootutil/sign_key.h" +#include "bootutil_priv.h" +#include "mcuboot_config/mcuboot_config.h" +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +#if defined(MCUBOOT_SIGN_RSA) || \ + defined(MCUBOOT_SIGN_EC256) || \ + defined(MCUBOOT_SIGN_EC384) || \ + defined(MCUBOOT_SIGN_EC) || \ + defined(MCUBOOT_SIGN_ED25519) +#define EXPECTED_SIG_TLV +#else + /* no signing, sha256 digest only */ +#endif + +#ifdef EXPECTED_SIG_TLV +#if !defined(MCUBOOT_BUILTIN_KEY) +#if !defined(MCUBOOT_HW_KEY) +/* The key TLV contains the hash of the public key. */ +# define EXPECTED_KEY_TLV IMAGE_TLV_KEYHASH +# define KEY_BUF_SIZE IMAGE_HASH_SIZE +#else +/* The key TLV contains the whole public key. + * Add a few extra bytes to the key buffer size for encoding and + * for public exponent. + */ +# define EXPECTED_KEY_TLV IMAGE_TLV_PUBKEY +# define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) +#endif /* !MCUBOOT_HW_KEY */ + +#if !defined(MCUBOOT_HW_KEY) +int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) +{ + bootutil_sha_context sha_ctx; + int i; + const struct bootutil_key *key; + uint8_t hash[IMAGE_HASH_SIZE]; + + BOOT_LOG_DBG("bootutil_find_key"); + + if (keyhash_len > IMAGE_HASH_SIZE) { + return -1; + } + + for (i = 0; i < bootutil_key_cnt; i++) { + key = &bootutil_keys[i]; + bootutil_sha_init(&sha_ctx); + bootutil_sha_update(&sha_ctx, key->key, *key->len); + bootutil_sha_finish(&sha_ctx, hash); + bootutil_sha_drop(&sha_ctx); + if (!memcmp(hash, keyhash, keyhash_len)) { + return i; + } + } + return -1; +} +#else /* !MCUBOOT_HW_KEY */ +extern unsigned int pub_key_len; +int bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) +{ + bootutil_sha_context sha_ctx; + uint8_t hash[IMAGE_HASH_SIZE]; + uint8_t key_hash[IMAGE_HASH_SIZE]; + size_t key_hash_size = sizeof(key_hash); + int rc; + FIH_DECLARE(fih_rc, FIH_FAILURE); + + BOOT_LOG_DBG("bootutil_find_key: image_index %d", image_index); + + bootutil_sha_init(&sha_ctx); + bootutil_sha_update(&sha_ctx, key, key_len); + bootutil_sha_finish(&sha_ctx, hash); + bootutil_sha_drop(&sha_ctx); + + rc = boot_retrieve_public_key_hash(image_index, key_hash, &key_hash_size); + if (rc) { + return -1; + } + + /* Adding hardening to avoid this potential attack: + * - Image is signed with an arbitrary key and the corresponding public + * key is added as a TLV field. + * - During public key validation (comparing against key-hash read from + * HW) a fault is injected to accept the public key as valid one. + */ + FIH_CALL(boot_fih_memequal, fih_rc, hash, key_hash, key_hash_size); + if (FIH_EQ(fih_rc, FIH_SUCCESS)) { + bootutil_keys[0].key = key; + pub_key_len = key_len; + return 0; + } + + return -1; +} +#endif /* !MCUBOOT_HW_KEY */ +#endif /* !MCUBOOT_BUILTIN_KEY */ +#endif /* EXPECTED_SIG_TLV */ diff --git a/boot/bootutil/src/bootutil_img_hash.c b/boot/bootutil/src/bootutil_img_hash.c new file mode 100644 index 0000000000..354001d915 --- /dev/null +++ b/boot/bootutil/src/bootutil_img_hash.c @@ -0,0 +1,200 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2017-2019 Linaro LTD + * Copyright (c) 2016-2019 JUUL Labs + * Copyright (c) 2019-2025 Arm Limited + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * Original license: + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +#include "bootutil/crypto/sha.h" +#include "bootutil/fault_injection_hardening.h" +#include "bootutil/image.h" +#include "bootutil_priv.h" +#include "mcuboot_config/mcuboot_config.h" +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +#ifndef MCUBOOT_SIGN_PURE +/* + * Compute SHA hash over the image. + * (SHA384 if ECDSA-P384 is being used, + * SHA256 otherwise). + */ +int +bootutil_img_hash(struct boot_loader_state *state, + struct image_header *hdr, const struct flash_area *fap, + uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *hash_result, + uint8_t *seed, int seed_len + ) +{ + bootutil_sha_context sha_ctx; + uint32_t size; + uint16_t hdr_size; + uint32_t blk_off; + uint32_t tlv_off; +#if !defined(MCUBOOT_HASH_STORAGE_DIRECTLY) + int rc; + uint32_t off; + uint32_t blk_sz; +#endif +#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY + uintptr_t base = 0; + int fa_ret; +#endif +#if defined(MCUBOOT_ENC_IMAGES) + struct enc_key_data *enc_state; + int image_index; +#endif +#if defined(MCUBOOT_SWAP_USING_OFFSET) + uint32_t sector_off = 0; +#endif + +#if (BOOT_IMAGE_NUMBER == 1) || !defined(MCUBOOT_ENC_IMAGES) || \ + defined(MCUBOOT_RAM_LOAD) + (void)state; + (void)hdr_size; + (void)blk_off; + (void)tlv_off; +#ifdef MCUBOOT_RAM_LOAD + (void)blk_sz; + (void)off; + (void)rc; + (void)fap; + (void)tmp_buf; + (void)tmp_buf_sz; +#endif +#endif + BOOT_LOG_DBG("bootutil_img_hash"); + +#ifdef MCUBOOT_ENC_IMAGES + if (state == NULL) { + enc_state = NULL; + image_index = 0; + } else { + enc_state = BOOT_CURR_ENC(state); + image_index = BOOT_CURR_IMG(state); + } + + /* Encrypted images only exist in the secondary slot */ + if (MUST_DECRYPT(fap, image_index, hdr) && + !boot_enc_valid(enc_state, 1)) { + BOOT_LOG_DBG("bootutil_img_hash: error encrypted image found in primary slot"); + return -1; + } +#endif + +#if defined(MCUBOOT_SWAP_USING_OFFSET) + /* For swap using offset mode, the image starts in the second sector of the upgrade slot, so + * apply the offset when this is needed + */ + sector_off = boot_get_state_secondary_offset(state, fap); +#endif + + bootutil_sha_init(&sha_ctx); + + /* in some cases (split image) the hash is seeded with data from + * the loader image */ + if (seed && (seed_len > 0)) { + bootutil_sha_update(&sha_ctx, seed, seed_len); + } + + /* Hash is computed over image header and image itself. */ + size = hdr_size = hdr->ih_hdr_size; + size += hdr->ih_img_size; + tlv_off = size; + + /* If protected TLVs are present they are also hashed. */ + size += hdr->ih_protect_tlv_size; + +#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY + /* No chunk loading, storage is mapped to address space and can + * be directly given to hashing function. + */ + fa_ret = flash_device_base(flash_area_get_device_id(fap), &base); + if (fa_ret != 0) { + base = 0; + } + + bootutil_sha_update(&sha_ctx, (void *)(base + flash_area_get_off(fap)), size); +#else /* MCUBOOT_HASH_STORAGE_DIRECTLY */ +#ifdef MCUBOOT_RAM_LOAD + bootutil_sha_update(&sha_ctx, + (void*)(IMAGE_RAM_BASE + hdr->ih_load_addr), + size); +#else + for (off = 0; off < size; off += blk_sz) { + blk_sz = size - off; + if (blk_sz > tmp_buf_sz) { + blk_sz = tmp_buf_sz; + } +#ifdef MCUBOOT_ENC_IMAGES + /* The only data that is encrypted in an image is the payload; + * both header and TLVs (when protected) are not. + */ + if ((off < hdr_size) && ((off + blk_sz) > hdr_size)) { + /* read only the header */ + blk_sz = hdr_size - off; + } + if ((off < tlv_off) && ((off + blk_sz) > tlv_off)) { + /* read only up to the end of the image payload */ + blk_sz = tlv_off - off; + } +#endif +#if defined(MCUBOOT_SWAP_USING_OFFSET) + rc = flash_area_read(fap, off + sector_off, tmp_buf, blk_sz); +#else + rc = flash_area_read(fap, off, tmp_buf, blk_sz); +#endif + if (rc) { + bootutil_sha_drop(&sha_ctx); + BOOT_LOG_DBG("bootutil_img_validate Error %d reading data chunk %p %u %u", + rc, fap, off, blk_sz); + return rc; + } +#ifdef MCUBOOT_ENC_IMAGES + if (MUST_DECRYPT(fap, image_index, hdr)) { + /* Only payload is encrypted (area between header and TLVs) */ + int slot = flash_area_id_to_multi_image_slot(image_index, + flash_area_get_id(fap)); + + if (off >= hdr_size && off < tlv_off) { + blk_off = (off - hdr_size) & 0xf; + boot_enc_decrypt(enc_state, slot, off - hdr_size, + blk_sz, blk_off, tmp_buf); + } + } +#endif + bootutil_sha_update(&sha_ctx, tmp_buf, blk_sz); + } +#endif /* MCUBOOT_RAM_LOAD */ +#endif /* MCUBOOT_HASH_STORAGE_DIRECTLY */ + bootutil_sha_finish(&sha_ctx, hash_result); + bootutil_sha_drop(&sha_ctx); + + return 0; +} +#endif /* !MCUBOOT_SIGN_PURE */ diff --git a/boot/bootutil/src/bootutil_img_security_cnt.c b/boot/bootutil/src/bootutil_img_security_cnt.c new file mode 100644 index 0000000000..c141c56d0b --- /dev/null +++ b/boot/bootutil/src/bootutil_img_security_cnt.c @@ -0,0 +1,100 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2017-2019 Linaro LTD + * Copyright (c) 2016-2019 JUUL Labs + * Copyright (c) 2019-2025 Arm Limited + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * Original license: + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +#include "bootutil/image.h" +#include "bootutil/security_cnt.h" +#include "bootutil_priv.h" + +/** + * Reads the value of an image's security counter. + * + * @param state Pointer to the boot state object. + * @param slot Slot of the current image to get the security counter of. + * @param fap Pointer to a description structure of the image's + * flash area. + * @param security_cnt Pointer to store the security counter value. + * + * @return 0 on success; nonzero on failure. + */ +int32_t +bootutil_get_img_security_cnt(struct boot_loader_state *state, int slot, + const struct flash_area *fap, + uint32_t *img_security_cnt) +{ + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + if ((state == NULL) || + (boot_img_hdr(state, slot) == NULL) || + (fap == NULL) || + (img_security_cnt == NULL)) { + /* Invalid parameter. */ + return BOOT_EBADARGS; + } + + /* The security counter TLV is in the protected part of the TLV area. */ + if (boot_img_hdr(state, slot)->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + +#if defined(MCUBOOT_SWAP_USING_OFFSET) + it.start_off = boot_get_state_secondary_offset(state, fap); +#endif + + rc = bootutil_tlv_iter_begin(&it, boot_img_hdr(state, slot), fap, IMAGE_TLV_SEC_CNT, true); + if (rc) { + return rc; + } + + /* Traverse through the protected TLV area to find + * the security counter TLV. + */ + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + if (rc != 0) { + /* Security counter TLV has not been found. */ + return -1; + } + + if (len != sizeof(*img_security_cnt)) { + /* Security counter is not valid. */ + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(boot_img_hdr(state, slot), fap, off, img_security_cnt, len); + if (rc != 0) { + return BOOT_EFLASH; + } + + return 0; +} diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index eb5ce16ed7..d971e7f896 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -61,167 +61,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil_priv.h" -#ifndef MCUBOOT_SIGN_PURE -/* - * Compute SHA hash over the image. - * (SHA384 if ECDSA-P384 is being used, - * SHA256 otherwise). - */ -static int -bootutil_img_hash(struct boot_loader_state *state, - struct image_header *hdr, const struct flash_area *fap, - uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *hash_result, - uint8_t *seed, int seed_len - ) -{ - bootutil_sha_context sha_ctx; - uint32_t size; - uint16_t hdr_size; - uint32_t blk_off; - uint32_t tlv_off; -#if !defined(MCUBOOT_HASH_STORAGE_DIRECTLY) - int rc; - uint32_t off; - uint32_t blk_sz; -#endif -#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY - uintptr_t base = 0; - int fa_ret; -#endif -#if defined(MCUBOOT_ENC_IMAGES) - struct enc_key_data *enc_state; - int image_index; -#endif -#if defined(MCUBOOT_SWAP_USING_OFFSET) - uint32_t sector_off = 0; -#endif - -#if (BOOT_IMAGE_NUMBER == 1) || !defined(MCUBOOT_ENC_IMAGES) || \ - defined(MCUBOOT_RAM_LOAD) - (void)state; - (void)hdr_size; - (void)blk_off; - (void)tlv_off; -#ifdef MCUBOOT_RAM_LOAD - (void)blk_sz; - (void)off; - (void)rc; - (void)fap; - (void)tmp_buf; - (void)tmp_buf_sz; -#endif -#endif - BOOT_LOG_DBG("bootutil_img_hash"); - -#ifdef MCUBOOT_ENC_IMAGES - if (state == NULL) { - enc_state = NULL; - image_index = 0; - } else { - enc_state = BOOT_CURR_ENC(state); - image_index = BOOT_CURR_IMG(state); - } - - /* Encrypted images only exist in the secondary slot */ - if (MUST_DECRYPT(fap, image_index, hdr) && - !boot_enc_valid(enc_state, 1)) { - BOOT_LOG_DBG("bootutil_img_hash: error encrypted image found in primary slot"); - return -1; - } -#endif - -#if defined(MCUBOOT_SWAP_USING_OFFSET) - /* For swap using offset mode, the image starts in the second sector of the upgrade slot, so - * apply the offset when this is needed - */ - sector_off = boot_get_state_secondary_offset(state, fap); -#endif - - bootutil_sha_init(&sha_ctx); - - /* in some cases (split image) the hash is seeded with data from - * the loader image */ - if (seed && (seed_len > 0)) { - bootutil_sha_update(&sha_ctx, seed, seed_len); - } - - /* Hash is computed over image header and image itself. */ - size = hdr_size = hdr->ih_hdr_size; - size += hdr->ih_img_size; - tlv_off = size; - - /* If protected TLVs are present they are also hashed. */ - size += hdr->ih_protect_tlv_size; - -#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY - /* No chunk loading, storage is mapped to address space and can - * be directly given to hashing function. - */ - fa_ret = flash_device_base(flash_area_get_device_id(fap), &base); - if (fa_ret != 0) { - base = 0; - } - - bootutil_sha_update(&sha_ctx, (void *)(base + flash_area_get_off(fap)), size); -#else /* MCUBOOT_HASH_STORAGE_DIRECTLY */ -#ifdef MCUBOOT_RAM_LOAD - bootutil_sha_update(&sha_ctx, - (void*)(IMAGE_RAM_BASE + hdr->ih_load_addr), - size); -#else - for (off = 0; off < size; off += blk_sz) { - blk_sz = size - off; - if (blk_sz > tmp_buf_sz) { - blk_sz = tmp_buf_sz; - } -#ifdef MCUBOOT_ENC_IMAGES - /* The only data that is encrypted in an image is the payload; - * both header and TLVs (when protected) are not. - */ - if ((off < hdr_size) && ((off + blk_sz) > hdr_size)) { - /* read only the header */ - blk_sz = hdr_size - off; - } - if ((off < tlv_off) && ((off + blk_sz) > tlv_off)) { - /* read only up to the end of the image payload */ - blk_sz = tlv_off - off; - } -#endif -#if defined(MCUBOOT_SWAP_USING_OFFSET) - rc = flash_area_read(fap, off + sector_off, tmp_buf, blk_sz); -#else - rc = flash_area_read(fap, off, tmp_buf, blk_sz); -#endif - if (rc) { - bootutil_sha_drop(&sha_ctx); - BOOT_LOG_DBG("bootutil_img_validate Error %d reading data chunk %p %u %u", - rc, fap, off, blk_sz); - return rc; - } -#ifdef MCUBOOT_ENC_IMAGES - if (MUST_DECRYPT(fap, image_index, hdr)) { - /* Only payload is encrypted (area between header and TLVs) */ - int slot = flash_area_id_to_multi_image_slot(image_index, - flash_area_get_id(fap)); - - if (off >= hdr_size && off < tlv_off) { - blk_off = (off - hdr_size) & 0xf; - boot_enc_decrypt(enc_state, slot, off - hdr_size, - blk_sz, blk_off, tmp_buf); - } - } -#endif - bootutil_sha_update(&sha_ctx, tmp_buf, blk_sz); - } -#endif /* MCUBOOT_RAM_LOAD */ -#endif /* MCUBOOT_HASH_STORAGE_DIRECTLY */ - bootutil_sha_finish(&sha_ctx, hash_result); - bootutil_sha_drop(&sha_ctx); - - return 0; -} -#endif - /* * Currently, we only support being able to verify one type of * signature, because there is a single verification function that we @@ -279,143 +118,9 @@ bootutil_img_hash(struct boot_loader_state *state, # define EXPECTED_KEY_TLV IMAGE_TLV_PUBKEY # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ - -#if !defined(MCUBOOT_HW_KEY) -static int -bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) -{ - bootutil_sha_context sha_ctx; - int i; - const struct bootutil_key *key; - uint8_t hash[IMAGE_HASH_SIZE]; - - BOOT_LOG_DBG("bootutil_find_key"); - - if (keyhash_len > IMAGE_HASH_SIZE) { - return -1; - } - - for (i = 0; i < bootutil_key_cnt; i++) { - key = &bootutil_keys[i]; - bootutil_sha_init(&sha_ctx); - bootutil_sha_update(&sha_ctx, key->key, *key->len); - bootutil_sha_finish(&sha_ctx, hash); - bootutil_sha_drop(&sha_ctx); - if (!memcmp(hash, keyhash, keyhash_len)) { - return i; - } - } - return -1; -} -#else /* !MCUBOOT_HW_KEY */ -extern unsigned int pub_key_len; -static int -bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) -{ - bootutil_sha_context sha_ctx; - uint8_t hash[IMAGE_HASH_SIZE]; - uint8_t key_hash[IMAGE_HASH_SIZE]; - size_t key_hash_size = sizeof(key_hash); - int rc; - FIH_DECLARE(fih_rc, FIH_FAILURE); - - BOOT_LOG_DBG("bootutil_find_key: image_index %d", image_index); - - bootutil_sha_init(&sha_ctx); - bootutil_sha_update(&sha_ctx, key, key_len); - bootutil_sha_finish(&sha_ctx, hash); - bootutil_sha_drop(&sha_ctx); - - rc = boot_retrieve_public_key_hash(image_index, key_hash, &key_hash_size); - if (rc) { - return -1; - } - - /* Adding hardening to avoid this potential attack: - * - Image is signed with an arbitrary key and the corresponding public - * key is added as a TLV field. - * - During public key validation (comparing against key-hash read from - * HW) a fault is injected to accept the public key as valid one. - */ - FIH_CALL(boot_fih_memequal, fih_rc, hash, key_hash, key_hash_size); - if (FIH_EQ(fih_rc, FIH_SUCCESS)) { - bootutil_keys[0].key = key; - pub_key_len = key_len; - return 0; - } - - return -1; -} -#endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ #endif /* EXPECTED_SIG_TLV */ -/** - * Reads the value of an image's security counter. - * - * @param state Pointer to the boot state object. - * @param slot Slot of the current image to get the security counter of. - * @param fap Pointer to a description structure of the image's - * flash area. - * @param security_cnt Pointer to store the security counter value. - * - * @return 0 on success; nonzero on failure. - */ -int32_t -bootutil_get_img_security_cnt(struct boot_loader_state *state, int slot, - const struct flash_area *fap, - uint32_t *img_security_cnt) -{ - struct image_tlv_iter it; - uint32_t off; - uint16_t len; - int32_t rc; - - if ((state == NULL) || - (boot_img_hdr(state, slot) == NULL) || - (fap == NULL) || - (img_security_cnt == NULL)) { - /* Invalid parameter. */ - return BOOT_EBADARGS; - } - - /* The security counter TLV is in the protected part of the TLV area. */ - if (boot_img_hdr(state, slot)->ih_protect_tlv_size == 0) { - return BOOT_EBADIMAGE; - } - -#if defined(MCUBOOT_SWAP_USING_OFFSET) - it.start_off = boot_get_state_secondary_offset(state, fap); -#endif - - rc = bootutil_tlv_iter_begin(&it, boot_img_hdr(state, slot), fap, IMAGE_TLV_SEC_CNT, true); - if (rc) { - return rc; - } - - /* Traverse through the protected TLV area to find - * the security counter TLV. - */ - - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - if (rc != 0) { - /* Security counter TLV has not been found. */ - return -1; - } - - if (len != sizeof(*img_security_cnt)) { - /* Security counter is not valid. */ - return BOOT_EBADIMAGE; - } - - rc = LOAD_IMAGE_DATA(boot_img_hdr(state, slot), fap, off, img_security_cnt, len); - if (rc != 0) { - return BOOT_EFLASH; - } - - return 0; -} - #if defined(MCUBOOT_SIGN_PURE) /* Returns: * 0 -- found diff --git a/boot/espressif/CMakeLists.txt b/boot/espressif/CMakeLists.txt index 05358839c1..0fa2759eab 100644 --- a/boot/espressif/CMakeLists.txt +++ b/boot/espressif/CMakeLists.txt @@ -236,6 +236,9 @@ endif() set(bootutil_srcs ${BOOTUTIL_DIR}/src/boot_record.c + ${BOOTUTIL_DIR}/src/bootutil_find_key.c + ${BOOTUTIL_DIR}/src/bootutil_img_hash.c + ${BOOTUTIL_DIR}/src/bootutil_img_security_cnt.c ${BOOTUTIL_DIR}/src/bootutil_misc.c ${BOOTUTIL_DIR}/src/bootutil_public.c ${BOOTUTIL_DIR}/src/caps.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index c601afa67a..d969756c81 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -106,6 +106,9 @@ endif() zephyr_library_include_directories(${BOOT_DIR}/bootutil/include) zephyr_library_sources( ${BOOT_DIR}/bootutil/src/image_validate.c + ${BOOT_DIR}/bootutil/src/bootutil_find_key.c + ${BOOT_DIR}/bootutil/src/bootutil_img_hash.c + ${BOOT_DIR}/bootutil/src/bootutil_img_security_cnt.c ${BOOT_DIR}/bootutil/src/tlv.c ${BOOT_DIR}/bootutil/src/encrypted.c ${BOOT_DIR}/bootutil/src/image_rsa.c diff --git a/sim/mcuboot-sys/build.rs b/sim/mcuboot-sys/build.rs index e74a086d00..1c897818db 100644 --- a/sim/mcuboot-sys/build.rs +++ b/sim/mcuboot-sys/build.rs @@ -449,6 +449,9 @@ fn main() { } conf.file("../../boot/bootutil/src/image_validate.c"); + conf.file("../../boot/bootutil/src/bootutil_find_key.c"); + conf.file("../../boot/bootutil/src/bootutil_img_hash.c"); + conf.file("../../boot/bootutil/src/bootutil_img_security_cnt.c"); if sig_rsa || sig_rsa3072 { conf.file("../../boot/bootutil/src/image_rsa.c"); } else if sig_ecdsa || sig_ecdsa_mbedtls || sig_ecdsa_psa {