Skip to content

Commit 5b4a6eb

Browse files
tomi-fontjukkar
authored andcommitted
[nrf fromlist] secure_storage: make UIDs 32-bit
Make the storage UID type 32-bit long. This makes it more convenient to use those UIDs as storage entry IDs when storing the entries to NVM. The previous 64+ bits UIDs made it incovenient to use them as such. As Zephyr defines UID ranges to be used (see e.g. `zephyr/psa/key_ids.h`), this guarantees that all the UIDs will fit within the 30 bits reserved for them. The secure storage ITS implementation API is changed to take `psa_storage_uid_t` separately so the implementation can check that no forbidden bits are set before they are packed into `secure_storage_its_uid_t`. This change breaks backward compatibility because `secure_storage_its_uid_t`, which is used both as part of the additional data for authentication and for generating encryption keys, changes size from 12 to 4 bytes. For users wanting to preserve backward compatibility (for example when upgrading an existing installation to a newer Zephyr release) or that for some reason want to use a 64-bit `psa_storage_uid_t`, the Kconfig option CONFIG_SECURE_STORAGE_64_BIT_UID is added. When enabled, it makes the implementation behave the same as previously and compatibility with existing entries is preserved. This was tested manually. Fixes zephyrproject-rtos/zephyr#86177. Signed-off-by: Tomi Fontanilles <[email protected]> Upstream PR #: 94171 (cherry picked from commit c784ed1)
1 parent f444dbd commit 5b4a6eb

File tree

9 files changed

+139
-69
lines changed

9 files changed

+139
-69
lines changed

subsys/secure_storage/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ module = SECURE_STORAGE
2525
module-str = secure_storage
2626
source "subsys/logging/Kconfig.template.log_config"
2727

28+
config SECURE_STORAGE_64_BIT_UID
29+
bool "Make psa_storage_uid_t 64-bit"
30+
help
31+
Zephyr, by default, uses a 30-bit psa_storage_uid_t, which allows using only 32 bits to
32+
identify entries.
33+
UID ranges are defined for the different users of the API which guarantees that all the
34+
UIDs fit within 30 bits. See for example the zephyr/psa/key_ids.h header file.
35+
Enable this for backward compatibility if you are updating an existing installation with
36+
stored entries that was using Zephyr prior to 4.3 or if for some reason you need the full
37+
64-bit UID range.
38+
2839
choice SECURE_STORAGE_ITS_IMPLEMENTATION
2940
prompt "Internal Trusted Storage (ITS) API implementation"
3041

subsys/secure_storage/Kconfig.its_store

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ config SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_ZMS
1717
depends on ZMS
1818
help
1919
This implementation of the ITS store module makes direct use of ZMS for storage.
20-
It needs a `secure_storage_its_partition` devicetree chosen property that points
20+
It needs a secure_storage_its_partition devicetree chosen property that points
2121
to a fixed storage partition that will be dedicated to the ITS. It has lower
2222
overhead compared to the settings-based implementation, both in terms of runtime
2323
execution and storage space, and also ROM footprint if the settings subsystem is disabled.
@@ -78,7 +78,8 @@ config SECURE_STORAGE_ITS_STORE_SETTINGS_PREFIX
7878
config SECURE_STORAGE_ITS_STORE_SETTINGS_NAME_MAX_LEN
7979
int "Maximum setting name length"
8080
range 2 64
81-
default 22 if !SECURE_STORAGE_ITS_STORE_SETTINGS_NAME_CUSTOM
82-
default 0
81+
default 0 if SECURE_STORAGE_ITS_STORE_SETTINGS_NAME_CUSTOM
82+
default 22 if SECURE_STORAGE_64_BIT_UID
83+
default 14
8384

8485
endif # SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,21 @@
1414
#include "its/common.h"
1515

1616
/** @brief See `psa_its_set()`, to which this function is analogous. */
17-
psa_status_t secure_storage_its_set(secure_storage_its_uid_t uid, size_t data_length,
18-
const void *p_data, psa_storage_create_flags_t create_flags);
17+
psa_status_t secure_storage_its_set(secure_storage_its_caller_id_t caller_id, psa_storage_uid_t uid,
18+
size_t data_length, const void *p_data,
19+
psa_storage_create_flags_t create_flags);
1920

