secure_storage: introduce the secure storage subsystem

Implements RFC https://github.com/zephyrproject-rtos/zephyr/issues/75275.

See also the PR (https://github.com/zephyrproject-rtos/zephyr/pull/76222)
for more information.

Signed-off-by: Tomi Fontanilles <tomi.fontanilles@nordicsemi.no>
This commit is contained in:
Tomi Fontanilles 2024-09-13 08:35:38 +03:00 committed by Carles Cufí
parent d022d315d2
commit bf0e6d7c83
25 changed files with 1713 additions and 0 deletions

View file

@ -4107,6 +4107,14 @@ RTIO:
tests:
- rtio
Secure storage:
status: maintained
maintainers:
- tomi-font
files:
- subsys/secure_storage/
labels:
- "area: Secure storage"
Storage:
status: odd fixes
files:

View file

@ -50,6 +50,7 @@ add_subdirectory_ifdef(CONFIG_MODEM_MODULES modem)
add_subdirectory_ifdef(CONFIG_NETWORKING net)
add_subdirectory_ifdef(CONFIG_PROFILING profiling)
add_subdirectory_ifdef(CONFIG_RETENTION retention)
add_subdirectory_ifdef(CONFIG_SECURE_STORAGE secure_storage)
add_subdirectory_ifdef(CONFIG_SENSING sensing)
add_subdirectory_ifdef(CONFIG_SETTINGS settings)
add_subdirectory_ifdef(CONFIG_SHELL shell)

View file

@ -38,6 +38,7 @@ source "subsys/random/Kconfig"
source "subsys/retention/Kconfig"
source "subsys/rtio/Kconfig"
source "subsys/sd/Kconfig"
source "subsys/secure_storage/Kconfig"
source "subsys/sensing/Kconfig"
source "subsys/settings/Kconfig"
source "subsys/shell/Kconfig"

View file

@ -0,0 +1,48 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
zephyr_library_include_directories(include/internal) # secure_storage headers
add_subdirectory(src)
# Make the subsystem's PSA Secure Storage API headers available only when it's enabled.
zephyr_include_directories(
include
)
# Make the secure_storage headers available to the application only when it's implementing the relevant APIs.
function(make_available header)
if (NOT header STREQUAL "common.h")
make_available(common.h)
endif()
if ((header MATCHES "^its") AND NOT (header STREQUAL "its/common.h"))
make_available(its/common.h)
endif()
configure_file(include/internal/zephyr/secure_storage/${header}
${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/secure_storage/${header}
COPYONLY)
endfunction()
if (CONFIG_SECURE_STORAGE_ITS_IMPLEMENTATION_CUSTOM)
make_available(its.h)
endif()
if (CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_CUSTOM)
make_available(ps.h)
endif()
if (CONFIG_SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_CUSTOM
OR (CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM
AND CONFIG_SECURE_STORAGE_ITS_TRANSFORM_MODULE))
make_available(its/transform.h)
endif()
if (CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM)
make_available(its/store.h)
endif()
if (CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_CUSTOM
OR CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_CUSTOM
OR CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER_CUSTOM)
make_available(its/transform/aead_get.h)
endif()

View file

@ -0,0 +1,102 @@
# Copyright (c) 2024 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0
menuconfig SECURE_STORAGE
bool "Secure storage subsystem"
depends on !BUILD_WITH_TFM
select EXPERIMENTAL
help
The secure storage subsystem provides an implementation of the PSA Secure Storage API
functions on board targets that don't already have one.
It allows making use of the PSA Secure Storage API and persistent keys in the PSA Crypto
API in a standard and portable way.
It is configurable and different implementations can be used to accommodate the varying
capabilities of different devices.
In addition to providing functional support for the PSA Secure Storage API, depending on
the device-specific security features that are available and used, the subsystem may
secure the data stored through it at rest.
This is however highly dependent on the device and configuration in use, and not a
guarantee of the subsystem.
if SECURE_STORAGE
module = SECURE_STORAGE
module-str = secure_storage
source "subsys/logging/Kconfig.template.log_config"
choice SECURE_STORAGE_ITS_IMPLEMENTATION
prompt "Internal Trusted Storage (ITS) API implementation"
config SECURE_STORAGE_ITS_IMPLEMENTATION_ZEPHYR
bool "Zephyr's ITS implementation"
select SECURE_STORAGE_ITS_TRANSFORM_MODULE
select SECURE_STORAGE_ITS_STORE_MODULE
help
Use Zephyr's implementation of the ITS API.
It calls into the transform and store modules, which
can be configured and have custom implementations.
config SECURE_STORAGE_ITS_IMPLEMENTATION_CUSTOM
bool "Custom ITS implementation"
help
A custom implementation of the ITS API is present.
Implement the functions declared in <zephyr/secure_storage/its.h>.
The header is made available when this Kconfig option is enabled.
endchoice # SECURE_STORAGE_ITS_IMPLEMENTATION
config SECURE_STORAGE_ITS_MAX_DATA_SIZE
int "Maximum data size of an ITS entry in bytes"
default 128
help
The maximum size, in bytes, that the data of an ITS entry can be.
Increasing this value increases the stack usage when serving PSA ITS API calls.
menuconfig SECURE_STORAGE_ITS_TRANSFORM_MODULE
bool "ITS transform module"
help
The module that handles the transformation and validation of the
ITS data before it's written to and after it's read from NVM.
Zephyr's ITS implementation calls into it.
if SECURE_STORAGE_ITS_TRANSFORM_MODULE
rsource "Kconfig.its_transform"
endif
menuconfig SECURE_STORAGE_ITS_STORE_MODULE
bool "ITS store module"
imply FLASH # for FLASH_HAS_DRIVER_ENABLED
help
The module that handles the storage/retrieval of the ITS data to/from NVM.
Zephyr's ITS implementation calls into it.
if SECURE_STORAGE_ITS_STORE_MODULE
rsource "Kconfig.its_store"
endif
choice SECURE_STORAGE_PS_IMPLEMENTATION
prompt "Protected Storage (PS) API implementation"
default SECURE_STORAGE_PS_IMPLEMENTATION_ITS
config SECURE_STORAGE_PS_IMPLEMENTATION_ITS
bool "PS calls directly into the ITS"
help
The PS API doesn't have an implementation of its own, and directly calls into the ITS API.
This means that the implementation of the PS API will be identical to that of the ITS API.
config SECURE_STORAGE_PS_IMPLEMENTATION_CUSTOM
bool "Custom PS implementation"
help
A custom implementation of the PS API is present.
Implement the functions declared in <zephyr/secure_storage/ps.h>.
The header is made available when this Kconfig option is enabled.
endchoice # SECURE_STORAGE_PS_IMPLEMENTATION
config SECURE_STORAGE_PS_SUPPORTS_SET_EXTENDED
bool "PS API implementation supports psa_ps_create() and psa_ps_set_extended()"
depends on SECURE_STORAGE_PS_IMPLEMENTATION_CUSTOM
help
Whether the psa_ps_create() and psa_ps_set_extended() functions are implemented.
endif # SECURE_STORAGE

View file

@ -0,0 +1,34 @@
# Copyright (c) 2024 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0
choice SECURE_STORAGE_ITS_STORE_IMPLEMENTATION
prompt "ITS store module implementation"
config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
bool "ITS store module implementation using the settings subsystem for storage"
DT_STORAGE_PARTITION := $(dt_nodelabel_path,storage_partition)
depends on FLASH_HAS_DRIVER_ENABLED \
&& $(dt_path_enabled,$(DT_STORAGE_PARTITION)) \
&& $(dt_node_has_compat,$(dt_node_parent,$(DT_STORAGE_PARTITION)),fixed-partitions)
imply FLASH_MAP
imply NVS
select SETTINGS
config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_NONE
bool "No ITS store module implementation"
config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM
bool "Custom ITS store module implementation"
help
Implement the functions declared in <zephyr/secure_storage/its/store.h>.
The header is made available when this Kconfig option is enabled.
endchoice # SECURE_STORAGE_ITS_STORE_IMPLEMENTATION
if SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
config SECURE_STORAGE_ITS_STORE_SETTINGS_PREFIX
string "Subtree in which to store the settings, with a trailing slash. Can be empty."
default "its/"
endif # SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS

View file

@ -0,0 +1,134 @@
# Copyright (c) 2024 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0
choice SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION
prompt "ITS transform module implementation"
config SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_AEAD
bool "ITS transform module implementation using AEAD to protect the data"
imply HWINFO # for HWINFO_HAS_DRIVER
config SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_CUSTOM
bool "Custom ITS transform module implementation"
help
Implement the functions declared in <zephyr/secure_storage/its/transform.h>
and set CONFIG_SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD appropriately.
The header is made available when this Kconfig option is enabled.
endchoice # SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION
config SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD
int "Overhead, in bytes, associated with the transformation of an entry's data for storage"
range 0 1000
# authentication tag (16) + nonce (12)
default 28 if SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_AEAD \
&& SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE = 12
default -1
help
This indicates how many more bytes an ITS entry's data will be once it
has been processed by the secure_storage_its_transform_to_store() function.
if SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_AEAD
choice SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME
prompt "AEAD ITS transform module scheme"
default SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_AES_GCM
help
The AEAD scheme used to encrypt and authenticate the data.
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_AES_GCM
bool "AES-GCM AEAD scheme"
select PSA_WANT_KEY_TYPE_AES
select PSA_WANT_ALG_GCM
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_CHACHA20_POLY1305
bool "ChaCha20-Poly1305 AEAD scheme"
depends on SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE = 12
select PSA_WANT_KEY_TYPE_CHACHA20
select PSA_WANT_ALG_CHACHA20_POLY1305
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_CUSTOM
bool "Custom AEAD scheme"
help
Implement the secure_storage_its_transform_aead_get_scheme() function
declared in <zephyr/secure_storage/its/transform/aead_get.h>
and set CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE appropriately.
The header is made available when this Kconfig option is enabled.
endchoice # SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME
choice SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER
prompt "AEAD ITS transform module encryption key provider"
default SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_DEVICE_ID_HASH if HWINFO_HAS_DRIVER
default SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_ENTRY_UID_HASH if !HWINFO_HAS_DRIVER
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_DEVICE_ID_HASH
bool "Hash of the device ID returned by the HW info API (not necessarily secure)"
depends on HWINFO_HAS_DRIVER
select PSA_WANT_ALG_SHA_256
help
This key provider generates keys by hashing the following:
- the device EUI64 as returned by hwinfo_get_device_eui64() as first choice;
- the device ID as returned by hwinfo_get_device_uuid() as second choice.
In addition to the device ID, it adds the UID of the ITS entry
for which it is generating a key to the data hashed as a salt.
This is not necessarily secure as the device ID may be easily readable
by an attacker, not unique, and/or guessable, depending on the device.
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_ENTRY_UID_HASH
bool "Hash of the ITS entry UID (not secure)"
select PSA_WANT_ALG_SHA_256
help
This key provider generates keys by hashing the UID of the ITS entry for which it is
generating a key. This is not secure, and only intended for functional support,
because the UIDs are easily guessable and even stored in clear by the store module.
Use a secure key provider if possible.
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_CUSTOM
bool "Custom key provider"
help
Implement the secure_storage_its_transform_aead_get_key() function
declared in <zephyr/secure_storage/its/transform/aead_get.h>.
The header is made available when this Kconfig option is enabled.
endchoice # SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE
int "AEAD ITS transform module encryption key size in bytes"
default 32
if !SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_CUSTOM
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_NO_INSECURE_KEY_WARNING
bool "Silence the insecure ITS encryption key warnings"
endif
choice SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER
prompt "AEAD ITS transform module nonce provider"
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER_DEFAULT
bool "Default nonce provider"
help
The default nonce provider generates a random number for the first nonce with
psa_generate_random(), then increments it for every subsequent nonce. A random
source that doesn't repeat values between reboots is required for this to be secure.
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER_CUSTOM
bool "Custom nonce provider"
help
Implement the secure_storage_its_transform_aead_get_nonce() function
declared in <zephyr/secure_storage/its/transform/aead_get.h>.
The header is made available when this Kconfig option is enabled.
endchoice # SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER
config SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE
int "AEAD ITS transform module nonce size in bytes"
range 4 24
default 12
help
Make sure to update CONFIG_SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD
appropriately when changing the value of this option.
endif # SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_AEAD

View file

@ -0,0 +1,19 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SECURE_STORAGE_COMMON_H
#define SECURE_STORAGE_COMMON_H
/** @file zephyr/secure_storage/common.h Common definitions of the secure storage subsystem. */
#include <stdint.h>
/* A size-optimized version of `psa_storage_create_flags_t`. Used for storing the `create_flags`. */
typedef uint8_t secure_storage_packed_create_flags_t;
#define SECURE_STORAGE_ALL_CREATE_FLAGS \
(PSA_STORAGE_FLAG_NONE | \
PSA_STORAGE_FLAG_WRITE_ONCE | \
PSA_STORAGE_FLAG_NO_CONFIDENTIALITY | \
PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION)
#endif

View file

@ -0,0 +1,31 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SECURE_STORAGE_ITS_H
#define SECURE_STORAGE_ITS_H
/** @file zephyr/secure_storage/its.h The secure storage ITS implementation.
*
* The functions declared in this header implement the PSA ITS API
* when the secure storage subsystem is enabled.
* They must not be called directly, and this header must not be included other than when
* providing a custom implementation (@kconfig{CONFIG_SECURE_STORAGE_ITS_IMPLEMENTATION_CUSTOM}).
*/
#include "its/common.h"
/** @brief See `psa_its_set()`, to which this function is analogous. */
psa_status_t secure_storage_its_set(secure_storage_its_uid_t uid, size_t data_length,
const void *p_data, psa_storage_create_flags_t create_flags);
/** @brief See `psa_its_get()`, to which this function is analogous. */
psa_status_t secure_storage_its_get(secure_storage_its_uid_t uid, size_t data_offset,
size_t data_size, void *p_data, size_t *p_data_length);
/** @brief See `psa_its_get_info()`, to which this function is analogous. */
psa_status_t secure_storage_its_get_info(secure_storage_its_uid_t uid,
struct psa_storage_info_t *p_info);
/** @brief See `psa_its_remove()`, to which this function is analogous. */
psa_status_t secure_storage_its_remove(secure_storage_its_uid_t uid);
#endif

View file

@ -0,0 +1,30 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SECURE_STORAGE_ITS_COMMON_H
#define SECURE_STORAGE_ITS_COMMON_H
/** @file zephyr/secure_storage/its/common.h
* @brief Common definitions of the secure storage subsystem's ITS APIs.
*/
#include "../common.h"
#include <zephyr/toolchain.h>
#include <psa/storage_common.h>
/** @brief The ID of the caller from which the ITS API call originates.
* This is used to prevent ID collisions between different callers that are not aware
* of each other and so might use the same numerical IDs, e.g. PSA Crypto and PSA ITS.
*/
typedef enum {
SECURE_STORAGE_ITS_CALLER_PSA_ITS,
SECURE_STORAGE_ITS_CALLER_PSA_PS,
SECURE_STORAGE_ITS_CALLER_MBEDTLS,
} secure_storage_its_caller_id_t;
/** The UID (caller + entry IDs) of an ITS entry. */
typedef struct {
psa_storage_uid_t uid;
secure_storage_its_caller_id_t caller_id;
} __packed secure_storage_its_uid_t;
#endif

View file

@ -0,0 +1,52 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SECURE_STORAGE_ITS_STORE_H
#define SECURE_STORAGE_ITS_STORE_H
/** @file zephyr/secure_storage/its/store.h The secure storage ITS store module.
*
* The functions declared in this header implement the ITS store module.
* They are meant to be called only by the ITS implementation.
* This header may be included when providing a custom implementation of the
* ITS store module (@kconfig{CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM}).
*/
#include <zephyr/secure_storage/its/common.h>
/** @brief Writes the data of an ITS entry to the storage medium.
*
* @param uid The entry's UID.
* @param data_length The number of bytes in `data`.
* @param data The data to store.
*
* @retval `PSA_SUCCESS` on success.
* @retval `PSA_ERROR_INSUFFICIENT_STORAGE` if there is insufficient storage space.
* @retval `PSA_ERROR_STORAGE_FAILURE` on any other failure.
*/
psa_status_t secure_storage_its_store_set(secure_storage_its_uid_t uid,
size_t data_length, const void *data);
/** @brief Retrieves the data of an ITS entry from the storage medium.
*
* @param[in] uid The entry's UID.
* @param[in] data_size The size of `data` in bytes.
* @param[out] data The buffer to which the entry's stored data is written.
* @param[out] data_length On success, the number of bytes written to `data`.
* May be less than `data_size`.
*
* @retval `PSA_SUCCESS` on success.
* @retval `PSA_ERROR_DOES_NOT_EXIST` if no entry with the given UID exists.
* @retval `PSA_ERROR_STORAGE_FAILURE` on any other failure.
*/
psa_status_t secure_storage_its_store_get(secure_storage_its_uid_t uid, size_t data_size,
void *data, size_t *data_length);
/** @brief Removes an ITS entry from the storage medium.
*
* @param uid The entry's UID.
*
* @return `PSA_SUCCESS` on success, anything else on failure.
*/
psa_status_t secure_storage_its_store_remove(secure_storage_its_uid_t uid);
#endif

View file

@ -0,0 +1,62 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SECURE_STORAGE_ITS_TRANSFORM_H
#define SECURE_STORAGE_ITS_TRANSFORM_H
/** @file zephyr/secure_storage/its/transform.h The secure storage ITS transform module.
*
* The functions declared in this header implement the ITS transform module.
* They are meant to be called only by the ITS implementation.
* This header may be included when providing a custom implementation of the
* ITS transform module (@kconfig{CONFIG_SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_CUSTOM}).
*/
#include <zephyr/secure_storage/its/common.h>
/** The maximum size, in bytes, of an entry's data after it has been transformed for storage. */
enum { SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE
= CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE
+ sizeof(secure_storage_packed_create_flags_t)
+ CONFIG_SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD };
#define SECURE_STORAGE_ITS_TRANSFORM_DATA_SIZE(stored_data_len) \
(stored_data_len - (SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE \
- CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE))
/** @brief Transforms the data of an ITS entry for storage.
*
* @param[in] uid The entry's UID.
* @param[in] data_len The number of bytes in `data`.
* @param[in] data The data to transform for storage.
* @param[in] create_flags The entry's create flags. It must contain only valid
* `PSA_STORAGE_FLAG_*` values. It gets stored as part of `stored_data`.
* @param[out] stored_data The buffer to which the transformed data is written.
* @param[out] stored_data_len On success, the number of bytes written to `stored_data`.
*
* @return `PSA_SUCCESS` on success, anything else on failure.
*/
psa_status_t secure_storage_its_transform_to_store(
secure_storage_its_uid_t uid, size_t data_len, const void *data,
secure_storage_packed_create_flags_t create_flags,
uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],
size_t *stored_data_len);
/** @brief Transforms and validates the stored data of an ITS entry for use.
*
* @param[in] uid The entry's UID.
* @param[in] stored_data_len The number of bytes in `stored_data`.
* @param[in] stored_data The stored data to transform for use.
* @param[in] data_size The size of `data` in bytes.
* @param[out] data The buffer to which the transformed data is written.
* @param[out] data_len On success, the number of bytes written to `stored_data`.
* @param[out] create_flags On success, the entry's create flags.
*
* @return `PSA_SUCCESS` on success, anything else on failure.
*/
psa_status_t secure_storage_its_transform_from_store(
secure_storage_its_uid_t uid, size_t stored_data_len,
const uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],
size_t data_size, void *data, size_t *data_len,
psa_storage_create_flags_t *create_flags);
#endif

