From 5c01623394ede020e2b79ed89bf3e2c84c04f72a Mon Sep 17 00:00:00 2001 From: Grimmauld Date: Thu, 6 Feb 2025 12:03:02 +0100 Subject: [PATCH] fmt --- src/lib_ykoath.rs | 137 ++++++++++++++++++++++------------------------ src/main.rs | 16 +++--- 2 files changed, 72 insertions(+), 81 deletions(-) diff --git a/src/lib_ykoath.rs b/src/lib_ykoath.rs index 1dc967e..377183e 100644 --- a/src/lib_ykoath.rs +++ b/src/lib_ykoath.rs @@ -1,13 +1,11 @@ -/// Utilities for interacting with YubiKey OATH/TOTP functionality - -extern crate pcsc; extern crate byteorder; +/// Utilities for interacting with YubiKey OATH/TOTP functionality +extern crate pcsc; -use std::ffi::{CString}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; +use std::ffi::CString; use std::io::{Cursor, Read, Write}; -use std::time::{SystemTime}; - +use std::time::SystemTime; pub type DetectResult<'a> = Result>, pcsc::Error>; @@ -39,55 +37,43 @@ pub fn format_code(code: u32, digits: OathDigits) -> String { } else { code_string.split_off(code_string.len() - 6) } - }, + } OathDigits::Eight => { if code_string.len() <= 8 { format!("{:0>8}", code_string) } else { code_string.split_off(code_string.len() - 8) } - }, + } } } fn to_error_response(sw1: u8, sw2: u8) -> Option { let code: usize = (sw1 as usize | sw2 as usize) << 8; - + match code { - code if code == ErrorResponse::GenericError as usize => { - Some(String::from("Generic error")) - }, - code if code == ErrorResponse::NoSpace as usize => { - Some(String::from("No space on device")) - }, + code if code == ErrorResponse::GenericError as usize => Some(String::from("Generic error")), + code if code == ErrorResponse::NoSpace as usize => Some(String::from("No space on device")), code if code == ErrorResponse::CommandAborted as usize => { Some(String::from("Command was aborted")) - }, + } code if code == ErrorResponse::AuthRequired as usize => { Some(String::from("Authentication required")) - }, - code if code == ErrorResponse::WrongSyntax as usize => { - Some(String::from("Wrong syntax")) - }, + } + code if code == ErrorResponse::WrongSyntax as usize => Some(String::from("Wrong syntax")), code if code == ErrorResponse::InvalidInstruction as usize => { Some(String::from("Invalid instruction")) - }, - code if code == SuccessResponse::Okay as usize => { - None - }, - sw1 if sw1 == SuccessResponse::MoreData as usize => { - None - }, - _ => { - Some(String::from("Unknown error")) - }, + } + code if code == SuccessResponse::Okay as usize => None, + sw1 if sw1 == SuccessResponse::MoreData as usize => None, + _ => Some(String::from("Unknown error")), } } fn to_tlv(tag: Tag, value: &[u8]) -> Vec { let mut buf = vec![tag as u8]; let len = value.len(); - + if len < 0x80 { buf.push(len as u8); } else if len < 0xff { @@ -97,7 +83,7 @@ fn to_tlv(tag: Tag, value: &[u8]) -> Vec { buf.push(0x82); buf.write_u16::(len as u16).unwrap(); } - + buf.write(value).unwrap(); buf } @@ -176,12 +162,12 @@ pub enum OathType { pub struct OathCredential { pub name: String, pub code: OathCode, -// TODO: Support this stuff -// pub oath_type: OathType, -// pub touch: bool, -// pub algo: OathAlgo, -// pub hidden: bool, -// pub steam: bool, + // TODO: Support this stuff + // pub oath_type: OathType, + // pub touch: bool, + // pub algo: OathAlgo, + // pub hidden: bool, + // pub steam: bool, } impl OathCredential { @@ -189,11 +175,11 @@ impl OathCredential { OathCredential { name: name.to_string(), code: code, -// oath_type: oath_type, -// touch: touch, -// algo: algo, -// hidden: name.starts_with("_hidden:"), -// steam: name.starts_with("Steam:"), + // oath_type: oath_type, + // touch: touch, + // algo: algo, + // hidden: name.starts_with("_hidden:"), + // steam: name.starts_with("Steam:"), } } } @@ -208,8 +194,8 @@ pub enum OathDigits { pub struct OathCode { pub digits: OathDigits, pub value: u32, -// pub expiration: u32, -// pub steam: bool, + // pub expiration: u32, + // pub steam: bool, } pub struct ApduResponse { @@ -222,9 +208,9 @@ pub struct YubiKey<'a> { pub name: &'a str, } -impl<'a> YubiKey<'a> { +impl<'a> YubiKey<'a> { /// Read the OATH codes from the device - pub fn get_oath_codes(&self) -> Result, String>{ + pub fn get_oath_codes(&self) -> Result, String> { // Establish a PC/SC context let ctx = match pcsc::Context::establish(pcsc::Scope::User) { Ok(ctx) => ctx, @@ -233,9 +219,9 @@ impl<'a> YubiKey<'a> { // Connect to the card let mut card = match ctx.connect( - &CString::new(self.name).unwrap(), - pcsc::ShareMode::Shared, - pcsc::Protocols::ANY + &CString::new(self.name).unwrap(), + pcsc::ShareMode::Shared, + pcsc::Protocols::ANY, ) { Ok(card) => card, Err(err) => return Err(format!("{}", err)), @@ -256,9 +242,17 @@ impl<'a> YubiKey<'a> { let mut response_buf = Vec::new(); // Request OATH codes from device - let response = self.apdu(&tx, 0, Instruction::CalculateAll as u8, 0, - 0x01, Some(&to_tlv(Tag::Challenge, - &time_challenge(Some(SystemTime::now()))))); + let response = self.apdu( + &tx, + 0, + Instruction::CalculateAll as u8, + 0, + 0x01, + Some(&to_tlv( + Tag::Challenge, + &time_challenge(Some(SystemTime::now())), + )), + ); // Handle errors from command match response { @@ -275,19 +269,19 @@ impl<'a> YubiKey<'a> { sw1 = more_resp.sw1; sw2 = more_resp.sw2; response_buf.extend(more_resp.buf); - }, + } Err(e) => { return Err(format!("{}", e)); - }, + } } } if let Some(msg) = to_error_response(sw1, sw2) { return Err(format!("{}", msg)); } - + return Ok(self.parse_list(&response_buf).unwrap()); - }, + } Err(e) => { return Err(format!("{}", e)); } @@ -298,7 +292,7 @@ impl<'a> YubiKey<'a> { pub fn parse_list(&self, b: &[u8]) -> Result, String> { let mut rdr = Cursor::new(b); let mut results = Vec::new(); - + loop { if let Err(_) = rdr.read_u8() { break; @@ -334,10 +328,10 @@ impl<'a> YubiKey<'a> { if let Err(_) = rdr.read_exact(&mut name) { break; }; - + rdr.read_u8().unwrap(); // TODO: Don't discard the response tag rdr.read_u8().unwrap(); // TODO: Don't discard the response lenght + 1 - + let digits = match rdr.read_u8() { Ok(6) => OathDigits::Six, Ok(8) => OathDigits::Eight, @@ -352,10 +346,10 @@ impl<'a> YubiKey<'a> { results.push(OathCredential::new( &String::from_utf8(name).unwrap(), - OathCode { digits, value } + OathCode { digits, value }, )); } - + Ok(results) } @@ -363,11 +357,11 @@ impl<'a> YubiKey<'a> { pub fn apdu( &self, tx: &pcsc::Transaction, - class: u8, - instruction: u8, - parameter1: u8, - parameter2: u8, - data: Option<&[u8]> + class: u8, + instruction: u8, + parameter1: u8, + parameter2: u8, + data: Option<&[u8]>, ) -> Result { // Create a container for the transaction payload let mut tx_buf = Vec::new(); @@ -386,7 +380,7 @@ impl<'a> YubiKey<'a> { tx_buf.push(instruction); tx_buf.push(parameter1); tx_buf.push(parameter2); - + // Construct and attach the data's byte count if nc > 255 { tx_buf.push(0); @@ -394,7 +388,7 @@ impl<'a> YubiKey<'a> { } else { tx_buf.push(nc as u8); } - + // Attach the data itself if included if let Some(data) = data { tx_buf.write(data).unwrap(); @@ -405,7 +399,7 @@ impl<'a> YubiKey<'a> { let mut s = String::new(); for byte in &tx_buf { s += &format!("{:02X} ", byte); - } + } println!("DEBUG (SEND) >> {}", s); } @@ -438,9 +432,8 @@ impl<'a> YubiKey<'a> { Ok(ApduResponse { buf, - sw1: *sw1, + sw1: *sw1, sw2: *sw2, }) } } - diff --git a/src/main.rs b/src/main.rs index 5eab039..6708496 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,17 +15,17 @@ fn main() { let context = pcsc::Context::establish(pcsc::Scope::User).unwrap(); let mut readers_buf = [0; 2048]; let readers = context.list_readers(&mut readers_buf).unwrap(); - + // Initialize a vector to track all our detected devices let mut yubikeys: Vec = Vec::new(); // Iterate over the connected USB devices for reader in readers { - yubikeys.push(lib_ykoath::YubiKey{ + yubikeys.push(lib_ykoath::YubiKey { name: reader.to_str().unwrap(), }); } - + // Show message if no YubiKey(s) if yubikeys.len() == 0 { println!("No yubikeys detected"); @@ -41,9 +41,9 @@ fn main() { Err(e) => { println!("ERROR {}", e); continue; - }, + } }; - + // Show message is node codes found if codes.len() == 0 { println!("No credentials on device {}", device_label); @@ -54,10 +54,8 @@ fn main() { let code = lib_ykoath::format_code(oath.code.value, oath.code.digits); let name_clone = oath.name.clone(); let mut label_vec: Vec<&str> = name_clone.split(":").collect(); - let mut code_entry_label: String = String::from( - label_vec.remove(0) - ); - + let mut code_entry_label: String = String::from(label_vec.remove(0)); + if label_vec.len() > 0 { code_entry_label.push_str(" ("); code_entry_label.push_str(&label_vec.join(""));