Make PIN verification failure a StatusWord case
Retry count is now u8, as it cannot exceed 16 (being returned in the lower half of SW2).
This commit is contained in:
+10
@@ -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<u32> 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,
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ pub enum Error {
|
||||
/// Wrong PIN
|
||||
WrongPin {
|
||||
/// Number of tries remaining
|
||||
tries: u32,
|
||||
tries: u8,
|
||||
},
|
||||
|
||||
/// Invalid object
|
||||
|
||||
+2
-2
@@ -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}.",
|
||||
|
||||
+3
-12
@@ -396,7 +396,7 @@ impl YubiKey {
|
||||
|
||||
/// Get the number of PIN retries
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn get_pin_retries(&mut self) -> Result<u32, Error> {
|
||||
pub fn get_pin_retries(&mut self) -> Result<u8, Error> {
|
||||
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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user