diff --git a/Cargo.lock b/Cargo.lock index 9fb7bf0..211bf75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -966,7 +966,11 @@ dependencies = [ "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "gumdrop 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle-encoding 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "x509-parser 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "yubikey-piv 0.0.3", ] diff --git a/src/transaction.rs b/src/transaction.rs index a5cefb4..0509b0d 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -18,6 +18,13 @@ use crate::mgm::{MgmKey, DES_LEN_3DES}; const CB_PIN_MAX: usize = 8; +#[cfg(feature = "untested")] +pub(crate) enum ChangeRefAction { + ChangePin, + ChangePuk, + UnblockPin, +} + /// Exclusive transaction with the YubiKey's PC/SC card. pub(crate) struct Transaction<'tx> { inner: pcsc::Transaction<'tx>, @@ -179,18 +186,24 @@ impl<'tx> Transaction<'tx> { /// Change the PIN. #[cfg(feature = "untested")] - pub fn change_pin(&self, action: i32, current_pin: &[u8], new_pin: &[u8]) -> Result<(), Error> { - let mut templ = [0, Ins::ChangeReference.code(), 0, 0x80]; - + pub fn change_ref( + &self, + action: ChangeRefAction, + current_pin: &[u8], + new_pin: &[u8], + ) -> Result<(), Error> { if current_pin.len() > CB_PIN_MAX || new_pin.len() > CB_PIN_MAX { return Err(Error::SizeError); } - if action == CHREF_ACT_UNBLOCK_PIN { - templ[1] = Ins::ResetRetry.code(); - } else if action == CHREF_ACT_CHANGE_PUK { - templ[3] = 0x81; - } + const PIN: u8 = 0x80; + const PUK: u8 = 0x81; + + let templ = match action { + ChangeRefAction::ChangePin => [0, Ins::ChangeReference.code(), 0, PIN], + ChangeRefAction::ChangePuk => [0, Ins::ChangeReference.code(), 0, PUK], + ChangeRefAction::UnblockPin => [0, Ins::ResetRetry.code(), 0, PIN], + }; let mut indata = Zeroizing::new([0xff; CB_PIN_MAX * 2]); indata[0..current_pin.len()].copy_from_slice(current_pin); diff --git a/src/yubikey.rs b/src/yubikey.rs index 1c7fffc..4c7ee76 100644 --- a/src/yubikey.rs +++ b/src/yubikey.rs @@ -50,8 +50,8 @@ use std::{ #[cfg(feature = "untested")] use crate::{ - apdu::StatusWords, metadata, Buffer, ObjectId, CB_BUF_MAX, CB_OBJ_MAX, MGMT_AID, TAG_ADMIN, - TAG_ADMIN_FLAGS_1, TAG_ADMIN_TIMESTAMP, + apdu::StatusWords, metadata, transaction::ChangeRefAction, Buffer, ObjectId, CB_BUF_MAX, + CB_OBJ_MAX, MGMT_AID, TAG_ADMIN, TAG_ADMIN_FLAGS_1, TAG_ADMIN_TIMESTAMP, }; use getrandom::getrandom; #[cfg(feature = "untested")] @@ -68,13 +68,6 @@ pub(crate) const ALGO_3DES: u8 = 0x03; /// Card management key pub(crate) const KEY_CARDMGM: u8 = 0x9b; -#[cfg(feature = "untested")] -pub(crate) const CHREF_ACT_CHANGE_PIN: i32 = 0; -#[cfg(feature = "untested")] -pub(crate) const CHREF_ACT_UNBLOCK_PIN: i32 = 1; -#[cfg(feature = "untested")] -pub(crate) const CHREF_ACT_CHANGE_PUK: i32 = 2; - const TAG_DYN_AUTH: u8 = 0x7c; /// Cached YubiKey PIN @@ -401,7 +394,7 @@ impl YubiKey { pub fn change_pin(&mut self, current_pin: &[u8], new_pin: &[u8]) -> Result<(), Error> { { let txn = self.begin_transaction()?; - txn.change_pin(CHREF_ACT_CHANGE_PIN, current_pin, new_pin)?; + txn.change_ref(ChangeRefAction::ChangePin, current_pin, new_pin)?; } if !new_pin.is_empty() { @@ -458,7 +451,7 @@ impl YubiKey { #[cfg(feature = "untested")] pub fn change_puk(&mut self, current_puk: &[u8], new_puk: &[u8]) -> Result<(), Error> { let txn = self.begin_transaction()?; - txn.change_pin(CHREF_ACT_CHANGE_PUK, current_puk, new_puk) + txn.change_ref(ChangeRefAction::ChangePuk, current_puk, new_puk) } /// Block PUK: permanently prevent the PIN from becoming unblocked @@ -472,7 +465,7 @@ impl YubiKey { while tries_remaining != 0 { // 2 -> change puk - let res = txn.change_pin(CHREF_ACT_CHANGE_PUK, &puk, &puk); + let res = txn.change_ref(ChangeRefAction::ChangePuk, &puk, &puk); match res { Ok(()) => puk[0] += 1, @@ -533,7 +526,7 @@ impl YubiKey { #[cfg(feature = "untested")] pub fn unblock_pin(&mut self, puk: &[u8], new_pin: &[u8]) -> Result<(), Error> { let txn = self.begin_transaction()?; - txn.change_pin(CHREF_ACT_UNBLOCK_PIN, puk, new_pin) + txn.change_ref(ChangeRefAction::UnblockPin, puk, new_pin) } /// Fetch an object from the YubiKey