diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4315dfc..c53f4c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,7 @@ jobs: with: profile: minimal toolchain: ${{ matrix.rust }} + components: rustfmt, clippy override: true - name: Test run: | diff --git a/Cargo.toml b/Cargo.toml index a7a3d40..e6785c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,8 @@ license = "Apache-2.0 OR MIT" repository = "https://github.com/trussed-dev/apdu-dispatch" [workspace.dependencies] -iso7816 = "0.1.2" +iso7816 = "0.2.0" +heapless = "0.9" [patch.crates-io] apdu-app.path = "app" diff --git a/app/Cargo.toml b/app/Cargo.toml index c6b7823..48f5571 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -10,3 +10,4 @@ repository.workspace = true [dependencies] iso7816.workspace = true +heapless.workspace = true diff --git a/app/src/lib.rs b/app/src/lib.rs index f04f60c..c30d7e1 100644 --- a/app/src/lib.rs +++ b/app/src/lib.rs @@ -1,11 +1,12 @@ #![no_std] -pub use iso7816::{command::CommandView, Data, Interface, Status}; +pub use heapless::VecView; +pub use iso7816::{command::CommandView, Interface}; pub type Result = iso7816::Result<()>; /// An App can receive and respond APDUs at behest of the ApduDispatch. -pub trait App: iso7816::App { +pub trait App: iso7816::App { /// Given parsed APDU for select command. /// Write response data back to buf, and return length of payload. Return APDU Error code on error. /// Alternatively, the app can defer the response until later by returning it in `poll()`. @@ -13,7 +14,7 @@ pub trait App: iso7816::App { &mut self, interface: Interface, apdu: CommandView<'_>, - reply: &mut Data, + reply: &mut VecView, ) -> Result; /// Deselects the app. This is the result of another app getting selected. @@ -22,5 +23,10 @@ pub trait App: iso7816::App { /// Given parsed APDU for app when selected. /// Write response data back to buf, and return length of payload. Return APDU Error code on error. - fn call(&mut self, interface: Interface, apdu: CommandView<'_>, reply: &mut Data) -> Result; + fn call( + &mut self, + interface: Interface, + apdu: CommandView<'_>, + reply: &mut VecView, + ) -> Result; } diff --git a/dispatch/Cargo.toml b/dispatch/Cargo.toml index 18c7446..45c5b4b 100644 --- a/dispatch/Cargo.toml +++ b/dispatch/Cargo.toml @@ -11,9 +11,9 @@ repository.workspace = true [dependencies] apdu-app = "0.1.0" delog = "0.1.4" -heapless = "0.7" interchange = "0.3.0" iso7816.workspace = true +heapless.workspace = true [dev-dependencies] # Testing diff --git a/dispatch/src/dispatch.rs b/dispatch/src/dispatch.rs index 1a9e1ef..c795594 100644 --- a/dispatch/src/dispatch.rs +++ b/dispatch/src/dispatch.rs @@ -8,7 +8,6 @@ //! //! Apps need to implement the App trait to be managed. //! -use core::mem; use crate::response::SIZE as ResponseSize; use crate::App; @@ -123,8 +122,8 @@ impl<'pipe> ApduDispatch<'pipe> { // but that won't work due to ownership rules fn find_app<'a, 'b>( aid: Option<&Aid>, - apps: &'a mut [&'b mut dyn App], - ) -> Option<&'a mut &'b mut dyn App> { + apps: &'a mut [&'b mut dyn App], + ) -> Option<&'a mut &'b mut dyn App> { // match aid { // Some(aid) => apps.iter_mut().find(|app| aid.starts_with(app.rid())), // None => None, @@ -366,12 +365,7 @@ impl<'pipe> ApduDispatch<'pipe> { } #[inline(never)] - fn handle_app_select( - &mut self, - apps: &mut [&mut dyn App], - aid: Aid, - interface: Interface, - ) { + fn handle_app_select(&mut self, apps: &mut [&mut dyn App], aid: Aid, interface: Interface) { // three cases: // - currently selected app has different AID -> deselect it, to give it // the chance to clear sensitive state @@ -395,7 +389,7 @@ impl<'pipe> ApduDispatch<'pipe> { _ => panic!("Unexpected buffer state."), }; - let old_aid = mem::replace(&mut self.current_aid, Some(aid)); + let old_aid = self.current_aid.replace(aid); if let Some(old_aid) = old_aid { if old_aid != aid { let app = Self::find_app(self.current_aid.as_ref(), apps).unwrap(); @@ -412,11 +406,7 @@ impl<'pipe> ApduDispatch<'pipe> { } #[inline(never)] - fn handle_app_command( - &mut self, - apps: &mut [&mut dyn App], - interface: Interface, - ) { + fn handle_app_command(&mut self, apps: &mut [&mut dyn App], interface: Interface) { // if there is a selected app, send it the command let mut response = response::Data::new(); if let Some(app) = Self::find_app(self.current_aid.as_ref(), apps) { @@ -431,7 +421,7 @@ impl<'pipe> ApduDispatch<'pipe> { }; } - pub fn poll(&mut self, apps: &mut [&mut dyn App]) -> Option { + pub fn poll(&mut self, apps: &mut [&mut dyn App]) -> Option { // Only take on one transaction at a time. let request_type = self.check_for_request(); diff --git a/dispatch/tests/dispatch.rs b/dispatch/tests/dispatch.rs index 236d34b..bc51927 100644 --- a/dispatch/tests/dispatch.rs +++ b/dispatch/tests/dispatch.rs @@ -1,6 +1,7 @@ use apdu_dispatch::app::{App, CommandView, Result as AppResult}; use apdu_dispatch::dispatch; use apdu_dispatch::{interchanges, response}; +use heapless::VecView; use hex_literal::hex; use interchange::Channel; use iso7816::Status; @@ -47,12 +48,12 @@ impl iso7816::App for TestApp1 { } // This app echos to Ins code 0x10 -impl App<{ apdu_dispatch::response::SIZE }> for TestApp1 { +impl App for TestApp1 { fn select( &mut self, _interface: dispatch::Interface, _apdu: CommandView<'_>, - _reply: &mut response::Data, + _reply: &mut VecView, ) -> AppResult { Ok(()) } @@ -63,7 +64,7 @@ impl App<{ apdu_dispatch::response::SIZE }> for TestApp1 { &mut self, _: dispatch::Interface, apdu: CommandView<'_>, - reply: &mut response::Data, + reply: &mut VecView, ) -> AppResult { println!("TestApp1::call"); match apdu.instruction().into() { @@ -79,8 +80,8 @@ impl App<{ apdu_dispatch::response::SIZE }> for TestApp1 { } // For measuring the stack burden of dispatch 0x15 => { - let buf = heapless::Vec::new(); - let addr = (&buf as *const response::Data) as u32; + let buf = heapless::Vec::::new(); + let addr = (&buf as *const VecView).addr() as u32; reply.extend_from_slice(&addr.to_be_bytes()).unwrap(); Ok(()) } @@ -122,12 +123,12 @@ impl iso7816::App for TestApp2 { } // This app echos to Ins code 0x20 -impl App<{ apdu_dispatch::response::SIZE }> for TestApp2 { +impl App for TestApp2 { fn select( &mut self, _interface: dispatch::Interface, _apdu: CommandView<'_>, - _reply: &mut response::Data, + _reply: &mut VecView, ) -> AppResult { Ok(()) } @@ -138,7 +139,7 @@ impl App<{ apdu_dispatch::response::SIZE }> for TestApp2 { &mut self, _: dispatch::Interface, apdu: CommandView<'_>, - reply: &mut response::Data, + reply: &mut VecView, ) -> AppResult { println!("TestApp2::call"); match apdu.instruction().into() { @@ -174,12 +175,12 @@ impl iso7816::App for PanicApp { } // This app echos to Ins code 0x20 -impl App<{ apdu_dispatch::response::SIZE }> for PanicApp { +impl App for PanicApp { fn select( &mut self, _interface: dispatch::Interface, _apdu: CommandView<'_>, - _reply: &mut response::Data, + _reply: &mut VecView, ) -> AppResult { panic!("Dont call the panic app"); } @@ -192,7 +193,7 @@ impl App<{ apdu_dispatch::response::SIZE }> for PanicApp { &mut self, _: dispatch::Interface, _apdu: CommandView<'_>, - _reply: &mut response::Data, + _reply: &mut VecView, ) -> AppResult { panic!("Dont call the panic app"); } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index b3b6356..a271373 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -12,6 +12,7 @@ cargo-fuzz = true libfuzzer-sys = "0.4" arbitrary = { version = "1", features = ["derive"] } interchange = "0.3.0" +heapless = "0.9.0" [dependencies.apdu-dispatch] path = "../dispatch" diff --git a/fuzz/fuzz_targets/fuzz_target_1.rs b/fuzz/fuzz_targets/fuzz_target_1.rs index 924c6f0..33d718f 100644 --- a/fuzz/fuzz_targets/fuzz_target_1.rs +++ b/fuzz/fuzz_targets/fuzz_target_1.rs @@ -2,6 +2,7 @@ use apdu_dispatch::app::Result as AppResult; use apdu_dispatch::{dispatch::Interface, interchanges, iso7816, App}; use arbitrary::{Arbitrary, Unstructured}; +use heapless::VecView; use interchange::Channel; use libfuzzer_sys::fuzz_target; @@ -53,12 +54,12 @@ impl iso7816::App for FuzzAppImpl { } } -impl App<{ apdu_dispatch::response::SIZE }> for FuzzAppImpl { +impl App for FuzzAppImpl { fn select( &mut self, _interface: iso7816::Interface, _apdu: apdu_dispatch::app::CommandView<'_>, - _reply: &mut apdu_dispatch::response::Data, + _reply: &mut heapless::VecView, ) -> AppResult { Ok(()) } @@ -69,7 +70,7 @@ impl App<{ apdu_dispatch::response::SIZE }> for FuzzAppImpl { &mut self, _: Interface, _apdu: apdu_dispatch::app::CommandView<'_>, - reply: &mut apdu_dispatch::response::Data, + reply: &mut VecView, ) -> AppResult { let (ref data, status) = &self.responses[self.count]; reply.extend_from_slice(data).ok(); @@ -89,10 +90,7 @@ fuzz_target!(|input: Input| { .enumerate() .map(|(idx, app)| FuzzAppImpl::new(idx, app)) .collect(); - let mut dyn_apps: Vec<_> = apps - .iter_mut() - .map(|s| (s as &mut dyn apdu_dispatch::App<7609>)) - .collect(); + let mut dyn_apps: Vec<&mut dyn apdu_dispatch::App> = apps.iter_mut().map(|s| s as _).collect(); let contact = Channel::new(); let (mut contact_requester, contact_responder) = contact