Skip to content

Commit df7225f

Browse files
committed
bootutil: Add support for multi-sign of same type
This commit adds functionality to the bootutil library to support multiple sign verfication of same type when 'MCUBOOT_BUILTIN_KEY' or 'MCUBOOT_HW_KEY' is enabled. The image_validate.c file is refactored such that: * bootutil_find_key() find the key is moved to a new file bootutil_find_key.c. * bootutil_image_hash() is moved to a new file bootutil_image_hash.c. * bootutil_img_security_cnt() is moved to a new file bootutil_img_security_cnt.c. This allows common validation code to be reused for multiple signatures. All code specific to multi sign is under the option 'MCUBOOT_IMAGE_MULTI_SIG_SUPPORT'. Furthermore, key id type is updated to uint32_t as per PSA crypto spec. Signed-off-by: Maulik Patel <maulik.patel@arm.com> Change-Id: I05c97ac385c5816c812c51feb010028df8412fe5
1 parent 083b3ef commit df7225f

File tree

13 files changed

+537
-335
lines changed

13 files changed

+537
-335
lines changed

boot/bootutil/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#------------------------------------------------------------------------------
2-
# Copyright (c) 2020-2023, Arm Limited. All rights reserved.
2+
# Copyright (c) 2020-2025, Arm Limited. All rights reserved.
33
#
44
# SPDX-License-Identifier: Apache-2.0
55
#
@@ -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
@@ -33,6 +36,7 @@ target_sources(bootutil
3336
src/swap_scratch.c
3437
src/tlv.c
3538
)
39+
3640
if(CONFIG_BOOT_RAM_LOAD)
3741
target_sources(bootutil
3842
PRIVATE

boot/bootutil/include/bootutil/image.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,23 @@ int32_t bootutil_get_img_security_cnt(struct boot_loader_state *state, int slot,
236236
const struct flash_area *fap,
237237
uint32_t *img_security_cnt);
238238

239+
#if defined(MCUBOOT_BUILTIN_KEY)
240+
int bootutil_find_key(uint8_t image_index, uint8_t *key_id_buf, uint8_t key_id_buf_len);
241+
#elif defined(MCUBOOT_HW_KEY)
242+
int bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len);
243+
#else
244+
int bootutil_find_key(uint8_t image_index, uint8_t *keyhash, uint8_t keyhash_len);
245+
#endif
246+
247+
int bootutil_img_hash(struct boot_loader_state *state,
248+
struct image_header *hdr, const struct flash_area *fap,
249+
uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *hash_result,
250+
uint8_t *seed, int seed_len
251+
#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
252+
, uint32_t start_offset
253+
#endif
254+
);
255+
239256
#ifdef __cplusplus
240257
}
241258
#endif

boot/bootutil/include/bootutil/sign_key.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727

2828
/* mcuboot_config.h is needed for MCUBOOT_HW_KEY to work */
2929
#include "mcuboot_config/mcuboot_config.h"
30+
#ifdef MCUBOOT_IMAGE_MULTI_SIG_SUPPORT
31+
#include <stdbool.h>
32+
#endif /* MCUBOOT_IMAGE_MULTI_SIG_SUPPORT */
3033

