Skip to content

Commit 0ea6f35

Browse files
tomi-fontfabiobaltieri
authored andcommitted
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 <[email protected]>
1 parent d27e4dc commit 0ea6f35

File tree

7 files changed

+162
-9
lines changed

7 files changed

+162
-9
lines changed

subsys/secure_storage/Kconfig.its_store

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,26 @@
44
choice SECURE_STORAGE_ITS_STORE_IMPLEMENTATION
55
prompt "ITS store module implementation"
66

7+
DT_ITS_PARTITION := $(dt_chosen_path,secure_storage_its_partition)
8+
DT_STORAGE_PARTITION := $(dt_nodelabel_path,storage_partition)
9+
10+
config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_ZMS
11+
bool "ITS store module implementation using ZMS for storage"
12+
depends on FLASH_HAS_DRIVER_ENABLED \
13+
&& $(dt_path_enabled,$(DT_ITS_PARTITION)) \
14+
&& $(dt_node_has_compat,$(dt_node_parent,$(DT_ITS_PARTITION)),fixed-partitions)
15+
select ZMS
16+
help
17+
This implementation of the ITS store module makes direct use of ZMS for storage.
18+
It needs a `secure_storage_its_partition` devicetree chosen property that points
19+
to a fixed storage partition that will be dedicated to the ITS. It has lower
20+
overhead compared to the settings-based implementation, both in terms of runtime
21+
execution and storage space, and also ROM footprint if the settings subsystem is disabled.
22+
As this implementations directly maps the PSA storage UIDs to ZMS entry IDs, it limits
23+
their values to the first 30 bits.
24+
725
config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
826
bool "ITS store module implementation using the settings subsystem for storage"
9-
DT_STORAGE_PARTITION := $(dt_nodelabel_path,storage_partition)
1027
depends on FLASH_HAS_DRIVER_ENABLED \
1128
&& $(dt_path_enabled,$(DT_STORAGE_PARTITION)) \
1229
&& $(dt_node_has_compat,$(dt_node_parent,$(DT_STORAGE_PARTITION)),fixed-partitions)
@@ -25,6 +42,20 @@ config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM
2542

2643
endchoice # SECURE_STORAGE_ITS_STORE_IMPLEMENTATION
2744

45+
if SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_ZMS
46+
47+
config SECURE_STORAGE_ITS_STORE_ZMS_SECTOR_SIZE
48+
int "Sector size of the ZMS partition"
49+
default 4096
50+
help
51+
The sector size impacts the runtime behavior of ZMS and restricts the maximum
52+
ITS entry data size (which is the sector size minus ZMS and ITS overhead).
53+
Changing it will result in loss of existing data stored on a partition.
54+
It must be a multiple of the flash page size on devices that require an erase.
55+
See the ZMS documentation for more information.
56+
57+
endif # SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_ZMS
58+
2859
if SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
2960

3061
config SECURE_STORAGE_ITS_STORE_SETTINGS_PREFIX

subsys/secure_storage/include/internal/zephyr/secure_storage/its/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ typedef enum {
1919
SECURE_STORAGE_ITS_CALLER_PSA_ITS,
2020
SECURE_STORAGE_ITS_CALLER_PSA_PS,
2121
SECURE_STORAGE_ITS_CALLER_MBEDTLS,
22+
SECURE_STORAGE_ITS_CALLER_COUNT
2223
} secure_storage_its_caller_id_t;
2324

2425
/** The UID (caller + entry IDs) of an ITS entry. */

