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