View file

@ -0,0 +1,45 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SECURE_STORAGE_ITS_TRANSFORM_AEAD_GET_H
#define SECURE_STORAGE_ITS_TRANSFORM_AEAD_GET_H
/** @file zephyr/secure_storage/its/transform/aead_get.h The AEAD ITS transform module API.
*
* The functions declared in this header allow customization
* of the AEAD implementation of the ITS transform module.
* They are not meant to be called directly other than by the AEAD ITS transform module.
* This header may be included when providing a custom implementation of one
* or more of these functions (@kconfig{CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_*_CUSTOM}).
*/
#include <zephyr/secure_storage/its/common.h>
#include <psa/crypto_types.h>
/** @brief Returns the key type and algorithm to use for the AEAD operations.
*
* @param[out] key_type The key type to use.
* @param[out] alg The algorithm to use.
*/
void secure_storage_its_transform_aead_get_scheme(psa_key_type_t *key_type, psa_algorithm_t *alg);
/** @brief Returns the encryption key to use for an ITS entry's AEAD operations.
*
* @param[in] uid The UID of the ITS entry for whom the returned key is used.
* @param[out] key The encryption key.
*
* @return `PSA_SUCCESS` on success, anything else on failure.
*/
psa_status_t secure_storage_its_transform_aead_get_key(
secure_storage_its_uid_t uid,
uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE]);
/** @brief Generates a nonce for an AEAD operation.
*
* @param[out] nonce The generated nonce.
*
* @return `PSA_SUCCESS` on success, anything else on failure.
*/
psa_status_t secure_storage_its_transform_aead_get_nonce(
uint8_t nonce[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE]);
#endif

