1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
pub mod hid_const {
// From : Common U2F HID transport header - Review Draft
// 2014-10-08
// Size of HID reports
pub const HID_RPT_SIZE: usize = 64; // Default size of raw HID report
// Frame layout - command- and continuation frames
pub const CID_BROADCAST: u32 = 0xffff_ffff; // Broadcast channel id
pub const CID_BROADCAST_SLICE: [u8; 4] = [0xff, 0xff, 0xff, 0xff]; // Broadcast channel id
pub const TYPE_MASK: u8 = 0x80; // Frame type mask
pub const TYPE_INIT: u8 = 0x80; // Initial frame identifier
pub const TYPE_CONT: u8 = 0x00; // Continuation frame identifier
// HID usage- and usage-page definitions
pub const FIDO_USAGE_PAGE: u16 = 0xf1d0; // FIDO alliance HID usage page
pub const FIDO_USAGE_U2FHID: u8 = 0x01; // U2FHID usage for top-level collection
pub const FIDO_USAGE_DATA_IN: u8 = 0x20; // Raw IN data report
pub const FIDO_USAGE_DATA_OUT: u8 = 0x21; // Raw OUT data report
// General constants
pub const U2FHID_IF_VERSION: usize = 2; // Current interface implementation version
pub const U2FHID_TRANS_TIMEOUT: usize = 3000; // Default message timeout in ms
// U2FHID native commands
pub const U2FHID_PING: u8 = TYPE_INIT | 0x01; // Echo data through local processor only
pub const U2FHID_MSG: u8 = TYPE_INIT | 0x03; // Send U2F message frame
pub const U2FHID_LOCK: u8 = TYPE_INIT | 0x04; // Send lock channel command
pub const U2FHID_INIT: u8 = TYPE_INIT | 0x06; // Channel initialization
pub const U2FHID_WINK: u8 = TYPE_INIT | 0x08; // Send device identification wink
pub const U2FHID_SYNC: u8 = TYPE_INIT | 0x3c; // Protocol resync command
pub const U2FHID_ERROR: u8 = TYPE_INIT | 0x3f; // Error response
pub const U2FHID_VENDOR_FIRST: u8 = TYPE_INIT | 0x40; // First vendor defined command
pub const U2FHID_VENDOR_LAST: u8 = TYPE_INIT | 0x7f; // Last vendor defined command
// U2FHID_INIT command defines
pub const INIT_NONCE_SIZE: usize = 8; // Size of channel initialization challenge
pub const CAPFLAG_WINK: u8 = 0x01; // Device supports WINK command
// Low-level error codes. Return as negatives.
pub const ERR_NONE: u8 = 0x00; // No error
pub const ERR_INVALID_CMD: u8 = 0x01; // Invalid command
pub const ERR_INVALID_PAR: u8 = 0x02; // Invalid parameter
pub const ERR_INVALID_LEN: u8 = 0x03; // Invalid message length
pub const ERR_INVALID_SEQ: u8 = 0x04; // Invalid message sequencing
pub const ERR_MSG_TIMEOUT: u8 = 0x05; // Message has timed out
pub const ERR_CHANNEL_BUSY: u8 = 0x06; // Channel busy
pub const ERR_LOCK_REQUIRED: u8 = 0x0a; // Command requires channel lock
pub const ERR_SYNC_FAIL: u8 = 0x0b; // SYNC command failed
pub const ERR_OTHER: u8 = 0x7f; // Other unspecified error
}
pub mod hid_type {
#![allow(dead_code)]
use crate::u2f::proto::hid::hid_const::*;
pub enum Packet {
Init {
cmd: u8, // Frame type - b7 defines type
bcnth: u8, // Message byte count - high part
bcntl: u8, // Message byte count - low part
data: [u8; HID_RPT_SIZE - 7], // Data payload
},
Cont {
seq: u8, // Frame type - b7 defines type
data: [u8; HID_RPT_SIZE - 5], // Data payload
},
}
pub struct U2fHidFrame {
cid: u32, // Channel identifier
packet: Packet,
}
impl U2fHidFrame {
#[inline]
pub fn frame_type(&self) -> u8 {
match self.packet {
Packet::Init { cmd, .. } => cmd & TYPE_MASK,
Packet::Cont { seq, .. } => seq & TYPE_MASK,
}
}
#[inline]
pub fn frame_cmd(&self) -> Option<u8> {
match self.packet {
Packet::Init { cmd, .. } => Some(cmd & !TYPE_MASK),
_ => None,
}
}
#[inline]
pub fn frame_seq(&self) -> Option<u8> {
match self.packet {
Packet::Cont { seq, .. } => Some(seq & !TYPE_MASK),
_ => None,
}
}
#[inline]
pub fn msg_len(&self) -> Option<u16> {
match self.packet {
Packet::Init { bcnth, bcntl, .. } => Some(bcnth as u16 * 256 + bcntl as u16),
_ => None,
}
}
}
pub struct U2fHidInitReq {
nonce: [u8; INIT_NONCE_SIZE], // Client application nonce
}
pub struct U2fHidInitRsp {
nonce: [u8; INIT_NONCE_SIZE], // Client application nonce
cid: u32, // Client application nonce
interface_version: u8, // Channel identifier
major_version: u8, // Interface version
minor_version: u8, // Major version number
build_version: u8, // Minor version number
cap_flags: u8, // Build version number
}
// U2FHID_SYNC command defines
pub struct U2fHidSyncReq {
nonce: u8, // Client application nonce
}
pub struct U2fHidSyncRsp {
nonce: u8, // Client application nonce
}
}