1/* 2 * PSA crypto support for secure element drivers 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 21#include "common.h" 22 23#if defined(MBEDTLS_PSA_CRYPTO_SE_C) 24 25#include <stdint.h> 26#include <string.h> 27 28#include "psa/crypto_se_driver.h" 29 30#include "psa_crypto_se.h" 31 32#if defined(MBEDTLS_PSA_ITS_FILE_C) 33#include "psa_crypto_its.h" 34#else /* Native ITS implementation */ 35#include "psa/error.h" 36#include "psa/internal_trusted_storage.h" 37#endif 38 39#include "mbedtls/platform.h" 40 41 42 43/****************************************************************/ 44/* Driver lookup */ 45/****************************************************************/ 46 47/* This structure is identical to psa_drv_se_context_t declared in 48 * `crypto_se_driver.h`, except that some parts are writable here 49 * (non-const, or pointer to non-const). */ 50typedef struct { 51 void *persistent_data; 52 size_t persistent_data_size; 53 uintptr_t transient_data; 54} psa_drv_se_internal_context_t; 55 56struct psa_se_drv_table_entry_s { 57 psa_key_location_t location; 58 const psa_drv_se_t *methods; 59 union { 60 psa_drv_se_internal_context_t internal; 61 psa_drv_se_context_t context; 62 } u; 63}; 64 65static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS]; 66 67psa_se_drv_table_entry_t *psa_get_se_driver_entry( 68 psa_key_lifetime_t lifetime) 69{ 70 size_t i; 71 psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); 72 /* In the driver table, location=0 means an entry that isn't used. 73 * No driver has a location of 0 because it's a reserved value 74 * (which designates transparent keys). Make sure we never return 75 * a driver entry for location 0. */ 76 if (location == 0) { 77 return NULL; 78 } 79 for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { 80 if (driver_table[i].location == location) { 81 return &driver_table[i]; 82 } 83 } 84 return NULL; 85} 86 87const psa_drv_se_t *psa_get_se_driver_methods( 88 const psa_se_drv_table_entry_t *driver) 89{ 90 return driver->methods; 91} 92 93psa_drv_se_context_t *psa_get_se_driver_context( 94 psa_se_drv_table_entry_t *driver) 95{ 96 return &driver->u.context; 97} 98 99int psa_get_se_driver(psa_key_lifetime_t lifetime, 100 const psa_drv_se_t **p_methods, 101 psa_drv_se_context_t **p_drv_context) 102{ 103 psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime); 104 if (p_methods != NULL) { 105 *p_methods = (driver ? driver->methods : NULL); 106 } 107 if (p_drv_context != NULL) { 108 *p_drv_context = (driver ? &driver->u.context : NULL); 109 } 110 return driver != NULL; 111} 112 113 114 115/****************************************************************/ 116/* Persistent data management */ 117/****************************************************************/ 118 119static psa_status_t psa_get_se_driver_its_file_uid( 120 const psa_se_drv_table_entry_t *driver, 121 psa_storage_uid_t *uid) 122{ 123 if (driver->location > PSA_MAX_SE_LOCATION) { 124 return PSA_ERROR_NOT_SUPPORTED; 125 } 126 127 /* ITS file sizes are limited to 32 bits. */ 128 if (driver->u.internal.persistent_data_size > UINT32_MAX) { 129 return PSA_ERROR_NOT_SUPPORTED; 130 } 131 132 /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */ 133 *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location; 134 return PSA_SUCCESS; 135} 136 137psa_status_t psa_load_se_persistent_data( 138 const psa_se_drv_table_entry_t *driver) 139{ 140 psa_status_t status; 141 psa_storage_uid_t uid; 142 size_t length; 143 144 status = psa_get_se_driver_its_file_uid(driver, &uid); 145 if (status != PSA_SUCCESS) { 146 return status; 147 } 148 149 /* Read the amount of persistent data that the driver requests. 150 * If the data in storage is larger, it is truncated. If the data 151 * in storage is smaller, silently keep what is already at the end 152 * of the output buffer. */ 153 /* psa_get_se_driver_its_file_uid ensures that the size_t 154 * persistent_data_size is in range, but compilers don't know that, 155 * so cast to reassure them. */ 156 return psa_its_get(uid, 0, 157 (uint32_t) driver->u.internal.persistent_data_size, 158 driver->u.internal.persistent_data, 159 &length); 160} 161 162psa_status_t psa_save_se_persistent_data( 163 const psa_se_drv_table_entry_t *driver) 164{ 165 psa_status_t status; 166 psa_storage_uid_t uid; 167 168 status = psa_get_se_driver_its_file_uid(driver, &uid); 169 if (status != PSA_SUCCESS) { 170 return status; 171 } 172 173 /* psa_get_se_driver_its_file_uid ensures that the size_t 174 * persistent_data_size is in range, but compilers don't know that, 175 * so cast to reassure them. */ 176 return psa_its_set(uid, 177 (uint32_t) driver->u.internal.persistent_data_size, 178 driver->u.internal.persistent_data, 179 0); 180} 181 182psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location) 183{ 184 psa_storage_uid_t uid; 185 if (location > PSA_MAX_SE_LOCATION) { 186 return PSA_ERROR_NOT_SUPPORTED; 187 } 188 uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location; 189 return psa_its_remove(uid); 190} 191 192psa_status_t psa_find_se_slot_for_key( 193 const psa_key_attributes_t *attributes, 194 psa_key_creation_method_t method, 195 psa_se_drv_table_entry_t *driver, 196 psa_key_slot_number_t *slot_number) 197{ 198 psa_status_t status; 199 psa_key_location_t key_location = 200 PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); 201 202 /* If the location is wrong, it's a bug in the library. */ 203 if (driver->location != key_location) { 204 return PSA_ERROR_CORRUPTION_DETECTED; 205 } 206 207 /* If the driver doesn't support key creation in any way, give up now. */ 208 if (driver->methods->key_management == NULL) { 209 return PSA_ERROR_NOT_SUPPORTED; 210 } 211 212 if (psa_get_key_slot_number(attributes, slot_number) == PSA_SUCCESS) { 213 /* The application wants to use a specific slot. Allow it if 214 * the driver supports it. On a system with isolation, 215 * the crypto service must check that the application is 216 * permitted to request this slot. */ 217 psa_drv_se_validate_slot_number_t p_validate_slot_number = 218 driver->methods->key_management->p_validate_slot_number; 219 if (p_validate_slot_number == NULL) { 220 return PSA_ERROR_NOT_SUPPORTED; 221 } 222 status = p_validate_slot_number(&driver->u.context, 223 driver->u.internal.persistent_data, 224 attributes, method, 225 *slot_number); 226 } else if (method == PSA_KEY_CREATION_REGISTER) { 227 /* The application didn't specify a slot number. This doesn't 228 * make sense when registering a slot. */ 229 return PSA_ERROR_INVALID_ARGUMENT; 230 } else { 231 /* The application didn't tell us which slot to use. Let the driver 232 * choose. This is the normal case. */ 233 psa_drv_se_allocate_key_t p_allocate = 234 driver->methods->key_management->p_allocate; 235 if (p_allocate == NULL) { 236 return PSA_ERROR_NOT_SUPPORTED; 237 } 238 status = p_allocate(&driver->u.context, 239 driver->u.internal.persistent_data, 240 attributes, method, 241 slot_number); 242 } 243 return status; 244} 245 246psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver, 247 psa_key_slot_number_t slot_number) 248{ 249 psa_status_t status; 250 psa_status_t storage_status; 251 /* Normally a missing method would mean that the action is not 252 * supported. But psa_destroy_key() is not supposed to return 253 * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should 254 * be able to destroy it. The only use case for a driver that 255 * does not have a way to destroy keys at all is if the keys are 256 * locked in a read-only state: we can use the keys but not 257 * destroy them. Hence, if the driver doesn't support destroying 258 * keys, it's really a lack of permission. */ 259 if (driver->methods->key_management == NULL || 260 driver->methods->key_management->p_destroy == NULL) { 261 return PSA_ERROR_NOT_PERMITTED; 262 } 263 status = driver->methods->key_management->p_destroy( 264 &driver->u.context, 265 driver->u.internal.persistent_data, 266 slot_number); 267 storage_status = psa_save_se_persistent_data(driver); 268 return status == PSA_SUCCESS ? storage_status : status; 269} 270 271psa_status_t psa_init_all_se_drivers(void) 272{ 273 size_t i; 274 for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { 275 psa_se_drv_table_entry_t *driver = &driver_table[i]; 276 if (driver->location == 0) { 277 continue; /* skipping unused entry */ 278 } 279 const psa_drv_se_t *methods = psa_get_se_driver_methods(driver); 280 if (methods->p_init != NULL) { 281 psa_status_t status = methods->p_init( 282 &driver->u.context, 283 driver->u.internal.persistent_data, 284 driver->location); 285 if (status != PSA_SUCCESS) { 286 return status; 287 } 288 status = psa_save_se_persistent_data(driver); 289 if (status != PSA_SUCCESS) { 290 return status; 291 } 292 } 293 } 294 return PSA_SUCCESS; 295} 296 297 298 299/****************************************************************/ 300/* Driver registration */ 301/****************************************************************/ 302 303psa_status_t psa_register_se_driver( 304 psa_key_location_t location, 305 const psa_drv_se_t *methods) 306{ 307 size_t i; 308 psa_status_t status; 309 310 if (methods->hal_version != PSA_DRV_SE_HAL_VERSION) { 311 return PSA_ERROR_NOT_SUPPORTED; 312 } 313 /* Driver table entries are 0-initialized. 0 is not a valid driver 314 * location because it means a transparent key. */ 315 MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0, 316 "Secure element support requires 0 to mean a local key"); 317 318 if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) { 319 return PSA_ERROR_INVALID_ARGUMENT; 320 } 321 if (location > PSA_MAX_SE_LOCATION) { 322 return PSA_ERROR_NOT_SUPPORTED; 323 } 324 325 for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { 326 if (driver_table[i].location == 0) { 327 break; 328 } 329 /* Check that location isn't already in use up to the first free 330 * entry. Since entries are created in order and never deleted, 331 * there can't be a used entry after the first free entry. */ 332 if (driver_table[i].location == location) { 333 return PSA_ERROR_ALREADY_EXISTS; 334 } 335 } 336 if (i == PSA_MAX_SE_DRIVERS) { 337 return PSA_ERROR_INSUFFICIENT_MEMORY; 338 } 339 340 driver_table[i].location = location; 341 driver_table[i].methods = methods; 342 driver_table[i].u.internal.persistent_data_size = 343 methods->persistent_data_size; 344 345 if (methods->persistent_data_size != 0) { 346 driver_table[i].u.internal.persistent_data = 347 mbedtls_calloc(1, methods->persistent_data_size); 348 if (driver_table[i].u.internal.persistent_data == NULL) { 349 status = PSA_ERROR_INSUFFICIENT_MEMORY; 350 goto error; 351 } 352 /* Load the driver's persistent data. On first use, the persistent 353 * data does not exist in storage, and is initialized to 354 * all-bits-zero by the calloc call just above. */ 355 status = psa_load_se_persistent_data(&driver_table[i]); 356 if (status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST) { 357 goto error; 358 } 359 } 360 361 return PSA_SUCCESS; 362 363error: 364 memset(&driver_table[i], 0, sizeof(driver_table[i])); 365 return status; 366} 367 368void psa_unregister_all_se_drivers(void) 369{ 370 size_t i; 371 for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { 372 if (driver_table[i].u.internal.persistent_data != NULL) { 373 mbedtls_free(driver_table[i].u.internal.persistent_data); 374 } 375 } 376 memset(driver_table, 0, sizeof(driver_table)); 377} 378 379 380 381/****************************************************************/ 382/* The end */ 383/****************************************************************/ 384 385#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ 386