Update to heapless 0.9 and trussed-core 0.2

This commit is contained in:
Sosthène Guédon
2026-03-25 18:34:39 +01:00
committed by Robin Krahl
parent d53f29a1be
commit 4e118bba70
13 changed files with 137 additions and 116 deletions
+12 -1
View File
@@ -6,7 +6,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
-
- Update dependencies:
- `apdu-app` v0.2
- `cosey` v0.4
- `ctap-types` v0.5
- `ctaphid-app` v0.2
- `heapless` v0.9
- `heapless-bytes` v0.5
- `iso7816` v0.2
- `trussed-chunked` v0.3
- `trussed-core` v0.2
- `trussed-fs-info` v0.3
- `trussed-hkdf` v0.4
## [v0.2.0](https://github.com/trussed-dev/fido-authenticator/releases/tag/v0.2.0) (2025-09-02)
+19 -19
View File
@@ -9,24 +9,24 @@ documentation = "https://docs.rs/fido-authenticator"
description = "FIDO authenticator Trussed app"
[dependencies]
apdu-app = { version = "0.1", optional = true }
apdu-app = { version = "0.2", optional = true }
cbor-smol = "0.5"
cosey = "0.3"
ctap-types = { version = "0.4", features = ["get-info-full", "large-blobs", "third-party-payment"] }
ctaphid-app = { version = "0.1", optional = true }
cosey = "0.4"
ctap-types = { version = "0.5", features = ["get-info-full", "large-blobs", "third-party-payment"] }
ctaphid-app = { version = "0.2", optional = true }
delog = "0.1"
heapless = "0.7"
heapless-bytes = "0.3"
iso7816 = { version = "0.1.2", optional = true }
heapless = "0.9"
heapless-bytes = { version = "0.5", features = ["heapless-0.9"]}
iso7816 = { version = "0.2", optional = true }
littlefs2-core = "0.1"
serde = { version = "1.0", default-features = false }
serde_bytes = { version = "0.11.14", default-features = false }
serde-indexed = "0.1"
sha2 = { version = "0.10", default-features = false }
trussed-chunked = { version = "0.2", optional = true }
trussed-core = { version = "0.1", features = ["aes256-cbc", "certificate-client", "chacha8-poly1305", "crypto-client", "ed255", "filesystem-client", "hmac-sha256", "management-client", "p256", "sha256", "ui-client"] }
trussed-fs-info = "0.2"
trussed-hkdf = "0.3"
trussed-chunked = { version = "0.3", optional = true }
trussed-core = { version = "0.2", features = ["aes256-cbc", "certificate-client", "chacha8-poly1305", "crypto-client", "ed255", "filesystem-client", "hmac-sha256", "management-client", "p256", "sha256", "ui-client"] }
trussed-fs-info = "0.3"
trussed-hkdf = "0.4"
[features]
dispatch = ["apdu-dispatch", "ctaphid-dispatch", "dep:iso7816"]
@@ -46,38 +46,38 @@ log-warn = []
log-error = []
[dev-dependencies]
admin-app = { git = "https://github.com/Nitrokey/admin-app.git", tag = "v0.1.0-nitrokey.20", features = ["migration-tests"] }
admin-app = { git = "https://github.com/Nitrokey/admin-app.git", tag = "v0.1.0-nitrokey.21", features = ["migration-tests"] }
aes = "0.8.4"
cbc = { version = "0.1.2", features = ["alloc"] }
ciborium = "0.2.2"
ciborium-io = "0.2.2"
cipher = "0.4.4"
ctaphid = { version = "0.3.1", default-features = false }
ctaphid-dispatch = "0.3"
ctaphid-dispatch = "0.4"
delog = { version = "0.1.6", features = ["std-log"] }
env_logger = "0.11"
hex-literal = "0.4.1"
hmac = "0.12.1"
interchange = "0.3"
itertools = "0.14"
littlefs2 = "0.6"
littlefs2 = "0.7"
log = "0.4.21"
p256 = { version = "0.13.2", features = ["ecdh"] }
rand = "0.8.4"
rand_chacha = "0.3"
sha2 = "0.10"
serde_test = "1.0.176"
trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "024e0eca5fb7dbd2457831f7c7bffe4341e08775", features = ["virt"] }
trussed-staging = { git = "https://github.com/trussed-dev/trussed-staging.git", tag = "v0.3.3", features = ["chunked", "hkdf", "virt", "fs-info"] }
trussed-usbip = { git = "https://github.com/trussed-dev/pc-usbip-runner.git", rev = "504674453c9573a30aa2f155101df49eb2af1ba7", default-features = false, features = ["ctaphid"] }
usbd-ctaphid = "0.3"
trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "0f8df68be879acdde1f8cf428c11e5d29692a47b", features = ["virt"] }
trussed-staging = { git = "https://github.com/trussed-dev/trussed-staging.git", tag = "v0.4.0", features = ["chunked", "hkdf", "virt", "fs-info"] }
trussed-usbip = { git = "https://github.com/trussed-dev/pc-usbip-runner.git", rev = "017921df0930707c4af68882ccb1f8b3f1bbf7c5", default-features = false, features = ["ctaphid"] }
usbd-ctaphid = "0.4"
x509-parser = "0.16"
[package.metadata.docs.rs]
features = ["chunked", "dispatch"]
[patch.crates-io]
trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "024e0eca5fb7dbd2457831f7c7bffe4341e08775" }
trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "0f8df68be879acdde1f8cf428c11e5d29692a47b" }
[profile.test]
opt-level = 2
+5 -5
View File
@@ -8,10 +8,10 @@ edition = "2021"
cargo-fuzz = true
[dependencies]
ctap-types = { version = "0.4", features = ["arbitrary"] }
ctap-types = { version = "0.5", features = ["arbitrary"] }
libfuzzer-sys = "0.4"
trussed = { version = "0.1", features = ["clients-1", "certificate-client", "crypto-client", "filesystem-client", "management-client", "aes256-cbc", "ed255", "p256", "sha256"] }
trussed-staging = { version = "0.3.0", features = ["chunked", "hkdf", "virt", "fs-info"] }
trussed = { version = "0.1", features = ["certificate-client", "crypto-client", "filesystem-client", "management-client", "aes256-cbc", "ed255", "p256", "sha256"] }
trussed-staging = { version = "0.4.0", features = ["chunked", "hkdf", "virt", "fs-info"] }
[dependencies.fido-authenticator]
path = ".."
@@ -24,5 +24,5 @@ doc = false
bench = false
[patch.crates-io]
trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "6bba8fde36d05c0227769eb63345744e87d84b2b" }
trussed-staging = { git = "https://github.com/trussed-dev/trussed-staging.git", rev = "1e1ca03a3a62ea9b802f4070ea4bce002eeb4bec" }
trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "0f8df68be879acdde1f8cf428c11e5d29692a47b" }
trussed-staging = { git = "https://github.com/trussed-dev/trussed-staging.git", tag = "v0.4.0" }
+2 -1
View File
@@ -2,12 +2,13 @@
use ctap_types::{authenticator::Request, ctap1::Authenticator as _, ctap2::Authenticator as _};
use fido_authenticator::{Authenticator, Config, Conforming};
use trussed::virt::StoreConfig;
use trussed_staging::virt;
use libfuzzer_sys::fuzz_target;
fuzz_target!(|requests: Vec<Request<'_>>| {
virt::with_ram_client("fido", |client| {
virt::with_client(StoreConfig::ram(), "fido", |client| {
let mut authenticator = Authenticator::new(
client,
Conforming {},
+21 -20
View File
@@ -202,13 +202,14 @@ impl Credential {
fn deserialize_bytes<E: serde::de::Error, const N: usize>(
s: &[u8],
) -> core::result::Result<Bytes<N>, E> {
Bytes::from_slice(s).map_err(|_| E::invalid_length(s.len(), &"a fixed-size sequence of bytes"))
Bytes::try_from(s).map_err(|_| E::invalid_length(s.len(), &"a fixed-size sequence of bytes"))
}
fn deserialize_str<E: serde::de::Error, const N: usize>(
s: &str,
) -> core::result::Result<String<N>, E> {
Ok(s.into())
s.try_into()
.map_err(|_| E::custom("Serialized string doesn't fit "))
}
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -794,12 +795,12 @@ mod test {
fn credential_data() -> CredentialData {
CredentialData {
rp: Rp::new(PublicKeyCredentialRpEntity {
id: String::from("John Doe"),
id: String::try_from("John Doe").unwrap(),
name: None,
icon: None,
}),
user: User::new(PublicKeyCredentialUserEntity {
id: Bytes::from_slice(&[1, 2, 3]).unwrap(),
id: Bytes::from(&[1, 2, 3]),
icon: None,
name: None,
display_name: None,
@@ -807,7 +808,7 @@ mod test {
creation_time: 123,
use_counter: false,
algorithm: -7,
key: Key::WrappedKey(Bytes::from_slice(&[1, 2, 3]).unwrap()),
key: Key::WrappedKey(Bytes::from(&[1, 2, 3])),
hmac_secret: Some(false),
cred_protect: None,
use_short_id: Some(true),
@@ -821,7 +822,7 @@ mod test {
rp: Rp {
format: SerializationFormat::Long,
inner: PublicKeyCredentialRpEntity {
id: String::from("John Doe"),
id: String::try_from("John Doe").unwrap(),
name: None,
icon: None,
},
@@ -829,7 +830,7 @@ mod test {
user: User {
format: SerializationFormat::Long,
inner: PublicKeyCredentialUserEntity {
id: Bytes::from_slice(&[1, 2, 3]).unwrap(),
id: Bytes::from(&[1, 2, 3]),
icon: None,
name: None,
display_name: None,
@@ -838,7 +839,7 @@ mod test {
creation_time: 123,
use_counter: false,
algorithm: -7,
key: Key::WrappedKey(Bytes::from_slice(&[1, 2, 3]).unwrap()),
key: Key::WrappedKey(Bytes::from(&[1, 2, 3])),
hmac_secret: Some(false),
cred_protect: None,
use_short_id: None,
@@ -865,7 +866,7 @@ mod test {
let between = Uniform::from(0..(N + 1));
let n = between.sample(&mut OsRng);
bytes.resize_default(n).unwrap();
bytes.resize_zero(n).unwrap();
OsRng.fill_bytes(&mut bytes);
bytes
@@ -1079,7 +1080,7 @@ mod test {
#[test]
fn max_credential_id() {
let rp_id: String<256> = core::iter::repeat_n('?', 256).collect();
let key = Bytes::from_slice(&[u8::MAX; 128]).unwrap();
let key = Bytes::from(&[u8::MAX; 128]);
let credential = StrippedCredential {
ctap: CtapVersion::Fido21Pre,
creation_time: u32::MAX,
@@ -1160,8 +1161,8 @@ mod test {
fn inner(&self) -> PublicKeyCredentialRpEntity {
PublicKeyCredentialRpEntity {
id: self.id.into(),
name: self.name.map(From::from),
id: self.id.try_into().unwrap(),
name: self.name.map(|n| n.try_into().unwrap()),
icon: None,
}
}
@@ -1225,10 +1226,10 @@ mod test {
fn inner(&self) -> PublicKeyCredentialUserEntity {
PublicKeyCredentialUserEntity {
id: Bytes::from_slice(self.id).unwrap(),
icon: self.icon.map(From::from),
name: self.name.map(From::from),
display_name: self.display_name.map(From::from),
id: Bytes::try_from(self.id).unwrap(),
icon: self.icon.map(|v| v.try_into().unwrap()),
name: self.name.map(|v| v.try_into().unwrap()),
display_name: self.display_name.map(|v| v.try_into().unwrap()),
}
}
}
@@ -1300,7 +1301,7 @@ mod test {
"
);
let credential = FullCredential::deserialize(&Bytes::from_slice(&data).unwrap()).unwrap();
let credential = FullCredential::deserialize(&Bytes::from(&data)).unwrap();
assert!(matches!(credential.ctap, CtapVersion::Fido21Pre));
assert_eq!(credential.nonce, &hex!("F62CA01ED181A3D03D561FC7"));
assert_eq!(
@@ -1309,7 +1310,7 @@ mod test {
rp: Rp {
format: SerializationFormat::Long,
inner: PublicKeyCredentialRpEntity {
id: "webauthn.io".into(),
id: "webauthn.io".try_into().unwrap(),
name: None,
icon: None,
},
@@ -1317,9 +1318,9 @@ mod test {
user: User {
format: SerializationFormat::Long,
inner: PublicKeyCredentialUserEntity {
id: Bytes::from_slice(&hex!("6447567A644445")).unwrap(),
id: Bytes::from(&hex!("6447567A644445")),
icon: None,
name: Some("test1".into()),
name: Some("test1".try_into().unwrap()),
display_name: None,
},
},
+21 -23
View File
@@ -1,9 +1,7 @@
//! The `ctap_types::ctap1::Authenticator` implementation.
use ctap_types::{
ctap1::{authenticate, register, Authenticator, ControlByte, Error, Result},
heapless_bytes::Bytes,
};
use ctap_types::ctap1::{authenticate, register, Authenticator, ControlByte, Error, Result};
use heapless_bytes::Bytes;
use serde_bytes::ByteArray;
use trussed_core::{
@@ -71,9 +69,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
syscall!(self.trussed.delete(private_key));
let key = Key::WrappedKey(
wrapped_key
.to_bytes()
.map_err(|_| Error::UnspecifiedCheckingError)?,
Bytes::try_from(&*wrapped_key).map_err(|_| Error::UnspecifiedCheckingError)?,
);
let nonce = ByteArray::new(self.nonce());
@@ -124,14 +120,15 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
(Some((key, cert)), _aaguid) => {
info!("aaguid: {}", hex_str!(&_aaguid));
(
syscall!(self.trussed.sign(
Mechanism::P256,
key,
&commitment,
SignatureSerialization::Asn1Der
))
.signature
.to_bytes()
Bytes::try_from(
&*syscall!(self.trussed.sign(
Mechanism::P256,
key,
&commitment,
SignatureSerialization::Asn1Der
))
.signature,
)
.unwrap(),
cert,
)
@@ -226,14 +223,15 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
.unwrap();
commitment.extend_from_slice(auth.challenge).unwrap();
let signature = syscall!(self.trussed.sign(
Mechanism::P256,
key,
&commitment,
SignatureSerialization::Asn1Der
))
.signature
.to_bytes()
let signature = Bytes::try_from(
&*syscall!(self.trussed.sign(
Mechanism::P256,
key,
&commitment,
SignatureSerialization::Asn1Der
))
.signature,
)
.unwrap();
Ok(authenticate::Response {
+19 -17
View File
@@ -96,7 +96,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
let mut response = ctap2::get_info::Response::default();
response.versions = versions;
response.extensions = Some(extensions);
response.aaguid = Bytes::from_slice(&aaguid).unwrap();
response.aaguid = Bytes::from(&aaguid);
response.options = Some(options);
response.transports = Some(transports);
// 1200
@@ -293,7 +293,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
// Turns out it's size 92 (enum serialization not optimized yet...)
// let mut wrapped_key = Bytes::<60>::new();
// wrapped_key.extend_from_slice(&wrapped_key_msg).unwrap();
Key::WrappedKey(wrapped_key.to_bytes().map_err(|_| Error::Other)?)
Key::WrappedKey(Bytes::try_from(&*wrapped_key).map_err(|_| Error::Other)?)
}
};
@@ -450,7 +450,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
attestation_algorithm.sign(&mut self.trussed, attestation_key, &commitment);
let packed = PackedAttestationStatement {
alg: attestation_algorithm.into(),
sig: signature.to_bytes().map_err(|_| Error::Other)?,
sig: Bytes::try_from(&*signature).map_err(|_| Error::Other)?,
x5c: attestation_maybe.as_ref().map(|attestation| {
// See: https://www.w3.org/TR/webauthn-2/#sctn-packed-attestation-cert-requirements
let cert = attestation.1.clone();
@@ -900,11 +900,15 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
fn vendor(&mut self, op: VendorOperation) -> Result<()> {
info_now!("hello VO {:?}", &op);
match op.into() {
0x79 => syscall!(self.trussed.debug_dump_store()),
_ => return Err(Error::InvalidCommand),
};
Ok(())
0x79 => {
#[allow(deprecated)]
{
syscall!(self.trussed.debug_dump_store());
}
Err(Error::InvalidCommand)
}
_ => Err(Error::InvalidCommand),
}
}
#[inline(never)]
@@ -1249,7 +1253,7 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
return Err(Error::PinPolicyViolation);
}
pin.resize_default(pin_length).unwrap();
pin.resize_zero(pin_length).unwrap();
Ok(pin)
}
@@ -1286,7 +1290,7 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
// check pinAuth
let mut data: Bytes<{ sizes::MAX_CREDENTIAL_ID_LENGTH_PLUS_256 }> =
Bytes::from_slice(&[parameters.sub_command as u8]).unwrap();
Bytes::from(&[parameters.sub_command as u8]);
let len = 1 + match parameters.sub_command {
Subcommand::EnumerateCredentialsBegin
| Subcommand::DeleteCredential
@@ -1468,7 +1472,7 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
let cred_random = syscall!(self.trussed.derive_key(
Mechanism::HmacSha256,
credential_key,
Some(Bytes::from_slice(&[get_assertion_state.uv_performed as u8]).unwrap()),
Some(Bytes::from(&[get_assertion_state.uv_performed as u8])),
StorageAttributes::new().set_persistence(Location::Volatile)
))
.key;
@@ -1515,7 +1519,7 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
shared_secret.delete(&mut self.trussed);
output.hmac_secret = Some(Bytes::from_slice(&output_enc).unwrap());
output.hmac_secret = Some(Bytes::try_from(&*output_enc).unwrap());
}
if extensions.third_party_payment.unwrap_or_default() {
@@ -1619,10 +1623,8 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
let signing_algorithm =
SigningAlgorithm::try_from(credential.algorithm()).map_err(|_| Error::Other)?;
let signature = signing_algorithm
.sign(&mut self.trussed, key, &commitment)
.to_bytes()
.unwrap();
let signature =
Bytes::try_from(&*signing_algorithm.sign(&mut self.trussed, key, &commitment)).unwrap();
// select preferred format or skip attestation statement
let att_stmt_fmt = data
@@ -1645,7 +1647,7 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
&commitment,
);
(
signature.to_bytes().map_err(|_| Error::Other)?,
Bytes::try_from(&*signature).map_err(|_| Error::Other)?,
signing_algorithm.into(),
)
} else {
+15 -10
View File
@@ -106,7 +106,7 @@ impl<T: CryptoClient> PinTokenMut<'_, T> {
// in spec: encrypt(..., pinUvAuthToken)
pub fn encrypt(&mut self, shared_secret: &SharedSecret) -> Result<Bytes<48>> {
let token = shared_secret.wrap(self.trussed, self.pin_token.key_id);
Bytes::from_slice(&token).map_err(|_| Error::Other)
Bytes::try_from(&*token).map_err(|_| Error::Other)
}
}
@@ -119,7 +119,7 @@ struct Rp {
impl Rp {
fn new<T: CryptoClient>(trussed: &mut T, id: String<256>) -> Self {
let hash =
syscall!(trussed.hash(Mechanism::Sha256, Message::from_slice(id.as_ref()).unwrap()))
syscall!(trussed.hash(Mechanism::Sha256, Message::try_from(id.as_bytes()).unwrap()))
.hash
.as_slice()
.try_into()
@@ -366,7 +366,7 @@ impl<'a, T: CryptoClient + HkdfClient + HmacSha256 + P256> PinProtocol<'a, T> {
// operations. For simplicity, we store two separate keys instead.
fn kdf_v2(&mut self, input: KeyId) -> Option<SharedSecret> {
fn hkdf<T: HkdfClient>(trussed: &mut T, okm: OkmId, info: &[u8]) -> Option<KeyId> {
let info = Message::from_slice(info).ok()?;
let info = Message::try_from(info).ok()?;
try_syscall!(trussed.hkdf_expand(okm, info, 32, Location::Volatile))
.ok()
.map(|reply| reply.key)
@@ -420,11 +420,10 @@ impl SharedSecret {
fn generate_iv<T: CryptoClient>(&self, trussed: &mut T) -> ShortData {
match self {
Self::V1 { .. } => ShortData::from_slice(&[0; 16]).unwrap(),
Self::V2 { .. } => syscall!(trussed.random_bytes(16))
.bytes
.try_convert_into()
.unwrap(),
Self::V1 { .. } => ShortData::from(&[0; 16]),
Self::V2 { .. } => {
ShortData::try_from(&*syscall!(trussed.random_bytes(16)).bytes).unwrap()
}
}
}
@@ -436,7 +435,10 @@ impl SharedSecret {
syscall!(trussed.encrypt(Mechanism::Aes256Cbc, key_id, data, &[], Some(iv.clone())))
.ciphertext;
if matches!(self, Self::V2 { .. }) {
ciphertext.insert_slice_at(&iv, 0).unwrap();
let ciphertext_len = ciphertext.len();
ciphertext.resize_zero(iv.len() + ciphertext_len).unwrap();
ciphertext.copy_within(..ciphertext_len, iv.len());
ciphertext[..iv.len()].copy_from_slice(&iv);
}
ciphertext
}
@@ -454,7 +456,10 @@ impl SharedSecret {
))
.wrapped_key;
if matches!(self, Self::V2 { .. }) {
wrapped_key.insert_slice_at(&iv, 0).unwrap();
let wrapped_key_len = wrapped_key.len();
wrapped_key.resize_zero(iv.len() + wrapped_key_len).unwrap();
wrapped_key.copy_within(..wrapped_key_len, iv.len());
wrapped_key[..iv.len()].copy_from_slice(&iv);
}
wrapped_key
}
+10 -9
View File
@@ -8,7 +8,8 @@ use crate::msp;
use crate::{Authenticator, TrussedRequirements, UserPresence};
use ctap_types::{ctap1, ctap2};
use iso7816::{command::CommandView, Data, Status};
use heapless::VecView;
use iso7816::{command::CommandView, Status};
impl<UP, T> iso7816::App for Authenticator<UP, T>
where
@@ -21,10 +22,10 @@ where
#[inline(never)]
/// Deserialize U2F, call authenticator, serialize response *Result*.
fn handle_ctap1_from_hid<T, UP, const R: usize>(
fn handle_ctap1_from_hid<T, UP>(
authenticator: &mut Authenticator<UP, T>,
data: &[u8],
response: &mut Data<R>,
response: &mut VecView<u8>,
) where
T: TrussedRequirements,
UP: UserPresence,
@@ -65,10 +66,10 @@ fn handle_ctap1_from_hid<T, UP, const R: usize>(
#[inline(never)]
/// Deserialize CBOR, call authenticator, serialize response *Result*.
fn handle_ctap2<T, UP, const R: usize>(
fn handle_ctap2<T, UP>(
authenticator: &mut Authenticator<UP, T>,
data: &[u8],
response: &mut Data<R>,
response: &mut VecView<u8>,
) where
T: TrussedRequirements,
UP: UserPresence,
@@ -89,10 +90,10 @@ fn handle_ctap2<T, UP, const R: usize>(
}
#[inline(never)]
fn try_handle_ctap1<T, UP, const R: usize>(
fn try_handle_ctap1<T, UP>(
authenticator: &mut Authenticator<UP, T>,
command: CommandView<'_>,
response: &mut Data<R>,
response: &mut VecView<u8>,
) -> Result<(), Status>
where
T: TrussedRequirements,
@@ -124,10 +125,10 @@ where
}
#[inline(never)]
fn try_handle_ctap2<T, UP, const R: usize>(
fn try_handle_ctap2<T, UP>(
authenticator: &mut Authenticator<UP, T>,
data: &[u8],
response: &mut Data<R>,
response: &mut VecView<u8>,
) -> Result<(), u8>
where
T: TrussedRequirements,
+6 -5
View File
@@ -1,6 +1,7 @@
use apdu_app::Interface;
use ctap_types::{serde::error::Error as SerdeError, Error};
use iso7816::{command::CommandView, Data, Status};
use heapless::VecView;
use iso7816::{command::CommandView, Status};
use crate::{Authenticator, TrussedRequirements, UserPresence};
@@ -21,7 +22,7 @@ impl From<CtapMappingError> for Error {
}
}
impl<UP, T, const R: usize> apdu_app::App<R> for Authenticator<UP, T>
impl<UP, T> apdu_app::App for Authenticator<UP, T>
where
UP: UserPresence,
T: TrussedRequirements,
@@ -30,7 +31,7 @@ where
&mut self,
interface: Interface,
_: CommandView<'_>,
reply: &mut Data<R>,
reply: &mut VecView<u8>,
) -> apdu_app::Result {
// FIDO-over-CCID does not seem to officially be a thing; we don't support it.
// If we would, need to review the following cases catering to semi-documented U2F legacy.
@@ -48,7 +49,7 @@ where
&mut self,
interface: Interface,
apdu: CommandView<'_>,
response: &mut Data<R>,
response: &mut VecView<u8>,
) -> apdu_app::Result {
// FIDO-over-CCID does not seem to officially be a thing; we don't support it.
// If we would, need to review the following cases catering to semi-documented U2F legacy.
@@ -77,7 +78,7 @@ where
super::handle_ctap2(self, apdu.data(), response)
}
Ok(ctaphid_app::Command::Msg) => super::try_handle_ctap1(self, apdu, response)?,
Ok(ctaphid_app::Command::Deselect) => apdu_app::App::<R>::deselect(self),
Ok(ctaphid_app::Command::Deselect) => apdu_app::App::deselect(self),
_ => {
info!("Unsupported ins for fido app {:02x}", instruction);
return Err(iso7816::Status::InstructionNotSupportedOrInvalid);
+5 -5
View File
@@ -1,12 +1,12 @@
use ctaphid_app::{App, Command, Error};
use heapless_bytes::Bytes;
use heapless_bytes::BytesView;
use trussed_core::InterruptFlag;
#[allow(unused_imports)]
use crate::msp;
use crate::{Authenticator, TrussedRequirements, UserPresence};
impl<UP, T, const N: usize> App<'static, N> for Authenticator<UP, T>
impl<UP, T> App<'static> for Authenticator<UP, T>
where
UP: UserPresence,
T: TrussedRequirements,
@@ -20,7 +20,7 @@ where
&mut self,
command: Command,
request: &[u8],
response: &mut Bytes<N>,
response: &mut BytesView,
) -> Result<(), Error> {
debug_now!(
"ctaphid-dispatch: remaining stack: {} bytes",
@@ -35,8 +35,8 @@ where
// info_now!("request: ");
// blocking::dump_hex(request, request.len());
match command {
Command::Cbor => super::handle_ctap2(self, request, response),
Command::Msg => super::handle_ctap1_from_hid(self, request, response),
Command::Cbor => super::handle_ctap2(self, request, response.as_mut()),
Command::Msg => super::handle_ctap1_from_hid(self, request, response.as_mut()),
_ => {
debug_now!("ctaphid trying to dispatch {:?}", command);
}
+1 -1
View File
@@ -369,7 +369,7 @@ impl<'a, const N: usize> Pipe<'a, N> {
}
match self.interchange.request((
request.command,
Bytes::from_slice(&self.buffer[..request.length as usize]).unwrap(),
Bytes::try_from(&self.buffer[..request.length as usize]).unwrap(),
)) {
Ok(_) => {
self.state = State::WaitingOnAuthenticator(request);
+1
View File
@@ -33,6 +33,7 @@ macro_rules! exhaustive_struct {
}
}
#[allow(unused_imports)]
pub(crate) use exhaustive_struct;
pub struct KeyAgreementKey(p256::ecdh::EphemeralSecret);