View file

@ -0,0 +1,39 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SECURE_STORAGE_PS_H
#define SECURE_STORAGE_PS_H
/** @file zephyr/secure_storage/ps.h The secure storage PS implementation.
*
* The functions declared in this header implement the PSA PS API
* when the secure storage subsystem is enabled.
* They must not be called directly, and this header must not be included other than when
* providing a custom implementation (@kconfig{CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_CUSTOM}).
*/
#include <psa/storage_common.h>
/** @brief See `psa_ps_set()`, to which this function is analogous. */
psa_status_t secure_storage_ps_set(const psa_storage_uid_t uid, size_t data_length,
const void *p_data, psa_storage_create_flags_t create_flags);
/** @brief See `psa_ps_get()`, to which this function is analogous. */
psa_status_t secure_storage_ps_get(const psa_storage_uid_t uid, size_t data_offset,
size_t data_length, void *p_data, size_t *p_data_length);
/** @brief See `psa_ps_get_info()`, to which this function is analogous. */
psa_status_t secure_storage_ps_get_info(const psa_storage_uid_t uid,
struct psa_storage_info_t *p_info);
/** @brief See `psa_ps_remove()`, to which this function is analogous. */
psa_status_t secure_storage_ps_remove(const psa_storage_uid_t uid);
/** @brief See `psa_ps_create()`, to which this function is analogous. */
psa_status_t secure_storage_ps_create(psa_storage_uid_t uid, size_t capacity,
psa_storage_create_flags_t create_flags);
/** @brief See `psa_ps_set_extended()`, to which this function is analogous. */
psa_status_t secure_storage_ps_set_extended(psa_storage_uid_t uid, size_t data_offset,
size_t data_length, const void *p_data);
#endif

View file

@ -0,0 +1,29 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef PSA_ERROR_H
#define PSA_ERROR_H
/**
* @file psa/error.h Return values of the PSA Secure Storage API.
* @ingroup psa_secure_storage
* @{
*/
#include <stdint.h>
typedef int32_t psa_status_t;
#define PSA_SUCCESS ((psa_status_t)0)
#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132)
#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133)
#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134)
#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135)
#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139)
#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140)
#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142)
#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146)
#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149)
#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152)
/** @} */
#endif

