Skip to content

Conversation

@Vge0rge
Copy link
Contributor

@Vge0rge Vge0rge commented Nov 6, 2025

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

Copilot AI review requested due to automatic review settings November 6, 2025 12:21
@Vge0rge Vge0rge requested review from a team as code owners November 6, 2025 12:21
@NordicBuilder NordicBuilder added the changelog-entry-required Update changelog before merge. Remove label if entry is not needed or already added. label Nov 6, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds access control policies for Cracen builtin keys (IKG and KMU) when used with TF-M, restricting key access to specifically allowed users based on owner ID encoded in key attributes.

Key changes:

  • Implements a policy framework with user-to-key-slot mappings for both IKG and KMU builtin keys
  • Adds permission checks across all key management operations to enforce the policy
  • Provides no-op implementation when TF-M is not enabled

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
cracen_builtin_key_policy.c New file implementing policy enforcement logic with allowlists for IKG and KMU keys
cracen_psa_builtin_key_policy.h New header defining policy data structures and the permission check API
key_management.c Adds permission checks to all key management functions
cracen_psa.h Removes unused TF-M header include
cracenpsa.cmake Adds new policy source file to build (duplicated entry)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@NordicBuilder
Copy link
Contributor

NordicBuilder commented Nov 6, 2025

CI Information

To view the history of this post, click the 'edited' button above
Build number: 5

Inputs:

Sources:

sdk-nrf: PR head: 59a9b82de74b9aeb8922a35cf2b5ace49b76ac25

more details

sdk-nrf:

PR head: 59a9b82de74b9aeb8922a35cf2b5ace49b76ac25
merge base: 4a5e29492e78ad8ae5da7e0ad26ec59db2afa25d
target head (main): 9e14b6e4b8036bb723223fb91d1454811bfc1ef4
Diff

Github labels

Enabled Name Description
ci-disabled Disable the ci execution
ci-all-test Run all of ci, no test spec filtering will be done
ci-force-downstream Force execution of downstream even if twister fails
ci-run-twister Force run twister
ci-run-zephyr-twister Force run zephyr twister
List of changed files detected by CI (5)
subsys
│  ├── nrf_security
│  │  ├── src
│  │  │  ├── drivers
│  │  │  │  ├── cracen
│  │  │  │  │  ├── cracenpsa
│  │  │  │  │  │  ├── cracenpsa.cmake
│  │  │  │  │  │  ├── include
│  │  │  │  │  │  │  ├── cracen_psa.h
│  │  │  │  │  │  │  │ cracen_psa_builtin_key_policy.h
│  │  │  │  │  │  ├── src
│  │  │  │  │  │  │  ├── cracen_builtin_key_policy.c
│  │  │  │  │  │  │  │ key_management.c

Outputs:

Toolchain

Version: df3cc9d822
Build docker image: docker-dtr.nordicsemi.no/sw-production/ncs-build:df3cc9d822_e595b21c39

Test Spec & Results: ✅ Success; ❌ Failure; 🟠 Queued; 🟡 Progress; ◻️ Skipped; ⚠️ Quarantine

  • ◻️ Toolchain - Skipped: existing toolchain is used
  • ✅ Build twister
    • sdk-nrf test count: 2302
  • ❌ Integration tests
    • ✅ test_ble_nrf_config
    • ✅ test-fw-nrfconnect-chip
    • ❌ test-fw-nrfconnect-nrf_crypto
    • ✅ test-fw-nrfconnect-rs
    • ✅ test-fw-nrfconnect-tfm
    • ✅ test-sdk-find-my
    • ✅ test-sdk-mcuboot
    • ✅ test-sdk-dfu
    • ⚠️ test-fw-nrfconnect-nrf-iot_cloud
