@@ -17,7 +17,7 @@ use crate::authenticators::ApplicationName;
17
17
use crate :: key_id_managers:: { KeyTriple , ManageKeyIDs } ;
18
18
use std:: collections:: HashSet ;
19
19
use std:: convert:: TryInto ;
20
- use std:: sync:: { Arc , RwLock } ;
20
+ use std:: sync:: { Arc , Mutex , RwLock } ;
21
21
22
22
use parsec_interface:: operations:: key_attributes:: KeyLifetime ;
23
23
use parsec_interface:: operations:: ProviderInfo ;
@@ -29,6 +29,7 @@ use parsec_interface::operations::{OpExportPublicKey, ResultExportPublicKey};
29
29
use parsec_interface:: operations:: { OpImportKey , ResultImportKey } ;
30
30
use parsec_interface:: operations:: { OpListOpcodes , ResultListOpcodes } ;
31
31
use parsec_interface:: requests:: { Opcode , ProviderID , ResponseStatus , Result } ;
32
+ use std_semaphore:: Semaphore ;
32
33
use uuid:: Uuid ;
33
34
34
35
#[ allow(
@@ -63,6 +64,16 @@ pub struct MbedProvider {
63
64
// reference it to match with the method prototypes.
64
65
key_id_store : Arc < RwLock < dyn ManageKeyIDs + Send + Sync > > ,
65
66
local_ids : RwLock < LocalIdStore > ,
67
+ // Calls to `psa_open_key`, `psa_create_key` and `psa_close_key` are not thread safe - the slot
68
+ // allocation mechanism in Mbed Crypto can return the same key slot for overlapping calls.
69
+ // `key_handle_mutex` is use as a way of securing access to said operations among the threads.
70
+ // This issue tracks progress on fixing the original problem in Mbed Crypto:
71
+ // https://github.com/ARMmbed/mbed-crypto/issues/266
72
+ key_handle_mutex : Mutex < ( ) > ,
73
+ // As mentioned above, calls dealing with key slot allocation are not secured for concurrency.
74
+ // `key_slot_semaphore` is used to ensure that only `PSA_KEY_SLOT_COUNT` threads can have slots
75
+ // assigned at any time.
76
+ key_slot_semaphore : Semaphore ,
66
77
}
67
78
68
79
/// Gets a PSA Key ID from the Key ID Manager.
@@ -156,6 +167,8 @@ impl MbedProvider {
156
167
let mbed_provider = MbedProvider {
157
168
key_id_store,
158
169
local_ids : RwLock :: new ( HashSet :: new ( ) ) ,
170
+ key_handle_mutex : Mutex :: new ( ( ) ) ,
171
+ key_slot_semaphore : Semaphore :: new ( constants:: PSA_KEY_SLOT_COUNT ) ,
159
172
} ;
160
173
{
161
174
// The local scope allows to drop store_handle and local_ids_handle in order to return
@@ -245,6 +258,7 @@ impl Provide for MbedProvider {
245
258
246
259
fn create_key ( & self , app_name : ApplicationName , op : OpCreateKey ) -> Result < ResultCreateKey > {
247
260
println ! ( "Mbed Provider - Create Key" ) ;
261
+ let _semaphore_guard = self . key_slot_semaphore . access ( ) ;
248
262
let key_name = op. key_name ;
249
263
let key_attributes = op. key_attributes ;
250
264
let key_triple = KeyTriple :: new ( app_name, ProviderID :: MbedProvider , key_name) ;
@@ -263,6 +277,10 @@ impl Provide for MbedProvider {
263
277
let mut key_handle: psa_crypto_binding:: psa_key_handle_t = 0 ;
264
278
265
279
let create_key_status = unsafe {
280
+ let _guard = self
281
+ . key_handle_mutex
282
+ . lock ( )
283
+ . expect ( "Grabbing key handle mutex failed" ) ;
266
284
psa_crypto_binding:: psa_create_key ( key_attrs. key_lifetime , key_id, & mut key_handle)
267
285
} ;
268
286
@@ -307,6 +325,10 @@ impl Provide for MbedProvider {
307
325
}
308
326
309
327
unsafe {
328
+ let _guard = self
329
+ . key_handle_mutex
330
+ . lock ( )
331
+ . expect ( "Grabbing key handle mutex failed" ) ;
310
332
psa_crypto_binding:: psa_close_key ( key_handle) ;
311
333
}
312
334
} else {
@@ -328,6 +350,7 @@ impl Provide for MbedProvider {
328
350
329
351
fn import_key ( & self , app_name : ApplicationName , op : OpImportKey ) -> Result < ResultImportKey > {
330
352
println ! ( "Mbed Provider - Import Key" ) ;
353
+ let _semaphore_guard = self . key_slot_semaphore . access ( ) ;
331
354
let key_name = op. key_name ;
332
355
let key_attributes = op. key_attributes ;
333
356
let key_data = op. key_data ;
@@ -347,6 +370,10 @@ impl Provide for MbedProvider {
347
370
let mut key_handle: psa_crypto_binding:: psa_key_handle_t = 0 ;
348
371
349
372
let create_key_status = unsafe {
373
+ let _guard = self
374
+ . key_handle_mutex
375
+ . lock ( )
376
+ . expect ( "Grabbing key handle mutex failed" ) ;
350
377
psa_crypto_binding:: psa_create_key ( key_attrs. key_lifetime , key_id, & mut key_handle)
351
378
} ;
352
379
@@ -390,6 +417,10 @@ impl Provide for MbedProvider {
390
417
}
391
418
392
419
unsafe {
420
+ let _guard = self
421
+ . key_handle_mutex
422
+ . lock ( )
423
+ . expect ( "Grabbing key handle mutex failed" ) ;
393
424
psa_crypto_binding:: psa_close_key ( key_handle) ;
394
425
}
395
426
} else {
@@ -415,6 +446,7 @@ impl Provide for MbedProvider {
415
446
op : OpExportPublicKey ,
416
447
) -> Result < ResultExportPublicKey > {
417
448
println ! ( "Mbed Provider - Export Public Key" ) ;
449
+ let _semaphore_guard = self . key_slot_semaphore . access ( ) ;
418
450
let key_name = op. key_name ;
419
451
let key_lifetime = op. key_lifetime ;
420
452
let key_triple = KeyTriple :: new ( app_name, ProviderID :: MbedProvider , key_name) ;
@@ -426,8 +458,13 @@ impl Provide for MbedProvider {
426
458
427
459
let ret_val: Result < ResultExportPublicKey > ;
428
460
429
- let open_key_status =
430
- unsafe { psa_crypto_binding:: psa_open_key ( lifetime, key_id, & mut key_handle) } ;
461
+ let open_key_status = unsafe {
462
+ let _guard = self
463
+ . key_handle_mutex
464
+ . lock ( )
465
+ . expect ( "Grabbing key handle mutex failed" ) ;
466
+ psa_crypto_binding:: psa_open_key ( lifetime, key_id, & mut key_handle)
467
+ } ;
431
468
432
469
if open_key_status == constants:: PSA_SUCCESS {
433
470
// TODO: There's no calculation of the buffer size here, nor is there any handling of the
@@ -455,6 +492,10 @@ impl Provide for MbedProvider {
455
492
}
456
493
457
494
unsafe {
495
+ let _guard = self
496
+ . key_handle_mutex
497
+ . lock ( )
498
+ . expect ( "Grabbing key handle mutex failed" ) ;
458
499
psa_crypto_binding:: psa_close_key ( key_handle) ;
459
500
}
460
501
} else {
@@ -467,6 +508,7 @@ impl Provide for MbedProvider {
467
508
468
509
fn destroy_key ( & self , app_name : ApplicationName , op : OpDestroyKey ) -> Result < ResultDestroyKey > {
469
510
println ! ( "Mbed Provider - Destroy Key" ) ;
511
+ let _semaphore_guard = self . key_slot_semaphore . access ( ) ;
470
512
let key_name = op. key_name ;
471
513
let key_lifetime = op. key_lifetime ;
472
514
let key_triple = KeyTriple :: new ( app_name, ProviderID :: MbedProvider , key_name) ;
@@ -477,8 +519,13 @@ impl Provide for MbedProvider {
477
519
let lifetime = conversion_utils:: convert_key_lifetime ( key_lifetime) ;
478
520
let mut key_handle: psa_crypto_binding:: psa_key_handle_t = 0 ;
479
521
480
- let open_key_status =
481
- unsafe { psa_crypto_binding:: psa_open_key ( lifetime, key_id, & mut key_handle) } ;
522
+ let open_key_status = unsafe {
523
+ let _guard = self
524
+ . key_handle_mutex
525
+ . lock ( )
526
+ . expect ( "Grabbing key handle mutex failed" ) ;
527
+ psa_crypto_binding:: psa_open_key ( lifetime, key_id, & mut key_handle)
528
+ } ;
482
529
483
530
if open_key_status == constants:: PSA_SUCCESS {
484
531
let destroy_key_status = unsafe { psa_crypto_binding:: psa_destroy_key ( key_handle) } ;
@@ -501,6 +548,7 @@ impl Provide for MbedProvider {
501
548
502
549
fn asym_sign ( & self , app_name : ApplicationName , op : OpAsymSign ) -> Result < ResultAsymSign > {
503
550
println ! ( "Mbed Provider - Asym Sign" ) ;
551
+ let _semaphore_guard = self . key_slot_semaphore . access ( ) ;
504
552
let key_name = op. key_name ;
505
553
let key_lifetime = op. key_lifetime ;
506
554
let hash = op. hash ;
@@ -511,8 +559,13 @@ impl Provide for MbedProvider {
511
559
let lifetime = conversion_utils:: convert_key_lifetime ( key_lifetime) ;
512
560
let mut key_handle: psa_crypto_binding:: psa_key_handle_t = 0 ;
513
561
514
- let open_key_status =
515
- unsafe { psa_crypto_binding:: psa_open_key ( lifetime, key_id, & mut key_handle) } ;
562
+ let open_key_status = unsafe {
563
+ let _guard = self
564
+ . key_handle_mutex
565
+ . lock ( )
566
+ . expect ( "Grabbing key handle mutex failed" ) ;
567
+ psa_crypto_binding:: psa_open_key ( lifetime, key_id, & mut key_handle)
568
+ } ;
516
569
517
570
if open_key_status == constants:: PSA_SUCCESS {
518
571
let mut policy = psa_crypto_binding:: psa_key_policy_t {
@@ -543,6 +596,10 @@ impl Provide for MbedProvider {
543
596
} ;
544
597
545
598
unsafe {
599
+ let _guard = self
600
+ . key_handle_mutex
601
+ . lock ( )
602
+ . expect ( "Grabbing key handle mutex failed" ) ;
546
603
psa_crypto_binding:: psa_close_key ( key_handle) ;
547
604
}
548
605
@@ -564,6 +621,7 @@ impl Provide for MbedProvider {
564
621
565
622
fn asym_verify ( & self , app_name : ApplicationName , op : OpAsymVerify ) -> Result < ResultAsymVerify > {
566
623
println ! ( "Mbed Provider - Asym Verify" ) ;
624
+ let _semaphore_guard = self . key_slot_semaphore . access ( ) ;
567
625
let key_name = op. key_name ;
568
626
let key_lifetime = op. key_lifetime ;
569
627
let hash = op. hash ;
@@ -575,8 +633,13 @@ impl Provide for MbedProvider {
575
633
let lifetime = conversion_utils:: convert_key_lifetime ( key_lifetime) ;
576
634
let mut key_handle: psa_crypto_binding:: psa_key_handle_t = 0 ;
577
635
578
- let open_key_status =
579
- unsafe { psa_crypto_binding:: psa_open_key ( lifetime, key_id, & mut key_handle) } ;
636
+ let open_key_status = unsafe {
637
+ let _guard = self
638
+ . key_handle_mutex
639
+ . lock ( )
640
+ . expect ( "Grabbing key handle mutex failed" ) ;
641
+ psa_crypto_binding:: psa_open_key ( lifetime, key_id, & mut key_handle)
642
+ } ;
580
643
581
644
if open_key_status == constants:: PSA_SUCCESS {
582
645
let mut policy = psa_crypto_binding:: psa_key_policy_t {
@@ -605,6 +668,10 @@ impl Provide for MbedProvider {
605
668
} ;
606
669
607
670
unsafe {
671
+ let _guard = self
672
+ . key_handle_mutex
673
+ . lock ( )
674
+ . expect ( "Grabbing key handle mutex failed" ) ;
608
675
psa_crypto_binding:: psa_close_key ( key_handle) ;
609
676
}
610
677
0 commit comments