/src/mbedtls/library/psa_crypto_storage.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * PSA persistent key storage |
3 | | */ |
4 | | /* |
5 | | * Copyright The Mbed TLS Contributors |
6 | | * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later |
7 | | */ |
8 | | |
9 | | #include "common.h" |
10 | | |
11 | | #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) |
12 | | |
13 | | #include <stdlib.h> |
14 | | #include <string.h> |
15 | | |
16 | | #include "psa/crypto.h" |
17 | | #include "psa_crypto_storage.h" |
18 | | #include "mbedtls/platform_util.h" |
19 | | |
20 | | #if defined(MBEDTLS_PSA_ITS_FILE_C) |
21 | | #include "psa_crypto_its.h" |
22 | | #else /* Native ITS implementation */ |
23 | | #include "psa/error.h" |
24 | | #include "psa/internal_trusted_storage.h" |
25 | | #endif |
26 | | |
27 | | #include "mbedtls/platform.h" |
28 | | |
29 | | |
30 | | |
31 | | /****************************************************************/ |
32 | | /* Key storage */ |
33 | | /****************************************************************/ |
34 | | |
35 | | /* Determine a file name (ITS file identifier) for the given key identifier. |
36 | | * The file name must be distinct from any file that is used for a purpose |
37 | | * other than storing a key. Currently, the only such file is the random seed |
38 | | * file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is |
39 | | * 0xFFFFFF52. */ |
40 | | static psa_storage_uid_t psa_its_identifier_of_slot(mbedtls_svc_key_id_t key) |
41 | 35 | { |
42 | | #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) |
43 | | /* Encode the owner in the upper 32 bits. This means that if |
44 | | * owner values are nonzero (as they are on a PSA platform), |
45 | | * no key file will ever have a value less than 0x100000000, so |
46 | | * the whole range 0..0xffffffff is available for non-key files. */ |
47 | | uint32_t unsigned_owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key); |
48 | | return ((uint64_t) unsigned_owner_id << 32) | |
49 | | MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); |
50 | | #else |
51 | | /* Use the key id directly as a file name. |
52 | | * psa_is_key_id_valid() in psa_crypto_slot_management.c |
53 | | * is responsible for ensuring that key identifiers do not have a |
54 | | * value that is reserved for non-key files. */ |
55 | 35 | return key; |
56 | 35 | #endif |
57 | 35 | } |
58 | | |
59 | | /** |
60 | | * \brief Load persistent data for the given key slot number. |
61 | | * |
62 | | * This function reads data from a storage backend and returns the data in a |
63 | | * buffer. |
64 | | * |
65 | | * \param key Persistent identifier of the key to be loaded. This |
66 | | * should be an occupied storage location. |
67 | | * \param[out] data Buffer where the data is to be written. |
68 | | * \param data_size Size of the \c data buffer in bytes. |
69 | | * |
70 | | * \retval #PSA_SUCCESS \emptydescription |
71 | | * \retval #PSA_ERROR_DATA_INVALID \emptydescription |
72 | | * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription |
73 | | * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription |
74 | | * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription |
75 | | */ |
76 | | static psa_status_t psa_crypto_storage_load( |
77 | | const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size) |
78 | 0 | { |
79 | 0 | psa_status_t status; |
80 | 0 | psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); |
81 | 0 | struct psa_storage_info_t data_identifier_info; |
82 | 0 | size_t data_length = 0; |
83 | |
|
84 | 0 | status = psa_its_get_info(data_identifier, &data_identifier_info); |
85 | 0 | if (status != PSA_SUCCESS) { |
86 | 0 | return status; |
87 | 0 | } |
88 | | |
89 | 0 | status = psa_its_get(data_identifier, 0, (uint32_t) data_size, data, &data_length); |
90 | 0 | if (data_size != data_length) { |
91 | 0 | return PSA_ERROR_DATA_INVALID; |
92 | 0 | } |
93 | | |
94 | 0 | return status; |
95 | 0 | } |
96 | | |
97 | | int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key) |
98 | 0 | { |
99 | 0 | psa_status_t ret; |
100 | 0 | psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); |
101 | 0 | struct psa_storage_info_t data_identifier_info; |
102 | |
|
103 | 0 | ret = psa_its_get_info(data_identifier, &data_identifier_info); |
104 | |
|
105 | 0 | if (ret == PSA_ERROR_DOES_NOT_EXIST) { |
106 | 0 | return 0; |
107 | 0 | } |
108 | 0 | return 1; |
109 | 0 | } |
110 | | |
111 | | /** |
112 | | * \brief Store persistent data for the given key slot number. |
113 | | * |
114 | | * This function stores the given data buffer to a persistent storage. |
115 | | * |
116 | | * \param key Persistent identifier of the key to be stored. This |
117 | | * should be an unoccupied storage location. |
118 | | * \param[in] data Buffer containing the data to be stored. |
119 | | * \param data_length The number of bytes |
120 | | * that make up the data. |
121 | | * |
122 | | * \retval #PSA_SUCCESS \emptydescription |
123 | | * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription |
124 | | * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription |
125 | | * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription |
126 | | * \retval #PSA_ERROR_DATA_INVALID \emptydescription |
127 | | */ |
128 | | static psa_status_t psa_crypto_storage_store(const mbedtls_svc_key_id_t key, |
129 | | const uint8_t *data, |
130 | | size_t data_length) |
131 | 0 | { |
132 | 0 | psa_status_t status; |
133 | 0 | psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); |
134 | 0 | struct psa_storage_info_t data_identifier_info; |
135 | |
|
136 | 0 | if (psa_is_key_present_in_storage(key) == 1) { |
137 | 0 | return PSA_ERROR_ALREADY_EXISTS; |
138 | 0 | } |
139 | | |
140 | 0 | status = psa_its_set(data_identifier, (uint32_t) data_length, data, 0); |
141 | 0 | if (status != PSA_SUCCESS) { |
142 | 0 | return PSA_ERROR_DATA_INVALID; |
143 | 0 | } |
144 | | |
145 | 0 | status = psa_its_get_info(data_identifier, &data_identifier_info); |
146 | 0 | if (status != PSA_SUCCESS) { |
147 | 0 | goto exit; |
148 | 0 | } |
149 | | |
150 | 0 | if (data_identifier_info.size != data_length) { |
151 | 0 | status = PSA_ERROR_DATA_INVALID; |
152 | 0 | goto exit; |
153 | 0 | } |
154 | | |
155 | 0 | exit: |
156 | 0 | if (status != PSA_SUCCESS) { |
157 | | /* Remove the file in case we managed to create it but something |
158 | | * went wrong. It's ok if the file doesn't exist. If the file exists |
159 | | * but the removal fails, we're already reporting an error so there's |
160 | | * nothing else we can do. */ |
161 | 0 | (void) psa_its_remove(data_identifier); |
162 | 0 | } |
163 | 0 | return status; |
164 | 0 | } |
165 | | |
166 | | psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key) |
167 | 0 | { |
168 | 0 | psa_status_t ret; |
169 | 0 | psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); |
170 | 0 | struct psa_storage_info_t data_identifier_info; |
171 | |
|
172 | 0 | ret = psa_its_get_info(data_identifier, &data_identifier_info); |
173 | 0 | if (ret == PSA_ERROR_DOES_NOT_EXIST) { |
174 | 0 | return PSA_SUCCESS; |
175 | 0 | } |
176 | | |
177 | 0 | if (psa_its_remove(data_identifier) != PSA_SUCCESS) { |
178 | 0 | return PSA_ERROR_DATA_INVALID; |
179 | 0 | } |
180 | | |
181 | 0 | ret = psa_its_get_info(data_identifier, &data_identifier_info); |
182 | 0 | if (ret != PSA_ERROR_DOES_NOT_EXIST) { |
183 | 0 | return PSA_ERROR_DATA_INVALID; |
184 | 0 | } |
185 | | |
186 | 0 | return PSA_SUCCESS; |
187 | 0 | } |
188 | | |
189 | | /** |
190 | | * \brief Get data length for given key slot number. |
191 | | * |
192 | | * \param key Persistent identifier whose stored data length |
193 | | * is to be obtained. |
194 | | * \param[out] data_length The number of bytes that make up the data. |
195 | | * |
196 | | * \retval #PSA_SUCCESS \emptydescription |
197 | | * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription |
198 | | * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription |
199 | | * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription |
200 | | */ |
201 | | static psa_status_t psa_crypto_storage_get_data_length( |
202 | | const mbedtls_svc_key_id_t key, |
203 | | size_t *data_length) |
204 | 35 | { |
205 | 35 | psa_status_t status; |
206 | 35 | psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); |
207 | 35 | struct psa_storage_info_t data_identifier_info; |
208 | | |
209 | 35 | status = psa_its_get_info(data_identifier, &data_identifier_info); |
210 | 35 | if (status != PSA_SUCCESS) { |
211 | 35 | return status; |
212 | 35 | } |
213 | | |
214 | 0 | *data_length = (size_t) data_identifier_info.size; |
215 | |
|
216 | 0 | return PSA_SUCCESS; |
217 | 35 | } |
218 | | |
219 | | /** |
220 | | * Persistent key storage magic header. |
221 | | */ |
222 | 0 | #define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY" |
223 | 0 | #define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH (sizeof(PSA_KEY_STORAGE_MAGIC_HEADER)) |
224 | | |
225 | | typedef struct { |
226 | | uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH]; |
227 | | uint8_t version[4]; |
228 | | uint8_t lifetime[sizeof(psa_key_lifetime_t)]; |
229 | | uint8_t type[2]; |
230 | | uint8_t bits[2]; |
231 | | uint8_t policy[sizeof(psa_key_policy_t)]; |
232 | | uint8_t data_len[4]; |
233 | | uint8_t key_data[]; |
234 | | } psa_persistent_key_storage_format; |
235 | | |
236 | | void psa_format_key_data_for_storage(const uint8_t *data, |
237 | | const size_t data_length, |
238 | | const psa_key_attributes_t *attr, |
239 | | uint8_t *storage_data) |
240 | 0 | { |
241 | 0 | psa_persistent_key_storage_format *storage_format = |
242 | 0 | (psa_persistent_key_storage_format *) storage_data; |
243 | |
|
244 | 0 | memcpy(storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, |
245 | 0 | PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH); |
246 | 0 | MBEDTLS_PUT_UINT32_LE(0, storage_format->version, 0); |
247 | 0 | MBEDTLS_PUT_UINT32_LE(attr->lifetime, storage_format->lifetime, 0); |
248 | 0 | MBEDTLS_PUT_UINT16_LE((uint16_t) attr->type, storage_format->type, 0); |
249 | 0 | MBEDTLS_PUT_UINT16_LE((uint16_t) attr->bits, storage_format->bits, 0); |
250 | 0 | MBEDTLS_PUT_UINT32_LE(attr->policy.usage, storage_format->policy, 0); |
251 | 0 | MBEDTLS_PUT_UINT32_LE(attr->policy.alg, storage_format->policy, sizeof(uint32_t)); |
252 | 0 | MBEDTLS_PUT_UINT32_LE(attr->policy.alg2, storage_format->policy, 2 * sizeof(uint32_t)); |
253 | 0 | MBEDTLS_PUT_UINT32_LE(data_length, storage_format->data_len, 0); |
254 | 0 | memcpy(storage_format->key_data, data, data_length); |
255 | 0 | } |
256 | | |
257 | | static psa_status_t check_magic_header(const uint8_t *data) |
258 | 0 | { |
259 | 0 | if (memcmp(data, PSA_KEY_STORAGE_MAGIC_HEADER, |
260 | 0 | PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH) != 0) { |
261 | 0 | return PSA_ERROR_DATA_INVALID; |
262 | 0 | } |
263 | 0 | return PSA_SUCCESS; |
264 | 0 | } |
265 | | |
266 | | psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data, |
267 | | size_t storage_data_length, |
268 | | uint8_t **key_data, |
269 | | size_t *key_data_length, |
270 | | psa_key_attributes_t *attr) |
271 | 0 | { |
272 | 0 | psa_status_t status; |
273 | 0 | const psa_persistent_key_storage_format *storage_format = |
274 | 0 | (const psa_persistent_key_storage_format *) storage_data; |
275 | 0 | uint32_t version; |
276 | |
|
277 | 0 | if (storage_data_length < sizeof(*storage_format)) { |
278 | 0 | return PSA_ERROR_DATA_INVALID; |
279 | 0 | } |
280 | | |
281 | 0 | status = check_magic_header(storage_data); |
282 | 0 | if (status != PSA_SUCCESS) { |
283 | 0 | return status; |
284 | 0 | } |
285 | | |
286 | 0 | version = MBEDTLS_GET_UINT32_LE(storage_format->version, 0); |
287 | 0 | if (version != 0) { |
288 | 0 | return PSA_ERROR_DATA_INVALID; |
289 | 0 | } |
290 | | |
291 | 0 | *key_data_length = MBEDTLS_GET_UINT32_LE(storage_format->data_len, 0); |
292 | 0 | if (*key_data_length > (storage_data_length - sizeof(*storage_format)) || |
293 | 0 | *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) { |
294 | 0 | return PSA_ERROR_DATA_INVALID; |
295 | 0 | } |
296 | | |
297 | 0 | if (*key_data_length == 0) { |
298 | 0 | *key_data = NULL; |
299 | 0 | } else { |
300 | 0 | *key_data = mbedtls_calloc(1, *key_data_length); |
301 | 0 | if (*key_data == NULL) { |
302 | 0 | return PSA_ERROR_INSUFFICIENT_MEMORY; |
303 | 0 | } |
304 | 0 | memcpy(*key_data, storage_format->key_data, *key_data_length); |
305 | 0 | } |
306 | | |
307 | 0 | attr->lifetime = MBEDTLS_GET_UINT32_LE(storage_format->lifetime, 0); |
308 | 0 | attr->type = MBEDTLS_GET_UINT16_LE(storage_format->type, 0); |
309 | 0 | attr->bits = MBEDTLS_GET_UINT16_LE(storage_format->bits, 0); |
310 | 0 | attr->policy.usage = MBEDTLS_GET_UINT32_LE(storage_format->policy, 0); |
311 | 0 | attr->policy.alg = MBEDTLS_GET_UINT32_LE(storage_format->policy, sizeof(uint32_t)); |
312 | 0 | attr->policy.alg2 = MBEDTLS_GET_UINT32_LE(storage_format->policy, 2 * sizeof(uint32_t)); |
313 | |
|
314 | 0 | return PSA_SUCCESS; |
315 | 0 | } |
316 | | |
317 | | psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr, |
318 | | const uint8_t *data, |
319 | | const size_t data_length) |
320 | 0 | { |
321 | 0 | size_t storage_data_length; |
322 | 0 | uint8_t *storage_data; |
323 | 0 | psa_status_t status; |
324 | | |
325 | | /* All keys saved to persistent storage always have a key context */ |
326 | 0 | if (data == NULL || data_length == 0) { |
327 | 0 | return PSA_ERROR_INVALID_ARGUMENT; |
328 | 0 | } |
329 | | |
330 | 0 | if (data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) { |
331 | 0 | return PSA_ERROR_INSUFFICIENT_STORAGE; |
332 | 0 | } |
333 | 0 | storage_data_length = data_length + sizeof(psa_persistent_key_storage_format); |
334 | |
|
335 | 0 | storage_data = mbedtls_calloc(1, storage_data_length); |
336 | 0 | if (storage_data == NULL) { |
337 | 0 | return PSA_ERROR_INSUFFICIENT_MEMORY; |
338 | 0 | } |
339 | | |
340 | 0 | psa_format_key_data_for_storage(data, data_length, attr, storage_data); |
341 | |
|
342 | 0 | status = psa_crypto_storage_store(attr->id, |
343 | 0 | storage_data, storage_data_length); |
344 | |
|
345 | 0 | mbedtls_zeroize_and_free(storage_data, storage_data_length); |
346 | |
|
347 | 0 | return status; |
348 | 0 | } |
349 | | |
350 | | void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length) |
351 | 35 | { |
352 | 35 | mbedtls_zeroize_and_free(key_data, key_data_length); |
353 | 35 | } |
354 | | |
355 | | psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr, |
356 | | uint8_t **data, |
357 | | size_t *data_length) |
358 | 35 | { |
359 | 35 | psa_status_t status = PSA_SUCCESS; |
360 | 35 | uint8_t *loaded_data; |
361 | 35 | size_t storage_data_length = 0; |
362 | 35 | mbedtls_svc_key_id_t key = attr->id; |
363 | | |
364 | 35 | status = psa_crypto_storage_get_data_length(key, &storage_data_length); |
365 | 35 | if (status != PSA_SUCCESS) { |
366 | 35 | return status; |
367 | 35 | } |
368 | | |
369 | 0 | loaded_data = mbedtls_calloc(1, storage_data_length); |
370 | |
|
371 | 0 | if (loaded_data == NULL) { |
372 | 0 | return PSA_ERROR_INSUFFICIENT_MEMORY; |
373 | 0 | } |
374 | | |
375 | 0 | status = psa_crypto_storage_load(key, loaded_data, storage_data_length); |
376 | 0 | if (status != PSA_SUCCESS) { |
377 | 0 | goto exit; |
378 | 0 | } |
379 | | |
380 | 0 | status = psa_parse_key_data_from_storage(loaded_data, storage_data_length, |
381 | 0 | data, data_length, attr); |
382 | | |
383 | | /* All keys saved to persistent storage always have a key context */ |
384 | 0 | if (status == PSA_SUCCESS && |
385 | 0 | (*data == NULL || *data_length == 0)) { |
386 | 0 | status = PSA_ERROR_STORAGE_FAILURE; |
387 | 0 | } |
388 | |
|
389 | 0 | exit: |
390 | 0 | mbedtls_zeroize_and_free(loaded_data, storage_data_length); |
391 | 0 | return status; |
392 | 0 | } |
393 | | |
394 | | |
395 | | |
396 | | /****************************************************************/ |
397 | | /* Transactions */ |
398 | | /****************************************************************/ |
399 | | |
400 | | #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) |
401 | | |
402 | | psa_crypto_transaction_t psa_crypto_transaction; |
403 | | |
404 | | psa_status_t psa_crypto_save_transaction(void) |
405 | | { |
406 | | struct psa_storage_info_t p_info; |
407 | | psa_status_t status; |
408 | | status = psa_its_get_info(PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info); |
409 | | if (status == PSA_SUCCESS) { |
410 | | /* This shouldn't happen: we're trying to start a transaction while |
411 | | * there is still a transaction that hasn't been replayed. */ |
412 | | return PSA_ERROR_CORRUPTION_DETECTED; |
413 | | } else if (status != PSA_ERROR_DOES_NOT_EXIST) { |
414 | | return status; |
415 | | } |
416 | | return psa_its_set(PSA_CRYPTO_ITS_TRANSACTION_UID, |
417 | | sizeof(psa_crypto_transaction), |
418 | | &psa_crypto_transaction, |
419 | | 0); |
420 | | } |
421 | | |
422 | | psa_status_t psa_crypto_load_transaction(void) |
423 | | { |
424 | | psa_status_t status; |
425 | | size_t length; |
426 | | status = psa_its_get(PSA_CRYPTO_ITS_TRANSACTION_UID, 0, |
427 | | sizeof(psa_crypto_transaction), |
428 | | &psa_crypto_transaction, &length); |
429 | | if (status != PSA_SUCCESS) { |
430 | | return status; |
431 | | } |
432 | | if (length != sizeof(psa_crypto_transaction)) { |
433 | | return PSA_ERROR_DATA_INVALID; |
434 | | } |
435 | | return PSA_SUCCESS; |
436 | | } |
437 | | |
438 | | psa_status_t psa_crypto_stop_transaction(void) |
439 | | { |
440 | | psa_status_t status = psa_its_remove(PSA_CRYPTO_ITS_TRANSACTION_UID); |
441 | | /* Whether or not updating the storage succeeded, the transaction is |
442 | | * finished now. It's too late to go back, so zero out the in-memory |
443 | | * data. */ |
444 | | memset(&psa_crypto_transaction, 0, sizeof(psa_crypto_transaction)); |
445 | | return status; |
446 | | } |
447 | | |
448 | | #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ |
449 | | |
450 | | |
451 | | |
452 | | /****************************************************************/ |
453 | | /* Random generator state */ |
454 | | /****************************************************************/ |
455 | | |
456 | | #if defined(MBEDTLS_PSA_INJECT_ENTROPY) |
457 | | psa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed, |
458 | | size_t seed_size) |
459 | | { |
460 | | psa_status_t status; |
461 | | struct psa_storage_info_t p_info; |
462 | | |
463 | | status = psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info); |
464 | | |
465 | | if (PSA_ERROR_DOES_NOT_EXIST == status) { /* No seed exists */ |
466 | | status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0); |
467 | | } else if (PSA_SUCCESS == status) { |
468 | | /* You should not be here. Seed needs to be injected only once */ |
469 | | status = PSA_ERROR_NOT_PERMITTED; |
470 | | } |
471 | | return status; |
472 | | } |
473 | | #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ |
474 | | |
475 | | |
476 | | |
477 | | /****************************************************************/ |
478 | | /* The end */ |
479 | | /****************************************************************/ |
480 | | |
481 | | #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ |