Convert tries pointers into Result elements

This commit is contained in:
Jack Grigg
2019-11-20 12:06:49 +00:00
parent 31ef465571
commit b750b9cbbb
3 changed files with 52 additions and 84 deletions
+3 -3
View File
@@ -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",
+21 -16
View File
@@ -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);
+28 -65
View File
@@ -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<i32, ErrorKind> {
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<i32, ErrorKind> {
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<i32, ErrorKind> {
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<i32, ErrorKind> {
// 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);