recover_pk Flake8 ignore E501
[RRG-proxmark3.git] / common / mbedtls / psa_crypto_slot_management.c
blobed7da73d4f2bf13cb6594a83e081c5526ce78947
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
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 #include "common.h"
23 #if defined(MBEDTLS_PSA_CRYPTO_C)
25 #include "psa_crypto_service_integration.h"
26 #include "psa/crypto.h"
28 #include "psa_crypto_core.h"
29 #include "psa_crypto_slot_management.h"
30 #include "psa_crypto_storage.h"
31 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
32 #include "psa_crypto_se.h"
33 #endif
35 #include <stdlib.h>
36 #include <string.h>
37 #if defined(MBEDTLS_PLATFORM_C)
38 #include "mbedtls/platform.h"
39 #else
40 #define mbedtls_calloc calloc
41 #define mbedtls_free free
42 #endif
44 #define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) )
46 typedef struct {
47 psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT];
48 unsigned key_slots_initialized : 1;
49 } psa_global_data_t;
51 static psa_global_data_t global_data;
53 psa_status_t psa_validate_key_id(
54 mbedtls_svc_key_id_t key, int vendor_ok) {
55 psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
57 if ((PSA_KEY_ID_USER_MIN <= key_id) &&
58 (key_id <= PSA_KEY_ID_USER_MAX))
59 return (PSA_SUCCESS);
61 if (vendor_ok &&
62 (PSA_KEY_ID_VENDOR_MIN <= key_id) &&
63 (key_id <= PSA_KEY_ID_VENDOR_MAX))
64 return (PSA_SUCCESS);
66 return (PSA_ERROR_INVALID_HANDLE);
69 /** Get the description in memory of a key given its identifier and lock it.
71 * The descriptions of volatile keys and loaded persistent keys are
72 * stored in key slots. This function returns a pointer to the key slot
73 * containing the description of a key given its identifier.
75 * The function searches the key slots containing the description of the key
76 * with \p key identifier. The function does only read accesses to the key
77 * slots. The function does not load any persistent key thus does not access
78 * any storage.
80 * For volatile key identifiers, only one key slot is queried as a volatile
81 * key with identifier key_id can only be stored in slot of index
82 * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ).
84 * On success, the function locks the key slot. It is the responsibility of
85 * the caller to unlock the key slot when it does not access it anymore.
87 * \param key Key identifier to query.
88 * \param[out] p_slot On success, `*p_slot` contains a pointer to the
89 * key slot containing the description of the key
90 * identified by \p key.
92 * \retval #PSA_SUCCESS
93 * The pointer to the key slot containing the description of the key
94 * identified by \p key was returned.
95 * \retval #PSA_ERROR_INVALID_HANDLE
96 * \p key is not a valid key identifier.
97 * \retval #PSA_ERROR_DOES_NOT_EXIST
98 * There is no key with key identifier \p key in the key slots.
100 static psa_status_t psa_get_and_lock_key_slot_in_memory(
101 mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot) {
102 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
103 psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
104 size_t slot_idx;
105 psa_key_slot_t *slot = NULL;
107 if (psa_key_id_is_volatile(key_id)) {
108 slot = &global_data.key_slots[ key_id - PSA_KEY_ID_VOLATILE_MIN ];
111 * Check if both the PSA key identifier key_id and the owner
112 * identifier of key match those of the key slot.
114 * Note that, if the key slot is not occupied, its PSA key identifier
115 * is equal to zero. This is an invalid value for a PSA key identifier
116 * and thus cannot be equal to the valid PSA key identifier key_id.
118 status = mbedtls_svc_key_id_equal(key, slot->attr.id) ?
119 PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
120 } else {
121 status = psa_validate_key_id(key, 1);
122 if (status != PSA_SUCCESS)
123 return (status);
125 for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
126 slot = &global_data.key_slots[ slot_idx ];
127 if (mbedtls_svc_key_id_equal(key, slot->attr.id))
128 break;
130 status = (slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT) ?
131 PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
134 if (status == PSA_SUCCESS) {
135 status = psa_lock_key_slot(slot);
136 if (status == PSA_SUCCESS)
137 *p_slot = slot;
140 return (status);
143 psa_status_t psa_initialize_key_slots(void) {
144 /* Nothing to do: program startup and psa_wipe_all_key_slots() both
145 * guarantee that the key slots are initialized to all-zero, which
146 * means that all the key slots are in a valid, empty state. */
147 global_data.key_slots_initialized = 1;
148 return (PSA_SUCCESS);
151 void psa_wipe_all_key_slots(void) {
152 size_t slot_idx;
154 for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
155 psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
156 slot->lock_count = 1;
157 (void) psa_wipe_key_slot(slot);
159 global_data.key_slots_initialized = 0;
162 psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id,
163 psa_key_slot_t **p_slot) {
164 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
165 size_t slot_idx;
166 psa_key_slot_t *selected_slot, *unlocked_persistent_key_slot;
168 if (! global_data.key_slots_initialized) {
169 status = PSA_ERROR_BAD_STATE;
170 goto error;
173 selected_slot = unlocked_persistent_key_slot = NULL;
174 for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
175 psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
176 if (! psa_is_key_slot_occupied(slot)) {
177 selected_slot = slot;
178 break;
181 if ((unlocked_persistent_key_slot == NULL) &&
182 (! PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) &&
183 (! psa_is_key_slot_locked(slot)))
184 unlocked_persistent_key_slot = slot;
188 * If there is no unused key slot and there is at least one unlocked key
189 * slot containing the description of a persistent key, recycle the first
190 * such key slot we encountered. If we later need to operate on the
191 * persistent key we are evicting now, we will reload its description from
192 * storage.
194 if ((selected_slot == NULL) &&
195 (unlocked_persistent_key_slot != NULL)) {
196 selected_slot = unlocked_persistent_key_slot;
197 selected_slot->lock_count = 1;
198 psa_wipe_key_slot(selected_slot);
201 if (selected_slot != NULL) {
202 status = psa_lock_key_slot(selected_slot);
203 if (status != PSA_SUCCESS)
204 goto error;
206 *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN +
207 ((psa_key_id_t)(selected_slot - global_data.key_slots));
208 *p_slot = selected_slot;
210 return (PSA_SUCCESS);
212 status = PSA_ERROR_INSUFFICIENT_MEMORY;
214 error:
215 *p_slot = NULL;
216 *volatile_key_id = 0;
218 return (status);
221 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
222 static psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot) {
223 psa_status_t status = PSA_SUCCESS;
224 uint8_t *key_data = NULL;
225 size_t key_data_length = 0;
227 status = psa_load_persistent_key(&slot->attr,
228 &key_data, &key_data_length);
229 if (status != PSA_SUCCESS)
230 goto exit;
232 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
233 /* Special handling is required for loading keys associated with a
234 * dynamically registered SE interface. */
235 const psa_drv_se_t *drv;
236 psa_drv_se_context_t *drv_context;
237 if (psa_get_se_driver(slot->attr.lifetime, &drv, &drv_context)) {
238 psa_se_key_data_storage_t *data;
240 if (key_data_length != sizeof(*data)) {
241 status = PSA_ERROR_DATA_INVALID;
242 goto exit;
244 data = (psa_se_key_data_storage_t *) key_data;
245 status = psa_copy_key_material_into_slot(
246 slot, data->slot_number, sizeof(data->slot_number));
247 goto exit;
249 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
251 status = psa_copy_key_material_into_slot(slot, key_data, key_data_length);
253 exit:
254 psa_free_persistent_key_data(key_data, key_data_length);
255 return (status);
257 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
259 psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,
260 psa_key_slot_t **p_slot) {
261 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
263 *p_slot = NULL;
264 if (! global_data.key_slots_initialized)
265 return (PSA_ERROR_BAD_STATE);
268 * On success, the pointer to the slot is passed directly to the caller
269 * thus no need to unlock the key slot here.
271 status = psa_get_and_lock_key_slot_in_memory(key, p_slot);
272 if (status != PSA_ERROR_DOES_NOT_EXIST)
273 return (status);
275 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
276 psa_key_id_t volatile_key_id;
278 status = psa_get_empty_key_slot(&volatile_key_id, p_slot);
279 if (status != PSA_SUCCESS)
280 return (status);
282 (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
283 (*p_slot)->attr.id = key;
285 status = psa_load_persistent_key_into_slot(*p_slot);
286 if (status != PSA_SUCCESS)
287 psa_wipe_key_slot(*p_slot);
289 return (status);
290 #else
291 return (PSA_ERROR_DOES_NOT_EXIST);
292 #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
296 psa_status_t psa_unlock_key_slot(psa_key_slot_t *slot) {
297 if (slot == NULL)
298 return (PSA_SUCCESS);
300 if (slot->lock_count > 0) {
301 slot->lock_count--;
302 return (PSA_SUCCESS);
306 * As the return error code may not be handled in case of multiple errors,
307 * do our best to report if the lock counter is equal to zero: if
308 * available call MBEDTLS_PARAM_FAILED that may terminate execution (if
309 * called as part of the execution of a unit test suite this will stop the
310 * test suite execution).
312 #ifdef MBEDTLS_CHECK_PARAMS
313 MBEDTLS_PARAM_FAILED(slot->lock_count > 0);
314 #endif
316 return (PSA_ERROR_CORRUPTION_DETECTED);
319 psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime,
320 psa_se_drv_table_entry_t **p_drv) {
321 if (psa_key_lifetime_is_external(lifetime)) {
322 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
323 /* Check whether a driver is registered against this lifetime */
324 psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime);
325 if (driver != NULL) {
326 if (p_drv != NULL)
327 *p_drv = driver;
328 return (PSA_SUCCESS);
330 #else /* MBEDTLS_PSA_CRYPTO_SE_C */
331 (void) p_drv;
332 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
334 #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
335 /* Key location for external keys gets checked by the wrapper */
336 return (PSA_SUCCESS);
337 #else /* MBEDTLS_PSA_CRYPTO_DRIVERS */
338 /* No support for external lifetimes at all, or dynamic interface
339 * did not find driver for requested lifetime. */
340 return (PSA_ERROR_INVALID_ARGUMENT);
341 #endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
342 } else
343 /* Local/internal keys are always valid */
344 return (PSA_SUCCESS);
347 psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime) {
348 if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {
349 /* Volatile keys are always supported */
350 return (PSA_SUCCESS);
351 } else {
352 /* Persistent keys require storage support */
353 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
354 return (PSA_SUCCESS);
355 #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
356 return (PSA_ERROR_NOT_SUPPORTED);
357 #endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */
361 psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle) {
362 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
363 psa_status_t status;
364 psa_key_slot_t *slot;
366 status = psa_get_and_lock_key_slot(key, &slot);
367 if (status != PSA_SUCCESS) {
368 *handle = PSA_KEY_HANDLE_INIT;
369 return (status);
372 *handle = key;
374 return (psa_unlock_key_slot(slot));
376 #else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
377 (void) key;
378 *handle = PSA_KEY_HANDLE_INIT;
379 return (PSA_ERROR_NOT_SUPPORTED);
380 #endif /* !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
383 psa_status_t psa_close_key(psa_key_handle_t handle) {
384 psa_status_t status;
385 psa_key_slot_t *slot;
387 if (psa_key_handle_is_null(handle))
388 return (PSA_SUCCESS);
390 status = psa_get_and_lock_key_slot_in_memory(handle, &slot);
391 if (status != PSA_SUCCESS)
392 return (status);
394 if (slot->lock_count <= 1)
395 return (psa_wipe_key_slot(slot));
396 else
397 return (psa_unlock_key_slot(slot));
400 psa_status_t psa_purge_key(mbedtls_svc_key_id_t key) {
401 psa_status_t status;
402 psa_key_slot_t *slot;
404 status = psa_get_and_lock_key_slot_in_memory(key, &slot);
405 if (status != PSA_SUCCESS)
406 return (status);
408 if ((! PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) &&
409 (slot->lock_count <= 1))
410 return (psa_wipe_key_slot(slot));
411 else
412 return (psa_unlock_key_slot(slot));
415 void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats) {
416 size_t slot_idx;
418 memset(stats, 0, sizeof(*stats));
420 for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) {
421 const psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
422 if (psa_is_key_slot_locked(slot)) {
423 ++stats->locked_slots;
425 if (! psa_is_key_slot_occupied(slot)) {
426 ++stats->empty_slots;
427 continue;
429 if (slot->attr.lifetime == PSA_KEY_LIFETIME_VOLATILE)
430 ++stats->volatile_slots;
431 else if (slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT) {
432 psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
433 ++stats->persistent_slots;
434 if (id > stats->max_open_internal_key_id)
435 stats->max_open_internal_key_id = id;
436 } else {
437 psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
438 ++stats->external_slots;
439 if (id > stats->max_open_external_key_id)
440 stats->max_open_external_key_id = id;
445 #endif /* MBEDTLS_PSA_CRYPTO_C */