Skip to content

Commit

Permalink
Use apdu-app instead of apdu-dispatch
Browse files Browse the repository at this point in the history
  • Loading branch information
robin-nitrokey committed Oct 21, 2024
1 parent 7e41e0f commit 7121790
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 73 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ license = "Apache-2.0 OR MIT"
description = "Secrets App - a Trussed app to manage OTP and Password Safe features of Nitrokey 3"

[dependencies]
apdu-dispatch = { version = "0.1.2", optional = true }
apdu-app = { version = "0.1", optional = true }
ctaphid-dispatch = { version = "0.1", optional = true }
cbor-smol = "0.4"
delog = "0.1.6"
flexiber = { version = "0.1.0", features = ["derive", "heapless"] }
heapless = "0.7"
heapless-bytes = "0.3"
hex-literal = "0.3"
iso7816 = "0.1"
iso7816 = "0.1.3"
serde = { version = "1", default-features = false }
trussed = { version = "0.1", features = ["clients-3"] }
encrypted_container = { path = "components/encrypted_container" }
Expand All @@ -29,6 +29,7 @@ trussed-auth = "0.3.0"
[features]
default = ["apdu-dispatch"]
devel = ["apdu-dispatch", "log-all", "delog/std-log", "devel-counters"]
apdu-dispatch = ["dep:apdu-app"]

# Count accesses to the read-only and read-write persistence storage
devel-counters = []
Expand All @@ -50,7 +51,6 @@ log-warn = []
log-error = []