View file

@ -0,0 +1,126 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef PSA_INTERNAL_TRUSTED_STORAGE_H
#define PSA_INTERNAL_TRUSTED_STORAGE_H
/** @file psa/internal_trusted_storage.h The PSA Internal Trusted Storage (ITS) API.
* @ingroup psa_secure_storage
* For more information on the ITS, see [The Internal Trusted Storage API](https://arm-software.github.io/psa-api/storage/1.0/overview/architecture.html#the-internal-trusted-storage-api).
*/
/** @cond INTERNAL_HIDDEN */
#include "../internal/zephyr/secure_storage/its.h"
#ifdef BUILDING_MBEDTLS_CRYPTO
#define ITS_CALLER_ID SECURE_STORAGE_ITS_CALLER_MBEDTLS
#else
#define ITS_CALLER_ID SECURE_STORAGE_ITS_CALLER_PSA_ITS
#endif
#define ITS_UID (secure_storage_its_uid_t){.uid = uid, .caller_id = ITS_CALLER_ID}
/** @endcond */
#include <psa/storage_common.h>
#define PSA_ITS_API_VERSION_MAJOR 1
#define PSA_ITS_API_VERSION_MINOR 0
/**
* @brief Creates a new or modifies an existing entry.
*
* Stores data in the internal storage.
*
* @param uid The identifier of the data. Must be nonzero.
* @param data_length The size in bytes of the data in `p_data` to store.
* @param p_data A buffer containing the data to store.
* @param create_flags Flags indicating the properties of the entry.
*
* @retval PSA_SUCCESS The operation completed successfully.
* @retval PSA_ERROR_NOT_PERMITTED An entry associated with the provided `uid` already
* exists and was created with `PSA_STORAGE_FLAG_WRITE_ONCE`.
* @retval PSA_ERROR_NOT_SUPPORTED One or more of the flags provided in `create_flags`
* are not supported or invalid.
* @retval PSA_ERROR_INVALID_ARGUMENT One or more arguments other than `create_flags` are
* invalid.
* @retval PSA_ERROR_INSUFFICIENT_STORAGE There is insufficient space on the storage medium.
* @retval PSA_ERROR_STORAGE_FAILURE The physical storage has failed (fatal error).
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
psa_status_t psa_its_set(psa_storage_uid_t uid, size_t data_length,
const void *p_data, psa_storage_create_flags_t create_flags)
{
return secure_storage_its_set(ITS_UID, data_length, p_data, create_flags);
}
/**
* @brief Retrieves data associated with the provided `uid`.
*
* @param[in] uid The identifier of the data.
* @param[in] data_offset The offset, in bytes, from which to start reading the data.
* @param[in] data_size The number of bytes to read.
* @param[out] p_data The buffer where the data will be placed on success.
* Must be at least `data_size` bytes long.
* @param[out] p_data_length On success, the number of bytes placed in `p_data`.
*
* @retval PSA_SUCCESS The operation completed successfully.
* @retval PSA_ERROR_INVALID_ARGUMENT One or more of the arguments are invalid. This can also
* happen if `data_offset` is larger than the size of the data
* associated with `uid`.
* @retval PSA_ERROR_DOES_NOT_EXIST The provided `uid` was not found in the storage.
* @retval PSA_ERROR_STORAGE_FAILURE The physical storage has failed (fatal error).
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
psa_status_t psa_its_get(psa_storage_uid_t uid, size_t data_offset,
size_t data_size, void *p_data, size_t *p_data_length)
{
return secure_storage_its_get(ITS_UID, data_offset, data_size, p_data, p_data_length);
}
/**
* @brief Retrieves the metadata of a given entry.
*
* @param[in] uid The identifier of the entry.
* @param[out] p_info A pointer to a `psa_storage_info_t` struct that will
* be populated with the metadata on success.
*
* @retval PSA_SUCCESS The operation completed successfully.
* @retval PSA_ERROR_INVALID_ARGUMENT One or more of the arguments are invalid.
* @retval PSA_ERROR_DOES_NOT_EXIST The provided `uid` was not found in the storage.
* @retval PSA_ERROR_STORAGE_FAILURE The physical storage has failed (fatal error).
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info)
{
return secure_storage_its_get_info(ITS_UID, p_info);
}
/**
* @brief Removes the provided `uid` and its associated data.
*
* Deletes all the data associated with the entry from internal storage.
*
* @param uid The identifier of the entry to remove.
*
* @retval PSA_SUCCESS The operation completed successfully.
* @retval PSA_ERROR_NOT_PERMITTED The entry was created with `PSA_STORAGE_FLAG_WRITE_ONCE`.
* @retval PSA_ERROR_INVALID_ARGUMENT `uid` is invalid.
* @retval PSA_ERROR_DOES_NOT_EXIST The provided `uid` was not found in the storage.
* @retval PSA_ERROR_STORAGE_FAILURE The physical storage has failed (fatal error).
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
psa_status_t psa_its_remove(psa_storage_uid_t uid)
{
return secure_storage_its_remove(ITS_UID);
}
#undef ITS_UID
#undef ITS_CALLER_ID
#endif

View file

@ -0,0 +1,241 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef PSA_PROTECTED_STORAGE_H
#define PSA_PROTECTED_STORAGE_H
/** @file psa/protected_storage.h The PSA Protected Storage (PS) API.
* @ingroup psa_secure_storage
* For more information on the PS, see [The Protected Storage API](https://arm-software.github.io/psa-api/storage/1.0/overview/architecture.html#the-protected-storage-api).
*/
/** @cond INTERNAL_HIDDEN */
#ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
#include "../internal/zephyr/secure_storage/its.h"
#define ITS_UID (secure_storage_its_uid_t){.uid = uid, \
.caller_id = SECURE_STORAGE_ITS_CALLER_PSA_PS}
#else
#include "../internal/zephyr/secure_storage/ps.h"
#endif
/** @endcond */
#include <psa/storage_common.h>
#define PSA_PS_API_VERSION_MAJOR 1
#define PSA_PS_API_VERSION_MINOR 0
/**
* @brief Creates a new or modifies an existing entry.
*
* @param uid The identifier of the data. Must be nonzero.
* @param data_length The size in bytes of the data in `p_data` to store.
* @param p_data A buffer containing the data to store.
* @param create_flags Flags indicating the properties of the entry.
*
* @retval PSA_SUCCESS The operation completed successfully.
* @retval PSA_ERROR_GENERIC_ERROR An unspecified internal failure happened.
* @retval PSA_ERROR_NOT_PERMITTED An entry associated with the provided `uid` already
* exists and was created with `PSA_STORAGE_FLAG_WRITE_ONCE`.
* @retval PSA_ERROR_NOT_SUPPORTED One or more of the flags provided in `create_flags`
* are not supported or invalid.
* @retval PSA_ERROR_INVALID_ARGUMENT One or more arguments other than `create_flags` are
* invalid.
* @retval PSA_ERROR_INSUFFICIENT_STORAGE There is insufficient space on the storage medium.
* @retval PSA_ERROR_STORAGE_FAILURE The physical storage has failed (fatal error).
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
psa_status_t psa_ps_set(psa_storage_uid_t uid, size_t data_length,
const void *p_data, psa_storage_create_flags_t create_flags)
{
#ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
return secure_storage_its_set(ITS_UID, data_length, p_data, create_flags);
#else
return secure_storage_ps_set(uid, data_length, p_data, create_flags);
#endif
}
/**
* @brief Retrieves data associated with the provided `uid`.
*
* @param[in] uid The identifier of the data.
* @param[in] data_offset The offset, in bytes, from which to start reading the data.
* @param[in] data_size The number of bytes to read.
* @param[out] p_data The buffer where the data will be placed on success.
* Must be at least `data_size` bytes long.
* @param[out] p_data_length On success, the number of bytes placed in `p_data`.
*
* @retval PSA_SUCCESS The operation completed successfully.
* @retval PSA_ERROR_GENERIC_ERROR An unspecified internal failure happened.
* @retval PSA_ERROR_INVALID_ARGUMENT One or more of the arguments are invalid. This can also
* happen if `data_offset` is larger than the size of the data
* associated with `uid`.
* @retval PSA_ERROR_DOES_NOT_EXIST The provided `uid` was not found in the storage.
* @retval PSA_ERROR_STORAGE_FAILURE The physical storage has failed (fatal error).
* @retval PSA_ERROR_INVALID_SIGNATURE The data associated with `uid` failed authentication.
* @retval PSA_ERROR_DATA_CORRUPT The data associated with `uid` is corrupt.
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
psa_status_t psa_ps_get(psa_storage_uid_t uid, size_t data_offset,
size_t data_size, void *p_data, size_t *p_data_length)
{
#ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
return secure_storage_its_get(ITS_UID, data_offset, data_size, p_data, p_data_length);
#else
return secure_storage_ps_get(uid, data_offset, data_size, p_data, p_data_length);
#endif
}
/**
* @brief Retrieves the metadata of a given entry.
*
* @param[in] uid The identifier of the entry.
* @param[out] p_info A pointer to a `psa_storage_info_t` struct that will
* be populated with the metadata on success.
*
* @retval PSA_SUCCESS The operation completed successfully.
* @retval PSA_ERROR_GENERIC_ERROR An unspecified internal failure happened.
* @retval PSA_ERROR_INVALID_ARGUMENT One or more of the arguments are invalid.
* @retval PSA_ERROR_DOES_NOT_EXIST The provided `uid` was not found in the storage.
* @retval PSA_ERROR_STORAGE_FAILURE The physical storage has failed (fatal error).
* @retval PSA_ERROR_INVALID_SIGNATURE The data associated with `uid` failed authentication.
* @retval PSA_ERROR_DATA_CORRUPT The data associated with `uid` is corrupt.
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
psa_status_t psa_ps_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info)
{
#ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
return secure_storage_its_get_info(ITS_UID, p_info);
#else
return secure_storage_ps_get_info(uid, p_info);
#endif
}
/**
* @brief Removes the provided `uid` and its associated data.
*
* Deletes previously stored data and any associated metadata, including rollback protection data.
*
* @param uid The identifier of the entry to remove.
*
* @return A status indicating the success/failure of the operation
*
* @retval PSA_SUCCESS The operation completed successfully.
* @retval PSA_ERROR_GENERIC_ERROR An unspecified internal failure happened.
* @retval PSA_ERROR_NOT_PERMITTED The entry was created with `PSA_STORAGE_FLAG_WRITE_ONCE`.
* @retval PSA_ERROR_INVALID_ARGUMENT `uid` is invalid.
* @retval PSA_ERROR_DOES_NOT_EXIST The provided `uid` was not found in the storage.
* @retval PSA_ERROR_STORAGE_FAILURE The physical storage has failed (fatal error).
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
psa_status_t psa_ps_remove(psa_storage_uid_t uid)
{
#ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
return secure_storage_its_remove(ITS_UID);
#else
return secure_storage_ps_remove(uid);
#endif
}
/**
* @brief Reserves storage for the provided `uid`.
*
* Upon success, the capacity of the storage for `uid` will be `capacity`, and the size will be 0.
* It is only necessary to call this function for data that will be written with the
* @ref psa_ps_set_extended() function. If only the @ref psa_ps_set() function is used, calls to
* this function are redundant. This function cannot be used to replace or resize an existing entry.
*
* @param uid The identifier of the entry to reserve storage for.
* @param capacity The capacity, in bytes, to allocate.
* @param create_flags Flags indicating the properties of the entry.
*
* @retval PSA_SUCCESS The operation completed successfully.
* @retval PSA_ERROR_GENERIC_ERROR An unspecified internal failure happened.
* @retval PSA_ERROR_NOT_SUPPORTED The implementation doesn't support this function or one
* or more of the flags provided in `create_flags` are not
* supported or invalid.
* @retval PSA_ERROR_INVALID_ARGUMENT `uid` is invalid.
* @retval PSA_ERROR_ALREADY_EXISTS An entry with the provided `uid` already exists.
* @retval PSA_ERROR_INSUFFICIENT_STORAGE There is insufficient space on the storage medium.
* @retval PSA_ERROR_STORAGE_FAILURE The physical storage has failed (fatal error).
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
psa_status_t psa_ps_create(psa_storage_uid_t uid, size_t capacity,
psa_storage_create_flags_t create_flags)
{
#ifdef CONFIG_SECURE_STORAGE_PS_SUPPORTS_SET_EXTENDED
return secure_storage_ps_create(uid, capacity, create_flags);
#else
return PSA_ERROR_NOT_SUPPORTED;
#endif
}
/**
* @brief Writes part of the data associated with the provided `uid`.
*
* Before calling this function, storage must have been reserved with a call to
* @ref psa_ps_create(). This function can also be used to overwrite data that was
* written with @ref psa_ps_set(). This function can overwrite existing data and/or extend
* it up to the capacity of the entry specified in @ref psa_ps_create(), but cannot create gaps.
*
* @param uid The identifier of the entry to write.
* @param data_offset The offset, in bytes, from which to start writing the data.
* Can be at most the current size of the data.
* @param data_length The size in bytes of the data in `p_data` to write. `data_offset`
* + `data_length` can be at most the capacity of the entry.
* @param p_data A buffer containing the data to write.
*
* @retval PSA_SUCCESS The operation completed successfully.
* @retval PSA_ERROR_GENERIC_ERROR An unspecified internal failure happened.
* @retval PSA_ERROR_NOT_PERMITTED The entry was created with `PSA_STORAGE_FLAG_WRITE_ONCE`.
* @retval PSA_ERROR_NOT_SUPPORTED The implementation doesn't support this function.
* @retval PSA_ERROR_INVALID_ARGUMENT One or more of the arguments are invalid.
* @retval PSA_ERROR_DOES_NOT_EXIST The provided `uid` was not found in the storage.
* @retval PSA_ERROR_STORAGE_FAILURE The physical storage has failed (fatal error).
* @retval PSA_ERROR_INVALID_SIGNATURE The data associated with `uid` failed authentication.
* @retval PSA_ERROR_DATA_CORRUPT The data associated with `uid` is corrupt.
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, size_t data_offset,
size_t data_length, const void *p_data)
{
#ifdef CONFIG_SECURE_STORAGE_PS_SUPPORTS_SET_EXTENDED
return secure_storage_ps_set_extended(uid, data_offset, data_length, p_data);
#else
return PSA_ERROR_NOT_SUPPORTED;
#endif
}
/**
* @brief Lists optional features.
*
* @return A bitmask with flags set for the optional features supported by the implementation.
* Currently defined flags are limited to `PSA_STORAGE_SUPPORT_SET_EXTENDED`.
*/
/** @cond INTERNAL_HIDDEN */
static ALWAYS_INLINE
/** @endcond */
uint32_t psa_ps_get_support(void)
{
uint32_t flags = 0;
#ifdef CONFIG_SECURE_STORAGE_PS_SUPPORTS_SET_EXTENDED
flags |= PSA_STORAGE_SUPPORT_SET_EXTENDED;
#endif
return flags;
}
#undef ITS_UID
#endif

