Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nrf_security: cracen: make IKG seed KMU slot configurable #17381

Merged
merged 3 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions doc/nrf/releases_and_maturity/migration/migration_guide_2.8.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,15 @@ SUIT DFU for nRF54H20
Nordic Secure Immutable Bootloader (NSIB, B0, or B0n)
-----------------------------------------------------

Custom printing has been dropped in favor of using the logging subsystem, with output printed out to the default logging device.
The ``CONFIG_SECURE_BOOT_DEBUG`` Kconfig option has been removed.
To disable logging in B0 or B0n, set the :kconfig:option:`CONFIG_LOG` option to ``n``.
To send logs over RTT instead of UART, apply the following settings:
.. toggle::

Custom printing has been dropped in favor of using the logging subsystem, with output printed out to the default logging device.
tomi-font marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Custom printing has been dropped in favor of using the logging subsystem, with output printed out to the default logging device.
Custom printing is replaced by the logging subsystem, with output printed out to the default logging device.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not something I wrote. All I did here was add the toggle...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was reviewed and approved by Anna in #17079

The ``CONFIG_SECURE_BOOT_DEBUG`` Kconfig option has been removed.
To disable logging in B0 or B0n, set the :kconfig:option:`CONFIG_LOG` option to ``n``.
To send logs over RTT instead of UART, apply the following settings:

* Enable the :kconfig:option:`CONFIG_USE_SEGGER_RTT` and :kconfig:option:`CONFIG_RTT_CONSOLE` Kconfig options.
* Disable the :kconfig:option:`CONFIG_UART_CONSOLE` and :kconfig:option:`CONFIG_SERIAL` Kconfig options.
* Enable the :kconfig:option:`CONFIG_USE_SEGGER_RTT` and :kconfig:option:`CONFIG_RTT_CONSOLE` Kconfig options.
* Disable the :kconfig:option:`CONFIG_UART_CONSOLE` and :kconfig:option:`CONFIG_SERIAL` Kconfig options.
Comment on lines +95 to +96
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why these two got indented?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I put everything in here under a toggle, so everything needs to be indented one level more.


Libraries
=========
Expand Down Expand Up @@ -120,6 +122,13 @@ AT command parser

* The :c:func:`at_parser_cmd_type_get` has been renamed to :c:func:`at_parser_at_cmd_type_get`.

nRF Security
------------

.. toggle::

* The ``CONFIG_CRACEN_LOAD_KMU_SEED`` Kconfig option was renamed to :kconfig:option:`CONFIG_CRACEN_IKG_SEED_LOAD`.

.. _migration_2.8_recommended:

Recommended changes
Expand Down Expand Up @@ -359,4 +368,6 @@ This section provides detailed lists of changes by :ref:`protocol <protocols>`.
Bluetooth® LE
-------------

* To use the Zephyr Bluetooth LE Controller, use the :ref:`bt-ll-sw-split <zephyr:snippet-bt-ll-sw-split>` snippet (see :ref:`app_build_snippets`).
.. toggle::

* To use the Zephyr Bluetooth LE Controller, use the :ref:`bt-ll-sw-split <zephyr:snippet-bt-ll-sw-split>` snippet (see :ref:`app_build_snippets`).
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Developing with PMICs
Security
========

|no_changes_yet_note|
* The :kconfig:option:`CONFIG_CRACEN_IKG_SEED_KMU_SLOT` Kconfig option was added to allow customization of the KMU slot used to store CRACEN's Internal Key Generator (IKG) seed.

