1 /*
2  *  PSA crypto layer on top of Mbed TLS crypto
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_C)
12 
13 #include "psa/crypto.h"
14 
15 #include "psa_crypto_core.h"
16 #include "psa_crypto_driver_wrappers_no_static.h"
17 #include "psa_crypto_slot_management.h"
18 #include "psa_crypto_storage.h"
19 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
20 #include "psa_crypto_se.h"
21 #endif
22 
23 #include <stdlib.h>
24 #include <string.h>
25 #include "mbedtls/platform.h"
26 
27 typedef struct {
28     psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT];
29     uint8_t key_slots_initialized;
30 } psa_global_data_t;
31 
32 static psa_global_data_t global_data;
33 
psa_is_valid_key_id(mbedtls_svc_key_id_t key,int vendor_ok)34 int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok)
35 {
36     psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
37 
38     if ((PSA_KEY_ID_USER_MIN <= key_id) &&
39         (key_id <= PSA_KEY_ID_USER_MAX)) {
40         return 1;
41     }
42 
43     if (vendor_ok &&
44         (PSA_KEY_ID_VENDOR_MIN <= key_id) &&
45         (key_id <= PSA_KEY_ID_VENDOR_MAX)) {
46         return 1;
47     }
48 
49     return 0;
50 }
51 
52 /** Get the description in memory of a key given its identifier and lock it.
53  *
54  * The descriptions of volatile keys and loaded persistent keys are
55  * stored in key slots. This function returns a pointer to the key slot
56  * containing the description of a key given its identifier.
57  *
58  * The function searches the key slots containing the description of the key
59  * with \p key identifier. The function does only read accesses to the key
60  * slots. The function does not load any persistent key thus does not access
61  * any storage.
62  *
63  * For volatile key identifiers, only one key slot is queried as a volatile
64  * key with identifier key_id can only be stored in slot of index
65  * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ).
66  *
67  * On success, the function locks the key slot. It is the responsibility of
68  * the caller to unlock the key slot when it does not access it anymore.
69  *
70  * \param key           Key identifier to query.
71  * \param[out] p_slot   On success, `*p_slot` contains a pointer to the
72  *                      key slot containing the description of the key
73  *                      identified by \p key.
74  *
75  * \retval #PSA_SUCCESS
76  *         The pointer to the key slot containing the description of the key
77  *         identified by \p key was returned.
78  * \retval #PSA_ERROR_INVALID_HANDLE
79  *         \p key is not a valid key identifier.
80  * \retval #PSA_ERROR_DOES_NOT_EXIST
81  *         There is no key with key identifier \p key in the key slots.
82  */
psa_get_and_lock_key_slot_in_memory(mbedtls_svc_key_id_t key,psa_key_slot_t ** p_slot)83 static psa_status_t psa_get_and_lock_key_slot_in_memory(
84     mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot)
85 {
86     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
87     psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
88     size_t slot_idx;
89     psa_key_slot_t *slot = NULL;
90 
91     if (psa_key_id_is_volatile(key_id)) {
92         slot = &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN];
93 
94         /*
95          * Check if both the PSA key identifier key_id and the owner
96          * identifier of key match those of the key slot.
97          *
98          * Note that, if the key slot is not occupied, its PSA key identifier
99          * is equal to zero. This is an invalid value for a PSA key identifier
100          * and thus cannot be equal to the valid PSA key identifier key_id.
101          */
102         status = mbedtls_svc_key_id_equal(key, slot->attr.id) ?
103                  PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
104     } else {
105         if (!psa_is_valid_key_id(key, 1)) {
106             return PSA_ERROR_INVALID_HANDLE;
107         }
108 
109         for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
110             slot = &global_data.key_slots[slot_idx];
111             if (mbedtls_svc_key_id_equal(key, slot->attr.id)) {
112                 break;
113             }
114         }
115         status = (slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT) ?
116                  PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
117     }
118 
119     if (status == PSA_SUCCESS) {
120         status = psa_lock_key_slot(slot);
121         if (status == PSA_SUCCESS) {
122             *p_slot = slot;
123         }
124     }
125 
126     return status;
127 }
128 
psa_initialize_key_slots(void)129 psa_status_t psa_initialize_key_slots(void)
130 {
131     /* Nothing to do: program startup and psa_wipe_all_key_slots() both
132      * guarantee that the key slots are initialized to all-zero, which
133      * means that all the key slots are in a valid, empty state. */
134     global_data.key_slots_initialized = 1;
135     return PSA_SUCCESS;
136 }
137 
psa_wipe_all_key_slots(void)138 void psa_wipe_all_key_slots(void)
139 {
140     size_t slot_idx;
141 
142     for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
143         psa_key_slot_t *slot = &global_data.key_slots[slot_idx];
144         slot->lock_count = 1;
145         (void) psa_wipe_key_slot(slot);
146     }
147     global_data.key_slots_initialized = 0;
148 }
149 
psa_get_empty_key_slot(psa_key_id_t * volatile_key_id,psa_key_slot_t ** p_slot)150 psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id,
151                                     psa_key_slot_t **p_slot)
152 {
153     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
154     size_t slot_idx;
155     psa_key_slot_t *selected_slot, *unlocked_persistent_key_slot;
156 
157     if (!global_data.key_slots_initialized) {
158         status = PSA_ERROR_BAD_STATE;
159         goto error;
160     }
161 
162     selected_slot = unlocked_persistent_key_slot = NULL;
163     for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
164         psa_key_slot_t *slot = &global_data.key_slots[slot_idx];
165         if (!psa_is_key_slot_occupied(slot)) {
166             selected_slot = slot;
167             break;
168         }
169 
170         if ((unlocked_persistent_key_slot == NULL) &&
171             (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) &&
172             (!psa_is_key_slot_locked(slot))) {
173             unlocked_persistent_key_slot = slot;
174         }
175     }
176 
177     /*
178      * If there is no unused key slot and there is at least one unlocked key
179      * slot containing the description of a persistent key, recycle the first
180      * such key slot we encountered. If we later need to operate on the
181      * persistent key we are evicting now, we will reload its description from
182      * storage.
183      */
184     if ((selected_slot == NULL) &&
185         (unlocked_persistent_key_slot != NULL)) {
186         selected_slot = unlocked_persistent_key_slot;
187         selected_slot->lock_count = 1;
188         psa_wipe_key_slot(selected_slot);
189     }
190 
191     if (selected_slot != NULL) {
192         status = psa_lock_key_slot(selected_slot);
193         if (status != PSA_SUCCESS) {
194             goto error;
195         }
196 
197         *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN +
198                            ((psa_key_id_t) (selected_slot - global_data.key_slots));
199         *p_slot = selected_slot;
200 
201         return PSA_SUCCESS;
202     }
203     status = PSA_ERROR_INSUFFICIENT_MEMORY;
204 
205 error:
206     *p_slot = NULL;
207     *volatile_key_id = 0;
208 
209     return status;
210 }
211 
212 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
psa_load_persistent_key_into_slot(psa_key_slot_t * slot)213 static psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot)
214 {
215     psa_status_t status = PSA_SUCCESS;
216     uint8_t *key_data = NULL;
217     size_t key_data_length = 0;
218 
219     status = psa_load_persistent_key(&slot->attr,
220                                      &key_data, &key_data_length);
221     if (status != PSA_SUCCESS) {
222         goto exit;
223     }
224 
225 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
226     /* Special handling is required for loading keys associated with a
227      * dynamically registered SE interface. */
228     const psa_drv_se_t *drv;
229     psa_drv_se_context_t *drv_context;
230     if (psa_get_se_driver(slot->attr.lifetime, &drv, &drv_context)) {
231         psa_se_key_data_storage_t *data;
232 
233         if (key_data_length != sizeof(*data)) {
234             status = PSA_ERROR_DATA_INVALID;
235             goto exit;
236         }
237         data = (psa_se_key_data_storage_t *) key_data;
238         status = psa_copy_key_material_into_slot(
239             slot, data->slot_number, sizeof(data->slot_number));
240         goto exit;
241     }
242 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
243 
244     status = psa_copy_key_material_into_slot(slot, key_data, key_data_length);
245 
246 exit:
247     psa_free_persistent_key_data(key_data, key_data_length);
248     return status;
249 }
250 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
251 
252 #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
253 
psa_load_builtin_key_into_slot(psa_key_slot_t * slot)254 static psa_status_t psa_load_builtin_key_into_slot(psa_key_slot_t *slot)
255 {
256     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
257     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
258     psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE;
259     psa_drv_slot_number_t slot_number = 0;
260     size_t key_buffer_size = 0;
261     size_t key_buffer_length = 0;
262 
263     if (!psa_key_id_is_builtin(
264             MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id))) {
265         return PSA_ERROR_DOES_NOT_EXIST;
266     }
267 
268     /* Check the platform function to see whether this key actually exists */
269     status = mbedtls_psa_platform_get_builtin_key(
270         slot->attr.id, &lifetime, &slot_number);
271     if (status != PSA_SUCCESS) {
272         return status;
273     }
274 
275     /* Set required key attributes to ensure get_builtin_key can retrieve the
276      * full attributes. */
277     psa_set_key_id(&attributes, slot->attr.id);
278     psa_set_key_lifetime(&attributes, lifetime);
279 
280     /* Get the full key attributes from the driver in order to be able to
281      * calculate the required buffer size. */
282     status = psa_driver_wrapper_get_builtin_key(
283         slot_number, &attributes,
284         NULL, 0, NULL);
285     if (status != PSA_ERROR_BUFFER_TOO_SMALL) {
286         /* Builtin keys cannot be defined by the attributes alone */
287         if (status == PSA_SUCCESS) {
288             status = PSA_ERROR_CORRUPTION_DETECTED;
289         }
290         return status;
291     }
292 
293     /* If the key should exist according to the platform, then ask the driver
294      * what its expected size is. */
295     status = psa_driver_wrapper_get_key_buffer_size(&attributes,
296                                                     &key_buffer_size);
297     if (status != PSA_SUCCESS) {
298         return status;
299     }
300 
301     /* Allocate a buffer of the required size and load the builtin key directly
302      * into the (now properly sized) slot buffer. */
303     status = psa_allocate_buffer_to_slot(slot, key_buffer_size);
304     if (status != PSA_SUCCESS) {
305         return status;
306     }
307 
308     status = psa_driver_wrapper_get_builtin_key(
309         slot_number, &attributes,
310         slot->key.data, slot->key.bytes, &key_buffer_length);
311     if (status != PSA_SUCCESS) {
312         goto exit;
313     }
314 
315     /* Copy actual key length and core attributes into the slot on success */
316     slot->key.bytes = key_buffer_length;
317     slot->attr = attributes.core;
318 
319 exit:
320     if (status != PSA_SUCCESS) {
321         psa_remove_key_data_from_memory(slot);
322     }
323     return status;
324 }
325 #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
326 
psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,psa_key_slot_t ** p_slot)327 psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,
328                                        psa_key_slot_t **p_slot)
329 {
330     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
331 
332     *p_slot = NULL;
333     if (!global_data.key_slots_initialized) {
334         return PSA_ERROR_BAD_STATE;
335     }
336 
337     /*
338      * On success, the pointer to the slot is passed directly to the caller
339      * thus no need to unlock the key slot here.
340      */
341     status = psa_get_and_lock_key_slot_in_memory(key, p_slot);
342     if (status != PSA_ERROR_DOES_NOT_EXIST) {
343         return status;
344     }
345 
346     /* Loading keys from storage requires support for such a mechanism */
347 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \
348     defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
349     psa_key_id_t volatile_key_id;
350 
351     status = psa_get_empty_key_slot(&volatile_key_id, p_slot);
352     if (status != PSA_SUCCESS) {
353         return status;
354     }
355 
356     (*p_slot)->attr.id = key;
357     (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
358 
359     status = PSA_ERROR_DOES_NOT_EXIST;
360 #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
361     /* Load keys in the 'builtin' range through their own interface */
362     status = psa_load_builtin_key_into_slot(*p_slot);
363 #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
364 
365 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
366     if (status == PSA_ERROR_DOES_NOT_EXIST) {
367         status = psa_load_persistent_key_into_slot(*p_slot);
368     }
369 #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
370 
371     if (status != PSA_SUCCESS) {
372         psa_wipe_key_slot(*p_slot);
373         if (status == PSA_ERROR_DOES_NOT_EXIST) {
374             status = PSA_ERROR_INVALID_HANDLE;
375         }
376     } else {
377         /* Add implicit usage flags. */
378         psa_extend_key_usage_flags(&(*p_slot)->attr.policy.usage);
379     }
380 
381     return status;
382 #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
383     return PSA_ERROR_INVALID_HANDLE;
384 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
385 }
386 
psa_unlock_key_slot(psa_key_slot_t * slot)387 psa_status_t psa_unlock_key_slot(psa_key_slot_t *slot)
388 {
389     if (slot == NULL) {
390         return PSA_SUCCESS;
391     }
392 
393     if (slot->lock_count > 0) {
394         slot->lock_count--;
395         return PSA_SUCCESS;
396     }
397 
398     /*
399      * As the return error code may not be handled in case of multiple errors,
400      * do our best to report if the lock counter is equal to zero. Assert with
401      * MBEDTLS_TEST_HOOK_TEST_ASSERT that the lock counter is strictly greater
402      * than zero: if the MBEDTLS_TEST_HOOKS configuration option is enabled and
403      * the function is called as part of the execution of a test suite, the
404      * execution of the test suite is stopped in error if the assertion fails.
405      */
406     MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->lock_count > 0);
407     return PSA_ERROR_CORRUPTION_DETECTED;
408 }
409 
psa_validate_key_location(psa_key_lifetime_t lifetime,psa_se_drv_table_entry_t ** p_drv)410 psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime,
411                                        psa_se_drv_table_entry_t **p_drv)
412 {
413     if (psa_key_lifetime_is_external(lifetime)) {
414 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
415         /* Check whether a driver is registered against this lifetime */
416         psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime);
417         if (driver != NULL) {
418             if (p_drv != NULL) {
419                 *p_drv = driver;
420             }
421             return PSA_SUCCESS;
422         }
423 #else /* MBEDTLS_PSA_CRYPTO_SE_C */
424         (void) p_drv;
425 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
426 
427         /* Key location for external keys gets checked by the wrapper */
428         return PSA_SUCCESS;
429     } else {
430         /* Local/internal keys are always valid */
431         return PSA_SUCCESS;
432     }
433 }
434 
psa_validate_key_persistence(psa_key_lifetime_t lifetime)435 psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime)
436 {
437     if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {
438         /* Volatile keys are always supported */
439         return PSA_SUCCESS;
440     } else {
441         /* Persistent keys require storage support */
442 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
443         if (PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime)) {
444             return PSA_ERROR_INVALID_ARGUMENT;
445         } else {
446             return PSA_SUCCESS;
447         }
448 #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
449         return PSA_ERROR_NOT_SUPPORTED;
450 #endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */
451     }
452 }
453 
psa_open_key(mbedtls_svc_key_id_t key,psa_key_handle_t * handle)454 psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle)
455 {
456 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \
457     defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
458     psa_status_t status;
459     psa_key_slot_t *slot;
460 
461     status = psa_get_and_lock_key_slot(key, &slot);
462     if (status != PSA_SUCCESS) {
463         *handle = PSA_KEY_HANDLE_INIT;
464         if (status == PSA_ERROR_INVALID_HANDLE) {
465             status = PSA_ERROR_DOES_NOT_EXIST;
466         }
467 
468         return status;
469     }
470 
471     *handle = key;
472 
473     return psa_unlock_key_slot(slot);
474 
475 #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
476     (void) key;
477     *handle = PSA_KEY_HANDLE_INIT;
478     return PSA_ERROR_NOT_SUPPORTED;
479 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
480 }
481 
psa_close_key(psa_key_handle_t handle)482 psa_status_t psa_close_key(psa_key_handle_t handle)
483 {
484     psa_status_t status;
485     psa_key_slot_t *slot;
486 
487     if (psa_key_handle_is_null(handle)) {
488         return PSA_SUCCESS;
489     }
490 
491     status = psa_get_and_lock_key_slot_in_memory(handle, &slot);
492     if (status != PSA_SUCCESS) {
493         if (status == PSA_ERROR_DOES_NOT_EXIST) {
494             status = PSA_ERROR_INVALID_HANDLE;
495         }
496 
497         return status;
498     }
499     if (slot->lock_count <= 1) {
500         return psa_wipe_key_slot(slot);
501     } else {
502         return psa_unlock_key_slot(slot);
503     }
504 }
505 
psa_purge_key(mbedtls_svc_key_id_t key)506 psa_status_t psa_purge_key(mbedtls_svc_key_id_t key)
507 {
508     psa_status_t status;
509     psa_key_slot_t *slot;
510 
511     status = psa_get_and_lock_key_slot_in_memory(key, &slot);
512     if (status != PSA_SUCCESS) {
513         return status;
514     }
515 
516     if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) &&
517         (slot->lock_count <= 1)) {
518         return psa_wipe_key_slot(slot);
519     } else {
520         return psa_unlock_key_slot(slot);
521     }
522 }
523 
mbedtls_psa_get_stats(mbedtls_psa_stats_t * stats)524 void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats)
525 {
526     size_t slot_idx;
527 
528     memset(stats, 0, sizeof(*stats));
529 
530     for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
531         const psa_key_slot_t *slot = &global_data.key_slots[slot_idx];
532         if (psa_is_key_slot_locked(slot)) {
533             ++stats->locked_slots;
534         }
535         if (!psa_is_key_slot_occupied(slot)) {
536             ++stats->empty_slots;
537             continue;
538         }
539         if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
540             ++stats->volatile_slots;
541         } else {
542             psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
543             ++stats->persistent_slots;
544             if (id > stats->max_open_internal_key_id) {
545                 stats->max_open_internal_key_id = id;
546             }
547         }
548         if (PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime) !=
549             PSA_KEY_LOCATION_LOCAL_STORAGE) {
550             psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
551             ++stats->external_slots;
552             if (id > stats->max_open_external_key_id) {
553                 stats->max_open_external_key_id = id;
554             }
555         }
556     }
557 }
558 
559 #endif /* MBEDTLS_PSA_CRYPTO_C */
560