View file

@ -0,0 +1,51 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef PSA_STORAGE_COMMON_H
#define PSA_STORAGE_COMMON_H
/**
* @defgroup psa_secure_storage PSA Secure Storage API
* @ingroup os_services
* @details For more information on the PSA Secure Storage API, see the
* [PSA Certified Secure Storage API](https://arm-software.github.io/psa-api/storage/1.0/)
* specification.
*/
/**
* @file psa/storage_common.h
* @ingroup psa_secure_storage
* @brief Common definitions of the PSA Secure Storage API.
* @{
*/
#include <psa/error.h>
#include <stddef.h>
/** UID type for identifying entries. */
typedef uint64_t psa_storage_uid_t;
/** Flags used when creating an entry. */
typedef uint32_t psa_storage_create_flags_t;
/** No flag to pass. */
#define PSA_STORAGE_FLAG_NONE 0u
/** The data associated with the UID will not be able to be modified or deleted. */
#define PSA_STORAGE_FLAG_WRITE_ONCE (1u << 0)
/** The data associated with the UID is public, requiring only integrity. */
#define PSA_STORAGE_FLAG_NO_CONFIDENTIALITY (1u << 1)
/** The data associated with the UID does not require replay protection. */
#define PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION (1u << 2)
/** Metadata associated with a specific entry. */
struct psa_storage_info_t {
/** The allocated capacity of the storage associated with an entry. */
size_t capacity;
/** The size of an entry's data. */
size_t size;
/** The flags used when the entry was created. */
psa_storage_create_flags_t flags;
};
/** Flag indicating that @ref psa_ps_create() and @ref psa_ps_set_extended() are supported. */
#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1u << 0)
/** @} */
#endif

