Skip to content

Commit

Permalink
pal: add crypto keys module
Browse files Browse the repository at this point in the history
[KRKNWK-19108]
Add sidewalk pal module to store persistent keys.
It uses secure storage via psa api.

Signed-off-by: Krzysztof Taborowski <[email protected]>
  • Loading branch information
ktaborowski committed Jul 29, 2024
1 parent 58c646d commit 3368893
Show file tree
Hide file tree
Showing 12 changed files with 437 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ config SIDEWALK_ON_DEV_CERT
bool "Enable Sidewalk on device certification"
depends on SHELL

config SIDEWALK_CRYPTO_PSA_KEY_STORAGE
bool "Enable psa crypto storage for persistent Sidewalk keys [EXPERIMENTAL]"
select EXPERIMENTAL

config SIDEWALK_PAL_RADIO_SOURCE
bool "Build sub-GHz radio driver from sources [EXPERIMENTAL]"
select EXPERIMENTAL
Expand Down
2 changes: 2 additions & 0 deletions Kconfig.dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ config SIDEWALK_CRYPTO
imply PSA_WANT_KEY_TYPE_HMAC
imply PSA_WANT_GENERATE_RANDOM
imply MBEDTLS_ENABLE_HEAP
imply MBEDTLS_PSA_CRYPTO_STORAGE_C if SIDEWALK_CRYPTO_PSA_KEY_STORAGE
imply TRUSTED_STORAGE if SIDEWALK_CRYPTO_PSA_KEY_STORAGE
help
Sidewalk security module

Expand Down
67 changes: 67 additions & 0 deletions subsys/sal/sid_pal/include/sid_crypto_keys.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#ifndef SID_CRYPTO_KEYS_H
#define SID_CRYPTO_KEYS_H

#include <psa/crypto.h>

/**
* @brief Persistent psa key ids used in Sidewalk.
*/
typedef enum {
SID_CRYPTO_MFG_ED25519_PRIV_KEY_ID = PSA_KEY_ID_USER_MIN,
SID_CRYPTO_MFG_SECP_256R1_PRIV_KEY_ID,
SID_CRYPTO_KV_WAN_MASTER_KEY_ID,
SID_CRYPTO_KV_APP_KEY_KEY_ID,
SID_CRYPTO_KV_PAN_KEY_ID,
SID_CRYPTO_KV_D2D_KEY_ID,
SID_CRYPTO_KEY_ID_LAST
} sid_crypto_key_id_t;

/**
* @brief Init secure key storage for Sidewalk keys.
*
* @return 0 on success, or -errno on failure.
*/
int sid_crypto_keys_init(void);

/**
* @brief Set key value.
*
* @details On success:
* The raw key data buffer will be overwritten with key id and zeros.
* key value under given key id will be overwritten.
*
* @param id [in] Key id to set with the new data.
* @param data [in/out] raw key data buffer on input.
* overwrite with key id on output.
* @param size [in] size of raw key data buffer.
* @return 0 on success, or -errno on failure.
*/
int sid_crypto_keys_set(psa_key_id_t id, uint8_t *data, size_t size);

/**
* @brief Get key id by data.
*
* @param id [out] psa key id from key data buffer.
* If key not found set to PSA_KEY_ID_NULL.
* @param data [in] key data buffer.
* @param size [in] size of key data buffer.
* @return 0 on success, or -errno on failure.
* -ENOENT - if key not found.
*/
int sid_crypto_keys_get(psa_key_id_t *id, uint8_t *data, size_t size);


/**
* @brief Deinit sidewalk key storage.
*
* @return 0 on success, or -errno on failure.
*/
int sid_crypto_keys_deinit(void);

