Skip to content

Commit 0b6645e

Browse files
committed
Add docs and some fixes
This commit adds documentation to the structures and methods in the new Trusted Service provider. A few small fixes are also added, along with a finer-grained approach to zeroizing the key data in import_key. Signed-off-by: Ionut Mihalcea <[email protected]>
1 parent f56682b commit 0b6645e

File tree

5 files changed

+119
-26
lines changed

5 files changed

+119
-26
lines changed

src/providers/trusted_service/asym_sign.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl Provider {
2020
Ok(psa_sign_hash::Result {
2121
signature: self
2222
.context
23-
.asym_sign(key_id, op.hash.to_vec(), op.alg)?
23+
.sign_hash(key_id, op.hash.to_vec(), op.alg)?
2424
.into(),
2525
})
2626
}
@@ -35,7 +35,7 @@ impl Provider {
3535
let key_id = key_management::get_key_id(&key_triple, &*store_handle)?;
3636

3737
self.context
38-
.asym_verify(key_id, op.hash.to_vec(), op.signature.to_vec(), op.alg)?;
38+
.verify_hash(key_id, op.hash.to_vec(), op.signature.to_vec(), op.alg)?;
3939

4040
Ok(psa_verify_hash::Result {})
4141
}

src/providers/trusted_service/context/asym_sign.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ use parsec_interface::requests::ResponseStatus;
88
use std::convert::TryInto;
99

