Skip to content

Commit 6fe57f3

Browse files
committed
Add TS provider
Create base of Trusted Service provider - it connects to the service and can be instantiated in the service. Signed-off-by: Ionut Mihalcea <[email protected]>
1 parent 7417c2d commit 6fe57f3

File tree

6 files changed

+240
-4
lines changed

6 files changed

+240
-4
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ users = "0.11.0"
4545
libc = "0.2.77"
4646
anyhow = "1.0.32"
4747
rust-cryptoauthlib = { version = "0.1.0", optional = true }
48+
prost = { version = "0.6.1", optional = true }
4849

4950
[dev-dependencies]
5051
rand = { version = "0.8.2", features = ["small_rng"] }
@@ -64,7 +65,7 @@ mbed-crypto-provider = ["psa-crypto"]
6465
pkcs11-provider = ["pkcs11", "picky-asn1-der", "picky-asn1", "picky-asn1-x509", "psa-crypto", "rand"]
6566
tpm-provider = ["tss-esapi", "picky-asn1-der", "picky-asn1", "picky-asn1-x509", "hex"]
6667
cryptoauthlib-provider = ["rust-cryptoauthlib"]
67-
trusted-service-provider = ["psa-crypto", "bindgen", "prost-build"]
68+
trusted-service-provider = ["psa-crypto", "bindgen", "prost-build", "prost"]
6869
all-providers = ["tpm-provider", "pkcs11-provider", "mbed-crypto-provider", "cryptoauthlib-provider"]
6970

7071
# Authenticators

src/providers/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ pub mod tpm;
2626
#[cfg(feature = "cryptoauthlib-provider")]
2727
pub mod cryptoauthlib;
2828

29+
#[cfg(feature = "trusted-service-provider")]
30+
pub mod trusted_service;
31+
2932
/// Provider configuration structure
3033
/// For providers configs in Parsec config.toml we use a format similar
3134
/// to the one described in the Internally Tagged Enum representation
@@ -81,6 +84,11 @@ pub enum ProviderConfig {
8184
/// I2C baud rate
8285
baud: Option<u32>,
8386
},
87+
/// Trusted Service provider configuration
88+
TrustedService {
89+
/// Name of Key Info Manager to use
90+
key_info_manager: String,
91+
},
8492
}
8593

8694
impl ProviderConfig {
@@ -102,6 +110,10 @@ impl ProviderConfig {
102110
ProviderConfig::CryptoAuthLib {
103111
ref key_info_manager,
104112
..
113+
} =
114+
ProviderConfig::TrustedService {
115+
ref key_info_manager,
116+
..
105117
} => key_info_manager,
106118
}
107119
}
@@ -112,6 +124,7 @@ impl ProviderConfig {
112124
ProviderConfig::Pkcs11 { .. } => ProviderID::Pkcs11,
113125
ProviderConfig::Tpm { .. } => ProviderID::Tpm,
114126
ProviderConfig::CryptoAuthLib { .. } => ProviderID::CryptoAuthLib,
127+
ProviderConfig::TrustedService { .. } => ProviderID::TrustedService,
115128
}
116129
}
117130
}
+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright 2020 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
use log::info;
4+
use std::ffi::{c_void, CString};
5+
use std::io::{Error, ErrorKind};
6+
use std::ptr::null_mut;
7+
use ts_binding::*;
8+
9+
#[allow(
10+
non_snake_case,
11+
non_camel_case_types,
12+
non_upper_case_globals,
13+
clippy::unseparated_literal_suffix,
14+
// There is an issue where long double become u128 in extern blocks. Check this issue:
15+
// https://github.com/rust-lang/rust-bindgen/issues/1549
16+
improper_ctypes,
17+
missing_debug_implementations,
18+
trivial_casts,
19+
clippy::all,
20+
unused,
21+
unused_qualifications
22+
)]
23+
pub mod ts_binding {
24+
include!(concat!(env!("OUT_DIR"), "/ts_bindings.rs"));
25+
}
26+
27+
#[allow(
28+
non_snake_case,
29+
non_camel_case_types,
30+
non_upper_case_globals,
31+
clippy::unseparated_literal_suffix,
32+
// There is an issue where long double become u128 in extern blocks. Check this issue:
33+
// https://github.com/rust-lang/rust-bindgen/issues/1549
34+
improper_ctypes,
35+
missing_debug_implementations,
36+
trivial_casts,
37+
clippy::all,
38+
unused,
39+
unused_qualifications
40+
)]
41+
mod ts_protobuf {
42+
include!(concat!(env!("OUT_DIR"), "/ts_crypto.rs"));
43+
}
44+
45+
#[derive(Debug)]
46+
pub struct Context {
47+
rpc_caller: *mut rpc_caller,
48+
service_context: *mut service_context,
49+
rpc_session_handle: *mut c_void,
50+
}
51+
52+
impl Context {
53+
pub fn connect() -> anyhow::Result<Self> {
54+
info!("Querying for crypto Trusted Services");
55+
let mut status = 0;
56+
let service_context = unsafe {
57+
service_locator_query(
58+
CString::new("sn:tf.org:crypto:0").unwrap().into_raw(),
59+
&mut status,
60+
)
61+
};
62+
if service_context == null_mut() || status != 0 {
63+
return Err(Error::new(
64+
ErrorKind::Other,
65+
format!(
66+
"Failed to connect to Trusted Service; status code: {}",
67+
status
68+
),
69+
)
70+
.into());
71+
}
72+
73+
info!("Starting crypto Trusted Service context");
74+
let mut rpc_caller = null_mut();
75+
let rpc_session_handle = unsafe { service_context_open(service_context, &mut rpc_caller) };
76+
if rpc_caller == null_mut() || rpc_session_handle == null_mut() {
77+
return Err(
78+
Error::new(ErrorKind::Other, "Failed to start Trusted Service context").into(),
79+
);
80+
}
81+
let ctx = Context {
82+
rpc_caller,
83+
service_context,
84+
rpc_session_handle,
85+
};
86+
87+
Ok(ctx)
88+
}
89+
}
90+
91+
impl Drop for Context {
92+
fn drop(&mut self) {
93+
unsafe { service_context_close(self.service_context, self.rpc_session_handle) };
94+
95+
unsafe { service_locator_relinquish(self.service_context) };
96+
}
97+
}
98+
99+
unsafe impl Sync for Context {}
100+
unsafe impl Send for Context {}

