Skip to content

Commit c17f874

Browse files
authored
Merge pull request #286 from ionut-arm/ts-sign-verify
Add asymmetric sign and verify to TS provider
2 parents eadc312 + 7cf3f1b commit c17f874

File tree

6 files changed

+223
-36
lines changed

6 files changed

+223
-36
lines changed

build.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ use std::io::{Error, ErrorKind, Result};
55
use std::path::{Path, PathBuf};
66

77
fn generate_ts_bindings(ts_include_dir: String) -> Result<()> {
8-
let header = ts_include_dir.clone() + "/service/locator/service_locator.h";
8+
let header = ts_include_dir.clone() + "/service/locator/interface/service_locator.h";
99

1010
println!("cargo:rerun-if-changed={}", header);
1111

1212
let bindings = bindgen::Builder::default()
13-
.clang_arg(format!("-I{}", ts_include_dir))
13+
.clang_arg(format!("-I{}", ts_include_dir + "/rpc/common/interface"))
1414
.rustfmt_bindings(true)
1515
.header(header)
1616
.generate_comments(false)
@@ -29,7 +29,7 @@ fn generate_ts_bindings(ts_include_dir: String) -> Result<()> {
2929
println!("cargo:rustc-link-lib=dylib=c++");
3030

3131
println!("cargo:rustc-link-search=native=/usr/local/lib");
32-
println!("cargo:rustc-link-lib=static=ts-lib");
32+
println!("cargo:rustc-link-lib=dylib=ts");
3333
// TODO: Remove once we can use the full TS stack and this isn't needed
3434
println!("cargo:rustc-link-lib=static=mbedcrypto");
3535
println!("cargo:rustc-link-lib=static=protobuf-nanopb");
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2020 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
use super::Provider;
4+
use crate::authenticators::ApplicationName;
5+
use crate::key_info_managers::KeyTriple;
6+
use crate::providers::mbed_crypto::key_management;
7+
use parsec_interface::operations::{psa_sign_hash, psa_verify_hash};
8+
use parsec_interface::requests::{ProviderID, Result};
9+
10+
impl Provider {
11+
pub(super) fn psa_sign_hash_internal(
12+
&self,
13+
app_name: ApplicationName,
14+
op: psa_sign_hash::Operation,
15+
) -> Result<psa_sign_hash::Result> {
16+
let key_triple = KeyTriple::new(app_name, ProviderID::TrustedService, op.key_name.clone());
17+
let store_handle = self.key_info_store.read().expect("Key store lock poisoned");
18+
let key_id = key_management::get_key_id(&key_triple, &*store_handle)?;
19+
20+
Ok(psa_sign_hash::Result {
21+
signature: self
22+
.context
23+
.asym_sign(key_id, op.hash.to_vec(), op.alg)?
24+
.into(),
25+
})
26+
}
27+
28+
pub(super) fn psa_verify_hash_internal(
29+
&self,
30+
app_name: ApplicationName,
31+
op: psa_verify_hash::Operation,
32+
) -> Result<psa_verify_hash::Result> {
33+
let key_triple = KeyTriple::new(app_name, ProviderID::TrustedService, op.key_name.clone());
34+
let store_handle = self.key_info_store.read().expect("Key store lock poisoned");
35+
let key_id = key_management::get_key_id(&key_triple, &*store_handle)?;
36+
37+
self.context
38+
.asym_verify(key_id, op.hash.to_vec(), op.signature.to_vec(), op.alg)?;
39+
40+
Ok(psa_verify_hash::Result {})
41+
}
42+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2020 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
use super::ts_protobuf::{SignHashIn, SignHashOut, VerifyHashIn};
4+
use super::Context;
5+
use log::info;
6+
use parsec_interface::operations::psa_algorithm::AsymmetricSignature;
7+
use parsec_interface::requests::ResponseStatus;
8+
use std::convert::TryInto;
9+
10+
impl Context {
11+
pub fn asym_sign(
12+
&self,
13+
key_id: u32,
14+
hash: Vec<u8>,
15+
algorithm: AsymmetricSignature,
16+
) -> Result<Vec<u8>, ResponseStatus> {
17+
info!("Handling GenerateKey request");
18+
let proto_req = SignHashIn {
19+
handle: 0,
20+
hash,
21+
alg: algorithm.try_into()?,
22+
};
23+
let SignHashOut { signature } = self.send_request_with_key(proto_req, key_id)?;
24+
25+
Ok(signature)
26+
}
27+
28+
pub fn asym_verify(
29+
&self,
30+
key_id: u32,
31+
hash: Vec<u8>,
32+
signature: Vec<u8>,
33+
algorithm: AsymmetricSignature,
34+
) -> Result<(), ResponseStatus> {
35+
info!("Handling GenerateKey request");
36+
let proto_req = VerifyHashIn {
37+
handle: 0,
38+
hash,
39+
signature,
40+
alg: algorithm.try_into()?,
41+
};
42+
self.send_request_with_key(proto_req, key_id)?;
43+
44+
Ok(())
45+
}
46+
}

src/providers/trusted_service/context/key_management.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
use super::ts_protobuf::{
44
CloseKeyIn, DestroyKeyIn, DestroyKeyOut, GenerateKeyIn, GenerateKeyOut, KeyAttributes,
5-
KeyLifetime, KeyPolicy, Opcode, OpenKeyIn, OpenKeyOut,
5+
KeyLifetime, KeyPolicy, OpenKeyIn, OpenKeyOut,
66
};
77
use super::Context;
88
use log::info;
@@ -26,37 +26,34 @@ impl Context {
2626
}),
2727
}),
2828
};
29-
let GenerateKeyOut { handle } =
30-
self.send_request(&proto_req, Opcode::GenerateKey, self.rpc_caller)?;
29+
let GenerateKeyOut { handle } = self.send_request(&proto_req)?;
3130

