Skip to content

Commit 529698d

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 68a4c96 commit 529698d

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
@@ -392,11 +392,6 @@ static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx)
392392
ctx->required_algorithm = 0;
393393

394394
#else /* !MCUBOOT_BUILTIN_KEY */
395-
/* The incoming key ID is equal to the image index. The key ID value must be
396-
* shifted (by one in this case) because zero is reserved (PSA_KEY_ID_NULL)
397-
* and considered invalid.
398-
*/
399-
ctx->key_id++; /* Make sure it is not equal to 0. */
400395
#if defined(MCUBOOT_SIGN_EC256)
401396
ctx->curve_byte_count = 32;
402397
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
if (keyhash_len > IMAGE_HASH_SIZE) {
284284
return -1;
@@ -334,6 +334,32 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len)
334334
return -1;
335335
}
336336
#endif /* !MCUBOOT_HW_KEY */
337+
338+
#else
339+
/* For MCUBOOT_BUILTIN_KEY, key id is passed */
340+
#define EXPECTED_KEY_TLV IMAGE_TLV_KEYID
341+
#define KEY_BUF_SIZE sizeof(int32_t)
342+
343+
static int bootutil_find_key(uint8_t image_index, uint8_t *key_id_buf, uint8_t key_id_buf_len)
344+
{
345+
int rc;
346+
FIH_DECLARE(fih_rc, FIH_FAILURE);
347+
348+
/* Key id is passed */
349+
assert(key_id_buf_len == sizeof(int32_t));
350+
int32_t key_id = (((int32_t)key_id_buf[0] << 24) |
351+
((int32_t)key_id_buf[1] << 16) |
352+
((int32_t)key_id_buf[2] << 8) |
353+
((int32_t)key_id_buf[3]));
354+
355+
/* Check if key id is associated with the image */
356+
FIH_CALL(boot_verify_key_id_for_image, fih_rc, image_index, key_id);
357+
if (FIH_EQ(fih_rc, FIH_SUCCESS)) {
358+
return key_id;
359+
}
360+
361+
return -1;
362+
}
337363
#endif /* !MCUBOOT_BUILTIN_KEY */
338364
#endif /* EXPECTED_SIG_TLV */
339365

@@ -449,6 +475,7 @@ static int bootutil_check_for_pure(const struct image_header *hdr,
449475
static const uint16_t allowed_unprot_tlvs[] = {
450476
IMAGE_TLV_KEYHASH,
451477
IMAGE_TLV_PUBKEY,
478+
IMAGE_TLV_KEYID,
452479
IMAGE_TLV_SHA256,
453480
IMAGE_TLV_SHA384,
454481
IMAGE_TLV_SHA512,
@@ -492,14 +519,7 @@ bootutil_img_validate(struct boot_loader_state *state,
492519
uint32_t img_sz;
493520
#ifdef EXPECTED_SIG_TLV
494521
FIH_DECLARE(valid_signature, FIH_FAILURE);
495-
#ifndef MCUBOOT_BUILTIN_KEY
496522
int key_id = -1;
497-
#else
498-
/* Pass a key ID equal to the image index, the underlying crypto library
499-
* is responsible for mapping the image index to a builtin key ID.
500-
*/
501-
int key_id = image_index;
502-
#endif /* !MCUBOOT_BUILTIN_KEY */
503523
#ifdef MCUBOOT_HW_KEY
504524
uint8_t key_buf[KEY_BUF_SIZE];
505525
#endif
@@ -637,7 +657,7 @@ bootutil_img_validate(struct boot_loader_state *state,
637657
if (rc) {
638658
goto out;
639659
}
640-
key_id = bootutil_find_key(buf, len);
660+
key_id = bootutil_find_key(image_index, buf, len);
641661
#else
642662
rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
643663
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,
@@ -135,13 +136,19 @@ def add(self, kind, payload):
135136
"""
136137
e = STRUCT_ENDIAN_DICT[self.endian]
137138
if isinstance(kind, int):
138-
if not TLV_VENDOR_RES_MIN <= kind <= TLV_VENDOR_RES_MAX:
139+
if kind in TLV_VALUES.values():
140+
buf = struct.pack(e + 'BBH', kind, 0, len(payload))
141+
elif TLV_VENDOR_RES_MIN <= kind <= TLV_VENDOR_RES_MAX:
142+
# Custom vendor-reserved tag
143+
buf = struct.pack(e + 'HH', kind, len(payload))
144+
else:
139145
msg = "Invalid custom TLV type value '0x{:04x}', allowed " \
140146
"value should be between 0x{:04x} and 0x{:04x}".format(
141147
kind, TLV_VENDOR_RES_MIN, TLV_VENDOR_RES_MAX)
142148
raise click.UsageError(msg)
143-
buf = struct.pack(e + 'HH', kind, len(payload))
144149
else:
150+
if kind not in TLV_VALUES:
151+
raise click.UsageError(f"Unknown TLV type string: {kind}")
145152
buf = struct.pack(e + 'BBH', TLV_VALUES[kind], 0, len(payload))
146153
self.buf += buf
147154
self.buf += payload
@@ -639,6 +646,9 @@ def create(self, key, public_key_format, enckey, dependencies=None,
639646
print(os.path.basename(__file__) + ': export digest')
640647
return
641648

649+
if self.key_ids is not None:
650+
self._add_key_id_tlv_to_unprotected(tlv, self.key_ids[0])
651+
642652
if key is not None or fixed_sig is not None:
643653
if public_key_format == 'hash':
644654
tlv.add('KEYHASH', pubbytes)
@@ -890,3 +900,13 @@ def verify(imgfile, key):
890900
pass
891901
tlv_off += TLV_SIZE + tlv_len
892902
return VerifyResult.INVALID_SIGNATURE, None, None, None
903+
904+
def set_key_ids(self, key_ids):
905+
"""Set list of key IDs (integers) to be inserted before each signature."""
906+
self.key_ids = key_ids
907+
908+
def _add_key_id_tlv_to_unprotected(self, tlv, key_id: int):
909+
"""Add a key ID TLV into the *unprotected* TLV area."""
910+
tag = TLV_VALUES['KEYID']
911+
value = key_id.to_bytes(4, self.endian)
912+
tlv.add(tag, value)

0 commit comments

Comments
 (0)