src/providers/trusted_service/mod.rs

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright 2020 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
//! Trusted Service provider
4+
//!
5+
//! This provider is backed by a crypto Trusted Service deployed in TrustZone
6+
use crate::key_info_managers::ManageKeyInfo;
7+
use crate::providers::Provide;
8+
use context::Context;
9+
use derivative::Derivative;
10+
use parsec_interface::operations::list_providers::ProviderInfo;
11+
use parsec_interface::operations::psa_key_attributes::{Attributes, Id};
12+
use parsec_interface::requests::{Opcode, ProviderID, Result};
13+
use psa_crypto::types::key;
14+
use std::collections::HashMap;
15+
use std::collections::HashSet;
16+
use std::sync::{atomic::AtomicU32, Arc, RwLock};
17+
use uuid::Uuid;
18+
19+
mod context;
20+
21+
const SUPPORTED_OPCODES: [Opcode; 0] = [];
22+
23+
/// Trusted Service provider structure
24+
///
25+
/// Currently the provider only supports volatile keys due to limitations in the stack
26+
/// underneath us. Therefore none of the key information is persisted, being kept instead
27+
/// in a map for fast access.
28+
#[derive(Derivative)]
29+
#[derivative(Debug)]
30+
pub struct Provider {
31+
context: Context,
32+
// When calling write on a reference of key_info_store, a type
33+
// std::sync::RwLockWriteGuard<dyn ManageKeyInfo + Send + Sync> is returned. We need to use the
34+
// dereference operator (*) to access the inner type dyn ManageKeyInfo + Send + Sync and then
35+
// reference it to match with the method prototypes.
36+
#[derivative(Debug = "ignore")]
37+
key_info_store: Arc<RwLock<dyn ManageKeyInfo + Send + Sync>>,
38+
key_attr_map: HashMap<String, (Id, Attributes)>,
39+
40+
// Holds the highest ID of all keys (including destroyed keys). New keys will receive an ID of
41+
// id_counter + 1. Once id_counter reaches the highest allowed ID, no more keys can be created.
42+
id_counter: AtomicU32,
43+
}
44+
45+
impl Provider {
46+
/// Creates and initialise a new instance of Provider.
47+
fn new(
48+
key_info_store: Arc<RwLock<dyn ManageKeyInfo + Send + Sync>>,
49+
) -> anyhow::Result<Provider> {
50+
let ts_provider = Provider {
51+
key_info_store,
52+
context: Context::connect()?,
53+
key_attr_map: HashMap::new(),
54+
id_counter: AtomicU32::new(key::PSA_KEY_ID_USER_MIN),
55+
};
56+
Ok(ts_provider)
57+
}
58+
}
59+
60+
impl Provide for Provider {
61+
fn describe(&self) -> Result<(ProviderInfo, HashSet<Opcode>)> {
62+
Ok((ProviderInfo {
63+
// Assigned UUID for this provider: 1c1139dc-ad7c-47dc-ad6b-db6fdb466552
64+
uuid: Uuid::parse_str("1c1139dc-ad7c-47dc-ad6b-db6fdb466552")?,
65+
description: String::from("Provider exposing functionality provided by the Crypto Trusted Service running in a Trusted Execution Environment"),
66+
vendor: String::from("Arm"),
67+
version_maj: 0,
68+
version_min: 1,
69+
version_rev: 0,
70+
id: ProviderID::TrustedService,
71+
}, SUPPORTED_OPCODES.iter().copied().collect()))
72+
}
73+
}
74+
75+
/// Trusted Service provider builder
76+
#[derive(Default, Derivative)]
77+
#[derivative(Debug)]
78+
pub struct ProviderBuilder {
79+
#[derivative(Debug = "ignore")]
80+
key_info_store: Option<Arc<RwLock<dyn ManageKeyInfo + Send + Sync>>>,
81+
}
82+
83+
impl ProviderBuilder {
84+
/// Create a new provider builder
85+
pub fn new() -> ProviderBuilder {
86+
ProviderBuilder {
87+
key_info_store: None,
88+
}
89+
}
90+
91+
/// Add a KeyInfo manager
92+
pub fn with_key_info_store(
93+
mut self,
94+
key_info_store: Arc<RwLock<dyn ManageKeyInfo + Send + Sync>>,
95+
) -> ProviderBuilder {
96+
self.key_info_store = Some(key_info_store);
97+
98+
self
99+
}
100+
101+
/// Build into a TrustedService
102+
pub fn build(self) -> anyhow::Result<Provider> {
103+
Provider::new(self.key_info_store.ok_or_else(|| {
104+
std::io::Error::new(std::io::ErrorKind::InvalidData, "missing key info store")
105+
})?)
106+
}
107+
}

