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, ParseError,
/// Wrong PIN /// Wrong PIN
WrongPin, WrongPin { tries: i32 },
/// Invalid object /// Invalid object
InvalidObject, InvalidObject,
@@ -100,7 +100,7 @@ impl ErrorKind {
ErrorKind::GenericError => "YKPIV_GENERIC_ERROR", ErrorKind::GenericError => "YKPIV_GENERIC_ERROR",
ErrorKind::KeyError => "YKPIV_KEY_ERROR", ErrorKind::KeyError => "YKPIV_KEY_ERROR",
ErrorKind::ParseError => "YKPIV_PARSE_ERROR", ErrorKind::ParseError => "YKPIV_PARSE_ERROR",
ErrorKind::WrongPin => "YKPIV_WRONG_PIN", ErrorKind::WrongPin { .. } => "YKPIV_WRONG_PIN",
ErrorKind::InvalidObject => "YKPIV_INVALID_OBJECT", ErrorKind::InvalidObject => "YKPIV_INVALID_OBJECT",
ErrorKind::AlgorithmError => "YKPIV_ALGORITHM_ERROR", ErrorKind::AlgorithmError => "YKPIV_ALGORITHM_ERROR",
ErrorKind::PinLocked => "YKPIV_PIN_LOCKED", ErrorKind::PinLocked => "YKPIV_PIN_LOCKED",
@@ -122,7 +122,7 @@ impl ErrorKind {
ErrorKind::GenericError => "generic error", ErrorKind::GenericError => "generic error",
ErrorKind::KeyError => "key error", ErrorKind::KeyError => "key error",
ErrorKind::ParseError => "parse error", ErrorKind::ParseError => "parse error",
ErrorKind::WrongPin => "wrong pin", ErrorKind::WrongPin { .. } => "wrong pin",
ErrorKind::InvalidObject => "invalid object", ErrorKind::InvalidObject => "invalid object",
ErrorKind::AlgorithmError => "algorithm error", ErrorKind::AlgorithmError => "algorithm error",
ErrorKind::PinLocked => "PIN locked", ErrorKind::PinLocked => "PIN locked",
+14 -9
View File
@@ -510,7 +510,7 @@ pub unsafe fn ykpiv_util_block_puk(state: &mut YubiKey) -> Result<(), ErrorKind>
let mut _currentBlock; let mut _currentBlock;
let mut res = Ok(()); let mut res = Ok(());
let mut puk = [0x30, 0x42, 0x41, 0x44, 0x46, 0x30, 0x30, 0x44]; 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 data = [0u8; YKPIV_OBJ_MAX_SIZE];
let mut cb_data: usize = data.len(); let mut cb_data: usize = data.len();
let mut p_item: *mut u8 = ptr::null_mut(); let mut p_item: *mut u8 = ptr::null_mut();
@@ -527,30 +527,35 @@ pub unsafe fn ykpiv_util_block_puk(state: &mut YubiKey) -> Result<(), ErrorKind>
loop { loop {
if _currentBlock == 3 { if _currentBlock == 3 {
if tries != 0 { if tries_remaining != 0 {
res = ykpiv_change_puk( match ykpiv_change_puk(
state, state,
puk.as_ptr(), puk.as_ptr(),
mem::size_of::<*const c_char>(), mem::size_of::<*const c_char>(),
puk.as_ptr(), puk.as_ptr(),
mem::size_of::<*const c_char>(), mem::size_of::<*const c_char>(),
&mut tries, ) {
); Ok(()) => {
if res.is_ok() {
let _rhs = 1; let _rhs = 1;
let mut _lhs = &mut puk[0]; let mut _lhs = &mut puk[0];
*_lhs += _rhs; *_lhs += _rhs;
_currentBlock = 3; _currentBlock = 3;
} else { }
Err(ErrorKind::WrongPin { tries }) => {
tries_remaining = tries;
_currentBlock = 3;
continue;
}
Err(e) => {
if res != Err(ErrorKind::PinLocked) { if res != Err(ErrorKind::PinLocked) {
_currentBlock = 3; _currentBlock = 3;
continue; continue;
} }
tries = 0; tries_remaining = 0;
res = Ok(()); res = Ok(());
_currentBlock = 3; _currentBlock = 3;
} }
}
} else { } else {
let res = _read_metadata(state, TAG_ADMIN, data.as_mut_ptr(), &mut cb_data); 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 /// Reconnect to a YubiKey
pub(crate) unsafe fn reconnect(state: &mut YubiKey) -> Result<(), ErrorKind> { pub(crate) unsafe fn reconnect(state: &mut YubiKey) -> Result<(), ErrorKind> {
let mut active_protocol: u32 = 0; let mut active_protocol: u32 = 0;
let mut tries: i32 = 0;
if state.verbose != 0 { if state.verbose != 0 {
eprintln!("trying to reconnect to current reader."); 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)?; _ykpiv_select_application(state)?;
if !state.pin.is_null() { 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 { } else {
Ok(()) Ok(())
} }
@@ -1469,27 +1468,25 @@ pub(crate) unsafe fn _cache_pin(
} }
/// Verify device PIN /// Verify device PIN
pub unsafe fn ykpiv_verify( ///
state: &mut YubiKey, /// Returns the number of tries remaining both on success and on a wrong PIN.
pin: *const c_char, pub unsafe fn ykpiv_verify(state: &mut YubiKey, pin: *const c_char) -> Result<i32, ErrorKind> {
tries: *mut i32,
) -> Result<(), ErrorKind> {
ykpiv_verify_select( ykpiv_verify_select(
state, state,
pin, pin,
if !pin.is_null() { strlen(pin) } else { 0 }, if !pin.is_null() { strlen(pin) } else { 0 },
tries,
false, false,
) )
} }
/// Verify device PIN /// Verify device PIN
///
/// Returns the number of tries remaining both on success and on a wrong PIN.
pub(crate) unsafe fn _verify( pub(crate) unsafe fn _verify(
state: &mut YubiKey, state: &mut YubiKey,
pin: *const c_char, pin: *const c_char,
pin_len: usize, pin_len: usize,
tries: *mut i32, ) -> Result<i32, ErrorKind> {
) -> Result<(), ErrorKind> {
let mut data = [0u8; 261]; let mut data = [0u8; 261];
let mut recv_len = data.len() as u32; let mut recv_len = data.len() as u32;
let mut sw: i32 = 0; let mut sw: i32 = 0;
@@ -1524,8 +1521,8 @@ pub(crate) unsafe fn _verify(
apdu.zeroize(); apdu.zeroize();
if res.is_err() { if let Err(e) = res {
return res; return Err(e);
} }
if sw == SW_SUCCESS { if sw == SW_SUCCESS {
@@ -1535,43 +1532,37 @@ pub(crate) unsafe fn _verify(
_cache_pin(state, pin, pin_len); _cache_pin(state, pin, pin_len);
} }
if !tries.is_null() { Ok(sw & 0xf)
*tries = sw & 0xf;
}
Ok(())
} else if sw >> 8 == 0x63 { } else if sw >> 8 == 0x63 {
if !tries.is_null() { Err(ErrorKind::WrongPin { tries: sw & 0xf })
*tries = sw & 0xf;
}
Err(ErrorKind::WrongPin)
} else if sw == SW_ERR_AUTH_BLOCKED { } else if sw == SW_ERR_AUTH_BLOCKED {
if !tries.is_null() { Err(ErrorKind::WrongPin { tries: 0 })
*tries = 0;
}
Err(ErrorKind::WrongPin)
} else { } else {
Err(ErrorKind::GenericError) Err(ErrorKind::GenericError)
} }
} }
/// Verify and select application /// Verify and select application
///
/// Returns the number of tries remaining both on success and on a wrong PIN.
pub unsafe fn ykpiv_verify_select( pub unsafe fn ykpiv_verify_select(
state: &mut YubiKey, state: &mut YubiKey,
pin: *const c_char, pin: *const c_char,
pin_len: usize, pin_len: usize,
tries: *mut i32,
force_select: bool, force_select: bool,
) -> Result<(), ErrorKind> { ) -> Result<i32, ErrorKind> {
let mut res = Ok(()); let mut res = Ok(-1);
_ykpiv_begin_transaction(state)?; _ykpiv_begin_transaction(state)?;
if force_select { 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() { if res.is_ok() {
res = _verify(state, pin, pin_len, tries); res = _verify(state, pin, pin_len);
} }
_ykpiv_end_transaction(state); _ykpiv_end_transaction(state);
@@ -1579,22 +1570,18 @@ pub unsafe fn ykpiv_verify_select(
} }
/// Get the number of PIN retries /// Get the number of PIN retries
pub unsafe fn ykpiv_get_pin_retries(state: &mut YubiKey, tries: *mut i32) -> Result<(), ErrorKind> { pub unsafe fn ykpiv_get_pin_retries(state: &mut YubiKey) -> Result<i32, ErrorKind> {
if tries.is_null() {
return Err(ErrorKind::ArgumentError);
}
// 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
// subsequent verify calls will return a "verification not needed" instead of // subsequent verify calls will return a "verification not needed" instead of
// the number of tries left... // the number of tries left...
_ykpiv_select_application(state)?; _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. // WRONG_PIN is expected on successful query.
match ykrc { match ykrc {
Ok(()) | Err(ErrorKind::WrongPin) => Ok(()), Ok(tries) | Err(ErrorKind::WrongPin { tries }) => Ok(tries),
e => e, Err(e) => Err(e),
} }
} }
@@ -1657,7 +1644,6 @@ pub(crate) unsafe fn _ykpiv_change_pin(
current_pin_len: usize, current_pin_len: usize,
new_pin: *const c_char, new_pin: *const c_char,
new_pin_len: usize, new_pin_len: usize,
tries: *mut i32,
) -> Result<(), ErrorKind> { ) -> Result<(), ErrorKind> {
let mut sw: i32 = 0; let mut sw: i32 = 0;
let mut templ = [0, YKPIV_INS_CHANGE_REFERENCE, 0, 0x80]; 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 != SW_SUCCESS {
if sw >> 8 == 0x63 { if sw >> 8 == 0x63 {
if !tries.is_null() { return Err(ErrorKind::WrongPin { tries: sw & 0xf });
*tries = sw & 0xf;
}
return Err(ErrorKind::WrongPin);
} else if sw == SW_ERR_AUTH_BLOCKED { } else if sw == SW_ERR_AUTH_BLOCKED {
return Err(ErrorKind::PinLocked); return Err(ErrorKind::PinLocked);
} else { } else {
@@ -1749,22 +1731,13 @@ pub unsafe fn ykpiv_change_pin(
current_pin_len: usize, current_pin_len: usize,
new_pin: *const c_char, new_pin: *const c_char,
new_pin_len: usize, new_pin_len: usize,
tries: *mut i32,
) -> Result<(), ErrorKind> { ) -> Result<(), ErrorKind> {
let mut res = Err(ErrorKind::GenericError); let mut res = Err(ErrorKind::GenericError);
_ykpiv_begin_transaction(state)?; _ykpiv_begin_transaction(state)?;
if _ykpiv_ensure_application_selected(state).is_ok() { if _ykpiv_ensure_application_selected(state).is_ok() {
res = _ykpiv_change_pin( res = _ykpiv_change_pin(state, 0, current_pin, current_pin_len, new_pin, new_pin_len);
state,
0,
current_pin,
current_pin_len,
new_pin,
new_pin_len,
tries,
);
if res.is_ok() && !new_pin.is_null() { if res.is_ok() && !new_pin.is_null() {
// Intentionally ignore errors. If the PIN fails to save, it will only // 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, current_puk_len: usize,
new_puk: *const c_char, new_puk: *const c_char,
new_puk_len: usize, new_puk_len: usize,
tries: *mut i32,
) -> Result<(), ErrorKind> { ) -> Result<(), ErrorKind> {
let mut res = Err(ErrorKind::GenericError); let mut res = Err(ErrorKind::GenericError);
_ykpiv_begin_transaction(state)?; _ykpiv_begin_transaction(state)?;
if _ykpiv_ensure_application_selected(state).is_ok() { if _ykpiv_ensure_application_selected(state).is_ok() {
res = _ykpiv_change_pin( res = _ykpiv_change_pin(state, 2, current_puk, current_puk_len, new_puk, new_puk_len);
state,
2,
current_puk,
current_puk_len,
new_puk,
new_puk_len,
tries,
);
} }
_ykpiv_end_transaction(state); _ykpiv_end_transaction(state);
@@ -1820,14 +1784,13 @@ pub unsafe fn ykpiv_unblock_pin(
puk_len: usize, puk_len: usize,
new_pin: *const c_char, new_pin: *const c_char,
new_pin_len: usize, new_pin_len: usize,
tries: *mut i32,
) -> Result<(), ErrorKind> { ) -> Result<(), ErrorKind> {
let mut res = Err(ErrorKind::GenericError); let mut res = Err(ErrorKind::GenericError);
_ykpiv_begin_transaction(state)?; _ykpiv_begin_transaction(state)?;
if _ykpiv_ensure_application_selected(state).is_ok() { 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); _ykpiv_end_transaction(state);