Skip to content

Commit

Permalink
[nrfconnect] Implement KMUKeyAllocator
Browse files Browse the repository at this point in the history
KMUKeyAllocator is used to overwrite PSAKeyAllocator for the
specific use-cases of KMU driver.

This feature is available only on the device which run Cracen.

Signed-off-by: Arkadiusz Balys <[email protected]>
  • Loading branch information
ArekBalysNordic committed Feb 5, 2025
1 parent 56a0278 commit fcdf98d
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 1 deletion.
1 change: 1 addition & 0 deletions config/nrfconnect/chip-module/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ endif()
if (CONFIG_CHIP_CRYPTO_PSA)
matter_add_gn_arg_string("chip_crypto" "psa")
matter_add_gn_arg_bool ("chip_crypto_psa_spake2p" CONFIG_PSA_WANT_ALG_SPAKE2P_MATTER)
matter_add_gn_arg_bool ("chip_use_cracen_kmu" CONFIG_CHIP_STORE_KEYS_IN_KMU)
endif()

if (BOARD STREQUAL "native_posix")
Expand Down
32 changes: 32 additions & 0 deletions config/nrfconnect/chip-module/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,38 @@ config CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU_ENCRYPTED

endif # CHIP_CRYPTO_PSA_MIGRATE_DAC_PRIV_KEY

config CHIP_STORE_KEYS_IN_KMU
bool "Use KMU to store crypto keys"
depends on CRACEN_LIB_KMU
default y
select EXPERIMENTAL
help
Stores cryptographic materials like keys in the KMU if available on the device.
This option utilizes a custom nRF Connect implementation of PSAKeyAllocator for key
storage. All non-volatile cryptographic materials used by the Matter stack will be
stored in KMU slots.

if CHIP_STORE_KEYS_IN_KMU

config CHIP_KMU_SLOT_RANGE_START
int "Starting KMU slot number for Matter crypto materials"
default 100
help
Defines the starting KMU slot number reserved for storing Matter-related keys.
This configuration does not include the DAC private key. To change DAC private key
location see the CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU_SLOT_ID Kconfig.

config CHIP_KMU_SLOT_RANGE_END
int "Last available KMU slot for Matter crypto materials"
default 175 if CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU
default 180
help
Defines the last available KMU slot for storing Matter-related keys.
This configuration does not include the DAC private key. To change DAC private key
location see the CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU_SLOT_ID Kconfig.

endif # CHIP_STORE_KEYS_IN_KMU

config CHIP_PERSISTENT_SUBSCRIPTIONS
default n
# selecting experimental for this feature since there is an issue with multiple controllers.
Expand Down
1 change: 0 additions & 1 deletion config/nrfconnect/chip-module/Kconfig.features
Original file line number Diff line number Diff line change
Expand Up @@ -288,5 +288,4 @@ config CHIP_LAST_FABRIC_REMOVED_ACTION_DELAY
After removing the last fabric the device will wait for the defined time and then perform
an action chosen by the CHIP_LAST_FABRIC_REMOVED_ACTION option. This schedule will allow for
avoiding race conditions before the device removes non-volatile data.

endif # CHIP
6 changes: 6 additions & 0 deletions src/platform/nrfconnect/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ static_library("nrfconnect") {
sources += [ "../Zephyr/SysHeapMalloc.cpp" ]
}

if (chip_use_cracen_kmu) {
sources += [
"KMUKeyAllocator.h",
]
}

cflags = [ "-Wconversion" ]
}

Expand Down
135 changes: 135 additions & 0 deletions src/platform/nrfconnect/KMUKeyAllocator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* Copyright (c) 2025 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cracen_psa_kmu.h>
#include <crypto/PSAKeyAllocator.h>

// Define the number of slots per NOC and ICD key.
#define KMU_SLOTS_PER_NOC_KEY 2
#define KMU_SLOTS_PER_ICD_KEY 2 // ICD KEY means a pair of AES and HMAC keys per fabric
#define KMU_SLOTS_PER_GROUP_KEY 1

#define KMU_SLOTS_NOC_MAX_NUMBER (KMU_SLOTS_PER_NOC_KEY * CONFIG_CHIP_MAX_FABRICS)
#define KMU_SLOTS_ICD_MAX_NUMBER (KMU_SLOTS_PER_ICD_KEY * CONFIG_CHIP_MAX_FABRICS * CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC)
#define KMU_SLOTS_GROUP_MAX_NUMBER (KMU_SLOTS_PER_GROUP_KEY * CHIP_CONFIG_MAX_GROUP_KEYS_PER_FABRIC * CONFIG_CHIP_MAX_FABRICS)

// Check whether the number of slots is within the range of the KMU.
#if ((KMU_SLOTS_NOC_MAX_NUMBER + KMU_SLOTS_ICD_MAX_NUMBER + KMU_SLOTS_GROUP_MAX_NUMBER) > \
CONFIG_CHIP_KMU_SLOT_RANGE_END - CONFIG_CHIP_KMU_SLOT_RANGE_START)
{
#pragma message("NOC keys: " STRINGIFY(KMU_SLOTS_NOC_MAX_NUMBER) "+ ICD keys: " STRINGIFY( \
KMU_SLOTS_ICD_MAX_NUMBER) "+ GROUP keys: " STRINGIFY(KMU_SLOTS_GROUP_MAX_NUMBER) ">" STRINGIFY(KMU_AVAILABLE_MATTER_SLOTS))
#error \
"The number of slots exceeds the range of the KMU defined in CONFIG_CHIP_KMU_SLOT_RANGE_START and CONFIG_CHIP_KMU_SLOT_RANGE_END"
}
#endif

