Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use apdu-app instead of apdu-dispatch #121

Merged
merged 2 commits into from
Oct 21, 2024
Merged
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
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) {
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
78 changes: 34 additions & 44 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 @@ -70,16 +70,6 @@ pub struct YkGetHmac<'l> {
pub slot_cmd: Option<YkCommand>,
}

impl<'l, const C: usize> TryFrom<&'l Data<C>> for YkGetHmac<'l> {
type Error = Status;
fn try_from(data: &'l Data<C>) -> Result<Self, Self::Error> {
Ok(Self {
challenge: data,
slot_cmd: None,
})
}
}

impl<'l> YkGetHmac<'l> {
pub fn get_credential_label(&self) -> Result<&[u8], Status> {
Ok(match self.slot_cmd.ok_or(Status::IncorrectDataParameter)? {
Expand Down Expand Up @@ -152,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 @@ -215,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 @@ -248,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 @@ -282,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 @@ -305,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 @@ -334,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 @@ -357,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 @@ -389,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 @@ -412,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 @@ -441,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 @@ -474,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 @@ -491,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 @@ -526,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 @@ -707,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 @@ -888,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 @@ -966,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
Loading