1 /*
2 * PSA crypto support for secure element drivers
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_SE_C)
12
13 #include <stdint.h>
14 #include <string.h>
15
16 #include "psa/crypto_se_driver.h"
17
18 #include "psa_crypto_se.h"
19
20 #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
27 #include "mbedtls/platform.h"
28
29
30
31 /****************************************************************/
32 /* Driver lookup */
33 /****************************************************************/
34
35 /* 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). */
38 typedef struct {
39 void *persistent_data;
40 size_t persistent_data_size;
41 uintptr_t transient_data;
42 } psa_drv_se_internal_context_t;
43
44 struct psa_se_drv_table_entry_s {
45 psa_key_location_t location;
46 const psa_drv_se_t *methods;
47 union {
48 psa_drv_se_internal_context_t internal;
49 psa_drv_se_context_t context;
50 } u;
51 };
52
53 static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS];
54
psa_get_se_driver_entry(psa_key_lifetime_t lifetime)55 psa_se_drv_table_entry_t *psa_get_se_driver_entry(
56 psa_key_lifetime_t lifetime)
57 {
58 size_t i;
59 psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime);
60 /* 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. */
64 if (location == 0) {
65 return NULL;
66 }
67 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;
73 }
74
psa_get_se_driver_methods(const psa_se_drv_table_entry_t * driver)75 const psa_drv_se_t *psa_get_se_driver_methods(
76 const psa_se_drv_table_entry_t *driver)
77 {
78 return driver->methods;
79 }
80
psa_get_se_driver_context(psa_se_drv_table_entry_t * driver)81 psa_drv_se_context_t *psa_get_se_driver_context(
82 psa_se_drv_table_entry_t *driver)
83 {
84 return &driver->u.context;
85 }
86
psa_get_se_driver(psa_key_lifetime_t lifetime,const psa_drv_se_t ** p_methods,psa_drv_se_context_t ** p_drv_context)87 int 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)
90 {
91 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;
99 }
100
101
102
103 /****************************************************************/
104 /* Persistent data management */
105 /****************************************************************/
106
psa_get_se_driver_its_file_uid(const psa_se_drv_table_entry_t * driver,psa_storage_uid_t * uid)107 static psa_status_t psa_get_se_driver_its_file_uid(
108 const psa_se_drv_table_entry_t *driver,
109 psa_storage_uid_t *uid)
110 {
111 if (driver->location > PSA_MAX_SE_LOCATION) {
112 return PSA_ERROR_NOT_SUPPORTED;
113 }
114
115 #if SIZE_MAX > UINT32_MAX
116 /* ITS file sizes are limited to 32 bits. */
117 if (driver->u.internal.persistent_data_size > UINT32_MAX) {
118 return PSA_ERROR_NOT_SUPPORTED;
119 }
120 #endif
121
122 /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */
123 *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location;
124 return PSA_SUCCESS;
125 }
126
psa_load_se_persistent_data(const psa_se_drv_table_entry_t * driver)127 psa_status_t psa_load_se_persistent_data(
128 const psa_se_drv_table_entry_t *driver)
129 {
130 psa_status_t status;
131 psa_storage_uid_t uid;
132 size_t length;
133
134 status = psa_get_se_driver_its_file_uid(driver, &uid);
135 if (status != PSA_SUCCESS) {
136 return status;
137 }
138
139 /* 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. */
143 /* 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. */
146 return psa_its_get(uid, 0,
147 (uint32_t) driver->u.internal.persistent_data_size,
148 driver->u.internal.persistent_data,
149 &length);
150 }
151
psa_save_se_persistent_data(const psa_se_drv_table_entry_t * driver)152 psa_status_t psa_save_se_persistent_data(
153 const psa_se_drv_table_entry_t *driver)
154 {
155 psa_status_t status;
156 psa_storage_uid_t uid;
157
158 status = psa_get_se_driver_its_file_uid(driver, &uid);
159 if (status != PSA_SUCCESS) {
160 return status;
161 }
162
163 /* 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. */
166 return psa_its_set(uid,
167 (uint32_t) driver->u.internal.persistent_data_size,
168 driver->u.internal.persistent_data,
169 0);
170 }
171
psa_destroy_se_persistent_data(psa_key_location_t location)172 psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location)
173 {
174 psa_storage_uid_t uid;
175 if (location > PSA_MAX_SE_LOCATION) {
176 return PSA_ERROR_NOT_SUPPORTED;
177 }
178 uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location;
179 return psa_its_remove(uid);
180 }
181
psa_find_se_slot_for_key(const psa_key_attributes_t * attributes,psa_key_creation_method_t method,psa_se_drv_table_entry_t * driver,psa_key_slot_number_t * slot_number)182 psa_status_t psa_find_se_slot_for_key(
183 const psa_key_attributes_t *attributes,
184 psa_key_creation_method_t method,
185 psa_se_drv_table_entry_t *driver,
186 psa_key_slot_number_t *slot_number)
187 {
188 psa_status_t status;
189 psa_key_location_t key_location =
190 PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));
191
192 /* If the location is wrong, it's a bug in the library. */
193 if (driver->location != key_location) {
194 return PSA_ERROR_CORRUPTION_DETECTED;
195 }
196
197 /* If the driver doesn't support key creation in any way, give up now. */
198 if (driver->methods->key_management == NULL) {
199 return PSA_ERROR_NOT_SUPPORTED;
200 }
201
202 if (psa_get_key_slot_number(attributes, slot_number) == PSA_SUCCESS) {
203 /* 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;
209 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) {
217 /* The application didn't specify a slot number. This doesn't
218 * make sense when registering a slot. */
219 return PSA_ERROR_INVALID_ARGUMENT;
220 } else {
221 /* 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;
225 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);
232 }
233 return status;
234 }
235
psa_destroy_se_key(psa_se_drv_table_entry_t * driver,psa_key_slot_number_t slot_number)236 psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver,
237 psa_key_slot_number_t slot_number)
238 {
239 psa_status_t status;
240 psa_status_t storage_status;
241 /* 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. */
249 if (driver->methods->key_management == NULL ||
250 driver->methods->key_management->p_destroy == NULL) {
251 return PSA_ERROR_NOT_PERMITTED;
252 }
253 status = driver->methods->key_management->p_destroy(
254 &driver->u.context,
255 driver->u.internal.persistent_data,
256 slot_number);
257 storage_status = psa_save_se_persistent_data(driver);
258 return status == PSA_SUCCESS ? storage_status : status;
259 }
260
psa_init_all_se_drivers(void)261 psa_status_t psa_init_all_se_drivers(void)
262 {
263 size_t i;
264 for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
265 psa_se_drv_table_entry_t *driver = &driver_table[i];
266 if (driver->location == 0) {
267 continue; /* skipping unused entry */
268 }
269 const psa_drv_se_t *methods = psa_get_se_driver_methods(driver);
270 if (methods->p_init != NULL) {
271 psa_status_t status = methods->p_init(
272 &driver->u.context,
273 driver->u.internal.persistent_data,
274 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 }
282 }
283 }
284 return PSA_SUCCESS;
285 }
286
287
288
289 /****************************************************************/
290 /* Driver registration */
291 /****************************************************************/
292
psa_register_se_driver(psa_key_location_t location,const psa_drv_se_t * methods)293 psa_status_t psa_register_se_driver(
294 psa_key_location_t location,
295 const psa_drv_se_t *methods)
296 {
297 size_t i;
298 psa_status_t status;
299
300 if (methods->hal_version != PSA_DRV_SE_HAL_VERSION) {
301 return PSA_ERROR_NOT_SUPPORTED;
302 }
303 /* Driver table entries are 0-initialized. 0 is not a valid driver
304 * location because it means a transparent key. */
305 MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0,
306 "Secure element support requires 0 to mean a local key");
307 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 }
313
314 for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
315 if (driver_table[i].location == 0) {
316 break;
317 }
318 /* Check that location isn't already in use up to the first free
319 * entry. Since entries are created in order and never deleted,
320 * there can't be a used entry after the first free entry. */
321 if (driver_table[i].location == location) {
322 return PSA_ERROR_ALREADY_EXISTS;
323 }
324 }
325 if (i == PSA_MAX_SE_DRIVERS) {
326 return PSA_ERROR_INSUFFICIENT_MEMORY;
327 }
328
329 driver_table[i].location = location;
330 driver_table[i].methods = methods;
331 driver_table[i].u.internal.persistent_data_size =
332 methods->persistent_data_size;
333
334 if (methods->persistent_data_size != 0) {
335 driver_table[i].u.internal.persistent_data =
336 mbedtls_calloc(1, methods->persistent_data_size);
337 if (driver_table[i].u.internal.persistent_data == NULL) {
338 status = PSA_ERROR_INSUFFICIENT_MEMORY;
339 goto error;
340 }
341 /* 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. */
344 status = psa_load_se_persistent_data(&driver_table[i]);
345 if (status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST) {
346 goto error;
347 }
348 }
349
350 return PSA_SUCCESS;
351
352 error:
353 memset(&driver_table[i], 0, sizeof(driver_table[i]));
354 return status;
355 }
356
psa_unregister_all_se_drivers(void)357 void psa_unregister_all_se_drivers(void)
358 {
359 size_t i;
360 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 }
364 }
365 memset(driver_table, 0, sizeof(driver_table));
366 }
367
368
369
370 /****************************************************************/
371 /* The end */
372 /****************************************************************/
373
374 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
375