Coverage Report

Created: 2026-05-12 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mbedtls/library/psa_crypto_storage.h
Line
Count
Source
1
/**
2
 * \file psa_crypto_storage.h
3
 *
4
 * \brief PSA cryptography module: Mbed TLS key storage
5
 */
6
/*
7
 *  Copyright The Mbed TLS Contributors
8
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
9
 */
10
11
#ifndef PSA_CRYPTO_STORAGE_H
12
#define PSA_CRYPTO_STORAGE_H
13
14
#ifdef __cplusplus
15
extern "C" {
16
#endif
17
18
#include "psa/crypto.h"
19
#include "psa/crypto_se_driver.h"
20
21
#include <stdint.h>
22
#include <string.h>
23
24
/* Limit the maximum key size in storage. */
25
#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS)
26
/* Reflect the maximum size for the key buffer. */
27
#define PSA_CRYPTO_MAX_STORAGE_SIZE (MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE)
28
#else
29
/* Just set an upper boundary but it should have no effect since the key size
30
 * is limited in memory. */
31
0
#define PSA_CRYPTO_MAX_STORAGE_SIZE (PSA_BITS_TO_BYTES(PSA_MAX_KEY_BITS))
32
#endif
33
34
/* Sanity check: a file size must fit in 32 bits. Allow a generous
35
 * 64kB of metadata. */
36
#if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000
37
#error "PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000"
38
#endif
39
40
/** The maximum permitted persistent slot number.
41
 *
42
 * In Mbed Crypto 0.1.0b:
43
 * - Using the file backend, all key ids are ok except 0.
44
 * - Using the ITS backend, all key ids are ok except 0xFFFFFF52
45
 *   (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the
46
 *   device's random seed (if this feature is enabled).
47
 * - Only key ids from 1 to #MBEDTLS_PSA_KEY_SLOT_COUNT are actually used.
48
 *
49
 * Since we need to preserve the random seed, avoid using that key slot.
50
 * Reserve a whole range of key slots just in case something else comes up.
51
 *
52
 * This limitation will probably become moot when we implement client
53
 * separation for key storage.
54
 */
55
0
#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER PSA_KEY_ID_VENDOR_MAX
56
57
/**
58
 * \brief Checks if persistent data is stored for the given key slot number
59
 *
60
 * This function checks if any key data or metadata exists for the key slot in
61
 * the persistent storage.
62
 *
63
 * \param key           Persistent identifier to check.
64
 *
65
 * \retval 0
66
 *         No persistent data present for slot number
67
 * \retval 1
68
 *         Persistent data present for slot number
69
 */
70
int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key);
71
72
/**
73
 * \brief Format key data and metadata and save to a location for given key
74
 *        slot.
75
 *
76
 * This function formats the key data and metadata and saves it to a
77
 * persistent storage backend. The storage location corresponding to the
78
 * key slot must be empty, otherwise this function will fail. This function
79
 * should be called after loading the key into an internal slot to ensure the
80
 * persistent key is not saved into a storage location corresponding to an
81
 * already occupied non-persistent key, as well as ensuring the key data is
82
 * validated.
83
 *
84
 * Note: This function will only succeed for key buffers which are not
85
 * empty. If passed a NULL pointer or zero-length, the function will fail
86
 * with #PSA_ERROR_INVALID_ARGUMENT.
87
 *
88
 * \param[in] attr          The attributes of the key to save.
89
 *                          The key identifier field in the attributes
90
 *                          determines the key's location.
91
 * \param[in] data          Buffer containing the key data.
92
 * \param data_length       The number of bytes that make up the key data.
93
 *
94
 * \retval #PSA_SUCCESS \emptydescription
95
 * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
96
 * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
97
 * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
98
 * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
99
 * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription
100
 * \retval #PSA_ERROR_DATA_INVALID \emptydescription
101
 * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
102
 */
103
psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr,
104
                                     const uint8_t *data,
