Skip to content

Commit 6b183cc

Browse files
committed
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 <maulik.patel@arm.com> Change-Id: I5d3f4a1327356238e5865dba91b4ec251ffcf1aa
1 parent 268968f commit 6b183cc

File tree

9 files changed

+472
-309
lines changed

9 files changed

+472
-309
lines changed

boot/bootutil/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ target_include_directories(bootutil
1717
target_sources(bootutil
1818
PRIVATE
1919
src/boot_record.c
20+
src/bootutil_find_key.c
21+
src/bootutil_img_hash.c
22+
src/bootutil_img_security_cnt.c
2023
src/bootutil_misc.c
2124
src/bootutil_public.c
2225
src/caps.c

boot/bootutil/include/bootutil/image.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,19 @@ int32_t bootutil_get_img_security_cnt(struct boot_loader_state *state, int slot,
243243
const struct flash_area *fap,
244244
uint32_t *img_security_cnt);
245245

246+
#if !defined(MCUBOOT_HW_KEY)
247+
int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len);
248+
#else
249+
int bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len);
250+
#endif
251+
252+
int
253+
bootutil_img_hash(struct boot_loader_state *state,
254+
struct image_header *hdr, const struct flash_area *fap,
255+
uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *hash_result,
256+
uint8_t *seed, int seed_len
257+
);
258+
246259
#ifdef __cplusplus
247260
}
248261
#endif