2021
/** @brief See `psa_its_get()`, to which this function is analogous. */
21-
psa_status_t secure_storage_its_get(secure_storage_its_uid_t uid, size_t data_offset,
22-
size_t data_size, void *p_data, size_t *p_data_length);
22+
psa_status_t secure_storage_its_get(secure_storage_its_caller_id_t caller_id, psa_storage_uid_t uid,
23+
size_t data_offset, size_t data_size,
24+
void *p_data, size_t *p_data_length);
2325

2426
/** @brief See `psa_its_get_info()`, to which this function is analogous. */
25-
psa_status_t secure_storage_its_get_info(secure_storage_its_uid_t uid,
26-
struct psa_storage_info_t *p_info);
27+
psa_status_t secure_storage_its_get_info(secure_storage_its_caller_id_t caller_id,
28+
psa_storage_uid_t uid, struct psa_storage_info_t *p_info);
2729

2830
/** @brief See `psa_its_remove()`, to which this function is analogous. */
29-
psa_status_t secure_storage_its_remove(secure_storage_its_uid_t uid);
31+
psa_status_t secure_storage_its_remove(secure_storage_its_caller_id_t caller_id,
32+
psa_storage_uid_t uid);
3033

3134
#endif

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
#include <psa/storage_common.h>
1313

1414
/** @brief The ID of the caller from which the ITS API call originates.
15-
* This is used to prevent ID collisions between different callers that are not aware
16-
* of each other and so might use the same numerical IDs, e.g. PSA Crypto and PSA ITS.
15+
* This is used to namespace the different callers and possibly treat them differently.
1716
*/
1817
typedef enum {
1918
SECURE_STORAGE_ITS_CALLER_PSA_ITS,
@@ -22,12 +21,32 @@ typedef enum {
2221
SECURE_STORAGE_ITS_CALLER_COUNT
2322
} secure_storage_its_caller_id_t;
2423

24+
#ifdef CONFIG_SECURE_STORAGE_64_BIT_UID
25+
2526
/** The UID (caller + entry IDs) of an ITS entry. */
2627
typedef struct {
2728
psa_storage_uid_t uid;
2829
secure_storage_its_caller_id_t caller_id;
2930
} __packed secure_storage_its_uid_t;
3031

32+
#else
33+
34+
#define SECURE_STORAGE_ITS_UID_BIT_SIZE 30
35+
#define SECURE_STORAGE_ITS_CALLER_ID_BIT_SIZE 2
36+
37+
/** @brief The UID (caller + entry IDs) of an ITS entry.
38+
* This is a packed, 32-bit version of `psa_storage_uid_t` which allows storing
39+
* smaller IDs compared to the 64-bit ones that PSA Secure Storage specifies.
40+
* Zephyr defines ranges of IDs to be used by different users of the API (subsystems, application)
41+
* which guarantees 1. no collisions and 2. that the IDs used fit within `uid`.
42+
*/
43+
typedef struct {
44+
psa_storage_uid_t uid : SECURE_STORAGE_ITS_UID_BIT_SIZE;
45+
secure_storage_its_caller_id_t caller_id : SECURE_STORAGE_ITS_CALLER_ID_BIT_SIZE;
46+
} secure_storage_its_uid_t;
47+
48+
#endif /* CONFIG_SECURE_STORAGE_64_BIT_UID */
49+
3150
#ifdef CONFIG_SECURE_STORAGE_ITS_TRANSFORM_MODULE
3251

3352
/** The maximum size, in bytes, of an entry's data after it has been transformed for storage. */

subsys/secure_storage/include/psa/internal_trusted_storage.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#else
1717
#define ITS_CALLER_ID SECURE_STORAGE_ITS_CALLER_PSA_ITS
1818
#endif
19-
#define ITS_UID (secure_storage_its_uid_t){.uid = uid, .caller_id = ITS_CALLER_ID}
2019
/** @endcond */
2120

2221
#include <psa/storage_common.h>
@@ -50,7 +49,7 @@ static ALWAYS_INLINE
5049
psa_status_t psa_its_set(psa_storage_uid_t uid, size_t data_length,
5150
const void *p_data, psa_storage_create_flags_t create_flags)
5251
{
53-
return secure_storage_its_set(ITS_UID, data_length, p_data, create_flags);
52+
return secure_storage_its_set(ITS_CALLER_ID, uid, data_length, p_data, create_flags);
5453
}
5554

5655
/**
@@ -76,7 +75,8 @@ static ALWAYS_INLINE
7675
psa_status_t psa_its_get(psa_storage_uid_t uid, size_t data_offset,
7776
size_t data_size, void *p_data, size_t *p_data_length)
7877
{
79-
return secure_storage_its_get(ITS_UID, data_offset, data_size, p_data, p_data_length);
78+
return secure_storage_its_get(ITS_CALLER_ID, uid, data_offset,
79+
data_size, p_data, p_data_length);
8080
}
8181

8282
/**
@@ -96,7 +96,7 @@ static ALWAYS_INLINE
9696
/** @endcond */
9797
psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info)
9898
{
99-
return secure_storage_its_get_info(ITS_UID, p_info);
99+
return secure_storage_its_get_info(ITS_CALLER_ID, uid, p_info);
100100
}
101101

