Skip to content

Commit 7e110e4

Browse files
tomi-fontendre-nordic
authored andcommitted
nrf_security: cracen: kmu: add slot blocking function
Plus some minor improvements. Signed-off-by: Tomi Fontanilles <[email protected]>
1 parent e63cfa8 commit 7e110e4

File tree

5 files changed

+145
-53
lines changed

5 files changed

+145
-53
lines changed

subsys/nrf_security/src/drivers/cracen/common/include/cracen/lib_kmu.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ int lib_kmu_provision_slot(int slot_id, struct kmu_src *kmu_src);
9292
*/
9393
int lib_kmu_push_slot(int slot_id);
9494

95+
/** @brief Block one or more consecutive KMU slots.
96+
*
97+
* @param[in] slot_id ID of the first KMU slot to block.
98+
* @param[in] slot_count Number of consecutive slots to block.
99+
*
100+
* @return LIB_KMU_SUCCESS If the operation was successful.
101+
* @return -LIB_KMU_ERROR If the operation returned an error.
102+
*
103+
* @note This uses the `PUSHBLOCK` task on devices that do not have the `BLOCK` one.
104+
*/
105+
int lib_kmu_block_slot_range(int slot_id, unsigned int slot_count);
106+
95107
/** @brief Revoke the KMU slot.
96108
*
97109
* @param[in] slot_id Slot id of the KMU slot.

subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_kmu.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,22 @@ enum cracen_kmu_metadata_key_usage_scheme {
5555
CRACEN_KMU_KEY_USAGE_SCHEME_RAW
5656
};
5757

58-
/**
59-
* @brief Retrieves the slot number for a given key handle.
58+
/** Retrieves the slot number for a given key handle.
6059
*
6160
* @param[in] key_id Key handler.
6261
* @param[out] lifetime Lifetime for key.
6362
* @param[out] slot_number The key's slot number.
64-
*
65-
* @return psa_status_t
6663
*/
6764
psa_status_t cracen_kmu_get_key_slot(mbedtls_svc_key_id_t key_id, psa_key_lifetime_t *lifetime,
6865
psa_drv_slot_number_t *slot_number);
6966

67+
/** Blocks a key in the KMU.
68+
*
69+
* @param[in] key_attr Attributes of the key to block.
70+
*
71+
* @note The underlying operation performed is a `BLOCK` on devices
72+
* that support it, and a `PUSHBLOCK` on those that don't.
73+
*/
74+
psa_status_t cracen_kmu_block(const psa_key_attributes_t *key_attr);
75+
7076
#endif /* CRACEN_PSA_KMU_H */

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

Lines changed: 88 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ static psa_status_t cracen_kmu_encrypt(const uint8_t *key, size_t key_length,
155155
encrypted_buffer_length);
156156

157157
if (status == PSA_SUCCESS) {
158-
*encrypted_buffer_length += 16;
158+
*encrypted_buffer_length += CRACEN_KMU_SLOT_KEY_SIZE;
159159
}
160160
return status;
161161
}
@@ -261,6 +261,13 @@ static psa_status_t read_primary_slot_metadata(unsigned int slot_id, kmu_metadat
261261
return PSA_SUCCESS;
262262
}
263263

264+
static psa_status_t get_kmu_slot_id_and_metadata(mbedtls_svc_key_id_t key_id,
265+
unsigned int *slot_id, kmu_metadata *metadata)
266+
{
267+
*slot_id = CRACEN_PSA_GET_KMU_SLOT(MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key_id));
268+
return read_primary_slot_metadata(*slot_id, metadata);
269+
}
270+
264271
static bool can_sign(const psa_key_attributes_t *key_attr)
265272
{
266273
return (psa_get_key_usage_flags(key_attr) & PSA_KEY_USAGE_SIGN_MESSAGE) ||
@@ -338,24 +345,66 @@ static psa_status_t end_provisioning(uint32_t slot_id, uint32_t num_slots)
338345
return PSA_SUCCESS;
339346
}
340347