boot/bootutil/src/bootutil_find_key.c

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2017-2019 Linaro LTD
5+
* Copyright (c) 2016-2019 JUUL Labs
6+
* Copyright (c) 2019-2025 Arm Limited
7+
* Copyright (c) 2025 Nordic Semiconductor ASA
8+
*
9+
* Original license:
10+
*
11+
* Licensed to the Apache Software Foundation (ASF) under one
12+
* or more contributor license agreements. See the NOTICE file
13+
* distributed with this work for additional information
14+
* regarding copyright ownership. The ASF licenses this file
15+
* to you under the Apache License, Version 2.0 (the
16+
* "License"); you may not use this file except in compliance
17+
* with the License. You may obtain a copy of the License at
18+
*
19+
* http://www.apache.org/licenses/LICENSE-2.0
20+
*
21+
* Unless required by applicable law or agreed to in writing,
22+
* software distributed under the License is distributed on an
23+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
24+
* KIND, either express or implied. See the License for the
25+
* specific language governing permissions and limitations
26+
* under the License.
27+
*/
28+
29+
#include <stdint.h>
30+
31+
#include "bootutil/crypto/sha.h"
32+
#include "bootutil/fault_injection_hardening.h"
33+
#include "bootutil/image.h"
34+
#include "bootutil/sign_key.h"
35+
#include "bootutil_priv.h"
36+
#include "mcuboot_config/mcuboot_config.h"
37+
#include "bootutil/bootutil_log.h"
38+
39+
BOOT_LOG_MODULE_DECLARE(mcuboot);
40+
41+
#if defined(MCUBOOT_SIGN_RSA) || \
42+
defined(MCUBOOT_SIGN_EC256) || \
43+
defined(MCUBOOT_SIGN_EC384) || \
44+
defined(MCUBOOT_SIGN_EC) || \
45+
defined(MCUBOOT_SIGN_ED25519)
46+
#define EXPECTED_SIG_TLV
47+
#else
48+
/* no signing, sha256 digest only */
49+
#endif
50+
51+
#ifdef EXPECTED_SIG_TLV
52+
#if !defined(MCUBOOT_BYPASS_KEY_MATCH)
53+
/* Find functions are only needed when key is checked first */
54+
#if !defined(MCUBOOT_BUILTIN_KEY)
55+
#if !defined(MCUBOOT_HW_KEY)
56+
/* The key TLV contains the hash of the public key. */
57+
# define EXPECTED_KEY_TLV IMAGE_TLV_KEYHASH
58+
# define KEY_BUF_SIZE IMAGE_HASH_SIZE
59+
#else
60+
/* The key TLV contains the whole public key.
61+
* Add a few extra bytes to the key buffer size for encoding and
62+
* for public exponent.
63+
*/
64+
# define EXPECTED_KEY_TLV IMAGE_TLV_PUBKEY
65+
# define KEY_BUF_SIZE (SIG_BUF_SIZE + 24)
66+
#endif /* !MCUBOOT_HW_KEY */
67+
68+
#if !defined(MCUBOOT_HW_KEY)
69+
int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len)
70+
{
71+
bootutil_sha_context sha_ctx;
72+
int i;
73+
const struct bootutil_key *key;
74+
uint8_t hash[IMAGE_HASH_SIZE];
75+
76+
BOOT_LOG_DBG("bootutil_find_key");
77+
78+
if (keyhash_len > IMAGE_HASH_SIZE) {
79+
return -1;
80+
}
81+
82+
for (i = 0; i < bootutil_key_cnt; i++) {
83+
key = &bootutil_keys[i];
84+
bootutil_sha_init(&sha_ctx);
85+
bootutil_sha_update(&sha_ctx, key->key, *key->len);
86+
bootutil_sha_finish(&sha_ctx, hash);
87+
bootutil_sha_drop(&sha_ctx);
88+
if (!memcmp(hash, keyhash, keyhash_len)) {
89+
return i;
90+
}
91+
}
92+
return -1;
93+
}
94+
#else /* !MCUBOOT_HW_KEY */
95+
extern unsigned int pub_key_len;
96+
int bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len)
97+
{
98+
bootutil_sha_context sha_ctx;
99+
uint8_t hash[IMAGE_HASH_SIZE];
100+
uint8_t key_hash[IMAGE_HASH_SIZE];
101+
size_t key_hash_size = sizeof(key_hash);
102+
int rc;
103+
FIH_DECLARE(fih_rc, FIH_FAILURE);
104+
105+
BOOT_LOG_DBG("bootutil_find_key: image_index %d", image_index);
106+
107+
bootutil_sha_init(&sha_ctx);
108+
bootutil_sha_update(&sha_ctx, key, key_len);
109+
bootutil_sha_finish(&sha_ctx, hash);
110+
bootutil_sha_drop(&sha_ctx);
111+
112+
rc = boot_retrieve_public_key_hash(image_index, key_hash, &key_hash_size);
113+
if (rc) {
114+
return -1;
115+
}
116+
117+
/* Adding hardening to avoid this potential attack:
118+
* - Image is signed with an arbitrary key and the corresponding public
119+
* key is added as a TLV field.
120+
* - During public key validation (comparing against key-hash read from
121+
* HW) a fault is injected to accept the public key as valid one.
122+
*/
123+
FIH_CALL(boot_fih_memequal, fih_rc, hash, key_hash, key_hash_size);
124+
if (FIH_EQ(fih_rc, FIH_SUCCESS)) {
125+
bootutil_keys[0].key = key;
126+
pub_key_len = key_len;
127+
return 0;
128+
}
129+
130+
return -1;
131+
}
132+
#endif /* !MCUBOOT_HW_KEY */
133+
#endif /* !MCUBOOT_BUILTIN_KEY */
134+
135+
#else /* !MCUBOOT_BYPASS_KEY_MATCH */
136+
static inline int
137+
bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len)
138+
{
139+
(void)image_index;
140+
(void)key;
141+
(void)key_len;
142+
143+
/* There is only one key, so it always matches */
144+
return 0;
145+
}
146+
#endif /* !MCUBOOT_BYPASS_KEY_MATCH */
147+
#endif /* EXPECTED_SIG_TLV */

