From ef2ba477131e376702629acb6ebf6e90ea2c754c Mon Sep 17 00:00:00 2001 From: Nicolas Stalder Date: Sat, 16 May 2020 03:04:43 +0200 Subject: [PATCH] Soo close to setup. Need some CCID fixes --- Cargo.toml | 1 + src/derp.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ src/pipe.rs | 6 ++-- 4 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 src/derp.rs diff --git a/Cargo.toml b/Cargo.toml index c9a8b7d..6316a13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ heapless-bytes = { git = "https://github.com/ycrypto/heapless-bytes", branch = " # heapless-bytes = { path = "../../../heapless-bytes" } interchange = { path = "../interchange" } iso7816 = { path = "../iso7816" } +untrusted = "0.7.1" usb-device = { version = "0.2.3", features = ["control-buffer-256"] } [features] diff --git a/src/derp.rs b/src/derp.rs new file mode 100644 index 0000000..0ece355 --- /dev/null +++ b/src/derp.rs @@ -0,0 +1,85 @@ +pub use untrusted::{Input, Reader}; + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum Error { + HighTagNumberForm, + LongLengthNotSupported, + NonCanonical, + Read, + UnexpectedEnd, + WrongTag, + WrongValue, +} + +pub type Result = core::result::Result; + +impl From for Error { + fn from(_: untrusted::EndOfInput) -> Error { + Error::UnexpectedEnd + } +} + +/// Return the value of the given tag and apply a decoding function to it. +pub fn nested<'a, F, R>(input: &mut Reader<'a>, tag: u8, decoder: F) -> Result +where + F: FnOnce(&mut untrusted::Reader<'a>) -> Result, +{ + let inner = expect_tag_and_get_value(input, tag)?; + inner.read_all(Error::Read, decoder) +} + +/// Read a tag and return it's value. Errors when the expect and actual tag do not match. +pub fn expect_tag_and_get_value<'a>(input: &mut Reader<'a>, tag: u8) -> Result> { + let (actual_tag, inner) = read_tag_and_get_value(input)?; + if usize::from(tag) != usize::from(actual_tag) { + return Err(Error::WrongTag); + } + Ok(inner) +} + +/// Read a tag and its value. Errors when the expected and actual tag and values do not match. +pub fn expect_tag_and_value<'a>(input: &mut Reader<'a>, tag: u8, value: &[u8]) -> Result<()> { + let (actual_tag, inner) = read_tag_and_get_value(input)?; + if usize::from(tag) != usize::from(actual_tag) { + return Err(Error::WrongTag); + } + if value != inner.as_slice_less_safe() { + return Err(Error::WrongValue); + } + Ok(()) +} + +/// Read the next tag, and return it and its value. +pub fn read_tag_and_get_value<'a>(input: &mut Reader<'a>) -> Result<(u8, Input<'a>)> { + let tag = input.read_byte()?; + if (tag & 0x1F) == 0x1F { + return Err(Error::HighTagNumberForm); + } + + // If the high order bit of the first byte is set to zero then the length + // is encoded in the seven remaining bits of that byte. Otherwise, those + // seven bits represent the number of bytes used to encode the length. + let length = match input.read_byte()? { + n if (n & 0x80) == 0 => usize::from(n), + 0x81 => { + let second_byte = input.read_byte()?; + if second_byte < 128 { + return Err(Error::NonCanonical); + } + usize::from(second_byte) + } + 0x82 => { + let second_byte = usize::from(input.read_byte()?); + let third_byte = usize::from(input.read_byte()?); + let combined = (second_byte << 8) | third_byte; + if combined < 256 { + return Err(Error::NonCanonical); + } + combined + } + _ => return Err(Error::LongLengthNotSupported), + }; + + let inner = input.read_bytes(length)?; + Ok((tag, inner)) +} diff --git a/src/lib.rs b/src/lib.rs index f787f02..ce3f6e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,10 @@ pub mod constants; pub mod class; +// writer pub mod der; +// parser +pub mod derp; pub mod pipe; pub mod types; diff --git a/src/pipe.rs b/src/pipe.rs index 174d22b..9e94e7d 100644 --- a/src/pipe.rs +++ b/src/pipe.rs @@ -190,7 +190,7 @@ where self.interchange.request(command).expect("could not deposit command"); // apdu::Command::try_from(&self.message).unwrap() // ).expect("could not deposit command"); - hprintln!("set ccid state to processing").ok(); + // hprintln!("set ccid state to processing").ok(); self.state = State::Processing; // todo!("have message of length {} to dispatch", self.message.len()); } @@ -205,8 +205,8 @@ where // } // } if let State::Processing = self.state { - hprintln!("processing, checking for response, interchange state {:?}", - self.interchange.state()).ok(); + // hprintln!("processing, checking for response, interchange state {:?}", + // self.interchange.state()).ok(); if let Some(response) = self.interchange.take_response() { self.message = response.into_message();