3231
let proto_req = CloseKeyIn { handle };
33-
self.send_request(&proto_req, Opcode::CloseKey, self.rpc_caller)?;
32+
self.send_request(&proto_req)?;
3433

3534
Ok(())
3635
}
3736

38-
pub fn destroy_key(&self, id: u32) -> Result<(), ResponseStatus> {
37+
pub fn destroy_key(&self, key_id: u32) -> Result<(), ResponseStatus> {
3938
info!("Handling DestroyKey request");
40-
if !self.check_key_exists(id)? {
39+
if !self.check_key_exists(key_id)? {
4140
return Err(ResponseStatus::PsaErrorDoesNotExist);
4241
}
43-
let proto_req = OpenKeyIn { id };
44-
let OpenKeyOut { handle } =
45-
self.send_request(&proto_req, Opcode::OpenKey, self.rpc_caller)?;
42+
let proto_req = OpenKeyIn { id: key_id };
43+
let OpenKeyOut { handle } = self.send_request(&proto_req)?;
4644

4745
let proto_req = DestroyKeyIn { handle };
48-
let _proto_resp: DestroyKeyOut =
49-
self.send_request(&proto_req, Opcode::DestroyKey, self.rpc_caller)?;
46+
let _proto_resp: DestroyKeyOut = self.send_request(&proto_req)?;
5047
Ok(())
5148
}
5249

53-
pub fn check_key_exists(&self, id: u32) -> Result<bool, Error> {
50+
pub fn check_key_exists(&self, key_id: u32) -> Result<bool, Error> {
5451
info!("Handling CheckKey request");
55-
let proto_req = OpenKeyIn { id };
56-
match self.send_request(&proto_req, Opcode::OpenKey, self.rpc_caller) {
52+
let proto_req = OpenKeyIn { id: key_id };
53+
match self.send_request(&proto_req) {
5754
Ok(OpenKeyOut { handle }) => {
5855
let proto_req = CloseKeyIn { handle };
59-
self.send_request(&proto_req, Opcode::CloseKey, self.rpc_caller)?;
56+
self.send_request(&proto_req)?;
6057
Ok(true)
6158
}
6259
Err(e) => {

src/providers/trusted_service/context/mod.rs

Lines changed: 98 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::ptr::null_mut;
1010
use std::slice;
1111
use std::sync::Mutex;
1212
use ts_binding::*;
13-
use ts_protobuf::Opcode;
13+
use ts_protobuf::{CloseKeyIn, GetOpcode, OpenKeyIn, OpenKeyOut, SetHandle};
1414

1515
#[allow(
1616
non_snake_case,
@@ -30,6 +30,7 @@ pub mod ts_binding {
3030
include!(concat!(env!("OUT_DIR"), "/ts_bindings.rs"));
3131
}
3232

33+
mod asym_sign;
3334
mod key_management;
3435

3536
#[allow(
@@ -48,6 +49,59 @@ mod key_management;
4849
)]
4950
mod ts_protobuf {
5051
include!(concat!(env!("OUT_DIR"), "/ts_crypto.rs"));
52+
53+
pub trait GetOpcode {
54+
fn opcode(&self) -> Opcode;
55+
}
56+
57+
macro_rules! opcode_impl {
58+
($type:ty, $opcode:ident) => {
59+
impl GetOpcode for $type {
60+
fn opcode(&self) -> Opcode {
61+
Opcode::$opcode
62+
}
63+
}
64+
};
65+
66+
($type_in:ty, $type_out:ty, $opcode:ident) => {
67+
impl GetOpcode for $type_in {
68+
fn opcode(&self) -> Opcode {
69+
Opcode::$opcode
70+
}
71+
}
72+
73+
impl GetOpcode for $type_out {
74+
fn opcode(&self) -> Opcode {
75+
Opcode::$opcode
76+
}
77+
}
78+
};
79+
}
80+
81+
opcode_impl!(OpenKeyIn, OpenKeyOut, OpenKey);
82+
opcode_impl!(CloseKeyIn, CloseKey);
83+
opcode_impl!(GenerateKeyIn, GenerateKeyOut, GenerateKey);
84+
opcode_impl!(DestroyKeyIn, DestroyKeyOut, DestroyKey);
85+
opcode_impl!(SignHashIn, SignHashOut, SignHash);
86+
opcode_impl!(VerifyHashIn, VerifyHashOut, VerifyHash);
87+
88+
pub trait SetHandle {
89+
fn set_handle(&mut self, handle: u32);
90+
}
91+
92+
macro_rules! set_handle_impl {
93+
($type:ty) => {
94+
impl SetHandle for $type {
95+
fn set_handle(&mut self, handle: u32) {
96+
self.handle = handle;
97+
}
98+
}
99+
};
100+
}
101+
102+
set_handle_impl!(DestroyKeyIn);
103+
set_handle_impl!(SignHashIn);
104+
set_handle_impl!(VerifyHashIn);
51105
}
52106

53107
// TODO:
@@ -65,15 +119,27 @@ pub struct Context {
65119

66120
impl Context {
67121
pub fn connect() -> anyhow::Result<Self> {
68-
info!("Querying for crypto Trusted Services");
122+
// Initialise service locator. Can be called multiple times,
123+
// but *must* be called at least once.
124+
unsafe { service_locator_init() };
125+
126+
info!("Obtaining a crypto Trusted Service context.");
69127
let mut status = 0;
70128
let service_context = unsafe {
71129
service_locator_query(
72-
CString::new("sn:tf.org:crypto:0").unwrap().into_raw(),
130+
CString::new("sn:trustedfirmware.org:crypto:0")
131+
.unwrap()
132+
.into_raw(),
73133
&mut status,
74134
)
75135
};
76-
if service_context == null_mut() || status != 0 {
136+
if service_context == null_mut() {
137+
return Err(Error::new(
138+
ErrorKind::Other,
139+
"Failed to obtain a Trusted Service context",
140+
)
141+
.into());
142+
} else if status != 0 {
77143
return Err(Error::new(
78144
ErrorKind::Other,
79145
format!(
@@ -104,15 +170,14 @@ impl Context {
104170

105171
fn send_request<T: Message + Default>(
106172
&self,
107-
req: &impl Message,
108-
opcode: Opcode,
109-
rpc_cl: *mut rpc_caller,
173+
req: &(impl Message + GetOpcode),
110174
) -> Result<T, PsaError> {
111175
let _mutex_guard = self.call_mutex.try_lock().expect("Call mutex poisoned");
112176
info!("Beginning call to Trusted Service");
113177

114178
let mut buf_out = null_mut();
115-
let call_handle = unsafe { rpc_caller_begin(rpc_cl, &mut buf_out, req.encoded_len()) };
179+
let call_handle =
180+
unsafe { rpc_caller_begin(self.rpc_caller, &mut buf_out, req.encoded_len()) };
116181
if call_handle == null_mut() {
117182
error!("Call handle was null");
118183
return Err(PsaError::CommunicationFailure);
@@ -122,7 +187,7 @@ impl Context {
122187
}
123188
let mut buf_out = unsafe { slice::from_raw_parts_mut(buf_out, req.encoded_len()) };
124189
req.encode(&mut buf_out).map_err(|e| {
125-
unsafe { rpc_caller_end(rpc_cl, call_handle) };
190+
unsafe { rpc_caller_end(self.rpc_caller, call_handle) };
126191
format_error!("Failed to serialize Protobuf request", e);
127192
PsaError::CommunicationFailure
128193
})?;
@@ -134,39 +199,55 @@ impl Context {
134199
let mut resp_buf_size = 0;
135200
let status = unsafe {
136201
rpc_caller_invoke(
137-
rpc_cl,
202+
self.rpc_caller,
138203
call_handle,
139-
i32::from(opcode).try_into().unwrap(),
204+
i32::from(req.opcode()).try_into().unwrap(),
140205
&mut opstatus,
141206
&mut resp_buf,
142207
&mut resp_buf_size,
143208
)
144209
};
145210
if status != 0 || opstatus != 0 {
146-
unsafe { rpc_caller_end(rpc_cl, call_handle) };
211+
unsafe { rpc_caller_end(self.rpc_caller, call_handle) };
147212
error!(
148213
"Error on call invocation: status = {}, opstatus = {}",
149-
status, opstatus as i32
214+
status, opstatus
150215
);
151-
Status::from(opstatus as i32).to_result()?;
216+
Status::from(opstatus).to_result()?;
152217
}
153218
let resp_buf = unsafe { slice::from_raw_parts_mut(resp_buf, resp_buf_size) };
154219
resp.merge(&*resp_buf).map_err(|e| {
155-
unsafe { rpc_caller_end(rpc_cl, call_handle) };
220+
unsafe { rpc_caller_end(self.rpc_caller, call_handle) };
156221
format_error!("Failed to serialize Protobuf request", e);
157222
PsaError::CommunicationFailure
158223
})?;
159-
unsafe { rpc_caller_end(rpc_cl, call_handle) };
224+
unsafe { rpc_caller_end(self.rpc_caller, call_handle) };
160225

161226
Ok(resp)
162227
}
228+
229+
fn send_request_with_key<T: Message + Default>(
230+
&self,
231+
mut req: impl Message + GetOpcode + SetHandle,
232+
key_id: u32,
233+
) -> Result<T, PsaError> {
234+
let proto_req = OpenKeyIn { id: key_id };
235+
let OpenKeyOut { handle } = self.send_request(&proto_req)?;
236+
req.set_handle(handle);
237+
let res = self.send_request(&req);
238+
let proto_req = CloseKeyIn { handle };
239+
let res_close = self.send_request(&proto_req);
240+
let res = res?;
241+
res_close?;
242+
Ok(res)
243+
}
163244
}
164245

165246
impl Drop for Context {
166247
fn drop(&mut self) {
167248
unsafe { service_context_close(self.service_context, self.rpc_session_handle) };
168249

169-
unsafe { service_locator_relinquish(self.service_context) };
250+
unsafe { service_context_relinquish(self.service_context) };
170251
}
171252
}
172253

0 commit comments

Comments
 (0)