boot/bootutil/src/bootutil_img_hash.c

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2017-2019 Linaro LTD
5+
* Copyright (c) 2016-2019 JUUL Labs
6+
* Copyright (c) 2019-2025 Arm Limited
7+
* Copyright (c) 2025 Nordic Semiconductor ASA
8+
*
9+
* Original license:
10+
*
11+
* Licensed to the Apache Software Foundation (ASF) under one
12+
* or more contributor license agreements. See the NOTICE file
13+
* distributed with this work for additional information
14+
* regarding copyright ownership. The ASF licenses this file
15+
* to you under the Apache License, Version 2.0 (the
16+
* "License"); you may not use this file except in compliance
17+
* with the License. You may obtain a copy of the License at
18+
*
19+
* http://www.apache.org/licenses/LICENSE-2.0
20+
*
21+
* Unless required by applicable law or agreed to in writing,
22+
* software distributed under the License is distributed on an
23+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
24+
* KIND, either express or implied. See the License for the
25+
* specific language governing permissions and limitations
26+
* under the License.
27+
*/
28+
29+
#include <stdint.h>
30+
#include <flash_map_backend/flash_map_backend.h>
31+
32+
#include "bootutil/crypto/sha.h"
33+
#include "bootutil/fault_injection_hardening.h"
34+
#include "bootutil/image.h"
35+
#include "bootutil_priv.h"
36+
#include "mcuboot_config/mcuboot_config.h"
37+
#include "bootutil/bootutil_log.h"
38+
39+
BOOT_LOG_MODULE_DECLARE(mcuboot);
40+
41+
#ifndef MCUBOOT_SIGN_PURE
42+
/*
43+
* Compute SHA hash over the image.
44+
* (SHA384 if ECDSA-P384 is being used,
45+
* SHA256 otherwise).
46+
*/
47+
int
48+
bootutil_img_hash(struct boot_loader_state *state,
49+
struct image_header *hdr, const struct flash_area *fap,
50+
uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *hash_result,
51+
uint8_t *seed, int seed_len
52+
)
53+
{
54+
bootutil_sha_context sha_ctx;
55+
uint32_t size;
56+
uint16_t hdr_size;
57+
uint32_t blk_off;
58+
uint32_t tlv_off;
59+
#if !defined(MCUBOOT_HASH_STORAGE_DIRECTLY)
60+
int rc;
61+
uint32_t off;
62+
uint32_t blk_sz;
63+
#endif
64+
#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY
65+
uintptr_t base = 0;
66+
int fa_ret;
67+
#endif
68+
#if defined(MCUBOOT_ENC_IMAGES)
69+
struct enc_key_data *enc_state;
70+
int image_index;
71+
#endif
72+
#if defined(MCUBOOT_SWAP_USING_OFFSET)
73+
uint32_t sector_off = 0;
74+
#endif
75+
76+
#if (BOOT_IMAGE_NUMBER == 1) || !defined(MCUBOOT_ENC_IMAGES) || \
77+
defined(MCUBOOT_RAM_LOAD)
78+
(void)state;
79+
(void)hdr_size;
80+
(void)blk_off;
81+
(void)tlv_off;
82+
#ifdef MCUBOOT_RAM_LOAD
83+
(void)blk_sz;
84+
(void)off;
85+
(void)rc;
86+
(void)fap;
87+
(void)tmp_buf;
88+
(void)tmp_buf_sz;
89+
#endif
90+
#endif
91+
BOOT_LOG_DBG("bootutil_img_hash");
92+
93+
#ifdef MCUBOOT_ENC_IMAGES
94+
if (state == NULL) {
95+
enc_state = NULL;
96+
image_index = 0;
97+
} else {
98+
enc_state = BOOT_CURR_ENC(state);
99+
image_index = BOOT_CURR_IMG(state);
100+
}
101+
102+
/* Encrypted images only exist in the secondary slot */
103+
if (MUST_DECRYPT(fap, image_index, hdr) &&
104+
!boot_enc_valid(enc_state, 1)) {
105+
BOOT_LOG_DBG("bootutil_img_hash: error encrypted image found in primary slot");
106+
return -1;
107+
}
108+
#endif
109+
110+
#if defined(MCUBOOT_SWAP_USING_OFFSET)
111+
/* For swap using offset mode, the image starts in the second sector of the upgrade slot, so
112+
* apply the offset when this is needed
113+
*/
114+
sector_off = boot_get_state_secondary_offset(state, fap);
115+
#endif
116+
117+
bootutil_sha_init(&sha_ctx);
118+
119+
/* in some cases (split image) the hash is seeded with data from
120+
* the loader image */
121+
if (seed && (seed_len > 0)) {
122+
bootutil_sha_update(&sha_ctx, seed, seed_len);
123+
}
124+
125+
/* Hash is computed over image header and image itself. */
126+
size = hdr_size = hdr->ih_hdr_size;
127+
size += hdr->ih_img_size;
128+
tlv_off = size;
129+
130+
/* If protected TLVs are present they are also hashed. */
131+
size += hdr->ih_protect_tlv_size;
132+
133+
#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY
134+
/* No chunk loading, storage is mapped to address space and can
135+
* be directly given to hashing function.
136+
*/
137+
fa_ret = flash_device_base(flash_area_get_device_id(fap), &base);
138+
if (fa_ret != 0) {
139+
base = 0;
140+
}
141+
142+
bootutil_sha_update(&sha_ctx, (void *)(base + flash_area_get_off(fap)), size);
143+
#else /* MCUBOOT_HASH_STORAGE_DIRECTLY */
144+
#ifdef MCUBOOT_RAM_LOAD
145+
bootutil_sha_update(&sha_ctx,
146+
(void*)(IMAGE_RAM_BASE + hdr->ih_load_addr),
147+
size);
148+
#else
149+
for (off = 0; off < size; off += blk_sz) {
150+
blk_sz = size - off;
151+
if (blk_sz > tmp_buf_sz) {
152+
blk_sz = tmp_buf_sz;
153+
}
154+
#ifdef MCUBOOT_ENC_IMAGES
155+
/* The only data that is encrypted in an image is the payload;
156+
* both header and TLVs (when protected) are not.
157+
*/
158+
if ((off < hdr_size) && ((off + blk_sz) > hdr_size)) {
159+
/* read only the header */
160+
blk_sz = hdr_size - off;
161+
}
162+
if ((off < tlv_off) && ((off + blk_sz) > tlv_off)) {
163+
/* read only up to the end of the image payload */
164+
blk_sz = tlv_off - off;
165+
}
166+
#endif
167+
#if defined(MCUBOOT_SWAP_USING_OFFSET)
168+
rc = flash_area_read(fap, off + sector_off, tmp_buf, blk_sz);
169+
#else
170+
rc = flash_area_read(fap, off, tmp_buf, blk_sz);
171+
#endif
172+
if (rc) {
173+
bootutil_sha_drop(&sha_ctx);
174+
BOOT_LOG_DBG("bootutil_img_validate Error %d reading data chunk %p %u %u",
175+
rc, fap, off, blk_sz);
176+
return rc;
177+
}
178+
#ifdef MCUBOOT_ENC_IMAGES
179+
if (MUST_DECRYPT(fap, image_index, hdr)) {
180+
/* Only payload is encrypted (area between header and TLVs) */
181+
int slot = flash_area_id_to_multi_image_slot(image_index,
182+
flash_area_get_id(fap));
183+
184+
if (off >= hdr_size && off < tlv_off) {
185+
blk_off = (off - hdr_size) & 0xf;
186+
boot_enc_decrypt(enc_state, slot, off - hdr_size,
187+
blk_sz, blk_off, tmp_buf);
188+
}
189+
}
190+
#endif
191+
bootutil_sha_update(&sha_ctx, tmp_buf, blk_sz);
192+
}
193+
#endif /* MCUBOOT_RAM_LOAD */
194+
#endif /* MCUBOOT_HASH_STORAGE_DIRECTLY */
195+
bootutil_sha_finish(&sha_ctx, hash_result);
196+
bootutil_sha_drop(&sha_ctx);
197+
198+
return 0;
199+
}
200+
#endif /* !MCUBOOT_SIGN_PURE */

0 commit comments

Comments
 (0)