diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake b/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake index 71e6e13324eb..5ad70d6ac3b2 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake @@ -23,6 +23,12 @@ list(APPEND cracen_driver_sources ${CMAKE_CURRENT_LIST_DIR}/src/prng_pool.c ) +if(BUILD_INSIDE_TFM) + list(APPEND cracen_driver_sources + ${CMAKE_CURRENT_LIST_DIR}/src/cracen_builtin_key_policy.c + ) +endif() + # Include hardware cipher implementation for all devices except nRF54LM20A # nRF54LM20A uses only cracen_sw if(NOT CONFIG_CRACEN_NEED_MULTIPART_WORKAROUNDS) diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h index fff3e1dc1c19..e68d849bfd0f 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h @@ -18,10 +18,6 @@ #include "cracen_psa_key_ids.h" #include "sxsymcrypt/keyref.h" -#ifdef __NRF_TFM__ -#include -#endif - /** * See "PSA Cryptography API" for documentation. */ diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_builtin_key_policy.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_builtin_key_policy.h new file mode 100644 index 000000000000..7b54df50155c --- /dev/null +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_builtin_key_policy.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef CRACEN_BUILTIN_KEY_POLICY_H +#define CRACEN_BUILTIN_KEY_POLICY_H + +#include "common.h" +#include +#include + +#if defined(__NRF_TFM__) + +typedef struct { + mbedtls_key_owner_id_t user; + psa_drv_slot_number_t key_slot; +} cracen_builtin_ikg_key_policy_t; + +typedef enum { + KMU_ENTRY_SLOT_SINGLE, + KMU_ENTRY_SLOT_RANGE, +} cracen_kmu_entry_type_t; + +/* When defining a range of KMU slots both the start and end slot numbers are inclusive. */ +typedef struct { + mbedtls_key_owner_id_t user; + psa_drv_slot_number_t key_slot_start; + psa_drv_slot_number_t key_slot_end; + cracen_kmu_entry_type_t kmu_entry_type; +} cracen_builtin_kmu_key_policy_t; + +bool cracen_builtin_key_user_allowed(const psa_key_attributes_t *attributes); + +#else + +static inline bool cracen_builtin_key_user_allowed(const psa_key_attributes_t *attributes) +{ + (void)attributes; + return true; +} + +#endif /* __NRF_TFM__ */ + +#endif /* CRACEN_BUILTIN_KEY_POLICY_H */ \ No newline at end of file diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen_builtin_key_policy.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen_builtin_key_policy.c new file mode 100644 index 000000000000..d9c912264b22 --- /dev/null +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen_builtin_key_policy.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "common.h" + +#include +#include +#include +#include + +#include "psa_manifest/pid.h" +#include "tfm_builtin_key_ids.h" +#include + +#define NUMBER_OF_ELEMENTS_OF(x) (sizeof(x) / sizeof(*(x))) + +#define MAPPED_TZ_NS_AGENT_DEFAULT_CLIENT_ID (-0x3c000000) + +const cracen_builtin_ikg_key_policy_t g_builtin_ikg_policy[] = { +#ifdef TFM_SP_ITS + {.user = TFM_SP_ITS, .key_slot = TFM_BUILTIN_KEY_ID_HUK}, +#endif /* TFM_SP_ITS */ +#ifdef TFM_SP_PS + {.user = TFM_SP_PS, .key_slot = TFM_BUILTIN_KEY_ID_HUK}, +#endif /* TFM_SP_PS */ +#ifdef TFM_SP_INITIAL_ATTESTATION + {.user = TFM_SP_INITIAL_ATTESTATION, .key_slot = TFM_BUILTIN_KEY_ID_IAK} +#endif /* TFM_SP_INITIAL_ATTESTATION */ +}; + +#ifdef PSA_NEED_CRACEN_KMU_DRIVER + +const cracen_builtin_kmu_key_policy_t g_builtin_kmu_policy[] = { + /* 0x0 is used by libraries like the hw_unique_key library when manually generating psa + * key_ids. Allow access to all slots for these libraries since they don't have the logic to + * have an owner id and reside inside TF-M. + */ + {.user = 0x0, + .key_slot_start = 0, + .key_slot_end = 255, + .kmu_entry_type = KMU_ENTRY_SLOT_RANGE}, +#ifdef TFM_SP_ITS + {.user = TFM_SP_ITS, + .key_slot_start = 0, + .key_slot_end = 255, + .kmu_entry_type = KMU_ENTRY_SLOT_RANGE}, +#endif /* TFM_SP_ITS */ +#ifdef TFM_SP_CRYPTO + {.user = TFM_SP_CRYPTO, + .key_slot_start = 0, + .key_slot_end = 255, + .kmu_entry_type = KMU_ENTRY_SLOT_RANGE}, +#endif /* TFM_SP_CRYPTO */ + /* The docs have KMU slots >= 180 reserved so don't allow NS users to access them */ + {.user = MAPPED_TZ_NS_AGENT_DEFAULT_CLIENT_ID, + .key_slot_start = 0, + .key_slot_end = 179, + .kmu_entry_type = KMU_ENTRY_SLOT_RANGE}}; + +static bool cracen_builtin_kmu_user_allowed(mbedtls_key_owner_id_t owner, + psa_drv_slot_number_t slot_number, + const psa_key_attributes_t *attributes) +{ + for (uint32_t i = 0; i < NUMBER_OF_ELEMENTS_OF(g_builtin_kmu_policy); i++) { + + switch (g_builtin_kmu_policy[i].kmu_entry_type) { + case KMU_ENTRY_SLOT_SINGLE: + if (g_builtin_kmu_policy[i].user == owner && + g_builtin_kmu_policy[i].key_slot_start == slot_number) { + return true; + } + break; + + case KMU_ENTRY_SLOT_RANGE: + if (g_builtin_kmu_policy[i].user == owner && + (slot_number >= g_builtin_kmu_policy[i].key_slot_start && + slot_number <= g_builtin_kmu_policy[i].key_slot_end)) { + return true; + } + break; + default: + break; + } + } + + return false; +} +#endif /* PSA_NEED_CRACEN_KMU_DRIVER */ + +static bool cracen_builtin_ikg_user_allowed(mbedtls_key_owner_id_t owner, + psa_drv_slot_number_t slot_number, + const psa_key_attributes_t *attributes) +{ + for (uint32_t i = 0; i < NUMBER_OF_ELEMENTS_OF(g_builtin_ikg_policy); i++) { + if (g_builtin_ikg_policy[i].user == owner && + g_builtin_ikg_policy[i].key_slot == slot_number) { + return true; + } + } + + return false; +} + +bool cracen_builtin_key_user_allowed(const psa_key_attributes_t *attributes) +{ + mbedtls_key_owner_id_t owner = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(psa_get_key_id(attributes)); + psa_drv_slot_number_t slot_id; + + if (PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)) == + PSA_KEY_LOCATION_CRACEN) { + + slot_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(attributes)); + if (!cracen_builtin_ikg_user_allowed(owner, slot_id, attributes)) { + return false; + } + } + +#ifdef PSA_NEED_CRACEN_KMU_DRIVER + if (PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)) == + PSA_KEY_LOCATION_CRACEN_KMU) { + + slot_id = CRACEN_PSA_GET_KMU_SLOT( + MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(attributes))); + if (!cracen_builtin_kmu_user_allowed(owner, slot_id, attributes)) { + return false; + } + } +#endif /* PSA_NEED_CRACEN_KMU_DRIVER */ + + return true; +} \ No newline at end of file diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c index ed8132bad7a2..535c2e3273c8 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "ecc.h" #include @@ -894,6 +895,10 @@ psa_status_t cracen_export_public_key(const psa_key_attributes_t *attributes, return PSA_ERROR_INVALID_ARGUMENT; } + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + if (IS_ENABLED(PSA_NEED_CRACEN_KEY_TYPE_ECC_KEY_PAIR_EXPORT)) { if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) { return export_ecc_public_key_from_keypair(attributes, key_buffer, @@ -945,6 +950,10 @@ psa_status_t cracen_import_key(const psa_key_attributes_t *attributes, const uin return PSA_ERROR_INVALID_ARGUMENT; } + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); #ifdef PSA_NEED_CRACEN_KMU_DRIVER @@ -1198,6 +1207,10 @@ psa_status_t cracen_generate_key(const psa_key_attributes_t *attributes, uint8_t psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + #ifdef PSA_NEED_CRACEN_KMU_DRIVER if (location == PSA_KEY_LOCATION_CRACEN_KMU) { return generate_key_for_kmu(attributes, key_buffer, key_buffer_size, @@ -1330,6 +1343,11 @@ psa_status_t cracen_get_builtin_key(psa_drv_slot_number_t slot_number, * and the `lifetime` field of the attribute struct. We will fill all the other * attributes, and update the `lifetime` field to be more specific. */ + + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + switch (slot_number) { case CRACEN_BUILTIN_IDENTITY_KEY_ID: case CRACEN_BUILTIN_MKEK_ID: @@ -1387,6 +1405,10 @@ psa_status_t cracen_export_key(const psa_key_attributes_t *attributes, const uin psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + if (location == PSA_KEY_LOCATION_CRACEN_KMU) { /* The keys will already be in the key buffer as they got loaded their by a previous * call to cracen_get_builtin_key or cached in the memory. @@ -1435,6 +1457,10 @@ psa_status_t cracen_copy_key(psa_key_attributes_t *attributes, const uint8_t *so size_t target_key_buffer_size, size_t *target_key_buffer_length) { #ifdef PSA_NEED_CRACEN_KMU_DRIVER + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); @@ -1489,6 +1515,10 @@ psa_status_t cracen_copy_key(psa_key_attributes_t *attributes, const uint8_t *so psa_status_t cracen_destroy_key(const psa_key_attributes_t *attributes) { #ifdef PSA_NEED_CRACEN_KMU_DRIVER + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + return cracen_kmu_destroy_key(attributes); #endif @@ -1501,6 +1531,10 @@ psa_status_t cracen_derive_key(const psa_key_attributes_t *attributes, const uin { psa_key_type_t key_type = psa_get_key_type(attributes); + if (!cracen_builtin_key_user_allowed(attributes)) { + return PSA_ERROR_NOT_PERMITTED; + } + if (PSA_KEY_TYPE_IS_SPAKE2P_KEY_PAIR(key_type) && IS_ENABLED(PSA_NEED_CRACEN_SPAKE2P)) { return cracen_derive_spake2p_key(attributes, input, input_length, key, key_size, key_length);