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:
Jack Grigg
2019-11-30 15:22:14 +00:00
parent 9fe363661e
commit 4b5cd8dd45
4 changed files with 16 additions and 15 deletions
+10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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();