blob: 9628ff2899eb792e5b79c3f1e179304ac9dabe82 [file] [log] [blame]
Gilles Peskinea899a722019-06-24 14:06:43 +02001/*
2 * PSA crypto support for secure element drivers
3 */
Bence Szépkúti86974652020-06-15 11:59:37 +02004/*
Bence Szépkúti1e148272020-08-07 13:07:28 +02005 * Copyright The Mbed TLS Contributors
Dave Rodgman7ff79652023-11-03 12:04:52 +00006 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Gilles Peskinea899a722019-06-24 14:06:43 +02007 */
8
Gilles Peskinedb09ef62020-06-03 01:43:33 +02009#include "common.h"
Gilles Peskinea899a722019-06-24 14:06:43 +020010
Gilles Peskinea8ade162019-06-26 11:24:49 +020011#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
Gilles Peskinea899a722019-06-24 14:06:43 +020012
Gilles Peskine5243a202019-07-12 23:38:19 +020013#include <stdint.h>
Gilles Peskined0890212019-06-24 14:34:43 +020014#include <string.h>
15
Gilles Peskine5243a202019-07-12 23:38:19 +020016#include "psa/crypto_se_driver.h"
17
Gilles Peskinea899a722019-06-24 14:06:43 +020018#include "psa_crypto_se.h"
19
Gilles Peskine8b96cad2019-07-23 17:38:08 +020020#if defined(MBEDTLS_PSA_ITS_FILE_C)
21#include "psa_crypto_its.h"
22#else /* Native ITS implementation */
23#include "psa/error.h"
24#include "psa/internal_trusted_storage.h"
25#endif
26
Gilles Peskine5243a202019-07-12 23:38:19 +020027#include "mbedtls/platform.h"
Gilles Peskine5243a202019-07-12 23:38:19 +020028
29
30
Gilles Peskinef989dbe2019-06-26 18:18:12 +020031/****************************************************************/
32/* Driver lookup */
33/****************************************************************/
34
Gilles Peskine5243a202019-07-12 23:38:19 +020035/* This structure is identical to psa_drv_se_context_t declared in
36 * `crypto_se_driver.h`, except that some parts are writable here
37 * (non-const, or pointer to non-const). */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010038typedef struct {
Gilles Peskine5243a202019-07-12 23:38:19 +020039 void *persistent_data;
40 size_t persistent_data_size;
41 uintptr_t transient_data;
42} psa_drv_se_internal_context_t;
43
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010044struct psa_se_drv_table_entry_s {
Gilles Peskine2b04f462020-05-10 00:44:04 +020045 psa_key_location_t location;
Gilles Peskinea899a722019-06-24 14:06:43 +020046 const psa_drv_se_t *methods;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010047 union {
Gilles Peskine5243a202019-07-12 23:38:19 +020048 psa_drv_se_internal_context_t internal;
49 psa_drv_se_context_t context;
Gilles Peskine1a75d0c2020-04-14 19:33:25 +020050 } u;
Gilles Peskine01fd8752020-04-14 19:31:52 +020051};
Gilles Peskinea899a722019-06-24 14:06:43 +020052
Gilles Peskinef989dbe2019-06-26 18:18:12 +020053static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS];
54
Gilles Peskine5243a202019-07-12 23:38:19 +020055psa_se_drv_table_entry_t *psa_get_se_driver_entry(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010056 psa_key_lifetime_t lifetime)
Gilles Peskinef989dbe2019-06-26 18:18:12 +020057{
58 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010059 psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime);
Gilles Peskine2b04f462020-05-10 00:44:04 +020060 /* In the driver table, location=0 means an entry that isn't used.
61 * No driver has a location of 0 because it's a reserved value
62 * (which designates transparent keys). Make sure we never return
63 * a driver entry for location 0. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010064 if (location == 0) {
65 return NULL;
Gilles Peskinef989dbe2019-06-26 18:18:12 +020066 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010067 for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
68 if (driver_table[i].location == location) {
69 return &driver_table[i];
70 }
71 }
72 return NULL;
Gilles Peskinef989dbe2019-06-26 18:18:12 +020073}
74
75const psa_drv_se_t *psa_get_se_driver_methods(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010076 const psa_se_drv_table_entry_t *driver)
Gilles Peskinef989dbe2019-06-26 18:18:12 +020077{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010078 return driver->methods;
Gilles Peskinef989dbe2019-06-26 18:18:12 +020079}
80
Gilles Peskine5243a202019-07-12 23:38:19 +020081psa_drv_se_context_t *psa_get_se_driver_context(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010082 psa_se_drv_table_entry_t *driver)
Gilles Peskinef989dbe2019-06-26 18:18:12 +020083{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010084 return &driver->u.context;
Gilles Peskinef989dbe2019-06-26 18:18:12 +020085}
86
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010087int psa_get_se_driver(psa_key_lifetime_t lifetime,
88 const psa_drv_se_t **p_methods,
89 psa_drv_se_context_t **p_drv_context)
Gilles Peskine5243a202019-07-12 23:38:19 +020090{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010091 psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime);
92 if (p_methods != NULL) {
93 *p_methods = (driver ? driver->methods : NULL);
94 }
95 if (p_drv_context != NULL) {
96 *p_drv_context = (driver ? &driver->u.context : NULL);
97 }
98 return driver != NULL;
Gilles Peskine5243a202019-07-12 23:38:19 +020099}
100
101
102
103/****************************************************************/
104/* Persistent data management */
105/****************************************************************/
106
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200107static psa_status_t psa_get_se_driver_its_file_uid(
108 const psa_se_drv_table_entry_t *driver,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100109 psa_storage_uid_t *uid)
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200110{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100111 if (driver->location > PSA_MAX_SE_LOCATION) {
112 return PSA_ERROR_NOT_SUPPORTED;
113 }
Gilles Peskine573bbc12019-07-23 19:59:23 +0200114
115#if SIZE_MAX > UINT32_MAX
116 /* ITS file sizes are limited to 32 bits. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100117 if (driver->u.internal.persistent_data_size > UINT32_MAX) {
118 return PSA_ERROR_NOT_SUPPORTED;
119 }
Gilles Peskine573bbc12019-07-23 19:59:23 +0200120#endif
121
Gilles Peskine75c126b2019-07-24 15:56:01 +0200122 /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */
Gilles Peskine2b04f462020-05-10 00:44:04 +0200123 *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100124 return PSA_SUCCESS;
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200125}
126
Gilles Peskine5243a202019-07-12 23:38:19 +0200127psa_status_t psa_load_se_persistent_data(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100128 const psa_se_drv_table_entry_t *driver)
Gilles Peskine5243a202019-07-12 23:38:19 +0200129{
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200130 psa_status_t status;
131 psa_storage_uid_t uid;
Gilles Peskine8b663892019-07-31 17:57:57 +0200132 size_t length;
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200133
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100134 status = psa_get_se_driver_its_file_uid(driver, &uid);
135 if (status != PSA_SUCCESS) {
136 return status;
137 }
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200138
Gilles Peskine8b663892019-07-31 17:57:57 +0200139 /* Read the amount of persistent data that the driver requests.
140 * If the data in storage is larger, it is truncated. If the data
141 * in storage is smaller, silently keep what is already at the end
142 * of the output buffer. */
Gilles Peskine75c126b2019-07-24 15:56:01 +0200143 /* psa_get_se_driver_its_file_uid ensures that the size_t
144 * persistent_data_size is in range, but compilers don't know that,
145 * so cast to reassure them. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100146 return psa_its_get(uid, 0,
147 (uint32_t) driver->u.internal.persistent_data_size,
148 driver->u.internal.persistent_data,
149 &length);
Gilles Peskine5243a202019-07-12 23:38:19 +0200150}
151
152psa_status_t psa_save_se_persistent_data(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100153 const psa_se_drv_table_entry_t *driver)
Gilles Peskine5243a202019-07-12 23:38:19 +0200154{
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200155 psa_status_t status;
156 psa_storage_uid_t uid;
157
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100158 status = psa_get_se_driver_its_file_uid(driver, &uid);
159 if (status != PSA_SUCCESS) {
160 return status;
161 }
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200162
Gilles Peskine75c126b2019-07-24 15:56:01 +0200163 /* psa_get_se_driver_its_file_uid ensures that the size_t
164 * persistent_data_size is in range, but compilers don't know that,
165 * so cast to reassure them. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100166 return psa_its_set(uid,
167 (uint32_t) driver->u.internal.persistent_data_size,
168 driver->u.internal.persistent_data,
169 0);
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200170}
171
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100172psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location)
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200173{
174 psa_storage_uid_t uid;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100175 if (location > PSA_MAX_SE_LOCATION) {
176 return PSA_ERROR_NOT_SUPPORTED;
177 }
Gilles Peskine2b04f462020-05-10 00:44:04 +0200178 uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100179 return psa_its_remove(uid);
Gilles Peskine5243a202019-07-12 23:38:19 +0200180}
Gilles Peskinef989dbe2019-06-26 18:18:12 +0200181
Gilles Peskinecbaff462019-07-12 23:46:04 +0200182psa_status_t psa_find_se_slot_for_key(
183 const psa_key_attributes_t *attributes,
Gilles Peskinee88c2c12019-08-05 16:44:14 +0200184 psa_key_creation_method_t method,
Gilles Peskinecbaff462019-07-12 23:46:04 +0200185 psa_se_drv_table_entry_t *driver,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100186 psa_key_slot_number_t *slot_number)
Gilles Peskinecbaff462019-07-12 23:46:04 +0200187{
188 psa_status_t status;
Gilles Peskine2b04f462020-05-10 00:44:04 +0200189 psa_key_location_t key_location =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100190 PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));
Gilles Peskinecbaff462019-07-12 23:46:04 +0200191
Gilles Peskine2b04f462020-05-10 00:44:04 +0200192 /* If the location is wrong, it's a bug in the library. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100193 if (driver->location != key_location) {
194 return PSA_ERROR_CORRUPTION_DETECTED;
195 }
Gilles Peskinecbaff462019-07-12 23:46:04 +0200196
197 /* If the driver doesn't support key creation in any way, give up now. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100198 if (driver->methods->key_management == NULL) {
199 return PSA_ERROR_NOT_SUPPORTED;
200 }
Gilles Peskinecbaff462019-07-12 23:46:04 +0200201
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100202 if (psa_get_key_slot_number(attributes, slot_number) == PSA_SUCCESS) {
Gilles Peskine46d94392019-08-05 14:55:50 +0200203 /* The application wants to use a specific slot. Allow it if
204 * the driver supports it. On a system with isolation,
205 * the crypto service must check that the application is
206 * permitted to request this slot. */
207 psa_drv_se_validate_slot_number_t p_validate_slot_number =
208 driver->methods->key_management->p_validate_slot_number;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100209 if (p_validate_slot_number == NULL) {
210 return PSA_ERROR_NOT_SUPPORTED;
211 }
212 status = p_validate_slot_number(&driver->u.context,
213 driver->u.internal.persistent_data,
214 attributes, method,
215 *slot_number);
216 } else if (method == PSA_KEY_CREATION_REGISTER) {
Gilles Peskine3efcebb2019-10-01 14:18:35 +0200217 /* The application didn't specify a slot number. This doesn't
218 * make sense when registering a slot. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 return PSA_ERROR_INVALID_ARGUMENT;
220 } else {
Gilles Peskine46d94392019-08-05 14:55:50 +0200221 /* The application didn't tell us which slot to use. Let the driver
222 * choose. This is the normal case. */
223 psa_drv_se_allocate_key_t p_allocate =
224 driver->methods->key_management->p_allocate;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100225 if (p_allocate == NULL) {
226 return PSA_ERROR_NOT_SUPPORTED;
227 }
228 status = p_allocate(&driver->u.context,
229 driver->u.internal.persistent_data,
230 attributes, method,
231 slot_number);
Gilles Peskine46d94392019-08-05 14:55:50 +0200232 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100233 return status;
Gilles Peskinecbaff462019-07-12 23:46:04 +0200234}
235
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100236psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver,
237 psa_key_slot_number_t slot_number)
Gilles Peskine354f7672019-07-12 23:46:38 +0200238{
239 psa_status_t status;
240 psa_status_t storage_status;
Gilles Peskine340b1272019-07-25 14:13:24 +0200241 /* Normally a missing method would mean that the action is not
242 * supported. But psa_destroy_key() is not supposed to return
243 * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should
244 * be able to destroy it. The only use case for a driver that
245 * does not have a way to destroy keys at all is if the keys are
246 * locked in a read-only state: we can use the keys but not
247 * destroy them. Hence, if the driver doesn't support destroying
248 * keys, it's really a lack of permission. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100249 if (driver->methods->key_management == NULL ||
250 driver->methods->key_management->p_destroy == NULL) {
251 return PSA_ERROR_NOT_PERMITTED;
252 }
Gilles Peskine354f7672019-07-12 23:46:38 +0200253 status = driver->methods->key_management->p_destroy(
Gilles Peskine1a75d0c2020-04-14 19:33:25 +0200254 &driver->u.context,
255 driver->u.internal.persistent_data,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100256 slot_number);
257 storage_status = psa_save_se_persistent_data(driver);
258 return status == PSA_SUCCESS ? storage_status : status;
Gilles Peskine354f7672019-07-12 23:46:38 +0200259}
260
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100261psa_status_t psa_init_all_se_drivers(void)
Gilles Peskined9348f22019-10-01 15:22:29 +0200262{
263 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100264 for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
Gilles Peskined9348f22019-10-01 15:22:29 +0200265 psa_se_drv_table_entry_t *driver = &driver_table[i];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100266 if (driver->location == 0) {
Gilles Peskined9348f22019-10-01 15:22:29 +0200267 continue; /* skipping unused entry */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100268 }
269 const psa_drv_se_t *methods = psa_get_se_driver_methods(driver);
270 if (methods->p_init != NULL) {
Gilles Peskined9348f22019-10-01 15:22:29 +0200271 psa_status_t status = methods->p_init(
Gilles Peskine1a75d0c2020-04-14 19:33:25 +0200272 &driver->u.context,
273 driver->u.internal.persistent_data,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100274 driver->location);
275 if (status != PSA_SUCCESS) {
276 return status;
277 }
278 status = psa_save_se_persistent_data(driver);
279 if (status != PSA_SUCCESS) {
280 return status;
281 }
Gilles Peskined9348f22019-10-01 15:22:29 +0200282 }
283 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100284 return PSA_SUCCESS;
Gilles Peskined9348f22019-10-01 15:22:29 +0200285}
286
Gilles Peskinef989dbe2019-06-26 18:18:12 +0200287
288
289/****************************************************************/
290/* Driver registration */
291/****************************************************************/
Gilles Peskinea899a722019-06-24 14:06:43 +0200292
293psa_status_t psa_register_se_driver(
Gilles Peskine2b04f462020-05-10 00:44:04 +0200294 psa_key_location_t location,
Gilles Peskinea899a722019-06-24 14:06:43 +0200295 const psa_drv_se_t *methods)
296{
297 size_t i;
Gilles Peskine5243a202019-07-12 23:38:19 +0200298 psa_status_t status;
Gilles Peskinea899a722019-06-24 14:06:43 +0200299
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100300 if (methods->hal_version != PSA_DRV_SE_HAL_VERSION) {
301 return PSA_ERROR_NOT_SUPPORTED;
302 }
Gilles Peskine9717d102019-06-26 11:50:04 +0200303 /* Driver table entries are 0-initialized. 0 is not a valid driver
Gilles Peskine2b04f462020-05-10 00:44:04 +0200304 * location because it means a transparent key. */
Tom Cosgrovebdd01a72023-03-08 14:19:51 +0000305 MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0,
306 "Secure element support requires 0 to mean a local key");
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100307 if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) {
308 return PSA_ERROR_INVALID_ARGUMENT;
309 }
310 if (location > PSA_MAX_SE_LOCATION) {
311 return PSA_ERROR_NOT_SUPPORTED;
312 }
Gilles Peskinea899a722019-06-24 14:06:43 +0200313
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100314 for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
315 if (driver_table[i].location == 0) {
Gilles Peskinea899a722019-06-24 14:06:43 +0200316 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100317 }
Gilles Peskine2b04f462020-05-10 00:44:04 +0200318 /* Check that location isn't already in use up to the first free
Gilles Peskinea899a722019-06-24 14:06:43 +0200319 * entry. Since entries are created in order and never deleted,
320 * there can't be a used entry after the first free entry. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100321 if (driver_table[i].location == location) {
322 return PSA_ERROR_ALREADY_EXISTS;
323 }
Gilles Peskinea899a722019-06-24 14:06:43 +0200324 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100325 if (i == PSA_MAX_SE_DRIVERS) {
326 return PSA_ERROR_INSUFFICIENT_MEMORY;
327 }
Gilles Peskinea899a722019-06-24 14:06:43 +0200328
Gilles Peskine2b04f462020-05-10 00:44:04 +0200329 driver_table[i].location = location;
Gilles Peskinea899a722019-06-24 14:06:43 +0200330 driver_table[i].methods = methods;
Gilles Peskine1a75d0c2020-04-14 19:33:25 +0200331 driver_table[i].u.internal.persistent_data_size =
Gilles Peskined5536d82019-10-01 16:55:29 +0200332 methods->persistent_data_size;
Gilles Peskine5243a202019-07-12 23:38:19 +0200333
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100334 if (methods->persistent_data_size != 0) {
Gilles Peskine1a75d0c2020-04-14 19:33:25 +0200335 driver_table[i].u.internal.persistent_data =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100336 mbedtls_calloc(1, methods->persistent_data_size);
337 if (driver_table[i].u.internal.persistent_data == NULL) {
Gilles Peskine5243a202019-07-12 23:38:19 +0200338 status = PSA_ERROR_INSUFFICIENT_MEMORY;
339 goto error;
340 }
Gilles Peskine8b96cad2019-07-23 17:38:08 +0200341 /* Load the driver's persistent data. On first use, the persistent
342 * data does not exist in storage, and is initialized to
343 * all-bits-zero by the calloc call just above. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100344 status = psa_load_se_persistent_data(&driver_table[i]);
345 if (status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST) {
Gilles Peskine5243a202019-07-12 23:38:19 +0200346 goto error;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100347 }
Gilles Peskine5243a202019-07-12 23:38:19 +0200348 }
Gilles Peskine5243a202019-07-12 23:38:19 +0200349
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100350 return PSA_SUCCESS;
Gilles Peskine5243a202019-07-12 23:38:19 +0200351
352error:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100353 memset(&driver_table[i], 0, sizeof(driver_table[i]));
354 return status;
Gilles Peskinea899a722019-06-24 14:06:43 +0200355}
356
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100357void psa_unregister_all_se_drivers(void)
Gilles Peskined0890212019-06-24 14:34:43 +0200358{
Gilles Peskine5243a202019-07-12 23:38:19 +0200359 size_t i;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100360 for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
361 if (driver_table[i].u.internal.persistent_data != NULL) {
362 mbedtls_free(driver_table[i].u.internal.persistent_data);
363 }
Gilles Peskine5243a202019-07-12 23:38:19 +0200364 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100365 memset(driver_table, 0, sizeof(driver_table));
Gilles Peskined0890212019-06-24 14:34:43 +0200366}
367
Gilles Peskinef989dbe2019-06-26 18:18:12 +0200368
369
370/****************************************************************/
371/* The end */
372/****************************************************************/
373
Gilles Peskinea8ade162019-06-26 11:24:49 +0200374#endif /* MBEDTLS_PSA_CRYPTO_SE_C */