psa_crypto_slot_management.c 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132
  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. #include "common.h"
  9. #if defined(MBEDTLS_PSA_CRYPTO_C)
  10. #include "psa/crypto.h"
  11. #include "psa_crypto_core.h"
  12. #include "psa_crypto_driver_wrappers_no_static.h"
  13. #include "psa_crypto_slot_management.h"
  14. #include "psa_crypto_storage.h"
  15. #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
  16. #include "psa_crypto_se.h"
  17. #endif
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include "mbedtls/platform.h"
  21. #if defined(MBEDTLS_THREADING_C)
  22. #include "mbedtls/threading.h"
  23. #endif
  24. /* Make sure we have distinct ranges of key identifiers for distinct
  25. * purposes. */
  26. MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MIN < PSA_KEY_ID_USER_MAX,
  27. "Empty user key ID range");
  28. MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN < PSA_KEY_ID_VENDOR_MAX,
  29. "Empty vendor key ID range");
  30. MBEDTLS_STATIC_ASSERT(MBEDTLS_PSA_KEY_ID_BUILTIN_MIN <= MBEDTLS_PSA_KEY_ID_BUILTIN_MAX,
  31. "Empty builtin key ID range");
  32. MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MIN <= PSA_KEY_ID_VOLATILE_MAX,
  33. "Empty volatile key ID range");
  34. MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MAX < PSA_KEY_ID_VENDOR_MIN ||
  35. PSA_KEY_ID_VENDOR_MAX < PSA_KEY_ID_USER_MIN,
  36. "Overlap between user key IDs and vendor key IDs");
  37. MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN &&
  38. MBEDTLS_PSA_KEY_ID_BUILTIN_MAX <= PSA_KEY_ID_VENDOR_MAX,
  39. "Builtin key identifiers are not in the vendor range");
  40. MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= PSA_KEY_ID_VOLATILE_MIN &&
  41. PSA_KEY_ID_VOLATILE_MAX <= PSA_KEY_ID_VENDOR_MAX,
  42. "Volatile key identifiers are not in the vendor range");
  43. MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MAX < MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ||
  44. MBEDTLS_PSA_KEY_ID_BUILTIN_MAX < PSA_KEY_ID_VOLATILE_MIN,
  45. "Overlap between builtin key IDs and volatile key IDs");
  46. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  47. /* Dynamic key store.
  48. *
  49. * The key store consists of multiple slices.
  50. *
  51. * The volatile keys are stored in variable-sized tables called slices.
  52. * Slices are allocated on demand and deallocated when possible.
  53. * The size of slices increases exponentially, so the average overhead
  54. * (number of slots that are allocated but not used) is roughly
  55. * proportional to the number of keys (with a factor that grows
  56. * when the key store is fragmented).
  57. *
  58. * One slice is dedicated to the cache of persistent and built-in keys.
  59. * For simplicity, they are separated from volatile keys. This cache
  60. * slice has a fixed size and has the slice index KEY_SLOT_CACHE_SLICE_INDEX,
  61. * located after the slices for volatile keys.
  62. */
  63. /* Size of the last slice containing the cache of persistent and built-in keys. */
  64. #define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT
  65. /* Volatile keys are stored in slices 0 through
  66. * (KEY_SLOT_VOLATILE_SLICE_COUNT - 1) inclusive.
  67. * Each slice is twice the size of the previous slice.
  68. * Volatile key identifiers encode the slice number as follows:
  69. * bits 30..31: 0b10 (mandated by the PSA Crypto specification).
  70. * bits 25..29: slice index (0...KEY_SLOT_VOLATILE_SLICE_COUNT-1)
  71. * bits 0..24: slot index in slice
  72. */
  73. #define KEY_ID_SLOT_INDEX_WIDTH 25u
  74. #define KEY_ID_SLICE_INDEX_WIDTH 5u
  75. #define KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH 16u
  76. #define KEY_SLOT_VOLATILE_SLICE_COUNT 22u
  77. #define KEY_SLICE_COUNT (KEY_SLOT_VOLATILE_SLICE_COUNT + 1u)
  78. #define KEY_SLOT_CACHE_SLICE_INDEX KEY_SLOT_VOLATILE_SLICE_COUNT
  79. /* Check that the length of the largest slice (calculated as
  80. * KEY_SLICE_LENGTH_MAX below) does not overflow size_t. We use
  81. * an indirect method in case the calculation of KEY_SLICE_LENGTH_MAX
  82. * itself overflows uintmax_t: if (BASE_LENGTH << c)
  83. * overflows size_t then BASE_LENGTH > SIZE_MAX >> c.
  84. */
  85. #if (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH > \
  86. SIZE_MAX >> (KEY_SLOT_VOLATILE_SLICE_COUNT - 1))
  87. #error "Maximum slice length overflows size_t"
  88. #endif
  89. #if KEY_ID_SLICE_INDEX_WIDTH + KEY_ID_SLOT_INDEX_WIDTH > 30
  90. #error "Not enough room in volatile key IDs for slice index and slot index"
  91. #endif
  92. #if KEY_SLOT_VOLATILE_SLICE_COUNT > (1 << KEY_ID_SLICE_INDEX_WIDTH)
  93. #error "Too many slices to fit the slice index in a volatile key ID"
  94. #endif
  95. #define KEY_SLICE_LENGTH_MAX \
  96. (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << (KEY_SLOT_VOLATILE_SLICE_COUNT - 1))
  97. #if KEY_SLICE_LENGTH_MAX > 1 << KEY_ID_SLOT_INDEX_WIDTH
  98. #error "Not enough room in volatile key IDs for a slot index in the largest slice"
  99. #endif
  100. #if KEY_ID_SLICE_INDEX_WIDTH > 8
  101. #error "Slice index does not fit in uint8_t for psa_key_slot_t::slice_index"
  102. #endif
  103. /* Calculate the volatile key id to use for a given slot.
  104. * This function assumes valid parameter values. */
  105. static psa_key_id_t volatile_key_id_of_index(size_t slice_idx,
  106. size_t slot_idx)
  107. {
  108. /* We assert above that the slice and slot indexes fit in separate
  109. * bit-fields inside psa_key_id_t, which is a 32-bit type per the
  110. * PSA Cryptography specification. */
  111. return (psa_key_id_t) (0x40000000u |
  112. (slice_idx << KEY_ID_SLOT_INDEX_WIDTH) |
  113. slot_idx);
  114. }
  115. /* Calculate the slice containing the given volatile key.
  116. * This function assumes valid parameter values. */
  117. static size_t slice_index_of_volatile_key_id(psa_key_id_t key_id)
  118. {
  119. size_t mask = (1LU << KEY_ID_SLICE_INDEX_WIDTH) - 1;
  120. return (key_id >> KEY_ID_SLOT_INDEX_WIDTH) & mask;
  121. }
  122. /* Calculate the index of the slot containing the given volatile key.
  123. * This function assumes valid parameter values. */
  124. static size_t slot_index_of_volatile_key_id(psa_key_id_t key_id)
  125. {
  126. return key_id & ((1LU << KEY_ID_SLOT_INDEX_WIDTH) - 1);
  127. }
  128. /* In global_data.first_free_slot_index, use this special value to
  129. * indicate that the slice is full. */
  130. #define FREE_SLOT_INDEX_NONE ((size_t) -1)
  131. #if defined(MBEDTLS_TEST_HOOKS)
  132. size_t psa_key_slot_volatile_slice_count(void)
  133. {
  134. return KEY_SLOT_VOLATILE_SLICE_COUNT;
  135. }
  136. #endif
  137. #else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  138. /* Static key store.
  139. *
  140. * All the keys (volatile or persistent) are in a single slice.
  141. * We only use slices as a concept to allow some differences between
  142. * static and dynamic key store management to be buried in auxiliary
  143. * functions.
  144. */
  145. #define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT
  146. #define KEY_SLICE_COUNT 1u
  147. #define KEY_SLOT_CACHE_SLICE_INDEX 0
  148. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  149. typedef struct {
  150. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  151. psa_key_slot_t *key_slices[KEY_SLICE_COUNT];
  152. size_t first_free_slot_index[KEY_SLOT_VOLATILE_SLICE_COUNT];
  153. #else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  154. psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT];
  155. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  156. uint8_t key_slots_initialized;
  157. } psa_global_data_t;
  158. static psa_global_data_t global_data;
  159. static uint8_t psa_get_key_slots_initialized(void)
  160. {
  161. uint8_t initialized;
  162. #if defined(MBEDTLS_THREADING_C)
  163. mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
  164. #endif /* defined(MBEDTLS_THREADING_C) */
  165. initialized = global_data.key_slots_initialized;
  166. #if defined(MBEDTLS_THREADING_C)
  167. mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
  168. #endif /* defined(MBEDTLS_THREADING_C) */
  169. return initialized;
  170. }
  171. /** The length of the given slice in the key slot table.
  172. *
  173. * \param slice_idx The slice number. It must satisfy
  174. * 0 <= slice_idx < KEY_SLICE_COUNT.
  175. *
  176. * \return The number of elements in the given slice.
  177. */
  178. static inline size_t key_slice_length(size_t slice_idx);
  179. /** Get a pointer to the slot where the given volatile key is located.
  180. *
  181. * \param key_id The key identifier. It must be a valid volatile key
  182. * identifier.
  183. * \return A pointer to the only slot that the given key
  184. * can be in. Note that the slot may be empty or
  185. * contain a different key.
  186. */
  187. static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id);
  188. /** Get a pointer to an entry in the persistent key cache.
  189. *
  190. * \param slot_idx The index in the table. It must satisfy
  191. * 0 <= slot_idx < PERSISTENT_KEY_CACHE_COUNT.
  192. * \return A pointer to the slot containing the given
  193. * persistent key cache entry.
  194. */
  195. static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx);
  196. /** Get a pointer to a slot given by slice and index.
  197. *
  198. * \param slice_idx The slice number. It must satisfy
  199. * 0 <= slice_idx < KEY_SLICE_COUNT.
  200. * \param slot_idx An index in the given slice. It must satisfy
  201. * 0 <= slot_idx < key_slice_length(slice_idx).
  202. *
  203. * \return A pointer to the given slot.
  204. */
  205. static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx);
  206. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  207. #if defined(MBEDTLS_TEST_HOOKS)
  208. size_t (*mbedtls_test_hook_psa_volatile_key_slice_length)(size_t slice_idx) = NULL;
  209. #endif
  210. static inline size_t key_slice_length(size_t slice_idx)
  211. {
  212. if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) {
  213. return PERSISTENT_KEY_CACHE_COUNT;
  214. } else {
  215. #if defined(MBEDTLS_TEST_HOOKS)
  216. if (mbedtls_test_hook_psa_volatile_key_slice_length != NULL) {
  217. return mbedtls_test_hook_psa_volatile_key_slice_length(slice_idx);
  218. }
  219. #endif
  220. return KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << slice_idx;
  221. }
  222. }
  223. static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id)
  224. {
  225. size_t slice_idx = slice_index_of_volatile_key_id(key_id);
  226. if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) {
  227. return NULL;
  228. }
  229. size_t slot_idx = slot_index_of_volatile_key_id(key_id);
  230. if (slot_idx >= key_slice_length(slice_idx)) {
  231. return NULL;
  232. }
  233. psa_key_slot_t *slice = global_data.key_slices[slice_idx];
  234. if (slice == NULL) {
  235. return NULL;
  236. }
  237. return &slice[slot_idx];
  238. }
  239. static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx)
  240. {
  241. return &global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX][slot_idx];
  242. }
  243. static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx)
  244. {
  245. return &global_data.key_slices[slice_idx][slot_idx];
  246. }
  247. #else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  248. static inline size_t key_slice_length(size_t slice_idx)
  249. {
  250. (void) slice_idx;
  251. return ARRAY_LENGTH(global_data.key_slots);
  252. }
  253. static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id)
  254. {
  255. MBEDTLS_STATIC_ASSERT(ARRAY_LENGTH(global_data.key_slots) <=
  256. PSA_KEY_ID_VOLATILE_MAX - PSA_KEY_ID_VOLATILE_MIN + 1,
  257. "The key slot array is larger than the volatile key ID range");
  258. return &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN];
  259. }
  260. static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx)
  261. {
  262. return &global_data.key_slots[slot_idx];
  263. }
  264. static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx)
  265. {
  266. (void) slice_idx;
  267. return &global_data.key_slots[slot_idx];
  268. }
  269. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  270. int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok)
  271. {
  272. psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
  273. if ((PSA_KEY_ID_USER_MIN <= key_id) &&
  274. (key_id <= PSA_KEY_ID_USER_MAX)) {
  275. return 1;
  276. }
  277. if (vendor_ok &&
  278. (PSA_KEY_ID_VENDOR_MIN <= key_id) &&
  279. (key_id <= PSA_KEY_ID_VENDOR_MAX)) {
  280. return 1;
  281. }
  282. return 0;
  283. }
  284. /** Get the description in memory of a key given its identifier and lock it.
  285. *
  286. * The descriptions of volatile keys and loaded persistent keys are
  287. * stored in key slots. This function returns a pointer to the key slot
  288. * containing the description of a key given its identifier.
  289. *
  290. * The function searches the key slots containing the description of the key
  291. * with \p key identifier. The function does only read accesses to the key
  292. * slots. The function does not load any persistent key thus does not access
  293. * any storage.
  294. *
  295. * For volatile key identifiers, only one key slot is queried as a volatile
  296. * key with identifier key_id can only be stored in slot of index
  297. * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ).
  298. *
  299. * On success, the function locks the key slot. It is the responsibility of
  300. * the caller to unlock the key slot when it does not access it anymore.
  301. *
  302. * If multi-threading is enabled, the caller must hold the
  303. * global key slot mutex.
  304. *
  305. * \param key Key identifier to query.
  306. * \param[out] p_slot On success, `*p_slot` contains a pointer to the
  307. * key slot containing the description of the key
  308. * identified by \p key.
  309. *
  310. * \retval #PSA_SUCCESS
  311. * The pointer to the key slot containing the description of the key
  312. * identified by \p key was returned.
  313. * \retval #PSA_ERROR_INVALID_HANDLE
  314. * \p key is not a valid key identifier.
  315. * \retval #PSA_ERROR_DOES_NOT_EXIST
  316. * There is no key with key identifier \p key in the key slots.
  317. */
  318. static psa_status_t psa_get_and_lock_key_slot_in_memory(
  319. mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot)
  320. {
  321. psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
  322. psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
  323. size_t slot_idx;
  324. psa_key_slot_t *slot = NULL;
  325. if (psa_key_id_is_volatile(key_id)) {
  326. slot = get_volatile_key_slot(key_id);
  327. /* Check if both the PSA key identifier key_id and the owner
  328. * identifier of key match those of the key slot. */
  329. if (slot != NULL &&
  330. slot->state == PSA_SLOT_FULL &&
  331. mbedtls_svc_key_id_equal(key, slot->attr.id)) {
  332. status = PSA_SUCCESS;
  333. } else {
  334. status = PSA_ERROR_DOES_NOT_EXIST;
  335. }
  336. } else {
  337. if (!psa_is_valid_key_id(key, 1)) {
  338. return PSA_ERROR_INVALID_HANDLE;
  339. }
  340. for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) {
  341. slot = get_persistent_key_slot(slot_idx);
  342. /* Only consider slots which are in a full state. */
  343. if ((slot->state == PSA_SLOT_FULL) &&
  344. (mbedtls_svc_key_id_equal(key, slot->attr.id))) {
  345. break;
  346. }
  347. }
  348. status = (slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT) ?
  349. PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
  350. }
  351. if (status == PSA_SUCCESS) {
  352. status = psa_register_read(slot);
  353. if (status == PSA_SUCCESS) {
  354. *p_slot = slot;
  355. }
  356. }
  357. return status;
  358. }
  359. psa_status_t psa_initialize_key_slots(void)
  360. {
  361. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  362. global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] =
  363. mbedtls_calloc(PERSISTENT_KEY_CACHE_COUNT,
  364. sizeof(*global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX]));
  365. if (global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] == NULL) {
  366. return PSA_ERROR_INSUFFICIENT_MEMORY;
  367. }
  368. #else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  369. /* Nothing to do: program startup and psa_wipe_all_key_slots() both
  370. * guarantee that the key slots are initialized to all-zero, which
  371. * means that all the key slots are in a valid, empty state. The global
  372. * data mutex is already held when calling this function, so no need to
  373. * lock it here, to set the flag. */
  374. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  375. global_data.key_slots_initialized = 1;
  376. return PSA_SUCCESS;
  377. }
  378. void psa_wipe_all_key_slots(void)
  379. {
  380. for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) {
  381. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  382. if (global_data.key_slices[slice_idx] == NULL) {
  383. continue;
  384. }
  385. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  386. for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) {
  387. psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx);
  388. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  389. /* When MBEDTLS_PSA_KEY_STORE_DYNAMIC is disabled, calling
  390. * psa_wipe_key_slot() on an unused slot is useless, but it
  391. * happens to work (because we flip the state to PENDING_DELETION).
  392. *
  393. * When MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled,
  394. * psa_wipe_key_slot() needs to have a valid slice_index
  395. * field, but that value might not be correct in a
  396. * free slot, so we must not call it.
  397. *
  398. * Bypass the call to psa_wipe_key_slot() if the slot is empty,
  399. * but only if MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, to save
  400. * a few bytes of code size otherwise.
  401. */
  402. if (slot->state == PSA_SLOT_EMPTY) {
  403. continue;
  404. }
  405. #endif
  406. slot->var.occupied.registered_readers = 1;
  407. slot->state = PSA_SLOT_PENDING_DELETION;
  408. (void) psa_wipe_key_slot(slot);
  409. }
  410. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  411. mbedtls_free(global_data.key_slices[slice_idx]);
  412. global_data.key_slices[slice_idx] = NULL;
  413. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  414. }
  415. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  416. for (size_t slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) {
  417. global_data.first_free_slot_index[slice_idx] = 0;
  418. }
  419. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  420. /* The global data mutex is already held when calling this function. */
  421. global_data.key_slots_initialized = 0;
  422. }
  423. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  424. static psa_status_t psa_allocate_volatile_key_slot(psa_key_id_t *key_id,
  425. psa_key_slot_t **p_slot)
  426. {
  427. size_t slice_idx;
  428. for (slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) {
  429. if (global_data.first_free_slot_index[slice_idx] != FREE_SLOT_INDEX_NONE) {
  430. break;
  431. }
  432. }
  433. if (slice_idx == KEY_SLOT_VOLATILE_SLICE_COUNT) {
  434. return PSA_ERROR_INSUFFICIENT_MEMORY;
  435. }
  436. if (global_data.key_slices[slice_idx] == NULL) {
  437. global_data.key_slices[slice_idx] =
  438. mbedtls_calloc(key_slice_length(slice_idx),
  439. sizeof(psa_key_slot_t));
  440. if (global_data.key_slices[slice_idx] == NULL) {
  441. return PSA_ERROR_INSUFFICIENT_MEMORY;
  442. }
  443. }
  444. psa_key_slot_t *slice = global_data.key_slices[slice_idx];
  445. size_t slot_idx = global_data.first_free_slot_index[slice_idx];
  446. *key_id = volatile_key_id_of_index(slice_idx, slot_idx);
  447. psa_key_slot_t *slot = &slice[slot_idx];
  448. size_t next_free = slot_idx + 1 + slot->var.free.next_free_relative_to_next;
  449. if (next_free >= key_slice_length(slice_idx)) {
  450. next_free = FREE_SLOT_INDEX_NONE;
  451. }
  452. global_data.first_free_slot_index[slice_idx] = next_free;
  453. /* The .next_free field is not meaningful when the slot is not free,
  454. * so give it the same content as freshly initialized memory. */
  455. slot->var.free.next_free_relative_to_next = 0;
  456. psa_status_t status = psa_key_slot_state_transition(slot,
  457. PSA_SLOT_EMPTY,
  458. PSA_SLOT_FILLING);
  459. if (status != PSA_SUCCESS) {
  460. /* The only reason for failure is if the slot state was not empty.
  461. * This indicates that something has gone horribly wrong.
  462. * In this case, we leave the slot out of the free list, and stop
  463. * modifying it. This minimizes any further corruption. The slot
  464. * is a memory leak, but that's a lesser evil. */
  465. return status;
  466. }
  467. *p_slot = slot;
  468. /* We assert at compile time that the slice index fits in uint8_t. */
  469. slot->slice_index = (uint8_t) slice_idx;
  470. return PSA_SUCCESS;
  471. }
  472. psa_status_t psa_free_key_slot(size_t slice_idx,
  473. psa_key_slot_t *slot)
  474. {
  475. if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) {
  476. /* This is a cache entry. We don't maintain a free list, so
  477. * there's nothing to do. */
  478. return PSA_SUCCESS;
  479. }
  480. if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) {
  481. return PSA_ERROR_CORRUPTION_DETECTED;
  482. }
  483. psa_key_slot_t *slice = global_data.key_slices[slice_idx];
  484. psa_key_slot_t *slice_end = slice + key_slice_length(slice_idx);
  485. if (slot < slice || slot >= slice_end) {
  486. /* The slot isn't actually in the slice! We can't detect that
  487. * condition for sure, because the pointer comparison itself is
  488. * undefined behavior in that case. That same condition makes the
  489. * subtraction to calculate the slot index also UB.
  490. * Give up now to avoid causing further corruption.
  491. */
  492. return PSA_ERROR_CORRUPTION_DETECTED;
  493. }
  494. size_t slot_idx = slot - slice;
  495. size_t next_free = global_data.first_free_slot_index[slice_idx];
  496. if (next_free >= key_slice_length(slice_idx)) {
  497. /* The slot was full. The newly freed slot thus becomes the
  498. * end of the free list. */
  499. next_free = key_slice_length(slice_idx);
  500. }
  501. global_data.first_free_slot_index[slice_idx] = slot_idx;
  502. slot->var.free.next_free_relative_to_next =
  503. (int32_t) next_free - (int32_t) slot_idx - 1;
  504. return PSA_SUCCESS;
  505. }
  506. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  507. psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,
  508. psa_key_slot_t **p_slot)
  509. {
  510. psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
  511. size_t slot_idx;
  512. psa_key_slot_t *selected_slot, *unused_persistent_key_slot;
  513. if (!psa_get_key_slots_initialized()) {
  514. status = PSA_ERROR_BAD_STATE;
  515. goto error;
  516. }
  517. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  518. if (volatile_key_id != NULL) {
  519. return psa_allocate_volatile_key_slot(volatile_key_id, p_slot);
  520. }
  521. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  522. /* With a dynamic key store, allocate an entry in the cache slice,
  523. * applicable only to non-volatile keys that get cached in RAM.
  524. * With a static key store, allocate an entry in the sole slice,
  525. * applicable to all keys. */
  526. selected_slot = unused_persistent_key_slot = NULL;
  527. for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) {
  528. psa_key_slot_t *slot = get_key_slot(KEY_SLOT_CACHE_SLICE_INDEX, slot_idx);
  529. if (slot->state == PSA_SLOT_EMPTY) {
  530. selected_slot = slot;
  531. break;
  532. }
  533. if ((unused_persistent_key_slot == NULL) &&
  534. (slot->state == PSA_SLOT_FULL) &&
  535. (!psa_key_slot_has_readers(slot)) &&
  536. (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime))) {
  537. unused_persistent_key_slot = slot;
  538. }
  539. }
  540. /*
  541. * If there is no unused key slot and there is at least one unlocked key
  542. * slot containing the description of a persistent key, recycle the first
  543. * such key slot we encountered. If we later need to operate on the
  544. * persistent key we are evicting now, we will reload its description from
  545. * storage.
  546. */
  547. if ((selected_slot == NULL) &&
  548. (unused_persistent_key_slot != NULL)) {
  549. selected_slot = unused_persistent_key_slot;
  550. psa_register_read(selected_slot);
  551. status = psa_wipe_key_slot(selected_slot);
  552. if (status != PSA_SUCCESS) {
  553. goto error;
  554. }
  555. }
  556. if (selected_slot != NULL) {
  557. status = psa_key_slot_state_transition(selected_slot, PSA_SLOT_EMPTY,
  558. PSA_SLOT_FILLING);
  559. if (status != PSA_SUCCESS) {
  560. goto error;
  561. }
  562. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  563. selected_slot->slice_index = KEY_SLOT_CACHE_SLICE_INDEX;
  564. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  565. #if !defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  566. if (volatile_key_id != NULL) {
  567. /* Refresh slot_idx, for when the slot is not the original
  568. * selected_slot but rather unused_persistent_key_slot. */
  569. slot_idx = selected_slot - global_data.key_slots;
  570. *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + slot_idx;
  571. }
  572. #endif
  573. *p_slot = selected_slot;
  574. return PSA_SUCCESS;
  575. }
  576. status = PSA_ERROR_INSUFFICIENT_MEMORY;
  577. error:
  578. *p_slot = NULL;
  579. return status;
  580. }
  581. #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
  582. static psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot)
  583. {
  584. psa_status_t status = PSA_SUCCESS;
  585. uint8_t *key_data = NULL;
  586. size_t key_data_length = 0;
  587. status = psa_load_persistent_key(&slot->attr,
  588. &key_data, &key_data_length);
  589. if (status != PSA_SUCCESS) {
  590. goto exit;
  591. }
  592. #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
  593. /* Special handling is required for loading keys associated with a
  594. * dynamically registered SE interface. */
  595. const psa_drv_se_t *drv;
  596. psa_drv_se_context_t *drv_context;
  597. if (psa_get_se_driver(slot->attr.lifetime, &drv, &drv_context)) {
  598. psa_se_key_data_storage_t *data;
  599. if (key_data_length != sizeof(*data)) {
  600. status = PSA_ERROR_DATA_INVALID;
  601. goto exit;
  602. }
  603. data = (psa_se_key_data_storage_t *) key_data;
  604. status = psa_copy_key_material_into_slot(
  605. slot, data->slot_number, sizeof(data->slot_number));
  606. goto exit;
  607. }
  608. #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
  609. status = psa_copy_key_material_into_slot(slot, key_data, key_data_length);
  610. if (status != PSA_SUCCESS) {
  611. goto exit;
  612. }
  613. exit:
  614. psa_free_persistent_key_data(key_data, key_data_length);
  615. return status;
  616. }
  617. #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
  618. #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
  619. static psa_status_t psa_load_builtin_key_into_slot(psa_key_slot_t *slot)
  620. {
  621. psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
  622. psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
  623. psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE;
  624. psa_drv_slot_number_t slot_number = 0;
  625. size_t key_buffer_size = 0;
  626. size_t key_buffer_length = 0;
  627. if (!psa_key_id_is_builtin(
  628. MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id))) {
  629. return PSA_ERROR_DOES_NOT_EXIST;
  630. }
  631. /* Check the platform function to see whether this key actually exists */
  632. status = mbedtls_psa_platform_get_builtin_key(
  633. slot->attr.id, &lifetime, &slot_number);
  634. if (status != PSA_SUCCESS) {
  635. return status;
  636. }
  637. /* Set required key attributes to ensure get_builtin_key can retrieve the
  638. * full attributes. */
  639. psa_set_key_id(&attributes, slot->attr.id);
  640. psa_set_key_lifetime(&attributes, lifetime);
  641. /* Get the full key attributes from the driver in order to be able to
  642. * calculate the required buffer size. */
  643. status = psa_driver_wrapper_get_builtin_key(
  644. slot_number, &attributes,
  645. NULL, 0, NULL);
  646. if (status != PSA_ERROR_BUFFER_TOO_SMALL) {
  647. /* Builtin keys cannot be defined by the attributes alone */
  648. if (status == PSA_SUCCESS) {
  649. status = PSA_ERROR_CORRUPTION_DETECTED;
  650. }
  651. return status;
  652. }
  653. /* If the key should exist according to the platform, then ask the driver
  654. * what its expected size is. */
  655. status = psa_driver_wrapper_get_key_buffer_size(&attributes,
  656. &key_buffer_size);
  657. if (status != PSA_SUCCESS) {
  658. return status;
  659. }
  660. /* Allocate a buffer of the required size and load the builtin key directly
  661. * into the (now properly sized) slot buffer. */
  662. status = psa_allocate_buffer_to_slot(slot, key_buffer_size);
  663. if (status != PSA_SUCCESS) {
  664. return status;
  665. }
  666. status = psa_driver_wrapper_get_builtin_key(
  667. slot_number, &attributes,
  668. slot->key.data, slot->key.bytes, &key_buffer_length);
  669. if (status != PSA_SUCCESS) {
  670. goto exit;
  671. }
  672. /* Copy actual key length and core attributes into the slot on success */
  673. slot->key.bytes = key_buffer_length;
  674. slot->attr = attributes;
  675. exit:
  676. if (status != PSA_SUCCESS) {
  677. psa_remove_key_data_from_memory(slot);
  678. }
  679. return status;
  680. }
  681. #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
  682. psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,
  683. psa_key_slot_t **p_slot)
  684. {
  685. psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
  686. *p_slot = NULL;
  687. if (!psa_get_key_slots_initialized()) {
  688. return PSA_ERROR_BAD_STATE;
  689. }
  690. #if defined(MBEDTLS_THREADING_C)
  691. /* We need to set status as success, otherwise CORRUPTION_DETECTED
  692. * would be returned if the lock fails. */
  693. status = PSA_SUCCESS;
  694. /* If the key is persistent and not loaded, we cannot unlock the mutex
  695. * between checking if the key is loaded and setting the slot as FULL,
  696. * as otherwise another thread may load and then destroy the key
  697. * in the meantime. */
  698. PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
  699. &mbedtls_threading_key_slot_mutex));
  700. #endif
  701. /*
  702. * On success, the pointer to the slot is passed directly to the caller
  703. * thus no need to unlock the key slot here.
  704. */
  705. status = psa_get_and_lock_key_slot_in_memory(key, p_slot);
  706. if (status != PSA_ERROR_DOES_NOT_EXIST) {
  707. #if defined(MBEDTLS_THREADING_C)
  708. PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
  709. &mbedtls_threading_key_slot_mutex));
  710. #endif
  711. return status;
  712. }
  713. /* Loading keys from storage requires support for such a mechanism */
  714. #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \
  715. defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
  716. status = psa_reserve_free_key_slot(NULL, p_slot);
  717. if (status != PSA_SUCCESS) {
  718. #if defined(MBEDTLS_THREADING_C)
  719. PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
  720. &mbedtls_threading_key_slot_mutex));
  721. #endif
  722. return status;
  723. }
  724. (*p_slot)->attr.id = key;
  725. (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
  726. status = PSA_ERROR_DOES_NOT_EXIST;
  727. #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
  728. /* Load keys in the 'builtin' range through their own interface */
  729. status = psa_load_builtin_key_into_slot(*p_slot);
  730. #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
  731. #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
  732. if (status == PSA_ERROR_DOES_NOT_EXIST) {
  733. status = psa_load_persistent_key_into_slot(*p_slot);
  734. }
  735. #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
  736. if (status != PSA_SUCCESS) {
  737. psa_wipe_key_slot(*p_slot);
  738. /* If the key does not exist, we need to return
  739. * PSA_ERROR_INVALID_HANDLE. */
  740. if (status == PSA_ERROR_DOES_NOT_EXIST) {
  741. status = PSA_ERROR_INVALID_HANDLE;
  742. }
  743. } else {
  744. /* Add implicit usage flags. */
  745. psa_extend_key_usage_flags(&(*p_slot)->attr.policy.usage);
  746. psa_key_slot_state_transition((*p_slot), PSA_SLOT_FILLING,
  747. PSA_SLOT_FULL);
  748. status = psa_register_read(*p_slot);
  749. }
  750. #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
  751. status = PSA_ERROR_INVALID_HANDLE;
  752. #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
  753. if (status != PSA_SUCCESS) {
  754. *p_slot = NULL;
  755. }
  756. #if defined(MBEDTLS_THREADING_C)
  757. PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
  758. &mbedtls_threading_key_slot_mutex));
  759. #endif
  760. return status;
  761. }
  762. psa_status_t psa_unregister_read(psa_key_slot_t *slot)
  763. {
  764. if (slot == NULL) {
  765. return PSA_SUCCESS;
  766. }
  767. if ((slot->state != PSA_SLOT_FULL) &&
  768. (slot->state != PSA_SLOT_PENDING_DELETION)) {
  769. return PSA_ERROR_CORRUPTION_DETECTED;
  770. }
  771. /* If we are the last reader and the slot is marked for deletion,
  772. * we must wipe the slot here. */
  773. if ((slot->state == PSA_SLOT_PENDING_DELETION) &&
  774. (slot->var.occupied.registered_readers == 1)) {
  775. return psa_wipe_key_slot(slot);
  776. }
  777. if (psa_key_slot_has_readers(slot)) {
  778. slot->var.occupied.registered_readers--;
  779. return PSA_SUCCESS;
  780. }
  781. /*
  782. * As the return error code may not be handled in case of multiple errors,
  783. * do our best to report if there are no registered readers. Assert with
  784. * MBEDTLS_TEST_HOOK_TEST_ASSERT that there are registered readers:
  785. * if the MBEDTLS_TEST_HOOKS configuration option is enabled and
  786. * the function is called as part of the execution of a test suite, the
  787. * execution of the test suite is stopped in error if the assertion fails.
  788. */
  789. MBEDTLS_TEST_HOOK_TEST_ASSERT(psa_key_slot_has_readers(slot));
  790. return PSA_ERROR_CORRUPTION_DETECTED;
  791. }
  792. psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot)
  793. {
  794. psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
  795. #if defined(MBEDTLS_THREADING_C)
  796. /* We need to set status as success, otherwise CORRUPTION_DETECTED
  797. * would be returned if the lock fails. */
  798. status = PSA_SUCCESS;
  799. PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
  800. &mbedtls_threading_key_slot_mutex));
  801. #endif
  802. status = psa_unregister_read(slot);
  803. #if defined(MBEDTLS_THREADING_C)
  804. PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
  805. &mbedtls_threading_key_slot_mutex));
  806. #endif
  807. return status;
  808. }
  809. psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime,
  810. psa_se_drv_table_entry_t **p_drv)
  811. {
  812. if (psa_key_lifetime_is_external(lifetime)) {
  813. #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
  814. /* Check whether a driver is registered against this lifetime */
  815. psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime);
  816. if (driver != NULL) {
  817. if (p_drv != NULL) {
  818. *p_drv = driver;
  819. }
  820. return PSA_SUCCESS;
  821. }
  822. #else /* MBEDTLS_PSA_CRYPTO_SE_C */
  823. (void) p_drv;
  824. #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
  825. /* Key location for external keys gets checked by the wrapper */
  826. return PSA_SUCCESS;
  827. } else {
  828. /* Local/internal keys are always valid */
  829. return PSA_SUCCESS;
  830. }
  831. }
  832. psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime)
  833. {
  834. if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {
  835. /* Volatile keys are always supported */
  836. return PSA_SUCCESS;
  837. } else {
  838. /* Persistent keys require storage support */
  839. #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
  840. if (PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime)) {
  841. return PSA_ERROR_INVALID_ARGUMENT;
  842. } else {
  843. return PSA_SUCCESS;
  844. }
  845. #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
  846. return PSA_ERROR_NOT_SUPPORTED;
  847. #endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */
  848. }
  849. }
  850. psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle)
  851. {
  852. #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \
  853. defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
  854. psa_status_t status;
  855. psa_key_slot_t *slot;
  856. status = psa_get_and_lock_key_slot(key, &slot);
  857. if (status != PSA_SUCCESS) {
  858. *handle = PSA_KEY_HANDLE_INIT;
  859. if (status == PSA_ERROR_INVALID_HANDLE) {
  860. status = PSA_ERROR_DOES_NOT_EXIST;
  861. }
  862. return status;
  863. }
  864. *handle = key;
  865. return psa_unregister_read_under_mutex(slot);
  866. #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
  867. (void) key;
  868. *handle = PSA_KEY_HANDLE_INIT;
  869. return PSA_ERROR_NOT_SUPPORTED;
  870. #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
  871. }
  872. psa_status_t psa_close_key(psa_key_handle_t handle)
  873. {
  874. psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
  875. psa_key_slot_t *slot;
  876. if (psa_key_handle_is_null(handle)) {
  877. return PSA_SUCCESS;
  878. }
  879. #if defined(MBEDTLS_THREADING_C)
  880. /* We need to set status as success, otherwise CORRUPTION_DETECTED
  881. * would be returned if the lock fails. */
  882. status = PSA_SUCCESS;
  883. PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
  884. &mbedtls_threading_key_slot_mutex));
  885. #endif
  886. status = psa_get_and_lock_key_slot_in_memory(handle, &slot);
  887. if (status != PSA_SUCCESS) {
  888. if (status == PSA_ERROR_DOES_NOT_EXIST) {
  889. status = PSA_ERROR_INVALID_HANDLE;
  890. }
  891. #if defined(MBEDTLS_THREADING_C)
  892. PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
  893. &mbedtls_threading_key_slot_mutex));
  894. #endif
  895. return status;
  896. }
  897. if (slot->var.occupied.registered_readers == 1) {
  898. status = psa_wipe_key_slot(slot);
  899. } else {
  900. status = psa_unregister_read(slot);
  901. }
  902. #if defined(MBEDTLS_THREADING_C)
  903. PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
  904. &mbedtls_threading_key_slot_mutex));
  905. #endif
  906. return status;
  907. }
  908. psa_status_t psa_purge_key(mbedtls_svc_key_id_t key)
  909. {
  910. psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
  911. psa_key_slot_t *slot;
  912. #if defined(MBEDTLS_THREADING_C)
  913. /* We need to set status as success, otherwise CORRUPTION_DETECTED
  914. * would be returned if the lock fails. */
  915. status = PSA_SUCCESS;
  916. PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
  917. &mbedtls_threading_key_slot_mutex));
  918. #endif
  919. status = psa_get_and_lock_key_slot_in_memory(key, &slot);
  920. if (status != PSA_SUCCESS) {
  921. #if defined(MBEDTLS_THREADING_C)
  922. PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
  923. &mbedtls_threading_key_slot_mutex));
  924. #endif
  925. return status;
  926. }
  927. if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) &&
  928. (slot->var.occupied.registered_readers == 1)) {
  929. status = psa_wipe_key_slot(slot);
  930. } else {
  931. status = psa_unregister_read(slot);
  932. }
  933. #if defined(MBEDTLS_THREADING_C)
  934. PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
  935. &mbedtls_threading_key_slot_mutex));
  936. #endif
  937. return status;
  938. }
  939. void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats)
  940. {
  941. memset(stats, 0, sizeof(*stats));
  942. for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) {
  943. #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
  944. if (global_data.key_slices[slice_idx] == NULL) {
  945. continue;
  946. }
  947. #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
  948. for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) {
  949. const psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx);
  950. if (slot->state == PSA_SLOT_EMPTY) {
  951. ++stats->empty_slots;
  952. continue;
  953. }
  954. if (psa_key_slot_has_readers(slot)) {
  955. ++stats->locked_slots;
  956. }
  957. if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
  958. ++stats->volatile_slots;
  959. } else {
  960. psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
  961. ++stats->persistent_slots;
  962. if (id > stats->max_open_internal_key_id) {
  963. stats->max_open_internal_key_id = id;
  964. }
  965. }
  966. if (PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime) !=
  967. PSA_KEY_LOCATION_LOCAL_STORAGE) {
  968. psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
  969. ++stats->external_slots;
  970. if (id > stats->max_open_external_key_id) {
  971. stats->max_open_external_key_id = id;
  972. }
  973. }
  974. }
  975. }
  976. }
  977. #endif /* MBEDTLS_PSA_CRYPTO_C */