aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2019-02-19 13:51:10 +0000
committerRobin Krahl <robin.krahl@ireas.org>2019-02-19 14:54:29 +0100
commitdbae67d6fbb1f8a310b8de820fcda34c31eed39f (patch)
tree21ff0a6646ae12dc8e8578a1955516c4f39f1b6f
parent55d3369d9e7f68bb0c836c8143778b2918f01ba5 (diff)
downloadntw-dbae67d6fbb1f8a310b8de820fcda34c31eed39f.tar.gz
ntw-dbae67d6fbb1f8a310b8de820fcda34c31eed39f.tar.bz2
Use ssmarshal to deserialize the request data
Previously, we directly accessed the request data by indexing the buffer containing the data. This patch introduces the Request struct which can be deserialized from raw bytes using ssmarshal.
-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(())
}
}