Skip to content

Commit 7f7a152

Browse files
Vge0rgecarlescufi
authored andcommitted
nrf_security: Add key policy for the Cracen builtin keys
Add logic which allows to specifically define who can use the builtin keys (IKG and KMU one) for Cracen when used with TF-M. This includes a list of specifically allowed users for the builtin keys and any other access is denied. This is only relevant for a TF-M enabled application since that is currently the only way to encode ownership in the key attributes. Ref: NCSDK-35736 Signed-off-by: Georgios Vasilakis <[email protected]>
1 parent 9af3a16 commit 7f7a152

File tree

4 files changed

+214
-0
lines changed

4 files changed

+214
-0
lines changed

subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ list(APPEND cracen_driver_sources
2323
${CMAKE_CURRENT_LIST_DIR}/src/prng_pool.c
2424
)
2525

26+
if(BUILD_INSIDE_TFM)
27+
list(APPEND cracen_driver_sources
28+
${CMAKE_CURRENT_LIST_DIR}/src/builtin_key_policy.c
29+
)
30+
endif()
31+
2632
# Include hardware cipher implementation for all devices except nRF54LM20A
2733
# nRF54LM20A uses only cracen_sw
2834
if(NOT CONFIG_PSA_NEED_CRACEN_MULTIPART_WORKAROUNDS)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#ifndef CRACEN_PSA_BUILTIN_KEY_POLICY_H
8+
#define CRACEN_PSA_BUILTIN_KEY_POLICY_H
9+
10+
#include <psa/crypto.h>
11+
#include <psa/crypto_values.h>
12+
13+
#if defined(__NRF_TFM__)
14+
15+
typedef struct {
16+
mbedtls_key_owner_id_t owner;
17+
psa_drv_slot_number_t key_slot;
18+
} cracen_builtin_ikg_key_policy_t;
19+
20+
typedef enum {
21+
KMU_ENTRY_SLOT_SINGLE,
22+
KMU_ENTRY_SLOT_RANGE,
23+
} cracen_kmu_entry_type_t;
24+
25+
/* When defining a range of KMU slots both the start and end slot numbers are inclusive. */
26+
typedef struct {
27+
mbedtls_key_owner_id_t owner;
28+
psa_drv_slot_number_t key_slot_start;
29+
psa_drv_slot_number_t key_slot_end;
30+
cracen_kmu_entry_type_t kmu_entry_type;
31+
} cracen_builtin_kmu_key_policy_t;
32+
33+
bool cracen_builtin_key_user_allowed(const psa_key_attributes_t *attributes);
34+
35+
#else
36+
37+
static inline bool cracen_builtin_key_user_allowed(const psa_key_attributes_t *attributes)
38+
{
39+
(void)attributes;
40+
return true;
41+
}
42+
43+
#endif /* __NRF_TFM__ */
44+
45+
#endif /* CRACEN_PSA_BUILTIN_KEY_POLICY_H */
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include "common.h"
8+
9+
#include <psa/crypto.h>
10+
#include <psa/crypto_values.h>
11+
#include <zephyr/sys/util.h>
12+
#include <stddef.h>
13+
#include <string.h>
14+
15+
#include <psa_manifest/pid.h>
16+
#include <tfm_builtin_key_ids.h>
17+
#include <cracen_psa_builtin_key_policy.h>
18+
#include <drivers/nrfx_utils.h>
19+
20+
#define MAPPED_TZ_NS_AGENT_DEFAULT_CLIENT_ID (-0x3c000000)
21+
22+
static const cracen_builtin_ikg_key_policy_t g_builtin_ikg_policy[] = {
23+
#ifdef TFM_SP_ITS
24+
{.owner = TFM_SP_ITS, .key_slot = TFM_BUILTIN_KEY_ID_HUK},
25+
#endif /* TFM_SP_ITS */
26+
#ifdef TFM_SP_PS
27+
{.owner = TFM_SP_PS, .key_slot = TFM_BUILTIN_KEY_ID_HUK},
28+
#endif /* TFM_SP_PS */
29+
#ifdef TFM_SP_INITIAL_ATTESTATION
30+
{.owner = TFM_SP_INITIAL_ATTESTATION, .key_slot = TFM_BUILTIN_KEY_ID_IAK}
31+
#endif /* TFM_SP_INITIAL_ATTESTATION */
32+
};
33+
34+
#ifdef PSA_NEED_CRACEN_KMU_DRIVER
35+
36+
static const cracen_builtin_kmu_key_policy_t g_builtin_kmu_policy[] = {
37+
/* 0x0 is used by libraries like the hw_unique_key library when manually generating psa
38+
* key_ids. Allow access to all slots for these libraries since they don't have the logic to
39+
* have an owner id and reside inside TF-M.
40+
*/
41+
{.owner = 0x0,
42+
.key_slot_start = 0,
43+
.key_slot_end = 255,
44+
.kmu_entry_type = KMU_ENTRY_SLOT_RANGE},
45+
#ifdef TFM_SP_ITS
46+
{.owner = TFM_SP_ITS,
47+
.key_slot_start = 0,
48+
.key_slot_end = 255,
49+
.kmu_entry_type = KMU_ENTRY_SLOT_RANGE},
50+
#endif /* TFM_SP_ITS */
51+
#ifdef TFM_SP_CRYPTO
52+
{.owner = TFM_SP_CRYPTO,
53+
.key_slot_start = 0,
54+
.key_slot_end = 255,
55+
.kmu_entry_type = KMU_ENTRY_SLOT_RANGE},
56+
#endif /* TFM_SP_CRYPTO */
57+
/* The docs have KMU slots >= 180 reserved so don't allow NS users to access them */
58+
{.owner = MAPPED_TZ_NS_AGENT_DEFAULT_CLIENT_ID,
59+
.key_slot_start = 0,
60+
.key_slot_end = 179,
61+
.kmu_entry_type = KMU_ENTRY_SLOT_RANGE}};
62+
63+
static bool cracen_builtin_kmu_user_allowed(mbedtls_key_owner_id_t owner,
64+
psa_drv_slot_number_t slot_number,
65+
const psa_key_attributes_t *attributes)
66+
{
67+
for (uint32_t i = 0; i < NRFX_ARRAY_SIZE(g_builtin_kmu_policy); i++) {
68+
69+
switch (g_builtin_kmu_policy[i].kmu_entry_type) {
70+
case KMU_ENTRY_SLOT_SINGLE:
71+
if (g_builtin_kmu_policy[i].owner == owner &&
72+
g_builtin_kmu_policy[i].key_slot_start == slot_number) {
73+
return true;
74+
}
75+
break;
76+
case KMU_ENTRY_SLOT_RANGE:
77+
if (g_builtin_kmu_policy[i].owner == owner &&
78+
(slot_number >= g_builtin_kmu_policy[i].key_slot_start &&
79+
slot_number <= g_builtin_kmu_policy[i].key_slot_end)) {
80+
return true;
81+
}
82+
break;
83+
default:
84+
break;
85+
}
86+
}
87+
88+
return false;
89+
}
90+
#endif /* PSA_NEED_CRACEN_KMU_DRIVER */
91+
92+
static bool cracen_builtin_ikg_user_allowed(mbedtls_key_owner_id_t owner,
93+
psa_drv_slot_number_t slot_number,
94+
const psa_key_attributes_t *attributes)
95+
{
96+
for (uint32_t i = 0; i < NRFX_ARRAY_SIZE(g_builtin_ikg_policy); i++) {
97+
if (g_builtin_ikg_policy[i].owner == owner &&
98+
g_builtin_ikg_policy[i].key_slot == slot_number) {
99+
return true;
100+
}
101+
}
102+
103+
return false;
104+
}
105+
106+
bool cracen_builtin_key_user_allowed(const psa_key_attributes_t *attributes)
107+
{
108+
mbedtls_key_owner_id_t owner = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(psa_get_key_id(attributes));
109+
psa_drv_slot_number_t slot_id;
110+
111+
if (PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)) ==
112+
PSA_KEY_LOCATION_CRACEN) {
113+
114+
slot_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(attributes));
115+
return cracen_builtin_ikg_user_allowed(owner, slot_id, attributes);
116+
}
117+
118+
#ifdef PSA_NEED_CRACEN_KMU_DRIVER
119+
if (PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)) ==
120+
PSA_KEY_LOCATION_CRACEN_KMU) {
121+
122+
slot_id = CRACEN_PSA_GET_KMU_SLOT(
123+
MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(attributes)));
124+
return cracen_builtin_kmu_user_allowed(owner, slot_id, attributes);
125+
}
126+
#endif /* PSA_NEED_CRACEN_KMU_DRIVER */
127+
128+
return true;
129+
}

subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <cracen_psa_montgomery.h>
1515
#include <cracen_psa_ikg.h>
1616
#include <cracen_psa_rsa_keygen.h>
17+
#include <cracen_psa_builtin_key_policy.h>
1718
#include <nrf_security_mutexes.h>
1819
#include "ecc.h"
1920
#include <silexpk/sxops/rsa.h>
@@ -894,6 +895,10 @@ psa_status_t cracen_export_public_key(const psa_key_attributes_t *attributes,
894895
return PSA_ERROR_INVALID_ARGUMENT;
895896
}
896897

898+
if (!cracen_builtin_key_user_allowed(attributes)) {
899+
return PSA_ERROR_NOT_PERMITTED;
900+
}
901+
897902
if (IS_ENABLED(PSA_NEED_CRACEN_KEY_TYPE_ECC_KEY_PAIR_EXPORT)) {
898903
if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
899904
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
945950
return PSA_ERROR_INVALID_ARGUMENT;
946951
}
947952

953+
if (!cracen_builtin_key_user_allowed(attributes)) {
954+
return PSA_ERROR_NOT_PERMITTED;
955+
}
956+
948957
psa_key_location_t location =
949958
PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));
950959
#ifdef PSA_NEED_CRACEN_KMU_DRIVER
@@ -1205,6 +1214,10 @@ psa_status_t cracen_generate_key(const psa_key_attributes_t *attributes, uint8_t
12051214
psa_key_location_t location =
12061215
PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));
12071216

