Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
with:
profile: minimal
toolchain: ${{ matrix.rust }}
components: rustfmt, clippy
override: true
- name: Test
run: |
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
1 change: 1 addition & 0 deletions app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ repository.workspace = true

[dependencies]
iso7816.workspace = true
heapless.workspace = true
14 changes: 10 additions & 4 deletions app/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
#![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<const R: usize>: 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()`.
fn select(
&mut self,
interface: Interface,
apdu: CommandView<'_>,
reply: &mut Data<R>,
reply: &mut VecView<u8>,
) -> Result;

/// Deselects the app. This is the result of another app getting selected.
Expand All @@ -22,5 +23,10 @@ pub trait App<const R: usize>: 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<R>) -> Result;
fn call(
&mut self,
interface: Interface,
apdu: CommandView<'_>,
reply: &mut VecView<u8>,
) -> Result;
}
2 changes: 1 addition & 1 deletion dispatch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 6 additions & 16 deletions dispatch/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<ResponseSize>],
) -> Option<&'a mut &'b mut dyn App<ResponseSize>> {
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,
Expand Down Expand Up @@ -366,12 +365,7 @@ impl<'pipe> ApduDispatch<'pipe> {
}

#[inline(never)]
fn handle_app_select(
&mut self,
apps: &mut [&mut dyn App<ResponseSize>],
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
Expand All @@ -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();
Expand All @@ -412,11 +406,7 @@ impl<'pipe> ApduDispatch<'pipe> {
}

#[inline(never)]
fn handle_app_command(
&mut self,
apps: &mut [&mut dyn App<ResponseSize>],
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) {
Expand All @@ -431,7 +421,7 @@ impl<'pipe> ApduDispatch<'pipe> {
};
}

pub fn poll(&mut self, apps: &mut [&mut dyn App<ResponseSize>]) -> Option<Interface> {
pub fn poll(&mut self, apps: &mut [&mut dyn App]) -> Option<Interface> {
// Only take on one transaction at a time.
let request_type = self.check_for_request();

Expand Down
23 changes: 12 additions & 11 deletions dispatch/tests/dispatch.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<u8>,
) -> AppResult {
Ok(())
}
Expand All @@ -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<u8>,
) -> AppResult {
println!("TestApp1::call");
match apdu.instruction().into() {
Expand All @@ -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::<u8, { response::SIZE }>::new();
let addr = (&buf as *const VecView<u8>).addr() as u32;
reply.extend_from_slice(&addr.to_be_bytes()).unwrap();
Ok(())
}
Expand Down Expand Up @@ -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<u8>,
) -> AppResult {
Ok(())
}
Expand All @@ -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<u8>,
) -> AppResult {
println!("TestApp2::call");
match apdu.instruction().into() {
Expand Down Expand Up @@ -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<u8>,
) -> AppResult {
panic!("Dont call the panic app");
}
Expand All @@ -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<u8>,
) -> AppResult {
panic!("Dont call the panic app");
}
Expand Down
1 change: 1 addition & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 5 additions & 7 deletions fuzz/fuzz_targets/fuzz_target_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<u8>,
) -> AppResult {
Ok(())
}
Expand All @@ -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<u8>,
) -> AppResult {
let (ref data, status) = &self.responses[self.count];
reply.extend_from_slice(data).ok();
Expand All @@ -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
Expand Down
Loading