105
                                     const size_t data_length);
106
107
/**
108
 * \brief Parses key data and metadata and load persistent key for given
109
 * key slot number.
110
 *
111
 * This function reads from a storage backend, parses the key data and
112
 * metadata and writes them to the appropriate output parameters.
113
 *
114
 * Note: This function allocates a buffer and returns a pointer to it through
115
 * the data parameter. On successful return, the pointer is guaranteed to be
116
 * valid and the buffer contains at least one byte of data.
117
 * psa_free_persistent_key_data() must be called on the data buffer
118
 * afterwards to zeroize and free this buffer.
119
 *
120
 * \param[in,out] attr      On input, the key identifier field identifies
121
 *                          the key to load. Other fields are ignored.
122
 *                          On success, the attribute structure contains
123
 *                          the key metadata that was loaded from storage.
124
 * \param[out] data         Pointer to an allocated key data buffer on return.
125
 * \param[out] data_length  The number of bytes that make up the key data.
126
 *
127
 * \retval #PSA_SUCCESS \emptydescription
128
 * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
129
 * \retval #PSA_ERROR_DATA_INVALID \emptydescription
130
 * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
131
 * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
132
 */
133
psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr,
134
                                     uint8_t **data,
135
                                     size_t *data_length);
136
137
/**
138
 * \brief Remove persistent data for the given key slot number.
139
 *
140
 * \param key           Persistent identifier of the key to remove
141
 *                      from persistent storage.
142
 *
143
 * \retval #PSA_SUCCESS
144
 *         The key was successfully removed,
145
 *         or the key did not exist.
146
 * \retval #PSA_ERROR_DATA_INVALID \emptydescription
147
 */
148
psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key);
149
150
/**
151
 * \brief Free the temporary buffer allocated by psa_load_persistent_key().
152
 *
153
 * This function must be called at some point after psa_load_persistent_key()
154
 * to zeroize and free the memory allocated to the buffer in that function.
155
 *
156
 * \param key_data        Buffer for the key data.
157
 * \param key_data_length Size of the key data buffer.
158
 *
159
 */
160
void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length);
161
162
/**
163
 * \brief Formats key data and metadata for persistent storage
164
 *
165
 * \param[in] data          Buffer containing the key data.
166
 * \param data_length       Length of the key data buffer.
167
 * \param[in] attr          The core attributes of the key.
168
 * \param[out] storage_data Output buffer for the formatted data.
169
 *
170
 */
171
void psa_format_key_data_for_storage(const uint8_t *data,
172
                                     const size_t data_length,
173
                                     const psa_key_attributes_t *attr,
174
                                     uint8_t *storage_data);
175
176
/**
177
 * \brief Parses persistent storage data into key data and metadata
178
 *
179
 * \param[in] storage_data     Buffer for the storage data.
180
 * \param storage_data_length  Length of the storage data buffer
181
 * \param[out] key_data        On output, pointer to a newly allocated buffer
182
 *                             containing the key data. This must be freed
183
 *                             using psa_free_persistent_key_data()
184
 * \param[out] key_data_length Length of the key data buffer
185
 * \param[out] attr            On success, the attribute structure is filled
186
 *                             with the loaded key metadata.
187
 *
188
 * \retval #PSA_SUCCESS \emptydescription
189
 * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
190
 * \retval #PSA_ERROR_DATA_INVALID \emptydescription
191
 */
192
psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data,
193
                                             size_t storage_data_length,
194
                                             uint8_t **key_data,
195
                                             size_t *key_data_length,
196
                                             psa_key_attributes_t *attr);
197
198
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
199
/** This symbol is defined if transaction support is required. */
200
#define PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS 1
201
#endif
202
203
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
204
205
/** The type of transaction that is in progress.
206
 */
207
/* This is an integer type rather than an enum for two reasons: to support
208
 * unknown values when loading a transaction file, and to ensure that the
209
 * type has a known size.
210
 */
