Skip to content

Commit 439be35

Browse files
maulik-armadeaarm
authored andcommitted
BL2: Update key id mapping for built in keys
For MCUBOOT_BUILTIN_KEY, create config for secure and non-secure key id. This will be added to image as separate TLV entry. It will be parsed by mcuboot during verification and will be used to load key from OTP. Signed-off-by: Maulik Patel <maulik.patel@arm.com> Change-Id: Ia6148a993c908d0306461e91e449a0582fecaeaa
1 parent d1afad0 commit 439be35

File tree

6 files changed

+142
-63
lines changed

6 files changed

+142
-63
lines changed

bl2/ext/mcuboot/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ target_sources(bl2
7777
target_compile_definitions(bl2
7878
PRIVATE
7979
MCUBOOT_SIGNATURE_TYPE=${MCUBOOT_SIGNATURE_TYPE}
80+
$<$<BOOL:${MCUBOOT_BUILTIN_KEY}>:TFM_S_KEY_ID=${TFM_S_KEY_ID}>
81+
$<$<BOOL:${MCUBOOT_BUILTIN_KEY}>:TFM_NS_KEY_ID=${TFM_NS_KEY_ID}>
82+
MCUBOOT_ROTPK_MAX_KEYS_PER_IMAGE=${MCUBOOT_ROTPK_MAX_KEYS_PER_IMAGE}
8083
)
8184

8285
target_link_libraries(bl2
@@ -216,7 +219,6 @@ if (PLATFORM_DEFAULT_IMAGE_SIGNING)
216219
)
217220
218221
if(MCUBOOT_BUILTIN_KEY)
219-
set(TFM_S_KEY_ID 0)
220222
set(wrapper_args ${wrapper_args} --psa-key-ids ${TFM_S_KEY_ID})
221223
endif()
222224

bl2/ext/mcuboot/keys.c

Lines changed: 97 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* Modifications are Copyright (c) 2019-2024 Arm Limited.
2525
*/
2626

27+
#include <assert.h>
2728
#include <stddef.h>
2829
#include <stdbool.h>
2930
#include <bootutil/sign_key.h>
@@ -533,14 +534,17 @@ int boot_retrieve_public_key_hash(uint8_t image_index,
533534
(uint32_t *)key_hash_size);
534535
}
535536
#elif defined(MCUBOOT_BUILTIN_KEY)
537+
/* Maximum number of keys per image */
538+
#define MAX_KEYS_PER_IMAGE MCUBOOT_ROTPK_MAX_KEYS_PER_IMAGE
539+
536540
/**
537541
* @note When using builtin keys the signature verification happens based on key IDs.
538542
* During verification MCUboot feeds the image index as a key ID and it is the
539543
* underlying crypto library's responsibility to do a mapping (if required)
540544
* between the image indexes and the builtin key IDs. Therefore it only allows
541-
* as many IDs as there are images.
545+
* as many IDs as there are images times number of keys per image.
542546
*/
543-
const int bootutil_key_cnt = MCUBOOT_IMAGE_NUMBER;
547+
const int bootutil_key_cnt = (MCUBOOT_IMAGE_NUMBER * MAX_KEYS_PER_IMAGE);
544548

545549
/**
546550
* @brief Loader function to retrieve the Root of Trust Public Key
@@ -570,10 +574,11 @@ static enum tfm_plat_err_t tfm_plat_get_bl2_rotpk(const void *ctx,
570574
{
571575
enum tfm_plat_err_t err;
572576
const tfm_plat_builtin_key_descriptor_t *descriptor = (const tfm_plat_builtin_key_descriptor_t *)ctx;
573-
/* ToDo: sort out the mapping between Key IDs and image indexes at runtime */
574-
uint32_t image_idx = descriptor->key_id - 1;
575577

