psa_crypto_slot_management.c 19 KB

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