Protocols
=========
Expand Down
20 changes: 12 additions & 8 deletions lib/hw_unique_key/hw_unique_key_cracen.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ int hw_unique_key_derive_key(enum hw_unique_key_slot key_slot, const uint8_t *co

bool hw_unique_key_are_any_written(void)
{

psa_key_lifetime_t lifetime;
psa_drv_slot_number_t slot_number;
mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make(
0, PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_SEED, 0));
mbedtls_svc_key_id_t key_id;

key_id = mbedtls_svc_key_id_make(0, PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(
KMU_METADATA_SCHEME_SEED,
CONFIG_CRACEN_IKG_SEED_KMU_SLOT));
return cracen_kmu_get_key_slot(key_id, &lifetime, &slot_number) == PSA_SUCCESS;
}

Expand All @@ -83,11 +85,12 @@ int hw_unique_key_write(enum hw_unique_key_slot key_slot, const uint8_t *key)

psa_set_key_id(&seed_attr,
mbedtls_svc_key_id_make(0, PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(
CRACEN_KMU_KEY_USAGE_SCHEME_SEED, 0)));
KMU_METADATA_SCHEME_SEED,
CONFIG_CRACEN_IKG_SEED_KMU_SLOT)));
psa_set_key_type(&seed_attr, PSA_KEY_TYPE_RAW_DATA);
psa_set_key_lifetime(&seed_attr,
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_DEFAULT, PSA_KEY_LOCATION_CRACEN_KMU));
psa_set_key_lifetime(&seed_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_DEFAULT,
PSA_KEY_LOCATION_CRACEN_KMU));

status = cracen_import_key(&seed_attr, key, HUK_SIZE_BYTES, opaque_buffer,
sizeof(opaque_buffer), &outlen, &key_bits);
Expand All @@ -102,6 +105,7 @@ int hw_unique_key_write(enum hw_unique_key_slot key_slot, const uint8_t *key)

return HW_UNIQUE_KEY_SUCCESS;
}

int hw_unique_key_write_random(void)
{
psa_status_t status;
Expand All @@ -112,7 +116,7 @@ int hw_unique_key_write_random(void)
return -HW_UNIQUE_KEY_ERR_GENERATION_FAILED;
}

return hw_unique_key_write(0, random_data);
return hw_unique_key_write(/* unused */ -1, random_data);
}

bool hw_unique_key_is_written(enum hw_unique_key_slot key_slot)
Expand Down
18 changes: 13 additions & 5 deletions subsys/nrf_security/src/drivers/cracen/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,26 @@ config CRACEN_LIB_KMU
help
The CRACEN KMU library.

config CRACEN_LOAD_KMU_SEED
bool
prompt "Load the CRACEN IKG seed"
config CRACEN_IKG_SEED_LOAD
bool "Load the CRACEN IKG seed"
depends on CRACEN_LIB_KMU
default y
help
Configuration to load a The CRACEN IKG seed value from KMU.
The KMU seed is used to give support for key derived from IKG.
The IKG seed is used to derive the keys in the IKG.
If there is no seed in KMU, it is expected to be generated.
Note that this is not required to be used if a bootloader is loading
KMU seed.

config CRACEN_IKG_SEED_KMU_SLOT
int "KMU slot of the CRACEN IKG seed"
range 0 183
default 183
help
The CRACEN IKG seed spans over 3 KMU slots:
the one defined here and the two subsequent ones.
This defines the KMU slot (along with the two following it) to which
the IKG seed is provisioned and that is pushed when loading the IKG seed.

rsource 'psa_driver.Kconfig'