subsys/secure_storage/include/internal/zephyr/secure_storage/its/store.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919
* @param data_length The number of bytes in `data`.
2020
* @param data The data to store.
2121
*
22-
* @retval `PSA_SUCCESS` on success.
23-
* @retval `PSA_ERROR_INSUFFICIENT_STORAGE` if there is insufficient storage space.
24-
* @retval `PSA_ERROR_STORAGE_FAILURE` on any other failure.
22+
* @return One of the return values of `psa_its_set()`.
2523
*/
2624
psa_status_t secure_storage_its_store_set(secure_storage_its_uid_t uid,
2725
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,
3432
* @param[out] data_length On success, the number of bytes written to `data`.
3533
* May be less than `data_size`.
3634
*
37-
* @retval `PSA_SUCCESS` on success.
38-
* @retval `PSA_ERROR_DOES_NOT_EXIST` if no entry with the given UID exists.
39-
* @retval `PSA_ERROR_STORAGE_FAILURE` on any other failure.
35+
* @return One of the return values of `psa_its_get()`.
4036
*/
4137
psa_status_t secure_storage_its_store_get(secure_storage_its_uid_t uid, size_t data_size,
4238
void *data, size_t *data_length);

subsys/secure_storage/src/its/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ if (NOT CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NO_INSECURE_KEY_WARNING)
2424
endif()
2525
endif()
2626

27+
zephyr_library_sources_ifdef(CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_ZMS
28+
store/zms.c
29+
)
2730
zephyr_library_sources_ifdef(CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS
28-
store_settings.c
31+
store/settings.c
2932
)
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/* Copyright (c) 2024 Nordic Semiconductor
2+
* SPDX-License-Identifier: Apache-2.0
3+
*/
4+
#include <zephyr/secure_storage/its/store.h>
5+
#include <zephyr/logging/log.h>
6+
#include <zephyr/fs/zms.h>
7+
#include <zephyr/storage/flash_map.h>
8+
#ifdef CONFIG_SECURE_STORAGE_ITS_IMPLEMENTATION_ZEPHYR
9+
#include <zephyr/secure_storage/its/transform.h>
10+
#endif
11+
12+
LOG_MODULE_DECLARE(secure_storage, CONFIG_SECURE_STORAGE_LOG_LEVEL);
13+
14+
BUILD_ASSERT(CONFIG_SECURE_STORAGE_ITS_STORE_ZMS_SECTOR_SIZE
15+
> 2 * CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE);
16+
17+
#define PARTITION_DT_NODE DT_CHOSEN(secure_storage_its_partition)
18+
19+
static struct zms_fs s_zms = {
20+
.flash_device = FIXED_PARTITION_NODE_DEVICE(PARTITION_DT_NODE),
21+
.offset = FIXED_PARTITION_NODE_OFFSET(PARTITION_DT_NODE),
22+
.sector_size = CONFIG_SECURE_STORAGE_ITS_STORE_ZMS_SECTOR_SIZE,
23+
};
24+
25+
static int init_zms(void)
26+
{
27+
int ret;
28+
29+
s_zms.sector_count = FIXED_PARTITION_NODE_SIZE(PARTITION_DT_NODE) / s_zms.sector_size;
30+
31+
ret = zms_mount(&s_zms);
32+
if (ret) {
33+
LOG_DBG("Failed. (%d)", ret);
34+
}
35+
return ret;
36+
}
37+
SYS_INIT(init_zms, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
38+
39+
/* Bit position of the ITS caller ID in the ZMS entry ID. */
40+
#define ITS_CALLER_ID_POS 30
41+
/* Make sure that every ITS caller ID fits in ZMS entry IDs at the defined position. */
42+
BUILD_ASSERT(1 << (32 - ITS_CALLER_ID_POS) >= SECURE_STORAGE_ITS_CALLER_COUNT);
43+
44+
static bool has_forbidden_bits_set(secure_storage_its_uid_t uid)
45+
{
46+
if (uid.uid & GENMASK64(63, ITS_CALLER_ID_POS)) {
47+
LOG_DBG("UID %u/0x%llx cannot be used as it has bits set past "
48+
"the first " STRINGIFY(ITS_CALLER_ID_POS) " ones.",
49+
uid.caller_id, (unsigned long long)uid.uid);
50+
return true;
51+
}
52+
return false;
53+
}
54+
55+
static uint32_t zms_id_from(secure_storage_its_uid_t uid)
56+
{
57+
return (uint32_t)uid.uid | (uid.caller_id << ITS_CALLER_ID_POS);
58+
}
59+
60+
psa_status_t secure_storage_its_store_set(secure_storage_its_uid_t uid,
61+
size_t data_length, const void *data)
62+
{
63+
psa_status_t psa_ret;
64+
ssize_t zms_ret;
65+
const uint32_t zms_id = zms_id_from(uid);
66+
67+
if (has_forbidden_bits_set(uid)) {
68+
return PSA_ERROR_INVALID_ARGUMENT;
69+
}
70+
71+
zms_ret = zms_write(&s_zms, zms_id, data, data_length);
72+
if (zms_ret == data_length) {
73+
psa_ret = PSA_SUCCESS;
74+
} else if (zms_ret == -ENOSPC) {
75+
psa_ret = PSA_ERROR_INSUFFICIENT_STORAGE;
76+
} else {
77+
psa_ret = PSA_ERROR_STORAGE_FAILURE;
78+
}
79+
LOG_DBG("%s 0x%x with %zu bytes. (%zd)", (psa_ret == PSA_SUCCESS) ?
80+
"Wrote" : "Failed to write", zms_id, data_length, zms_ret);
81+
return psa_ret;
82+
}
83+
84+
psa_status_t secure_storage_its_store_get(secure_storage_its_uid_t uid, size_t data_size,
85+
void *data, size_t *data_length)
86+
{
87+
psa_status_t psa_ret;
88+
ssize_t zms_ret;
89+
const uint32_t zms_id = zms_id_from(uid);
90+
91+
if (has_forbidden_bits_set(uid)) {
92+
return PSA_ERROR_INVALID_ARGUMENT;
93+
}
94+
95+
zms_ret = zms_read(&s_zms, zms_id, data, data_size);
96+
if (zms_ret > 0) {
97+
*data_length = zms_ret;
98+
psa_ret = PSA_SUCCESS;
99+
} else if (zms_ret == -ENOENT) {
100+
psa_ret = PSA_ERROR_DOES_NOT_EXIST;
101+
} else {
102+
psa_ret = PSA_ERROR_STORAGE_FAILURE;
103+
}
104+
LOG_DBG("%s 0x%x for up to %zu bytes. (%zd)", (psa_ret != PSA_ERROR_STORAGE_FAILURE) ?
105+
"Read" : "Failed to read", zms_id, data_size, zms_ret);
106+
return psa_ret;
107+
}
108+
109+
psa_status_t secure_storage_its_store_remove(secure_storage_its_uid_t uid)
110+
{
111+
int zms_ret;
112+
const uint32_t zms_id = zms_id_from(uid);
113+
114+
if (has_forbidden_bits_set(uid)) {
115+
return PSA_ERROR_INVALID_ARGUMENT;
116+
}
117+
118+
zms_ret = zms_delete(&s_zms, zms_id);
119+
LOG_DBG("%s 0x%x. (%d)", zms_ret ? "Failed to delete" : "Deleted", zms_id, zms_ret);
120+
BUILD_ASSERT(PSA_SUCCESS == 0);
121+
return zms_ret;
122+
}

tests/subsys/secure_storage/psa/its/src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ ZTEST(secure_storage_psa_its, test_write_once_flag)
114114
{
115115
psa_status_t ret;
116116
/* Use a UID that isn't used in the other tests for the write-once entry. */
117-
const psa_storage_uid_t uid = ~UID;
117+
const psa_storage_uid_t uid = 1 << 16;
118118
const uint8_t data[MAX_DATA_SIZE] = {};
119119
struct psa_storage_info_t info;
120120

0 commit comments

Comments
 (0)