Skip to main content

u2f/
register.rs

1use byteorder::{BigEndian, ByteOrder};
2use bytes::Bytes;
3use serde::{Deserialize, Serialize};
4use sha2::{Digest, Sha256};
5use std::convert::TryFrom;
6
7use crate::messages::RegisteredKey;
8use crate::u2ferror::U2fError;
9use crate::util::*;
10
11/// The `Result` type used in this crate.
12type Result<T> = ::std::result::Result<T, U2fError>;
13
14// Single enrolment or pairing between an application and a token.
15#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Hash, Debug)]
16#[serde(rename_all = "camelCase")]
17pub struct Registration {
18  pub key_handle: Vec<u8>,
19  pub pub_key: Vec<u8>,
20
21  // AttestationCert can be null for Authenticate requests.
22  pub attestation_cert: Option<Vec<u8>>,
23  pub device_name: Option<String>,
24}
25
26pub(crate) fn sha256(data: &[u8]) -> Vec<u8> {
27  let mut hasher = Sha256::new();
28  hasher.update(data);
29  hasher.finalize().to_vec()
30}
31
32pub fn parse_registration(app_id: String, client_data: Vec<u8>, registration_data: Vec<u8>) -> Result<Registration> {
33  let reserved_byte = registration_data[0];
34  if reserved_byte != 0x05 {
35    return Err(U2fError::InvalidReservedByte);
36  }
37
38  let mut mem = Bytes::from(registration_data);
39
40  //Start parsing ... advance the reserved byte.
41  let _ = mem.split_to(1);
42
43  // P-256 NIST elliptic curve
44  let public_key = mem.split_to(65);
45
46  // Key Handle
47  let key_handle_size = mem.split_to(1);
48  let key_len = BigEndian::read_uint(&key_handle_size[..], 1);
49  let key_handle = mem.split_to(key_len as usize);
50
51  // The certificate length needs to be inferred by parsing.
52  let cert_len = asn_length(mem.clone()).unwrap();
53  let attestation_certificate = mem.split_to(cert_len);
54
55  // Remaining data corresponds to the signature
56  let signature = mem;
57
58  // Let's build the msg to verify the signature
59  let app_id_hash = sha256(&app_id.into_bytes());
60  let client_data_hash = sha256(&client_data[..]);
61
62  let mut msg = vec![0x00]; // A byte reserved for future use [1 byte] with the value 0x00
63  msg.extend_from_slice(app_id_hash.as_ref());
64  msg.extend_from_slice(client_data_hash.as_ref());
65  msg.extend_from_slice(key_handle.as_ref());
66  msg.extend_from_slice(public_key.as_ref());
67
68  // The signature is to be verified by the relying party using the public key certified
69  // in the attestation certificate.
70  let cerificate_public_key = super::crypto::X509PublicKey::try_from(&attestation_certificate[..])?;
71
72  if !(cerificate_public_key.is_secp256r1()?) {
73    return Err(U2fError::BadCertificate);
74  }
75
76  cerificate_public_key.verify_signature(&signature[..], &msg[..])?;
77
78  let registration = Registration {
79    key_handle: key_handle[..].to_vec(),
80    pub_key: public_key[..].to_vec(),
81    attestation_cert: Some(attestation_certificate[..].to_vec()),
82    device_name: cerificate_public_key.common_name(),
83  };
84
85  Ok(registration)
86}
87
88pub fn get_registered_key(app_id: String, key_handle: Vec<u8>) -> RegisteredKey {
89  RegisteredKey {
90    app_id,
91    version: U2F_V2.into(),
92    key_handle: Some(get_encoded(key_handle.as_slice())),
93  }
94}