211
typedef uint16_t psa_crypto_transaction_type_t;
212
213
/** No transaction is in progress.
214
 *
215
 * This has the value 0, so zero-initialization sets a transaction's type to
216
 * this value.
217
 */
218
#define PSA_CRYPTO_TRANSACTION_NONE             ((psa_crypto_transaction_type_t) 0x0000)
219
220
/** A key creation transaction.
221
 *
222
 * This is only used for keys in an external cryptoprocessor (secure element).
223
 * Keys in RAM or in internal storage are created atomically in storage
224
 * (simple file creation), so they do not need a transaction mechanism.
225
 */
226
0
#define PSA_CRYPTO_TRANSACTION_CREATE_KEY       ((psa_crypto_transaction_type_t) 0x0001)
227
228
/** A key destruction transaction.
229
 *
230
 * This is only used for keys in an external cryptoprocessor (secure element).
231
 * Keys in RAM or in internal storage are destroyed atomically in storage
232
 * (simple file deletion), so they do not need a transaction mechanism.
233
 */
234
0
#define PSA_CRYPTO_TRANSACTION_DESTROY_KEY      ((psa_crypto_transaction_type_t) 0x0002)
235
236
/** Transaction data.
237
 *
238
 * This type is designed to be serialized by writing the memory representation
239
 * and reading it back on the same device.
240
 *
241
 * \note The transaction mechanism is not thread-safe. There can only be one
242
 *       single active transaction at a time.
243
 *       The transaction object is #psa_crypto_transaction.
244
 *
245
 * \note If an API call starts a transaction, it must complete this transaction
246
 *       before returning to the application.
247
 *
248
 * The lifetime of a transaction is the following (note that only one
249
 * transaction may be active at a time):
250
 *
251
 * -# Call psa_crypto_prepare_transaction() to initialize the transaction
252
 *    object in memory and declare the type of transaction that is starting.
253
 * -# Fill in the type-specific fields of #psa_crypto_transaction.
254
 * -# Call psa_crypto_save_transaction() to start the transaction. This
255
 *    saves the transaction data to internal storage.
256
 * -# Perform the work of the transaction by modifying files, contacting
257
 *    external entities, or whatever needs doing. Note that the transaction
258
 *    may be interrupted by a power failure, so you need to have a way
259
 *    recover from interruptions either by undoing what has been done
260
 *    so far or by resuming where you left off.
261
 * -# If there are intermediate stages in the transaction, update
262
 *    the fields of #psa_crypto_transaction and call
263
 *    psa_crypto_save_transaction() again when each stage is reached.
264
 * -# When the transaction is over, call psa_crypto_stop_transaction() to
265
 *    remove the transaction data in storage and in memory.
266
 *
267
 * If the system crashes while a transaction is in progress, psa_crypto_init()
268
 * calls psa_crypto_load_transaction() and takes care of completing or
269
 * rewinding the transaction. This is done in psa_crypto_recover_transaction()
270
 * in psa_crypto.c. If you add a new type of transaction, be
271
 * sure to add code for it in psa_crypto_recover_transaction().
272
 */
273
typedef union {
274
    /* Each element of this union must have the following properties
275
     * to facilitate serialization and deserialization:
276
     *
277
     * - The element is a struct.
278
     * - The first field of the struct is `psa_crypto_transaction_type_t type`.
279
     * - Elements of the struct are arranged such a way that there is
280
     *   no padding.
281
     */
282
    struct psa_crypto_transaction_unknown_s {
283
        psa_crypto_transaction_type_t type;
284
        uint16_t unused1;
285
        uint32_t unused2;
286
        uint64_t unused3;
287
        uint64_t unused4;
288
    } unknown;
289
    /* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or
290
     * #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */
291
    struct psa_crypto_transaction_key_s {
292
        psa_crypto_transaction_type_t type;
293
        uint16_t unused1;
294
        psa_key_lifetime_t lifetime;
295
        psa_key_slot_number_t slot;
296
        mbedtls_svc_key_id_t id;
297
    } key;
298
} psa_crypto_transaction_t;
299
300
/** The single active transaction.
301
 */