endif # PSA_CRYPTO_DRIVER_CRACEN
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ struct kmu_src_t {
/** Revocation policy. */
uint32_t rpolicy;
/** 32-bit destination address. Cannot point to SICR and must be on a
* 64-bit boundary.
* 128-bit boundary.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess here we can say that is 64 bit boundary for the pdk and 128 for the dk, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect the alignment requirement to be 128 bits starting from now, so that's why I only mentioned that. And anyway support for PDK will be removed soon.

*/
uint64_t *dest;
uint8_t *dest;
/** 32 bits of any clear-text metadata that belongs with the key slot.
*/
uint32_t metadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,26 @@ typedef uint64_t psa_drv_slot_number_t;
/* Retrieve KMU slot number for PSA key id. */
#define CRACEN_PSA_GET_KMU_SLOT(key_id) ((key_id)&0xff)

#define CRACEN_KMU_KEY_USAGE_SCHEME_PROTECTED 0
#define CRACEN_KMU_KEY_USAGE_SCHEME_SEED 1
#define CRACEN_KMU_KEY_USAGE_SCHEME_ENCRYPTED 2
#define CRACEN_KMU_KEY_USAGE_SCHEME_RAW 3
enum kmu_metadata_key_usage_scheme {
/**
* These keys can only be pushed to CRACEN's protected RAM.
* The keys are not encrypted. Only AES supported.
*/
KMU_METADATA_SCHEME_PROTECTED,
/**
* CRACEN's IKG seed uses 3 key slots. Pushed to the seed register.
*/
KMU_METADATA_SCHEME_SEED,
/**
* These keys are stored in encrypted form. They will be decrypted
* to @ref kmu_push_area for usage.
*/
KMU_METADATA_SCHEME_ENCRYPTED,
/**
* These keys are not encrypted. Pushed to @ref kmu_push_area.
*/
KMU_METADATA_SCHEME_RAW
};

/**
* @brief Retrieves the slot number for a given key handle.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -659,9 +659,11 @@ int cracen_signature_get_rsa_key(struct si_rsa_key *rsa, bool extract_pubkey, bo

int cracen_prepare_ik_key(const uint8_t *user_data)
{
#ifdef CONFIG_CRACEN_LOAD_KMU_SEED
#ifdef CONFIG_CRACEN_IKG_SEED_LOAD
if (!nrf_cracen_seedram_lock_check(NRF_CRACEN)) {
if (lib_kmu_push_slot(0) || lib_kmu_push_slot(1) || lib_kmu_push_slot(2)) {
if (lib_kmu_push_slot(CONFIG_CRACEN_IKG_SEED_KMU_SLOT + 0) ||
lib_kmu_push_slot(CONFIG_CRACEN_IKG_SEED_KMU_SLOT + 1) ||
lib_kmu_push_slot(CONFIG_CRACEN_IKG_SEED_KMU_SLOT + 2)) {
return SX_ERR_INVALID_KEYREF;
}
nrf_cracen_seedram_lock_enable_set(NRF_CRACEN, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void cracen_acquire(void)
CRACEN_ENABLE_RNG_Msk |
CRACEN_ENABLE_PKEIKG_Msk);
irq_enable(CRACEN_IRQn);
LOG_DBG_MSG("Power on CRACEN.");
LOG_DBG_MSG("Powered on CRACEN.");
}

nrf_security_mutex_unlock(cracen_mutex);
Expand Down
35 changes: 17 additions & 18 deletions subsys/nrf_security/src/drivers/cracen/cracenpsa/src/kmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#include <sxsymcrypt/internal.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys/__assert.h>

#include "cracen_psa.h"
#include <hw_unique_key.h>
#include <cracen_psa.h>
#include "common.h"
#include "kmu.h"

Expand Down Expand Up @@ -254,7 +254,7 @@ static bool can_sign(const psa_key_attributes_t *key_attr)
*
* @return psa_status_t
*/
static psa_status_t verify_provisioning_state(void)
static psa_status_t clean_up_unfinished_provisioning(void)
{
uint32_t data;
int st = lib_kmu_read_metadata(PROVISIONING_SLOT, &data);
Expand Down Expand Up @@ -290,7 +290,7 @@ static psa_status_t verify_provisioning_state(void)
* @param num_slots
* @return psa_status_t
*/
psa_status_t set_provisioning_in_progress(uint32_t slot_id, uint32_t num_slots)
static psa_status_t set_provisioning_in_progress(uint32_t slot_id, uint32_t num_slots)
{
struct kmu_src_t kmu_desc = {};

Expand All @@ -312,7 +312,7 @@ psa_status_t set_provisioning_in_progress(uint32_t slot_id, uint32_t num_slots)
* @param num_slots
* @return psa_status_t
*/
psa_status_t end_provisioning(uint32_t slot_id, uint32_t num_slots)
static psa_status_t end_provisioning(uint32_t slot_id, uint32_t num_slots)
{
if (lib_kmu_revoke_slot(PROVISIONING_SLOT) != LIB_KMU_SUCCESS) {
return PSA_ERROR_HARDWARE_FAILURE;
Expand Down Expand Up @@ -341,14 +341,15 @@ psa_status_t cracen_kmu_destroy_key(const psa_key_attributes_t *attributes)
if (status != PSA_SUCCESS) {
return status;
}
/* Verify will clear related key slots. */
return verify_provisioning_state();
/* This will revoke the related key slots. */
return clean_up_unfinished_provisioning();
}

return PSA_ERROR_DOES_NOT_EXIST;
}

psa_status_t convert_to_psa_attributes(kmu_metadata *metadata, psa_key_attributes_t *key_attr)
static psa_status_t convert_to_psa_attributes(kmu_metadata *metadata,
psa_key_attributes_t *key_attr)
{
psa_key_persistence_t key_persistence;

Expand All @@ -375,7 +376,7 @@ psa_status_t convert_to_psa_attributes(kmu_metadata *metadata, psa_key_attribute

if (metadata->key_usage_scheme == KMU_METADATA_SCHEME_SEED) {
psa_set_key_type(key_attr, PSA_KEY_TYPE_RAW_DATA);
psa_set_key_bits(key_attr, 384);
psa_set_key_bits(key_attr, PSA_BYTES_TO_BITS(HUK_SIZE_BYTES));
return PSA_SUCCESS;
}

Expand Down Expand Up @@ -485,8 +486,6 @@ psa_status_t convert_to_psa_attributes(kmu_metadata *metadata, psa_key_attribute
return PSA_ERROR_CORRUPTION_DETECTED;
}
break;
case KMU_METADATA_SCHEME_SEED:
return PSA_ERROR_NOT_PERMITTED;
}

return PSA_SUCCESS;
Expand Down Expand Up @@ -688,7 +687,7 @@ psa_status_t cracen_kmu_provision(const psa_key_attributes_t *key_attr, int slot
uint8_t encrypted_workmem[CRACEN_KMU_SLOT_KEY_SIZE * 4] = {};
size_t encrypted_outlen = 0;

psa_status_t status = verify_provisioning_state();
psa_status_t status = clean_up_unfinished_provisioning();

if (status != PSA_SUCCESS) {
return status;
Expand Down Expand Up @@ -716,7 +715,7 @@ psa_status_t cracen_kmu_provision(const psa_key_attributes_t *key_attr, int slot
break;
case KMU_METADATA_SCHEME_SEED:
push_address = (uint8_t *)NRF_CRACEN->SEED;
if (key_buffer_size != 16 * 3) {
if (key_buffer_size != HUK_SIZE_BYTES) {
return PSA_ERROR_INVALID_ARGUMENT;
}
break;
Expand All @@ -740,8 +739,8 @@ psa_status_t cracen_kmu_provision(const psa_key_attributes_t *key_attr, int slot
}

/* Verify that required slots are empty */
size_t num_slots = (MAX(encrypted_outlen, key_buffer_size) + CRACEN_KMU_SLOT_KEY_SIZE - 1) /
CRACEN_KMU_SLOT_KEY_SIZE;
const size_t num_slots = DIV_ROUND_UP(MAX(encrypted_outlen, key_buffer_size),
CRACEN_KMU_SLOT_KEY_SIZE);

for (size_t i = 0; i < num_slots; i++) {
if (!lib_kmu_is_slot_empty(slot_id + i)) {
Expand All @@ -760,7 +759,7 @@ psa_status_t cracen_kmu_provision(const psa_key_attributes_t *key_attr, int slot
struct kmu_src_t kmu_desc = {};

for (size_t i = 0; i < num_slots; i++) {
kmu_desc.dest = (uint64_t *)(push_address + (CRACEN_KMU_SLOT_KEY_SIZE * i));
kmu_desc.dest = push_address + (CRACEN_KMU_SLOT_KEY_SIZE * i);
kmu_desc.metadata = UINT32_MAX;
if (i == 0) {
memcpy(&kmu_desc.metadata, &metadata, sizeof(metadata));
Expand All @@ -775,7 +774,7 @@ psa_status_t cracen_kmu_provision(const psa_key_attributes_t *key_attr, int slot
/* We've already verified that this slot empty, so it should not fail. */
status = PSA_ERROR_HARDWARE_FAILURE;

(void)verify_provisioning_state();
clean_up_unfinished_provisioning();
break;
}

Expand Down Expand Up @@ -856,7 +855,7 @@ psa_status_t cracen_kmu_get_builtin_key(psa_drv_slot_number_t slot_number,
return PSA_ERROR_DOES_NOT_EXIST;
}

psa_status_t status = verify_provisioning_state();
psa_status_t status = clean_up_unfinished_provisioning();

if (status != PSA_SUCCESS) {
return status;
Expand Down
23 changes: 1 addition & 22 deletions subsys/nrf_security/src/drivers/cracen/cracenpsa/src/kmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#pragma once

#include <stdint.h>
#include "cracen_psa.h"
#include <cracen_psa.h>

#define CRACEN_KMU_MAX_KEY_SIZE 32
#define CRACEN_KMU_SLOT_KEY_SIZE 16
Expand All @@ -27,27 +27,6 @@ typedef struct {
uint8_t slot_id; /* KMU slot number. */
} kmu_opaque_key_buffer;

enum kmu_metadata_key_usage_scheme {
/**
* These keys can only be pushed to Cracen's protected RAM.
* The keys are not encrypted. Only AES supported.
*/
KMU_METADATA_SCHEME_PROTECTED,
/**
* These keys use 3 key slots. Pushed to the seed register.
*/
KMU_METADATA_SCHEME_SEED,
/**
* These keys are stored in encrypted form. They will be decrypted
* to @ref kmu_push_area for usage.
*/
KMU_METADATA_SCHEME_ENCRYPTED,
/**
* These keys are not encrypted. Pushed to @ref kmu_push_area.
*/
KMU_METADATA_SCHEME_RAW
};

extern uint8_t kmu_push_area[64];

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ void lib_kmu_clear_all_events(void)
NRF_KMU_S->EVENTS_PROVISIONED = 0;
NRF_KMU_S->EVENTS_PUSHED = 0;
NRF_KMU_S->EVENTS_REVOKED = 0;
NRF_KMU_S->EVENTS_PUSHBLOCKED = 0;
}

static int trigger_task_and_wait_for_event_or_error(volatile uint32_t *task,
Expand Down Expand Up @@ -70,8 +71,12 @@ int lib_kmu_provision_slot(int slot_id, struct kmu_src_t *kmu_src)
return -LIB_KMU_NULL_PNT;
}

/* DEST must be on a 64-bit boundary */
__ASSERT(IS_PTR_ALIGNED(kmu_src->dest, uint64_t), "unaligned kmu_src->dest");
/* The DEST address must be 64-bit aligned on nrf54l15pdk.
* On nrf54l15dk, the alignment requirement changed to 128 bits.
*/
__ASSERT(IS_PTR_ALIGNED_BYTES(kmu_src->dest,
(IS_ENABLED(CONFIG_SOC_NRF54L15_ENGA_CPUAPP) ? 8 : 16)),
"DEST misaligned");

int result = 1;

Expand Down
Loading
Loading