Disabled integration tests
    • test-fw-nrfconnect-nrf_lrcs_positioning
    • desktop52_verification
    • test-fw-nrfconnect-apps
    • test-fw-nrfconnect-ble_mesh
    • test-fw-nrfconnect-ble_samples
    • test-fw-nrfconnect-fem
    • test-fw-nrfconnect-nfc
    • test-fw-nrfconnect-nrf-iot_libmodem-nrf
    • test-fw-nrfconnect-nrf-iot_lwm2m
    • test-fw-nrfconnect-nrf-iot_samples
    • test-fw-nrfconnect-nrf-iot_thingy91
    • test-fw-nrfconnect-nrf-iot_zephyr_lwm2m
    • test-fw-nrfconnect-ps-main
    • test-fw-nrfconnect-rpc
    • test-fw-nrfconnect-thread-main
    • test-low-level
    • test-sdk-audio
    • test-sdk-wifi
    • test-secdom-samples-public

Note: This message is automatically posted and updated by the CI

Copilot AI review requested due to automatic review settings November 6, 2025 14:19
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings November 6, 2025 14:21
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 <georgios.vasilakis@nordicsemi.no>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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)) {
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

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

The logic here always returns false if the IKG check fails, but should return true if the check passes to allow the key operation. The early return on line 117 prevents the function from returning true when access is allowed for IKG keys. This should be: if (cracen_builtin_ikg_user_allowed(owner, slot_id, attributes)) { return true; }

Suggested change
if (!cracen_builtin_ikg_user_allowed(owner, slot_id, attributes)) {
if (cracen_builtin_ikg_user_allowed(owner, slot_id, attributes)) {
return true;
} else {

Copilot uses AI. Check for mistakes.
Comment on lines +125 to +129
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;
}
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

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

The logic here always returns false if the KMU check fails, but should return true if the check passes. The early return on line 128 prevents the function from returning true when access is allowed for KMU keys. This should be: if (cracen_builtin_kmu_user_allowed(owner, slot_id, attributes)) { return true; }

Copilot uses AI. Check for mistakes.
The tfm_builtin_key_loader.h defines the symbol:
TFM_BUILTIN_KEY_LOADER_KEY_LOCATION which is also
defined in the tfm_builtin_key_ids.h when Cracen
is enabled. To avoid this remove including the
default key loader and only keep the Cracen one.

Signed-off-by: Georgios Vasilakis <georgios.vasilakis@nordicsemi.no>
@Vge0rge Vge0rge force-pushed the protect_builtin_keys branch from 1849194 to 59a9b82 Compare November 6, 2025 14:23
Comment on lines +14 to +15
#include "psa_manifest/pid.h"
#include "tfm_builtin_key_ids.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

use angle brackets

Comment on lines +7 to +8
#ifndef CRACEN_BUILTIN_KEY_POLICY_H
#define CRACEN_BUILTIN_KEY_POLICY_H
Copy link
Contributor

Choose a reason for hiding this comment

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

header guard mismatch

Copy link
Contributor

Choose a reason for hiding this comment

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

Don't call this source file cracen to follow convention in this directory?

#ifndef CRACEN_BUILTIN_KEY_POLICY_H
#define CRACEN_BUILTIN_KEY_POLICY_H

#include "common.h"
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
#include "common.h"
#include <common.h>

#ifndef CRACEN_BUILTIN_KEY_POLICY_H
#define CRACEN_BUILTIN_KEY_POLICY_H

#include "common.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this even including?

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;
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems to me this field is not actually useful and we could just do with key_slot_start and key_slot_end alone? For the KMU_ENTRY_SLOT_SINGLE case you would just have key_slot_start == key_slot_end.

Comment on lines +109 to +110
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;
Copy link
Contributor

Choose a reason for hiding this comment

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

We could also have a variable which holds MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(attributes)) to avoid repetition.

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)) ==
Copy link
Contributor

Choose a reason for hiding this comment

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

Use a switch instead?

Comment on lines +116 to +118
if (!cracen_builtin_ikg_user_allowed(owner, slot_id, attributes)) {
return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

How about just

Suggested change
if (!cracen_builtin_ikg_user_allowed(owner, slot_id, attributes)) {
return false;
}
return cracen_builtin_ikg_user_allowed(owner, slot_id, attributes)

?

Comment on lines +98 to +99
if (g_builtin_ikg_policy[i].user == owner &&
g_builtin_ikg_policy[i].key_slot == slot_number) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Terminology is not aligned (user/owner, key_slot/slot_number). Maybe align?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-entry-required Update changelog before merge. Remove label if entry is not needed or already added.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants