Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions boot/bootutil/include/bootutil/crypto/ecdsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,11 +394,6 @@ static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx)
ctx->required_algorithm = 0;

#else /* !MCUBOOT_BUILTIN_KEY */
/* The incoming key ID is equal to the image index. The key ID value must be
* shifted (by one in this case) because zero is reserved (PSA_KEY_ID_NULL)
* and considered invalid.
*/
ctx->key_id++; /* Make sure it is not equal to 0. */
#if defined(MCUBOOT_SIGN_EC256)
ctx->curve_byte_count = 32;
ctx->required_algorithm = PSA_ALG_SHA_256;
Expand Down
13 changes: 8 additions & 5 deletions boot/bootutil/include/bootutil/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Copyright (c) 2016-2019 Linaro LTD
* Copyright (c) 2016-2019 JUUL Labs
* Copyright (c) 2019-2023 Arm Limited
* Copyright (c) 2019-2025 Arm Limited
*
* Original license:
*
Expand Down Expand Up @@ -98,6 +98,7 @@ extern "C" {
*/
#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */
#define IMAGE_TLV_PUBKEY 0x02 /* public key */
#define IMAGE_TLV_KEYID 0x03 /* Signing key ID */
#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */
#define IMAGE_TLV_SHA384 0x11 /* SHA384 of image hdr and body */
#define IMAGE_TLV_SHA512 0x12 /* SHA512 of image hdr and body */
Expand Down Expand Up @@ -237,11 +238,13 @@ 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
#if defined(MCUBOOT_BUILTIN_KEY)
int bootutil_find_key(uint8_t image_index, uint8_t *key_id_buf, uint8_t key_id_buf_len);
#elif defined(MCUBOOT_HW_KEY)
int bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len);
#endif
#else
int bootutil_find_key(uint8_t image_index, uint8_t *keyhash, uint8_t keyhash_len);
#endif /* MCUBOOT_BUILTIN_KEY */

int
bootutil_img_hash(struct boot_loader_state *state,
Expand Down
18 changes: 17 additions & 1 deletion boot/bootutil/include/bootutil/sign_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
/* mcuboot_config.h is needed for MCUBOOT_HW_KEY to work */
#include "mcuboot_config/mcuboot_config.h"

#include "bootutil/fault_injection_hardening.h"

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -39,7 +41,21 @@ struct bootutil_key {
};

extern const struct bootutil_key bootutil_keys[];
#else

#ifdef MCUBOOT_BUILTIN_KEY
/**
* Verify that the specified key ID is valid for authenticating the given image.
*
* @param[in] image_index Index of the image to be verified.
* @param[in] key_id Identifier of the key to be verified against the image.
*
* @return FIH_SUCCESS if the key ID is valid for the image;
* FIH_FAILURE on failure.
*/
fih_ret boot_verify_key_id_for_image(uint8_t image_index, uint32_t key_id);
#endif /* MCUBOOT_BUILTIN_KEY */

#else /* !MCUBOOT_HW_KEY */
struct bootutil_key {
uint8_t *key;
unsigned int *len;
Expand Down
69 changes: 45 additions & 24 deletions boot/bootutil/src/bootutil_find_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,34 +51,27 @@ BOOT_LOG_MODULE_DECLARE(mcuboot);
#ifdef EXPECTED_SIG_TLV
#if !defined(MCUBOOT_BYPASS_KEY_MATCH)
/* Find functions are only needed when key is checked first */
#if !defined(MCUBOOT_BUILTIN_KEY)
#if !defined(MCUBOOT_HW_KEY)
int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len)
#if defined(MCUBOOT_BUILTIN_KEY)
int bootutil_find_key(uint8_t image_index, uint8_t *key_id_buf, uint8_t key_id_buf_len)
{
bootutil_sha_context sha_ctx;
int i;
const struct bootutil_key *key;
uint8_t hash[IMAGE_HASH_SIZE];
uint32_t key_id;
FIH_DECLARE(fih_rc, FIH_FAILURE);

BOOT_LOG_DBG("bootutil_find_key");
BOOT_LOG_DBG("bootutil_find_key: image_index %d", image_index);
/* Key id is passed */
assert(key_id_buf_len == sizeof(uint32_t));
memcpy(&key_id, key_id_buf, sizeof(key_id));

if (keyhash_len > IMAGE_HASH_SIZE) {
return -1;
/* Check if key id is associated with the image */
FIH_CALL(boot_verify_key_id_for_image, fih_rc, image_index, key_id);
if (FIH_EQ(fih_rc, FIH_SUCCESS)) {
return (int32_t)key_id;
}

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 */

#elif defined(MCUBOOT_HW_KEY)
extern unsigned int pub_key_len;
int bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len)
{
Expand Down Expand Up @@ -116,13 +109,41 @@ int bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len)

return -1;
}
#endif /* !MCUBOOT_HW_KEY */
#endif /* !MCUBOOT_BUILTIN_KEY */

#else /* !defined MCUBOOT_BUILTIN_KEY && !defined MCUBOOT_HW_KEY */
int bootutil_find_key(uint8_t image_index, 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];
(void)image_index;

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;
}
#endif /* MCUBOOT_HW_KEY */

