diff --git a/Cargo.lock b/Cargo.lock index da18b1b..6e83adb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2178,6 +2178,7 @@ dependencies = [ "base64 0.13.0", "chrono", "clap", + "digest", "hex", "openpgp-card", "openssl", @@ -2191,6 +2192,8 @@ dependencies = [ "sha2", "simpledateformat", "u2f", + "x509", + "x509-parser", "yubico_manager", "yubikey", ] diff --git a/Cargo.toml b/Cargo.toml index b26e707..ad75e13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,5 +24,8 @@ simpledateformat = "0.1.2" ring = "0.16.20" openssl = "0.10.35" pem = "0.8.3" +digest = "0.9.0" yubikey = "0.4.2" yubico_manager = "0.8.1" +x509 = "0.2" +x509-parser = "0.9" diff --git a/src/chall.rs b/src/chall.rs index 5a823e8..e60e96e 100644 --- a/src/chall.rs +++ b/src/chall.rs @@ -10,7 +10,7 @@ impl Command for CommandImpl { fn name(&self) -> &str { "chall" } fn subcommand<'a>(&self) -> App<'a, 'a> { - SubCommand::with_name(self.name()).about("OpenPGP Card List subcommand") + SubCommand::with_name(self.name()).about("Yubikey challenge-response hmac") .arg(Arg::with_name("challenge").long("challenge").takes_value(true).help("Challenge")) .arg(Arg::with_name("challenge-hex").long("challenge-hex").takes_value(true).help("Challenge HEX")) .arg(Arg::with_name("json").long("json").help("JSON output")) diff --git a/src/challconfig.rs b/src/challconfig.rs index 2199df4..86fd6e4 100644 --- a/src/challconfig.rs +++ b/src/challconfig.rs @@ -11,7 +11,7 @@ impl Command for CommandImpl { fn name(&self) -> &str { "chall-config" } fn subcommand<'a>(&self) -> App<'a, 'a> { - SubCommand::with_name(self.name()).about("OpenPGP Card List subcommand") + SubCommand::with_name(self.name()).about("Yubikey challenge-response hmac config") .arg(Arg::with_name("secret").long("secret").takes_value(true).help("Secret")) .arg(Arg::with_name("secret-hex").long("secret-hex").takes_value(true).help("Secret HEX")) .arg(Arg::with_name("yes-config-chall").long("yes-config-chall").help("Config chall key")) diff --git a/src/pgpcardlist.rs b/src/pgpcardlist.rs index 4ea3891..cbdd5be 100644 --- a/src/pgpcardlist.rs +++ b/src/pgpcardlist.rs @@ -63,9 +63,10 @@ impl Command for CommandImpl { Result::Ok(user) => { let h = hex::decode("8f25018489d6fe0dec34a352314c38dc146247b7de65735790f4398a92afa84b").unwrap(); let mut hh = [0_u8; 0x20]; - for i in 0..hh.len() { - hh[i] = h[i]; - } + // for i in 0..hh.len() { + // hh[i] = h[i]; + // } + hh.clone_from_slice(&h[..0x20]); let aa = user.signature_for_hash(Hash::SHA256(hh)); println!("////// {}", hex::encode(&aa.unwrap())); } diff --git a/src/piv.rs b/src/piv.rs index 3a0d93e..fa9455e 100644 --- a/src/piv.rs +++ b/src/piv.rs @@ -1,5 +1,13 @@ use clap::{ArgMatches, SubCommand, App, Arg}; use crate::cmd::{Command, CommandError}; +use yubikey::{YubiKey, Certificate}; +use yubikey::piv::SlotId; +use rust_util::XResult; +use sha2::Sha256; +use x509_parser::parse_x509_certificate; +use pem::Pem; +use digest::Digest; +use rust_util::util_msg::MessageType; pub struct CommandImpl; @@ -12,6 +20,69 @@ impl Command for CommandImpl { } fn run(&self, _arg_matches: &ArgMatches, _sub_arg_matches: &ArgMatches) -> CommandError { + let mut yk = YubiKey::open()?; + success!("Name: {}", yk.name()); + success!("Version: {}", yk.version()); + success!("Serial: {}", yk.serial()); + match yk.chuid() { + Ok(chuid) => success!("CHUID: {}",chuid.to_string()), + Err(e) => warning!("CHUID: {}", e), + } + match yk.cccid() { + Ok(cccid) => success!("CCCID: {}",cccid.to_string()), + Err(e) => warning!("CCCID: {}", e), + } + match yk.get_pin_retries() { + Ok(pin_retries) => success!("PIN retries: {}",pin_retries), + Err(e) => warning!("PIN retries: {}", e), + } + for slot in yubikey::piv::SLOTS.iter().cloned() { + print_cert_info(&mut yk, slot).ok(); + } Ok(()) } } + +fn print_cert_info(yubikey: &mut YubiKey, slot: SlotId) -> XResult<()> { + let cert = match Certificate::read(yubikey, slot) { + Ok(c) => c, + Err(e) => { + debugging!("error reading certificate in slot {:?}: {}", slot, e); + return simple_error!("error reading certificate in slot {:?}: {}", slot, e); + } + }; + let buf = cert.into_buffer(); + + if !buf.is_empty() { + let fingerprint_sha256 = Sha256::digest(&buf); + + let slot_id: u8 = slot.into(); + success!("Slot: {}", format!("{:x}", slot_id)); + + rust_util::util_msg::when(MessageType::DEBUG, || { + let cert_pem_obj = Pem { + tag: String::from("CERTIFICATE"), + contents: buf.to_vec(), + }; + debugging!("{}", pem::encode(&cert_pem_obj).trim()); + }); + + match parse_x509_certificate(&buf) { + Ok((_rem, cert)) => { + success!("Algorithm: {}", cert.tbs_certificate.subject_pki.algorithm.algorithm); + + success!("Subject: {}", cert.tbs_certificate.subject); + success!("Issuer: {}", cert.tbs_certificate.issuer); + success!("Fingerprint SHA256: {}", hex::encode(fingerprint_sha256)); + success!("Not Before: {}", cert.tbs_certificate.validity.not_before.to_rfc2822()); + success!("Not After: {}", cert.tbs_certificate.validity.not_after.to_rfc2822()); + } + _ => { + warning!("Failed to parse certificate"); + return Ok(()); + } + }; + } + + Ok(()) +}