From dbae67d6fbb1f8a310b8de820fcda34c31eed39f Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 19 Feb 2019 13:51:10 +0000 Subject: 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. --- src/device.rs | 53 +++++++++++++++++++++++++++++++++++------------------ 1 file 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 // 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, 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(()) } } -- cgit v1.2.3