Skip to content

Commit d7d923c

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 <[email protected]> Change-Id: I05c97ac385c5816c812c51feb010028df8412fe5
1 parent 35bdb7b commit d7d923c

File tree

13 files changed

+526
-325
lines changed

13 files changed

+526
-325
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
@@ -24,6 +24,9 @@
2424

2525
#include <stddef.h>
2626
#include <stdint.h>
27+
#ifdef MCUBOOT_IMAGE_MULTI_SIG_SUPPORT
28+
#include <stdbool.h>
29+
#endif /* MCUBOOT_IMAGE_MULTI_SIG_SUPPORT */
2730

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

0 commit comments

Comments
 (0)