#else /* !MCUBOOT_BYPASS_KEY_MATCH */
#if !defined(MCUBOOT_HW_KEY)
int bootutil_find_key(uint8_t *key, uint8_t key_len)
int bootutil_find_key(uint8_t image_index, uint8_t *key, uint8_t key_len)
{
(void)image_index;
(void)key;
(void)key_len;

Expand Down
4 changes: 2 additions & 2 deletions boot/bootutil/src/bootutil_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Copyright (c) 2017-2020 Linaro LTD
* Copyright (c) 2017-2019 JUUL Labs
* Copyright (c) 2019-2021 Arm Limited
* Copyright (c) 2019-2025 Arm Limited
*
* Original license:
*
Expand Down Expand Up @@ -288,7 +288,7 @@ struct boot_sector_buffer {
* an image and mlen to length of the hash.
*/
fih_ret bootutil_verify_sig(uint8_t *msg, uint32_t mlen, uint8_t *sig,
size_t slen, uint8_t key_id);
size_t slen, uint32_t key_id);

fih_ret boot_fih_memequal(const void *s1, const void *s2, size_t n);

Expand Down
6 changes: 3 additions & 3 deletions boot/bootutil/src/image_ecdsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Copyright (c) 2016-2019 JUUL Labs
* Copyright (c) 2017 Linaro LTD
* Copyright (C) 2021-2024 Arm Limited
* Copyright (C) 2021-2025 Arm Limited
*
* Original license:
*
Expand Down Expand Up @@ -41,7 +41,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot);
#if !defined(MCUBOOT_BUILTIN_KEY)
fih_ret
bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen,
uint8_t key_id)
uint32_t key_id)
{
int rc;
bootutil_ecdsa_context ctx;
Expand Down Expand Up @@ -74,7 +74,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen,
#else /* !MCUBOOT_BUILTIN_KEY */
fih_ret
bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen,
uint8_t key_id)
uint32_t key_id)
{
int rc;
bootutil_ecdsa_context ctx;
Expand Down
4 changes: 2 additions & 2 deletions boot/bootutil/src/image_ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2019 JUUL Labs
* Copyright (c) 2021-2023 Arm Limited
* Copyright (c) 2021-2025 Arm Limited
* Copyright (c) 2025 Nordic Semiconductor ASA
*/

Expand Down Expand Up @@ -85,7 +85,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end)
*/
fih_ret
bootutil_verify_sig(uint8_t *msg, uint32_t mlen, uint8_t *sig, size_t slen,
uint8_t key_id)
uint32_t key_id)
{
int rc;
FIH_DECLARE(fih_rc, FIH_FAILURE);
Expand Down
4 changes: 2 additions & 2 deletions boot/bootutil/src/image_rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Copyright (c) 2017-2018 Linaro LTD
* Copyright (c) 2017-2019 JUUL Labs
* Copyright (c) 2020-2023 Arm Limited
* Copyright (c) 2020-2025 Arm Limited
*
* Original license:
*
Expand Down Expand Up @@ -262,7 +262,7 @@ bootutil_cmp_rsasig(bootutil_rsa_context *ctx, uint8_t *hash, uint32_t hlen,

fih_ret
bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen,
uint8_t key_id)
uint32_t key_id)
{
bootutil_rsa_context ctx;
int rc;
Expand Down
35 changes: 16 additions & 19 deletions boot/bootutil/src/image_validate.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Copyright (c) 2017-2019 Linaro LTD
* Copyright (c) 2016-2019 JUUL Labs
* Copyright (c) 2019-2024 Arm Limited
* Copyright (c) 2019-2025 Arm Limited
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* Original license:
Expand Down Expand Up @@ -98,21 +98,24 @@ BOOT_LOG_MODULE_DECLARE(mcuboot);
#endif

#ifdef EXPECTED_SIG_TLV
#if defined(MCUBOOT_BUILTIN_KEY)
/* For MCUBOOT_BUILTIN_KEY, key id is passed */
#define EXPECTED_KEY_TLV IMAGE_TLV_KEYID
#define KEY_BUF_SIZE sizeof(uint32_t)

#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
#elif defined(MCUBOOT_HW_KEY)
/* 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 */
#endif /* !MCUBOOT_BUILTIN_KEY */
#define EXPECTED_KEY_TLV IMAGE_TLV_PUBKEY
#define KEY_BUF_SIZE (SIG_BUF_SIZE + 24)

#else /* !MCUBOOT_BUILTIN_KEY && !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
#endif /* MCUBOOT_BUILTIN_KEY */
#endif /* EXPECTED_SIG_TLV */

#if defined(MCUBOOT_SIGN_PURE)
Expand Down Expand Up @@ -169,6 +172,7 @@ static int bootutil_check_for_pure(const struct image_header *hdr, const struct
static const uint16_t allowed_unprot_tlvs[] = {
IMAGE_TLV_KEYHASH,
IMAGE_TLV_PUBKEY,
IMAGE_TLV_KEYID,
IMAGE_TLV_SHA256,
IMAGE_TLV_SHA384,
IMAGE_TLV_SHA512,
Expand Down Expand Up @@ -216,14 +220,7 @@ bootutil_img_validate(struct boot_loader_state *state,
uint32_t img_sz;
#ifdef EXPECTED_SIG_TLV
FIH_DECLARE(valid_signature, FIH_FAILURE);
#ifndef MCUBOOT_BUILTIN_KEY
int key_id = -1;
#else
/* Pass a key ID equal to the image index, the underlying crypto library
* is responsible for mapping the image index to a builtin key ID.
*/
int key_id = image_index;
#endif /* !MCUBOOT_BUILTIN_KEY */
#ifdef MCUBOOT_HW_KEY
uint8_t key_buf[KEY_BUF_SIZE];
#endif
Expand Down Expand Up @@ -377,7 +374,7 @@ bootutil_img_validate(struct boot_loader_state *state,
if (rc) {
goto out;
}
key_id = bootutil_find_key(buf, len);
key_id = bootutil_find_key(image_index, buf, len);
#else
rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
if (rc) {
Expand Down
22 changes: 18 additions & 4 deletions scripts/imgtool/image.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright 2018 Nordic Semiconductor ASA
# Copyright 2017-2020 Linaro Limited
# Copyright 2019-2024 Arm Limited
# Copyright 2019-2025 Arm Limited
#
# SPDX-License-Identifier: Apache-2.0
#
Expand Down Expand Up @@ -71,6 +71,7 @@
TLV_VALUES = {
'KEYHASH': 0x01,
'PUBKEY': 0x02,
'KEYID': 0x03,
'SHA256': 0x10,
'SHA384': 0x11,
'SHA512': 0x12,
Expand Down Expand Up @@ -138,15 +139,21 @@ def add(self, kind, payload):
"""
e = STRUCT_ENDIAN_DICT[self.endian]
if isinstance(kind, int):
if not TLV_VENDOR_RES_MIN <= kind <= TLV_VENDOR_RES_MAX:
if kind in TLV_VALUES.values():
buf = struct.pack(e + 'BBH', kind, 0, len(payload))
elif TLV_VENDOR_RES_MIN <= kind <= TLV_VENDOR_RES_MAX:
# Custom vendor-reserved tag
buf = struct.pack(e + 'HH', kind, len(payload))
else:
msg = (
f"Invalid custom TLV type value '0x{kind:04x}', allowed "
f"value should be between 0x{TLV_VENDOR_RES_MIN:04x} and "
"0x{TLV_VENDOR_RES_MAX:04x}"
)
raise click.UsageError(msg)
buf = struct.pack(e + 'HH', kind, len(payload))
else:
if kind not in TLV_VALUES:
raise click.UsageError(f"Unknown TLV type string: {kind}")
buf = struct.pack(e + 'BBH', TLV_VALUES[kind], 0, len(payload))
self.buf += buf
self.buf += payload
Expand Down Expand Up @@ -324,6 +331,7 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE,
self.non_bootable = non_bootable
self.vid = vid
self.cid = cid
self.psa_key_id = None

if self.max_align == DEFAULT_MAX_ALIGN:
self.boot_magic = bytes([
Expand Down Expand Up @@ -712,7 +720,9 @@ def create(self, key, public_key_format, enckey, dependencies=None,
return

if key is not None or fixed_sig is not None:
if public_key_format == 'hash':
if self.psa_key_id is not None:
tlv.add('KEYID', self.psa_key_id.to_bytes(4, self.endian))
elif public_key_format == 'hash':
tlv.add('KEYHASH', pubbytes)
else:
tlv.add('PUBKEY', pub)
Expand Down Expand Up @@ -806,6 +816,10 @@ def get_signature(self):
def get_infile_data(self):
return self.infile_data

def set_key_id(self, psa_key_id):
"""Set key ID (integer) to be inserted before the signature."""
self.psa_key_id = psa_key_id

def add_header(self, enckey, protected_tlv_size, compression_flags, aes_length=128):
"""Install the image header."""

Expand Down
Loading
Loading