576-
err = tfm_plat_otp_read(PLAT_OTP_ID_BL2_ROTPK_0 + image_idx, buf_len, buf);
578+
assert(descriptor->key_id >= 0);
579+
580+
uint32_t otp_id = PLAT_OTP_ID_BL2_ROTPK_0 + descriptor->key_id;
581+
err = tfm_plat_otp_read(otp_id, buf_len, buf);
577582
if (err != TFM_PLAT_ERR_SUCCESS) {
578583
return err;
579584
}
@@ -583,7 +588,7 @@ static enum tfm_plat_err_t tfm_plat_get_bl2_rotpk(const void *ctx,
583588
* encoding of the key (RSA) or alignment requirements of the stored key
584589
* material, which in OTP must be 4-bytes aligned
585590
*/
586-
err = tfm_plat_otp_get_size(PLAT_OTP_ID_BL2_ROTPK_0 + image_idx, key_len);
591+
err = tfm_plat_otp_get_size(otp_id, key_len);
587592
if (err != TFM_PLAT_ERR_SUCCESS) {
588593
return err;
589594
}
@@ -625,67 +630,119 @@ static enum tfm_plat_err_t tfm_plat_get_bl2_rotpk(const void *ctx,
625630
return TFM_PLAT_ERR_SUCCESS;
626631
}
627632

633+
typedef struct {
634+
uint32_t key_id[MAX_KEYS_PER_IMAGE]; /*!< Key id of built in keys */
635+
}image_key_id_mapping_t;
636+
637+
/* Platform specific image to key id (otp id offset) map */
638+
static const image_key_id_mapping_t tfm_image_key_map[] = {
639+
{
640+
/* Image 0: Only one key is provided and required */
641+
.key_id = { TFM_S_KEY_ID },
642+
},
643+
{
644+
/* Image 1: Only one key is provided and required */
645+
.key_id = { TFM_NS_KEY_ID },
646+
},
647+
#if (MCUBOOT_IMAGE_NUMBER > 2)
648+
{
649+
/* Image 2: Only one key is provided and required */
650+
.key_id = { TFM_S_KEY_ID_3 },
651+
},
652+
#endif /* MCUBOOT_IMAGE_NUMBER > 2 */
653+
#if (MCUBOOT_IMAGE_NUMBER > 3)
654+
{
655+
/* Image 3: Only one key is provided and required */
656+
.key_id = { TFM_S_KEY_ID_4 },
657+
},
658+
#endif /* MCUBOOT_IMAGE_NUMBER > 3 */
659+
};
660+
661+
static int get_key_id(uint8_t img_idx, uint8_t key_idx)
662+
{
663+
assert(img_idx < MCUBOOT_IMAGE_NUMBER);
664+
assert(key_idx < MAX_KEYS_PER_IMAGE);
665+
return tfm_image_key_map[img_idx].key_id[key_idx];
666+
}
667+
628668
/* The policy table is built dynamically at runtime to allow for an arbitrary
629669
* number of MCUBOOT_IMAGE_NUMBER entries, without hardcoding at build time
630670
*/
631671
size_t tfm_plat_builtin_key_get_policy_table_ptr(const tfm_plat_builtin_key_policy_t *policy_ptr[])
632672
{
633-
#if defined(MCUBOOT_BUILTIN_KEY)
634-
static tfm_plat_builtin_key_policy_t policy_table[MCUBOOT_IMAGE_NUMBER];
673+
static tfm_plat_builtin_key_policy_t policy_table[MCUBOOT_IMAGE_NUMBER][MAX_KEYS_PER_IMAGE];
635674
static bool policy_table_is_initalized = false;
636675

637676
if (!policy_table_is_initalized) {
638-
for (uint32_t idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) {
639-
tfm_plat_builtin_key_policy_t policy = {
640-
.key_id = idx + 1, /* ToDo: Relationship between key_id and image_idx is simply hardcoded */
641-
.per_user_policy = 0,
642-
.usage = PSA_KEY_USAGE_VERIFY_HASH,
643-
};
644-
645-
policy_table[idx] = policy;
646-
}
677+
for (uint32_t i = 0; i < MCUBOOT_IMAGE_NUMBER; i++) {
678+
for (uint32_t j = 0; j < MAX_KEYS_PER_IMAGE; j++) {
679+
tfm_plat_builtin_key_policy_t policy = {
680+
.per_user_policy = 0,
681+
.usage = PSA_KEY_USAGE_VERIFY_HASH,
682+
};
647683

684+
policy.key_id = get_key_id(i,j);
685+
policy_table[i][j] = policy;
686+
}
687+
}
648688
policy_table_is_initalized = true;
649689
}
650690

651-
*policy_ptr = &policy_table[0];
652-
return MCUBOOT_IMAGE_NUMBER;
653-
#else
654-
*policy_ptr = NULL;
655-
return 0;
656-
#endif
691+
*policy_ptr = &policy_table[0][0];
692+
return MCUBOOT_IMAGE_NUMBER * MAX_KEYS_PER_IMAGE;
693+
657694
}
658695

659696
/* The descriptor table is built dynamically at runtime to allow for an arbitrary
660697
* number of MCUBOOT_IMAGE_NUMBER entries, without hardcoding at build time
661698
*/
662699
size_t tfm_plat_builtin_key_get_desc_table_ptr(const tfm_plat_builtin_key_descriptor_t *desc_ptr[])
663700
{
664-
#if defined(MCUBOOT_BUILTIN_KEY)
665-
static tfm_plat_builtin_key_descriptor_t descriptor_table[MCUBOOT_IMAGE_NUMBER];
701+
static tfm_plat_builtin_key_descriptor_t descriptor_table[MCUBOOT_IMAGE_NUMBER][MAX_KEYS_PER_IMAGE];
666702
static bool descriptor_table_is_initalized = false;
667703

668704
if (!descriptor_table_is_initalized) {
669-
for (uint32_t idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) {
670-
tfm_plat_builtin_key_descriptor_t descriptor = {
671-
.key_id = idx + 1, /* ToDo: Relationship between key_id and image_idx is simply hardcoded */
672-
.slot_number = 0, /* Unused */
673-
.lifetime = PSA_KEY_LIFETIME_PERSISTENT,
674-
.loader_key_func = tfm_plat_get_bl2_rotpk,
675-
.loader_key_ctx = &descriptor_table[idx],
676-
};
677-
678-
descriptor_table[idx] = descriptor;
705+
for (uint32_t i = 0; i < MCUBOOT_IMAGE_NUMBER; i++) {
706+
for (uint32_t j = 0; j < MAX_KEYS_PER_IMAGE; j++) {
707+
tfm_plat_builtin_key_descriptor_t descriptor = {
708+
.slot_number = 0, /* Unused */
709+
.lifetime = PSA_KEY_LIFETIME_PERSISTENT,
710+
.loader_key_func = tfm_plat_get_bl2_rotpk,
711+
.loader_key_ctx = &descriptor_table[i][j],
712+
};
713+
descriptor.key_id = get_key_id(i,j);
714+
descriptor_table[i][j] = descriptor;
715+
}
679716
}
680717

681718
descriptor_table_is_initalized = true;
682719
}
683720

684-
*desc_ptr = &descriptor_table[0];
685-
return MCUBOOT_IMAGE_NUMBER;
686-
#else
721+
*desc_ptr = &descriptor_table[0][0];
722+
return MCUBOOT_IMAGE_NUMBER * MAX_KEYS_PER_IMAGE;
723+
}
724+
725+
int boot_verify_key_id_for_image(uint8_t image_index, int32_t key_id)
726+
{
727+
for (int i = 0; i < MAX_KEYS_PER_IMAGE; i++) {
728+
if (key_id == get_key_id(image_index, i)) {
729+
return 0;
730+
}
731+
}
732+
/* If the key id is not found in the image key id mapping, return -1 */
733+
return -1;
734+
}
735+
736+
#else /* MCUBOOT_BUILTIN_KEY */
737+
size_t tfm_plat_builtin_key_get_policy_table_ptr(const tfm_plat_builtin_key_policy_t *policy_ptr[])
738+
{
739+
*policy_ptr = NULL;
740+
return 0;
741+
}
742+
743+
size_t tfm_plat_builtin_key_get_desc_table_ptr(const tfm_plat_builtin_key_descriptor_t *desc_ptr[])
744+
{
687745
*desc_ptr = NULL;
688746
return 0;
689-
#endif
690747
}
691-
#endif /* MCUBOOT_USE_PSA_CRYPTO */
748+
#endif /* MCUBOOT_BUILTIN_KEY */

bl2/ext/mcuboot/mcuboot_default_config.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ set(MCUBOOT_SIGNATURE_TYPE "RSA-3072" CACHE STRING "Algori
5555
set(MCUBOOT_GENERATE_SIGNING_KEYPAIR OFF CACHE BOOL "Generate new keypair for signing and use that instead of MCUBOOT_KEY_S and MCUBOOT_KEY_NS")
5656
set(MCUBOOT_KEY_S "${CMAKE_SOURCE_DIR}/bl2/ext/mcuboot/root-${MCUBOOT_SIGNATURE_TYPE}.pem" CACHE FILEPATH "Path to key with which to sign secure binary")
5757
set(MCUBOOT_KEY_NS "${CMAKE_SOURCE_DIR}/bl2/ext/mcuboot/root-${MCUBOOT_SIGNATURE_TYPE}_1.pem" CACHE FILEPATH "Path to key with which to sign non-secure binary")
58+
set(TFM_S_KEY_ID 0 CACHE STRING "Key ID of the key used to sign the secure image")
59+
set(TFM_NS_KEY_ID 1 CACHE STRING "Key ID of the key used to sign the non-secure image")
60+
set(MCUBOOT_ROTPK_MAX_KEYS_PER_IMAGE 1 CACHE STRING "Maximum number of RoTPK keys per image to be used in BL2")
5861

5962
if (MCUBOOT_SIGNATURE_TYPE STREQUAL EC-P384)
6063
set(MCUBOOT_ROTPK_HASH_ALG SHA384 CACHE STRING "Algoritm to use to hash mcuboot ROTPKs")

bl2/ext/mcuboot/scripts/wrapper/wrapper.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
'the image manifest: full key or hash of the key.')
8989
@click.option('--psa-key-ids', multiple=True, type=int, required=False,
9090
help='List of integer key IDs for each signature.')
91-
@click.option('-k', '--key', metavar='filename')
91+
@click.option('-k', '--key', multiple=True, metavar='filename')
9292
@click.command(help='''Create a signed or unsigned image\n
9393
INFILE and OUTFILE are parsed as Intel HEX if the params have
9494
.hex extension, otherwise binary format is used''')
@@ -130,16 +130,23 @@ def wrap(key, align, version, header_size, pad_header, layout, pad, confirm,
130130
max_align=max_align)
131131

132132
img.load(infile)
133-
img.set_key_ids(psa_key_ids)
134-
key = imgtool.main.load_key(key) if key else None
133+
print (f"PSA key ids values: {psa_key_ids}")
134+
if psa_key_ids is not None:
135+
img.set_key_ids(psa_key_ids)
136+
137+
if key:
138+
keys = [imgtool.main.load_key(k) for k in key]
139+
else:
140+
keys = None
141+
135142
enckey = imgtool.main.load_key(encrypt) if encrypt else None
136143
if enckey and key:
137144
if (isinstance(key, imgtool.keys.RSA) and
138145
not isinstance(enckey, imgtool.keys.RSAPublic)):
139146
# FIXME
140147
raise click.UsageError("Signing and encryption must use the same "
141148
"type of key")
142-
img.create(key, public_key_format, enckey, dependencies, record_sw_type,
149+
img.create(keys, public_key_format, enckey, dependencies, record_sw_type,
143150
None, encrypt_keylen=int(encrypt_keylen))
144151
img.save(outfile, hex_addr)
145152

cmake/spe-CMakeLists.cmake

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ if(BL2 AND PLATFORM_DEFAULT_IMAGE_SIGNING)
184184
)
185185
186186
if(MCUBOOT_BUILTIN_KEY)
187-
set(TFM_NS_KEY_ID 1)
188187
set(wrapper_args ${wrapper_args} --psa-key-ids ${TFM_NS_KEY_ID})
189188
endif()
190189
@@ -234,6 +233,29 @@ if(BL2 AND PLATFORM_DEFAULT_IMAGE_SIGNING)
234233
--output ${CMAKE_BINARY_DIR}/bin/tfm_s_ns.bin
235234
)
236235
236+
set(wrapper_args
237+
--version ${MCUBOOT_IMAGE_VERSION_S}
238+
--layout ${CMAKE_CURRENT_SOURCE_DIR}/image_signing/layout_files/signing_layout_s_ns.o
239+
--key ${CMAKE_CURRENT_SOURCE_DIR}/image_signing/keys/image_s_signing_private_key.pem
240+
--public-key-format $<IF:$<BOOL:${MCUBOOT_HW_KEY}>,full,hash>
241+
--align ${MCUBOOT_ALIGN_VAL}
242+
--pad
243+
--pad-header
244+
-H ${BL2_HEADER_SIZE}
245+
-s ${MCUBOOT_SECURITY_COUNTER_S}
246+
-L ${MCUBOOT_ENC_KEY_LEN}
247+
$<$<STREQUAL:${MCUBOOT_UPGRADE_STRATEGY},OVERWRITE_ONLY>:--overwrite-only>
248+
$<$<BOOL:${MCUBOOT_CONFIRM_IMAGE}>:--confirm>
249+
$<$<BOOL:${MCUBOOT_ENC_IMAGES}>:-E${CMAKE_CURRENT_SOURCE_DIR}/image_signing/keys/image_enc_key.pem>
250+
$<$<BOOL:${MCUBOOT_MEASURED_BOOT}>:--measured-boot-record>
251+
${CMAKE_BINARY_DIR}/bin/tfm_s_ns.bin
252+
${CMAKE_BINARY_DIR}/tfm_s_ns_signed.bin
253+
)
254+
255+
if(MCUBOOT_BUILTIN_KEY)
256+
set(wrapper_args ${wrapper_args} --psa-key-ids ${TFM_S_KEY_ID})
257+
endif()
258+
237259
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/tfm_s_ns_signed.bin
238260
DEPENDS tfm_s_ns_bin ${CMAKE_BINARY_DIR}/bin/tfm_s_ns.bin
239261
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/image_signing/layout_files/signing_layout_s_ns.o
@@ -242,22 +264,7 @@ if(BL2 AND PLATFORM_DEFAULT_IMAGE_SIGNING)
242264
# sign the combined tfm_s_ns.bin file
243265
COMMAND ${Python3_EXECUTABLE}
244266
${CMAKE_CURRENT_SOURCE_DIR}/image_signing/scripts/wrapper/wrapper.py
245-
--version ${MCUBOOT_IMAGE_VERSION_S}
246-
--layout ${CMAKE_CURRENT_SOURCE_DIR}/image_signing/layout_files/signing_layout_s_ns.o
247-
--key ${CMAKE_CURRENT_SOURCE_DIR}/image_signing/keys/image_s_signing_private_key.pem
248-
--public-key-format $<IF:$<BOOL:${MCUBOOT_HW_KEY}>,full,hash>
249-
--align ${MCUBOOT_ALIGN_VAL}
250-
--pad
251-
--pad-header
252-
-H ${BL2_HEADER_SIZE}
253-
-s ${MCUBOOT_SECURITY_COUNTER_S}
254-
-L ${MCUBOOT_ENC_KEY_LEN}
255-
$<$<STREQUAL:${MCUBOOT_UPGRADE_STRATEGY},OVERWRITE_ONLY>:--overwrite-only>
256-
$<$<BOOL:${MCUBOOT_CONFIRM_IMAGE}>:--confirm>
257-
$<$<BOOL:${MCUBOOT_ENC_IMAGES}>:-E${CMAKE_CURRENT_SOURCE_DIR}/image_signing/keys/image_enc_key.pem>
258-
$<$<BOOL:${MCUBOOT_MEASURED_BOOT}>:--measured-boot-record>
259-
${CMAKE_BINARY_DIR}/bin/tfm_s_ns.bin
260-
${CMAKE_BINARY_DIR}/tfm_s_ns_signed.bin
267+
${wrapper_args}
261268
)
262269
endif()
263270
endif()

