From 508116066caf9d9258d1bbb983677ed62d81eb3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Mon, 24 Oct 2022 16:03:19 +0200 Subject: [PATCH] Run cargo fmt --- src/commands.rs | 82 ++++++++----- src/constants.rs | 20 ++-- src/container.rs | 102 ++++++++-------- src/dispatch.rs | 17 ++- src/lib.rs | 286 ++++++++++++++++++++++++++------------------- src/piv_types.rs | 77 +++++++----- src/state.rs | 85 +++++++------- tests/get_data.rs | 2 +- tests/setup/mod.rs | 53 ++++++--- 9 files changed, 432 insertions(+), 292 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 09965d4..109d9a3 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -66,7 +66,6 @@ impl<'l> TryFrom<&'l [u8]> for Select<'l> { } } - #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct GetData(containers::Container); @@ -74,7 +73,9 @@ impl TryFrom<&[u8]> for GetData { type Error = Status; fn try_from(data: &[u8]) -> Result { let mut decoder = flexiber::Decoder::new(data); - let tagged_slice: flexiber::TaggedSlice = decoder.decode().map_err(|_| Status::IncorrectDataParameter)?; + let tagged_slice: flexiber::TaggedSlice = decoder + .decode() + .map_err(|_| Status::IncorrectDataParameter)?; if tagged_slice.tag() != flexiber::Tag::application(0x1C) { return Err(Status::IncorrectDataParameter); } @@ -155,13 +156,20 @@ pub enum Verify { impl TryFrom> for Verify { type Error = Status; fn try_from(arguments: VerifyArguments<'_>) -> Result { - let VerifyArguments { key_reference, logout, data } = arguments; + let VerifyArguments { + key_reference, + logout, + data, + } = arguments; if key_reference != VerifyKeyReference::PivPin { return Err(Status::FunctionNotSupported); } Ok(match (logout.0, data.len()) { (false, 0) => Verify::Status(key_reference), - (false, 8) => Verify::Login(VerifyLogin::PivPin(data.try_into().map_err(|_| Status::IncorrectDataParameter)?)), + (false, 8) => Verify::Login(VerifyLogin::PivPin( + data.try_into() + .map_err(|_| Status::IncorrectDataParameter)?, + )), (false, _) => return Err(Status::IncorrectDataParameter), (true, 0) => Verify::Logout(key_reference), (true, _) => return Err(Status::IncorrectDataParameter), @@ -204,22 +212,27 @@ pub enum ChangeReference { impl TryFrom> for ChangeReference { type Error = Status; fn try_from(arguments: ChangeReferenceArguments<'_>) -> Result { - let ChangeReferenceArguments { key_reference, data } = arguments; + let ChangeReferenceArguments { + key_reference, + data, + } = arguments; use ChangeReferenceKeyReference::*; Ok(match (key_reference, data) { (GlobalPin, _) => return Err(Status::FunctionNotSupported), - (PivPin, data) => { - ChangeReference::ChangePin { - old_pin: Pin::try_from(&data[..8]).map_err(|_| Status::IncorrectDataParameter)?, - new_pin: Pin::try_from(&data[8..]).map_err(|_| Status::IncorrectDataParameter)?, - } - } + (PivPin, data) => ChangeReference::ChangePin { + old_pin: Pin::try_from(&data[..8]).map_err(|_| Status::IncorrectDataParameter)?, + new_pin: Pin::try_from(&data[8..]).map_err(|_| Status::IncorrectDataParameter)?, + }, (Puk, data) => { use crate::commands::Puk; ChangeReference::ChangePuk { - old_puk: Puk(data[..8].try_into().map_err(|_| Status::IncorrectDataParameter)?), - new_puk: Puk(data[8..].try_into().map_err(|_| Status::IncorrectDataParameter)?), + old_puk: Puk(data[..8] + .try_into() + .map_err(|_| Status::IncorrectDataParameter)?), + new_puk: Puk(data[8..] + .try_into() + .map_err(|_| Status::IncorrectDataParameter)?), } } }) @@ -229,7 +242,7 @@ impl TryFrom> for ChangeReference { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct ResetPinRetries { pub padded_pin: [u8; 8], - pub puk: [u8; 8], + pub puk: [u8; 8], } impl TryFrom<&[u8]> for ResetPinRetries { @@ -321,8 +334,7 @@ pub struct AuthenticateArguments<'l> { } #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Authenticate { -} +pub enum Authenticate {} impl TryFrom> for Authenticate { type Error = Status; @@ -332,8 +344,7 @@ impl TryFrom> for Authenticate { } #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct PutData { -} +pub struct PutData {} impl TryFrom<&[u8]> for PutData { type Error = Status; @@ -373,8 +384,7 @@ pub struct GenerateAsymmetricArguments<'l> { } #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum GenerateAsymmetric { -} +pub enum GenerateAsymmetric {} impl TryFrom> for GenerateAsymmetric { type Error = Status; @@ -392,7 +402,12 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command> for Command<'l> { /// /// The individual piv::Command TryFroms then further interpret these validated parameters. fn try_from(command: &'l iso7816::Command) -> Result { - let (class, instruction, p1, p2) = (command.class(), command.instruction(), command.p1, command.p2); + let (class, instruction, p1, p2) = ( + command.class(), + command.instruction(), + command.p1, + command.p2, + ); let data = command.data(); if !class.secure_messaging().none() { @@ -406,7 +421,6 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command> for Command<'l> { // TODO: should we check `command.expected() == 0`, where specified? Ok(match (class.into_inner(), instruction, p1, p2) { - (0x00, Instruction::Select, 0x04, 0x00) => { Self::Select(Select::try_from(data.as_slice())?) } @@ -418,12 +432,19 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command> for Command<'l> { (0x00, Instruction::Verify, p1, p2) => { let logout = VerifyLogout::try_from(p1)?; let key_reference = VerifyKeyReference::try_from(p2)?; - Self::Verify(Verify::try_from(VerifyArguments { key_reference, logout, data })?) + Self::Verify(Verify::try_from(VerifyArguments { + key_reference, + logout, + data, + })?) } (0x00, Instruction::ChangeReferenceData, 0x00, p2) => { let key_reference = ChangeReferenceKeyReference::try_from(p2)?; - Self::ChangeReference(ChangeReference::try_from(ChangeReferenceArguments { key_reference, data })?) + Self::ChangeReference(ChangeReference::try_from(ChangeReferenceArguments { + key_reference, + data, + })?) } (0x00, Instruction::ResetRetryCounter, 0x00, 0x80) => { @@ -433,7 +454,11 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command> for Command<'l> { (0x00, Instruction::GeneralAuthenticate, p1, p2) => { let unparsed_algorithm = p1; let key_reference = AuthenticateKeyReference::try_from(p2)?; - Self::Authenticate(Authenticate::try_from(AuthenticateArguments { unparsed_algorithm, key_reference, data })?) + Self::Authenticate(Authenticate::try_from(AuthenticateArguments { + unparsed_algorithm, + key_reference, + data, + })?) } (0x00, Instruction::PutData, 0x3F, 0xFF) => { @@ -442,7 +467,12 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command> for Command<'l> { (0x00, Instruction::GenerateAsymmetricKeyPair, 0x00, p2) => { let key_reference = GenerateAsymmetricKeyReference::try_from(p2)?; - Self::GenerateAsymmetric(GenerateAsymmetric::try_from(GenerateAsymmetricArguments { key_reference, data })?) + Self::GenerateAsymmetric(GenerateAsymmetric::try_from( + GenerateAsymmetricArguments { + key_reference, + data, + }, + )?) } _ => return Err(Status::FunctionNotSupported), diff --git a/src/constants.rs b/src/constants.rs index 0a14aba..2452d6d 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -19,7 +19,8 @@ pub const DERIVED_PIV_PIX: [u8; 6] = hex!("0000 2000 0100"); pub const PIV_TRUNCATED_AID: [u8; 9] = hex!("A000000308 00001000"); // pub const PIV_AID: &[u8] = &hex!("A000000308 00001000 0100"); -pub const PIV_AID: iso7816::Aid = iso7816::Aid::new_truncatable(&hex!("A000000308 00001000 0100"), 9); +pub const PIV_AID: iso7816::Aid = + iso7816::Aid::new_truncatable(&hex!("A000000308 00001000 0100"), 9); pub const DERIVED_PIV_AID: [u8; 11] = hex!("A000000308 00002000 0100"); @@ -27,7 +28,6 @@ pub const APPLICATION_LABEL: &[u8] = b"SoloKeys PIV"; pub const APPLICATION_URL: &[u8] = b"https://github.com/solokeys/piv-authenticator"; // pub const APPLICATION_URL: &[u8] = b"https://piv.is/SoloKeys/PIV/1.0.0-alpha1"; - // https://git.io/JfWuD pub const YUBICO_OTP_PIX: [u8; 3] = hex!("200101"); pub const YUBICO_OTP_AID: iso7816::Aid = iso7816::Aid::new(&hex!("A000000527 200101")); @@ -84,7 +84,7 @@ pub const SELECT: (u8, u8, u8, u8) = ( // p2: i think this is dummy here 0x00, // b2, b1 zero means "file occurence": first/only occurence, // b4, b3 zero means "file control information": return FCI template - // 256, + // 256, ); // @@ -101,12 +101,11 @@ pub const SELECT: (u8, u8, u8, u8) = ( pub const GET_DATA: (u8, u8, u8, u8) = ( 0x00, // as before, would be 0x0C for secure messaging 0xCB, // GET DATA. There's also `CA`, setting bit 1 here - // means (7816-4, sec. 5.1.2): use BER-TLV, as opposed - // to "no indication provided". + // means (7816-4, sec. 5.1.2): use BER-TLV, as opposed + // to "no indication provided". // P1, P2: 7816-4, sec. 7.4.1: bit 1 of INS set => P1,P2 identifies // a file. And 0x3FFF identifies current DF - 0x3F, - 0xFF, + 0x3F, 0xFF, // 256, ); @@ -233,7 +232,6 @@ pub const GET_DATA: (u8, u8, u8, u8) = ( // } //} - // 6A, 80 incorrect parameter in command data field // 6A, 81 function not supported // 6A, 82 data object not found ( = NOT FOUND for files, e.g. certificate, e.g. after GET-DATA) @@ -420,13 +418,13 @@ pub const YUBICO_ATTESTATION_CERTIFICATE_FOR_9A: &'static [u8; 584] = &[ ]; // pub const YUBICO_DEFAULT_MANAGEMENT_KEY: &'static [u8; 24] = b"123456781234567812345678"; pub const YUBICO_DEFAULT_MANAGEMENT_KEY: &'static [u8; 24] = &[ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ]; // stolen from le yubico -pub const DISCOVERY_OBJECT: &'static [u8; 20] = b"~\x12O\x0b\xa0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00_/\x02@\x00"; +pub const DISCOVERY_OBJECT: &'static [u8; 20] = + b"~\x12O\x0b\xa0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00_/\x02@\x00"; // import secrets; secrets.token_bytes(16) pub const GUID: &'static [u8; 16] = b"\x0c\x92\xc9\x04\xd0\xdeL\xd9\xf6\xd1\xa2\x9fE3\xca\xeb"; diff --git a/src/container.rs b/src/container.rs index 5870edb..dfc3a0d 100644 --- a/src/container.rs +++ b/src/container.rs @@ -29,7 +29,6 @@ pub enum KeyReference { // 20x RetiredKeyManagement(RetiredIndex), - } impl From for u8 { @@ -85,7 +84,7 @@ impl From for ContainerId { use Container::*; Self(match container { CardCapabilityContainer => 0xDB00, - CardHolderUniqueIdentifier =>0x3000, + CardHolderUniqueIdentifier => 0x3000, X509CertificateFor9A => 0x0101, CardholderFingerprints => 0x6010, SecurityObject => 0x9000, @@ -194,64 +193,63 @@ impl TryFrom> for Container { } } +// #[derive(Clone, Copy, PartialEq)] +// pub struct CertInfo { +// compressed: bool, +// } - // #[derive(Clone, Copy, PartialEq)] - // pub struct CertInfo { - // compressed: bool, - // } +// impl From for u8 { +// fn from(cert_info: CertInfo) -> Self { +// cert_info.compressed as u8 +// } +// } - // impl From for u8 { - // fn from(cert_info: CertInfo) -> Self { - // cert_info.compressed as u8 - // } - // } +// impl Encodable for CertInfo { +// fn encoded_len(&self) -> der::Result { +// Length::from(1) +// } - // impl Encodable for CertInfo { - // fn encoded_len(&self) -> der::Result { - // Length::from(1) - // } +// fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { +// encoder.encode(der::Any::new(0x71, &[u8::from(self)])) +// } +// } - // fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - // encoder.encode(der::Any::new(0x71, &[u8::from(self)])) - // } - // } +// pub struct Certificate<'a> { +// // max bytes: 1856 +// certificate: &'a [u8], // tag: 0x70 +// // 1B +// cert_info: CertInfo, // tag: 0x71 +// // 38 +// // mscuid: ?, // tag: 0x72 +// error_detection_code: [u8; 0], // tag: 0xFE +// } - // pub struct Certificate<'a> { - // // max bytes: 1856 - // certificate: &'a [u8], // tag: 0x70 - // // 1B - // cert_info: CertInfo, // tag: 0x71 - // // 38 - // // mscuid: ?, // tag: 0x72 - // error_detection_code: [u8; 0], // tag: 0xFE - // } +// impl Encodable for CertInfo { +// fn encoded_len(&self) -> der::Result { +// Length::from(1) +// } - // impl Encodable for CertInfo { - // fn encoded_len(&self) -> der::Result { - // Length::from(1) - // } +// fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { +// encoder.encode(der::Any::new(0x71, &[u8::from(self)])) +// } +// } - // fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - // encoder.encode(der::Any::new(0x71, &[u8::from(self)])) - // } - // } +// #[derive(Encodable)] +// pub struct DiscoveryObject<'a> { +// #[tlv(tag = "0x4F")] +// piv_card_application_aid: &'a [u8; 11], // tag: 0x4F, max bytes = 12, +// #[tlv(tag = 0x5F2f)] +// pin_usage_policy: [u8; 2], // tag: 0x5F2F, max bytes = 2, +// } - // #[derive(Encodable)] - // pub struct DiscoveryObject<'a> { - // #[tlv(tag = "0x4F")] - // piv_card_application_aid: &'a [u8; 11], // tag: 0x4F, max bytes = 12, - // #[tlv(tag = 0x5F2f)] - // pin_usage_policy: [u8; 2], // tag: 0x5F2F, max bytes = 2, - // } +// impl Encodable for CertInfo { +// fn encoded_len(&self) -> der::Result { +// Length::from(1) +// } - // impl Encodable for CertInfo { - // fn encoded_len(&self) -> der::Result { - // Length::from(1) - // } - - // fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - // encoder.encode(der::Any::new(0x71, &[u8::from(self)])) - // } - // } +// fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { +// encoder.encode(der::Any::new(0x71, &[u8::from(self)])) +// } +// } // } diff --git a/src/dispatch.rs b/src/dispatch.rs index 77c6d13..a2a09ed 100644 --- a/src/dispatch.rs +++ b/src/dispatch.rs @@ -1,20 +1,27 @@ use crate::{Authenticator, /*constants::PIV_AID,*/ Result}; -use apdu_dispatch::{app::App, command, Command, response}; +use apdu_dispatch::{app::App, command, response, Command}; use trussed::client; #[cfg(feature = "apdu-dispatch")] -impl App<{command::SIZE}, {response::SIZE}> for Authenticator +impl App<{ command::SIZE }, { response::SIZE }> for Authenticator where - T: client::Client + client::Ed255 + client::Tdes + T: client::Client + client::Ed255 + client::Tdes, { fn select(&mut self, apdu: &Command, reply: &mut response::Data) -> Result { self.select(apdu, reply) } - fn deselect(&mut self) { self.deselect() } + fn deselect(&mut self) { + self.deselect() + } - fn call(&mut self, _: iso7816::Interface, apdu: &Command, reply: &mut response::Data) -> Result { + fn call( + &mut self, + _: iso7816::Interface, + apdu: &Command, + reply: &mut response::Data, + ) -> Result { self.respond(apdu, reply) } } diff --git a/src/lib.rs b/src/lib.rs index 373faf7..b2ded31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,14 +11,13 @@ pub mod commands; pub use commands::Command; pub mod constants; pub mod container; +pub mod derp; #[cfg(feature = "apdu-dispatch")] mod dispatch; -pub mod state; -pub mod derp; pub mod piv_types; +pub mod state; pub use piv_types::{Pin, Puk}; - use core::convert::TryInto; use flexiber::EncodableHeapless; @@ -35,14 +34,12 @@ pub type Result = iso7816::Result<()>; /// The `C` parameter is necessary, as PIV includes command sequences, /// where we need to store the previous command, so we need to know how /// much space to allocate. -pub struct Authenticator -{ +pub struct Authenticator { state: state::State, trussed: T, } -impl iso7816::App for Authenticator -{ +impl iso7816::App for Authenticator { fn aid(&self) -> iso7816::Aid { crate::constants::PIV_AID } @@ -52,11 +49,7 @@ impl Authenticator where T: client::Client + client::Ed255 + client::Tdes, { - pub fn new( - trussed: T, - ) - -> Self - { + pub fn new(trussed: T) -> Self { // seems like RefCell is not the right thing, we want something like `Rc` instead, // which can be cloned and injected into other parts of the App that use Trussed. // let trussed = RefCell::new(trussed); @@ -69,24 +62,20 @@ where // TODO: we'd like to listen on multiple AIDs. // The way apdu-dispatch currently works, this would deselect, resetting security indicators. - pub fn deselect(&mut self) { - } + pub fn deselect(&mut self) {} - pub fn select(&mut self, _apdu: &iso7816::Command, reply: &mut Data) -> Result - { + pub fn select( + &mut self, + _apdu: &iso7816::Command, + reply: &mut Data, + ) -> Result { use piv_types::Algorithms::*; info_now!("selecting PIV maybe"); let application_property_template = piv_types::ApplicationPropertyTemplate::default() .with_application_label(APPLICATION_LABEL) .with_application_url(APPLICATION_URL) - .with_supported_cryptographic_algorithms(&[ - Tdes, - Aes256, - P256, - Ed255, - X255, - ]); + .with_supported_cryptographic_algorithms(&[Tdes, Aes256, P256, Ed255, X255]); application_property_template .encode_to_heapless_vec(reply) @@ -95,8 +84,11 @@ where Ok(()) } - pub fn respond(&mut self, command: &iso7816::Command, reply: &mut Data) -> Result - { + pub fn respond( + &mut self, + command: &iso7816::Command, + reply: &mut Data, + ) -> Result { // need to implement Debug on iso7816::Command // info_now!("PIV responding to {:?}", command); let last_or_only = command.class().chain().last_or_only(); @@ -105,7 +97,10 @@ where let entire_command = match self.state.runtime.chained_command.as_mut() { Some(command_so_far) => { // TODO: make sure the header matches, e.g. '00 DB 3F FF' - command_so_far.data_mut().extend_from_slice(command.data()).unwrap(); + command_so_far + .data_mut() + .extend_from_slice(command.data()) + .unwrap(); if last_or_only { let entire_command = command_so_far.clone(); @@ -142,7 +137,6 @@ where // maybe reserve this for the case VerifyLogin::PivPin? pub fn login(&mut self, login: commands::VerifyLogin) -> Result { if let commands::VerifyLogin::PivPin(pin) = login { - // the actual PIN verification let mut persistent_state = self.state.persistent(&mut self.trussed); @@ -154,7 +148,6 @@ where persistent_state.reset_consecutive_pin_mismatches(); self.state.runtime.app_security_status.pin_verified = true; Ok(()) - } else { let remaining = persistent_state.increment_consecutive_pin_mismatches(); // should we logout here? @@ -181,9 +174,12 @@ where return Err(Status::FunctionNotSupported); } if self.state.runtime.app_security_status.pin_verified { - return Ok(()) + return Ok(()); } else { - let retries = self.state.persistent(&mut self.trussed).remaining_pin_retries(); + let retries = self + .state + .persistent(&mut self.trussed) + .remaining_pin_retries(); return Err(Status::RemainingRetries(retries)); } } @@ -343,9 +339,11 @@ where // - 9000, 61XX for success // - 6982 security status // - 6A80, 6A86 for data, P1/P2 issue - pub fn general_authenticate(&mut self, command: &iso7816::Command, reply: &mut Data) -> Result - { - + pub fn general_authenticate( + &mut self, + command: &iso7816::Command, + reply: &mut Data, + ) -> Result { // For "SSH", we need implement A.4.2 in SP-800-73-4 Part 2, ECDSA signatures // // ins = 87 = general authenticate @@ -432,7 +430,13 @@ where } info_now!("looking for keyreference"); - let key_handle = match self.state.persistent(&mut self.trussed).state.keys.authentication_key { + let key_handle = match self + .state + .persistent(&mut self.trussed) + .state + .keys + .authentication_key + { Some(key) => key, None => return Err(Status::KeyReferenceNotFound), }; @@ -442,8 +446,8 @@ where .map_err(|_error| { // NoSuchKey debug_now!("{:?}", &_error); - Status::UnspecifiedNonpersistentExecutionError } - )? + Status::UnspecifiedNonpersistentExecutionError + })? .signature; piv_types::DynamicAuthenticationTemplate::with_response(&signature) @@ -454,8 +458,12 @@ where Ok(()) } - pub fn request_for_challenge(&mut self, command: &iso7816::Command, remaining_data: &[u8], reply: &mut Data) -> Result - { + pub fn request_for_challenge( + &mut self, + command: &iso7816::Command, + remaining_data: &[u8], + reply: &mut Data, + ) -> Result { // - data is of the form // 00 87 03 9B 16 7C 14 80 08 99 6D 71 40 E7 05 DF 7F 81 08 6E EF 9C 02 00 69 73 E8 // - remaining data contains 81 08 @@ -474,9 +482,12 @@ where use state::{AuthenticateManagement, CommandCache}; let our_challenge = match self.state.runtime.command_cache { - Some(CommandCache::AuthenticateManagement(AuthenticateManagement { challenge } )) - => challenge, - _ => { return Err(Status::InstructionNotSupportedOrInvalid); } + Some(CommandCache::AuthenticateManagement(AuthenticateManagement { challenge })) => { + challenge + } + _ => { + return Err(Status::InstructionNotSupportedOrInvalid); + } }; // no retries ;) self.state.runtime.command_cache = None; @@ -495,7 +506,12 @@ where return Err(Status::IncorrectDataParameter); } - let key = self.state.persistent(&mut self.trussed).state.keys.management_key; + let key = self + .state + .persistent(&mut self.trussed) + .state + .keys + .management_key; let encrypted_challenge = syscall!(self.trussed.encrypt_tdes(key, challenge)).ciphertext; @@ -506,8 +522,12 @@ where Ok(()) } - pub fn request_for_witness(&mut self, command: &iso7816::Command, remaining_data: &[u8], reply: &mut Data) -> Result - { + pub fn request_for_witness( + &mut self, + command: &iso7816::Command, + remaining_data: &[u8], + reply: &mut Data, + ) -> Result { // invariants: parsed data was '7C L1 80 00' + remaining_data if command.p1 != 0x03 || command.p2 != 0x9b { @@ -518,11 +538,19 @@ where return Err(Status::IncorrectDataParameter); } - let key = self.state.persistent(&mut self.trussed).state.keys.management_key; + let key = self + .state + .persistent(&mut self.trussed) + .state + .keys + .management_key; let challenge = syscall!(self.trussed.random_bytes(8)).bytes; - let command_cache = state::AuthenticateManagement { challenge: challenge[..].try_into().unwrap() }; - self.state.runtime.command_cache = Some(state::CommandCache::AuthenticateManagement(command_cache)); + let command_cache = state::AuthenticateManagement { + challenge: challenge[..].try_into().unwrap(), + }; + self.state.runtime.command_cache = + Some(state::CommandCache::AuthenticateManagement(command_cache)); let encrypted_challenge = syscall!(self.trussed.encrypt_tdes(key, &challenge)).ciphertext; @@ -531,7 +559,6 @@ where .unwrap(); Ok(()) - } //fn change_reference_data(&mut self, command: &Command) -> Result { @@ -617,7 +644,6 @@ where // return Ok(()); // } - // Err(Status::KeyReferenceNotFound) //} @@ -682,8 +708,11 @@ where // } //} - pub fn generate_asymmetric_keypair(&mut self, command: &iso7816::Command, reply: &mut Data) -> Result - { + pub fn generate_asymmetric_keypair( + &mut self, + command: &iso7816::Command, + reply: &mut Data, + ) -> Result { if !self.state.runtime.app_security_status.management_verified { return Err(Status::SecurityStatusNotSatisfied); } @@ -721,23 +750,25 @@ where // TODO: iterate on this, don't expect tags.. let input = derp::Input::from(&command.data()); // let (mechanism, parameter) = input.read_all(derp::Error::Read, |input| { - let (mechanism, _pin_policy, _touch_policy) = input.read_all(derp::Error::Read, |input| { - derp::nested(input, 0xac, |input| { - let mechanism = derp::expect_tag_and_get_value(input, 0x80)?; - // let parameter = derp::expect_tag_and_get_value(input, 0x81)?; - let pin_policy = derp::expect_tag_and_get_value(input, 0xaa)?; - let touch_policy = derp::expect_tag_and_get_value(input, 0xab)?; - // Ok((mechanism.as_slice_less_safe(), parameter.as_slice_less_safe())) - Ok(( - mechanism.as_slice_less_safe(), - pin_policy.as_slice_less_safe(), - touch_policy.as_slice_less_safe(), - )) + let (mechanism, _pin_policy, _touch_policy) = input + .read_all(derp::Error::Read, |input| { + derp::nested(input, 0xac, |input| { + let mechanism = derp::expect_tag_and_get_value(input, 0x80)?; + // let parameter = derp::expect_tag_and_get_value(input, 0x81)?; + let pin_policy = derp::expect_tag_and_get_value(input, 0xaa)?; + let touch_policy = derp::expect_tag_and_get_value(input, 0xab)?; + // Ok((mechanism.as_slice_less_safe(), parameter.as_slice_less_safe())) + Ok(( + mechanism.as_slice_less_safe(), + pin_policy.as_slice_less_safe(), + touch_policy.as_slice_less_safe(), + )) + }) }) - }).map_err(|_e| { + .map_err(|_e| { info_now!("error parsing GenerateAsymmetricKeypair: {:?}", &_e); Status::IncorrectDataParameter - })?; + })?; // if mechanism != &[0x11] { // HA! patch in Ed255 @@ -747,16 +778,22 @@ where // ble policy - if let Some(key) = self.state.persistent(&mut self.trussed).state.keys.authentication_key { + if let Some(key) = self + .state + .persistent(&mut self.trussed) + .state + .keys + .authentication_key + { syscall!(self.trussed.delete(key)); } // let key = syscall!(self.trussed.generate_p256_private_key( // let key = syscall!(self.trussed.generate_p256_private_key( - let key = syscall!(self.trussed.generate_ed255_private_key( - trussed::types::Location::Internal, - )).key; - + let key = syscall!(self + .trussed + .generate_ed255_private_key(trussed::types::Location::Internal,)) + .key; // // TEMP // let mechanism = trussed::types::Mechanism::P256Prehashed; @@ -777,21 +814,26 @@ where // .signature; // blocking::dbg!(&signature); - self.state.persistent(&mut self.trussed).state.keys.authentication_key = Some(key); + self.state + .persistent(&mut self.trussed) + .state + .keys + .authentication_key = Some(key); self.state.persistent(&mut self.trussed).save(); // let public_key = syscall!(self.trussed.derive_p256_public_key( - let public_key = syscall!(self.trussed.derive_ed255_public_key( - key, - trussed::types::Location::Volatile, - )).key; + let public_key = syscall!(self + .trussed + .derive_ed255_public_key(key, trussed::types::Location::Volatile,)) + .key; let serialized_public_key = syscall!(self.trussed.serialize_key( // trussed::types::Mechanism::P256, trussed::types::Mechanism::Ed255, public_key.clone(), trussed::types::KeySerialization::Raw, - )).serialized_key; + )) + .serialized_key; // info_now!("supposed SEC1 pubkey, len {}: {:X?}", serialized_public_key.len(), &serialized_public_key); @@ -800,7 +842,9 @@ where let l2 = 32; let l1 = l2 + 2; - reply.extend_from_slice(&[0x7f, 0x49, l1, 0x86, l2]).unwrap(); + reply + .extend_from_slice(&[0x7f, 0x49, l1, 0x86, l2]) + .unwrap(); reply.extend_from_slice(&serialized_public_key).unwrap(); Ok(()) @@ -827,15 +871,17 @@ where // let input = derp::Input::from(&command.data()); - let (data_object, data) = input.read_all(derp::Error::Read, |input| { - let data_object = derp::expect_tag_and_get_value(input, 0x5c)?; - let data = derp::expect_tag_and_get_value(input, 0x53)?; - Ok((data_object.as_slice_less_safe(), data.as_slice_less_safe())) - // }).unwrap(); - }).map_err(|_e| { + let (data_object, data) = input + .read_all(derp::Error::Read, |input| { + let data_object = derp::expect_tag_and_get_value(input, 0x5c)?; + let data = derp::expect_tag_and_get_value(input, 0x53)?; + Ok((data_object.as_slice_less_safe(), data.as_slice_less_safe())) + // }).unwrap(); + }) + .map_err(|_e| { info_now!("error parsing PutData: {:?}", &_e); Status::IncorrectDataParameter - })?; + })?; // info_now!("PutData in {:?}: {:?}", data_object, data); @@ -858,7 +904,8 @@ where trussed::types::PathBuf::from(b"printed-information"), trussed::types::Message::from_slice(data).unwrap(), None, - )).map_err(|_| Status::NotEnoughMemory)?; + )) + .map_err(|_| Status::NotEnoughMemory)?; return Ok(()); } @@ -883,7 +930,8 @@ where trussed::types::PathBuf::from(b"authentication-key.x5c"), trussed::types::Message::from_slice(data).unwrap(), None, - )).map_err(|_| Status::NotEnoughMemory)?; + )) + .map_err(|_| Status::NotEnoughMemory)?; return Ok(Default::default()); } @@ -891,18 +939,19 @@ where Err(Status::IncorrectDataParameter) } + // match container { + // containers::Container::CardHolderUniqueIdentifier => + // piv_types::CardHolderUniqueIdentifier::default() + // .encode + // _ => todo!(), + // } + // todo!(); - // match container { - // containers::Container::CardHolderUniqueIdentifier => - // piv_types::CardHolderUniqueIdentifier::default() - // .encode - // _ => todo!(), - // } - // todo!(); - - fn get_data(&mut self, container: container::Container, reply: &mut Data) -> Result - { - + fn get_data( + &mut self, + container: container::Container, + reply: &mut Data, + ) -> Result { // TODO: check security status, else return Status::SecurityStatusNotSatisfied // Table 3, Part 1, SP 800-73-4 @@ -916,7 +965,7 @@ where } Container::BiometricInformationTemplatesGroupTemplate => { - return Err(Status::InstructionNotSupportedOrInvalid) + return Err(Status::InstructionNotSupportedOrInvalid); // todo!("biometric information template"), } @@ -967,26 +1016,27 @@ where // let data = Data::from_slice(YUBICO_ATTESTATION_CERTIFICATE).unwrap(); // reply.extend_from_slice(&data).ok(); // } - _ => return Err(Status::NotFound), } Ok(()) } - pub fn yubico_piv_extension(&mut self, command: &iso7816::Command, instruction: YubicoPivExtension, reply: &mut Data) -> Result - { + pub fn yubico_piv_extension( + &mut self, + command: &iso7816::Command, + instruction: YubicoPivExtension, + reply: &mut Data, + ) -> Result { info_now!("yubico extension: {:?}", &instruction); match instruction { YubicoPivExtension::GetSerial => { // make up a 4-byte serial - reply.extend_from_slice( - &[0x00, 0x52, 0xf7, 0x43]).ok(); + reply.extend_from_slice(&[0x00, 0x52, 0xf7, 0x43]).ok(); } YubicoPivExtension::GetVersion => { // make up a version, be >= 5.0.0 - reply.extend_from_slice( - &[0x06, 0x06, 0x06]).ok(); + reply.extend_from_slice(&[0x06, 0x06, 0x06]).ok(); } YubicoPivExtension::Attest => { @@ -997,10 +1047,11 @@ where let slot = command.p1; if slot == 0x9a { - reply.extend_from_slice(YUBICO_ATTESTATION_CERTIFICATE_FOR_9A).ok(); + reply + .extend_from_slice(YUBICO_ATTESTATION_CERTIFICATE_FOR_9A) + .ok(); } else { - - return Err(Status::FunctionNotSupported) + return Err(Status::FunctionNotSupported); } } @@ -1012,7 +1063,9 @@ where // TODO: find out what all needs resetting :) self.state.persistent(&mut self.trussed).reset_pin(); self.state.persistent(&mut self.trussed).reset_puk(); - self.state.persistent(&mut self.trussed).reset_management_key(); + self.state + .persistent(&mut self.trussed) + .reset_management_key(); self.state.runtime.app_security_status.pin_verified = false; self.state.runtime.app_security_status.puk_verified = false; self.state.runtime.app_security_status.management_verified = false; @@ -1020,13 +1073,14 @@ where try_syscall!(self.trussed.remove_file( trussed::types::Location::Internal, trussed::types::PathBuf::from(b"printed-information"), - )).ok(); + )) + .ok(); try_syscall!(self.trussed.remove_file( trussed::types::Location::Internal, trussed::types::PathBuf::from(b"authentication-key.x5c"), - )).ok(); - + )) + .ok(); } YubicoPivExtension::SetManagementKey => { @@ -1055,15 +1109,13 @@ where return Err(Status::IncorrectDataParameter); } let new_management_key: [u8; 24] = new_management_key.try_into().unwrap(); - self.state.persistent(&mut self.trussed).set_management_key(&new_management_key); - + self.state + .persistent(&mut self.trussed) + .set_management_key(&new_management_key); } _ => return Err(Status::FunctionNotSupported), } Ok(()) } - } - - diff --git a/src/piv_types.rs b/src/piv_types.rs index 11194a9..006da27 100644 --- a/src/piv_types.rs +++ b/src/piv_types.rs @@ -34,7 +34,7 @@ impl TryFrom<&[u8]> for Pin { Err(()) } } - _ => Err(()) + _ => Err(()), } } } @@ -103,45 +103,53 @@ impl Encodable for CryptographicAlgorithmTemplate<'_> { // '80' let cryptographic_algorithm_identifier_tag = flexiber::Tag::context(0); for alg in self.algorithms.iter() { - encoder.encode(&flexiber::TaggedSlice::from(cryptographic_algorithm_identifier_tag, &[*alg as _])?)?; + encoder.encode(&flexiber::TaggedSlice::from( + cryptographic_algorithm_identifier_tag, + &[*alg as _], + )?)?; } // '06' let object_identifier_tag = flexiber::Tag::universal(6); - encoder.encode(&flexiber::TaggedSlice::from(object_identifier_tag, &[0x00])?) + encoder.encode(&flexiber::TaggedSlice::from( + object_identifier_tag, + &[0x00], + )?) } } #[derive(Clone, Copy, Encodable, Eq, PartialEq)] pub struct CoexistentTagAllocationAuthorityTemplate<'l> { - #[tlv(application, primitive, number = "0xF")] // = 0x4F + #[tlv(application, primitive, number = "0xF")] // = 0x4F pub application_identifier: &'l [u8], } impl Default for CoexistentTagAllocationAuthorityTemplate<'static> { fn default() -> Self { - Self { application_identifier: crate::constants::NIST_RID } + Self { + application_identifier: crate::constants::NIST_RID, + } } } #[derive(Clone, Copy, Encodable, Eq, PartialEq)] -#[tlv(application, constructed, number = "0x1")] // = 0x61 +#[tlv(application, constructed, number = "0x1")] // = 0x61 pub struct ApplicationPropertyTemplate<'l> { /// Application identifier of application: PIX (without RID, with version) - #[tlv(application, primitive, number = "0xF")] // = 0x4F - aid: &'l[u8], + #[tlv(application, primitive, number = "0xF")] // = 0x4F + aid: &'l [u8], /// Text describing the application; e.g., for use on a man-machine interface. - #[tlv(application, primitive, number = "0x10")] // = 0x50 + #[tlv(application, primitive, number = "0x10")] // = 0x50 application_label: &'l [u8], /// Reference to the specification describing the application. - #[tlv(application, primitive, number = "0x50")] // = 0x5F50 + #[tlv(application, primitive, number = "0x50")] // = 0x5F50 application_url: &'l [u8], - #[tlv(context, constructed, number = "0xC")] // = 0xAC + #[tlv(context, constructed, number = "0xC")] // = 0xAC supported_cryptographic_algorithms: CryptographicAlgorithmTemplate<'l>, - #[tlv(application, constructed, number = "0x19")] // = 0x79 + #[tlv(application, constructed, number = "0x19")] // = 0x79 coexistent_tag_allocation_authority: CoexistentTagAllocationAuthorityTemplate<'l>, } @@ -158,7 +166,6 @@ impl Default for ApplicationPropertyTemplate<'static> { } impl<'a> ApplicationPropertyTemplate<'a> { - pub const fn with_application_label(self, application_label: &'a [u8]) -> Self { Self { aid: self.aid, @@ -179,18 +186,22 @@ impl<'a> ApplicationPropertyTemplate<'a> { } } - pub const fn with_supported_cryptographic_algorithms(self, supported_cryptographic_algorithms: &'a [Algorithms]) -> Self { + pub const fn with_supported_cryptographic_algorithms( + self, + supported_cryptographic_algorithms: &'a [Algorithms], + ) -> Self { Self { aid: self.aid, application_label: self.application_label, application_url: self.application_url, - supported_cryptographic_algorithms: CryptographicAlgorithmTemplate { algorithms: supported_cryptographic_algorithms}, + supported_cryptographic_algorithms: CryptographicAlgorithmTemplate { + algorithms: supported_cryptographic_algorithms, + }, coexistent_tag_allocation_authority: self.coexistent_tag_allocation_authority, } } } - /// TODO: This should be an enum of sorts, maybe. /// /// The data objects that appear in the dynamic authentication template (tag '7C') in the data field @@ -201,40 +212,52 @@ impl<'a> ApplicationPropertyTemplate<'a> { /// - '80 00' Returns '80 TL ' (as per definition) /// - '81 00' Returns '81 TL ' (as per external authenticate example) #[derive(Clone, Copy, Default, Encodable, Eq, PartialEq)] -#[tlv(application, constructed, number = "0x1C")] // = 0x7C +#[tlv(application, constructed, number = "0x1C")] // = 0x7C pub struct DynamicAuthenticationTemplate<'l> { /// The Witness (tag '80') contains encrypted data (unrevealed fact). /// This data is decrypted by the card. #[tlv(simple = "0x80")] - witness: Option<&'l[u8]>, + witness: Option<&'l [u8]>, /// The Challenge (tag '81') contains clear data (byte sequence), /// which is encrypted by the card. #[tlv(simple = "0x81")] - challenge: Option<&'l[u8]>, + challenge: Option<&'l [u8]>, /// The Response (tag '82') contains either the decrypted data from tag '80' /// or the encrypted data from tag '81'. #[tlv(simple = "0x82")] - response: Option<&'l[u8]>, + response: Option<&'l [u8]>, /// Not documented in SP-800-73-4 #[tlv(simple = "0x85")] - exponentiation: Option<&'l[u8]>, + exponentiation: Option<&'l [u8]>, } impl<'a> DynamicAuthenticationTemplate<'a> { pub fn with_challenge(challenge: &'a [u8]) -> Self { - Self { challenge: Some(challenge), ..Default::default() } + Self { + challenge: Some(challenge), + ..Default::default() + } } pub fn with_exponentiation(exponentiation: &'a [u8]) -> Self { - Self { exponentiation: Some(exponentiation), ..Default::default() } + Self { + exponentiation: Some(exponentiation), + ..Default::default() + } } pub fn with_response(response: &'a [u8]) -> Self { - Self { response: Some(response), ..Default::default() } + Self { + response: Some(response), + ..Default::default() + } } pub fn with_witness(witness: &'a [u8]) -> Self { - Self { witness: Some(witness), ..Default::default() } + Self { + witness: Some(witness), + ..Default::default() + } } } @@ -246,7 +269,7 @@ impl<'a> DynamicAuthenticationTemplate<'a> { // pivy: https://git.io/JfzBo // https://www.idmanagement.gov/wp-content/uploads/sites/1171/uploads/TIG_SCEPACS_v2.3.pdf #[derive(Clone, Copy, Encodable, Eq, PartialEq)] -#[tlv(application, primitive, number = "0x13")] // = 0x53 +#[tlv(application, primitive, number = "0x13")] // = 0x53 pub struct CardHolderUniqueIdentifier<'l> { #[tlv(simple = "0x30")] // pivy: 26B, TIG: 25B @@ -269,7 +292,6 @@ pub struct CardHolderUniqueIdentifier<'l> { // #[tlv(simple = "0x36")] // // 16B, like guid // cardholder_uuid: Option<&'l [u8]>, - #[tlv(simple = "0x3E")] issuer_asymmetric_signature: &'l [u8], @@ -384,4 +406,3 @@ pub struct DiscoveryObject { #[tlv(slice, application, number = "0x2f")] pin_usage_policy: [u8; 2], // tag: 0x5F2F, max bytes = 2, } - diff --git a/src/state.rs b/src/state.rs index 4ca3974..198e268 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,10 +1,9 @@ use core::convert::{TryFrom, TryInto}; use trussed::{ - block, + block, syscall, try_syscall, + types::{KeyId, Location, PathBuf}, Client as TrussedClient, - syscall, try_syscall, - types::{KeyId, PathBuf, Location}, }; use crate::constants::*; @@ -37,7 +36,10 @@ pub struct Slot { impl Default for Slot { fn default() -> Self { - Self { key: None, pin_policy: PinPolicy::Once, /*touch_policy: TouchPolicy::Never*/ } + Self { + key: None, + pin_policy: PinPolicy::Once, /*touch_policy: TouchPolicy::Never*/ + } } } @@ -46,10 +48,15 @@ impl Slot { use SlotName::*; match name { // Management => Slot { pin_policy: PinPolicy::Never, ..Default::default() }, - Signature => Slot { pin_policy: PinPolicy::Always, ..Default::default() }, - Pinless => Slot { pin_policy: PinPolicy::Never, ..Default::default() }, + Signature => Slot { + pin_policy: PinPolicy::Always, + ..Default::default() + }, + Pinless => Slot { + pin_policy: PinPolicy::Never, + ..Default::default() + }, _ => Default::default(), - } } } @@ -68,9 +75,9 @@ impl core::convert::TryFrom for RetiredSlotIndex { } pub enum SlotName { Identity, - Management, // Personalization? Administration? + Management, // Personalization? Administration? Signature, - Decryption, // Management after all? + Decryption, // Management after all? Pinless, Retired(RetiredSlotIndex), Attestation, @@ -78,8 +85,8 @@ pub enum SlotName { impl SlotName { pub fn default_pin_policy(&self) -> PinPolicy { - use SlotName::*; use PinPolicy::*; + use SlotName::*; match *self { Signature => Always, Pinless | Management | Attestation => Never, @@ -88,7 +95,10 @@ impl SlotName { } pub fn default_slot(&self) -> Slot { - Slot { key: None, pin_policy: self.default_pin_policy() } + Slot { + key: None, + pin_policy: self.default_pin_policy(), + } } pub fn reference(&self) -> u8 { @@ -137,7 +147,6 @@ pub struct Keys { pub retired_keys: [Option; 20], } - #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct State { pub runtime: Runtime, @@ -156,8 +165,8 @@ impl State { // TODO: it is really not good to overwrite user data on failure to decode old state. // To fix this, need a flag to detect if we're "fresh", and/or initialize state in factory. pub fn persistent<'t, T>(&mut self, trussed: &'t mut T) -> Persistent<'t, T> - where T: TrussedClient - + trussed::client::Tdes + where + T: TrussedClient + trussed::client::Tdes, { Persistent::load_or_initialize(trussed) } @@ -237,7 +246,6 @@ impl AsRef for Persistent<'_, T> { pub struct Runtime { // aid: Option< // consecutive_pin_mismatches: u8, - pub global_security_status: GlobalSecurityStatus, // pub currently_selected_application: SelectableAid, pub app_security_status: AppSecurityStatus, @@ -299,8 +307,7 @@ pub struct Runtime { // } #[derive(Clone, Debug, Default, Eq, PartialEq)] -pub struct GlobalSecurityStatus { -} +pub struct GlobalSecurityStatus {} #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum SecurityStatus { @@ -328,10 +335,8 @@ pub enum CommandCache { AuthenticateManagement(AuthenticateManagement), } - #[derive(Clone, Debug, Eq, PartialEq)] -pub struct GetData { -} +pub struct GetData {} #[derive(Clone, Debug, Eq, PartialEq)] pub struct AuthenticateManagement { @@ -342,7 +347,6 @@ impl<'t, T> Persistent<'t, T> where T: TrussedClient + trussed::client::Tdes, { - pub const PIN_RETRIES_DEFAULT: u8 = 3; // hmm...! pub const PUK_RETRIES_DEFAULT: u8 = 5; @@ -444,10 +448,10 @@ where pub fn set_management_key(&mut self, management_key: &[u8; 24]) { // let new_management_key = syscall!(self.trussed.unsafe_inject_tdes_key( - let new_management_key = syscall!(self.trussed.unsafe_inject_shared_key( - management_key, - trussed::types::Location::Internal, - )).key; + let new_management_key = syscall!(self + .trussed + .unsafe_inject_shared_key(management_key, trussed::types::Location::Internal,)) + .key; let old_management_key = self.state.keys.management_key; self.state.keys.management_key = new_management_key; self.save(); @@ -459,7 +463,8 @@ where let management_key = syscall!(trussed.unsafe_inject_shared_key( YUBICO_DEFAULT_MANAGEMENT_KEY, trussed::types::Location::Internal, - )).key; + )) + .key; let mut guid: [u8; 16] = syscall!(trussed.random_bytes(16)) .bytes @@ -489,21 +494,21 @@ where puk: Puk::try_from(Self::DEFAULT_PUK).unwrap(), timestamp: 0, guid, - } + }, }; state.save(); state } pub fn load(trussed: &'t mut T) -> Result { - let data = block!(trussed.read_file( - Location::Internal, - PathBuf::from(Self::FILENAME), - ).unwrap() - ).map_err(|e| { + let data = block!(trussed + .read_file(Location::Internal, PathBuf::from(Self::FILENAME),) + .unwrap()) + .map_err(|e| { info!("loading error: {:?}", &e); drop(e) - })?.data; + })? + .data; let previous_state: PersistentState = trussed::cbor_deserialize(&data).map_err(|e| { info!("cbor deser error: {:?}", e); @@ -511,12 +516,16 @@ where drop(e) })?; // horrible deser bug to forget Ok here :) - Ok(Self { trussed, state: previous_state }) + Ok(Self { + trussed, + state: previous_state, + }) } pub fn load_or_initialize(trussed: &'t mut T) -> Self { // todo: can't seem to combine load + initialize without code repetition - let data = try_syscall!(trussed.read_file(Location::Internal, PathBuf::from(Self::FILENAME))); + let data = + try_syscall!(trussed.read_file(Location::Internal, PathBuf::from(Self::FILENAME))); if let Ok(data) = data { let previous_state = trussed::cbor_deserialize(&data.data).map_err(|e| { info!("cbor deser error: {:?}", e); @@ -524,8 +533,8 @@ where drop(e) }); if let Ok(state) = previous_state { - // horrible deser bug to forget Ok here :) - return Self { trussed, state } + // horrible deser bug to forget Ok here :) + return Self { trussed, state }; } } @@ -548,6 +557,4 @@ where self.save(); self.state.timestamp } - } - diff --git a/tests/get_data.rs b/tests/get_data.rs index cbdd046..8e669a3 100644 --- a/tests/get_data.rs +++ b/tests/get_data.rs @@ -9,7 +9,7 @@ fn get_data() { // let cmd = cmd!("00 47 00 9A 0B AC 09 80 01 11 AA 01 02 AB 01 02"); // let cmd = cmd!("00 f8 00 00"); -// // without PIN, no key generation + // // without PIN, no key generation setup::piv(|piv| { // ykGetSerial diff --git a/tests/setup/mod.rs b/tests/setup/mod.rs index 293c9cf..c53b0dd 100644 --- a/tests/setup/mod.rs +++ b/tests/setup/mod.rs @@ -1,5 +1,6 @@ -trussed::platform!(Platform, - R: rand_core::OsRng,//chacha20::ChaCha8Rng, +trussed::platform!( + Platform, + R: rand_core::OsRng, //chacha20::ChaCha8Rng, S: store::Store, UI: ui::UserInterface, ); @@ -8,15 +9,21 @@ const COMMAND_SIZE: usize = 3072; #[macro_export] macro_rules! cmd { - ($tt:tt) => { iso7816::Command::<3072>::try_from(&hex_literal::hex!($tt)).unwrap() } + ($tt:tt) => { + iso7816::Command::<3072>::try_from(&hex_literal::hex!($tt)).unwrap() + }; } pub type Piv<'service> = piv_authenticator::Authenticator< - trussed::ClientImplementation<&'service mut trussed::service::Service>, COMMAND_SIZE>; + trussed::ClientImplementation<&'service mut trussed::service::Service>, + COMMAND_SIZE, +>; pub fn piv(test: impl FnOnce(&mut Piv) -> R) -> R { use trussed::Interchange as _; - unsafe { trussed::pipe::TrussedInterchange::reset_claims(); } + unsafe { + trussed::pipe::TrussedInterchange::reset_claims(); + } let trussed_platform = init_platform(); let mut trussed_service = trussed::service::Service::new(trussed_platform); let client_id = "test"; @@ -31,7 +38,7 @@ pub fn init_platform() -> Platform { store::InternalStorage::new(), store::ExternalStorage::new(), store::VolatileStorage::new(), - ); + ); let ui = ui::UserInterface::new(); let platform = Platform::new(rng, store, ui); @@ -41,28 +48,48 @@ pub fn init_platform() -> Platform { pub mod ui { use trussed::platform::{consent, reboot, ui}; - pub struct UserInterface { start_time: std::time::Instant } + pub struct UserInterface { + start_time: std::time::Instant, + } - impl UserInterface { pub fn new() -> Self { Self { start_time: std::time::Instant::now() } } } + impl UserInterface { + pub fn new() -> Self { + Self { + start_time: std::time::Instant::now(), + } + } + } impl trussed::platform::UserInterface for UserInterface { - fn check_user_presence(&mut self) -> consent::Level { consent::Level::Normal } + fn check_user_presence(&mut self) -> consent::Level { + consent::Level::Normal + } fn set_status(&mut self, _status: ui::Status) {} fn refresh(&mut self) {} - fn uptime(&mut self) -> core::time::Duration { self.start_time.elapsed() } - fn reboot(&mut self, _to: reboot::To) -> ! { loop { continue; } } + fn uptime(&mut self) -> core::time::Duration { + self.start_time.elapsed() + } + fn reboot(&mut self, _to: reboot::To) -> ! { + loop { + continue; + } + } } } pub mod store { - use littlefs2::{const_ram_storage, consts, fs::{Allocation, Filesystem}}; + use littlefs2::{ + const_ram_storage, consts, + fs::{Allocation, Filesystem}, + }; use trussed::types::{LfsResult, LfsStorage}; const_ram_storage!(InternalStorage, 8192); const_ram_storage!(ExternalStorage, 8192); const_ram_storage!(VolatileStorage, 8192); - trussed::store!(Store, + trussed::store!( + Store, Internal: InternalStorage, External: ExternalStorage, Volatile: VolatileStorage