302
extern psa_crypto_transaction_t psa_crypto_transaction;
303
304
/** Prepare for a transaction.
305
 *
306
 * There must not be an ongoing transaction.
307
 *
308
 * \param type          The type of transaction to start.
309
 */
310
static inline void psa_crypto_prepare_transaction(
311
    psa_crypto_transaction_type_t type)
312
0
{
313
0
    psa_crypto_transaction.unknown.type = type;
314
0
}
Unexecuted instantiation: psa_crypto_helpers.c:psa_crypto_prepare_transaction
Unexecuted instantiation: psa_crypto.c:psa_crypto_prepare_transaction
Unexecuted instantiation: psa_crypto_slot_management.c:psa_crypto_prepare_transaction
Unexecuted instantiation: psa_crypto_storage.c:psa_crypto_prepare_transaction
315
316
/** Save the transaction data to storage.
317
 *
318
 * You may call this function multiple times during a transaction to
319
 * atomically update the transaction state.
320
 *
321
 * \retval #PSA_SUCCESS \emptydescription
322
 * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
323
 * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
324
 * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
325
 */
326
psa_status_t psa_crypto_save_transaction(void);
327
328
/** Load the transaction data from storage, if any.
329
 *
330
 * This function is meant to be called from psa_crypto_init() to recover
331
 * in case a transaction was interrupted by a system crash.
332
 *
333
 * \retval #PSA_SUCCESS
334
 *         The data about the ongoing transaction has been loaded to
335
 *         #psa_crypto_transaction.
336
 * \retval #PSA_ERROR_DOES_NOT_EXIST
337
 *         There is no ongoing transaction.
338
 * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
339
 * \retval #PSA_ERROR_DATA_INVALID \emptydescription
340
 * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
341
 */
342
psa_status_t psa_crypto_load_transaction(void);
343
344
/** Indicate that the current transaction is finished.
345
 *
346
 * Call this function at the very end of transaction processing.
347
 * This function does not "commit" or "abort" the transaction: the storage
348
 * subsystem has no concept of "commit" and "abort", just saving and
349
 * removing the transaction information in storage.
350
 *
351
 * This function erases the transaction data in storage (if any) and
352
 * resets the transaction data in memory.
353
 *
354
 * \retval #PSA_SUCCESS
355
 *         There was transaction data in storage.
356
 * \retval #PSA_ERROR_DOES_NOT_EXIST
357
 *         There was no transaction data in storage.
358
 * \retval #PSA_ERROR_STORAGE_FAILURE
359
 *         It was impossible to determine whether there was transaction data
360
 *         in storage, or the transaction data could not be erased.
361
 */
362
psa_status_t psa_crypto_stop_transaction(void);
363
364
/** The ITS file identifier for the transaction data.
365
 *
366
 * 0xffffffNN = special file; 0x74 = 't' for transaction.
367
 */
368
0
#define PSA_CRYPTO_ITS_TRANSACTION_UID ((psa_key_id_t) 0xffffff74)
369
370
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
371
372
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
373
/** Backend side of mbedtls_psa_inject_entropy().
374
 *
375
 * This function stores the supplied data into the entropy seed file.
376
 *
377
 * \retval #PSA_SUCCESS
378
 *         Success
379
 * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
380
 * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
381
 * \retval #PSA_ERROR_NOT_PERMITTED
382
 *         The entropy seed file already exists.
383
 */
384
psa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed,
385
                                                size_t seed_size);
386
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
387
388
#ifdef __cplusplus
389
}
390
#endif
391
392
#endif /* PSA_CRYPTO_STORAGE_H */