1pub mod auth_data;
9mod crypto;
10mod ctapdef;
11mod ctaphid;
12mod encrypt {
13 pub mod cose;
14 pub mod enc_aes256_cbc;
15 pub mod enc_hmac_sha_256;
16 pub mod p256;
17 pub mod shared_secret;
18 pub mod shared_secret2;
19}
20mod hmac_ext;
21mod pintoken;
22pub mod public_key;
23pub mod public_key_credential_descriptor;
24pub mod public_key_credential_rp_entity;
25pub mod public_key_credential_user_entity;
26pub mod str_buf;
27pub mod util;
28pub mod util_ciborium;
29pub mod verifier;
30
31use anyhow::{anyhow, Result};
32
33pub mod fidokey;
34pub use fidokey::FidoKeyHid;
35
36mod hid;
37pub use hid::{HidInfo, HidParam};
38
39pub type Cfg = LibCfg;
40
41#[derive(Clone)]
42pub struct LibCfg {
43 pub enable_log: bool,
44 pub use_pre_bio_enrollment: bool,
45 pub use_pre_credential_management: bool,
46 pub enable_keep_alive_msg: bool,
47 pub keep_alive_msg: String,
48 pub keep_alive_msg_to_stderr: bool,
49}
50
51impl LibCfg {
52 pub fn init() -> Self {
53 LibCfg {
54 enable_log: false,
56 use_pre_bio_enrollment: true,
58 use_pre_credential_management: true,
60 enable_keep_alive_msg: true,
62 keep_alive_msg: "- Touch the sensor on the authenticator".to_string(),
64 keep_alive_msg_to_stderr: false,
66 }
67 }
68
69 pub fn with_enable_log(mut self, enable: bool) -> Self {
70 self.enable_log = enable;
71 self
72 }
73
74 pub fn with_keep_alive_msg_to_stderr(mut self, to_stderr: bool) -> Self {
75 self.keep_alive_msg_to_stderr = to_stderr;
76 self
77 }
78}
79
80pub fn get_hid_devices() -> Vec<HidInfo> {
82 hid::get_hid_devices(None)
83}
84
85pub fn get_fidokey_devices() -> Vec<HidInfo> {
87 hid::get_hid_devices(Some(0xf1d0))
88}
89
90pub struct FidoKeyHidFactory {}
92
93impl FidoKeyHidFactory {
94 pub fn create(cfg: &LibCfg) -> Result<FidoKeyHid> {
95 let device = {
96 let mut devs = get_fidokey_devices();
97 if devs.is_empty() {
98 return Err(anyhow!("FIDO device not found."));
99 }
100 if devs.len() > 1 {
101 return Err(anyhow!("Multiple FIDO devices found."));
102 }
103
104 let device = devs.pop().unwrap().param;
105
106 let params = vec![device];
107 FidoKeyHid::new(¶ms, cfg)?
108 };
109 Ok(device)
110 }
111
112 pub fn create_by_params(params: &[HidParam], cfg: &LibCfg) -> Result<FidoKeyHid> {
113 FidoKeyHid::new(params, cfg)
114 }
115}
116
117#[cfg(test)]
121mod tests {
122 use super::*;
123 use crate::crypto::digest;
124 use std::convert::TryFrom;
125 use str_buf::StrBuf;
126
127 #[test]
128 fn test_create_pin_auth() {
129 let out_bytes = hex::decode("1A81CD600A1F6CF4BE5260FE3257B241").unwrap();
130 let client_data_hash =
131 hex::decode("E61E2BD6C4612662960B159CD54CF8EFF1A998C89B3742519D11F85E0F5E7876")
132 .unwrap();
133 let check = "F0AC99D6AAD2E199AF9CF25F6568A6F5".to_string();
134 let sig = encrypt::enc_hmac_sha_256::authenticate(&out_bytes, &client_data_hash);
135 let pin_auth = sig[0..16].to_vec();
136 assert_eq!(check, hex::encode(pin_auth).to_uppercase());
137 }
138
139 #[test]
140 fn test_hmac() {
141 let key = b"this is key".to_vec();
142 let message = b"this is message".to_vec();
143
144 let sig = encrypt::enc_hmac_sha_256::authenticate(&key, &message);
145
146 let check = "1BCF27BDA4891AFA5F53CC027B8835564E35A8E3B631AA0F0563299296AD5909".to_string();
147 assert_eq!(check, hex::encode(sig).to_uppercase());
148 }
149
150 #[test]
151 fn test_enc_hmac_sha_256() {
152 let key_str = "this is key.";
153 let hasher = digest::digest(&digest::SHA256, key_str.as_bytes());
154 let key = <[u8; 32]>::try_from(hasher.as_ref()).unwrap();
155
156 let message = "this is message.";
157 let sig = encrypt::enc_hmac_sha_256::authenticate(&key, message.as_bytes());
158 print!("{}", StrBuf::bufh("- hmac signature", &sig));
159 assert_eq!(
160 sig,
161 util::to_str_hex("BF3D3FCFC4462CDCBEBBBC8AF82EA38B7B5ED4259B2061322C57B5CA696D6080")
162 );
163 }
164
165 #[test]
166 fn test_enc_aes256_cbc() {
167 let key_str = "this is key.";
168 let hasher = digest::digest(&digest::SHA256, key_str.as_bytes());
169 let key = <[u8; 32]>::try_from(hasher.as_ref()).unwrap();
170
171 let message = "this is message.";
172 let enc_data = encrypt::enc_aes256_cbc::encrypt_message_str(&key, message);
173 print!("{}", StrBuf::bufh("- enc_data", &enc_data));
174 assert_eq!(
175 enc_data,
176 util::to_str_hex("37455A8392187439EFAA249617AAB5C2")
177 );
178
179 let dec_data = encrypt::enc_aes256_cbc::decrypt_message_str(&key, &enc_data);
180 print!("- dec_data = {}", dec_data);
181 assert_eq!(dec_data, message);
182 }
183}