348+
static psa_status_t get_kmu_slot_count(kmu_metadata metadata, const psa_key_attributes_t *key_attr,
349+
unsigned int *slot_count)
350+
{
351+
switch (metadata.size) {
352+
case METADATA_ALG_KEY_BITS_128:
353+
*slot_count = 1;
354+
break;
355+
case METADATA_ALG_KEY_BITS_192:
356+
case METADATA_ALG_KEY_BITS_255:
357+
case METADATA_ALG_KEY_BITS_256:
358+
if (psa_get_key_type(key_attr) ==
359+
PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) {
360+
*slot_count = 4;
361+
} else {
362+
*slot_count = 2;
363+
}
364+
break;
365+
case METADATA_ALG_KEY_BITS_384_SEED:
366+
*slot_count = 3;
367+
break;
368+
default:
369+
return PSA_ERROR_DATA_INVALID;
370+
}
371+
372+
if (metadata.key_usage_scheme == CRACEN_KMU_KEY_USAGE_SCHEME_ENCRYPTED) {
373+
*slot_count += 2; /* nonce + tag */
374+
}
375+
376+
return PSA_SUCCESS;
377+
}
378+
379+
static psa_status_t get_kmu_slot_id_and_count(const psa_key_attributes_t *key_attr,
380+
unsigned int *slot_id, unsigned int *slot_count)
381+
{
382+
kmu_metadata metadata;
383+
psa_status_t status;
384+
385+
status = get_kmu_slot_id_and_metadata(psa_get_key_id(key_attr), slot_id, &metadata);
386+
if (status != PSA_SUCCESS) {
387+
return status;
388+
}
389+
390+
return get_kmu_slot_count(metadata, key_attr, slot_count);
391+
}
392+
341393
psa_status_t cracen_kmu_destroy_key(const psa_key_attributes_t *attributes)
342394
{
343395
psa_key_location_t location =
344396
PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));
345397

346398
if (location == PSA_KEY_LOCATION_CRACEN_KMU) {
347-
uint32_t slot_id = CRACEN_PSA_GET_KMU_SLOT(
348-
MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(attributes)));
349-
size_t num_slots = DIV_ROUND_UP(PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)),
350-
CRACEN_KMU_SLOT_KEY_SIZE);
351399
psa_status_t status;
400+
unsigned int slot_id, slot_count;
352401

