1use super::utils::from_slice_stream;
2use crate::crypto::COSEAlgorithm;
3use crate::ctap2::commands::CommandError;
4use crate::ctap2::server::RpIdHash;
5use crate::{crypto::COSEKey, errors::AuthenticatorError};
6use 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};
13use serde::ser::{Error as SerError, SerializeMap, Serializer};
14use serde::{
15 de::{Error as SerdeError, MapAccess, Visitor},
16 Deserialize, Deserializer, Serialize,
17};
18use serde_bytes::ByteBuf;
19use serde_cbor;
20use std::fmt;
21
22#[derive(Debug, PartialEq, Eq)]
23pub enum HmacSecretResponse {
24 Confirmed(bool),
27 Secret(Vec<u8>),
30}
31
32impl Serialize for HmacSecretResponse {
33 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
34 where
35 S: Serializer,
36 {
37 match self {
38 HmacSecretResponse::Confirmed(x) => serializer.serialize_bool(*x),
39 HmacSecretResponse::Secret(x) => serializer.serialize_bytes(&x),
40 }
41 }
42}
43impl<'de> Deserialize<'de> for HmacSecretResponse {
44 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
45 where
46 D: Deserializer<'de>,
47 {
48 struct HmacSecretResponseVisitor;
49
50 impl<'de> Visitor<'de> for HmacSecretResponseVisitor {
51 type Value = HmacSecretResponse;
52
53 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
54 formatter.write_str("a byte array or a boolean")
55 }
56
57 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
58 where
59 E: SerdeError,
60 {
61 Ok(HmacSecretResponse::Secret(v.to_vec()))
62 }
63
64 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
65 where
66 E: SerdeError,
67 {
68 Ok(HmacSecretResponse::Confirmed(v))
69 }
70 }
71 deserializer.deserialize_any(HmacSecretResponseVisitor)
72 }
73}
74
75#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Default)]
76pub struct Extension {
77 #[serde(rename = "pinMinLength", skip_serializing_if = "Option::is_none")]
78 pub pin_min_length: Option<u64>,
79 #[serde(rename = "hmac-secret", skip_serializing_if = "Option::is_none")]
80 pub hmac_secret: Option<HmacSecretResponse>,
81}
82
83fn parse_extensions<'a>(input: &'a [u8]) -> IResult<&'a [u8], Extension, NomError<&'a [u8]>> {
84 serde_to_nom(input)
85}
86
87#[derive(Serialize, PartialEq, Default, Eq, Clone)]
88pub struct AAGuid(pub [u8; 16]);
89
90impl AAGuid {
91 pub fn from(src: &[u8]) -> Result<AAGuid, ()> {
92 let mut payload = [0u8; 16];
93 if src.len() != payload.len() {
94 Err(())
95 } else {
96 payload.copy_from_slice(src);
97 Ok(AAGuid(payload))
98 }
99 }
100}
101
102impl fmt::Debug for AAGuid {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 write!(
105 f,
106 "AAGuid({:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x})",
107 self.0[0],
108 self.0[1],
109 self.0[2],
110 self.0[3],
111 self.0[4],
112 self.0[5],
113 self.0[6],
114 self.0[7],
115 self.0[8],
116 self.0[9],
117 self.0[10],
118 self.0[11],
119 self.0[12],
120 self.0[13],
121 self.0[14],
122 self.0[15]
123 )
124 }
125}
126
127impl fmt::Display for AAGuid {
128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129 write!(
130 f,
131 "{:x}{:x}{:x}{:x}-{:x}{:x}-{:x}{:x}-{:x}{:x}-{:x}{:x}{:x}{:x}{:x}{:x}",
132 self.0[0],
133 self.0[1],
134 self.0[2],
135 self.0[3],
136 self.0[4],
137 self.0[5],
138 self.0[6],
139 self.0[7],
140 self.0[8],
141 self.0[9],
142 self.0[10],
143 self.0[11],
144 self.0[12],
145 self.0[13],
146 self.0[14],
147 self.0[15]
148 )
149 }
150}
151
152impl<'de> Deserialize<'de> for AAGuid {
153 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
154 where
155 D: Deserializer<'de>,
156 {
157 struct AAGuidVisitor;
158
159 impl<'de> Visitor<'de> for AAGuidVisitor {
160 type Value = AAGuid;
161
162 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
163 formatter.write_str("a byte array")
164 }
165
166 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
167 where
168 E: SerdeError,
169 {
170 let mut buf = [0u8; 16];
171 if v.len() != buf.len() {
172 return Err(E::invalid_length(v.len(), &"16"));
173 }
174
175 buf.copy_from_slice(v);
176
177 Ok(AAGuid(buf))
178 }
179 }
180
181 deserializer.deserialize_bytes(AAGuidVisitor)
182 }
183}
184
185#[derive(Debug, PartialEq, Eq)]
186pub struct AttestedCredentialData {
187 pub aaguid: AAGuid,
188 pub credential_id: Vec<u8>,
189 pub credential_public_key: COSEKey,
190}
191
192fn serde_to_nom<'a, Output>(input: &'a [u8]) -> IResult<&'a [u8], Output>
193where
194 Output: Deserialize<'a>,
195{
196 from_slice_stream(input)
197 .map_err(|_e| nom::Err::Error(nom::error::make_error(input, nom::error::ErrorKind::NoneOf)))
198 }
202
203fn parse_attested_cred_data<'a>(
204 input: &'a [u8],
205) -> IResult<&'a [u8], AttestedCredentialData, NomError<&'a [u8]>> {
206 let (rest, aaguid_res) = map(take(16u8), AAGuid::from)(input)?;
207 let aaguid = aaguid_res.unwrap();
209 let (rest, cred_len) = be_u16(rest)?;
210 let (rest, credential_id) = map(take(cred_len), Vec::from)(rest)?;
211 let (rest, credential_public_key) = serde_to_nom(rest)?;
212 Ok((
213 rest,
214 (AttestedCredentialData {
215 aaguid,
216 credential_id,
217 credential_public_key: credential_public_key,
218 }),
219 ))
220}
221
222bitflags! {
223 pub struct AuthenticatorDataFlags: u8 {
224 const USER_PRESENT = 0x01;
225 const USER_VERIFIED = 0x04;
226 const ATTESTED = 0x40;
227 const EXTENSION_DATA = 0x80;
228 }
229}
230
231#[derive(Debug, PartialEq, Eq)]
232pub struct AuthenticatorData {
233 pub rp_id_hash: RpIdHash,
234 pub flags: AuthenticatorDataFlags,
235 pub counter: u32,
236 pub credential_data: Option<AttestedCredentialData>,
237 pub extensions: Extension,
238}
239
240fn parse_ad<'a>(input: &'a [u8]) -> IResult<&'a [u8], AuthenticatorData, NomError<&'a [u8]>> {
241 let (rest, rp_id_hash_res) = map(take(32u8), RpIdHash::from)(input)?;
242 let rp_id_hash = rp_id_hash_res.unwrap();
244 let (rest, flags) = map(be_u8, AuthenticatorDataFlags::from_bits_truncate)(rest)?;
247 let (rest, counter) = be_u32(rest)?;
248 let (rest, credential_data) = cond(
249 flags.contains(AuthenticatorDataFlags::ATTESTED),
250 parse_attested_cred_data,
251 )(rest)?;
252 let (rest, extensions) = cond(
253 flags.contains(AuthenticatorDataFlags::EXTENSION_DATA),
254 parse_extensions,
255 )(rest)?;
256 Ok((
260 rest,
261 AuthenticatorData {
262 rp_id_hash,
263 flags,
264 counter,
265 credential_data,
266 extensions: extensions.unwrap_or_default(),
267 },
268 ))
269}
270
271impl<'de> Deserialize<'de> for AuthenticatorData {
272 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
273 where
274 D: Deserializer<'de>,
275 {
276 struct AuthenticatorDataVisitor;
277
278 impl<'de> Visitor<'de> for AuthenticatorDataVisitor {
279 type Value = AuthenticatorData;
280
281 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
282 formatter.write_str("a byte array")
283 }
284
285 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
286 where
287 E: SerdeError,
288 {
289 parse_ad(v)
290 .map(|(_input, value)| value)
291 .map_err(|e| match e {
292 NomErr::Incomplete(nom::Needed::Size(len)) => {
293 E::invalid_length(v.len(), &format!("{}", v.len() + len.get()).as_ref())
294 }
295 NomErr::Incomplete(nom::Needed::Unknown) => {
296 E::invalid_length(v.len(), &"unknown") }
298 e => E::custom(e.to_string()),
301 })
302 }
303 }
304
305 deserializer.deserialize_bytes(AuthenticatorDataVisitor)
306 }
307}
308
309impl AuthenticatorData {
310 pub fn to_vec(&self) -> Result<Vec<u8>, AuthenticatorError> {
311 let mut data = Vec::new();
312 data.extend(&self.rp_id_hash.0);
313 data.extend(&[self.flags.bits()]);
314 data.extend(&self.counter.to_be_bytes());
315
316 if let Some(cred) = &self.credential_data {
319 data.extend(&cred.aaguid.0);
320 data.extend(&(cred.credential_id.len() as u16).to_be_bytes());
321 data.extend(&cred.credential_id);
322 data.extend(
323 &serde_cbor::to_vec(&cred.credential_public_key)
324 .map_err(CommandError::Serializing)?,
325 );
326 }
327 Ok(data)
328 }
329}
330
331#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
332pub struct AttestationCertificate(#[serde(with = "serde_bytes")] pub(crate) Vec<u8>);
334
335impl AsRef<[u8]> for AttestationCertificate {
336 fn as_ref(&self) -> &[u8] {
337 self.0.as_ref()
338 }
339}
340
341#[derive(Serialize, Deserialize, PartialEq, Eq)]
342pub struct Signature(#[serde(with = "serde_bytes")] pub(crate) ByteBuf);
343
344impl fmt::Debug for Signature {
345 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
346 let value = base64::encode_config(&self.0, base64::URL_SAFE_NO_PAD);
347 write!(f, "Signature({})", value)
348 }
349}
350
351impl AsRef<[u8]> for Signature {
352 fn as_ref(&self) -> &[u8] {
353 self.0.as_ref()
354 }
355}
356
357#[derive(Debug, PartialEq, Eq)]
358pub enum AttestationStatement {
359 None,
360 Packed(AttestationStatementPacked),
361 FidoU2F(AttestationStatementFidoU2F),
368 Unparsed(Vec<u8>),
370}
371
372#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
410pub struct AttestationStatementFidoU2F {
412 pub sig: Signature,
413
414 #[serde(rename = "x5c")]
415 pub attestation_cert: Vec<AttestationCertificate>,
417}
418
419#[allow(dead_code)] impl AttestationStatementFidoU2F {
421 pub fn new(cert: &[u8], signature: &[u8]) -> Self {
422 AttestationStatementFidoU2F {
423 sig: Signature(ByteBuf::from(signature)),
424 attestation_cert: vec![AttestationCertificate(Vec::from(cert))],
425 }
426 }
427}
428
429#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
430pub struct AttestationStatementPacked {
433 pub alg: COSEAlgorithm,
434 pub sig: Signature,
435
436 #[serde(rename = "x5c")]
437 pub attestation_cert: Vec<AttestationCertificate>,
439}
440
441#[derive(Debug, Deserialize, PartialEq, Eq)]
442#[serde(rename_all = "lowercase")]
443enum AttestationFormat {
444 #[serde(rename = "fido-u2f")]
445 FidoU2F,
446 Packed,
447 None,
448 }
454
455#[derive(Debug, PartialEq, Eq)]
456pub struct AttestationObject {
457 pub auth_data: AuthenticatorData,
458 pub att_statement: AttestationStatement,
459}
460
461impl<'de> Deserialize<'de> for AttestationObject {
462 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
463 where
464 D: Deserializer<'de>,
465 {
466 struct AttestationObjectVisitor;
467
468 impl<'de> Visitor<'de> for AttestationObjectVisitor {
469 type Value = AttestationObject;
470
471 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
472 formatter.write_str("a cbor map")
473 }
474
475 fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
476 where
477 M: MapAccess<'de>,
478 {
479 let mut format: Option<AttestationFormat> = None;
480 let mut auth_data = None;
481 let mut att_statement = None;
482
483 while let Some(key) = map.next_key()? {
484 match key {
485 1 => {
489 if format.is_some() {
490 return Err(SerdeError::duplicate_field("fmt"));
491 }
492 format = Some(map.next_value()?);
493 }
494 2 => {
495 if auth_data.is_some() {
496 return Err(SerdeError::duplicate_field("auth_data"));
497 }
498 auth_data = Some(map.next_value()?);
499 }
500 3 => {
501 let format = format
502 .as_ref()
503 .ok_or_else(|| SerdeError::missing_field("fmt"))?;
504 if att_statement.is_some() {
505 return Err(SerdeError::duplicate_field("att_statement"));
506 }
507 match format {
508 AttestationFormat::None => {
510 att_statement = Some(AttestationStatement::None);
511 }
512 AttestationFormat::Packed => {
513 att_statement =
514 Some(AttestationStatement::Packed(map.next_value()?));
515 }
516 AttestationFormat::FidoU2F => {
517 att_statement =
518 Some(AttestationStatement::FidoU2F(map.next_value()?));
519 }
520 }
521 }
522 k => return Err(M::Error::custom(format!("unexpected key: {:?}", k))),
523 }
524 }
525
526 let auth_data =
527 auth_data.ok_or_else(|| M::Error::custom("found no auth_data".to_string()))?;
528 let att_statement = att_statement.unwrap_or(AttestationStatement::None);
529
530 Ok(AttestationObject {
531 auth_data,
532 att_statement,
533 })
534 }
535 }
536
537 deserializer.deserialize_bytes(AttestationObjectVisitor)
538 }
539}
540
541impl Serialize for AttestationObject {
542 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
543 where
544 S: Serializer,
545 {
546 let map_len = 3;
548 let mut map = serializer.serialize_map(Some(map_len))?;
549
550 let auth_data =
551 self
552 .auth_data
553 .to_vec()
554 .map(|v| serde_cbor::Value::Bytes(v))
555 .map_err(|_| SerError::custom("Failed to serialize auth_data"))?;
556
557 map.serialize_entry(
558 &"authData",
559 &auth_data
560 )?;
561 match self.att_statement {
562 AttestationStatement::None => {
563 map.serialize_entry(&"fmt", &"none")?;
565 let v = serde_cbor::Value::Map(std::collections::BTreeMap::new());
566 map.serialize_entry(&"attStmt", &v)?;
567 }
568 AttestationStatement::Packed(ref v) => {
569 map.serialize_entry(&"fmt", &"packed")?;
570 map.serialize_entry(&"attStmt", v)?;
571 }
572 AttestationStatement::FidoU2F(ref v) => {
573 map.serialize_entry(&"fmt", &"fido-u2f")?;
574 map.serialize_entry(&"attStmt", v)?;
575 }
576 AttestationStatement::Unparsed(ref v) => {
577 map.serialize_entry(&"fmt", &"fido-u2f")?;
579 map.serialize_entry(&"attStmt", v)?;
580 }
581 }
582
583 map.end()
584 }
585}
586
587#[cfg(test)]
588mod test {
589 use super::super::utils::from_slice_stream;
590 use super::*;
591 use serde_cbor::from_slice;
592
593 const SAMPLE_ATTESTATION: [u8; 1006] = [
594 0xa3, 0x1, 0x66, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x2, 0x58, 0xc4, 0x49, 0x96, 0xd,
595 0xe5, 0x88, 0xe, 0x8c, 0x68, 0x74, 0x34, 0x17, 0xf, 0x64, 0x76, 0x60, 0x5b, 0x8f, 0xe4,
596 0xae, 0xb9, 0xa2, 0x86, 0x32, 0xc7, 0x99, 0x5c, 0xf3, 0xba, 0x83, 0x1d, 0x97, 0x63, 0x41,
597 0x0, 0x0, 0x0, 0x7, 0xcb, 0x69, 0x48, 0x1e, 0x8f, 0xf7, 0x40, 0x39, 0x93, 0xec, 0xa, 0x27,
598 0x29, 0xa1, 0x54, 0xa8, 0x0, 0x40, 0xc3, 0xcf, 0x1, 0x3b, 0xc6, 0x26, 0x93, 0x28, 0xfb,
599 0x7f, 0xa9, 0x76, 0xef, 0xa8, 0x4b, 0x66, 0x71, 0xad, 0xa9, 0x64, 0xea, 0xcb, 0x58, 0x76,
600 0x54, 0x51, 0xa, 0xc8, 0x86, 0x4f, 0xbb, 0x53, 0x2d, 0xfb, 0x2, 0xfc, 0xdc, 0xa9, 0x84,
601 0xc2, 0x5c, 0x67, 0x8a, 0x3a, 0xab, 0x57, 0xf3, 0x71, 0x77, 0xd3, 0xd4, 0x41, 0x64, 0x1,
602 0x50, 0xca, 0x6c, 0x42, 0x73, 0x1c, 0x42, 0xcb, 0x81, 0xba, 0xa5, 0x1, 0x2, 0x3, 0x26,
603 0x20, 0x1, 0x21, 0x58, 0x20, 0x9, 0x2e, 0x34, 0xfe, 0xa7, 0xd7, 0x32, 0xc8, 0xae, 0x4c,
604 0xf6, 0x96, 0xbe, 0x7a, 0x12, 0xdc, 0x29, 0xd5, 0xf1, 0xd3, 0xf1, 0x55, 0x4d, 0xdc, 0x87,
605 0xc4, 0xc, 0x9b, 0xd0, 0x17, 0xba, 0xf, 0x22, 0x58, 0x20, 0xc9, 0xf0, 0x97, 0x33, 0x55,
606 0x36, 0x58, 0xd9, 0xdb, 0x76, 0xf5, 0xef, 0x95, 0xcf, 0x8a, 0xc7, 0xfc, 0xc1, 0xb6, 0x81,
607 0x25, 0x5f, 0x94, 0x6b, 0x62, 0x13, 0x7d, 0xd0, 0xc4, 0x86, 0x53, 0xdb, 0x3, 0xa3, 0x63,
608 0x61, 0x6c, 0x67, 0x26, 0x63, 0x73, 0x69, 0x67, 0x58, 0x48, 0x30, 0x46, 0x2, 0x21, 0x0,
609 0xac, 0x2a, 0x78, 0xa8, 0xaf, 0x18, 0x80, 0x39, 0x73, 0x8d, 0x3, 0x5e, 0x4, 0x4d, 0x94,
610 0x4f, 0x3f, 0x57, 0xce, 0x88, 0x41, 0xfa, 0x81, 0x50, 0x40, 0xb6, 0xd1, 0x95, 0xb5, 0xeb,
611 0xe4, 0x6f, 0x2, 0x21, 0x0, 0x8f, 0xf4, 0x15, 0xc9, 0xb3, 0x6d, 0x1c, 0xd, 0x4c, 0xa3,
612 0xcf, 0x99, 0x8a, 0x46, 0xd4, 0x4c, 0x8b, 0x5c, 0x26, 0x3f, 0xdf, 0x22, 0x6c, 0x9b, 0x23,
613 0x83, 0x8b, 0x69, 0x47, 0x67, 0x48, 0x45, 0x63, 0x78, 0x35, 0x63, 0x81, 0x59, 0x2, 0xc1,
614 0x30, 0x82, 0x2, 0xbd, 0x30, 0x82, 0x1, 0xa5, 0xa0, 0x3, 0x2, 0x1, 0x2, 0x2, 0x4, 0x18,
615 0xac, 0x46, 0xc0, 0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xb,
616 0x5, 0x0, 0x30, 0x2e, 0x31, 0x2c, 0x30, 0x2a, 0x6, 0x3, 0x55, 0x4, 0x3, 0x13, 0x23, 0x59,
617 0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x55, 0x32, 0x46, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20,
618 0x43, 0x41, 0x20, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x34, 0x35, 0x37, 0x32, 0x30,
619 0x30, 0x36, 0x33, 0x31, 0x30, 0x20, 0x17, 0xd, 0x31, 0x34, 0x30, 0x38, 0x30, 0x31, 0x30,
620 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0xf, 0x32, 0x30, 0x35, 0x30, 0x30, 0x39, 0x30,
621 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x6e, 0x31, 0xb, 0x30, 0x9, 0x6, 0x3,
622 0x55, 0x4, 0x6, 0x13, 0x2, 0x53, 0x45, 0x31, 0x12, 0x30, 0x10, 0x6, 0x3, 0x55, 0x4, 0xa,
623 0xc, 0x9, 0x59, 0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x41, 0x42, 0x31, 0x22, 0x30, 0x20,
624 0x6, 0x3, 0x55, 0x4, 0xb, 0xc, 0x19, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
625 0x61, 0x74, 0x6f, 0x72, 0x20, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f,
626 0x6e, 0x31, 0x27, 0x30, 0x25, 0x6, 0x3, 0x55, 0x4, 0x3, 0xc, 0x1e, 0x59, 0x75, 0x62, 0x69,
627 0x63, 0x6f, 0x20, 0x55, 0x32, 0x46, 0x20, 0x45, 0x45, 0x20, 0x53, 0x65, 0x72, 0x69, 0x61,
628 0x6c, 0x20, 0x34, 0x31, 0x33, 0x39, 0x34, 0x33, 0x34, 0x38, 0x38, 0x30, 0x59, 0x30, 0x13,
629 0x6, 0x7, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x2, 0x1, 0x6, 0x8, 0x2a, 0x86, 0x48, 0xce, 0x3d,
630 0x3, 0x1, 0x7, 0x3, 0x42, 0x0, 0x4, 0x79, 0xea, 0x3b, 0x2c, 0x7c, 0x49, 0x70, 0x10, 0x62,
631 0x23, 0xc, 0xd2, 0x3f, 0xeb, 0x60, 0xe5, 0x29, 0x31, 0x71, 0xd4, 0x83, 0xf1, 0x0, 0xbe,
632 0x85, 0x9d, 0x6b, 0xf, 0x83, 0x97, 0x3, 0x1, 0xb5, 0x46, 0xcd, 0xd4, 0x6e, 0xcf, 0xca,
633 0xe3, 0xe3, 0xf3, 0xf, 0x81, 0xe9, 0xed, 0x62, 0xbd, 0x26, 0x8d, 0x4c, 0x1e, 0xbd, 0x37,
634 0xb3, 0xbc, 0xbe, 0x92, 0xa8, 0xc2, 0xae, 0xeb, 0x4e, 0x3a, 0xa3, 0x6c, 0x30, 0x6a, 0x30,
635 0x22, 0x6, 0x9, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0xc4, 0xa, 0x2, 0x4, 0x15, 0x31, 0x2e,
636 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x31, 0x34, 0x38, 0x32,
637 0x2e, 0x31, 0x2e, 0x37, 0x30, 0x13, 0x6, 0xb, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0xe5, 0x1c,
638 0x2, 0x1, 0x1, 0x4, 0x4, 0x3, 0x2, 0x5, 0x20, 0x30, 0x21, 0x6, 0xb, 0x2b, 0x6, 0x1, 0x4,
639 0x1, 0x82, 0xe5, 0x1c, 0x1, 0x1, 0x4, 0x4, 0x12, 0x4, 0x10, 0xcb, 0x69, 0x48, 0x1e, 0x8f,
640 0xf7, 0x40, 0x39, 0x93, 0xec, 0xa, 0x27, 0x29, 0xa1, 0x54, 0xa8, 0x30, 0xc, 0x6, 0x3, 0x55,
641 0x1d, 0x13, 0x1, 0x1, 0xff, 0x4, 0x2, 0x30, 0x0, 0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48,
642 0x86, 0xf7, 0xd, 0x1, 0x1, 0xb, 0x5, 0x0, 0x3, 0x82, 0x1, 0x1, 0x0, 0x97, 0x9d, 0x3, 0x97,
643 0xd8, 0x60, 0xf8, 0x2e, 0xe1, 0x5d, 0x31, 0x1c, 0x79, 0x6e, 0xba, 0xfb, 0x22, 0xfa, 0xa7,
644 0xe0, 0x84, 0xd9, 0xba, 0xb4, 0xc6, 0x1b, 0xbb, 0x57, 0xf3, 0xe6, 0xb4, 0xc1, 0x8a, 0x48,
645 0x37, 0xb8, 0x5c, 0x3c, 0x4e, 0xdb, 0xe4, 0x83, 0x43, 0xf4, 0xd6, 0xa5, 0xd9, 0xb1, 0xce,
646 0xda, 0x8a, 0xe1, 0xfe, 0xd4, 0x91, 0x29, 0x21, 0x73, 0x5, 0x8e, 0x5e, 0xe1, 0xcb, 0xdd,
647 0x6b, 0xda, 0xc0, 0x75, 0x57, 0xc6, 0xa0, 0xe8, 0xd3, 0x68, 0x25, 0xba, 0x15, 0x9e, 0x7f,
648 0xb5, 0xad, 0x8c, 0xda, 0xf8, 0x4, 0x86, 0x8c, 0xf9, 0xe, 0x8f, 0x1f, 0x8a, 0xea, 0x17,
649 0xc0, 0x16, 0xb5, 0x5c, 0x2a, 0x7a, 0xd4, 0x97, 0xc8, 0x94, 0xfb, 0x71, 0xd7, 0x53, 0xd7,
650 0x9b, 0x9a, 0x48, 0x4b, 0x6c, 0x37, 0x6d, 0x72, 0x3b, 0x99, 0x8d, 0x2e, 0x1d, 0x43, 0x6,
651 0xbf, 0x10, 0x33, 0xb5, 0xae, 0xf8, 0xcc, 0xa5, 0xcb, 0xb2, 0x56, 0x8b, 0x69, 0x24, 0x22,
652 0x6d, 0x22, 0xa3, 0x58, 0xab, 0x7d, 0x87, 0xe4, 0xac, 0x5f, 0x2e, 0x9, 0x1a, 0xa7, 0x15,
653 0x79, 0xf3, 0xa5, 0x69, 0x9, 0x49, 0x7d, 0x72, 0xf5, 0x4e, 0x6, 0xba, 0xc1, 0xc3, 0xb4,
654 0x41, 0x3b, 0xba, 0x5e, 0xaf, 0x94, 0xc3, 0xb6, 0x4f, 0x34, 0xf9, 0xeb, 0xa4, 0x1a, 0xcb,
655 0x6a, 0xe2, 0x83, 0x77, 0x6d, 0x36, 0x46, 0x53, 0x78, 0x48, 0xfe, 0xe8, 0x84, 0xbd, 0xdd,
656 0xf5, 0xb1, 0xba, 0x57, 0x98, 0x54, 0xcf, 0xfd, 0xce, 0xba, 0xc3, 0x44, 0x5, 0x95, 0x27,
657 0xe5, 0x6d, 0xd5, 0x98, 0xf8, 0xf5, 0x66, 0x71, 0x5a, 0xbe, 0x43, 0x1, 0xdd, 0x19, 0x11,
658 0x30, 0xe6, 0xb9, 0xf0, 0xc6, 0x40, 0x39, 0x12, 0x53, 0xe2, 0x29, 0x80, 0x3f, 0x3a, 0xef,
659 0x27, 0x4b, 0xed, 0xbf, 0xde, 0x3f, 0xcb, 0xbd, 0x42, 0xea, 0xd6, 0x79,
660 ];
661
662 const SAMPLE_CERT_CHAIN: [u8; 709] = [
663 0x81, 0x59, 0x2, 0xc1, 0x30, 0x82, 0x2, 0xbd, 0x30, 0x82, 0x1, 0xa5, 0xa0, 0x3, 0x2, 0x1,
664 0x2, 0x2, 0x4, 0x18, 0xac, 0x46, 0xc0, 0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7,
665 0xd, 0x1, 0x1, 0xb, 0x5, 0x0, 0x30, 0x2e, 0x31, 0x2c, 0x30, 0x2a, 0x6, 0x3, 0x55, 0x4, 0x3,
666 0x13, 0x23, 0x59, 0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x55, 0x32, 0x46, 0x20, 0x52, 0x6f,
667 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x34, 0x35,
668 0x37, 0x32, 0x30, 0x30, 0x36, 0x33, 0x31, 0x30, 0x20, 0x17, 0xd, 0x31, 0x34, 0x30, 0x38,
669 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0xf, 0x32, 0x30, 0x35, 0x30,
670 0x30, 0x39, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x6e, 0x31, 0xb,
671 0x30, 0x9, 0x6, 0x3, 0x55, 0x4, 0x6, 0x13, 0x2, 0x53, 0x45, 0x31, 0x12, 0x30, 0x10, 0x6,
672 0x3, 0x55, 0x4, 0xa, 0xc, 0x9, 0x59, 0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x41, 0x42, 0x31,
673 0x22, 0x30, 0x20, 0x6, 0x3, 0x55, 0x4, 0xb, 0xc, 0x19, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e,
674 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61,
675 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x27, 0x30, 0x25, 0x6, 0x3, 0x55, 0x4, 0x3, 0xc, 0x1e, 0x59,
676 0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x55, 0x32, 0x46, 0x20, 0x45, 0x45, 0x20, 0x53, 0x65,
677 0x72, 0x69, 0x61, 0x6c, 0x20, 0x34, 0x31, 0x33, 0x39, 0x34, 0x33, 0x34, 0x38, 0x38, 0x30,
678 0x59, 0x30, 0x13, 0x6, 0x7, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x2, 0x1, 0x6, 0x8, 0x2a, 0x86,
679 0x48, 0xce, 0x3d, 0x3, 0x1, 0x7, 0x3, 0x42, 0x0, 0x4, 0x79, 0xea, 0x3b, 0x2c, 0x7c, 0x49,
680 0x70, 0x10, 0x62, 0x23, 0xc, 0xd2, 0x3f, 0xeb, 0x60, 0xe5, 0x29, 0x31, 0x71, 0xd4, 0x83,
681 0xf1, 0x0, 0xbe, 0x85, 0x9d, 0x6b, 0xf, 0x83, 0x97, 0x3, 0x1, 0xb5, 0x46, 0xcd, 0xd4, 0x6e,
682 0xcf, 0xca, 0xe3, 0xe3, 0xf3, 0xf, 0x81, 0xe9, 0xed, 0x62, 0xbd, 0x26, 0x8d, 0x4c, 0x1e,
683 0xbd, 0x37, 0xb3, 0xbc, 0xbe, 0x92, 0xa8, 0xc2, 0xae, 0xeb, 0x4e, 0x3a, 0xa3, 0x6c, 0x30,
684 0x6a, 0x30, 0x22, 0x6, 0x9, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0xc4, 0xa, 0x2, 0x4, 0x15,
685 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x31, 0x34,
686 0x38, 0x32, 0x2e, 0x31, 0x2e, 0x37, 0x30, 0x13, 0x6, 0xb, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82,
687 0xe5, 0x1c, 0x2, 0x1, 0x1, 0x4, 0x4, 0x3, 0x2, 0x5, 0x20, 0x30, 0x21, 0x6, 0xb, 0x2b, 0x6,
688 0x1, 0x4, 0x1, 0x82, 0xe5, 0x1c, 0x1, 0x1, 0x4, 0x4, 0x12, 0x4, 0x10, 0xcb, 0x69, 0x48,
689 0x1e, 0x8f, 0xf7, 0x40, 0x39, 0x93, 0xec, 0xa, 0x27, 0x29, 0xa1, 0x54, 0xa8, 0x30, 0xc,
690 0x6, 0x3, 0x55, 0x1d, 0x13, 0x1, 0x1, 0xff, 0x4, 0x2, 0x30, 0x0, 0x30, 0xd, 0x6, 0x9, 0x2a,
691 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0xb, 0x5, 0x0, 0x3, 0x82, 0x1, 0x1, 0x0, 0x97, 0x9d,
692 0x3, 0x97, 0xd8, 0x60, 0xf8, 0x2e, 0xe1, 0x5d, 0x31, 0x1c, 0x79, 0x6e, 0xba, 0xfb, 0x22,
693 0xfa, 0xa7, 0xe0, 0x84, 0xd9, 0xba, 0xb4, 0xc6, 0x1b, 0xbb, 0x57, 0xf3, 0xe6, 0xb4, 0xc1,
694 0x8a, 0x48, 0x37, 0xb8, 0x5c, 0x3c, 0x4e, 0xdb, 0xe4, 0x83, 0x43, 0xf4, 0xd6, 0xa5, 0xd9,
695 0xb1, 0xce, 0xda, 0x8a, 0xe1, 0xfe, 0xd4, 0x91, 0x29, 0x21, 0x73, 0x5, 0x8e, 0x5e, 0xe1,
696 0xcb, 0xdd, 0x6b, 0xda, 0xc0, 0x75, 0x57, 0xc6, 0xa0, 0xe8, 0xd3, 0x68, 0x25, 0xba, 0x15,
697 0x9e, 0x7f, 0xb5, 0xad, 0x8c, 0xda, 0xf8, 0x4, 0x86, 0x8c, 0xf9, 0xe, 0x8f, 0x1f, 0x8a,
698 0xea, 0x17, 0xc0, 0x16, 0xb5, 0x5c, 0x2a, 0x7a, 0xd4, 0x97, 0xc8, 0x94, 0xfb, 0x71, 0xd7,
699 0x53, 0xd7, 0x9b, 0x9a, 0x48, 0x4b, 0x6c, 0x37, 0x6d, 0x72, 0x3b, 0x99, 0x8d, 0x2e, 0x1d,
700 0x43, 0x6, 0xbf, 0x10, 0x33, 0xb5, 0xae, 0xf8, 0xcc, 0xa5, 0xcb, 0xb2, 0x56, 0x8b, 0x69,
701 0x24, 0x22, 0x6d, 0x22, 0xa3, 0x58, 0xab, 0x7d, 0x87, 0xe4, 0xac, 0x5f, 0x2e, 0x9, 0x1a,
702 0xa7, 0x15, 0x79, 0xf3, 0xa5, 0x69, 0x9, 0x49, 0x7d, 0x72, 0xf5, 0x4e, 0x6, 0xba, 0xc1,
703 0xc3, 0xb4, 0x41, 0x3b, 0xba, 0x5e, 0xaf, 0x94, 0xc3, 0xb6, 0x4f, 0x34, 0xf9, 0xeb, 0xa4,
704 0x1a, 0xcb, 0x6a, 0xe2, 0x83, 0x77, 0x6d, 0x36, 0x46, 0x53, 0x78, 0x48, 0xfe, 0xe8, 0x84,
705 0xbd, 0xdd, 0xf5, 0xb1, 0xba, 0x57, 0x98, 0x54, 0xcf, 0xfd, 0xce, 0xba, 0xc3, 0x44, 0x5,
706 0x95, 0x27, 0xe5, 0x6d, 0xd5, 0x98, 0xf8, 0xf5, 0x66, 0x71, 0x5a, 0xbe, 0x43, 0x1, 0xdd,
707 0x19, 0x11, 0x30, 0xe6, 0xb9, 0xf0, 0xc6, 0x40, 0x39, 0x12, 0x53, 0xe2, 0x29, 0x80, 0x3f,
708 0x3a, 0xef, 0x27, 0x4b, 0xed, 0xbf, 0xde, 0x3f, 0xcb, 0xbd, 0x42, 0xea, 0xd6, 0x79,
709 ];
710
711 const SAMPLE_AUTH_DATA_MAKE_CREDENTIAL: [u8; 164] = [
712 0x58, 0xA2, 0xc2, 0x89, 0xc5, 0xca, 0x9b, 0x04, 0x60, 0xf9, 0x34, 0x6a, 0xb4, 0xe4, 0x2d, 0x84,
715 0x27, 0x43, 0x40, 0x4d, 0x31, 0xf4, 0x84, 0x68, 0x25, 0xa6, 0xd0, 0x65, 0xbe, 0x59, 0x7a,
717 0x87, 0x05, 0x1d, 0xC1, 0x00, 0x00, 0x00, 0x0b, 0xf8, 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15, 0x80, 0x06, 0x17, 0x11, 0x1f, 0x9e, 0xdc,
722 0x7d, 0x00, 0x10, 0x89, 0x59, 0xce, 0xad, 0x5b, 0x5c, 0x48, 0x16, 0x4e, 0x8a, 0xbc, 0xd6, 0xd9, 0x43, 0x5c,
725 0x6f, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xa5, 0xfd, 0x5c, 0xe1, 0xb1,
728 0xc4, 0x58, 0xc5, 0x30, 0xa5, 0x4f, 0xa6, 0x1b, 0x31, 0xbf, 0x6b, 0x04, 0xbe, 0x8b, 0x97,
729 0xaf, 0xde, 0x54, 0xdd, 0x8c, 0xbb, 0x69, 0x27, 0x5a, 0x8a, 0x1b, 0xe1, 0x22, 0x58, 0x20,
730 0xfa, 0x3a, 0x32, 0x31, 0xdd, 0x9d, 0xee, 0xd9, 0xd1, 0x89, 0x7b, 0xe5, 0xa6, 0x22, 0x8c,
731 0x59, 0x50, 0x1e, 0x4b, 0xcd, 0x12, 0x97, 0x5d, 0x3d, 0xff, 0x73, 0x0f, 0x01, 0x27, 0x8e,
732 0xa6, 0x1c, 0xA1, 0x6B, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0xF5, ];
739
740 const SAMPLE_AUTH_DATA_GET_ASSERTION: [u8; 229] = [
741 0x58, 0xE3, 0xc2, 0x89, 0xc5, 0xca, 0x9b, 0x04, 0x60, 0xf9, 0x34, 0x6a, 0xb4, 0xe4, 0x2d, 0x84,
744 0x27, 0x43, 0x40, 0x4d, 0x31, 0xf4, 0x84, 0x68, 0x25, 0xa6, 0xd0, 0x65, 0xbe, 0x59, 0x7a,
746 0x87, 0x05, 0x1d, 0xC1, 0x00, 0x00, 0x00, 0x0b, 0xf8, 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15, 0x80, 0x06, 0x17, 0x11, 0x1f, 0x9e, 0xdc,
751 0x7d, 0x00, 0x10, 0x89, 0x59, 0xce, 0xad, 0x5b, 0x5c, 0x48, 0x16, 0x4e, 0x8a, 0xbc, 0xd6, 0xd9, 0x43, 0x5c,
754 0x6f, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xa5, 0xfd, 0x5c, 0xe1, 0xb1,
757 0xc4, 0x58, 0xc5, 0x30, 0xa5, 0x4f, 0xa6, 0x1b, 0x31, 0xbf, 0x6b, 0x04, 0xbe, 0x8b, 0x97,
758 0xaf, 0xde, 0x54, 0xdd, 0x8c, 0xbb, 0x69, 0x27, 0x5a, 0x8a, 0x1b, 0xe1, 0x22, 0x58, 0x20,
759 0xfa, 0x3a, 0x32, 0x31, 0xdd, 0x9d, 0xee, 0xd9, 0xd1, 0x89, 0x7b, 0xe5, 0xa6, 0x22, 0x8c,
760 0x59, 0x50, 0x1e, 0x4b, 0xcd, 0x12, 0x97, 0x5d, 0x3d, 0xff, 0x73, 0x0f, 0x01, 0x27, 0x8e,
761 0xa6, 0x1c, 0xA1, 0x6B, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x58, 0x40, 0x1F, 0x91, 0x52, 0x6C, 0xAE, 0x45, 0x6E, 0x4C, 0xBB, 0x71, 0xC4, 0xDD, 0xE7, 0xBB, 0x87,
768 0x71, 0x57, 0xE6, 0xE5, 0x4D, 0xFE, 0xD3, 0x01, 0x5D, 0x7D, 0x4D, 0xBB, 0x22, 0x69, 0xAF,
769 0xCD, 0xE6, 0xA9, 0x1B, 0x8D, 0x26, 0x7E, 0xBB, 0xF8, 0x48, 0xEB, 0x95, 0xA6, 0x8E, 0x79,
770 0xC7, 0xAC, 0x70, 0x5E, 0x35, 0x1D, 0x54, 0x3D, 0xB0, 0x16, 0x58, 0x87, 0xD6, 0x29, 0x0F,
771 0xD4, 0x7A, 0x40, 0xC4,
772 ];
773
774 #[test]
775 fn parse_cert_chain() {
776 let cert: AttestationCertificate = from_slice(&SAMPLE_CERT_CHAIN[1..]).unwrap();
777 assert_eq!(&cert.0, &SAMPLE_CERT_CHAIN[4..]);
778
779 let _cert: Vec<AttestationCertificate> = from_slice(&SAMPLE_CERT_CHAIN).unwrap();
780 }
781
782 #[test]
783 fn parse_attestation_object() {
784 let value: AttestationObject = from_slice(&SAMPLE_ATTESTATION).unwrap();
785 println!("{:?}", value);
786
787 }
789
790 #[test]
791 fn parse_reader() {
792 let v: Vec<u8> = vec![
793 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72,
794 ];
795 let (rest, value): (&[u8], String) = from_slice_stream(&v).unwrap();
796 assert_eq!(value, "foobar");
797 assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
798 let (rest, value): (&[u8], String) = from_slice_stream(rest).unwrap();
799 assert_eq!(value, "foobar");
800 assert!(rest.is_empty());
801 }
802
803 #[test]
804 fn parse_extensions() {
805 let auth_make: AuthenticatorData = from_slice(&SAMPLE_AUTH_DATA_MAKE_CREDENTIAL).unwrap();
806 assert_eq!(
807 auth_make.extensions.hmac_secret,
808 Some(HmacSecretResponse::Confirmed(true))
809 );
810 let auth_get: AuthenticatorData = from_slice(&SAMPLE_AUTH_DATA_GET_ASSERTION).unwrap();
811 assert_eq!(
812 auth_get.extensions.hmac_secret,
813 Some(HmacSecretResponse::Secret(vec![
814 0x1F, 0x91, 0x52, 0x6C, 0xAE, 0x45, 0x6E, 0x4C, 0xBB, 0x71, 0xC4, 0xDD, 0xE7, 0xBB,
815 0x87, 0x71, 0x57, 0xE6, 0xE5, 0x4D, 0xFE, 0xD3, 0x01, 0x5D, 0x7D, 0x4D, 0xBB, 0x22,
816 0x69, 0xAF, 0xCD, 0xE6, 0xA9, 0x1B, 0x8D, 0x26, 0x7E, 0xBB, 0xF8, 0x48, 0xEB, 0x95,
817 0xA6, 0x8E, 0x79, 0xC7, 0xAC, 0x70, 0x5E, 0x35, 0x1D, 0x54, 0x3D, 0xB0, 0x16, 0x58,
818 0x87, 0xD6, 0x29, 0x0F, 0xD4, 0x7A, 0x40, 0xC4,
819 ]))
820 );
821 }
822
823 #[test]
825 fn test_aaguid_output() {
826 let input = [
827 0xcb, 0x69, 0x48, 0x1e, 0x8f, 0xf0, 0x00, 0x39, 0x93, 0xec, 0x0a, 0x27, 0x29, 0xa1,
828 0x54, 0xa8,
829 ];
830 let expected = "AAGuid(cb69481e-8ff0-0039-93ec-0a2729a154a8)";
831 let result = AAGuid::from(&input).expect("Failed to parse AAGuid");
832 let res_str = format!("{:?}", result);
833 assert_eq!(expected, &res_str);
834 }
835}