3134
#ifdef __cplusplus
3235
extern "C" {
@@ -62,17 +65,41 @@ extern struct bootutil_key bootutil_keys[];
6265
* Retrieve the hash of the corresponding public key for image authentication.
6366
*
6467
* @param[in] image_index Index of the image to be authenticated.
68+
* @param[in] key_index Index of the key to be used.
6569
* @param[out] public_key_hash Buffer to store the key-hash in.
6670
* @param[in,out] key_hash_size As input the size of the buffer. As output
6771
* the actual key-hash length.
6872
*
6973
* @return 0 on success; nonzero on failure.
7074
*/
7175
int boot_retrieve_public_key_hash(uint8_t image_index,
76+
uint8_t key_index,
7277
uint8_t *public_key_hash,
7378
size_t *key_hash_size);
79+
7480
#endif /* !MCUBOOT_HW_KEY */
7581

82+
#ifdef MCUBOOT_IMAGE_MULTI_SIG_SUPPORT
83+
/**
84+
* @brief Checks the key policy for signature verification.
85+
*
86+
* Determines whether a given key might or must be used to sign an image,
87+
* based on the validity of the signature and the key index. Updates the
88+
* provided output parameters to reflect the policy.
89+
*
90+
* @param valid_sig Indicates if the signature is valid.
91+
* @param key The key index to check.
92+
* @param[out] key_might_sign Set to true if the key might be used to sign.
93+
* @param[out] key_must_sign Set to true if the key must be used to sign.
94+
* @param[out] key_must_sign_count Set to the number of keys that must sign.
95+
*
96+
* @return 0 on success, or a negative error code on failure.
97+
*/
98+
int boot_plat_check_key_policy(bool valid_sig, uint32_t key,
99+
bool *key_might_sign, bool *key_must_sign,
100+
uint8_t *key_must_sign_count);
101+
#endif /* MCUBOOT_IMAGE_MULTI_SIG_SUPPORT */
102+
76103
extern const int bootutil_key_cnt;
77104

78105
#ifdef __cplusplus

boot/bootutil/src/bootutil_find_key.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
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/bootutil_log.h"
32+
#include "bootutil/crypto/sha.h"
33+
#include "bootutil/fault_injection_hardening.h"
34+
#include "bootutil/image.h"
35+
#include "bootutil/sign_key.h"
36+
#include "bootutil_priv.h"
37+
#include "mcuboot_config/mcuboot_config.h"
38+
39+
#ifdef MCUBOOT_IMAGE_MULTI_SIG_SUPPORT
40+
#define NUM_OF_KEYS MCUBOOT_ROTPK_MAX_KEYS_PER_IMAGE
41+
#else
42+
#define NUM_OF_KEYS 1
43+
#endif /* MCUBOOT_IMAGE_MULTI_SIG_SUPPORT */
44+
45+
#if defined(MCUBOOT_BUILTIN_KEY)
46+
int bootutil_find_key(uint8_t image_index, uint8_t *key_id_buf, uint8_t key_id_buf_len)
47+
{
48+
uint32_t key_id;
49+
FIH_DECLARE(fih_rc, FIH_FAILURE);
50+
51+
BOOT_LOG_DBG("bootutil_find_key: image_index %d", image_index);
52+
53+
/* Key id is passed */
54+
assert(key_id_buf_len == sizeof(uint32_t));
55+
memcpy(&key_id, key_id_buf, sizeof(key_id));
56+
57+
/* Check if key id is associated with the image */
58+
FIH_CALL(boot_verify_key_id_for_image, fih_rc, image_index, key_id);
59+
if (FIH_EQ(fih_rc, FIH_SUCCESS)) {
60+
return (int32_t)key_id;
61+
}
62+
63+
return -1;
64+
}
65+
66+
#elif defined(MCUBOOT_HW_KEY)
67+
extern unsigned int pub_key_len;
68+
int bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len)
69+
{
70+
bootutil_sha_context sha_ctx;
71+
uint8_t hash[IMAGE_HASH_SIZE];
72+
uint8_t key_hash[IMAGE_HASH_SIZE];
73+
size_t key_hash_size = sizeof(key_hash);
74+
int rc;
75+
uint8_t key_index;
76+
FIH_DECLARE(fih_rc, FIH_FAILURE);
77+
78+
BOOT_LOG_DBG("bootutil_find_key: image_index %d", image_index);
79+
80+
bootutil_sha_init(&sha_ctx);
81+
bootutil_sha_update(&sha_ctx, key, key_len);
82+
bootutil_sha_finish(&sha_ctx, hash);
83+
bootutil_sha_drop(&sha_ctx);
84+
85+
for(key_index = 0; key_index < NUM_OF_KEYS; key_index++) {
86+
rc = boot_retrieve_public_key_hash(image_index, key_index, key_hash, &key_hash_size);
87+
if (rc) {
88+
return -1;
89+
}
90+
91+
/* Adding hardening to avoid this potential attack:
92+
* - Image is signed with an arbitrary key and the corresponding public
93+
* key is added as a TLV field.
94+
* - During public key validation (comparing against key-hash read from
95+
* HW) a fault is injected to accept the public key as valid one.
96+
*/
97+
FIH_CALL(boot_fih_memequal, fih_rc, hash, key_hash, key_hash_size);
98+
if (FIH_EQ(fih_rc, FIH_SUCCESS)) {
99+
BOOT_LOG_INF("Key %d hash found for image %d", key_index, image_index);
100+
bootutil_keys[0].key = key;
101+
pub_key_len = key_len;
102+
return 0;
103+
}
104+
}
105+
BOOT_LOG_ERR("Key hash NOT found for image %d!", image_index);
106+
107+
return -1;
108+
}
109+
110+
#else /* !defined MCUBOOT_BUILTIN_KEY && !defined MCUBOOT_HW_KEY */
111+
int bootutil_find_key(uint8_t image_index, uint8_t *keyhash, uint8_t keyhash_len)
112+
{
113+
bootutil_sha_context sha_ctx;
114+
int i;
115+
uint8_t hash[IMAGE_HASH_SIZE];
116+
const struct bootutil_key *key;
117+
(void)image_index;
118+
119+
BOOT_LOG_DBG("bootutil_find_key");
120+
121+
if (keyhash_len > IMAGE_HASH_SIZE) {
122+
return -1;
123+
}
124+
125+
for (i = 0; i < bootutil_key_cnt; i++) {
126+
key = &bootutil_keys[i];
127+
bootutil_sha_init(&sha_ctx);
128+
bootutil_sha_update(&sha_ctx, key->key, *key->len);
129+
bootutil_sha_finish(&sha_ctx, hash);
130+
bootutil_sha_drop(&sha_ctx);
131+
if (!memcmp(hash, keyhash, keyhash_len)) {
132+
return i;
133+
}
134+
}
135+
return -1;
136+
}
137+
#endif

0 commit comments

Comments
 (0)