102102
/**
@@ -117,7 +117,7 @@ static ALWAYS_INLINE
117117
/** @endcond */
118118
psa_status_t psa_its_remove(psa_storage_uid_t uid)
119119
{
120-
return secure_storage_its_remove(ITS_UID);
120+
return secure_storage_its_remove(ITS_CALLER_ID, uid);
121121
}
122122

123123
#undef ITS_UID

subsys/secure_storage/include/psa/protected_storage.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
/** @cond INTERNAL_HIDDEN */
1313
#ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
1414
#include "../internal/zephyr/secure_storage/its.h"
15-
#define ITS_UID (secure_storage_its_uid_t){.uid = uid, \
16-
.caller_id = SECURE_STORAGE_ITS_CALLER_PSA_PS}
15+
#define ITS_CALLER_ID SECURE_STORAGE_ITS_CALLER_PSA_PS
1716
#else
1817
#include "../internal/zephyr/secure_storage/ps.h"
1918
#endif
@@ -50,7 +49,7 @@ psa_status_t psa_ps_set(psa_storage_uid_t uid, size_t data_length,
5049
const void *p_data, psa_storage_create_flags_t create_flags)
5150
{
5251
#ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
53-
return secure_storage_its_set(ITS_UID, data_length, p_data, create_flags);
52+
return secure_storage_its_set(ITS_CALLER_ID, uid, data_length, p_data, create_flags);
5453
#else
5554
return secure_storage_ps_set(uid, data_length, p_data, create_flags);
5655
#endif
@@ -83,7 +82,8 @@ psa_status_t psa_ps_get(psa_storage_uid_t uid, size_t data_offset,
8382
size_t data_size, void *p_data, size_t *p_data_length)
8483
{
8584
#ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
86-
return secure_storage_its_get(ITS_UID, data_offset, data_size, p_data, p_data_length);
85+
return secure_storage_its_get(ITS_CALLER_ID, uid, data_offset,
86+
data_size, p_data, p_data_length);
8787
#else
8888
return secure_storage_ps_get(uid, data_offset, data_size, p_data, p_data_length);
8989
#endif
@@ -110,7 +110,7 @@ static ALWAYS_INLINE
110110
psa_status_t psa_ps_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info)
111111
{
112112
#ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
113-
return secure_storage_its_get_info(ITS_UID, p_info);
113+
return secure_storage_its_get_info(ITS_CALLER_ID, uid, p_info);
114114
#else
115115
return secure_storage_ps_get_info(uid, p_info);
116116
#endif
@@ -138,7 +138,7 @@ static ALWAYS_INLINE
138138
psa_status_t psa_ps_remove(psa_storage_uid_t uid)
139139
{
140140
#ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
141-
return secure_storage_its_remove(ITS_UID);
141+
return secure_storage_its_remove(ITS_CALLER_ID, uid);
142142
#else
143143
return secure_storage_ps_remove(uid);
144144
#endif

subsys/secure_storage/include/psa/storage_common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
#include <stddef.h>
2121

2222
/** UID type for identifying entries. */
23+
#ifdef CONFIG_SECURE_STORAGE_64_BIT_UID
2324
typedef uint64_t psa_storage_uid_t;
25+
#else
26+
typedef uint32_t psa_storage_uid_t;
27+
#endif
2428

2529
/** Flags used when creating an entry. */
2630
typedef uint32_t psa_storage_create_flags_t;

subsys/secure_storage/src/its/implementation.c

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,33 @@
1111

1212
LOG_MODULE_DECLARE(secure_storage, CONFIG_SECURE_STORAGE_LOG_LEVEL);
1313

14+
#ifndef CONFIG_SECURE_STORAGE_64_BIT_UID
15+
BUILD_ASSERT(sizeof(secure_storage_its_uid_t) == 4); /* ITS UIDs are 32-bit */
16+
BUILD_ASSERT(1 << SECURE_STORAGE_ITS_CALLER_ID_BIT_SIZE >= SECURE_STORAGE_ITS_CALLER_COUNT);
17+
BUILD_ASSERT(SECURE_STORAGE_ITS_CALLER_ID_BIT_SIZE + SECURE_STORAGE_ITS_UID_BIT_SIZE == 32);
18+
#endif
19+
20+
static psa_status_t make_its_uid(secure_storage_its_caller_id_t caller_id, psa_storage_uid_t uid,
21+
secure_storage_its_uid_t *its_uid)
22+
{
23+
if (uid == 0) {
24+
return PSA_ERROR_INVALID_ARGUMENT;
25+
}
26+
27+
#ifndef CONFIG_SECURE_STORAGE_64_BIT_UID
28+
/* Check that the UID is not bigger than the maximum defined size. */
29+
if (uid & GENMASK64(63, SECURE_STORAGE_ITS_UID_BIT_SIZE)) {
30+
LOG_DBG("UID %u/0x%llx cannot be used as it has bits set past "
31+
"the first " STRINGIFY(SECURE_STORAGE_ITS_UID_BIT_SIZE) " ones.",
32+
caller_id, (unsigned long long)uid);
33+
return PSA_ERROR_INVALID_ARGUMENT;
34+
}
35+
#endif /* !CONFIG_SECURE_STORAGE_64_BIT_UID */
36+
37+
*its_uid = (secure_storage_its_uid_t){.caller_id = caller_id, .uid = uid};
38+
return PSA_SUCCESS;
39+
}
40+
1441
static void log_failed_operation(const char *operation, const char *preposition, psa_status_t ret)
1542
{
1643
LOG_ERR("Failed to %s data %s storage. (%d)", operation, preposition, ret);
@@ -117,12 +144,17 @@ static psa_status_t store_entry(secure_storage_its_uid_t uid, size_t data_length
117144
return ret;
118145
}
119146

120-
psa_status_t secure_storage_its_set(secure_storage_its_uid_t uid, size_t data_length,
121-
const void *p_data, psa_storage_create_flags_t create_flags)
147+
psa_status_t secure_storage_its_set(secure_storage_its_caller_id_t caller_id, psa_storage_uid_t uid,
148+
size_t data_length, const void *p_data,
149+
psa_storage_create_flags_t create_flags)
122150
{
123151
psa_status_t ret;
152+
secure_storage_its_uid_t its_uid;
124153

125-
if (uid.uid == 0 || (p_data == NULL && data_length != 0)) {
154+
if (make_its_uid(caller_id, uid, &its_uid) != PSA_SUCCESS) {
155+
return PSA_ERROR_INVALID_ARGUMENT;
156+
}
157+
if (p_data == NULL && data_length != 0) {
126158
return PSA_ERROR_INVALID_ARGUMENT;
127159
}
128160
if (create_flags & ~SECURE_STORAGE_ALL_CREATE_FLAGS) {
@@ -134,43 +166,49 @@ psa_status_t secure_storage_its_set(secure_storage_its_uid_t uid, size_t data_le
134166
return PSA_ERROR_INSUFFICIENT_STORAGE;
135167
}
136168

137-
if (keep_stored_entry(uid, data_length, p_data, create_flags, &ret)) {
169+
if (keep_stored_entry(its_uid, data_length, p_data, create_flags, &ret)) {
138170
return ret;
139171
}
140172

141-
ret = store_entry(uid, data_length, p_data, create_flags);
173+
ret = store_entry(its_uid, data_length, p_data, create_flags);
142174
return ret;
143175
}
144-
145-
psa_status_t secure_storage_its_get(secure_storage_its_uid_t uid, size_t data_offset,
146-
size_t data_size, void *p_data, size_t *p_data_length)
176+
psa_status_t secure_storage_its_get(secure_storage_its_caller_id_t caller_id, psa_storage_uid_t uid,
177+
size_t data_offset, size_t data_size,
178+
void *p_data, size_t *p_data_length)
147179
{
148-
if (uid.uid == 0 || (p_data == NULL && data_size != 0) || p_data_length == NULL) {
180+
psa_status_t ret;
181+
secure_storage_its_uid_t its_uid;
182+
uint8_t stored_data[SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE];
183+
size_t stored_data_len;
184+
psa_storage_create_flags_t create_flags;
185+
186+
if (make_its_uid(caller_id, uid, &its_uid) != PSA_SUCCESS) {
187+
return PSA_ERROR_INVALID_ARGUMENT;
188+
}
189+
if ((p_data == NULL && data_size != 0) || p_data_length == NULL) {
149190
return PSA_ERROR_INVALID_ARGUMENT;
150191
}
151192
if (data_size == 0) {
152193
*p_data_length = 0;
153194
return PSA_SUCCESS;
154195
}
155-
psa_status_t ret;
156-
uint8_t stored_data[SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE];
157-
size_t stored_data_len;
158-
psa_storage_create_flags_t create_flags;
159196

160-
ret = get_stored_data(uid, stored_data, &stored_data_len);
197+
198+
ret = get_stored_data(its_uid, stored_data, &stored_data_len);
161199
if (ret != PSA_SUCCESS) {
162200
return ret;
163201
}
164202
if (data_offset == 0
165203
&& data_size >= SECURE_STORAGE_ITS_TRANSFORM_DATA_SIZE(stored_data_len)) {
166204
/* All the data fits directly in the provided buffer. */
167-
return transform_stored_data(uid, stored_data_len, stored_data, data_size, p_data,
168-
p_data_length, &create_flags);
205+
return transform_stored_data(its_uid, stored_data_len, stored_data, data_size,
206+
p_data, p_data_length, &create_flags);
169207
}
170208
uint8_t data[CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE];
171209
size_t data_len;
172210

173-
ret = transform_stored_data(uid, stored_data_len, stored_data, sizeof(data), data,
211+
ret = transform_stored_data(its_uid, stored_data_len, stored_data, sizeof(data), data,
174212
&data_len, &create_flags);
175213
if (ret == PSA_SUCCESS) {
176214
if (data_offset > data_len) {
@@ -184,41 +222,47 @@ psa_status_t secure_storage_its_get(secure_storage_its_uid_t uid, size_t data_of
184222
return ret;
185223
}
186224

187-
psa_status_t secure_storage_its_get_info(secure_storage_its_uid_t uid,
188-
struct psa_storage_info_t *p_info)
225+
psa_status_t secure_storage_its_get_info(secure_storage_its_caller_id_t caller_id,
226+
psa_storage_uid_t uid, struct psa_storage_info_t *p_info)
189227
{
190228
psa_status_t ret;
229+
secure_storage_its_uid_t its_uid;
191230
uint8_t data[CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE];
192231

193-
if (uid.uid == 0 || p_info == NULL) {
232+
if (make_its_uid(caller_id, uid, &its_uid) != PSA_SUCCESS) {
233+
return PSA_ERROR_INVALID_ARGUMENT;
234+
}
235+
if (p_info == NULL) {
194236
return PSA_ERROR_INVALID_ARGUMENT;
195237
}
196238

197-
ret = get_entry(uid, sizeof(data), data, &p_info->size, &p_info->flags);
239+
ret = get_entry(its_uid, sizeof(data), data, &p_info->size, &p_info->flags);
198240
if (ret == PSA_SUCCESS) {
199241
p_info->capacity = p_info->size;
200242
}
201243
return ret;
202244
}
203245

204-
psa_status_t secure_storage_its_remove(secure_storage_its_uid_t uid)
246+
psa_status_t secure_storage_its_remove(secure_storage_its_caller_id_t caller_id,
247+
psa_storage_uid_t uid)
205248
{
206249
psa_status_t ret;
250+
secure_storage_its_uid_t its_uid;
207251
psa_storage_create_flags_t create_flags;
208252
uint8_t data[CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE];
209253
size_t data_len;
210254

211-
if (uid.uid == 0) {
255+
if (make_its_uid(caller_id, uid, &its_uid) != PSA_SUCCESS) {
212256
return PSA_ERROR_INVALID_ARGUMENT;
213257
}
214258

215-
ret = get_entry(uid, sizeof(data), data, &data_len, &create_flags);
259+
ret = get_entry(its_uid, sizeof(data), data, &data_len, &create_flags);
216260
if (ret == PSA_SUCCESS && (create_flags & PSA_STORAGE_FLAG_WRITE_ONCE)) {
217261
return PSA_ERROR_NOT_PERMITTED;
218262
}
219263
/* Allow overwriting corrupted entries as well to not be stuck with them forever. */
220264
if (ret == PSA_SUCCESS || ret == PSA_ERROR_STORAGE_FAILURE) {
221-
ret = secure_storage_its_store_remove(uid);
265+
ret = secure_storage_its_store_remove(its_uid);
222266
if (ret != PSA_SUCCESS) {
223267
log_failed_operation("remove", "from", ret);
224268
return PSA_ERROR_STORAGE_FAILURE;

0 commit comments

Comments
 (0)