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