diff options
author | Robin Krahl <robin.krahl@ireas.org> | 2019-02-18 14:23:10 +0000 |
---|---|---|
committer | Robin Krahl <robin.krahl@ireas.org> | 2019-02-18 15:53:39 +0100 |
commit | 7f3cc787d03423aa982ade0fa054bb79be18f6ae (patch) | |
tree | b709be7792b2b4af527881d354ee73ad62b7e04d | |
parent | 97e448c1d9921cd084e1da70f3943bead03474ed (diff) | |
download | ntw-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.rs | 78 |
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( |