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
|
/// Successful execution
|
||||||
Success,
|
Success,
|
||||||
|
|
||||||
|
/// PIN verification failure
|
||||||
|
VerifyFailError {
|
||||||
|
/// Remaining verification attempts
|
||||||
|
tries: u8,
|
||||||
|
},
|
||||||
|
|
||||||
/// Security status not satisfied
|
/// Security status not satisfied
|
||||||
SecurityStatusError,
|
SecurityStatusError,
|
||||||
|
|
||||||
@@ -379,6 +385,7 @@ impl StatusWords {
|
|||||||
pub fn code(self) -> u32 {
|
pub fn code(self) -> u32 {
|
||||||
match self {
|
match self {
|
||||||
StatusWords::None => 0,
|
StatusWords::None => 0,
|
||||||
|
StatusWords::VerifyFailError { tries } => 0x63c0 & tries as u32,
|
||||||
StatusWords::SecurityStatusError => 0x6982,
|
StatusWords::SecurityStatusError => 0x6982,
|
||||||
StatusWords::AuthBlockedError => 0x6983,
|
StatusWords::AuthBlockedError => 0x6983,
|
||||||
StatusWords::IncorrectParamError => 0x6a80,
|
StatusWords::IncorrectParamError => 0x6a80,
|
||||||
@@ -399,6 +406,9 @@ impl From<u32> for StatusWords {
|
|||||||
fn from(sw: u32) -> Self {
|
fn from(sw: u32) -> Self {
|
||||||
match sw {
|
match sw {
|
||||||
0x0000 => StatusWords::None,
|
0x0000 => StatusWords::None,
|
||||||
|
sw if sw & 0xfff0 == 0x63c0 => StatusWords::VerifyFailError {
|
||||||
|
tries: (sw & 0x000f) as u8,
|
||||||
|
},
|
||||||
0x6982 => StatusWords::SecurityStatusError,
|
0x6982 => StatusWords::SecurityStatusError,
|
||||||
0x6983 => StatusWords::AuthBlockedError,
|
0x6983 => StatusWords::AuthBlockedError,
|
||||||
0x6a80 => StatusWords::IncorrectParamError,
|
0x6a80 => StatusWords::IncorrectParamError,
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@ pub enum Error {
|
|||||||
/// Wrong PIN
|
/// Wrong PIN
|
||||||
WrongPin {
|
WrongPin {
|
||||||
/// Number of tries remaining
|
/// Number of tries remaining
|
||||||
tries: u32,
|
tries: u8,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Invalid object
|
/// Invalid object
|
||||||
|
|||||||
+2
-2
@@ -184,7 +184,7 @@ impl<'tx> Transaction<'tx> {
|
|||||||
match response.status_words() {
|
match response.status_words() {
|
||||||
StatusWords::Success => Ok(()),
|
StatusWords::Success => Ok(()),
|
||||||
StatusWords::AuthBlockedError => Err(Error::WrongPin { tries: 0 }),
|
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),
|
_ => Err(Error::GenericError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,7 +215,7 @@ impl<'tx> Transaction<'tx> {
|
|||||||
match status_words {
|
match status_words {
|
||||||
StatusWords::Success => Ok(()),
|
StatusWords::Success => Ok(()),
|
||||||
StatusWords::AuthBlockedError => Err(Error::PinLocked),
|
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!(
|
error!(
|
||||||
"failed changing pin, token response code: {:x}.",
|
"failed changing pin, token response code: {:x}.",
|
||||||
|
|||||||
+3
-12
@@ -396,7 +396,7 @@ impl YubiKey {
|
|||||||
|
|
||||||
/// Get the number of PIN retries
|
/// Get the number of PIN retries
|
||||||
#[cfg(feature = "untested")]
|
#[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()?;
|
let txn = self.begin_transaction()?;
|
||||||
|
|
||||||
// Force a re-select to unverify, because once verified the spec dictates that
|
// 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
|
/// Set the number of PIN retries
|
||||||
#[cfg(feature = "untested")]
|
#[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
|
// Special case: if either retry count is 0, it's a successful no-op
|
||||||
if pin_tries == 0 || puk_tries == 0 {
|
if pin_tries == 0 || puk_tries == 0 {
|
||||||
return Ok(());
|
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 txn = self.begin_transaction()?;
|
||||||
|
|
||||||
let templ = [
|
let templ = [0, Ins::SetPinRetries.code(), pin_tries, puk_tries];
|
||||||
0,
|
|
||||||
Ins::SetPinRetries.code(),
|
|
||||||
pin_tries as u8,
|
|
||||||
puk_tries as u8,
|
|
||||||
];
|
|
||||||
|
|
||||||
let status_words = txn.transfer_data(&templ, &[], 255)?.status_words();
|
let status_words = txn.transfer_data(&templ, &[], 255)?.status_words();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user