From b750b9cbbb17c6dd6596c34880f9a855a793b09d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 20 Nov 2019 12:06:49 +0000 Subject: [PATCH] Convert tries pointers into Result elements --- src/error.rs | 6 ++-- src/util.rs | 37 +++++++++++--------- src/yubikey.rs | 93 +++++++++++++++----------------------------------- 3 files changed, 52 insertions(+), 84 deletions(-) diff --git a/src/error.rs b/src/error.rs index 9e23a0b..e55178c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -63,7 +63,7 @@ pub enum ErrorKind { ParseError, /// Wrong PIN - WrongPin, + WrongPin { tries: i32 }, /// Invalid object InvalidObject, @@ -100,7 +100,7 @@ impl ErrorKind { ErrorKind::GenericError => "YKPIV_GENERIC_ERROR", ErrorKind::KeyError => "YKPIV_KEY_ERROR", ErrorKind::ParseError => "YKPIV_PARSE_ERROR", - ErrorKind::WrongPin => "YKPIV_WRONG_PIN", + ErrorKind::WrongPin { .. } => "YKPIV_WRONG_PIN", ErrorKind::InvalidObject => "YKPIV_INVALID_OBJECT", ErrorKind::AlgorithmError => "YKPIV_ALGORITHM_ERROR", ErrorKind::PinLocked => "YKPIV_PIN_LOCKED", @@ -122,7 +122,7 @@ impl ErrorKind { ErrorKind::GenericError => "generic error", ErrorKind::KeyError => "key error", ErrorKind::ParseError => "parse error", - ErrorKind::WrongPin => "wrong pin", + ErrorKind::WrongPin { .. } => "wrong pin", ErrorKind::InvalidObject => "invalid object", ErrorKind::AlgorithmError => "algorithm error", ErrorKind::PinLocked => "PIN locked", diff --git a/src/util.rs b/src/util.rs index e77bc06..f7bb6e9 100644 --- a/src/util.rs +++ b/src/util.rs @@ -510,7 +510,7 @@ pub unsafe fn ykpiv_util_block_puk(state: &mut YubiKey) -> Result<(), ErrorKind> let mut _currentBlock; let mut res = Ok(()); let mut puk = [0x30, 0x42, 0x41, 0x44, 0x46, 0x30, 0x30, 0x44]; - let mut tries: i32 = -1; + let mut tries_remaining: i32 = -1; let mut data = [0u8; YKPIV_OBJ_MAX_SIZE]; let mut cb_data: usize = data.len(); let mut p_item: *mut u8 = ptr::null_mut(); @@ -527,29 +527,34 @@ pub unsafe fn ykpiv_util_block_puk(state: &mut YubiKey) -> Result<(), ErrorKind> loop { if _currentBlock == 3 { - if tries != 0 { - res = ykpiv_change_puk( + if tries_remaining != 0 { + match ykpiv_change_puk( state, puk.as_ptr(), mem::size_of::<*const c_char>(), puk.as_ptr(), mem::size_of::<*const c_char>(), - &mut tries, - ); - - if res.is_ok() { - let _rhs = 1; - let mut _lhs = &mut puk[0]; - *_lhs += _rhs; - _currentBlock = 3; - } else { - if res != Err(ErrorKind::PinLocked) { + ) { + Ok(()) => { + let _rhs = 1; + let mut _lhs = &mut puk[0]; + *_lhs += _rhs; + _currentBlock = 3; + } + Err(ErrorKind::WrongPin { tries }) => { + tries_remaining = tries; _currentBlock = 3; continue; } - tries = 0; - res = Ok(()); - _currentBlock = 3; + Err(e) => { + if res != Err(ErrorKind::PinLocked) { + _currentBlock = 3; + continue; + } + tries_remaining = 0; + res = Ok(()); + _currentBlock = 3; + } } } else { let res = _read_metadata(state, TAG_ADMIN, data.as_mut_ptr(), &mut cb_data); diff --git a/src/yubikey.rs b/src/yubikey.rs index 42ccc2d..95c404a 100644 --- a/src/yubikey.rs +++ b/src/yubikey.rs @@ -558,7 +558,6 @@ pub unsafe fn ykpiv_list_readers( /// Reconnect to a YubiKey pub(crate) unsafe fn reconnect(state: &mut YubiKey) -> Result<(), ErrorKind> { let mut active_protocol: u32 = 0; - let mut tries: i32 = 0; if state.verbose != 0 { eprintln!("trying to reconnect to current reader."); @@ -576,7 +575,7 @@ pub(crate) unsafe fn reconnect(state: &mut YubiKey) -> Result<(), ErrorKind> { _ykpiv_select_application(state)?; if !state.pin.is_null() { - ykpiv_verify(state, state.pin as *const c_char, &mut tries) + ykpiv_verify(state, state.pin as *const c_char).map(|_| ()) } else { Ok(()) } @@ -1469,27 +1468,25 @@ pub(crate) unsafe fn _cache_pin( } /// Verify device PIN -pub unsafe fn ykpiv_verify( - state: &mut YubiKey, - pin: *const c_char, - tries: *mut i32, -) -> Result<(), ErrorKind> { +/// +/// Returns the number of tries remaining both on success and on a wrong PIN. +pub unsafe fn ykpiv_verify(state: &mut YubiKey, pin: *const c_char) -> Result { ykpiv_verify_select( state, pin, if !pin.is_null() { strlen(pin) } else { 0 }, - tries, false, ) } /// Verify device PIN +/// +/// Returns the number of tries remaining both on success and on a wrong PIN. pub(crate) unsafe fn _verify( state: &mut YubiKey, pin: *const c_char, pin_len: usize, - tries: *mut i32, -) -> Result<(), ErrorKind> { +) -> Result { let mut data = [0u8; 261]; let mut recv_len = data.len() as u32; let mut sw: i32 = 0; @@ -1524,8 +1521,8 @@ pub(crate) unsafe fn _verify( apdu.zeroize(); - if res.is_err() { - return res; + if let Err(e) = res { + return Err(e); } if sw == SW_SUCCESS { @@ -1535,43 +1532,37 @@ pub(crate) unsafe fn _verify( _cache_pin(state, pin, pin_len); } - if !tries.is_null() { - *tries = sw & 0xf; - } - Ok(()) + Ok(sw & 0xf) } else if sw >> 8 == 0x63 { - if !tries.is_null() { - *tries = sw & 0xf; - } - Err(ErrorKind::WrongPin) + Err(ErrorKind::WrongPin { tries: sw & 0xf }) } else if sw == SW_ERR_AUTH_BLOCKED { - if !tries.is_null() { - *tries = 0; - } - Err(ErrorKind::WrongPin) + Err(ErrorKind::WrongPin { tries: 0 }) } else { Err(ErrorKind::GenericError) } } /// Verify and select application +/// +/// Returns the number of tries remaining both on success and on a wrong PIN. pub unsafe fn ykpiv_verify_select( state: &mut YubiKey, pin: *const c_char, pin_len: usize, - tries: *mut i32, force_select: bool, -) -> Result<(), ErrorKind> { - let mut res = Ok(()); +) -> Result { + let mut res = Ok(-1); _ykpiv_begin_transaction(state)?; if force_select { - res = _ykpiv_ensure_application_selected(state); + if let Err(e) = _ykpiv_ensure_application_selected(state) { + res = Err(e); + } } if res.is_ok() { - res = _verify(state, pin, pin_len, tries); + res = _verify(state, pin, pin_len); } _ykpiv_end_transaction(state); @@ -1579,22 +1570,18 @@ pub unsafe fn ykpiv_verify_select( } /// Get the number of PIN retries -pub unsafe fn ykpiv_get_pin_retries(state: &mut YubiKey, tries: *mut i32) -> Result<(), ErrorKind> { - if tries.is_null() { - return Err(ErrorKind::ArgumentError); - } - +pub unsafe fn ykpiv_get_pin_retries(state: &mut YubiKey) -> Result { // Force a re-select to unverify, because once verified the spec dictates that // subsequent verify calls will return a "verification not needed" instead of // the number of tries left... _ykpiv_select_application(state)?; - let ykrc = ykpiv_verify(state, ptr::null(), tries); + let ykrc = ykpiv_verify(state, ptr::null()); // WRONG_PIN is expected on successful query. match ykrc { - Ok(()) | Err(ErrorKind::WrongPin) => Ok(()), - e => e, + Ok(tries) | Err(ErrorKind::WrongPin { tries }) => Ok(tries), + Err(e) => Err(e), } } @@ -1657,7 +1644,6 @@ pub(crate) unsafe fn _ykpiv_change_pin( current_pin_len: usize, new_pin: *const c_char, new_pin_len: usize, - tries: *mut i32, ) -> Result<(), ErrorKind> { let mut sw: i32 = 0; let mut templ = [0, YKPIV_INS_CHANGE_REFERENCE, 0, 0x80]; @@ -1721,11 +1707,7 @@ pub(crate) unsafe fn _ykpiv_change_pin( if sw != SW_SUCCESS { if sw >> 8 == 0x63 { - if !tries.is_null() { - *tries = sw & 0xf; - } - - return Err(ErrorKind::WrongPin); + return Err(ErrorKind::WrongPin { tries: sw & 0xf }); } else if sw == SW_ERR_AUTH_BLOCKED { return Err(ErrorKind::PinLocked); } else { @@ -1749,22 +1731,13 @@ pub unsafe fn ykpiv_change_pin( current_pin_len: usize, new_pin: *const c_char, new_pin_len: usize, - tries: *mut i32, ) -> Result<(), ErrorKind> { let mut res = Err(ErrorKind::GenericError); _ykpiv_begin_transaction(state)?; if _ykpiv_ensure_application_selected(state).is_ok() { - res = _ykpiv_change_pin( - state, - 0, - current_pin, - current_pin_len, - new_pin, - new_pin_len, - tries, - ); + res = _ykpiv_change_pin(state, 0, current_pin, current_pin_len, new_pin, new_pin_len); if res.is_ok() && !new_pin.is_null() { // Intentionally ignore errors. If the PIN fails to save, it will only @@ -1790,22 +1763,13 @@ pub unsafe fn ykpiv_change_puk( current_puk_len: usize, new_puk: *const c_char, new_puk_len: usize, - tries: *mut i32, ) -> Result<(), ErrorKind> { let mut res = Err(ErrorKind::GenericError); _ykpiv_begin_transaction(state)?; if _ykpiv_ensure_application_selected(state).is_ok() { - res = _ykpiv_change_pin( - state, - 2, - current_puk, - current_puk_len, - new_puk, - new_puk_len, - tries, - ); + res = _ykpiv_change_pin(state, 2, current_puk, current_puk_len, new_puk, new_puk_len); } _ykpiv_end_transaction(state); @@ -1820,14 +1784,13 @@ pub unsafe fn ykpiv_unblock_pin( puk_len: usize, new_pin: *const c_char, new_pin_len: usize, - tries: *mut i32, ) -> Result<(), ErrorKind> { let mut res = Err(ErrorKind::GenericError); _ykpiv_begin_transaction(state)?; if _ykpiv_ensure_application_selected(state).is_ok() { - res = _ykpiv_change_pin(state, 1, puk, puk_len, new_pin, new_pin_len, tries); + res = _ykpiv_change_pin(state, 1, puk, puk_len, new_pin, new_pin_len); } _ykpiv_end_transaction(state);