config/spe_config.cmake.in

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#-------------------------------------------------------------------------------
2-
# Copyright (c) 2023, Arm Limited. All rights reserved.
2+
# SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
33
#
44
# SPDX-License-Identifier: BSD-3-Clause
55
#
@@ -24,6 +24,8 @@ set(BL2 @BL2@)
2424
set(BL2_HEADER_SIZE @BL2_HEADER_SIZE@)
2525
set(BL2_TRAILER_SIZE @BL2_TRAILER_SIZE@)
2626
set(MCUBOOT_IMAGE_NUMBER @MCUBOOT_IMAGE_NUMBER@)
27+
set(TFM_S_KEY_ID @TFM_S_KEY_ID@)
28+
set(TFM_NS_KEY_ID @TFM_NS_KEY_ID@)
2729
set(MCUBOOT_CONFIRM_IMAGE @MCUBOOT_CONFIRM_IMAGE@)
2830
set(MCUBOOT_ENC_IMAGES @MCUBOOT_ENC_IMAGES@)
2931
set(MCUBOOT_ENC_KEY_LEN @MCUBOOT_ENC_KEY_LEN@)
@@ -35,6 +37,7 @@ set(MCUBOOT_S_IMAGE_MIN_VER @MCUBOOT_S_IMAGE_MIN_VER@)
3537

3638
set(MCUBOOT_MEASURED_BOOT @MCUBOOT_MEASURED_BOOT@)
3739
set(MCUBOOT_HW_KEY @MCUBOOT_HW_KEY@)
40+
set(MCUBOOT_BUILTIN_KEY @MCUBOOT_BUILTIN_KEY@)
3841

3942
set(MCUBOOT_SECURITY_COUNTER_S @MCUBOOT_SECURITY_COUNTER_S@)
4043
set(MCUBOOT_IMAGE_VERSION_S @MCUBOOT_IMAGE_VERSION_S@)

0 commit comments

Comments
 (0)