[patch.crates-io]
apdu-dispatch = { git = "https://github.com/trussed-dev/apdu-dispatch.git", rev = "915fc237103fcecc29d0f0b73391f19abf6576de" }
ctaphid-dispatch = { git = "https://github.com/Nitrokey/ctaphid-dispatch", tag = "v0.1.1-nitrokey.2" }
flexiber = { git = "https://github.com/Nitrokey/flexiber", tag = "0.1.1.nitrokey" }
littlefs2 = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "ebd27e49ca321089d01d8c9b169c4aeb58ceeeca" }
Expand Down
4 changes: 2 additions & 2 deletions fuzz/corpus-viewer/corpus-viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ fn main() -> Result<(), ()> {

let commands = parse(data.as_ref());
for data in commands {
if let Ok(command) = iso7816::Command::<{ 10 * 255 }>::try_from(data) {
if let Ok(cmd) = secrets_app::Command::try_from(&command) {
if let Ok(command) = iso7816::command::CommandView::try_from(data) {
if let Ok(cmd) = secrets_app::Command::try_from(command) {
println!(">>> {:?}", cmd);
} else {
println!(">>> (unparsed) {:?}", command);
Expand Down
15 changes: 4 additions & 11 deletions fuzz/fuzz_targets/fuzz_target_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,18 @@ use trussed::types::Location;
mod virt;

fuzz_target!(|data: &[u8]| {

virt::with_ram_client("secrets", move |client| {

let options = secrets_app::Options::new(
Location::Internal,
0,
1,
[0x42, 0x42, 0x42, 0x42],
u16::MAX,
);
let options =
secrets_app::Options::new(Location::Internal, 0, 1, [0x42, 0x42, 0x42, 0x42], u16::MAX);
let mut secrets = secrets_app::Authenticator::new(client, options);

let mut response = heapless::Vec::<u8, { 3 * 1024 }>::new();

let commands = parse(data);
for data in commands {
if let Ok(command) = iso7816::Command::<{ 10 * 255 }>::try_from(data) {
if let Ok(command) = iso7816::command::CommandView::try_from(data.as_slice()) {
response.clear();
secrets.respond(&command, &mut response).ok();
secrets.respond(command, &mut response).ok();
}
}
})
Expand Down
10 changes: 5 additions & 5 deletions fuzz/fuzz_targets/virt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ pub type VirtClient<S> = Client<S, dispatch::Dispatch>;

/// Run a client using a provided store
pub fn with_client<S, R, F>(store: S, client_id: &str, f: F) -> R
where
F: FnOnce(VirtClient<S>) -> R,
S: StoreProvider,
where
F: FnOnce(VirtClient<S>) -> R,
S: StoreProvider,
{
#[allow(clippy::unwrap_used)]
virt::with_platform(store, |platform| {
Expand All @@ -31,8 +31,8 @@ pub fn with_client<S, R, F>(store: S, client_id: &str, f: F) -> R
/// Run the backend with the extensions required
/// using a RAM file storage
pub fn with_ram_client<R, F>(client_id: &str, f: F) -> R
where
F: FnOnce(VirtClient<Ram>) -> R,
where
F: FnOnce(VirtClient<Ram>) -> R,
{
with_client(Ram::default(), client_id, f)
}
3 changes: 1 addition & 2 deletions fuzz/fuzz_targets/virt/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ use trussed::{
};
use trussed_auth::{AuthBackend, AuthContext, AuthExtension, MAX_HW_KEY_LEN};

pub const BACKENDS: &[BackendId<Backend>] =
&[BackendId::Custom(Backend::Auth), BackendId::Core];
pub const BACKENDS: &[BackendId<Backend>] = &[BackendId::Custom(Backend::Auth), BackendId::Core];

pub enum Backend {
Auth,
Expand Down
14 changes: 7 additions & 7 deletions src/authenticator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,9 @@ where
}

/// Respond to the iso7816 encoded request
pub fn respond<const C: usize, const R: usize>(
pub fn respond<const R: usize>(
&mut self,
command: &iso7816::Command<C>,
command: iso7816::command::CommandView<'_>,
reply: &mut Data<R>,
) -> Result {
let client_authorized_before = self.state.runtime.client_authorized;
Expand All @@ -258,9 +258,9 @@ where
result
}

fn inner_respond<const C: usize, const R: usize>(
fn inner_respond<const R: usize>(
&mut self,
command: &iso7816::Command<C>,
command: iso7816::command::CommandView<'_>,
reply: &mut Data<R>,
) -> Result {
let class = command.class();
Expand Down Expand Up @@ -1355,7 +1355,7 @@ impl<T> iso7816::App for Authenticator<T> {
}

#[cfg(feature = "apdu-dispatch")]
impl<T, const C: usize, const R: usize> apdu_dispatch::app::App<C, R> for Authenticator<T>
impl<T, const R: usize> apdu_app::App<R> for Authenticator<T>
where
T: client::Client
+ client::HmacSha1
Expand All @@ -1367,7 +1367,7 @@ where
fn select(
&mut self,
_interface: iso7816::Interface,
apdu: &iso7816::Command<C>,
apdu: iso7816::command::CommandView<'_>,
reply: &mut Data<R>,
) -> Result {
self.respond(apdu, reply)
Expand All @@ -1379,7 +1379,7 @@ where
fn call(
&mut self,
_: iso7816::Interface,
apdu: &iso7816::Command<C>,
apdu: iso7816::command::CommandView<'_>,
reply: &mut Data<R>,
) -> Result {
self.respond(apdu, reply)
Expand Down
68 changes: 34 additions & 34 deletions src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use flexiber::{Encodable, SimpleTag, TagLike};
use serde::{Deserialize, Serialize};

use iso7816::command::class::Class;
use iso7816::{Data, Instruction, Status};
use iso7816::{Instruction, Status};
use YkCommand::GetSerial;

use crate::oath::{Tag, YkCommand};
Expand Down Expand Up @@ -142,9 +142,9 @@ pub struct SetPassword<'l> {
pub response: &'l [u8],
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for SetPassword<'l> {
impl<'l> TryFrom<&'l [u8]> for SetPassword<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
// key = self.derive_key(password)
// keydata = bytearray([OATH_TYPE.TOTP | ALGO.SHA1]) + key
// challenge = os.urandom(8)
Expand Down Expand Up @@ -205,9 +205,9 @@ pub struct Validate<'l> {
pub challenge: &'l [u8],
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for Validate<'l> {
impl<'l> TryFrom<&'l [u8]> for Validate<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand Down Expand Up @@ -238,9 +238,9 @@ pub struct VerifyCode<'l> {
pub response: u32,
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for VerifyCode<'l> {
impl<'l> TryFrom<&'l [u8]> for VerifyCode<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand Down Expand Up @@ -272,9 +272,9 @@ pub struct SetPin<'l> {
pub password: &'l [u8],
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for SetPin<'l> {
impl<'l> TryFrom<&'l [u8]> for SetPin<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand All @@ -295,9 +295,9 @@ pub struct RenameCredential<'l> {
pub new_label: &'l [u8],
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for RenameCredential<'l> {
impl<'l> TryFrom<&'l [u8]> for RenameCredential<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand All @@ -324,9 +324,9 @@ pub struct GetCredential<'l> {
pub label: &'l [u8],
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for GetCredential<'l> {
impl<'l> TryFrom<&'l [u8]> for GetCredential<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand All @@ -347,9 +347,9 @@ pub struct ChangePin<'l> {
pub new_password: &'l [u8],
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for ChangePin<'l> {
impl<'l> TryFrom<&'l [u8]> for ChangePin<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand Down Expand Up @@ -379,9 +379,9 @@ pub struct VerifyPin<'l> {
pub password: &'l [u8],
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for VerifyPin<'l> {
impl<'l> TryFrom<&'l [u8]> for VerifyPin<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand All @@ -402,9 +402,9 @@ pub struct Calculate<'l> {
pub challenge: &'l [u8],
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for Calculate<'l> {
impl<'l> TryFrom<&'l [u8]> for Calculate<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand All @@ -431,9 +431,9 @@ pub struct CalculateAll<'l> {
pub challenge: &'l [u8],
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for CalculateAll<'l> {
impl<'l> TryFrom<&'l [u8]> for CalculateAll<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand Down Expand Up @@ -464,9 +464,9 @@ impl core::fmt::Debug for Delete<'_> {
}
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for Delete<'l> {
impl<'l> TryFrom<&'l [u8]> for Delete<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand All @@ -481,9 +481,9 @@ impl<'l, const C: usize> TryFrom<&'l Data<C>> for Delete<'l> {
}
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for ListCredentials {
impl<'l> TryFrom<&'l [u8]> for ListCredentials {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
let v = if !data.is_empty() { data[0] } else { 0 };
Ok(ListCredentials { version: v })
}
Expand Down Expand Up @@ -516,9 +516,9 @@ pub struct UpdateCredential<'l> {
pub password_safe: Option<PasswordSafeData<'l>>,
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for UpdateCredential<'l> {
impl<'l> TryFrom<&'l [u8]> for UpdateCredential<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
use flexiber::TaggedSlice;
let mut decoder = flexiber::Decoder::new(data);

Expand Down Expand Up @@ -697,10 +697,10 @@ impl TryFrom<SimpleTag> for Tag {
}
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for Register<'l> {
impl<'l> TryFrom<&'l [u8]> for Register<'l> {
type Error = Status;

fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
// All fields of the OTP Credential are obligatory
// The PWS entries are optional
use flexiber::Decodable;
Expand Down Expand Up @@ -878,15 +878,15 @@ impl<'l> Command<'l> {
}
}
}
impl<'l, const C: usize> TryFrom<&'l iso7816::Command<C>> for Command<'l> {
impl<'l> TryFrom<iso7816::command::CommandView<'l>> for Command<'l> {
type Error = Status;
/// The first layer of unraveling the iso7816::Command onion.
///
/// The responsibility here is to check (cla, ins, p1, p2) are valid as defined
/// in the "Command Syntax" boxes of NIST SP 800-73-4, and return early errors.
///
/// The individual piv::Command TryFroms then further interpret these validated parameters.
fn try_from(command: &'l iso7816::Command<C>) -> Result<Self, Self::Error> {
fn try_from(command: iso7816::command::CommandView<'l>) -> Result<Self, Self::Error> {
let (class, instruction, p1, p2) = (
command.class(),
command.instruction(),
Expand Down Expand Up @@ -956,11 +956,11 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command<C>> for Command<'l> {
}
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for Select<'l> {
impl<'l> TryFrom<&'l [u8]> for Select<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
fn try_from(data: &'l [u8]) -> Result<Self, Self::Error> {
// info_now!("comparing {} against {}", hex_str!(data.as_slice()), hex_str!(crate::YUBICO_OATH_AID));
Ok(match data.as_slice() {
Ok(match data {
crate::YUBICO_OATH_AID => Self { aid: data },
_ => return Err(Status::NotFound),
})
Expand Down
Loading

0 comments on commit 7121790

Please sign in to comment.