diff --git a/Cargo.lock b/Cargo.lock index df95a00..612a5ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1202,7 +1202,7 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "trussed" version = "0.1.0" -source = "git+https://github.com/trussed-dev/trussed?rev=84219ec991a7ea942faabe8fd2b862f827367762#84219ec991a7ea942faabe8fd2b862f827367762" +source = "git+https://github.com/trussed-dev/trussed?rev=51477a4c5d22b7fbfe9d5fed137701764b2c86ec#51477a4c5d22b7fbfe9d5fed137701764b2c86ec" dependencies = [ "aes", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index 325bb54..e79d212 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,4 +40,4 @@ name = "fido" required-features = ["ctaphid"] [patch.crates-io] -trussed = { git = "https://github.com/trussed-dev/trussed", rev = "84219ec991a7ea942faabe8fd2b862f827367762" } +trussed = { git = "https://github.com/trussed-dev/trussed", rev = "51477a4c5d22b7fbfe9d5fed137701764b2c86ec" } diff --git a/examples/fido.rs b/examples/fido.rs index e5704fb..15d1367 100644 --- a/examples/fido.rs +++ b/examples/fido.rs @@ -7,7 +7,8 @@ use clap::Parser; use clap_num::maybe_hex; use log::info; use trussed::platform::{consent, reboot, ui}; -use trussed::{virt, Client, Platform}; +use trussed::{backend::Dispatch, virt, Client, Platform}; +use trussed_usbip::ClientBuilder; use fido_authenticator::TrussedRequirements; use usbd_ctaphid::constants::MESSAGE_SIZE; @@ -119,17 +120,19 @@ struct Apps { admin: admin_app::App, } -impl trussed_usbip::Apps for Apps { - fn new(make_client: impl Fn(&str) -> C, _data: ()) -> Self { +impl trussed_usbip::Apps for Apps { + type Data = (); + + fn new>(builder: &B, _data: ()) -> Self { let fido = fido_authenticator::Authenticator::new( - make_client("fido"), + builder.build("fido", &[]), fido_authenticator::Conforming {}, fido_authenticator::Config { max_msg_size: MESSAGE_SIZE, skip_up_timeout: None, }, ); - let admin = admin_app::App::new(make_client("admin"), [0; 16], 0); + let admin = admin_app::App::new(builder.build("admin", &[]), [0; 16], 0); Self { fido, admin } } @@ -164,7 +167,7 @@ fn main() { }; log::info!("Initializing Trussed"); - trussed_usbip::Runner::new(store, options) + trussed_usbip::Builder::new(store, options) .init_platform(move |platform| { let ui: Box = Box::new(UserInterface::new()); @@ -177,7 +180,8 @@ fn main() { store_file(platform, fido_cert, "fido/x5c/00"); } }) - .exec::, _, _>(|_| ()); + .build::>() + .exec(|_| ()); } fn store_file(platform: &impl Platform, host_file: &Path, device_file: &str) { diff --git a/src/lib.rs b/src/lib.rs index a21dd20..3afddbb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,11 +3,13 @@ mod ccid; #[cfg(feature = "ctaphid")] mod ctaphid; -use std::{cell::RefCell, rc::Rc, thread, time::Duration}; +use std::{cell::RefCell, marker::PhantomData, rc::Rc, thread, time::Duration}; use trussed::{ + backend::{BackendId, CoreOnly, Dispatch}, + client, virt::{self, Platform, StoreProvider}, - ClientImplementation, Service, + ClientImplementation, }; use usb_device::{ bus::{UsbBus, UsbBusAllocator}, @@ -15,7 +17,9 @@ use usb_device::{ }; use usbip_device::UsbIpBus; -pub type Client = ClientImplementation>>; +pub type Client = ClientImplementation, D>; + +pub type InitPlatform = Box)>; pub struct Options { pub manufacturer: Option, @@ -31,8 +35,10 @@ impl Options { } } -pub trait Apps { - fn new(make_client: impl Fn(&str) -> C, data: D) -> Self; +pub trait Apps { + type Data; + + fn new>(builder: &B, data: Self::Data) -> Self; #[cfg(feature = "ctaphid")] fn with_ctaphid_apps( @@ -47,31 +53,25 @@ pub trait Apps { ) -> T; } -pub struct Runner { - store: S, - options: Options, - init_platform: Option)>>, +pub trait ClientBuilder { + fn build(&self, id: &str, backends: &'static [BackendId]) -> C; } -impl Runner { - pub fn new(store: S, options: Options) -> Self { - Self { - store, - options, - init_platform: Default::default(), - } +pub struct Runner { + store: S, + options: Options, + dispatch: D, + init_platform: Option>, + _marker: PhantomData, +} + +impl, D>> Runner { + pub fn builder(store: S, options: Options) -> Builder { + Builder::new(store, options) } - pub fn init_platform(&mut self, f: F) -> &mut Self - where - F: Fn(&mut Platform) + 'static, - { - self.init_platform = Some(Box::new(f)); - self - } - - pub fn exec, D>, D, F: Fn(&mut Platform) -> D>(&self, make_data: F) { - virt::with_platform(self.store.clone(), |mut platform| { + pub fn exec) -> A::Data>(self, make_data: F) { + virt::with_platform(self.store, |mut platform| { if let Some(init_platform) = &self.init_platform { init_platform(&mut platform); } @@ -87,17 +87,8 @@ impl Runner { let (mut ccid, mut apdu_dispatch) = ccid::setup(&bus_allocator); let mut usb_device = build_device(&bus_allocator, &self.options); - let service = Rc::new(RefCell::new(Service::new(platform))); - let syscall = Syscall::from(service.clone()); - let mut apps = A::new( - |id| { - service - .borrow_mut() - .try_new_client(id, syscall.clone()) - .expect("failed to create client") - }, - data, - ); + let service = Service::new(platform, self.dispatch); + let mut apps = A::new(&service, data); log::info!("Ready for work"); thread::scope(|s| { @@ -122,6 +113,87 @@ impl Runner { } } +pub struct Builder { + store: S, + options: Options, + dispatch: D, + init_platform: Option>, +} + +impl Builder { + pub fn new(store: S, options: Options) -> Self { + Self { + store, + options, + dispatch: Default::default(), + init_platform: Default::default(), + } + } +} + +impl Builder { + pub fn dispatch(self, dispatch: E) -> Builder { + Builder { + store: self.store, + options: self.options, + dispatch, + init_platform: self.init_platform, + } + } + + pub fn init_platform(mut self, f: F) -> Self + where + F: Fn(&mut Platform) + 'static, + { + self.init_platform = Some(Box::new(f)); + self + } +} + +impl Builder { + pub fn build, D>>(self) -> Runner { + Runner { + store: self.store, + options: self.options, + dispatch: self.dispatch, + init_platform: self.init_platform, + _marker: Default::default(), + } + } +} + +pub struct Service(Rc, D>>>); + +impl Service { + fn new(platform: Platform, dispatch: D) -> Self { + let service = trussed::Service::with_dispatch(platform, dispatch); + Self(Rc::new(RefCell::new(service))) + } +} + +impl ClientBuilder, D> for Service { + fn build(&self, id: &str, backends: &'static [BackendId]) -> Client { + client::ClientBuilder::new(id) + .backends(backends) + .prepare(&mut *self.0.borrow_mut()) + .expect("failed to create client") + .build(self.clone()) + } +} + +impl Clone for Service { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl trussed::client::Syscall for Service { + fn syscall(&mut self) { + log::debug!("syscall"); + self.0.borrow_mut().process(); + } +} + fn build_device<'a, B: UsbBus>( bus_allocator: &'a UsbBusAllocator, options: &'a Options, @@ -138,28 +210,3 @@ fn build_device<'a, B: UsbBus>( } usb_builder.device_class(0x03).device_sub_class(0).build() } - -pub struct Syscall { - service: Rc>>, -} - -impl trussed::client::Syscall for Syscall

{ - fn syscall(&mut self) { - log::debug!("syscall"); - self.service.borrow_mut().process(); - } -} - -impl Clone for Syscall

{ - fn clone(&self) -> Self { - Self { - service: self.service.clone(), - } - } -} - -impl From>>> for Syscall

{ - fn from(service: Rc>>) -> Self { - Self { service } - } -}