View file

@ -0,0 +1,6 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_library_sources(
log.c
)
add_subdirectory(its)

View file

@ -0,0 +1,29 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_library_sources_ifdef(CONFIG_SECURE_STORAGE_ITS_IMPLEMENTATION_ZEPHYR
implementation.c
)
zephyr_library_sources_ifdef(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_AEAD
transform/aead.c
transform/aead_get.c
)
if (NOT CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NO_INSECURE_KEY_WARNING)
if (CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_DEVICE_ID_HASH)
message(WARNING "
The PSA ITS encryption key provider in use generates keys by hashing the device ID
retrieved through the HW info API. This is not necessarily secure as the device ID may be
easily readable by an attacker, not unique, and/or guessable, depending on the device.
This means that the data and keys stored via the PSA APIs may not be secure at rest.")
elseif(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_ENTRY_UID_HASH)
message(WARNING "
The PSA ITS encryption key provider in use is not secure.
It's only intended for functional support.
This means that the data and keys stored via the PSA APIs will not be secure at rest.
Use a secure key provider if possible.")
endif()
endif()
zephyr_library_sources_ifdef(CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
store_settings.c
)

View file

@ -0,0 +1,228 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/secure_storage/its.h>
#include <zephyr/secure_storage/its/store.h>
#include <zephyr/secure_storage/its/transform.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/util.h>
#include <zephyr/toolchain.h>
#include <string.h>
LOG_MODULE_DECLARE(secure_storage, CONFIG_SECURE_STORAGE_LOG_LEVEL);
static void log_failed_operation(const char *operation, const char *preposition, psa_status_t ret)
{
LOG_ERR("Failed to %s data %s storage. (%d)", operation, preposition, ret);
}
static psa_status_t get_stored_data(
secure_storage_its_uid_t uid,
uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],
size_t *stored_data_len)
{
psa_status_t ret;
ret = secure_storage_its_store_get(uid, SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE,
stored_data, stored_data_len);
if (ret != PSA_SUCCESS) {
if (ret != PSA_ERROR_DOES_NOT_EXIST) {
log_failed_operation("retrieve", "from", ret);
}
return ret;
}
return PSA_SUCCESS;
}
static psa_status_t transform_stored_data(
secure_storage_its_uid_t uid, size_t stored_data_len,
const uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],
size_t data_size, void *data, size_t *data_len,
psa_storage_create_flags_t *create_flags)
{
psa_status_t ret;
ret = secure_storage_its_transform_from_store(uid, stored_data_len, stored_data,
data_size, data, data_len, create_flags);
if (ret != PSA_SUCCESS) {
log_failed_operation("transform", "from", ret);
return PSA_ERROR_STORAGE_FAILURE;
}
return PSA_SUCCESS;
}
static psa_status_t get_entry(secure_storage_its_uid_t uid, size_t data_size, uint8_t *data,
size_t *data_len, psa_storage_create_flags_t *create_flags)
{
psa_status_t ret;
uint8_t stored_data[SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE];
size_t stored_data_len;
ret = get_stored_data(uid, stored_data, &stored_data_len);
if (ret != PSA_SUCCESS) {
return ret;
}
return transform_stored_data(uid, stored_data_len, stored_data, data_size, data, data_len,
create_flags);
}
static bool keep_stored_entry(secure_storage_its_uid_t uid, size_t data_length, const void *p_data,
psa_storage_create_flags_t create_flags, psa_status_t *ret)
{
psa_storage_create_flags_t existing_create_flags;
uint8_t existing_data[CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE];
size_t existing_data_len;
*ret = get_entry(uid, sizeof(existing_data), existing_data, &existing_data_len,
&existing_create_flags);
if (*ret != PSA_SUCCESS) {
/* The entry either doesn't exist or is corrupted. */
/* Allow overwriting corrupted entries to not be stuck with them forever. */
return false;
}
if (existing_create_flags & PSA_STORAGE_FLAG_WRITE_ONCE) {
*ret = PSA_ERROR_NOT_PERMITTED;
return true;
}
if (existing_data_len == data_length &&
existing_create_flags == create_flags &&
!memcmp(existing_data, p_data, data_length)) {
LOG_DBG("Not writing entry %u/%llu to storage because its stored data"
" (of length %zu) is identical.", uid.caller_id, uid.uid, data_length);
*ret = PSA_SUCCESS;
return true;
}
return false;
}
static psa_status_t store_entry(secure_storage_its_uid_t uid, size_t data_length,
const void *p_data, psa_storage_create_flags_t create_flags)
{
psa_status_t ret;
uint8_t stored_data[SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE];
size_t stored_data_len;
ret = secure_storage_its_transform_to_store(uid, data_length, p_data, create_flags,
stored_data, &stored_data_len);
if (ret != PSA_SUCCESS) {
log_failed_operation("transform", "for", ret);
return PSA_ERROR_STORAGE_FAILURE;
}
ret = secure_storage_its_store_set(uid, stored_data_len, stored_data);
if (ret != PSA_SUCCESS) {
log_failed_operation("write", "to", ret);
}
return ret;
}
psa_status_t secure_storage_its_set(secure_storage_its_uid_t uid, size_t data_length,
const void *p_data, psa_storage_create_flags_t create_flags)
{
psa_status_t ret;
if (uid.uid == 0 || (p_data == NULL && data_length != 0)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (create_flags & ~SECURE_STORAGE_ALL_CREATE_FLAGS) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (data_length > CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE) {
LOG_DBG("Passed data length (%zu) exceeds maximum allowed (%u).",
data_length, CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE);
return PSA_ERROR_INSUFFICIENT_STORAGE;
}
if (keep_stored_entry(uid, data_length, p_data, create_flags, &ret)) {
return ret;
}
ret = store_entry(uid, data_length, p_data, create_flags);
return ret;
}
psa_status_t secure_storage_its_get(secure_storage_its_uid_t uid, size_t data_offset,
size_t data_size, void *p_data, size_t *p_data_length)
{
if (uid.uid == 0 || (p_data == NULL && data_size != 0) || p_data_length == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (data_size == 0) {
*p_data_length = 0;
return PSA_SUCCESS;
}
psa_status_t ret;
uint8_t stored_data[SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE];
size_t stored_data_len;
psa_storage_create_flags_t create_flags;
ret = get_stored_data(uid, stored_data, &stored_data_len);
if (ret != PSA_SUCCESS) {
return ret;
}
if (data_offset == 0
&& data_size >= SECURE_STORAGE_ITS_TRANSFORM_DATA_SIZE(stored_data_len)) {
/* All the data fits directly in the provided buffer. */
return transform_stored_data(uid, stored_data_len, stored_data, data_size, p_data,
p_data_length, &create_flags);
}
uint8_t data[CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE];
size_t data_len;
ret = transform_stored_data(uid, stored_data_len, stored_data, sizeof(data), data,
&data_len, &create_flags);
if (ret == PSA_SUCCESS) {
if (data_offset > data_len) {
LOG_DBG("Passed data offset (%zu) exceeds existing data length (%zu).",
data_offset, data_len);
return PSA_ERROR_INVALID_ARGUMENT;
}
*p_data_length = MIN(data_size, data_len - data_offset);
memcpy(p_data, data + data_offset, *p_data_length);
}
return ret;
}
psa_status_t secure_storage_its_get_info(secure_storage_its_uid_t uid,
struct psa_storage_info_t *p_info)
{
psa_status_t ret;
uint8_t data[CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE];
if (uid.uid == 0 || p_info == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
ret = get_entry(uid, sizeof(data), data, &p_info->size, &p_info->flags);
if (ret == PSA_SUCCESS) {
p_info->capacity = p_info->size;
}
return ret;
}
psa_status_t secure_storage_its_remove(secure_storage_its_uid_t uid)
{
psa_status_t ret;
psa_storage_create_flags_t create_flags;
uint8_t data[CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE];
size_t data_len;
if (uid.uid == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
ret = get_entry(uid, sizeof(data), data, &data_len, &create_flags);
if (ret == PSA_SUCCESS && (create_flags & PSA_STORAGE_FLAG_WRITE_ONCE)) {
return PSA_ERROR_NOT_PERMITTED;
}
/* Allow overwriting corrupted entries as well to not be stuck with them forever. */
if (ret == PSA_SUCCESS || ret == PSA_ERROR_STORAGE_FAILURE) {
ret = secure_storage_its_store_remove(uid);
if (ret != PSA_SUCCESS) {
log_failed_operation("remove", "from", ret);
return PSA_ERROR_STORAGE_FAILURE;
}
}
return ret;
}

View file

@ -0,0 +1,116 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/secure_storage/its/store.h>
#include <zephyr/init.h>
#include <zephyr/logging/log.h>
#include <zephyr/settings/settings.h>
#include <zephyr/sys/util.h>
#include <errno.h>
#include <stdio.h>
#ifdef CONFIG_SECURE_STORAGE_ITS_IMPLEMENTATION_ZEPHYR
#include <zephyr/secure_storage/its/transform.h>
BUILD_ASSERT(SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE <= SETTINGS_MAX_VAL_LEN);
#endif
LOG_MODULE_DECLARE(secure_storage, CONFIG_SECURE_STORAGE_LOG_LEVEL);
static int init_settings_subsys(void)
{
const int ret = settings_subsys_init();
if (ret) {
LOG_DBG("Failed to initialize the settings subsystem. (%d)", ret);
}
return ret;
}
SYS_INIT(init_settings_subsys, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
enum { NAME_BUF_SIZE = sizeof(CONFIG_SECURE_STORAGE_ITS_STORE_SETTINGS_PREFIX) - 1
+ 2 * (sizeof(secure_storage_its_uid_t) + 1) };
BUILD_ASSERT(NAME_BUF_SIZE <= SETTINGS_MAX_NAME_LEN + 1);
static void make_name(secure_storage_its_uid_t uid, char name[static NAME_BUF_SIZE])
{
int ret;
ret = snprintf(name, NAME_BUF_SIZE, CONFIG_SECURE_STORAGE_ITS_STORE_SETTINGS_PREFIX
"%x/%llx", uid.caller_id, (unsigned long long)uid.uid);
__ASSERT_NO_MSG(ret > 0 && ret < NAME_BUF_SIZE);
}
psa_status_t secure_storage_its_store_set(secure_storage_its_uid_t uid,
size_t data_length, const void *data)
{
int ret;
char name[NAME_BUF_SIZE];
make_name(uid, name);
ret = settings_save_one(name, data, data_length);
LOG_DBG("%s %s with %zu bytes. (%d)",
(ret == 0) ? "Saved" : "Failed to save", name, data_length, ret);
switch (ret) {
case 0:
return PSA_SUCCESS;
case -ENOMEM:
case -ENOSPC:
return PSA_ERROR_INSUFFICIENT_STORAGE;
default:
return PSA_ERROR_STORAGE_FAILURE;
}
}
struct load_params {
const size_t data_size;
uint8_t *const data;
ssize_t ret;
};
static int load_direct_setting(const char *key, size_t len, settings_read_cb read_cb,
void *cb_arg, void *param)
{
(void)key;
struct load_params *load_params = param;
load_params->ret = read_cb(cb_arg, load_params->data, MIN(load_params->data_size, len));
return 0;
}
psa_status_t secure_storage_its_store_get(secure_storage_its_uid_t uid, size_t data_size,
void *data, size_t *data_length)
{
psa_status_t ret;
char name[NAME_BUF_SIZE];
struct load_params load_params = {.data_size = data_size, .data = data, .ret = -ENOENT};
make_name(uid, name);
settings_load_subtree_direct(name, load_direct_setting, &load_params);
if (load_params.ret > 0) {
*data_length = load_params.ret;
ret = PSA_SUCCESS;
} else if (load_params.ret == 0 || load_params.ret == -ENOENT) {
ret = PSA_ERROR_DOES_NOT_EXIST;
} else {
ret = PSA_ERROR_STORAGE_FAILURE;
}
LOG_DBG("%s %s for up to %zu bytes. (%zd)", (ret != PSA_ERROR_STORAGE_FAILURE) ?
"Loaded" : "Failed to load", name, data_size, load_params.ret);
return ret;
}
psa_status_t secure_storage_its_store_remove(secure_storage_its_uid_t uid)
{
int ret;
char name[NAME_BUF_SIZE];
make_name(uid, name);
ret = settings_delete(name);
if (ret) {
LOG_DBG("Failed to delete %s. (%d)", name, ret);
return PSA_ERROR_STORAGE_FAILURE;
}
return PSA_SUCCESS;
}

View file

@ -0,0 +1,131 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#include <../library/psa_crypto_driver_wrappers.h>
#include <zephyr/secure_storage/its/transform.h>
#include <zephyr/secure_storage/its/transform/aead_get.h>
#include <zephyr/sys/__assert.h>
static psa_status_t psa_aead_crypt(psa_key_usage_t operation, secure_storage_its_uid_t uid,
const uint8_t nonce
[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE],
size_t add_data_len, const void *add_data, size_t input_len,
const void *input, size_t output_size, void *output,
size_t *output_len)
{
psa_status_t ret;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
uint8_t key[CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE];
psa_key_type_t key_type;
psa_algorithm_t alg;
psa_status_t (*aead_crypt)(const psa_key_attributes_t *attributes, const uint8_t *key,
size_t key_size, psa_algorithm_t alg, const uint8_t *nonce,
size_t nonce_length, const uint8_t *add_data,
size_t add_data_len, const uint8_t *input, size_t input_len,
uint8_t *output, size_t output_size, size_t *output_len);
secure_storage_its_transform_aead_get_scheme(&key_type, &alg);
psa_set_key_usage_flags(&key_attributes, operation);
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_type(&key_attributes, key_type);
psa_set_key_algorithm(&key_attributes, alg);
psa_set_key_bits(&key_attributes, sizeof(key) * 8);
/* Avoid calling psa_aead_*crypt() because that would require importing keys into
* PSA Crypto. This gets called from PSA Crypto for storing persistent keys so,
* even if using PSA_KEY_LIFETIME_VOLATILE, it would corrupt the global key store
* which holds all the active keys in the PSA Crypto core.
*/
aead_crypt = (operation == PSA_KEY_USAGE_ENCRYPT) ?
psa_driver_wrapper_aead_encrypt : psa_driver_wrapper_aead_decrypt;
ret = secure_storage_its_transform_aead_get_key(uid, key);
if (ret != PSA_SUCCESS) {
return ret;
}
ret = aead_crypt(&key_attributes, key, sizeof(key), alg, nonce,
CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE, add_data,
add_data_len, input, input_len, output, output_size, output_len);
mbedtls_platform_zeroize(key, sizeof(key));
return ret;
}
enum { CIPHERTEXT_MAX_SIZE
= PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE) };
BUILD_ASSERT(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD
== CIPHERTEXT_MAX_SIZE - CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE
+ CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE);
BUILD_ASSERT(SECURE_STORAGE_ALL_CREATE_FLAGS
<= (1 << (8 * sizeof(secure_storage_packed_create_flags_t))) - 1);
struct stored_entry {
secure_storage_packed_create_flags_t create_flags;
uint8_t nonce[CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE];
uint8_t ciphertext[CIPHERTEXT_MAX_SIZE]; /* Keep last as this is variable in size. */
} __packed;
BUILD_ASSERT(sizeof(struct stored_entry) == SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE);
/** @return The length of a `struct stored_entry` whose `ciphertext` is `len` bytes long. */
#define STORED_ENTRY_LEN(len) (sizeof(struct stored_entry) - CIPHERTEXT_MAX_SIZE + len)
struct additional_data {
secure_storage_its_uid_t uid;
secure_storage_packed_create_flags_t create_flags;
} __packed;
psa_status_t secure_storage_its_transform_to_store(
secure_storage_its_uid_t uid, size_t data_len, const void *data,
secure_storage_packed_create_flags_t create_flags,
uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],
size_t *stored_data_len)
{
psa_status_t ret;
struct stored_entry *stored_entry = (struct stored_entry *)stored_data;
const struct additional_data add_data = {.uid = uid, .create_flags = create_flags};
size_t ciphertext_len;
stored_entry->create_flags = create_flags;
ret = secure_storage_its_transform_aead_get_nonce(stored_entry->nonce);
if (ret != PSA_SUCCESS) {
return ret;
}
ret = psa_aead_crypt(PSA_KEY_USAGE_ENCRYPT, uid, stored_entry->nonce, sizeof(add_data),
&add_data, data_len, data, sizeof(stored_entry->ciphertext),
&stored_entry->ciphertext, &ciphertext_len);
if (ret == PSA_SUCCESS) {
*stored_data_len = STORED_ENTRY_LEN(ciphertext_len);
}
return ret;
}
psa_status_t secure_storage_its_transform_from_store(
secure_storage_its_uid_t uid, size_t stored_data_len,
const uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],
size_t data_size, void *data, size_t *data_len,
psa_storage_create_flags_t *create_flags)
{
if (stored_data_len < STORED_ENTRY_LEN(0)) {
return PSA_ERROR_STORAGE_FAILURE;
}
psa_status_t ret;
struct stored_entry *stored_entry = (struct stored_entry *)stored_data;
const struct additional_data add_data = {.uid = uid,
.create_flags = stored_entry->create_flags};
const size_t ciphertext_len = stored_data_len - STORED_ENTRY_LEN(0);
ret = psa_aead_crypt(PSA_KEY_USAGE_DECRYPT, uid, stored_entry->nonce, sizeof(add_data),
&add_data, ciphertext_len, stored_entry->ciphertext, data_size, data,
data_len);
if (ret == PSA_SUCCESS) {
*create_flags = stored_entry->create_flags;
}
return ret;
}

View file

@ -0,0 +1,144 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/secure_storage/its/transform/aead_get.h>
#include <zephyr/drivers/hwinfo.h>
#include <zephyr/init.h>
#include <zephyr/logging/log.h>
#include <psa/crypto.h>
#include <string.h>
#include <sys/types.h>
LOG_MODULE_DECLARE(secure_storage, CONFIG_SECURE_STORAGE_LOG_LEVEL);
#ifdef CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_AES_GCM
#define PSA_KEY_TYPE PSA_KEY_TYPE_AES
#define PSA_ALG PSA_ALG_GCM
#elif defined(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_CHACHA20_POLY1305)
#define PSA_KEY_TYPE PSA_KEY_TYPE_CHACHA20
#define PSA_ALG PSA_ALG_CHACHA20_POLY1305
#endif
#ifndef CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_CUSTOM
void secure_storage_its_transform_aead_get_scheme(psa_key_type_t *key_type, psa_algorithm_t *alg)
{
*key_type = PSA_KEY_TYPE;
*alg = PSA_ALG;
}
#endif /* !CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_SCHEME_CUSTOM */
#ifndef CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_CUSTOM
#define SHA256_OUTPUT_SIZE 32
BUILD_ASSERT(SHA256_OUTPUT_SIZE == PSA_HASH_LENGTH(PSA_ALG_SHA_256));
BUILD_ASSERT(SHA256_OUTPUT_SIZE >= CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE);
static psa_status_t hash_data_into_key(
size_t data_len, const void *data,
uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE])
{
size_t hash_len;
#if CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE == SHA256_OUTPUT_SIZE
/* Save stack usage and avoid unnecessary memory operations.*/
return psa_hash_compute(PSA_ALG_SHA_256, data, data_len, key,
CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE, &hash_len);
#else
uint8_t hash_output[SHA256_OUTPUT_SIZE];
const psa_status_t ret = psa_hash_compute(PSA_ALG_SHA_256, data, data_len, hash_output,
sizeof(hash_output), &hash_len);
if (ret == PSA_SUCCESS) {
memcpy(key, hash_output, CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE);
mbedtls_platform_zeroize(hash_output, sizeof(hash_output));
}
return ret;
#endif
}
#ifdef CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_DEVICE_ID_HASH
#define WARNING "Using a potentially insecure PSA ITS encryption key provider."
psa_status_t secure_storage_its_transform_aead_get_key(
secure_storage_its_uid_t uid,
uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE])
{
psa_status_t ret;
ssize_t hwinfo_ret;
struct {
uint8_t device_id[8];
secure_storage_its_uid_t uid; /* acts as a salt */
} __packed data;
hwinfo_ret = hwinfo_get_device_eui64(data.device_id);
if (hwinfo_ret != 0) {
hwinfo_ret = hwinfo_get_device_id(data.device_id, sizeof(data.device_id));
if (hwinfo_ret <= 0) {
return PSA_ERROR_HARDWARE_FAILURE;
}
if (hwinfo_ret < sizeof(data.device_id)) {
memset(data.device_id + hwinfo_ret, 0, sizeof(data.device_id) - hwinfo_ret);
}
}
data.uid = uid;
ret = hash_data_into_key(sizeof(data), &data, key);
mbedtls_platform_zeroize(data.device_id, sizeof(data.device_id));
return ret;
}
#elif defined(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_ENTRY_UID_HASH)
#define WARNING "Using an insecure PSA ITS encryption key provider."
psa_status_t secure_storage_its_transform_aead_get_key(
secure_storage_its_uid_t uid,
uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE])
{
return hash_data_into_key(sizeof(uid), &uid, key);
}
#endif /* CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER */
#ifndef CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NO_INSECURE_KEY_WARNING
static int warn_insecure_key(void)
{
printk("WARNING: %s\n", WARNING);
LOG_WRN("%s", WARNING);
return 0;
}
SYS_INIT(warn_insecure_key, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
#endif /* !CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NO_INSECURE_KEY_WARNING */
#endif /* !CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_PROVIDER_CUSTOM */
#ifdef CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER_DEFAULT
psa_status_t secure_storage_its_transform_aead_get_nonce(
uint8_t nonce[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE])
{
psa_status_t ret;
static uint8_t s_nonce[CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE];
static bool s_nonce_initialized;
if (!s_nonce_initialized) {
ret = psa_generate_random(s_nonce, sizeof(s_nonce));
if (ret != PSA_SUCCESS) {
return ret;
}
s_nonce_initialized = true;
} else {
for (unsigned int i = 0; i != sizeof(s_nonce); ++i) {
++s_nonce[i];
if (s_nonce[i] != 0) {
break;
}
}
}
memcpy(nonce, &s_nonce, sizeof(s_nonce));
return PSA_SUCCESS;
}
#endif /* CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_PROVIDER_DEFAULT */

View file

@ -0,0 +1,6 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(secure_storage, CONFIG_SECURE_STORAGE_LOG_LEVEL);