aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2019-02-18 14:23:10 +0000
committerRobin Krahl <robin.krahl@ireas.org>2019-02-18 15:53:39 +0100
commit7f3cc787d03423aa982ade0fa054bb79be18f6ae (patch)
treeb709be7792b2b4af527881d354ee73ad62b7e04d
parent97e448c1d9921cd084e1da70f3943bead03474ed (diff)
downloadntw-7f3cc787d03423aa982ade0fa054bb79be18f6ae.tar.gz
ntw-7f3cc787d03423aa982ade0fa054bb79be18f6ae.tar.bz2
Implement Nitrokey command handling
This patch changes the Get_Report handler in Nitrokey to extract the command data from the buffer sent with the Set_Report request, to execute a command based on this data and to write appropriate return data back to the device.
-rw-r--r--src/device.rs78
1 files changed, 76 insertions, 2 deletions
diff --git a/src/device.rs b/src/device.rs
index f7c4fc7..3b6cf46 100644
--- a/src/device.rs
+++ b/src/device.rs
@@ -5,6 +5,7 @@ use usb_device::bus::{UsbBus, UsbBusAllocator};
use usb_device::device::{UsbDevice, UsbDeviceBuilder, UsbVidPid};
use crate::hid::{HidDevice, Protocol, ReportType, Subclass};
+use crate::util::TryFrom;
const VID_CLAY_LOGIC: u16 = 0x20a0;
const PID_NITROKEY_PRO: u16 = 0x4108;
@@ -18,6 +19,40 @@ const REPORT_DESCRIPTOR: &[u8] = &[
0x75, 0x08, 0x95, 0x40, 0xB1, 0x02, 0xC0,
];
+enum_u8! {
+ #[derive(Clone, Copy, Debug, PartialEq)]
+ pub enum DeviceStatus {
+ Ok = 0,
+ Busy = 1,
+ Error = 2,
+ ReceivedReport = 3,
+ }
+}
+
+enum_u8! {
+ #[derive(Clone, Copy, Debug, PartialEq)]
+ pub enum CommandStatus {
+ Ok = 0,
+ WrongCrc = 1,
+ WrongSlot = 2,
+ SlotNotProgrammed = 3,
+ WrongPassword = 4,
+ NotAuthorized = 5,
+ TimestampWarning = 6,
+ NoNameError = 7,
+ NotSupported = 8,
+ UnknownCommand = 9,
+ AesDecryptionFailed = 10,
+ }
+}
+
+enum_u8! {
+ #[derive(Clone, Copy, Debug, PartialEq)]
+ pub enum CommandId {
+ GetStatus = 0,
+ }
+}
+
pub struct Nitrokey {
buf: [u8; REPORT_LEN],
}
@@ -28,6 +63,15 @@ impl Nitrokey {
buf: [0; REPORT_LEN],
}
}
+
+ fn execute_command(
+ &self,
+ command_id: CommandId,
+ data: &[u8],
+ ) -> Result<[u8; 53], CommandStatus> {
+ let _ = (command_id, data);
+ Err(CommandStatus::UnknownCommand)
+ }
}
impl HidDevice for Nitrokey {
@@ -44,8 +88,38 @@ impl HidDevice for Nitrokey {
}
fn get_report(&mut self, report_type: ReportType, report_id: u8) -> Result<&[u8], ()> {
- let _ = (report_type, report_id);
- Err(())
+ if report_type != ReportType::Feature || report_id != 0 {
+ return Err(());
+ }
+
+ let device_status = DeviceStatus::Ok;
+ let command_id = self.buf[0];
+ let result = if let Ok(command_id) = CommandId::try_from(command_id) {
+ self.execute_command(command_id, &self.buf[1..60])
+ } else {
+ Err(CommandStatus::UnknownCommand)
+ };
+ let (command_status, command_data) = result
+ .map(|d| (CommandStatus::Ok, d))
+ .unwrap_or_else(|status| (status, [0; 53]));
+
+ let pre_data: [u8; 7] = [
+ device_status.into(), // device status
+ command_id, // command_id
+ self.buf[60],
+ self.buf[61],
+ self.buf[62],
+ self.buf[63], // last_command_crc
+ command_status.into(), // last_command_status
+ ];
+ let post_data: [u8; 4] = [
+ 0x00, 0x00, 0x00, 0x01, // crc -- libnitrokey accepts any non-zero value
+ ];
+
+ self.buf[0..7].copy_from_slice(&pre_data);
+ self.buf[7..7 + command_data.len()].copy_from_slice(&command_data);
+ self.buf[60..64].copy_from_slice(&post_data);
+ Ok(&self.buf)
}
fn set_report(