1- use super :: utils:: from_slice_stream;
1+ use super :: utils:: { from_slice_stream, read_be_u16 , read_be_u32 , read_byte } ;
22use crate :: crypto:: COSEAlgorithm ;
33use crate :: ctap2:: commands:: CommandError ;
44use crate :: ctap2:: server:: RpIdHash ;
5+ use crate :: ctap2:: utils:: serde_parse_err;
56use 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- } ;
137use serde:: ser:: { Error as SerError , SerializeMap , Serializer } ;
148use serde:: {
159 de:: { Error as SerdeError , MapAccess , Visitor } ,
@@ -18,6 +12,7 @@ use serde::{
1812use serde_bytes:: ByteBuf ;
1913use serde_cbor;
2014use std:: fmt;
15+ use std:: io:: { Cursor , Read } ;
2116
2217#[ derive( Debug , PartialEq , Eq ) ]
2318pub 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 ) ]
9485pub 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
205185bitflags ! {
@@ -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-
259209impl < ' 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]
0 commit comments