Skip to content

Commit 59fddec

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 c4a7b25 commit 59fddec

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
@@ -273,12 +273,12 @@ bootutil_img_hash(struct boot_loader_state *state,
273273

274274
#if !defined(MCUBOOT_HW_KEY)
275275
static int
276-
bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len)
276+
bootutil_find_key(uint8_t image_index, uint8_t *keyhash, uint8_t keyhash_len)
277277
{
278278
bootutil_sha_context sha_ctx;
279279
int i;
280280
const struct bootutil_key *key;
281-
uint8_t hash[IMAGE_HASH_SIZE];
281+
(void)image_index;
282282

283283
BOOT_LOG_DBG("bootutil_find_key");
284284

@@ -338,6 +338,32 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len)
338338
return -1;
339339
}
340340
#endif /* !MCUBOOT_HW_KEY */
341+
342+
#else
343+
/* For MCUBOOT_BUILTIN_KEY, key id is passed */
344+
#define EXPECTED_KEY_TLV IMAGE_TLV_KEYID
345+
#define KEY_BUF_SIZE sizeof(int32_t)
346+
347+
static int bootutil_find_key(uint8_t image_index, uint8_t *key_id_buf, uint8_t key_id_buf_len)
348+
{
349+
int rc;
350+
FIH_DECLARE(fih_rc, FIH_FAILURE);
351+
352+
/* Key id is passed */
353+
assert(key_id_buf_len == sizeof(int32_t));
354+
int32_t key_id = (((int32_t)key_id_buf[0] << 24) |
355+
((int32_t)key_id_buf[1] << 16) |
356+
((int32_t)key_id_buf[2] << 8) |
357+
((int32_t)key_id_buf[3]));
358+
359+
/* Check if key id is associated with the image */
360+
FIH_CALL(boot_verify_key_id_for_image, fih_rc, image_index, key_id);
361+
if (FIH_EQ(fih_rc, FIH_SUCCESS)) {
362+
return key_id;
363+
}
364+
365+
return -1;
366+
}
341367
#endif /* !MCUBOOT_BUILTIN_KEY */
342368
#endif /* EXPECTED_SIG_TLV */
343369

@@ -453,6 +479,7 @@ static int bootutil_check_for_pure(const struct image_header *hdr,
453479
static const uint16_t allowed_unprot_tlvs[] = {
454480
IMAGE_TLV_KEYHASH,
455481
IMAGE_TLV_PUBKEY,
482+
IMAGE_TLV_KEYID,
456483
IMAGE_TLV_SHA256,
457484
IMAGE_TLV_SHA384,
458485
IMAGE_TLV_SHA512,
@@ -497,14 +524,7 @@ bootutil_img_validate(struct boot_loader_state *state,
497524
uint32_t img_sz;
498525
#ifdef EXPECTED_SIG_TLV
499526
FIH_DECLARE(valid_signature, FIH_FAILURE);
500-
#ifndef MCUBOOT_BUILTIN_KEY
501527
int key_id = -1;
502-
#else
503-
/* Pass a key ID equal to the image index, the underlying crypto library
504-
* is responsible for mapping the image index to a builtin key ID.
505-
*/
506-
int key_id = image_index;
507-
#endif /* !MCUBOOT_BUILTIN_KEY */
508528
#ifdef MCUBOOT_HW_KEY
509529
uint8_t key_buf[KEY_BUF_SIZE];
510530
#endif
@@ -642,7 +662,7 @@ bootutil_img_validate(struct boot_loader_state *state,
642662
if (rc) {
643663
goto out;
644664
}
645-
key_id = bootutil_find_key(buf, len);
665+
key_id = bootutil_find_key(image_index, buf, len);
646666
#else
647667
rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
648668
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)