1010
impl Context {
11-
pub fn asym_sign(
11+
/// Sign a hash with an asymmetric key given its ID and the signing algorithm.
12+
pub fn sign_hash(
1213
&self,
1314
key_id: u32,
1415
hash: Vec<u8>,
1516
algorithm: AsymmetricSignature,
1617
) -> Result<Vec<u8>, ResponseStatus> {
17-
info!("Handling GenerateKey request");
18+
info!("Handling SignHash request");
1819
let proto_req = SignHashIn {
1920
handle: 0,
2021
hash,
@@ -25,14 +26,15 @@ impl Context {
2526
Ok(signature)
2627
}
2728

28-
pub fn asym_verify(
29+
/// Verify a signature on a hash with an asymmetric key given its ID and the signing algorithm.
30+
pub fn verify_hash(
2931
&self,
3032
key_id: u32,
3133
hash: Vec<u8>,
3234
signature: Vec<u8>,
3335
algorithm: AsymmetricSignature,
3436
) -> Result<(), ResponseStatus> {
35-
info!("Handling GenerateKey request");
37+
info!("Handling VerifyHash request");
3638
let proto_req = VerifyHashIn {
3739
handle: 0,
3840
hash,

src/providers/trusted_service/context/key_management.rs

+39-6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ use std::convert::{TryFrom, TryInto};
1313
use zeroize::Zeroize;
1414

1515
impl Context {
16+
/// Generate a key given its attributes and ID
17+
///
18+
/// Lifetime flexibility is not supported: the `lifetime` parameter in the key
19+
/// attributes is essentially ignored and replaced with `KeyLifetime::Persistent`.
1620
pub fn generate_key(&self, key_attrs: Attributes, id: u32) -> Result<(), ResponseStatus> {
1721
info!("Handling GenerateKey request");
1822
let generate_req = GenerateKeyIn {
@@ -35,38 +39,66 @@ impl Context {
3539
Ok(())
3640
}
3741

42+
/// Import a key given its attributes, ID, and key data.
43+
///
44+
/// Lifetime flexibility is not supported: the `lifetime` parameter in the key
45+
/// attributes is essentially ignored and replaced with `KeyLifetime::Persistent`.
46+
///
47+
/// Key data must be in the format described by the PSA Crypto format.
3848
pub fn import_key(
3949
&self,
4050
key_attrs: Attributes,
4151
id: u32,
4252
key_data: &[u8],
4353
) -> Result<(), ResponseStatus> {
54+
info!("Handling ImportKey request");
55+
let mut data = key_data.to_vec();
4456
let mut import_req = ImportKeyIn {
4557
attributes: Some(KeyAttributes {
46-
r#type: u16::try_from(key_attrs.key_type)? as u32,
47-
key_bits: key_attrs.bits.try_into()?,
58+
r#type: u16::try_from(key_attrs.key_type).map_err(|e| {
59+
data.zeroize();
60+
e
61+
})? as u32,
62+
key_bits: key_attrs.bits.try_into().map_err(|e| {
63+
data.zeroize();
64+
e
65+
})?,
4866
lifetime: KeyLifetime::Persistent as u32,
4967
id,
5068
policy: Some(KeyPolicy {
51-
usage: key_attrs.policy.usage_flags.try_into()?,
52-
alg: key_attrs.policy.permitted_algorithms.try_into()?,
69+
usage: key_attrs.policy.usage_flags.into(),
70+
alg: key_attrs
71+
.policy
72+
.permitted_algorithms
73+
.try_into()
74+
.map_err(|e| {
75+
data.zeroize();
76+
e
77+
})?,
5378
}),
5479
}),
55-
data: key_data.to_vec(),
80+
data,
5681
};
57-
let ImportKeyOut { handle } = self.send_request(&import_req)?;
82+
let res = self.send_request(&import_req);
5883
import_req.data.zeroize();
84+
let ImportKeyOut { handle } = res?;
5985

6086
let close_req = CloseKeyIn { handle };
6187
self.send_request(&close_req)?;
6288

6389
Ok(())
6490
}
6591

92+
/// Export the public part of a key given its ID.
93+
///
94+
/// The public key data is returned in the format specified by the PSA Crypto
95+
/// format.
6696
pub fn export_public_key(&self, id: u32) -> Result<Vec<u8>, ResponseStatus> {
97+
info!("Handling ExportPublicKey request");
6798
Ok(self.send_request_with_key(ExportPublicKeyIn::default(), id)?)
6899
}
69100

101+
/// Destroy a key given its ID.
70102
pub fn destroy_key(&self, key_id: u32) -> Result<(), ResponseStatus> {
71103
info!("Handling DestroyKey request");
72104
if !self.check_key_exists(key_id)? {
@@ -80,6 +112,7 @@ impl Context {
80112
Ok(())
81113
}
82114

115+
/// Verify if a key with a given ID exists.
83116
pub fn check_key_exists(&self, key_id: u32) -> Result<bool, Error> {
84117
info!("Handling CheckKey request");
85118
let open_req = OpenKeyIn { id: key_id };

src/providers/trusted_service/context/mod.rs

+35-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ mod key_management;
5050
mod ts_protobuf {
5151
include!(concat!(env!("OUT_DIR"), "/ts_crypto.rs"));
5252

53+
/// Trait for associating an Opcode with each operation type
54+
/// and obtaining it in a generic way.
5355
pub trait GetOpcode {
5456
fn opcode(&self) -> Opcode;
5557
}
@@ -87,6 +89,8 @@ mod ts_protobuf {
8789
opcode_impl!(ImportKeyIn, ImportKeyOut, ImportKey);
8890
opcode_impl!(ExportPublicKeyIn, ExportPublicKeyOut, ExportPublicKey);
8991

92+
/// Trait allowing the handle of opened-key-dependent operations
93+
/// to be set in a generic way.
9094
pub trait SetHandle {
9195
fn set_handle(&mut self, handle: u32);
9296
}
@@ -110,8 +114,28 @@ mod ts_protobuf {
110114
// TODO:
111115
// * RPC caller error handling
112116
// * proper logging
113-
// * docs
114117

118+
/// Context for interacting with the crypto Trusted Service (TS).
119+
///
120+
/// The context maintains the state necessary for calls to be made
121+
/// and acts as a bridge between the two encoding types: Rust native
122+
/// PSA Crypto and the IPC mechanism used by the Normal World userland
123+
/// TS endpoint.
124+
///
125+
/// `Context` does not surface the full operation sequence demanded by the
126+
/// TS. Keys need not be opened before use - only referenced by their creation
127+
/// ID - and therefore not closed either.
128+
///
129+
/// # Safety
130+
///
131+
/// `Sync` and `Send` are manually implemented on this type since it
132+
/// contains pointers to the structures that perform various tasks
133+
/// and which act as the underlying client of `Context`. The use of
134+
/// these pointers is not thread-safe, so in order to allow `Context`
135+
/// to be used across threads, a `Mutex` is used to lock down all calls.
136+
///
137+
/// Upon being dropped, all the resources are released and no prior cleanup
138+
/// is required from the caller.
115139
#[derive(Debug)]
116140
pub struct Context {
117141
rpc_caller: *mut rpc_caller,
@@ -121,6 +145,7 @@ pub struct Context {
121145
}
122146

123147
impl Context {
148+
/// Establish a connection to the Trusted Service to obtain a working context.
124149
pub fn connect() -> anyhow::Result<Self> {
125150
// Initialise service locator. Can be called multiple times,
126151
// but *must* be called at least once.
@@ -171,11 +196,14 @@ impl Context {
171196
Ok(ctx)
172197
}
173198

199+
// Serialize and send a request and deserialize the response back to
200+
// the caller. The caller is responsible for explicitly declaring
201+
// the response type if its contents are of interest.
174202
fn send_request<T: Message + Default>(
175203
&self,
176204
req: &(impl Message + GetOpcode),
177205
) -> Result<T, PsaError> {
178-
let _mutex_guard = self.call_mutex.try_lock().expect("Call mutex poisoned");
206+
let _mutex_guard = self.call_mutex.lock().expect("Call mutex poisoned");
179207
info!("Beginning call to Trusted Service");
180208

181209
let mut buf_out = null_mut();
@@ -229,16 +257,21 @@ impl Context {
229257
Ok(resp)
230258
}
231259

260+
// Send a request that requires a key, given the key's ID.
261+
// This function is responsible for opening the key, for sending the
262+
// request with `send_request` and for closing the key afterwards.
232263
fn send_request_with_key<T: Message + Default>(
233264
&self,
234265
mut req: impl Message + GetOpcode + SetHandle,
235266
key_id: u32,
236267
) -> Result<T, PsaError> {
237268
let open_req = OpenKeyIn { id: key_id };
238269
let OpenKeyOut { handle } = self.send_request(&open_req)?;
270+
239271
req.set_handle(handle);
240272
let res = self.send_request(&req);
241273
let close_req = CloseKeyIn { handle };
274+
242275
let res_close = self.send_request(&close_req);
243276
let res = res?;
244277
res_close?;

src/providers/trusted_service/mod.rs

+37-12
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@
55
//! This provider is backed by a crypto Trusted Service deployed in TrustZone
66
use super::mbed_crypto::key_management as mbed_crypto_key_management;
77
use crate::authenticators::ApplicationName;
8-
use crate::key_info_managers::KeyTriple;
9-
use crate::key_info_managers::ManageKeyInfo;
8+
use crate::key_info_managers::{self, KeyTriple, ManageKeyInfo};
109
use crate::providers::Provide;
1110
use context::Context;
1211
use derivative::Derivative;
1312
use log::{error, trace};
1413
use parsec_interface::operations::list_providers::ProviderInfo;
1514
use parsec_interface::operations::{
16-
psa_destroy_key, psa_export_public_key, psa_generate_key, psa_import_key, psa_sign_hash,
17-
psa_verify_hash,
15+
list_keys, psa_destroy_key, psa_export_public_key, psa_generate_key, psa_import_key,
16+
psa_sign_hash, psa_verify_hash,
1817
};
19-
use parsec_interface::requests::{Opcode, ProviderID, Result};
18+
use parsec_interface::requests::{Opcode, ProviderID, ResponseStatus, Result};
2019
use psa_crypto::types::key;
2120
use std::collections::HashSet;
21+
use std::ops::Deref;
2222
use std::sync::{
2323
atomic::{AtomicU32, Ordering},
2424
Arc, RwLock,
@@ -29,13 +29,19 @@ mod asym_sign;
2929
mod context;
3030
mod key_management;
3131

32-
const SUPPORTED_OPCODES: [Opcode; 2] = [Opcode::PsaDestroyKey, Opcode::PsaGenerateKey];
32+
const SUPPORTED_OPCODES: [Opcode; 6] = [
33+
Opcode::PsaDestroyKey,
34+
Opcode::PsaGenerateKey,
35+
Opcode::PsaSignHash,
36+
Opcode::PsaVerifyHash,
37+
Opcode::PsaImportKey,
38+
Opcode::PsaExportPublicKey,
39+
];
3340

3441
/// Trusted Service provider structure
3542
///
36-
/// Currently the provider only supports volatile keys due to limitations in the stack
37-
/// underneath us. Therefore none of the key information is persisted, being kept instead
38-
/// in a map for fast access.
43+
/// Operations for this provider are serviced through an IPC interface that leads
44+
/// to a Secure World implementation of PSA Crypto.
3945
#[derive(Derivative)]
4046
#[derivative(Debug)]
4147
pub struct Provider {
@@ -53,7 +59,7 @@ pub struct Provider {
5359
}
5460

5561
impl Provider {
56-
/// Creates and initialise a new instance of Provider.
62+
/// Creates and initialises a new instance of Provider.
5763
fn new(
5864
key_info_store: Arc<RwLock<dyn ManageKeyInfo + Send + Sync>>,
5965
) -> anyhow::Result<Provider> {
@@ -64,14 +70,14 @@ impl Provider {
6470
};
6571
let mut max_key_id: key::psa_key_id_t = key::PSA_KEY_ID_USER_MIN;
6672
{
67-
// The local scope allows to drop store_handle and local_ids_handle in order to return
73+
// The local scope allows dropping store_handle and local_ids_handle in order to return
6874
// the ts_provider.
6975
let mut store_handle = ts_provider
7076
.key_info_store
7177
.write()
7278
.expect("Key store lock poisoned");
7379
let mut to_remove: Vec<KeyTriple> = Vec::new();
74-
// Go through all TrustedServiceProvider key triple to key info mappings and check if they are still
80+
// Go through all TrustedServiceProvider key triples to key info mappings and check if they are still
7581
// present.
7682
// Delete those who are not present and add to the local_store the ones present.
7783
match store_handle.get_all(ProviderID::TrustedService) {
@@ -129,6 +135,25 @@ impl Provide for Provider {
129135
}, SUPPORTED_OPCODES.iter().copied().collect()))
130136
}
131137

138+
fn list_keys(
139+
&self,
140+
app_name: ApplicationName,
141+
_op: list_keys::Operation,
142+
) -> Result<list_keys::Result> {
143+
let store_handle = self.key_info_store.read().expect("Key store lock poisoned");
144+
Ok(list_keys::Result {
145+
keys: key_info_managers::list_keys(
146+
store_handle.deref(),
147+
&app_name,
148+
ProviderID::TrustedService,
149+
)
150+
.map_err(|e| {
151+
format_error!("Error occurred when fetching key information", e);
152+
ResponseStatus::KeyInfoManagerError
153+
})?,
154+
})
155+
}
156+
132157
fn psa_generate_key(
133158
&self,
134159
app_name: ApplicationName,

0 commit comments

Comments
 (0)