353-
if (CRACEN_PSA_GET_KEY_USAGE_SCHEME(MBEDTLS_SVC_KEY_ID_GET_KEY_ID(
354-
psa_get_key_id(attributes))) == CRACEN_KMU_KEY_USAGE_SCHEME_ENCRYPTED) {
355-
num_slots += 2;
402+
status = get_kmu_slot_id_and_count(attributes, &slot_id, &slot_count);
403+
if (status != PSA_SUCCESS) {
404+
return status;
356405
}
357406

358-
status = set_provisioning_in_progress(slot_id, num_slots);
407+
status = set_provisioning_in_progress(slot_id, slot_count);
359408
if (status != PSA_SUCCESS) {
360409
return status;
361410
}
@@ -522,8 +571,8 @@ static psa_status_t convert_to_psa_attributes(kmu_metadata *metadata,
522571
return PSA_SUCCESS;
523572
}
524573

525-
psa_status_t convert_from_psa_attributes(const psa_key_attributes_t *key_attr,
526-
kmu_metadata *metadata)
574+
static psa_status_t convert_from_psa_attributes(const psa_key_attributes_t *key_attr,
575+
kmu_metadata *metadata)
527576
{
528577
memset(metadata, 0, sizeof(*metadata));
529578
metadata->metadata_version = 0;
@@ -737,8 +786,6 @@ psa_status_t cracen_kmu_provision(const psa_key_attributes_t *key_attr, int slot
737786
*/
738787
uint8_t encrypted_workmem[CRACEN_KMU_SLOT_KEY_SIZE * 4] = {};
739788
#endif
740-
size_t encrypted_outlen = 0;
741-
742789
psa_status_t status = clean_up_unfinished_provisioning();
743790

744791
if (status != PSA_SUCCESS) {
@@ -788,19 +835,17 @@ psa_status_t cracen_kmu_provision(const psa_key_attributes_t *key_attr, int slot
788835
status = cracen_kmu_encrypt(encrypted_workmem + CRACEN_KMU_SLOT_KEY_SIZE,
789836
ROUND_UP(key_buffer_size, CRACEN_KMU_SLOT_KEY_SIZE),
790837
&metadata, encrypted_workmem, sizeof(encrypted_workmem),
791-
&encrypted_outlen);
838+
&key_buffer_size);
792839

793840
if (status != PSA_SUCCESS) {
794841
return status;
795842
}
796843
key_buffer = encrypted_workmem;
797-
key_buffer_size = encrypted_outlen;
798844
}
799845
#endif /* PSA_NEED_CRACEN_KMU_ENCRYPTED_KEYS */
800846

801847
/* Verify that required slots are empty */
802-
const size_t num_slots = DIV_ROUND_UP(MAX(encrypted_outlen, key_buffer_size),
803-
CRACEN_KMU_SLOT_KEY_SIZE);
848+
const size_t num_slots = DIV_ROUND_UP(key_buffer_size, CRACEN_KMU_SLOT_KEY_SIZE);
804849

805850
for (size_t i = 0; i < num_slots; i++) {
806851
if (!lib_kmu_is_slot_empty(slot_id + i)) {
@@ -853,12 +898,13 @@ psa_status_t cracen_kmu_provision(const psa_key_attributes_t *key_attr, int slot
853898
psa_status_t cracen_kmu_get_key_slot(mbedtls_svc_key_id_t key_id, psa_key_lifetime_t *lifetime,
854899
psa_drv_slot_number_t *slot_number)
855900
{
856-
unsigned int slot_id = CRACEN_PSA_GET_KMU_SLOT(MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key_id));
901+
psa_status_t status;
902+
unsigned int slot_id;
857903
kmu_metadata metadata;
858-
const psa_status_t ret = read_primary_slot_metadata(slot_id, &metadata);
859904

860-
if (ret != PSA_SUCCESS) {
861-
return ret;
905+
status = get_kmu_slot_id_and_metadata(key_id, &slot_id, &metadata);
906+
if (status != PSA_SUCCESS) {
907+
return status;
862908
}
863909

864910
psa_key_persistence_t read_only = metadata.rpolicy == LIB_KMU_REV_POLICY_ROTATING
@@ -872,6 +918,22 @@ psa_status_t cracen_kmu_get_key_slot(mbedtls_svc_key_id_t key_id, psa_key_lifeti
872918
return PSA_SUCCESS;
873919
}
874920

921+
psa_status_t cracen_kmu_block(const psa_key_attributes_t *key_attr)
922+
{
923+
psa_status_t status;
924+
unsigned int slot_id, slot_count;
925+
926+
status = get_kmu_slot_id_and_count(key_attr, &slot_id, &slot_count);
927+
if (status != PSA_SUCCESS) {
928+
return status;
929+
}
930+
931+
if (lib_kmu_block_slot_range(slot_id, slot_count) != LIB_KMU_SUCCESS) {
932+
return PSA_ERROR_GENERIC_ERROR;
933+
}
934+
return PSA_SUCCESS;
935+
}
936+
875937
static psa_status_t push_kmu_key_to_ram(uint8_t *key_buffer, size_t key_buffer_size)
876938
{
877939
if (key_buffer_size > sizeof(kmu_push_area)) {
@@ -931,32 +993,15 @@ psa_status_t cracen_kmu_get_builtin_key(psa_drv_slot_number_t slot_number,
931993
if (key_buffer_size >= opaque_key_size) {
932994
*key_buffer_length = opaque_key_size;
933995
kmu_opaque_key_buffer *key = (kmu_opaque_key_buffer *)key_buffer;
996+
unsigned int slot_count;
934997

935998
key->key_usage_scheme = metadata.key_usage_scheme;
936-
switch (metadata.size) {
937-
case METADATA_ALG_KEY_BITS_128:
938-
key->number_of_slots = 1;
939-
break;
940-
case METADATA_ALG_KEY_BITS_192:
941-
case METADATA_ALG_KEY_BITS_255:
942-
case METADATA_ALG_KEY_BITS_256:
943-
if (psa_get_key_type(attributes) ==
944-
PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) {
945-
key->number_of_slots = 4;
946-
} else {
947-
key->number_of_slots = 2;
948-
}
949-
break;
950-
case METADATA_ALG_KEY_BITS_384_SEED:
951-
key->number_of_slots = 3;
952-
break;
953-
default:
954-
return PSA_ERROR_DATA_INVALID;
955-
}
956999

957-
if (key->key_usage_scheme == CRACEN_KMU_KEY_USAGE_SCHEME_ENCRYPTED) {
958-
key->number_of_slots += 2;
1000+
status = get_kmu_slot_count(metadata, attributes, &slot_count);
1001+
if (status != PSA_SUCCESS) {
1002+
return status;
9591003
}
1004+
key->number_of_slots = slot_count;
9601005

9611006
key->slot_id = slot_number;
9621007
} else {

subsys/nrf_security/src/drivers/cracen/cracenpsa/src/kmu.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,18 @@ int cracen_kmu_clean_key(const uint8_t *user_data);
5050
*
5151
* If the key is available the key_buffer will be filled with a valid
5252
* instance of @ref kmu_opaque_key_buffer.
53-
*
54-
* @return psa_status_t
5553
*/
5654
psa_status_t cracen_kmu_get_builtin_key(psa_drv_slot_number_t slot_number,
5755
psa_key_attributes_t *attributes, uint8_t *key_buffer,
5856
size_t key_buffer_size, size_t *key_buffer_length);
5957

6058
/**
6159
* @brief Provision a key in the KMU.
62-
*
63-
* @return psa_status_t
6460
*/
6561
psa_status_t cracen_kmu_provision(const psa_key_attributes_t *key_attr, int slot_id,
6662
const uint8_t *key_buffer, size_t key_buffer_size);
6763

6864
/**
69-
* @brief Destroy PSA key stored in KMU.
70-
*
65+
* @brief Destroy a key stored in the KMU.
7166
*/
7267
psa_status_t cracen_kmu_destroy_key(const psa_key_attributes_t *attributes);

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,22 @@
1616

1717
#include <cracen/lib_kmu.h>
1818

19+
#ifdef KMU_TASKS_BLOCK_ResetValue
20+
#define HAS_BLOCK_TASK 1
21+
#endif
22+
1923
void lib_kmu_clear_all_events(void)
2024
{
2125
NRF_KMU_S->EVENTS_METADATAREAD = 0;
2226
NRF_KMU_S->EVENTS_ERROR = 0;
2327
NRF_KMU_S->EVENTS_PROVISIONED = 0;
2428
NRF_KMU_S->EVENTS_PUSHED = 0;
2529
NRF_KMU_S->EVENTS_REVOKED = 0;
30+
#if HAS_BLOCK_TASK
31+
NRF_KMU_S->EVENTS_BLOCKED = 0;
32+
#else
2633
NRF_KMU_S->EVENTS_PUSHBLOCKED = 0;
34+
#endif
2735
}
2836

2937
static int trigger_task_and_wait_for_event_or_error(volatile uint32_t *task,
@@ -109,6 +117,32 @@ int lib_kmu_push_slot(int slot_id)
109117
&(NRF_KMU_S->EVENTS_PUSHED));
110118
}
111119

120+
static int block_kmu_slot(int slot_id)
121+
{
122+
NRF_KMU_S->KEYSLOT = slot_id;
123+
124+
#if HAS_BLOCK_TASK
125+
return trigger_task_and_wait_for_event_or_error(&(NRF_KMU_S->TASKS_BLOCK),
126+
&(NRF_KMU_S->EVENTS_BLOCKED));
127+
#else
128+
return trigger_task_and_wait_for_event_or_error(&(NRF_KMU_S->TASKS_PUSHBLOCK),
129+
&(NRF_KMU_S->EVENTS_PUSHBLOCKED));
130+
#endif
131+
}
132+
133+
int lib_kmu_block_slot_range(int slot_id, unsigned int slot_count)
134+
{
135+
int ret;
136+
137+
for (unsigned int i = 0; i != slot_count; ++i) {
138+
ret = block_kmu_slot(slot_id + i);
139+
if (ret != LIB_KMU_SUCCESS) {
140+
return ret;
141+
}
142+
}
143+
return LIB_KMU_SUCCESS;
144+
}
145+
112146
int lib_kmu_revoke_slot(int slot_id)
113147
{
114148
#if !defined(__NRF_TFM__)

0 commit comments

Comments
 (0)