secure_storage: add a ZMS-based implementation of the ITS store module
It becomes the new default when the secure_storage_its_partition devicetree chosen property is defined as it is a preferred alternative. See the help message of the `CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_ZMS` Kconfig option for more information. Signed-off-by: Tomi Fontanilles <tomi.fontanilles@nordicsemi.no>
This commit is contained in:
parent
d27e4dc463
commit
0ea6f352e7
@ -4,9 +4,26 @@
|
||||
choice SECURE_STORAGE_ITS_STORE_IMPLEMENTATION
|
||||
prompt "ITS store module implementation"
|
||||
|
||||
DT_ITS_PARTITION := $(dt_chosen_path,secure_storage_its_partition)
|
||||
DT_STORAGE_PARTITION := $(dt_nodelabel_path,storage_partition)
|
||||
|
||||
config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_ZMS
|
||||
bool "ITS store module implementation using ZMS for storage"
|
||||
depends on FLASH_HAS_DRIVER_ENABLED \
|
||||
&& $(dt_path_enabled,$(DT_ITS_PARTITION)) \
|
||||
&& $(dt_node_has_compat,$(dt_node_parent,$(DT_ITS_PARTITION)),fixed-partitions)
|
||||
select ZMS
|
||||
help
|
||||
This implementation of the ITS store module makes direct use of ZMS for storage.
|
||||
It needs a `secure_storage_its_partition` devicetree chosen property that points
|
||||
to a fixed storage partition that will be dedicated to the ITS. It has lower
|
||||
overhead compared to the settings-based implementation, both in terms of runtime
|
||||
execution and storage space, and also ROM footprint if the settings subsystem is disabled.
|
||||
As this implementations directly maps the PSA storage UIDs to ZMS entry IDs, it limits
|
||||
their values to the first 30 bits.
|
||||
|
||||
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)
|
||||
@ -25,6 +42,20 @@ config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM
|
||||
|
||||
endchoice # SECURE_STORAGE_ITS_STORE_IMPLEMENTATION
|
||||
|
||||
if SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_ZMS
|
||||
|
||||
config SECURE_STORAGE_ITS_STORE_ZMS_SECTOR_SIZE
|
||||
int "Sector size of the ZMS partition"
|
||||
default 4096
|
||||
help
|
||||
The sector size impacts the runtime behavior of ZMS and restricts the maximum
|
||||
ITS entry data size (which is the sector size minus ZMS and ITS overhead).
|
||||
Changing it will result in loss of existing data stored on a partition.
|
||||
It must be a multiple of the flash page size on devices that require an erase.
|
||||
See the ZMS documentation for more information.
|
||||
|
||||
endif # SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_ZMS
|
||||
|
||||
if SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
|
||||
|
||||
config SECURE_STORAGE_ITS_STORE_SETTINGS_PREFIX
|
||||
|
||||
@ -19,6 +19,7 @@ typedef enum {
|
||||
SECURE_STORAGE_ITS_CALLER_PSA_ITS,
|
||||
SECURE_STORAGE_ITS_CALLER_PSA_PS,
|
||||
SECURE_STORAGE_ITS_CALLER_MBEDTLS,
|
||||
SECURE_STORAGE_ITS_CALLER_COUNT
|
||||
} secure_storage_its_caller_id_t;
|
||||
|
||||
/** The UID (caller + entry IDs) of an ITS entry. */
|
||||
|
||||
@ -19,9 +19,7 @@
|
||||
* @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.
|
||||
* @return One of the return values of `psa_its_set()`.
|
||||
*/
|
||||
psa_status_t secure_storage_its_store_set(secure_storage_its_uid_t uid,
|
||||
size_t data_length, const void *data);
|
||||
@ -34,9 +32,7 @@ psa_status_t secure_storage_its_store_set(secure_storage_its_uid_t uid,
|
||||
* @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.
|
||||
* @return One of the return values of `psa_its_get()`.
|
||||
*/
|
||||
psa_status_t secure_storage_its_store_get(secure_storage_its_uid_t uid, size_t data_size,
|
||||
void *data, size_t *data_length);
|
||||
|
||||
@ -24,6 +24,9 @@ if (NOT CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NO_INSECURE_KEY_WARNING)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
|
||||
store_settings.c
|
||||
zephyr_library_sources_ifdef(CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_ZMS
|
||||
store/zms.c
|
||||
)
|
||||
zephyr_library_sources_ifdef(CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
|
||||
store/settings.c
|
||||
)
|
||||
|
||||
122
subsys/secure_storage/src/its/store/zms.c
Normal file
122
subsys/secure_storage/src/its/store/zms.c
Normal file
@ -0,0 +1,122 @@
|
||||
/* Copyright (c) 2024 Nordic Semiconductor
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <zephyr/secure_storage/its/store.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/fs/zms.h>
|
||||
#include <zephyr/storage/flash_map.h>
|
||||
#ifdef CONFIG_SECURE_STORAGE_ITS_IMPLEMENTATION_ZEPHYR
|
||||
#include <zephyr/secure_storage/its/transform.h>
|
||||
#endif
|
||||
|
||||
LOG_MODULE_DECLARE(secure_storage, CONFIG_SECURE_STORAGE_LOG_LEVEL);
|
||||
|
||||
BUILD_ASSERT(CONFIG_SECURE_STORAGE_ITS_STORE_ZMS_SECTOR_SIZE
|
||||
> 2 * CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE);
|
||||
|
||||
#define PARTITION_DT_NODE DT_CHOSEN(secure_storage_its_partition)
|
||||
|
||||
static struct zms_fs s_zms = {
|
||||
.flash_device = FIXED_PARTITION_NODE_DEVICE(PARTITION_DT_NODE),
|
||||
.offset = FIXED_PARTITION_NODE_OFFSET(PARTITION_DT_NODE),
|
||||
.sector_size = CONFIG_SECURE_STORAGE_ITS_STORE_ZMS_SECTOR_SIZE,
|
||||
};
|
||||
|
||||
static int init_zms(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
s_zms.sector_count = FIXED_PARTITION_NODE_SIZE(PARTITION_DT_NODE) / s_zms.sector_size;
|
||||
|
||||
ret = zms_mount(&s_zms);
|
||||
if (ret) {
|
||||
LOG_DBG("Failed. (%d)", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
SYS_INIT(init_zms, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||
|
||||
/* Bit position of the ITS caller ID in the ZMS entry ID. */
|
||||
#define ITS_CALLER_ID_POS 30
|
||||
/* Make sure that every ITS caller ID fits in ZMS entry IDs at the defined position. */
|
||||
BUILD_ASSERT(1 << (32 - ITS_CALLER_ID_POS) >= SECURE_STORAGE_ITS_CALLER_COUNT);
|
||||
|
||||
static bool has_forbidden_bits_set(secure_storage_its_uid_t uid)
|
||||
{
|
||||
if (uid.uid & GENMASK64(63, ITS_CALLER_ID_POS)) {
|
||||
LOG_DBG("UID %u/0x%llx cannot be used as it has bits set past "
|
||||
"the first " STRINGIFY(ITS_CALLER_ID_POS) " ones.",
|
||||
uid.caller_id, (unsigned long long)uid.uid);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t zms_id_from(secure_storage_its_uid_t uid)
|
||||
{
|
||||
return (uint32_t)uid.uid | (uid.caller_id << ITS_CALLER_ID_POS);
|
||||
}
|
||||
|
||||
psa_status_t secure_storage_its_store_set(secure_storage_its_uid_t uid,
|
||||
size_t data_length, const void *data)
|
||||
{
|
||||
psa_status_t psa_ret;
|
||||
ssize_t zms_ret;
|
||||
const uint32_t zms_id = zms_id_from(uid);
|
||||
|
||||
if (has_forbidden_bits_set(uid)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
zms_ret = zms_write(&s_zms, zms_id, data, data_length);
|
||||
if (zms_ret == data_length) {
|
||||
psa_ret = PSA_SUCCESS;
|
||||
} else if (zms_ret == -ENOSPC) {
|
||||
psa_ret = PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
} else {
|
||||
psa_ret = PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
LOG_DBG("%s 0x%x with %zu bytes. (%zd)", (psa_ret == PSA_SUCCESS) ?
|
||||
"Wrote" : "Failed to write", zms_id, data_length, zms_ret);
|
||||
return psa_ret;
|
||||
}
|
||||
|
||||
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 psa_ret;
|
||||
ssize_t zms_ret;
|
||||
const uint32_t zms_id = zms_id_from(uid);
|
||||
|
||||
if (has_forbidden_bits_set(uid)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
zms_ret = zms_read(&s_zms, zms_id, data, data_size);
|
||||
if (zms_ret > 0) {
|
||||
*data_length = zms_ret;
|
||||
psa_ret = PSA_SUCCESS;
|
||||
} else if (zms_ret == -ENOENT) {
|
||||
psa_ret = PSA_ERROR_DOES_NOT_EXIST;
|
||||
} else {
|
||||
psa_ret = PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
LOG_DBG("%s 0x%x for up to %zu bytes. (%zd)", (psa_ret != PSA_ERROR_STORAGE_FAILURE) ?
|
||||
"Read" : "Failed to read", zms_id, data_size, zms_ret);
|
||||
return psa_ret;
|
||||
}
|
||||
|
||||
psa_status_t secure_storage_its_store_remove(secure_storage_its_uid_t uid)
|
||||
{
|
||||
int zms_ret;
|
||||
const uint32_t zms_id = zms_id_from(uid);
|
||||
|
||||
if (has_forbidden_bits_set(uid)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
zms_ret = zms_delete(&s_zms, zms_id);
|
||||
LOG_DBG("%s 0x%x. (%d)", zms_ret ? "Failed to delete" : "Deleted", zms_id, zms_ret);
|
||||
BUILD_ASSERT(PSA_SUCCESS == 0);
|
||||
return zms_ret;
|
||||
}
|
||||
@ -114,7 +114,7 @@ ZTEST(secure_storage_psa_its, test_write_once_flag)
|
||||
{
|
||||
psa_status_t ret;
|
||||
/* Use a UID that isn't used in the other tests for the write-once entry. */
|
||||
const psa_storage_uid_t uid = ~UID;
|
||||
const psa_storage_uid_t uid = 1 << 16;
|
||||
const uint8_t data[MAX_DATA_SIZE] = {};
|
||||
struct psa_storage_info_t info;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user