src/utils/service_builder.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,15 @@ use crate::providers::mbed_crypto::ProviderBuilder as MbedCryptoProviderBuilder;
4747
use crate::providers::pkcs11::ProviderBuilder as Pkcs11ProviderBuilder;
4848
#[cfg(feature = "tpm-provider")]
4949
use crate::providers::tpm::ProviderBuilder as TpmProviderBuilder;
50+
#[cfg(feature = "trusted-service-provider")]
51+
use crate::providers::trusted_service::ProviderBuilder as TrustedServiceProviderBuilder;
5052

5153
#[cfg(any(
5254
feature = "mbed-crypto-provider",
5355
feature = "pkcs11-provider",
5456
feature = "tpm-provider",
55-
feature = "cryptoauthlib-provider"
57+
feature = "cryptoauthlib-provider",
58+
feature = "trusted-service-provider"
5659
))]
5760
use log::info;
5861

@@ -284,7 +287,8 @@ fn build_providers(
284287
feature = "mbed-crypto-provider",
285288
feature = "pkcs11-provider",
286289
feature = "tpm-provider",
287-
feature = "cryptoauthlib-provider"
290+
feature = "cryptoauthlib-provider",
291+
feature = "trusted-service-provider"
288292
)),
289293
allow(unused_variables),
290294
allow(clippy::match_single_binding)
@@ -362,11 +366,21 @@ unsafe fn get_provider(
362366
.build()?,
363367
))
364368
}
369+
#[cfg(feature = "trusted-service-provider")]
370+
ProviderConfig::TrustedService { .. } => {
371+
info!("Creating a TPM Provider.");
372+
Ok(Arc::new(
373+
TrustedServiceProviderBuilder::new()
374+
.with_key_info_store(key_info_manager)
375+
.build()?,
376+
))
377+
}
365378
#[cfg(not(all(
366379
feature = "mbed-crypto-provider",
367380
feature = "pkcs11-provider",
368381
feature = "tpm-provider",
369-
feature = "cryptoauthlib-provider"
382+
feature = "cryptoauthlib-provider",
383+
feature = "trusted-service-provider"
370384
)))]
371385
_ => {
372386
error!(

0 commit comments

Comments
 (0)