2 * PSA persistent key storage
5 * Copyright The Mbed TLS Contributors
6 * SPDX-License-Identifier: Apache-2.0
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
21 #if defined(MBEDTLS_CONFIG_FILE)
22 #include MBEDTLS_CONFIG_FILE
24 #include "mbedtls/config.h"
27 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
32 #include "psa_crypto_service_integration.h"
33 #include "psa/crypto.h"
34 #include "psa_crypto_storage.h"
35 #include "mbedtls/platform_util.h"
37 #if defined(MBEDTLS_PSA_ITS_FILE_C)
38 #include "psa_crypto_its.h"
39 #else /* Native ITS implementation */
40 #include "psa/error.h"
41 #include "psa/internal_trusted_storage.h"
44 #if defined(MBEDTLS_PLATFORM_C)
45 #include "mbedtls/platform.h"
48 #define mbedtls_calloc calloc
49 #define mbedtls_free free
54 /****************************************************************/
56 /****************************************************************/
58 /* Determine a file name (ITS file identifier) for the given key identifier.
59 * The file name must be distinct from any file that is used for a purpose
60 * other than storing a key. Currently, the only such file is the random seed
61 * file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is
63 static psa_storage_uid_t
psa_its_identifier_of_slot(mbedtls_svc_key_id_t key
) {
64 #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
65 /* Encode the owner in the upper 32 bits. This means that if
66 * owner values are nonzero (as they are on a PSA platform),
67 * no key file will ever have a value less than 0x100000000, so
68 * the whole range 0..0xffffffff is available for non-key files. */
69 uint32_t unsigned_owner_id
= MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key
);
70 return (((uint64_t) unsigned_owner_id
<< 32) |
71 MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key
));
73 /* Use the key id directly as a file name.
74 * psa_is_key_id_valid() in psa_crypto_slot_management.c
75 * is responsible for ensuring that key identifiers do not have a
76 * value that is reserved for non-key files. */
82 * \brief Load persistent data for the given key slot number.
84 * This function reads data from a storage backend and returns the data in a
87 * \param key Persistent identifier of the key to be loaded. This
88 * should be an occupied storage location.
89 * \param[out] data Buffer where the data is to be written.
90 * \param data_size Size of the \c data buffer in bytes.
92 * \retval #PSA_SUCCESS
93 * \retval #PSA_ERROR_DATA_INVALID
94 * \retval #PSA_ERROR_DATA_CORRUPT
95 * \retval #PSA_ERROR_STORAGE_FAILURE
96 * \retval #PSA_ERROR_DOES_NOT_EXIST
98 static psa_status_t
psa_crypto_storage_load(
99 const mbedtls_svc_key_id_t key
, uint8_t *data
, size_t data_size
) {
101 psa_storage_uid_t data_identifier
= psa_its_identifier_of_slot(key
);
102 struct psa_storage_info_t data_identifier_info
;
103 size_t data_length
= 0;
105 status
= psa_its_get_info(data_identifier
, &data_identifier_info
);
106 if (status
!= PSA_SUCCESS
)
109 status
= psa_its_get(data_identifier
, 0, (uint32_t) data_size
, data
, &data_length
);
110 if (data_size
!= data_length
)
111 return (PSA_ERROR_DATA_INVALID
);
116 int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key
) {
118 psa_storage_uid_t data_identifier
= psa_its_identifier_of_slot(key
);
119 struct psa_storage_info_t data_identifier_info
;
121 ret
= psa_its_get_info(data_identifier
, &data_identifier_info
);
123 if (ret
== PSA_ERROR_DOES_NOT_EXIST
)
129 * \brief Store persistent data for the given key slot number.
131 * This function stores the given data buffer to a persistent storage.
133 * \param key Persistent identifier of the key to be stored. This
134 * should be an unoccupied storage location.
135 * \param[in] data Buffer containing the data to be stored.
136 * \param data_length The number of bytes
137 * that make up the data.
139 * \retval #PSA_SUCCESS
140 * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
141 * \retval #PSA_ERROR_ALREADY_EXISTS
142 * \retval #PSA_ERROR_STORAGE_FAILURE
143 * \retval #PSA_ERROR_DATA_INVALID
145 static psa_status_t
psa_crypto_storage_store(const mbedtls_svc_key_id_t key
,
147 size_t data_length
) {
149 psa_storage_uid_t data_identifier
= psa_its_identifier_of_slot(key
);
150 struct psa_storage_info_t data_identifier_info
;
152 if (psa_is_key_present_in_storage(key
) == 1)
153 return (PSA_ERROR_ALREADY_EXISTS
);
155 status
= psa_its_set(data_identifier
, (uint32_t) data_length
, data
, 0);
156 if (status
!= PSA_SUCCESS
) {
157 return (PSA_ERROR_DATA_INVALID
);
160 status
= psa_its_get_info(data_identifier
, &data_identifier_info
);
161 if (status
!= PSA_SUCCESS
) {
165 if (data_identifier_info
.size
!= data_length
) {
166 status
= PSA_ERROR_DATA_INVALID
;
171 if (status
!= PSA_SUCCESS
) {
172 /* Remove the file in case we managed to create it but something
173 * went wrong. It's ok if the file doesn't exist. If the file exists
174 * but the removal fails, we're already reporting an error so there's
175 * nothing else we can do. */
176 (void) psa_its_remove(data_identifier
);
181 psa_status_t
psa_destroy_persistent_key(const mbedtls_svc_key_id_t key
) {
183 psa_storage_uid_t data_identifier
= psa_its_identifier_of_slot(key
);
184 struct psa_storage_info_t data_identifier_info
;
186 ret
= psa_its_get_info(data_identifier
, &data_identifier_info
);
187 if (ret
== PSA_ERROR_DOES_NOT_EXIST
)
188 return (PSA_SUCCESS
);
190 if (psa_its_remove(data_identifier
) != PSA_SUCCESS
)
191 return (PSA_ERROR_DATA_INVALID
);
193 ret
= psa_its_get_info(data_identifier
, &data_identifier_info
);
194 if (ret
!= PSA_ERROR_DOES_NOT_EXIST
)
195 return (PSA_ERROR_DATA_INVALID
);
197 return (PSA_SUCCESS
);
201 * \brief Get data length for given key slot number.
203 * \param key Persistent identifier whose stored data length
205 * \param[out] data_length The number of bytes that make up the data.
207 * \retval #PSA_SUCCESS
208 * \retval #PSA_ERROR_STORAGE_FAILURE
209 * \retval #PSA_ERROR_DOES_NOT_EXIST
210 * \retval #PSA_ERROR_DATA_CORRUPT
212 static psa_status_t
psa_crypto_storage_get_data_length(
213 const mbedtls_svc_key_id_t key
,
214 size_t *data_length
) {
216 psa_storage_uid_t data_identifier
= psa_its_identifier_of_slot(key
);
217 struct psa_storage_info_t data_identifier_info
;
219 status
= psa_its_get_info(data_identifier
, &data_identifier_info
);
220 if (status
!= PSA_SUCCESS
)
223 *data_length
= (size_t) data_identifier_info
.size
;
225 return (PSA_SUCCESS
);
229 * 32-bit integer manipulation macros (little endian)
231 #ifndef GET_UINT32_LE
232 #define GET_UINT32_LE( n, b, i ) \
234 (n) = ( (uint32_t) (b)[(i) ] ) \
235 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
236 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
237 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
241 #ifndef PUT_UINT32_LE
242 #define PUT_UINT32_LE( n, b, i ) \
244 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
245 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
246 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
247 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
252 * 16-bit integer manipulation macros (little endian)
254 #ifndef GET_UINT16_LE
255 #define GET_UINT16_LE( n, b, i ) \
257 (n) = ( (uint16_t) (b)[(i) ] ) \
258 | ( (uint16_t) (b)[(i) + 1] << 8 ); \
262 #ifndef PUT_UINT16_LE
263 #define PUT_UINT16_LE( n, b, i ) \
265 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
266 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
271 * Persistent key storage magic header.
273 #define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY"
274 #define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ( sizeof( PSA_KEY_STORAGE_MAGIC_HEADER ) )
277 uint8_t magic
[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH
];
279 uint8_t lifetime
[sizeof(psa_key_lifetime_t
)];
282 uint8_t policy
[sizeof(psa_key_policy_t
)];
285 } psa_persistent_key_storage_format
;
287 void psa_format_key_data_for_storage(const uint8_t *data
,
288 const size_t data_length
,
289 const psa_core_key_attributes_t
*attr
,
290 uint8_t *storage_data
) {
291 psa_persistent_key_storage_format
*storage_format
=
292 (psa_persistent_key_storage_format
*) storage_data
;
294 memcpy(storage_format
->magic
, PSA_KEY_STORAGE_MAGIC_HEADER
, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH
);
295 PUT_UINT32_LE(0, storage_format
->version
, 0);
296 PUT_UINT32_LE(attr
->lifetime
, storage_format
->lifetime
, 0);
297 PUT_UINT16_LE((uint16_t) attr
->type
, storage_format
->type
, 0);
298 PUT_UINT16_LE((uint16_t) attr
->bits
, storage_format
->bits
, 0);
299 PUT_UINT32_LE(attr
->policy
.usage
, storage_format
->policy
, 0);
300 PUT_UINT32_LE(attr
->policy
.alg
, storage_format
->policy
, sizeof(uint32_t));
301 PUT_UINT32_LE(attr
->policy
.alg2
, storage_format
->policy
, 2 * sizeof(uint32_t));
302 PUT_UINT32_LE(data_length
, storage_format
->data_len
, 0);
303 memcpy(storage_format
->key_data
, data
, data_length
);
306 static psa_status_t
check_magic_header(const uint8_t *data
) {
307 if (memcmp(data
, PSA_KEY_STORAGE_MAGIC_HEADER
,
308 PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH
) != 0)
309 return (PSA_ERROR_DATA_INVALID
);
310 return (PSA_SUCCESS
);
313 psa_status_t
psa_parse_key_data_from_storage(const uint8_t *storage_data
,
314 size_t storage_data_length
,
316 size_t *key_data_length
,
317 psa_core_key_attributes_t
*attr
) {
319 const psa_persistent_key_storage_format
*storage_format
=
320 (const psa_persistent_key_storage_format
*)storage_data
;
323 if (storage_data_length
< sizeof(*storage_format
))
324 return (PSA_ERROR_DATA_INVALID
);
326 status
= check_magic_header(storage_data
);
327 if (status
!= PSA_SUCCESS
)
330 GET_UINT32_LE(version
, storage_format
->version
, 0);
332 return (PSA_ERROR_DATA_INVALID
);
334 GET_UINT32_LE(*key_data_length
, storage_format
->data_len
, 0);
335 if (*key_data_length
> (storage_data_length
- sizeof(*storage_format
)) ||
336 *key_data_length
> PSA_CRYPTO_MAX_STORAGE_SIZE
)
337 return (PSA_ERROR_DATA_INVALID
);
339 if (*key_data_length
== 0) {
342 *key_data
= mbedtls_calloc(1, *key_data_length
);
343 if (*key_data
== NULL
)
344 return (PSA_ERROR_INSUFFICIENT_MEMORY
);
345 memcpy(*key_data
, storage_format
->key_data
, *key_data_length
);
348 GET_UINT32_LE(attr
->lifetime
, storage_format
->lifetime
, 0);
349 GET_UINT16_LE(attr
->type
, storage_format
->type
, 0);
350 GET_UINT16_LE(attr
->bits
, storage_format
->bits
, 0);
351 GET_UINT32_LE(attr
->policy
.usage
, storage_format
->policy
, 0);
352 GET_UINT32_LE(attr
->policy
.alg
, storage_format
->policy
, sizeof(uint32_t));
353 GET_UINT32_LE(attr
->policy
.alg2
, storage_format
->policy
, 2 * sizeof(uint32_t));
355 return (PSA_SUCCESS
);
358 psa_status_t
psa_save_persistent_key(const psa_core_key_attributes_t
*attr
,
360 const size_t data_length
) {
361 size_t storage_data_length
;
362 uint8_t *storage_data
;
365 /* All keys saved to persistent storage always have a key context */
366 if (data
== NULL
|| data_length
== 0)
367 return (PSA_ERROR_INVALID_ARGUMENT
);
369 if (data_length
> PSA_CRYPTO_MAX_STORAGE_SIZE
)
370 return (PSA_ERROR_INSUFFICIENT_STORAGE
);
371 storage_data_length
= data_length
+ sizeof(psa_persistent_key_storage_format
);
373 storage_data
= mbedtls_calloc(1, storage_data_length
);
374 if (storage_data
== NULL
)
375 return (PSA_ERROR_INSUFFICIENT_MEMORY
);
377 psa_format_key_data_for_storage(data
, data_length
, attr
, storage_data
);
379 status
= psa_crypto_storage_store(attr
->id
,
380 storage_data
, storage_data_length
);
382 mbedtls_free(storage_data
);
387 void psa_free_persistent_key_data(uint8_t *key_data
, size_t key_data_length
) {
388 if (key_data
!= NULL
) {
389 mbedtls_platform_zeroize(key_data
, key_data_length
);
391 mbedtls_free(key_data
);
394 psa_status_t
psa_load_persistent_key(psa_core_key_attributes_t
*attr
,
396 size_t *data_length
) {
397 psa_status_t status
= PSA_SUCCESS
;
398 uint8_t *loaded_data
;
399 size_t storage_data_length
= 0;
400 mbedtls_svc_key_id_t key
= attr
->id
;
402 status
= psa_crypto_storage_get_data_length(key
, &storage_data_length
);
403 if (status
!= PSA_SUCCESS
)
406 loaded_data
= mbedtls_calloc(1, storage_data_length
);
408 if (loaded_data
== NULL
)
409 return (PSA_ERROR_INSUFFICIENT_MEMORY
);
411 status
= psa_crypto_storage_load(key
, loaded_data
, storage_data_length
);
412 if (status
!= PSA_SUCCESS
)
415 status
= psa_parse_key_data_from_storage(loaded_data
, storage_data_length
,
416 data
, data_length
, attr
);
418 /* All keys saved to persistent storage always have a key context */
419 if (status
== PSA_SUCCESS
&&
420 (*data
== NULL
|| *data_length
== 0))
421 status
= PSA_ERROR_STORAGE_FAILURE
;
424 mbedtls_free(loaded_data
);
430 /****************************************************************/
432 /****************************************************************/
434 #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
436 psa_crypto_transaction_t psa_crypto_transaction
;
438 psa_status_t
psa_crypto_save_transaction(void) {
439 struct psa_storage_info_t p_info
;
441 status
= psa_its_get_info(PSA_CRYPTO_ITS_TRANSACTION_UID
, &p_info
);
442 if (status
== PSA_SUCCESS
) {
443 /* This shouldn't happen: we're trying to start a transaction while
444 * there is still a transaction that hasn't been replayed. */
445 return (PSA_ERROR_CORRUPTION_DETECTED
);
446 } else if (status
!= PSA_ERROR_DOES_NOT_EXIST
)
448 return (psa_its_set(PSA_CRYPTO_ITS_TRANSACTION_UID
,
449 sizeof(psa_crypto_transaction
),
450 &psa_crypto_transaction
,
454 psa_status_t
psa_crypto_load_transaction(void) {
457 status
= psa_its_get(PSA_CRYPTO_ITS_TRANSACTION_UID
, 0,
458 sizeof(psa_crypto_transaction
),
459 &psa_crypto_transaction
, &length
);
460 if (status
!= PSA_SUCCESS
)
462 if (length
!= sizeof(psa_crypto_transaction
))
463 return (PSA_ERROR_DATA_INVALID
);
464 return (PSA_SUCCESS
);
467 psa_status_t
psa_crypto_stop_transaction(void) {
468 psa_status_t status
= psa_its_remove(PSA_CRYPTO_ITS_TRANSACTION_UID
);
469 /* Whether or not updating the storage succeeded, the transaction is
470 * finished now. It's too late to go back, so zero out the in-memory
472 memset(&psa_crypto_transaction
, 0, sizeof(psa_crypto_transaction
));
476 #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
480 /****************************************************************/
481 /* Random generator state */
482 /****************************************************************/
484 #if defined(MBEDTLS_PSA_INJECT_ENTROPY)
485 psa_status_t
mbedtls_psa_storage_inject_entropy(const unsigned char *seed
,
488 struct psa_storage_info_t p_info
;
490 status
= psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID
, &p_info
);
492 if (PSA_ERROR_DOES_NOT_EXIST
== status
) { /* No seed exists */
493 status
= psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID
, seed_size
, seed
, 0);
494 } else if (PSA_SUCCESS
== status
) {
495 /* You should not be here. Seed needs to be injected only once */
496 status
= PSA_ERROR_NOT_PERMITTED
;
500 #endif /* MBEDTLS_PSA_INJECT_ENTROPY */
504 /****************************************************************/
506 /****************************************************************/
508 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */