Skip to content

Commit 05fe3b1

Browse files
committed
Ensure the safety of unsafe blocks
Checks all unsafe uses and comment why it is safe to use unsafe in the specific context. Refactors the utils module to make it easier to prove safety. Signed-off-by: Hugues de Valon <[email protected]>
1 parent 6a1cd93 commit 05fe3b1

File tree

2 files changed

+288
-128
lines changed

2 files changed

+288
-128
lines changed

src/providers/mbed_provider/mod.rs

Lines changed: 150 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,13 @@ use parsec_interface::operations::{OpExportPublicKey, ResultExportPublicKey};
2727
use parsec_interface::operations::{OpImportKey, ResultImportKey};
2828
use parsec_interface::operations::{OpListOpcodes, ResultListOpcodes};
2929
use parsec_interface::requests::{Opcode, ProviderID, ResponseStatus, Result};
30-
use psa_crypto_binding::psa_key_handle_t as KeyHandle;
31-
use psa_crypto_binding::psa_key_id_t as KeyId;
30+
use psa_crypto_binding::psa_key_id_t;
3231
use std::collections::HashSet;
3332
use std::convert::TryInto;
3433
use std::io::{Error, ErrorKind};
3534
use std::sync::{Arc, Mutex, RwLock};
3635
use std_semaphore::Semaphore;
37-
use utils::Key;
36+
use utils::KeyHandle;
3837
use uuid::Uuid;
3938

4039
#[allow(
@@ -53,7 +52,7 @@ mod psa_crypto_binding {
5352
mod constants;
5453
mod utils;
5554

56-
type LocalIdStore = HashSet<KeyId>;
55+
type LocalIdStore = HashSet<psa_key_id_t>;
5756

5857
const SUPPORTED_OPCODES: [Opcode; 7] = [
5958
Opcode::CreateKey,
@@ -91,7 +90,7 @@ pub struct MbedProvider {
9190
/// Gets a PSA Key ID from the Key ID Manager.
9291
/// Wrapper around the get method of the Key ID Manager to convert the key ID to the psa_key_id_t
9392
/// type.
94-
fn get_key_id(key_triple: &KeyTriple, store_handle: &dyn ManageKeyIDs) -> Result<KeyId> {
93+
fn get_key_id(key_triple: &KeyTriple, store_handle: &dyn ManageKeyIDs) -> Result<psa_key_id_t> {
9594
match store_handle.get(key_triple) {
9695
Ok(Some(key_id)) => {
9796
if let Ok(key_id_bytes) = key_id.try_into() {
@@ -114,13 +113,13 @@ fn create_key_id(
114113
key_triple: KeyTriple,
115114
store_handle: &mut dyn ManageKeyIDs,
116115
local_ids_handle: &mut LocalIdStore,
117-
) -> Result<KeyId> {
118-
let mut key_id = rand::random::<KeyId>();
116+
) -> Result<psa_key_id_t> {
117+
let mut key_id = rand::random::<psa_key_id_t>();
119118
while local_ids_handle.contains(&key_id)
120119
|| key_id == 0
121120
|| key_id > constants::PSA_MAX_PERSISTENT_KEY_IDENTIFIER
122121
{
123-
key_id = rand::random::<KeyId>();
122+
key_id = rand::random::<psa_key_id_t>();
124123
}
125124
match store_handle.insert(key_triple.clone(), key_id.to_ne_bytes().to_vec()) {
126125
Ok(insert_option) => {
@@ -140,7 +139,7 @@ fn create_key_id(
140139

141140
fn remove_key_id(
142141
key_triple: &KeyTriple,
143-
key_id: KeyId,
142+
key_id: psa_key_id_t,
144143
store_handle: &mut dyn ManageKeyIDs,
145144
local_ids_handle: &mut LocalIdStore,
146145
) -> Result<()> {
@@ -172,6 +171,8 @@ impl MbedProvider {
172171
/// if there, delete them. Adds Key IDs currently in use in the local IDs store.
173172
/// Returns `None` if the initialisation failed.
174173
fn new(key_id_store: Arc<RwLock<dyn ManageKeyIDs + Send + Sync>>) -> Option<MbedProvider> {
174+
// Safety: this function should be called before any of the other Mbed Crypto functions
175+
// are.
175176
if unsafe { psa_crypto_binding::psa_crypto_init() } != PSA_SUCCESS {
176177
error!("Error when initialising Mbed Crypto");
177178
return None;
@@ -208,23 +209,22 @@ impl MbedProvider {
208209
continue;
209210
}
210211
};
211-
let mut key_handle: KeyHandle = Default::default();
212-
let open_key_status =
213-
unsafe { psa_crypto_binding::psa_open_key(key_id, &mut key_handle) };
214-
if open_key_status == constants::PSA_ERROR_DOES_NOT_EXIST {
215-
to_remove.push(key_triple.clone());
216-
} else if open_key_status != PSA_SUCCESS {
217-
error!(
218-
"Error {} when opening a persistent Mbed Crypto key.",
219-
open_key_status
220-
);
221-
return None;
222-
} else {
223-
let _ = local_ids_handle.insert(key_id);
224-
unsafe {
225-
let _ = psa_crypto_binding::psa_close_key(key_handle);
212+
213+
// Safety: safe because:
214+
// * the Mbed Crypto library has been initialized
215+
// * this code is executed only by the main thread
216+
match unsafe { KeyHandle::open(key_id) } {
217+
Ok(_) => {
218+
let _ = local_ids_handle.insert(key_id);
219+
}
220+
Err(ResponseStatus::PsaErrorDoesNotExist) => {
221+
to_remove.push(key_triple.clone())
222+
}
223+
Err(e) => {
224+
error!("Error {} when opening a persistent Mbed Crypto key.", e);
225+
return None;
226226
}
227-
}
227+
};
228228
}
229229
}
230230
Err(string) => {
@@ -282,28 +282,30 @@ impl Provide for MbedProvider {
282282
)?;
283283

284284
let key_attrs = utils::convert_key_attributes(&key_attributes, key_id)?;
285-
let mut key = Key::new(&self.key_handle_mutex);
286-
287-
let generate_key_status = unsafe {
288-
let _guard = self
289-
.key_handle_mutex
290-
.lock()
291-
.expect("Grabbing key handle mutex failed");
292-
psa_crypto_binding::psa_generate_key(&key_attrs, key.as_mut())
293-
};
294285

295-
if generate_key_status != PSA_SUCCESS {
286+
let _guard = self
287+
.key_handle_mutex
288+
.lock()
289+
.expect("Grabbing key handle mutex failed");
290+
291+
// Safety:
292+
// * at this point the provider has been instantiated so Mbed Crypto has been initialized
293+
// * self.key_handle_mutex prevents concurrent accesses
294+
// * self.key_slot_semaphore prevents overflowing key slots
295+
let mut key_handle = unsafe { KeyHandle::generate(&key_attrs) }.or_else(|e| {
296296
remove_key_id(
297297
&key_triple,
298298
key_id,
299299
&mut *store_handle,
300300
&mut local_ids_handle,
301301
)?;
302-
error!("Generate key status: {}", generate_key_status);
303-
return Err(utils::convert_status(generate_key_status).ok_or_else(|| {
304-
error!("Failed to convert error status.");
305-
ResponseStatus::PsaErrorGenericError
306-
})?);
302+
error!("Generate key status: {}", e);
303+
Err(e)
304+
})?;
305+
306+
// Safety: same conditions than above.
307+
unsafe {
308+
key_handle.close()?;
307309
}
308310

309311
Ok(ResultCreateKey {})
@@ -328,33 +330,30 @@ impl Provide for MbedProvider {
328330
)?;
329331

330332
let key_attrs = utils::convert_key_attributes(&key_attributes, key_id)?;
331-
let mut key = Key::new(&self.key_handle_mutex);
332-
333-
let import_key_status = unsafe {
334-
let _guard = self
335-
.key_handle_mutex
336-
.lock()
337-
.expect("Grabbing key handle mutex failed");
338-
psa_crypto_binding::psa_import_key(
339-
&key_attrs,
340-
key_data.as_ptr(),
341-
key_data.len(),
342-
key.as_mut(),
343-
)
344-
};
345333

346-
if import_key_status != PSA_SUCCESS {
334+
let _guard = self
335+
.key_handle_mutex
336+
.lock()
337+
.expect("Grabbing key handle mutex failed");
338+
339+
// Safety:
340+
// * at this point the provider has been instantiated so Mbed Crypto has been initialized
341+
// * self.key_handle_mutex prevents concurrent accesses
342+
// * self.key_slot_semaphore prevents overflowing key slots
343+
let mut key_handle = unsafe { KeyHandle::import(&key_attrs, key_data) }.or_else(|e| {
347344
remove_key_id(
348345
&key_triple,
349346
key_id,
350347
&mut *store_handle,
351348
&mut local_ids_handle,
352349
)?;
353-
error!("Import key status: {}", import_key_status);
354-
return Err(utils::convert_status(import_key_status).ok_or_else(|| {
355-
error!("Failed to convert error status.");
356-
ResponseStatus::PsaErrorGenericError
357-
})?);
350+
error!("Import key status: {}", e);
351+
Err(e)
352+
})?;
353+
354+
// Safety: same conditions than above.
355+
unsafe {
356+
key_handle.close()?;
358357
}
359358

360359
Ok(ResultImportKey {})
@@ -371,24 +370,43 @@ impl Provide for MbedProvider {
371370
let key_triple = KeyTriple::new(app_name, ProviderID::MbedProvider, key_name);
372371
let store_handle = self.key_id_store.read().expect("Key store lock poisoned");
373372
let key_id = get_key_id(&key_triple, &*store_handle)?;
374-
let key = Key::open_key(key_id, &self.key_handle_mutex)?;
375373

376-
let key_attrs = key.get_attributes()?;
377-
let buffer_size = utils::psa_export_public_key_size(&key_attrs)?;
374+
let _guard = self
375+
.key_handle_mutex
376+
.lock()
377+
.expect("Grabbing key handle mutex failed");
378+
379+
let mut key_handle;
380+
let mut key_attrs;
381+
// Safety:
382+
// * at this point the provider has been instantiated so Mbed Crypto has been initialized
383+
// * self.key_handle_mutex prevents concurrent accesses
384+
// * self.key_slot_semaphore prevents overflowing key slots
385+
unsafe {
386+
key_handle = KeyHandle::open(key_id)?;
387+
key_attrs = key_handle.attributes()?;
388+
}
389+
390+
let buffer_size = utils::psa_export_public_key_size(key_attrs.as_ref())?;
378391
let mut buffer = vec![0u8; buffer_size];
379392
let mut actual_size = 0;
380393

381-
let export_status = unsafe {
382-
psa_crypto_binding::psa_export_public_key(
383-
key.raw_handle(),
394+
let export_status;
395+
// Safety: same conditions than above.
396+
unsafe {
397+
export_status = psa_crypto_binding::psa_export_public_key(
398+
key_handle.raw(),
384399
buffer.as_mut_ptr(),
385400
buffer_size,
386401
&mut actual_size,
387-
)
402+
);
403+
key_attrs.reset();
404+
key_handle.close()?;
388405
};
389406

390407
if export_status != PSA_SUCCESS {
391408
error!("Export status: {}", export_status);
409+
// Safety: same conditions than above.
392410
return Err(utils::convert_status(export_status).ok_or_else(|| {
393411
error!("Failed to convert error status.");
394412
ResponseStatus::PsaErrorGenericError
@@ -407,9 +425,23 @@ impl Provide for MbedProvider {
407425
let mut store_handle = self.key_id_store.write().expect("Key store lock poisoned");
408426
let mut local_ids_handle = self.local_ids.write().expect("Local ID lock poisoned");
409427
let key_id = get_key_id(&key_triple, &*store_handle)?;
410-
let key = Key::open_key(key_id, &self.key_handle_mutex)?;
411428

412-
let destroy_key_status = unsafe { psa_crypto_binding::psa_destroy_key(key.raw_handle()) };
429+
let _guard = self
430+
.key_handle_mutex
431+
.lock()
432+
.expect("Grabbing key handle mutex failed");
433+
434+
let key_handle;
435+
let destroy_key_status;
436+
437+
// Safety:
438+
// * at this point the provider has been instantiated so Mbed Crypto has been initialized
439+
// * self.key_handle_mutex prevents concurrent accesses
440+
// * self.key_slot_semaphore prevents overflowing key slots
441+
unsafe {
442+
key_handle = KeyHandle::open(key_id)?;
443+
destroy_key_status = psa_crypto_binding::psa_destroy_key(key_handle.raw());
444+
}
413445

414446
if destroy_key_status == PSA_SUCCESS {
415447
remove_key_id(
@@ -436,23 +468,41 @@ impl Provide for MbedProvider {
436468
let key_triple = KeyTriple::new(app_name, ProviderID::MbedProvider, key_name);
437469
let store_handle = self.key_id_store.read().expect("Key store lock poisoned");
438470
let key_id = get_key_id(&key_triple, &*store_handle)?;
439-
let key = Key::open_key(key_id, &self.key_handle_mutex)?;
440-
let key_attrs = key.get_attributes()?;
441471

442-
let buffer_size = utils::psa_asymmetric_sign_output_size(&key_attrs)?;
472+
let _guard = self
473+
.key_handle_mutex
474+
.lock()
475+
.expect("Grabbing key handle mutex failed");
476+
477+
let mut key_handle;
478+
let mut key_attrs;
479+
// Safety:
480+
// * at this point the provider has been instantiated so Mbed Crypto has been initialized
481+
// * self.key_handle_mutex prevents concurrent accesses
482+
// * self.key_slot_semaphore prevents overflowing key slots
483+
unsafe {
484+
key_handle = KeyHandle::open(key_id)?;
485+
key_attrs = key_handle.attributes()?;
486+
}
487+
488+
let buffer_size = utils::psa_asymmetric_sign_output_size(key_attrs.as_ref())?;
443489
let mut signature = vec![0u8; buffer_size];
444490
let mut signature_size: usize = 0;
445491

446-
let sign_status = unsafe {
447-
psa_crypto_binding::psa_asymmetric_sign(
448-
key.raw_handle(),
449-
key_attrs.core.policy.alg,
492+
let sign_status;
493+
// Safety: same conditions than above.
494+
unsafe {
495+
sign_status = psa_crypto_binding::psa_asymmetric_sign(
496+
key_handle.raw(),
497+
key_attrs.raw().core.policy.alg,
450498
hash.as_ptr(),
451499
hash.len(),
452500
signature.as_mut_ptr(),
453501
buffer_size,
454502
&mut signature_size,
455-
)
503+
);
504+
key_attrs.reset();
505+
key_handle.close()?;
456506
};
457507

458508
if sign_status == PSA_SUCCESS {
@@ -481,19 +531,33 @@ impl Provide for MbedProvider {
481531
let key_triple = KeyTriple::new(app_name, ProviderID::MbedProvider, key_name);
482532
let store_handle = self.key_id_store.read().expect("Key store lock poisoned");
483533
let key_id = get_key_id(&key_triple, &*store_handle)?;
484-
let key = Key::open_key(key_id, &self.key_handle_mutex)?;
485-
let key_attrs = key.get_attributes()?;
486534

487-
let verify_status = unsafe {
488-
psa_crypto_binding::psa_asymmetric_verify(
489-
key.raw_handle(),
490-
key_attrs.core.policy.alg,
535+
let _guard = self
536+
.key_handle_mutex
537+
.lock()
538+
.expect("Grabbing key handle mutex failed");
539+
540+
let mut key_handle;
541+
let mut key_attrs;
542+
let verify_status;
543+
// Safety:
544+
// * at this point the provider has been instantiated so Mbed Crypto has been initialized
545+
// * self.key_handle_mutex prevents concurrent accesses
546+
// * self.key_slot_semaphore prevents overflowing key slots
547+
unsafe {
548+
key_handle = KeyHandle::open(key_id)?;
549+
key_attrs = key_handle.attributes()?;
550+
verify_status = psa_crypto_binding::psa_asymmetric_verify(
551+
key_handle.raw(),
552+
key_attrs.raw().core.policy.alg,
491553
hash.as_ptr(),
492554
hash.len(),
493555
signature.as_ptr(),
494556
signature.len(),
495-
)
496-
};
557+
);
558+
key_attrs.reset();
559+
key_handle.close()?;
560+
}
497561

498562
if verify_status == PSA_SUCCESS {
499563
Ok(ResultAsymVerify {})
@@ -508,6 +572,7 @@ impl Provide for MbedProvider {
508572

509573
impl Drop for MbedProvider {
510574
fn drop(&mut self) {
575+
// Safety: the Provider was initialized with psa_crypto_init
511576
unsafe {
512577
psa_crypto_binding::mbedtls_psa_crypto_free();
513578
}

0 commit comments

Comments
 (0)