diff --git a/src/apdu.rs b/src/apdu.rs index b3e8e13..e407749 100644 --- a/src/apdu.rs +++ b/src/apdu.rs @@ -352,6 +352,12 @@ pub(crate) enum StatusWords { /// Successful execution Success, + /// PIN verification failure + VerifyFailError { + /// Remaining verification attempts + tries: u8, + }, + /// Security status not satisfied SecurityStatusError, @@ -379,6 +385,7 @@ impl StatusWords { pub fn code(self) -> u32 { match self { StatusWords::None => 0, + StatusWords::VerifyFailError { tries } => 0x63c0 & tries as u32, StatusWords::SecurityStatusError => 0x6982, StatusWords::AuthBlockedError => 0x6983, StatusWords::IncorrectParamError => 0x6a80, @@ -399,6 +406,9 @@ impl From for StatusWords { fn from(sw: u32) -> Self { match sw { 0x0000 => StatusWords::None, + sw if sw & 0xfff0 == 0x63c0 => StatusWords::VerifyFailError { + tries: (sw & 0x000f) as u8, + }, 0x6982 => StatusWords::SecurityStatusError, 0x6983 => StatusWords::AuthBlockedError, 0x6a80 => StatusWords::IncorrectParamError, diff --git a/src/error.rs b/src/error.rs index c8da1a9..79b7a78 100644 --- a/src/error.rs +++ b/src/error.rs @@ -68,7 +68,7 @@ pub enum Error { /// Wrong PIN WrongPin { /// Number of tries remaining - tries: u32, + tries: u8, }, /// Invalid object diff --git a/src/transaction.rs b/src/transaction.rs index df37b4f..68fa89f 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -184,7 +184,7 @@ impl<'tx> Transaction<'tx> { match response.status_words() { StatusWords::Success => Ok(()), StatusWords::AuthBlockedError => Err(Error::WrongPin { tries: 0 }), - StatusWords::Other(sw) if sw >> 8 == 0x63 => Err(Error::WrongPin { tries: sw & 0xf }), + StatusWords::VerifyFailError { tries } => Err(Error::WrongPin { tries }), _ => Err(Error::GenericError), } } @@ -215,7 +215,7 @@ impl<'tx> Transaction<'tx> { match status_words { StatusWords::Success => Ok(()), StatusWords::AuthBlockedError => Err(Error::PinLocked), - StatusWords::Other(sw) if sw >> 8 == 0x63 => Err(Error::WrongPin { tries: sw & 0xf }), + StatusWords::VerifyFailError { tries } => Err(Error::WrongPin { tries }), _ => { error!( "failed changing pin, token response code: {:x}.", diff --git a/src/yubikey.rs b/src/yubikey.rs index f1f5c0f..cedfc80 100644 --- a/src/yubikey.rs +++ b/src/yubikey.rs @@ -396,7 +396,7 @@ impl YubiKey { /// Get the number of PIN retries #[cfg(feature = "untested")] - pub fn get_pin_retries(&mut self) -> Result { + pub fn get_pin_retries(&mut self) -> Result { let txn = self.begin_transaction()?; // Force a re-select to unverify, because once verified the spec dictates that @@ -414,24 +414,15 @@ impl YubiKey { /// Set the number of PIN retries #[cfg(feature = "untested")] - pub fn set_pin_retries(&mut self, pin_tries: usize, puk_tries: usize) -> Result<(), Error> { + pub fn set_pin_retries(&mut self, pin_tries: u8, puk_tries: u8) -> Result<(), Error> { // Special case: if either retry count is 0, it's a successful no-op if pin_tries == 0 || puk_tries == 0 { return Ok(()); } - if pin_tries > 0xff || puk_tries > 0xff || pin_tries < 1 || puk_tries < 1 { - return Err(Error::RangeError); - } - let txn = self.begin_transaction()?; - let templ = [ - 0, - Ins::SetPinRetries.code(), - pin_tries as u8, - puk_tries as u8, - ]; + let templ = [0, Ins::SetPinRetries.code(), pin_tries, puk_tries]; let status_words = txn.transfer_data(&templ, &[], 255)?.status_words();