#endif /* SID_CRYPTO_KEYS_H */
1 change: 1 addition & 0 deletions subsys/sal/sid_pal/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ zephyr_library_sources_ifdef(CONFIG_SIDEWALK_VENDOR_SERVICE sid_ble_vnd_service.
zephyr_library_sources_ifdef(CONFIG_SIDEWALK_LOGGING_SERVICE sid_ble_log_service.c)

zephyr_library_sources_ifdef(CONFIG_SIDEWALK_CRYPTO sid_crypto.c)
zephyr_library_sources_ifdef(CONFIG_SIDEWALK_CRYPTO_PSA_KEY_STORAGE sid_crypto_keys.c)

zephyr_library_sources_ifdef(CONFIG_SIDEWALK_MFG_STORAGE sid_mfg_storage.c)

Expand Down
164 changes: 164 additions & 0 deletions subsys/sal/sid_pal/src/sid_crypto_keys.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include <sid_crypto_keys.h>
#include <errno.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(sid_crypto_key, CONFIG_SIDEWALK_CRYPTO_LOG_LEVEL);
#define ESUCCESS (0)

#ifdef CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_DERIVE_FROM_HUK
#include <hw_unique_key.h>
#ifndef HUK_HAS_KMU
#include <zephyr/sys/reboot.h>
#endif /* HUK_HAS_KMU */

static int write_huk(void)
{
if (!hw_unique_key_are_any_written()) {
int result = hw_unique_key_write_random();
if (result != HW_UNIQUE_KEY_SUCCESS) {
LOG_ERR("hw_unique_key_write_random error: %d", result);
return 0;
}
LOG_INF("Writing random keys to KMU Success!");
#if !defined(HUK_HAS_KMU)
/* Reboot to allow the bootloader to load the key into CryptoCell. */
sys_reboot(0);
#endif /* !defined(HUK_HAS_KMU) */
}

return 0;
}
#endif /* CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_DERIVE_FROM_HUK */

int sid_crypto_keys_init(void)
{
int err = ESUCCESS;
#ifdef CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_DERIVE_FROM_HUK
err = write_huk();
#endif /* CONFIG_TRUSTED_STORAGE_BACKEND_AEAD_KEY_DERIVE_FROM_HUK */

return err;
}

int sid_crypto_keys_set(psa_key_id_t id, uint8_t *data, size_t size)
{
/* Check arguments */
if (PSA_KEY_ID_NULL == id || !data || !size) {
return -EINVAL;
}

/* Remove the key if any exists */
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
status = psa_destroy_key(id);
if (PSA_SUCCESS != status && PSA_ERROR_INVALID_HANDLE != status) {
LOG_ERR("psa_destroy_key failed! (err %d id %d)", status, id);
}

/* Configure the key attributes */
psa_key_id_t out_id = PSA_KEY_ID_NULL;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
size_t key_bits = 0;
psa_key_usage_t usage_flags = 0;
psa_algorithm_t alg = PSA_ALG_NONE;
psa_key_type_t type = PSA_KEY_TYPE_NONE;

switch (id) {
case SID_CRYPTO_MFG_ED25519_PRIV_KEY_ID:
usage_flags = PSA_KEY_USAGE_SIGN_HASH;
alg = PSA_ALG_PURE_EDDSA;
type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS);
key_bits = 255;
break;
case SID_CRYPTO_MFG_SECP_256R1_PRIV_KEY_ID:
usage_flags = PSA_KEY_USAGE_SIGN_HASH;
alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
key_bits = 256;
break;
case SID_CRYPTO_KV_WAN_MASTER_KEY_ID:
case SID_CRYPTO_KV_APP_KEY_KEY_ID:
case SID_CRYPTO_KV_PAN_KEY_ID:
case SID_CRYPTO_KV_D2D_KEY_ID:
usage_flags = PSA_KEY_USAGE_SIGN_MESSAGE;
alg = PSA_ALG_CMAC;
type = PSA_KEY_TYPE_AES;
key_bits = 128;
/* TODO: What if one key can be used with two algs, eg PSA_ALG_CMAC and PSA_ALG_CTR? Should it be saved twice? */
break;
default:
LOG_ERR("Unknow persistent key id %d", id);
return -ENOENT;
}

psa_reset_key_attributes(&attributes);
psa_set_key_usage_flags(&attributes, usage_flags);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, type);
psa_set_key_bits(&attributes, key_bits);

psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&attributes, id);

/* Import key to secure storage */
status = psa_import_key(&attributes, data, size, &out_id);
if (PSA_SUCCESS == status && out_id == id) {
LOG_HEXDUMP_DBG(data, size, "found new key: ");
} else {
LOG_ERR("psa_import_key failed! (err %d id %d)", status, out_id);
return -EACCES;
}

/* Clear key data other then key id*/
memset(data, 0, size);
psa_key_id_t *data_id = (psa_key_id_t *)data;
*data_id = id;
LOG_HEXDUMP_DBG(data, size, "saved new key: ");

status = psa_purge_key(id);
if (status != PSA_SUCCESS) {
LOG_ERR("psa_purge_key failed! (err %d id %d)", status, id);
return -EFAULT;
}

psa_reset_key_attributes(&attributes);

return ESUCCESS;
}

int sid_crypto_keys_get(psa_key_id_t *id, uint8_t *data, size_t size)
{
if (!id || !data || !size) {
return -EINVAL;
}

/* if key not found, assign null id */
*id = PSA_KEY_ID_NULL;

/* Check if a key data cosists only of key id and zeros */
psa_key_id_t *data_id = (psa_key_id_t *)data;
if (SID_CRYPTO_KEY_ID_LAST <= *data_id || PSA_KEY_ID_USER_MIN > *data_id) {
return -ENOENT;
}

for (size_t i = sizeof(psa_key_id_t); i < size; i++) {
if (0x00 != data[i]) {
return -ENOENT;
}
}

memcpy(id, data_id, sizeof(psa_key_id_t));
LOG_DBG("found persistent key: %d", *id);
return ESUCCESS;
}

int sid_crypto_keys_deinit(void)
{
/* Nothing to do, left for stable api for future features */
return ESUCCESS;
}
15 changes: 15 additions & 0 deletions tests/functional/crypto_keys/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Copyright (c) 2022 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(sidewalk_functional_test)

# add test file
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
target_include_directories(app PRIVATE . src)
38 changes: 38 additions & 0 deletions tests/functional/crypto_keys/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#
# Copyright (c) 2022 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
config SIDEWALK_BUILD
default y

config SIDEWALK_CRYPTO
default y

config SIDEWALK_STORAGE
default y

config SIDEWALK_CRYPTO_PSA_KEY_STORAGE
default y

config SIDEWALK_CRYPTO_LOG_LEVEL
default 0

config SIDEWALK_LOG_LEVEL
default 0

# Stacks
config MAIN_STACK_SIZE
default 8192

config ZTEST_STACK_SIZE
default 8192

config HEAP_MEM_POOL_SIZE
default 4096

config MBEDTLS_HEAP_SIZE
default 4096

source "Kconfig.zephyr"
source "${ZEPHYR_BASE}/../sidewalk/Kconfig.dependencies"
7 changes: 7 additions & 0 deletions tests/functional/crypto_keys/boards/nrf52840dk_nrf52840.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

CONFIG_REBOOT=y
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

CONFIG_TFM_PROFILE_TYPE_NOT_SET=y

# Using hardware crypto accelerator
CONFIG_PSA_CRYPTO_DRIVER_OBERON=n
CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y
8 changes: 8 additions & 0 deletions tests/functional/crypto_keys/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#
# Copyright (c) 2022 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
CONFIG_ZTEST=y
CONFIG_MAIN_THREAD_PRIORITY=14
CONFIG_NVS_LOG_LEVEL_WRN=y
Loading

0 comments on commit 3368893

Please sign in to comment.