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:
parent
d022d315d2
commit
bf0e6d7c83
25 changed files with 1713 additions and 0 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
48
subsys/secure_storage/CMakeLists.txt
Normal file
48
subsys/secure_storage/CMakeLists.txt
Normal 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()
|
||||
102
subsys/secure_storage/Kconfig
Normal file
102
subsys/secure_storage/Kconfig
Normal 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
|
||||
34
subsys/secure_storage/Kconfig.its_store
Normal file
34
subsys/secure_storage/Kconfig.its_store
Normal 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
|
||||
134
subsys/secure_storage/Kconfig.its_transform
Normal file
134
subsys/secure_storage/Kconfig.its_transform
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
29
subsys/secure_storage/include/psa/error.h
Normal file
29
subsys/secure_storage/include/psa/error.h
Normal 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
|
||||
126
subsys/secure_storage/include/psa/internal_trusted_storage.h
Normal file
126
subsys/secure_storage/include/psa/internal_trusted_storage.h
Normal 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
|
||||
241
subsys/secure_storage/include/psa/protected_storage.h
Normal file
241
subsys/secure_storage/include/psa/protected_storage.h
Normal 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
|
||||
51
subsys/secure_storage/include/psa/storage_common.h
Normal file
51
subsys/secure_storage/include/psa/storage_common.h
Normal 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
|
||||
6
subsys/secure_storage/src/CMakeLists.txt
Normal file
6
subsys/secure_storage/src/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library_sources(
|
||||
log.c
|
||||
)
|
||||
add_subdirectory(its)
|
||||
29
subsys/secure_storage/src/its/CMakeLists.txt
Normal file
29
subsys/secure_storage/src/its/CMakeLists.txt
Normal 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
|
||||
)
|
||||
228
subsys/secure_storage/src/its/implementation.c
Normal file
228
subsys/secure_storage/src/its/implementation.c
Normal 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;
|
||||
}
|
||||
116
subsys/secure_storage/src/its/store_settings.c
Normal file
116
subsys/secure_storage/src/its/store_settings.c
Normal 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;
|
||||
}
|
||||
131
subsys/secure_storage/src/its/transform/aead.c
Normal file
131
subsys/secure_storage/src/its/transform/aead.c
Normal 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;
|
||||
}
|
||||
144
subsys/secure_storage/src/its/transform/aead_get.c
Normal file
144
subsys/secure_storage/src/its/transform/aead_get.c
Normal 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 */
|
||||
6
subsys/secure_storage/src/log.c
Normal file
6
subsys/secure_storage/src/log.c
Normal 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);
|
||||
Loading…
Reference in a new issue