use core::marker::PhantomData;
use interchange::Requester;
use crate::api::*;
use crate::error::*;
use crate::pipe::TrussedInterchange;
use crate::types::*;
pub use crate::platform::Syscall;
pub mod mechanisms;
pub use mechanisms::*;
#[derive(Copy, Clone, Debug)]
pub enum ClientError {
Full,
Pending,
DataTooLarge,
}
pub type ClientResult<'c, T, C> = core::result::Result<FutureResult<'c, T, C>, ClientError>;
pub trait Client: CertificateClient + CryptoClient + CounterClient + FilesystemClient + ManagementClient + UiClient {}
impl<S: Syscall> Client for ClientImplementation<S> {}
pub trait PollClient {
fn request<T: From<crate::api::Reply>>(&mut self, req: impl Into<Request>) -> ClientResult<'_, T, Self>;
fn poll(&mut self) -> core::task::Poll<core::result::Result<Reply, Error>>;
fn syscall(&mut self);
}
pub struct FutureResult<'c, T, C: ?Sized>
where C: PollClient
{
client: &'c mut C,
__: PhantomData<T>,
}
impl<'c,T, C> FutureResult<'c, T, C>
where
T: From<crate::api::Reply>,
C: PollClient,
{
pub fn new(client: &'c mut C) -> Self {
Self { client, __: PhantomData}
}
pub fn poll(&mut self)
-> core::task::Poll<core::result::Result<T, Error>>
{
use core::task::Poll::{Pending, Ready};
match self.client.poll() {
Ready(Ok(reply)) => Ready(Ok(T::from(reply))),
Ready(Err(error)) => Ready(Err(error)),
Pending => Pending
}
}
}
pub struct ClientImplementation<S> {
syscall: S,
pub(crate) interchange: Requester<TrussedInterchange>,
pending: Option<u8>,
}
impl<S> ClientImplementation<S>
where S: Syscall
{
pub fn new(interchange: Requester<TrussedInterchange>, syscall: S) -> Self {
Self { interchange, pending: None, syscall }
}
}
impl<S> PollClient for ClientImplementation<S>
where S: Syscall {
fn poll(&mut self)
-> core::task::Poll<core::result::Result<Reply, Error>>
{
match self.interchange.take_response() {
Some(reply) => {
match reply {
Ok(reply) => {
if Some(u8::from(&reply)) == self.pending {
self.pending = None;
core::task::Poll::Ready(Ok(reply))
} else {
info!("got: {:?}, expected: {:?}", Some(u8::from(&reply)), self.pending);
core::task::Poll::Ready(Err(Error::InternalError))
}
}
Err(error) => {
self.pending = None;
core::task::Poll::Ready(Err(error))
}
}
},
None => core::task::Poll::Pending
}
}
fn request<T: From<crate::api::Reply>>(&mut self, req: impl Into<Request>)
-> ClientResult<'_, T, Self>
{
if self.pending.is_some() {
return Err(ClientError::Pending);
}
let request = req.into();
self.pending = Some(u8::from(&request));
self.interchange.request(&request).map_err(drop).unwrap();
Ok(FutureResult::new(self))
}
fn syscall(&mut self) {
self.syscall.syscall()
}
}
impl<S: Syscall> CertificateClient for ClientImplementation<S> {}
impl<S: Syscall> CryptoClient for ClientImplementation<S> {}
impl<S: Syscall> CounterClient for ClientImplementation<S> {}
impl<S: Syscall> FilesystemClient for ClientImplementation<S> {}
impl<S: Syscall> ManagementClient for ClientImplementation<S> {}
impl<S: Syscall> UiClient for ClientImplementation<S> {}
pub trait CertificateClient: PollClient {
fn delete_certificate(&mut self, id: CertId)
-> ClientResult<'_, reply::DeleteCertificate, Self>
{
let r = self.request(request::DeleteCertificate { id })?;
r.client.syscall();
Ok(r)
}
fn read_certificate(&mut self, id: CertId)
-> ClientResult<'_, reply::ReadCertificate, Self>
{
let r = self.request(request::ReadCertificate { id })?;
r.client.syscall();
Ok(r)
}
fn write_certificate(&mut self, location: Location, der: &[u8])
-> ClientResult<'_, reply::WriteCertificate, Self>
{
let der = Message::from_slice(der).map_err(|_| ClientError::DataTooLarge)?;
let r = self.request(request::WriteCertificate { location, der })?;
r.client.syscall();
Ok(r)
}
}
pub trait CryptoClient: PollClient {
fn agree(
&mut self, mechanism: Mechanism,
private_key: KeyId, public_key: KeyId,
attributes: StorageAttributes,
)
-> ClientResult<'_, reply::Agree, Self>
{
let r = self.request(request::Agree {
mechanism,
private_key,
public_key,
attributes,
})?;
r.client.syscall();
Ok(r)
}
fn attest(&mut self, signing_mechanism: Mechanism, private_key: KeyId)
-> ClientResult<'_, reply::Attest, Self>
{
let r = self.request(request::Attest {
signing_mechanism,
private_key,
})?;
r.client.syscall();
Ok(r)
}
fn decrypt<'c>(&'c mut self, mechanism: Mechanism, key: KeyId,
message: &[u8], associated_data: &[u8],
nonce: &[u8], tag: &[u8],
)
-> ClientResult<'c, reply::Decrypt, Self>
{
let message = Message::from_slice(message).map_err(|_| ClientError::DataTooLarge)?;
let associated_data = Message::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?;
let nonce = ShortData::from_slice(nonce).map_err(|_| ClientError::DataTooLarge)?;
let tag = ShortData::from_slice(tag).map_err(|_| ClientError::DataTooLarge)?;
let r = self.request(request::Decrypt { mechanism, key, message, associated_data, nonce, tag })?;
r.client.syscall();
Ok(r)
}
fn delete(&mut self, key: KeyId)
-> ClientResult<'_, reply::Delete, Self>
{
let r = self.request(request::Delete {
key,
})?;
r.client.syscall();
Ok(r)
}
fn delete_all(&mut self, location: Location)
-> ClientResult<'_, reply::DeleteAllKeys, Self>
{
let r = self.request(request::DeleteAllKeys { location })?;
r.client.syscall();
Ok(r)
}
fn derive_key(&mut self, mechanism: Mechanism, base_key: KeyId, additional_data: Option<MediumData>, attributes: StorageAttributes)
-> ClientResult<'_, reply::DeriveKey, Self>
{
let r = self.request(request::DeriveKey {
mechanism,
base_key,
additional_data,
attributes,
})?;
r.client.syscall();
Ok(r)
}
fn deserialize_key<'c>(&'c mut self, mechanism: Mechanism, serialized_key: &[u8],
format: KeySerialization, attributes: StorageAttributes)
-> ClientResult<'c, reply::DeserializeKey, Self>
{
let serialized_key = Message::from_slice(serialized_key).map_err(|_| ClientError::DataTooLarge)?;
let r = self.request(request::DeserializeKey {
mechanism, serialized_key, format, attributes
} )?;
r.client.syscall();
Ok(r)
}
fn encrypt<'c>(&'c mut self, mechanism: Mechanism, key: KeyId,
message: &[u8], associated_data: &[u8], nonce: Option<ShortData>)
-> ClientResult<'c, reply::Encrypt, Self>
{
let message = Message::from_slice(message).map_err(|_| ClientError::DataTooLarge)?;
let associated_data = ShortData::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?;
let r = self.request(request::Encrypt { mechanism, key, message, associated_data, nonce })?;
r.client.syscall();
Ok(r)
}
fn exists(&mut self, mechanism: Mechanism, key: KeyId)
-> ClientResult<'_, reply::Exists, Self>
{
let r = self.request(request::Exists {
key,
mechanism,
})?;
r.client.syscall();
Ok(r)
}
fn generate_key(&mut self, mechanism: Mechanism, attributes: StorageAttributes)
-> ClientResult<'_, reply::GenerateKey, Self>
{
let r = self.request(request::GenerateKey {
mechanism,
attributes,
})?;
r.client.syscall();
Ok(r)
}
fn generate_secret_key(&mut self, size: usize, persistence: Location)
-> ClientResult<'_, reply::GenerateSecretKey, Self>
{
let r = self.request(request::GenerateSecretKey {
size,
attributes: StorageAttributes::new().set_persistence(persistence),
})?;
r.client.syscall();
Ok(r)
}
fn hash(&mut self, mechanism: Mechanism, message: Message)
-> ClientResult<'_, reply::Hash, Self>
{
let r = self.request(request::Hash { mechanism, message } )?;
r.client.syscall();
Ok(r)
}
fn random_bytes(&mut self, count: usize)
-> ClientResult<'_, reply::RandomBytes, Self>
{
let r = self.request(request::RandomBytes { count } )?;
r.client.syscall();
Ok(r)
}
fn serialize_key(&mut self, mechanism: Mechanism, key: KeyId, format: KeySerialization)
-> ClientResult<'_, reply::SerializeKey, Self>
{
let r = self.request(request::SerializeKey {
key,
mechanism,
format,
})?;
r.client.syscall();
Ok(r)
}
fn sign<'c>(
&'c mut self,
mechanism: Mechanism,
key: KeyId,
data: &[u8],
format: SignatureSerialization,
)
-> ClientResult<'c, reply::Sign, Self>
{
let r = self.request(request::Sign {
key,
mechanism,
message: Bytes::from_slice(data).map_err(|_| ClientError::DataTooLarge)?,
format,
})?;
r.client.syscall();
Ok(r)
}
fn verify<'c>(
&'c mut self,
mechanism: Mechanism,
key: KeyId,
message: &[u8],
signature: &[u8],
format: SignatureSerialization,
)
-> ClientResult<'c, reply::Verify, Self>
{
let r = self.request(request::Verify {
mechanism,
key,
message: Message::from_slice(&message).expect("all good"),
signature: Signature::from_slice(&signature).expect("all good"),
format,
})?;
r.client.syscall();
Ok(r)
}
#[deprecated]
fn unsafe_inject_key(&mut self, mechanism: Mechanism, raw_key: &[u8], persistence: Location)
-> ClientResult<'_, reply::UnsafeInjectKey, Self>
{
let r = self.request(request::UnsafeInjectKey {
mechanism,
raw_key: ShortData::from_slice(raw_key).unwrap(),
attributes: StorageAttributes::new().set_persistence(persistence),
})?;
r.client.syscall();
Ok(r)
}
fn unsafe_inject_shared_key(&mut self, raw_key: &[u8], location: Location)
-> ClientResult<'_, reply::UnsafeInjectSharedKey, Self>
{
let r = self.request(request::UnsafeInjectSharedKey {
raw_key: ShortData::from_slice(raw_key).unwrap(),
location,
})?;
r.client.syscall();
Ok(r)
}
fn unwrap_key<'c>(&'c mut self, mechanism: Mechanism, wrapping_key: KeyId, wrapped_key: Message,
associated_data: &[u8], attributes: StorageAttributes)
-> ClientResult<'c, reply::UnwrapKey, Self>
{
let associated_data = Message::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?;
let r = self.request(request::UnwrapKey {
mechanism,
wrapping_key,
wrapped_key,
associated_data,
attributes
})?;
r.client.syscall();
Ok(r)
}
fn wrap_key(&mut self, mechanism: Mechanism, wrapping_key: KeyId, key: KeyId,
associated_data: &[u8])
-> ClientResult<'_, reply::WrapKey, Self>
{
let associated_data = Message::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?;
let r = self.request(request::WrapKey { mechanism, wrapping_key, key, associated_data })?;
r.client.syscall();
Ok(r)
}
}
pub trait CounterClient: PollClient {
fn create_counter(&mut self, location: Location)
-> ClientResult<'_, reply::CreateCounter, Self>
{
let r = self.request(request::CreateCounter { location })?;
r.client.syscall();
Ok(r)
}
fn increment_counter(&mut self, id: CounterId)
-> ClientResult<'_, reply::IncrementCounter, Self>
{
let r = self.request(request::IncrementCounter { id })?;
r.client.syscall();
Ok(r)
}
}
pub trait FilesystemClient: PollClient {
fn debug_dump_store(&mut self)
-> ClientResult<'_, reply::DebugDumpStore, Self>
{
let r = self.request(request::DebugDumpStore {})?;
r.client.syscall();
Ok(r)
}
fn read_dir_first(
&mut self,
location: Location,
dir: PathBuf,
not_before_filename: Option<PathBuf>,
)
-> ClientResult<'_, reply::ReadDirFirst, Self>
{
let r = self.request(request::ReadDirFirst { location, dir, not_before_filename } )?;
r.client.syscall();
Ok(r)
}
fn read_dir_next(
&mut self,
)
-> ClientResult<'_, reply::ReadDirNext, Self>
{
let r = self.request(request::ReadDirNext {} )?;
r.client.syscall();
Ok(r)
}
fn read_dir_files_first(
&mut self,
location: Location,
dir: PathBuf,
user_attribute: Option<UserAttribute>,
)
-> ClientResult<'_, reply::ReadDirFilesFirst, Self>
{
let r = self.request(request::ReadDirFilesFirst { dir, location, user_attribute } )?;
r.client.syscall();
Ok(r)
}
fn read_dir_files_next(&mut self)
-> ClientResult<'_, reply::ReadDirFilesNext, Self>
{
let r = self.request(request::ReadDirFilesNext {} )?;
r.client.syscall();
Ok(r)
}
fn remove_dir(&mut self, location: Location, path: PathBuf)
-> ClientResult<'_, reply::RemoveDirAll, Self>
{
let r = self.request(request::RemoveDir { location, path } )?;
r.client.syscall();
Ok(r)
}
fn remove_dir_all(&mut self, location: Location, path: PathBuf)
-> ClientResult<'_, reply::RemoveDirAll, Self>
{
let r = self.request(request::RemoveDirAll { location, path } )?;
r.client.syscall();
Ok(r)
}
fn remove_file(&mut self, location: Location, path: PathBuf)
-> ClientResult<'_, reply::RemoveFile, Self>
{
let r = self.request(request::RemoveFile { location, path } )?;
r.client.syscall();
Ok(r)
}
fn read_file(&mut self, location: Location, path: PathBuf)
-> ClientResult<'_, reply::ReadFile, Self>
{
let r = self.request(request::ReadFile { location, path } )?;
r.client.syscall();
Ok(r)
}
fn locate_file(&mut self, location: Location, dir: Option<PathBuf>, filename: PathBuf)
-> ClientResult<'_, reply::LocateFile, Self>
{
let r = self.request(request::LocateFile { location, dir, filename } )?;
r.client.syscall();
Ok(r)
}
fn write_file(
&mut self,
location: Location,
path: PathBuf,
data: Message,
user_attribute: Option<UserAttribute>,
)
-> ClientResult<'_, reply::WriteFile, Self>
{
let r = self.request(request::WriteFile {
location, path, data,
user_attribute,
} )?;
r.client.syscall();
Ok(r)
}
}
pub trait ManagementClient: PollClient {
fn reboot(&mut self, to: reboot::To)
-> ClientResult<'_, reply::Reboot, Self>
{
let r = self.request(request::Reboot { to })?;
r.client.syscall();
Ok(r)
}
fn uptime(&mut self)
-> ClientResult<'_, reply::Uptime, Self>
{
let r = self.request(request::Uptime {})?;
r.client.syscall();
Ok(r)
}
}
pub trait UiClient: PollClient {
fn confirm_user_present(&mut self, timeout_milliseconds: u32)
-> ClientResult<'_, reply::RequestUserConsent, Self>
{
let r = self.request(request::RequestUserConsent {
level: consent::Level::Normal,
timeout_milliseconds,
} )?;
r.client.syscall();
Ok(r)
}
fn wink(&mut self, duration: core::time::Duration) -> ClientResult<'_, reply::Wink, Self> {
let r = self.request(request::Wink { duration } )?;
r.client.syscall();
Ok(r)
}
}
#[macro_export]
macro_rules! block {
($future_result:expr) => {{
let mut future_result = $future_result;
loop {
match future_result.poll() {
core::task::Poll::Ready(result) => { break result; },
core::task::Poll::Pending => {},
}
}
}}
}
#[macro_export]
macro_rules! syscall {
($pre_future_result:expr) => {{
let mut future_result = $pre_future_result.expect("no client error");
loop {
match future_result.poll() {
core::task::Poll::Ready(result) => { break result.expect("no errors"); },
core::task::Poll::Pending => {},
}
}
}}
}
#[macro_export]
macro_rules! try_syscall {
($pre_future_result:expr) => {{
let mut future_result = $pre_future_result.expect("no client error");
loop {
match future_result.poll() {
core::task::Poll::Ready(result) => { break result; },
core::task::Poll::Pending => {},
}
}
}}
}