Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers psa_crypto_se.c Source File

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 */