aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/device.rs53
1 files changed, 35 insertions, 18 deletions
diff --git a/src/device.rs b/src/device.rs
index 5fd0aed..0df14ae 100644
--- a/src/device.rs
+++ b/src/device.rs
@@ -1,7 +1,7 @@
// Copyright 2019 Robin Krahl <robin.krahl@ireas.org>
// SPDX-License-Identifier: GPL-3.0-or-later
-use serde::Serialize;
+use serde::{Deserialize, Serialize};
use serde_big_array::big_array;
use usb_device::bus::{UsbBus, UsbBusAllocator};
use usb_device::device::{UsbDevice, UsbDeviceBuilder, UsbVidPid};
@@ -14,6 +14,7 @@ const VID_CLAY_LOGIC: u16 = 0x20a0;
const PID_NITROKEY_PRO: u16 = 0x4108;
const REPORT_LEN: usize = 64;
+const REQUEST_DATA_LEN: usize = REPORT_LEN - 5;
const REPORT_DESCRIPTOR: &[u8] = &[
0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x19, 0xE0, 0x29, 0xE7, 0x15, 0x00, 0x25, 0x01,
0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x03, 0x95, 0x05, 0x75, 0x01,
@@ -22,7 +23,7 @@ const REPORT_DESCRIPTOR: &[u8] = &[
0x75, 0x08, 0x95, 0x40, 0xB1, 0x02, 0xC0,
];
-big_array! { BigArray; COMMAND_LEN, }
+big_array! { BigArray; COMMAND_LEN, REQUEST_DATA_LEN, }
enum_u8! {
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -51,11 +52,19 @@ enum_u8! {
}
}
+#[derive(Deserialize)]
+struct Request {
+ pub command_id: u8,
+ #[serde(with = "BigArray")]
+ pub data: [u8; REQUEST_DATA_LEN],
+ pub crc: u32,
+}
+
#[derive(Serialize)]
struct Response {
pub device_status: DeviceStatus,
pub command_id: u8,
- pub last_crc: [u8; 4],
+ pub last_crc: u32,
pub command_status: CommandStatus,
#[serde(with = "BigArray")]
pub data: [u8; COMMAND_LEN],
@@ -63,11 +72,11 @@ struct Response {
}
impl Response {
- fn new(device_status: DeviceStatus, command_id: u8) -> Response {
+ fn new(device_status: DeviceStatus, command_id: u8, last_crc: u32) -> Response {
Response {
device_status,
command_id,
- last_crc: [0; 4],
+ last_crc,
command_status: CommandStatus::NotSupported,
data: [0; COMMAND_LEN],
crc: 0,
@@ -76,12 +85,14 @@ impl Response {
}
pub struct Nitrokey {
+ request: Option<Request>,
buf: [u8; REPORT_LEN],
}
impl Nitrokey {
pub fn new() -> Self {
Nitrokey {
+ request: None,
buf: [0; REPORT_LEN],
}
}
@@ -105,19 +116,23 @@ impl HidDevice for Nitrokey {
return Err(());
}
- let mut response = Response::new(DeviceStatus::Ok, self.buf[0]);
- response.last_crc = [self.buf[60], self.buf[61], self.buf[62], self.buf[63]];
- response.command_status = if let Ok(command_id) = CommandId::try_from(response.command_id) {
- command_id.execute(&self.buf[1..60], &mut response.data)
+ if let Some(ref request) = self.request {
+ let mut response = Response::new(DeviceStatus::Ok, request.command_id, request.crc);
+ response.command_status =
+ if let Ok(command_id) = CommandId::try_from(request.command_id) {
+ command_id.execute(&request.data, &mut response.data)
+ } else {
+ CommandStatus::UnknownCommand
+ };
+ // TODO: calculate actual CRC
+ response.crc = 1; // libnitrokey accepts any non-zero value
+
+ let len = ssmarshal::serialize(&mut self.buf, &response).map_err(|_| ())?;
+ assert!(len == REPORT_LEN);
+ Ok(&self.buf)
} else {
- CommandStatus::UnknownCommand
- };
- // TODO: calculate actual CRC
- response.crc = 1; // libnitrokey accepts any non-zero value
-
- let len = ssmarshal::serialize(&mut self.buf, &response).map_err(|_| ())?;
- assert!(len == REPORT_LEN);
- Ok(&self.buf)
+ Err(())
+ }
}
fn set_report(
@@ -129,7 +144,9 @@ impl HidDevice for Nitrokey {
if report_type != ReportType::Feature || report_id != 0 || data.len() != REPORT_LEN {
Err(())
} else {
- self.buf.copy_from_slice(data);
+ let (request, len) = ssmarshal::deserialize(data).map_err(|_| ())?;
+ assert!(len == REPORT_LEN);
+ self.request = Some(request);
Ok(())
}
}