// Define the start of the KMU slots for Matter.
#define KMU_NOC_SLOT_START PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, CONFIG_CHIP_KMU_SLOT_RANGE_START)
#define KMU_ICD_SLOT_START \
PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, (KMU_NOC_SLOT_START + KMU_SLOTS_NOC_MAX_NUMBER))
#define KMU_GROUP_KEYS_SLOT_START \
PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, (KMU_ICD_SLOT_START + KMU_SLOTS_ICD_MAX_NUMBER))

// Check whether the DAC KMU slot doesn not overlap with the KMU slots dedicated for Matter core.
#if defined(CONFIG_CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU) && \
(CONFIG_CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU_SLOT_ID >= CONFIG_CHIP_KMU_SLOT_RANGE_START && \
CONFIG_CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU_SLOT_ID <= CONFIG_CHIP_KMU_SLOT_RANGE_END)
#error "CONFIG_CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU_SLOT_ID cannot overlap with KMU slots dedicated for Matter core"
#endif

namespace chip {
namespace DeviceLayer {
class KMUKeyAllocator : public chip::Crypto::PSAKeyAllocator
{
public:
psa_key_id_t GetDacKeyId() override
{
return PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW,
CONFIG_CHIP_CRYPTO_PSA_DAC_PRIV_KEY_KMU_SLOT_ID);
}
psa_key_id_t GetOpKeyId(FabricIndex fabricIndex) override
{
return static_cast<psa_key_id_t>(KMU_NOC_SLOT_START + ((fabricIndex - 1) * KMU_SLOTS_PER_NOC_KEY));
}
psa_key_id_t AllocateICDKeyId() override
{
psa_key_id_t newKeyId = PSA_KEY_ID_NULL;
if (CHIP_NO_ERROR != FindFreeSlot(newKeyId, KMU_ICD_SLOT_START, KMU_ICD_SLOT_START + KMU_SLOTS_ICD_MAX_NUMBER))
{
newKeyId = PSA_KEY_ID_NULL;
}
return newKeyId;
}
void UpdateKeyAttributes(psa_key_attributes_t & attrs) override
{
// Set the key lifetime to persistent and the location to CRACEN_KMU if key is in a proper range
if (psa_get_key_id(&attrs) >=
PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, CONFIG_CHIP_KMU_SLOT_RANGE_START) &&
psa_get_key_id(&attrs) <
PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, CONFIG_CHIP_KMU_SLOT_RANGE_END))
{
psa_set_key_lifetime(
&attrs, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, PSA_KEY_LOCATION_CRACEN_KMU));
}
// TODO: Currently ECDSA keys are supported only if HASH_ANY is provided, so change it.
// Remove this workaround once KMU supports ECDSA SHA256.
if (psa_get_key_algorithm(&attrs) == PSA_ALG_ECDSA(PSA_ALG_SHA_256))
{
psa_set_key_algorithm(&attrs, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH));
}

// TODO: Change PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8) to PSA_ALG_CCM
// To be compatible with the KMU. Remove this workaround once KMU supports PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG.
// Currently we need to use EXPORT flag because the Cracen does not support copying keys from ITS to KMU
if (psa_get_key_algorithm(&attrs) == PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8))
{
psa_set_key_algorithm(&attrs, PSA_ALG_CCM);
psa_set_key_usage_flags(&attrs, psa_get_key_usage_flags(&attrs) | PSA_KEY_USAGE_EXPORT);
}

// TODO: Currently we need to use EXPORT flag because the Cracen does not support copying keys from ITS to KMU
if (psa_get_key_type(&attrs) == PSA_KEY_TYPE_HMAC)
{
psa_set_key_usage_flags(&attrs, psa_get_key_usage_flags(&attrs) | PSA_KEY_USAGE_EXPORT);
}
}

private:
CHIP_ERROR FindFreeSlot(psa_key_id_t & keyId, psa_key_id_t start, psa_key_id_t end)
{
psa_key_attributes_t attributes;
psa_status_t status = PSA_SUCCESS;
for (keyId = start; keyId < end; ++keyId)
{
status = psa_get_key_attributes(keyId, &attributes);
if (status == PSA_ERROR_INVALID_HANDLE)
{
return CHIP_NO_ERROR;
}
else if (status != PSA_SUCCESS)
{
return CHIP_ERROR_INTERNAL;
}
psa_reset_key_attributes(&attributes);
}
return CHIP_ERROR_NOT_FOUND;
}
};

} // namespace DeviceLayer
} // namespace chip
4 changes: 4 additions & 0 deletions src/platform/nrfconnect/args.gni
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ declare_args() {

# Enable factory data support
chip_enable_factory_data = false

# Use KMU to store cryptographic materials.
# This requires a dedicated platform-specific crypto implementation.
chip_use_cracen_kmu = false
}

0 comments on commit fcdf98d

Please sign in to comment.