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
use libusb;
use std::sync::Mutex;
use super::{
HsmDevice, UsbConfig, UsbDevices, UsbTimeout, YUBIHSM2_BULK_IN_ENDPOINT,
YUBIHSM2_BULK_OUT_ENDPOINT,
};
use adapter::{Adapter, AdapterError, AdapterErrorKind::UsbError};
use securechannel::MAX_MSG_SIZE;
use serial_number::SerialNumber;
use uuid::Uuid;
pub struct UsbAdapter {
handle: Mutex<libusb::DeviceHandle<'static>>,
device: HsmDevice,
timeout: UsbTimeout,
}
impl UsbAdapter {
pub(super) fn new(device: HsmDevice, timeout: UsbTimeout) -> Result<Self, AdapterError> {
let handle = device.open_handle()?;
let adapter = UsbAdapter {
device,
timeout,
handle: Mutex::new(handle),
};
Ok(adapter)
}
pub fn device(&self) -> &HsmDevice {
&self.device
}
}
impl Adapter for UsbAdapter {
type Config = UsbConfig;
fn open(config: &UsbConfig) -> Result<Self, AdapterError> {
UsbDevices::open(config.serial, UsbTimeout::from_millis(config.timeout_ms))
}
fn healthcheck(&self) -> Result<(), AdapterError> {
let handle = self.handle.lock().unwrap();
if let Err(e) = handle.active_configuration() {
fail!(UsbError, "healthcheck failed: {}", e);
}
Ok(())
}
fn serial_number(&self) -> Result<SerialNumber, AdapterError> {
Ok(self.device.serial_number)
}
fn send_message(&self, _uuid: Uuid, cmd: Vec<u8>) -> Result<Vec<u8>, AdapterError> {
let mut handle = self.handle.lock().unwrap();
send_message(&mut handle, cmd.as_ref(), self.timeout)?;
recv_message(&mut handle, self.timeout)
}
}
impl Default for UsbAdapter {
fn default() -> Self {
UsbDevices::open(None, UsbTimeout::default()).unwrap()
}
}
fn send_message(
handle: &mut libusb::DeviceHandle,
data: &[u8],
timeout: UsbTimeout,
) -> Result<usize, AdapterError> {
let nbytes = handle.write_bulk(YUBIHSM2_BULK_OUT_ENDPOINT, data, timeout.duration())?;
if data.len() == nbytes {
Ok(nbytes)
} else {
fail!(
UsbError,
"incomplete bulk transfer: {} of {} bytes",
nbytes,
data.len()
);
}
}
fn recv_message(
handle: &mut libusb::DeviceHandle,
timeout: UsbTimeout,
) -> Result<Vec<u8>, AdapterError> {
let mut response = vec![0u8; MAX_MSG_SIZE];
let nbytes = handle.read_bulk(YUBIHSM2_BULK_IN_ENDPOINT, &mut response, timeout.duration())?;
response.truncate(nbytes);
Ok(response)
}