Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions examples/is_configured.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use challenge_response::{config::Slot, ChallengeResponse, Device};

fn main() {
let mut cr = ChallengeResponse::new().unwrap();
let device = cr.find_device().unwrap();

println!("Checking configuration for device: {:?}", device.name);

check_slot(&mut cr, &device, Slot::Slot1);
check_slot(&mut cr, &device, Slot::Slot2);
}

fn check_slot(cr: &mut ChallengeResponse, device: &Device, slot: Slot) {
match cr.is_configured(device.clone(), slot.clone()) {
Ok(configured) => {
println!(
"Slot {:?} is {}configured",
slot,
if configured { "" } else { "not " }
);
}
Err(e) => {
eprintln!("Error checking slot {:?}: {:?}", slot, e);
}
}
}
50 changes: 49 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use error::ChallengeResponseError;
use hmacmode::Hmac;
use otpmode::Aes128Block;
use sec::{crc16, CRC_RESIDUAL_OK};
use usb::{Backend, BackendType, Flags, Frame, CHALLENGE_SIZE};
use usb::{Backend, BackendType, Flags, Frame, Status, CHALLENGE_SIZE};

pub use usb::Device;

Expand Down Expand Up @@ -71,6 +71,54 @@ impl ChallengeResponse {
.read_serial_from_device(conf.device.bus_id, conf.device.address_id)
}

pub fn read_status(&mut self, conf: Config) -> Result<Status> {
let (mut handle, interfaces) = self
.backend
.open_device(conf.device.bus_id, conf.device.address_id)?;

let challenge = [0; CHALLENGE_SIZE];
let command = Command::DeviceConfig;

let d = Frame::new(challenge, command);
let mut buf = [0; usb::STATUS_UPDATE_PAYLOAD_SIZE];
self.backend
.wait(&mut handle, |f| !f.contains(Flags::SLOT_WRITE_FLAG), &mut buf)?;

self.backend.write_frame(&mut handle, &d)?;

// Read the response.
let mut response = [0; usb::RESPONSE_SIZE];
self.backend.read_response(&mut handle, &mut response)?;
self.backend.close_device(handle, interfaces)?;

// Check response.
if crc16(&response[..8]) != CRC_RESIDUAL_OK {
return Err(ChallengeResponseError::WrongCRC);
}

let slice = &response[..6];
let array: [u8; 6] = slice.try_into().unwrap();
let status: Status = unsafe { std::mem::transmute(array) };

Ok(status)
}

pub fn is_configured(&mut self, device: Device, slot: Slot) -> Result<bool> {
let conf = Config::new_from(device);
let status = self.read_status(conf)?;

if status.pgm_seq == 0 {
return Ok(false);
}

let configured = match slot {
Slot::Slot1 => (status.touch_level & 1) != 0,
Slot::Slot2 => (status.touch_level & 2) != 0,
};

Ok(configured)
}

pub fn write_config(&mut self, conf: Config, device_config: &mut DeviceModeConfig) -> Result<()> {
let d = device_config.to_frame(conf.command);
let mut buf = [0; usb::STATUS_UPDATE_PAYLOAD_SIZE];
Expand Down
10 changes: 10 additions & 0 deletions src/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ pub struct Frame {
filler: [u8; 3],
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Status {
pub version_major: u8,
pub version_minor: u8,
pub version_build: u8,
pub pgm_seq: u8,
pub touch_level: u16,
}

impl Frame {
pub fn new(payload: [u8; PAYLOAD_SIZE], command: Command) -> Self {
let mut f = Frame {
Expand Down