Skip to content

Commit 9f1b3ac

Browse files
committed
Merge branch 'msirringhaus-drop_nom' into ctap2-2021
2 parents 5d0ae37 + 09acd61 commit 9f1b3ac

File tree

5 files changed

+130
-137
lines changed

5 files changed

+130
-137
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ serde_cbor = "0.11"
6565
serde_json = "1.0"
6666
bytes = { version = "0.5", optional = true, features = ["serde"] }
6767
base64 = "^0.13"
68-
nom = { version = "^7.1.1", features = ["std"], default-features = false}
6968
sha2 = "^0.10.0"
7069
cfg-if = "1.0"
7170
# Crypto backends

src/ctap2/attestation.rs

Lines changed: 64 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
1-
use super::utils::from_slice_stream;
1+
use super::utils::{from_slice_stream, read_be_u16, read_be_u32, read_byte};
22
use crate::crypto::COSEAlgorithm;
33
use crate::ctap2::commands::CommandError;
44
use crate::ctap2::server::RpIdHash;
5+
use crate::ctap2::utils::serde_parse_err;
56
use crate::{crypto::COSEKey, errors::AuthenticatorError};
6-
use nom::{
7-
bytes::complete::take,
8-
combinator::{cond, map},
9-
error::Error as NomError,
10-
number::complete::{be_u16, be_u32, be_u8},
11-
Err as NomErr, IResult,
12-
};
137
use serde::ser::{Error as SerError, SerializeMap, Serializer};
148
use serde::{
159
de::{Error as SerdeError, MapAccess, Visitor},
@@ -18,6 +12,7 @@ use serde::{
1812
use serde_bytes::ByteBuf;
1913
use serde_cbor;
2014
use std::fmt;
15+
use std::io::{Cursor, Read};
2116

2217
#[derive(Debug, PartialEq, Eq)]
2318
pub enum HmacSecretResponse {
@@ -86,10 +81,6 @@ impl Extension {
8681
}
8782
}
8883

89-
fn parse_extensions(input: &[u8]) -> IResult<&[u8], Extension, NomError<&[u8]>> {
90-
serde_to_nom(input)
91-
}
92-
9384
#[derive(Serialize, PartialEq, Default, Eq, Clone)]
9485
pub struct AAGuid(pub [u8; 16]);
9586

@@ -172,34 +163,23 @@ pub struct AttestedCredentialData {
172163
pub credential_public_key: COSEKey,
173164
}
174165

175-
fn serde_to_nom<'a, Output>(input: &'a [u8]) -> IResult<&'a [u8], Output>
176-
where
177-
Output: Deserialize<'a>,
178-
{
179-
from_slice_stream(input)
180-
.map_err(|_e| nom::Err::Error(nom::error::make_error(input, nom::error::ErrorKind::NoneOf)))
181-
// can't use custom errorkind because of error type mismatch in parse_attested_cred_data
182-
//.map_err(|e| NomErr::Error(Context::Code(input, ErrorKind::Custom(e))))
183-
// .map_err(|_| NomErr::Error(Context::Code(input, ErrorKind::Custom(42))))
184-
}
185-
186-
fn parse_attested_cred_data(
187-
input: &[u8],
188-
) -> IResult<&[u8], AttestedCredentialData, NomError<&[u8]>> {
189-
let (rest, aaguid_res) = map(take(16u8), AAGuid::from)(input)?;
190-
// // We can unwrap here, since we _know_ the input will be 16 bytes error out before calling from()
191-
let aaguid = aaguid_res.unwrap();
192-
let (rest, cred_len) = be_u16(rest)?;
193-
let (rest, credential_id) = map(take(cred_len), Vec::from)(rest)?;
194-
let (rest, credential_public_key) = serde_to_nom(rest)?;
195-
Ok((
196-
rest,
197-
(AttestedCredentialData {
198-
aaguid,
199-
credential_id,
200-
credential_public_key,
201-
}),
202-
))
166+
fn parse_attested_cred_data<R: Read, E: SerdeError>(
167+
data: &mut R,
168+
) -> Result<AttestedCredentialData, E> {
169+
let mut aaguid_raw = [0u8; 16];
170+
data.read_exact(&mut aaguid_raw)
171+
.map_err(|_| serde_parse_err("AAGuid"))?;
172+
let aaguid = AAGuid(aaguid_raw);
173+
let cred_len = read_be_u16(data)?;
174+
let mut credential_id = vec![0u8; cred_len as usize];
175+
data.read_exact(&mut credential_id)
176+
.map_err(|_| serde_parse_err("CredentialId"))?;
177+
let credential_public_key = from_slice_stream(data)?;
178+
Ok(AttestedCredentialData {
179+
aaguid,
180+
credential_id,
181+
credential_public_key,
182+
})
203183
}
204184

205185
bitflags! {
@@ -226,36 +206,6 @@ pub struct AuthenticatorData {
226206
pub extensions: Extension,
227207
}
228208

229-
fn parse_ad(input: &[u8]) -> IResult<&[u8], AuthenticatorData, NomError<&[u8]>> {
230-
let (rest, rp_id_hash_res) = map(take(32u8), RpIdHash::from)(input)?;
231-
// We can unwrap here, since we _know_ the input to from() will be 32 bytes or error out before calling from()
232-
let rp_id_hash = rp_id_hash_res.unwrap();
233-
// preserve the flags, even if some reserved values are set.
234-
let (rest, flags) = map(be_u8, AuthenticatorDataFlags::from_bits_truncate)(rest)?;
235-
let (rest, counter) = be_u32(rest)?;
236-
let (rest, credential_data) = cond(
237-
flags.contains(AuthenticatorDataFlags::ATTESTED),
238-
parse_attested_cred_data,
239-
)(rest)?;
240-
let (rest, extensions) = cond(
241-
flags.contains(AuthenticatorDataFlags::EXTENSION_DATA),
242-
parse_extensions,
243-
)(rest)?;
244-
// TODO(baloo): we should check for end of buffer and raise a parse
245-
// parse error if data is still in the buffer
246-
//eof!() >>
247-
Ok((
248-
rest,
249-
AuthenticatorData {
250-
rp_id_hash,
251-
flags,
252-
counter,
253-
credential_data,
254-
extensions: extensions.unwrap_or_default(),
255-
},
256-
))
257-
}
258-
259209
impl<'de> Deserialize<'de> for AuthenticatorData {
260210
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
261211
where
@@ -270,23 +220,40 @@ impl<'de> Deserialize<'de> for AuthenticatorData {
270220
formatter.write_str("a byte array")
271221
}
272222

273-
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
223+
fn visit_bytes<E>(self, input: &[u8]) -> Result<Self::Value, E>
274224
where
275225
E: SerdeError,
276226
{
277-
parse_ad(v)
278-
.map(|(_input, value)| value)
279-
.map_err(|e| match e {
280-
NomErr::Incomplete(nom::Needed::Size(len)) => {
281-
E::invalid_length(v.len(), &format!("{}", v.len() + len.get()).as_ref())
282-
}
283-
NomErr::Incomplete(nom::Needed::Unknown) => {
284-
E::invalid_length(v.len(), &"unknown") // We don't know the expected value
285-
}
286-
// TODO(baloo): is that enough? should we be more
287-
// specific on the error type?
288-
e => E::custom(e.to_string()),
289-
})
227+
let mut cursor = Cursor::new(input);
228+
let mut rp_id_hash_raw = [0u8; 32];
229+
cursor
230+
.read_exact(&mut rp_id_hash_raw)
231+
.map_err(|_| serde_parse_err("32 bytes"))?;
232+
let rp_id_hash = RpIdHash(rp_id_hash_raw);
233+
234+
// preserve the flags, even if some reserved values are set.
235+
let flags = AuthenticatorDataFlags::from_bits_truncate(read_byte(&mut cursor)?);
236+
let counter = read_be_u32(&mut cursor)?;
237+
let mut credential_data = None;
238+
if flags.contains(AuthenticatorDataFlags::ATTESTED) {
239+
credential_data = Some(parse_attested_cred_data(&mut cursor)?);
240+
}
241+
242+
let extensions = if flags.contains(AuthenticatorDataFlags::EXTENSION_DATA) {
243+
from_slice_stream(&mut cursor)?
244+
} else {
245+
Default::default()
246+
};
247+
248+
// TODO(baloo): we should check for end of buffer and raise a parse
249+
// parse error if data is still in the buffer
250+
Ok(AuthenticatorData {
251+
rp_id_hash,
252+
flags,
253+
counter,
254+
credential_data,
255+
extensions,
256+
})
290257
}
291258
}
292259

@@ -805,12 +772,21 @@ mod test {
805772
let v: Vec<u8> = vec![
806773
0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72,
807774
];
808-
let (rest, value): (&[u8], String) = from_slice_stream(&v).unwrap();
775+
let mut data = Cursor::new(v);
776+
let value: String = from_slice_stream::<_, _, serde_cbor::Error>(&mut data).unwrap();
809777
assert_eq!(value, "foobar");
810-
assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
811-
let (rest, value): (&[u8], String) = from_slice_stream(rest).unwrap();
778+
let mut remaining = Vec::new();
779+
data.read_to_end(&mut remaining).unwrap();
780+
assert_eq!(
781+
remaining.as_slice(),
782+
&[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]
783+
);
784+
let mut data = Cursor::new(remaining);
785+
let value: String = from_slice_stream::<_, _, serde_cbor::Error>(&mut data).unwrap();
812786
assert_eq!(value, "foobar");
813-
assert!(rest.is_empty());
787+
let mut remaining = Vec::new();
788+
data.read_to_end(&mut remaining).unwrap();
789+
assert!(remaining.is_empty());
814790
}
815791

816792
#[test]

src/ctap2/commands/get_assertion.rs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,11 @@ use crate::ctap2::commands::make_credentials::UserVerification;
1616
use crate::ctap2::server::{
1717
PublicKeyCredentialDescriptor, RelyingPartyWrapper, RpIdHash, User, UserVerificationRequirement,
1818
};
19+
use crate::ctap2::utils::{read_be_u32, read_byte};
1920
use crate::errors::AuthenticatorError;
2021
use crate::transport::errors::{ApduErrorStatus, HIDError};
2122
use crate::transport::FidoDevice;
2223
use crate::u2ftypes::CTAP1RequestAPDU;
23-
use nom::{
24-
error::VerboseError,
25-
number::complete::{be_u32, be_u8},
26-
sequence::tuple,
27-
};
2824
use serde::{
2925
de::{Error as DesError, MapAccess, Visitor},
3026
ser::{Error as SerError, SerializeMap},
@@ -33,6 +29,7 @@ use serde::{
3329
use serde_bytes::ByteBuf;
3430
use serde_cbor::{de::from_slice, ser, Value};
3531
use std::fmt;
32+
use std::io::Cursor;
3633

3734
#[derive(Clone, Copy, Debug, Serialize)]
3835
#[cfg_attr(test, derive(Deserialize))]
@@ -452,17 +449,11 @@ impl GetAssertionResult {
452449
rp_id_hash: &RpIdHash,
453450
key_handle: &PublicKeyCredentialDescriptor,
454451
) -> Result<GetAssertionResult, CommandError> {
455-
let parse_authentication = |input| {
456-
// Parsing an u8, then a u32, and the rest is the signature
457-
let (rest, (user_presence, counter)) = tuple((be_u8, be_u32))(input)?;
458-
let signature = Vec::from(rest);
459-
Ok((user_presence, counter, signature))
460-
};
461-
let (user_presence, counter, signature) =
462-
parse_authentication(input).map_err(|e: nom::Err<VerboseError<_>>| {
463-
error!("error while parsing authentication: {:?}", e);
464-
CommandError::Deserializing(DesError::custom("unable to parse authentication"))
465-
})?;
452+
let mut data = Cursor::new(input);
453+
let user_presence = read_byte(&mut data).map_err(CommandError::Deserializing)?;
454+
let counter = read_be_u32(&mut data).map_err(CommandError::Deserializing)?;
455+
// Remaining data is signature (Note: `data.remaining_slice()` is not yet stabilized)
456+
let signature = Vec::from(&data.get_ref()[data.position() as usize..]);
466457

467458
// Step 5 of Section 10.3 of CTAP2.1: "Copy bits 0 (the UP bit) and bit 1 from the
468459
// CTAP2/U2F response user presence byte to bits 0 and 1 of the CTAP2 flags, respectively.

src/ctap2/commands/make_credentials.rs

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,11 @@ use crate::ctap2::server::{
1818
PublicKeyCredentialDescriptor, PublicKeyCredentialParameters, RelyingParty,
1919
RelyingPartyWrapper, RpIdHash, User, UserVerificationRequirement,
2020
};
21+
use crate::ctap2::utils::{read_byte, serde_parse_err};
2122
use crate::errors::AuthenticatorError;
2223
use crate::transport::errors::{ApduErrorStatus, HIDError};
2324
use crate::transport::FidoDevice;
2425
use crate::u2ftypes::CTAP1RequestAPDU;
25-
use nom::{
26-
bytes::complete::{tag, take},
27-
error::VerboseError,
28-
number::complete::be_u8,
29-
};
3026
#[cfg(test)]
3127
use serde::Deserialize;
3228
use serde::{
@@ -35,6 +31,7 @@ use serde::{
3531
Serialize, Serializer,
3632
};
3733
use serde_cbor::{self, de::from_slice, ser, Value};
34+
use std::io::{Cursor, Read};
3835

3936
#[derive(Debug)]
4037
pub struct MakeCredentialsResult(pub AttestationObject);
@@ -44,30 +41,35 @@ impl MakeCredentialsResult {
4441
input: &[u8],
4542
rp_id_hash: &RpIdHash,
4643
) -> Result<MakeCredentialsResult, CommandError> {
47-
let parse_register = |input| {
48-
let (rest, _) = tag(&[0x05])(input)?;
49-
let (rest, public_key) = take(65u8)(rest)?;
50-
let (rest, key_handle_len) = be_u8(rest)?;
51-
let (rest, key_handle) = take(key_handle_len)(rest)?;
52-
Ok((rest, public_key, key_handle))
53-
};
44+
let mut data = Cursor::new(input);
45+
let magic_num = read_byte(&mut data).map_err(CommandError::Deserializing)?;
46+
if magic_num != 0x05 {
47+
error!("error while parsing registration: magic header not 0x05, but {magic_num}");
48+
return Err(CommandError::Deserializing(DesError::invalid_value(
49+
serde::de::Unexpected::Unsigned(magic_num as u64),
50+
&"0x05",
51+
)));
52+
}
53+
let mut public_key = [0u8; 65];
54+
data.read_exact(&mut public_key)
55+
.map_err(|_| CommandError::Deserializing(serde_parse_err("PublicKey")))?;
5456

55-
let (rest, public_key, key_handle) =
56-
parse_register(input).map_err(|e: nom::Err<VerboseError<_>>| {
57-
error!("error while parsing registration: {:?}", e);
58-
CommandError::Deserializing(DesError::custom("unable to parse registration"))
59-
})?;
57+
let credential_id_len = read_byte(&mut data).map_err(CommandError::Deserializing)?;
58+
let mut credential_id = vec![0u8; credential_id_len as usize];
59+
data.read_exact(&mut credential_id)
60+
.map_err(|_| CommandError::Deserializing(serde_parse_err("CredentialId")))?;
6061

61-
let cert_and_sig = parse_u2f_der_certificate(rest).map_err(|e| {
62-
error!("error while parsing registration: {:?}", e);
63-
CommandError::Deserializing(DesError::custom("unable to parse registration"))
62+
let cert_and_sig = parse_u2f_der_certificate(&data.get_ref()[data.position() as usize..])
63+
.map_err(|err| {
64+
CommandError::Deserializing(serde_parse_err(&format!(
65+
"Certificate and Signature: {err:?}",
66+
)))
6467
})?;
6568

66-
let credential_ec2_key = COSEEC2Key::from_sec1_uncompressed(Curve::SECP256R1, public_key)
67-
.map_err(|e| {
68-
error!("error while parsing registration: {:?}", e);
69-
CommandError::Deserializing(DesError::custom("unable to parse registration"))
70-
})?;
69+
let credential_ec2_key = COSEEC2Key::from_sec1_uncompressed(Curve::SECP256R1, &public_key)
70+
.map_err(|err| {
71+
CommandError::Deserializing(serde_parse_err(&format!("EC2 Key: {err:?}",)))
72+
})?;
7173

7274
let credential_public_key = COSEKey {
7375
alg: COSEAlgorithm::ES256,
@@ -84,7 +86,7 @@ impl MakeCredentialsResult {
8486
counter: 0,
8587
credential_data: Some(AttestedCredentialData {
8688
aaguid: AAGuid::default(),
87-
credential_id: Vec::from(key_handle),
89+
credential_id,
8890
credential_public_key,
8991
}),
9092
extensions: Default::default(),

src/ctap2/utils.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,39 @@
11
use serde::de;
2-
use serde_cbor::error::Result;
32
use serde_cbor::Deserializer;
3+
use std::io::Read;
44

5-
pub fn from_slice_stream<'a, T>(slice: &'a [u8]) -> Result<(&'a [u8], T)>
5+
pub fn serde_parse_err<E: de::Error>(s: &str) -> E {
6+
E::custom(format!("Failed to parse {s}"))
7+
}
8+
9+
pub fn from_slice_stream<'a, T, R: Read, E: de::Error>(data: &mut R) -> Result<T, E>
610
where
711
T: de::Deserialize<'a>,
812
{
9-
let mut deserializer = Deserializer::from_slice(slice);
10-
let value = de::Deserialize::deserialize(&mut deserializer)?;
11-
let rest = &slice[deserializer.byte_offset()..];
13+
let mut deserializer = Deserializer::from_reader(data);
14+
de::Deserialize::deserialize(&mut deserializer)
15+
.map_err(|x| serde_parse_err(&format!("{}: {}", stringify!(T), &x.to_string())))
16+
}
17+
18+
// Parsing routines
19+
20+
pub fn read_be_u32<R: Read, E: de::Error>(data: &mut R) -> Result<u32, E> {
21+
let mut buf = [0; 4];
22+
data.read_exact(&mut buf)
23+
.map_err(|_| serde_parse_err("u32"))?;
24+
Ok(u32::from_be_bytes(buf))
25+
}
26+
27+
pub fn read_be_u16<R: Read, E: de::Error>(data: &mut R) -> Result<u16, E> {
28+
let mut buf = [0; 2];
29+
data.read_exact(&mut buf)
30+
.map_err(|_| serde_parse_err("u16"))?;
31+
Ok(u16::from_be_bytes(buf))
32+
}
1233

13-
Ok((rest, value))
34+
pub fn read_byte<R: Read, E: de::Error>(data: &mut R) -> Result<u8, E> {
35+
match data.bytes().next() {
36+
Some(Ok(s)) => Ok(s),
37+
_ => Err(serde_parse_err("u8")),
38+
}
1439
}

0 commit comments

Comments
 (0)