Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
psa_crypto_se.c
00001 /* 00002 * PSA crypto support for secure element drivers 00003 */ 00004 /* Copyright (C) 2019, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of Mbed TLS (https://tls.mbed.org) 00020 */ 00021 00022 #if !defined(MBEDTLS_CONFIG_FILE) 00023 #include "mbedtls/config.h" 00024 #else 00025 #include MBEDTLS_CONFIG_FILE 00026 #endif 00027 00028 #if defined(MBEDTLS_PSA_CRYPTO_SE_C) 00029 00030 #include <assert.h> 00031 #include <stdint.h> 00032 #include <string.h> 00033 00034 #include "psa/crypto_se_driver.h" 00035 00036 #include "psa_crypto_se.h" 00037 00038 #if defined(MBEDTLS_PSA_ITS_FILE_C) 00039 #include "psa_crypto_its.h" 00040 #else /* Native ITS implementation */ 00041 #include "psa/error.h" 00042 #include "psa/internal_trusted_storage.h" 00043 #endif 00044 00045 #include "mbedtls/platform.h" 00046 #if !defined(MBEDTLS_PLATFORM_C) 00047 #define mbedtls_calloc calloc 00048 #define mbedtls_free free 00049 #endif 00050 00051 00052 00053 /****************************************************************/ 00054 /* Driver lookup */ 00055 /****************************************************************/ 00056 00057 /* This structure is identical to psa_drv_se_context_t declared in 00058 * `crypto_se_driver.h`, except that some parts are writable here 00059 * (non-const, or pointer to non-const). */ 00060 typedef struct 00061 { 00062 void *persistent_data; 00063 size_t persistent_data_size; 00064 uintptr_t transient_data; 00065 } psa_drv_se_internal_context_t; 00066 00067 typedef struct psa_se_drv_table_entry_s 00068 { 00069 psa_key_lifetime_t lifetime; 00070 const psa_drv_se_t *methods; 00071 union 00072 { 00073 psa_drv_se_internal_context_t internal; 00074 psa_drv_se_context_t context; 00075 }; 00076 } psa_se_drv_table_entry_t; 00077 00078 static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS]; 00079 00080 psa_se_drv_table_entry_t *psa_get_se_driver_entry( 00081 psa_key_lifetime_t lifetime ) 00082 { 00083 size_t i; 00084 /* In the driver table, lifetime=0 means an entry that isn't used. 00085 * No driver has a lifetime of 0 because it's a reserved value 00086 * (which designates volatile keys). Make sure we never return 00087 * a driver entry for lifetime 0. */ 00088 if( lifetime == 0 ) 00089 return( NULL ); 00090 for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) 00091 { 00092 if( driver_table[i].lifetime == lifetime ) 00093 return( &driver_table[i] ); 00094 } 00095 return( NULL ); 00096 } 00097 00098 const psa_drv_se_t *psa_get_se_driver_methods( 00099 const psa_se_drv_table_entry_t *driver ) 00100 { 00101 return( driver->methods ); 00102 } 00103 00104 psa_drv_se_context_t *psa_get_se_driver_context( 00105 psa_se_drv_table_entry_t *driver ) 00106 { 00107 return( &driver->context ); 00108 } 00109 00110 int psa_get_se_driver( psa_key_lifetime_t lifetime, 00111 const psa_drv_se_t **p_methods, 00112 psa_drv_se_context_t **p_drv_context) 00113 { 00114 psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry( lifetime ); 00115 if( p_methods != NULL ) 00116 *p_methods = ( driver ? driver->methods : NULL ); 00117 if( p_drv_context != NULL ) 00118 *p_drv_context = ( driver ? &driver->context : NULL ); 00119 return( driver != NULL ); 00120 } 00121 00122 00123 00124 /****************************************************************/ 00125 /* Persistent data management */ 00126 /****************************************************************/ 00127 00128 static psa_status_t psa_get_se_driver_its_file_uid( 00129 const psa_se_drv_table_entry_t *driver, 00130 psa_storage_uid_t *uid ) 00131 { 00132 if( driver->lifetime > PSA_MAX_SE_LIFETIME ) 00133 return( PSA_ERROR_NOT_SUPPORTED ); 00134 00135 #if SIZE_MAX > UINT32_MAX 00136 /* ITS file sizes are limited to 32 bits. */ 00137 if( driver->internal.persistent_data_size > UINT32_MAX ) 00138 return( PSA_ERROR_NOT_SUPPORTED ); 00139 #endif 00140 00141 /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */ 00142 *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->lifetime; 00143 return( PSA_SUCCESS ); 00144 } 00145 00146 psa_status_t psa_load_se_persistent_data( 00147 const psa_se_drv_table_entry_t *driver ) 00148 { 00149 psa_status_t status; 00150 psa_storage_uid_t uid; 00151 size_t length; 00152 00153 status = psa_get_se_driver_its_file_uid( driver, &uid ); 00154 if( status != PSA_SUCCESS ) 00155 return( status ); 00156 00157 /* Read the amount of persistent data that the driver requests. 00158 * If the data in storage is larger, it is truncated. If the data 00159 * in storage is smaller, silently keep what is already at the end 00160 * of the output buffer. */ 00161 /* psa_get_se_driver_its_file_uid ensures that the size_t 00162 * persistent_data_size is in range, but compilers don't know that, 00163 * so cast to reassure them. */ 00164 return( psa_its_get( uid, 0, 00165 (uint32_t) driver->internal.persistent_data_size, 00166 driver->internal.persistent_data, 00167 &length ) ); 00168 } 00169 00170 psa_status_t psa_save_se_persistent_data( 00171 const psa_se_drv_table_entry_t *driver ) 00172 { 00173 psa_status_t status; 00174 psa_storage_uid_t uid; 00175 00176 status = psa_get_se_driver_its_file_uid( driver, &uid ); 00177 if( status != PSA_SUCCESS ) 00178 return( status ); 00179 00180 /* psa_get_se_driver_its_file_uid ensures that the size_t 00181 * persistent_data_size is in range, but compilers don't know that, 00182 * so cast to reassure them. */ 00183 return( psa_its_set( uid, 00184 (uint32_t) driver->internal.persistent_data_size, 00185 driver->internal.persistent_data, 00186 0 ) ); 00187 } 00188 00189 psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime ) 00190 { 00191 psa_storage_uid_t uid; 00192 if( lifetime > PSA_MAX_SE_LIFETIME ) 00193 return( PSA_ERROR_NOT_SUPPORTED ); 00194 uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + lifetime; 00195 return( psa_its_remove( uid ) ); 00196 } 00197 00198 psa_status_t psa_find_se_slot_for_key( 00199 const psa_key_attributes_t *attributes, 00200 psa_key_creation_method_t method, 00201 psa_se_drv_table_entry_t *driver, 00202 psa_key_slot_number_t *slot_number ) 00203 { 00204 psa_status_t status; 00205 00206 /* If the lifetime is wrong, it's a bug in the library. */ 00207 if( driver->lifetime != psa_get_key_lifetime( attributes ) ) 00208 return( PSA_ERROR_CORRUPTION_DETECTED ); 00209 00210 /* If the driver doesn't support key creation in any way, give up now. */ 00211 if( driver->methods->key_management == NULL ) 00212 return( PSA_ERROR_NOT_SUPPORTED ); 00213 00214 if( psa_get_key_slot_number( attributes, slot_number ) == PSA_SUCCESS ) 00215 { 00216 /* The application wants to use a specific slot. Allow it if 00217 * the driver supports it. On a system with isolation, 00218 * the crypto service must check that the application is 00219 * permitted to request this slot. */ 00220 psa_drv_se_validate_slot_number_t p_validate_slot_number = 00221 driver->methods->key_management->p_validate_slot_number; 00222 if( p_validate_slot_number == NULL ) 00223 return( PSA_ERROR_NOT_SUPPORTED ); 00224 status = p_validate_slot_number( &driver->context, 00225 driver->internal.persistent_data, 00226 attributes, method, 00227 *slot_number ); 00228 } 00229 else if( method == PSA_KEY_CREATION_REGISTER ) 00230 { 00231 /* The application didn't specify a slot number. This doesn't 00232 * make sense when registering a slot. */ 00233 return( PSA_ERROR_INVALID_ARGUMENT ); 00234 } 00235 else 00236 { 00237 /* The application didn't tell us which slot to use. Let the driver 00238 * choose. This is the normal case. */ 00239 psa_drv_se_allocate_key_t p_allocate = 00240 driver->methods->key_management->p_allocate; 00241 if( p_allocate == NULL ) 00242 return( PSA_ERROR_NOT_SUPPORTED ); 00243 status = p_allocate( &driver->context, 00244 driver->internal.persistent_data, 00245 attributes, method, 00246 slot_number ); 00247 } 00248 return( status ); 00249 } 00250 00251 psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver, 00252 psa_key_slot_number_t slot_number ) 00253 { 00254 psa_status_t status; 00255 psa_status_t storage_status; 00256 /* Normally a missing method would mean that the action is not 00257 * supported. But psa_destroy_key() is not supposed to return 00258 * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should 00259 * be able to destroy it. The only use case for a driver that 00260 * does not have a way to destroy keys at all is if the keys are 00261 * locked in a read-only state: we can use the keys but not 00262 * destroy them. Hence, if the driver doesn't support destroying 00263 * keys, it's really a lack of permission. */ 00264 if( driver->methods->key_management == NULL || 00265 driver->methods->key_management->p_destroy == NULL ) 00266 return( PSA_ERROR_NOT_PERMITTED ); 00267 status = driver->methods->key_management->p_destroy( 00268 &driver->context, 00269 driver->internal.persistent_data, 00270 slot_number ); 00271 storage_status = psa_save_se_persistent_data( driver ); 00272 return( status == PSA_SUCCESS ? storage_status : status ); 00273 } 00274 00275 psa_status_t psa_init_all_se_drivers( void ) 00276 { 00277 size_t i; 00278 for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) 00279 { 00280 psa_se_drv_table_entry_t *driver = &driver_table[i]; 00281 if( driver->lifetime == 0 ) 00282 continue; /* skipping unused entry */ 00283 const psa_drv_se_t *methods = psa_get_se_driver_methods( driver ); 00284 if( methods->p_init != NULL ) 00285 { 00286 psa_status_t status = methods->p_init( 00287 &driver->context, 00288 driver->internal.persistent_data, 00289 driver->lifetime ); 00290 if( status != PSA_SUCCESS ) 00291 return( status ); 00292 status = psa_save_se_persistent_data( driver ); 00293 if( status != PSA_SUCCESS ) 00294 return( status ); 00295 } 00296 } 00297 return( PSA_SUCCESS ); 00298 } 00299 00300 00301 00302 /****************************************************************/ 00303 /* Driver registration */ 00304 /****************************************************************/ 00305 00306 psa_status_t psa_register_se_driver( 00307 psa_key_lifetime_t lifetime, 00308 const psa_drv_se_t *methods) 00309 { 00310 size_t i; 00311 psa_status_t status; 00312 00313 if( methods->hal_version != PSA_DRV_SE_HAL_VERSION ) 00314 return( PSA_ERROR_NOT_SUPPORTED ); 00315 /* Driver table entries are 0-initialized. 0 is not a valid driver 00316 * lifetime because it means a volatile key. */ 00317 #if defined(static_assert) 00318 static_assert( PSA_KEY_LIFETIME_VOLATILE == 0, 00319 "Secure element support requires 0 to mean a volatile key" ); 00320 #endif 00321 if( lifetime == PSA_KEY_LIFETIME_VOLATILE || 00322 lifetime == PSA_KEY_LIFETIME_PERSISTENT ) 00323 { 00324 return( PSA_ERROR_INVALID_ARGUMENT ); 00325 } 00326 if( lifetime > PSA_MAX_SE_LIFETIME ) 00327 return( PSA_ERROR_NOT_SUPPORTED ); 00328 00329 for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) 00330 { 00331 if( driver_table[i].lifetime == 0 ) 00332 break; 00333 /* Check that lifetime isn't already in use up to the first free 00334 * entry. Since entries are created in order and never deleted, 00335 * there can't be a used entry after the first free entry. */ 00336 if( driver_table[i].lifetime == lifetime ) 00337 return( PSA_ERROR_ALREADY_EXISTS ); 00338 } 00339 if( i == PSA_MAX_SE_DRIVERS ) 00340 return( PSA_ERROR_INSUFFICIENT_MEMORY ); 00341 00342 driver_table[i].lifetime = lifetime; 00343 driver_table[i].methods = methods; 00344 driver_table[i].internal.persistent_data_size = 00345 methods->persistent_data_size; 00346 00347 if( methods->persistent_data_size != 0 ) 00348 { 00349 driver_table[i].internal.persistent_data = 00350 mbedtls_calloc( 1, methods->persistent_data_size ); 00351 if( driver_table[i].internal.persistent_data == NULL ) 00352 { 00353 status = PSA_ERROR_INSUFFICIENT_MEMORY; 00354 goto error; 00355 } 00356 /* Load the driver's persistent data. On first use, the persistent 00357 * data does not exist in storage, and is initialized to 00358 * all-bits-zero by the calloc call just above. */ 00359 status = psa_load_se_persistent_data( &driver_table[i] ); 00360 if( status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST ) 00361 goto error; 00362 } 00363 00364 return( PSA_SUCCESS ); 00365 00366 error: 00367 memset( &driver_table[i], 0, sizeof( driver_table[i] ) ); 00368 return( status ); 00369 } 00370 00371 void psa_unregister_all_se_drivers( void ) 00372 { 00373 size_t i; 00374 for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) 00375 { 00376 if( driver_table[i].internal.persistent_data != NULL ) 00377 mbedtls_free( driver_table[i].internal.persistent_data ); 00378 } 00379 memset( driver_table, 0, sizeof( driver_table ) ); 00380 } 00381 00382 00383 00384 /****************************************************************/ 00385 /* The end */ 00386 /****************************************************************/ 00387 00388 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
Generated on Tue Jul 12 2022 13:54:45 by
