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 */
631671size_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 */
662699size_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 */
0 commit comments