Skip to content

Commit 3377167

Browse files
authored
WIP: CTAP2 support (#150)
* Moving platform specific modules into new module 'transport' * Replace capability-defines with bitflags (and add ctap2 capabilities) * Make HID commands its own type * Run cargo fmt and clippy * Add test for U2F_VERSION * CTAP2: Implement first ctap2-command GetInfo as well as ctap1-fallback GetVersion, plus tests * Sort CTAPHID const values according to value Co-authored-by: Martin Sirringhaus <>
1 parent 660a701 commit 3377167

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1561
-109
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ maintenance = { status = "actively-developed" }
1515

1616
[features]
1717
binding-recompile = ["bindgen"]
18-
webdriver = ["base64", "bytes", "warp", "tokio", "serde", "serde_json"]
18+
webdriver = ["base64", "bytes", "warp", "tokio", "serde_json"]
1919

2020
[target.'cfg(target_os = "linux")'.dependencies]
2121
libudev = "^0.2"
@@ -47,7 +47,8 @@ runloop = "0.1.0"
4747
bitflags = "1.0"
4848
tokio = { version = "0.2", optional = true, features = ["macros"] }
4949
warp = { version = "0.2.4", optional = true }
50-
serde = { version = "1.0", optional = true, features = ["derive"] }
50+
serde = { version = "1.0", features = ["derive"] }
51+
serde_cbor = "0.11"
5152
serde_json = { version = "1.0", optional = true }
5253
bytes = { version = "0.5", optional = true, features = ["serde"] }
5354
base64 = { version = "^0.10", optional = true }

src/authenticatorservice.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ impl AuthenticatorService {
222222
#[cfg(test)]
223223
mod tests {
224224
use super::{AuthenticatorService, AuthenticatorTransport};
225+
use crate::consts::Capability;
225226
use crate::consts::PARAMETER_SIZE;
226227
use crate::statecallback::StateCallback;
227228
use crate::{AuthenticatorTransports, KeyHandle, RegisterFlags, SignFlags, StatusUpdate};
@@ -257,7 +258,7 @@ mod tests {
257258
version_major: 1,
258259
version_minor: 2,
259260
version_build: 3,
260-
cap_flags: 0,
261+
cap_flags: Capability::empty(),
261262
}
262263
}
263264
}

src/consts.rs

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,65 @@ pub const U2FHID_IF_VERSION: u32 = 2; // Current interface implementation versio
3030
pub const U2FHID_FRAME_TIMEOUT: u32 = 500; // Default frame timeout in ms
3131
pub const U2FHID_TRANS_TIMEOUT: u32 = 3000; // Default message timeout in ms
3232

33-
// U2FHID native commands
34-
pub const U2FHID_PING: u8 = TYPE_INIT | 0x01; // Echo data through local processor only
35-
pub const U2FHID_MSG: u8 = TYPE_INIT | 0x03; // Send U2F message frame
36-
pub const U2FHID_LOCK: u8 = TYPE_INIT | 0x04; // Send lock channel command
37-
pub const U2FHID_INIT: u8 = TYPE_INIT | 0x06; // Channel initialization
38-
pub const U2FHID_WINK: u8 = TYPE_INIT | 0x08; // Send device identification wink
39-
pub const U2FHID_ERROR: u8 = TYPE_INIT | 0x3f; // Error response
33+
// CTAPHID native commands
34+
const CTAPHID_PING: u8 = TYPE_INIT | 0x01; // Echo data through local processor only
35+
const CTAPHID_MSG: u8 = TYPE_INIT | 0x03; // Send U2F message frame
36+
const CTAPHID_LOCK: u8 = TYPE_INIT | 0x04; // Send lock channel command
37+
const CTAPHID_INIT: u8 = TYPE_INIT | 0x06; // Channel initialization
38+
const CTAPHID_WINK: u8 = TYPE_INIT | 0x08; // Send device identification wink
39+
const CTAPHID_CBOR: u8 = TYPE_INIT | 0x10; // Encapsulated CBOR encoded message
40+
const CTAPHID_CANCEL: u8 = TYPE_INIT | 0x11; // Cancel outstanding requests
41+
const CTAPHID_KEEPALIVE: u8 = TYPE_INIT | 0x3b; // Keepalive sent to authenticator every 100ms and whenever a status changes
42+
const CTAPHID_ERROR: u8 = TYPE_INIT | 0x3f; // Error response
43+
44+
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
45+
#[repr(u8)]
46+
pub enum HIDCmd {
47+
Ping,
48+
Msg,
49+
Lock,
50+
Init,
51+
Wink,
52+
Cbor,
53+
Cancel,
54+
Keepalive,
55+
Error,
56+
Unknown(u8),
57+
}
58+
59+
impl Into<u8> for HIDCmd {
60+
fn into(self) -> u8 {
61+
match self {
62+
HIDCmd::Ping => CTAPHID_PING,
63+
HIDCmd::Msg => CTAPHID_MSG,
64+
HIDCmd::Lock => CTAPHID_LOCK,
65+
HIDCmd::Init => CTAPHID_INIT,
66+
HIDCmd::Wink => CTAPHID_WINK,
67+
HIDCmd::Cbor => CTAPHID_CBOR,
68+
HIDCmd::Cancel => CTAPHID_CANCEL,
69+
HIDCmd::Keepalive => CTAPHID_KEEPALIVE,
70+
HIDCmd::Error => CTAPHID_ERROR,
71+
HIDCmd::Unknown(v) => v,
72+
}
73+
}
74+
}
75+
76+
impl From<u8> for HIDCmd {
77+
fn from(v: u8) -> HIDCmd {
78+
match v {
79+
CTAPHID_PING => HIDCmd::Ping,
80+
CTAPHID_MSG => HIDCmd::Msg,
81+
CTAPHID_LOCK => HIDCmd::Lock,
82+
CTAPHID_INIT => HIDCmd::Init,
83+
CTAPHID_WINK => HIDCmd::Wink,
84+
CTAPHID_CBOR => HIDCmd::Cbor,
85+
CTAPHID_CANCEL => HIDCmd::Cancel,
86+
CTAPHID_KEEPALIVE => HIDCmd::Keepalive,
87+
CTAPHID_ERROR => HIDCmd::Error,
88+
v => HIDCmd::Unknown(v),
89+
}
90+
}
91+
}
4092

4193
// U2FHID_MSG commands
4294
pub const U2F_VENDOR_FIRST: u8 = TYPE_INIT | 0x40; // First vendor defined command
@@ -57,8 +109,25 @@ pub const U2F_CHECK_IS_REGISTERED: u8 = 0x07; // Check if the key handle is regi
57109

58110
// U2FHID_INIT command defines
59111
pub const INIT_NONCE_SIZE: usize = 8; // Size of channel initialization challenge
60-
pub const CAPFLAG_WINK: u8 = 0x01; // Device supports WINK command
61-
pub const CAPFLAG_LOCK: u8 = 0x02; // Device supports LOCK command
112+
113+
bitflags! {
114+
pub struct Capability: u8 {
115+
const WINK = 0x01;
116+
const LOCK = 0x02;
117+
const CBOR = 0x04;
118+
const NMSG = 0x08;
119+
}
120+
}
121+
122+
impl Capability {
123+
pub fn has_fido1(self) -> bool {
124+
!self.contains(Capability::NMSG)
125+
}
126+
127+
pub fn has_fido2(self) -> bool {
128+
self.contains(Capability::CBOR)
129+
}
130+
}
62131

63132
// Low-level error codes. Return as negatives.
64133

0 commit comments

Comments
 (0)