1217+
if (!cracen_builtin_key_user_allowed(attributes)) {
1218+
return PSA_ERROR_NOT_PERMITTED;
1219+
}
1220+
12081221
#ifdef PSA_NEED_CRACEN_KMU_DRIVER
12091222
if (location == PSA_KEY_LOCATION_CRACEN_KMU) {
12101223
return generate_key_for_kmu(attributes, key_buffer, key_buffer_size,
@@ -1337,6 +1350,11 @@ psa_status_t cracen_get_builtin_key(psa_drv_slot_number_t slot_number,
13371350
* and the `lifetime` field of the attribute struct. We will fill all the other
13381351
* attributes, and update the `lifetime` field to be more specific.
13391352
*/
1353+
1354+
if (!cracen_builtin_key_user_allowed(attributes)) {
1355+
return PSA_ERROR_NOT_PERMITTED;
1356+
}
1357+
13401358
switch (slot_number) {
13411359
case CRACEN_BUILTIN_IDENTITY_KEY_ID:
13421360
case CRACEN_BUILTIN_MKEK_ID:
@@ -1394,6 +1412,10 @@ psa_status_t cracen_export_key(const psa_key_attributes_t *attributes, const uin
13941412
psa_key_location_t location =
13951413
PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));
13961414

1415+
if (!cracen_builtin_key_user_allowed(attributes)) {
1416+
return PSA_ERROR_NOT_PERMITTED;
1417+
}
1418+
13971419
if (location == PSA_KEY_LOCATION_CRACEN_KMU) {
13981420
/* The keys will already be in the key buffer as they got loaded their by a previous
13991421
* call to cracen_get_builtin_key or cached in the memory.
@@ -1442,6 +1464,10 @@ psa_status_t cracen_copy_key(psa_key_attributes_t *attributes, const uint8_t *so
14421464
size_t target_key_buffer_size, size_t *target_key_buffer_length)
14431465
{
14441466
#ifdef PSA_NEED_CRACEN_KMU_DRIVER
1467+
if (!cracen_builtin_key_user_allowed(attributes)) {
1468+
return PSA_ERROR_NOT_PERMITTED;
1469+
}
1470+
14451471
psa_key_location_t location =
14461472
PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));
14471473

@@ -1496,6 +1522,10 @@ psa_status_t cracen_copy_key(psa_key_attributes_t *attributes, const uint8_t *so
14961522
psa_status_t cracen_destroy_key(const psa_key_attributes_t *attributes)
14971523
{
14981524
#ifdef PSA_NEED_CRACEN_KMU_DRIVER
1525+
if (!cracen_builtin_key_user_allowed(attributes)) {
1526+
return PSA_ERROR_NOT_PERMITTED;
1527+
}
1528+
14991529
return cracen_kmu_destroy_key(attributes);
15001530
#endif
15011531

@@ -1508,6 +1538,10 @@ psa_status_t cracen_derive_key(const psa_key_attributes_t *attributes, const uin
15081538
{
15091539
psa_key_type_t key_type = psa_get_key_type(attributes);
15101540

1541+
if (!cracen_builtin_key_user_allowed(attributes)) {
1542+
return PSA_ERROR_NOT_PERMITTED;
1543+
}
1544+
15111545
if (PSA_KEY_TYPE_IS_SPAKE2P_KEY_PAIR(key_type) && IS_ENABLED(PSA_NEED_CRACEN_SPAKE2P)) {
15121546
return cracen_derive_spake2p_key(attributes, input, input_length, key, key_size,
15131547
key_length);

0 commit comments

Comments
 (0)