Skip to content

Commit 722caa3

Browse files
committed
bootutil: Parse key id for built in keys
When MCUBOOT_BUILTIN_KEY is enabled, the key id TLV entry is added to the image. Parse this entry while validating the image to identify the key used to sign the image. This enables future support for scenarios such as multiple built-in keys or multi-signature. Signed-off-by: Maulik Patel <maulik.patel@arm.com> Change-Id: Ibe26bc2b09e63350f4214719606a5aa4bc1be93c
1 parent 6a178d2 commit 722caa3

File tree

5 files changed

+64
-17
lines changed

5 files changed

+64
-17
lines changed

boot/bootutil/include/bootutil/crypto/ecdsa.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -394,11 +394,6 @@ static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx)
394394
ctx->required_algorithm = 0;
395395

396396
#else /* !MCUBOOT_BUILTIN_KEY */
397-
/* The incoming key ID is equal to the image index. The key ID value must be
398-
* shifted (by one in this case) because zero is reserved (PSA_KEY_ID_NULL)
399-
* and considered invalid.
400-
*/
401-
ctx->key_id++; /* Make sure it is not equal to 0. */
402397
#if defined(MCUBOOT_SIGN_EC256)
403398
ctx->curve_byte_count = 32;
404399
ctx->required_algorithm = PSA_ALG_SHA_256;

boot/bootutil/include/bootutil/image.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ extern "C" {
9898
*/
9999
#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */
100100
#define IMAGE_TLV_PUBKEY 0x02 /* public key */
101+
#define IMAGE_TLV_KEYID 0x03 /* Key ID */
101102
#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */
102103
#define IMAGE_TLV_SHA384 0x11 /* SHA384 of image hdr and body */
103104
#define IMAGE_TLV_SHA512 0x12 /* SHA512 of image hdr and body */

boot/bootutil/include/bootutil/sign_key.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ struct bootutil_key {
3939
};
4040

4141
extern const struct bootutil_key bootutil_keys[];
42+
#ifdef MCUBOOT_BUILTIN_KEY
43+
/**
44+
* Verify that the specified key ID is valid for authenticating the given image.
45+
*
46+
* @param[in] image_index Index of the image to be verified.
47+
* @param[in] key_id Identifier of the key to be verified against the image.
48+
*
49+
* @return 0 if the key ID is valid for the image; nonzero on failure.
50+
*/
51+
int boot_verify_key_id_for_image(uint8_t image_index, uint32_t key_id);
52+
#endif /* MCUBOOT_BUILTIN_KEY */
4253
#else
4354
struct bootutil_key {
4455
uint8_t *key;

boot/bootutil/src/image_validate.c

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -282,12 +282,12 @@ bootutil_img_hash(struct boot_loader_state *state,
282282

283283
#if !defined(MCUBOOT_HW_KEY)
284284
static int
285-
bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len)
285+
bootutil_find_key(uint8_t image_index, uint8_t *keyhash, uint8_t keyhash_len)
286286
{
287287
bootutil_sha_context sha_ctx;
288288
int i;
289289
const struct bootutil_key *key;
290-
uint8_t hash[IMAGE_HASH_SIZE];
290+
(void)image_index;
291291

292292
BOOT_LOG_DBG("bootutil_find_key");
293293

@@ -347,6 +347,32 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len)
347347
return -1;
348348
}
349349
#endif /* !MCUBOOT_HW_KEY */
350+
351+
#else
352+
/* For MCUBOOT_BUILTIN_KEY, key id is passed */
353+
#define EXPECTED_KEY_TLV IMAGE_TLV_KEYID
354+
#define KEY_BUF_SIZE sizeof(int32_t)
355+
356+
static int bootutil_find_key(uint8_t image_index, uint8_t *key_id_buf, uint8_t key_id_buf_len)
357+
{
358+
int rc;
359+
FIH_DECLARE(fih_rc, FIH_FAILURE);
360+
361+
/* Key id is passed */
362+
assert(key_id_buf_len == sizeof(int32_t));
363+
int32_t key_id = (((int32_t)key_id_buf[0] << 24) |
364+
((int32_t)key_id_buf[1] << 16) |
365+
((int32_t)key_id_buf[2] << 8) |
366+
((int32_t)key_id_buf[3]));
367+
368+
/* Check if key id is associated with the image */
369+
FIH_CALL(boot_verify_key_id_for_image, fih_rc, image_index, key_id);
370+
if (FIH_EQ(fih_rc, FIH_SUCCESS)) {
371+
return key_id;
372+
}
373+
374+
return -1;
375+
}
350376
#endif /* !MCUBOOT_BUILTIN_KEY */
351377
#endif /* EXPECTED_SIG_TLV */
352378

@@ -462,6 +488,7 @@ static int bootutil_check_for_pure(const struct image_header *hdr,
462488
static const uint16_t allowed_unprot_tlvs[] = {
463489
IMAGE_TLV_KEYHASH,
464490
IMAGE_TLV_PUBKEY,
491+
IMAGE_TLV_KEYID,
465492
IMAGE_TLV_SHA256,
466493
IMAGE_TLV_SHA384,
467494
IMAGE_TLV_SHA512,
@@ -506,14 +533,7 @@ bootutil_img_validate(struct boot_loader_state *state,
506533
uint32_t img_sz;
507534
#ifdef EXPECTED_SIG_TLV
508535
FIH_DECLARE(valid_signature, FIH_FAILURE);
509-
#ifndef MCUBOOT_BUILTIN_KEY
510536
int key_id = -1;
511-
#else
512-
/* Pass a key ID equal to the image index, the underlying crypto library
513-
* is responsible for mapping the image index to a builtin key ID.
514-
*/
515-
int key_id = image_index;
516-
#endif /* !MCUBOOT_BUILTIN_KEY */
517537
#ifdef MCUBOOT_HW_KEY
518538
uint8_t key_buf[KEY_BUF_SIZE];
519539
#endif
@@ -651,7 +671,7 @@ bootutil_img_validate(struct boot_loader_state *state,
651671
if (rc) {
652672
goto out;
653673
}
654-
key_id = bootutil_find_key(buf, len);
674+
key_id = bootutil_find_key(image_index, buf, len);
655675
#else
656676
rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
657677
if (rc) {

scripts/imgtool/image.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
TLV_VALUES = {
7777
'KEYHASH': 0x01,
7878
'PUBKEY': 0x02,
79+
'KEYID': 0x03,
7980
'SHA256': 0x10,
8081
'SHA384': 0x11,
8182
'SHA512': 0x12,
@@ -136,13 +137,19 @@ def add(self, kind, payload):
136137
"""
137138
e = STRUCT_ENDIAN_DICT[self.endian]
138139
if isinstance(kind, int):
139-
if not TLV_VENDOR_RES_MIN <= kind <= TLV_VENDOR_RES_MAX:
140+
if kind in TLV_VALUES.values():
141+
buf = struct.pack(e + 'BBH', kind, 0, len(payload))
142+
elif TLV_VENDOR_RES_MIN <= kind <= TLV_VENDOR_RES_MAX:
143+
# Custom vendor-reserved tag
144+
buf = struct.pack(e + 'HH', kind, len(payload))
145+
else:
140146
msg = "Invalid custom TLV type value '0x{:04x}', allowed " \
141147
"value should be between 0x{:04x} and 0x{:04x}".format(
142148
kind, TLV_VENDOR_RES_MIN, TLV_VENDOR_RES_MAX)
143149
raise click.UsageError(msg)
144-
buf = struct.pack(e + 'HH', kind, len(payload))
145150
else:
151+
if kind not in TLV_VALUES:
152+
raise click.UsageError(f"Unknown TLV type string: {kind}")
146153
buf = struct.pack(e + 'BBH', TLV_VALUES[kind], 0, len(payload))
147154
self.buf += buf
148155
self.buf += payload
@@ -641,6 +648,9 @@ def create(self, key, public_key_format, enckey, dependencies=None,
641648
print(os.path.basename(__file__) + ': export digest')
642649
return
643650

651+
if self.key_ids is not None:
652+
self._add_key_id_tlv_to_unprotected(tlv, self.key_ids[0])
653+
644654
if key is not None or fixed_sig is not None:
645655
if public_key_format == 'hash':
646656
tlv.add('KEYHASH', pubbytes)
@@ -907,3 +917,13 @@ def verify(imgfile, key):
907917
pass
908918
tlv_off += TLV_SIZE + tlv_len
909919
return VerifyResult.INVALID_SIGNATURE, None, None, None
920+
921+
def set_key_ids(self, key_ids):
922+
"""Set list of key IDs (integers) to be inserted before each signature."""
923+
self.key_ids = key_ids
924+
925+
def _add_key_id_tlv_to_unprotected(self, tlv, key_id: int):
926+
"""Add a key ID TLV into the *unprotected* TLV area."""
927+
tag = TLV_VALUES['KEYID']
928+
value = key_id.to_bytes(4, self.endian)
929+
tlv.add(tag, value)

0 commit comments

Comments
 (0)