Merge pull request #15 from tarcieri/apdu-cleanups

Clean up APDU construction with builder API
This commit is contained in:
Tony Arcieri
2019-11-21 09:18:30 -08:00
committed by GitHub
3 changed files with 222 additions and 187 deletions
+75 -10
View File
@@ -1,7 +1,13 @@
//! Application Protocol Data Unit (APDU) //! Application Protocol Data Unit (APDU)
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use zeroize::Zeroize; use zeroize::{Zeroize, Zeroizing};
/// Size of a serialized APDU (5 byte header + 255 bytes data)
pub const APDU_SIZE: usize = 260;
/// Buffer type (self-zeroizing byte vector)
pub(crate) type Buffer = Zeroizing<Vec<u8>>;
/// Application Protocol Data Unit (APDU). /// Application Protocol Data Unit (APDU).
/// ///
@@ -10,30 +16,83 @@ use zeroize::Zeroize;
#[derive(Clone)] #[derive(Clone)]
pub struct APDU { pub struct APDU {
/// Instruction class - indicates the type of command, e.g. interindustry or proprietary /// Instruction class - indicates the type of command, e.g. interindustry or proprietary
pub cla: u8, cla: u8,
/// Instruction code - indicates the specific command, e.g. "write data" /// Instruction code - indicates the specific command, e.g. "write data"
pub ins: u8, ins: u8,
/// Instruction parameter 1 for the command, e.g. offset into file at which to write the data /// Instruction parameter 1 for the command, e.g. offset into file at which to write the data
pub p1: u8, p1: u8,
/// Instruction parameter 2 for the command /// Instruction parameter 2 for the command
pub p2: u8, p2: u8,
/// Length of command - encodes the number of bytes of command data to follow /// Length of command - encodes the number of bytes of command data to follow
pub lc: u8, lc: u8,
/// Command data /// Command data
pub data: [u8; 255], data: [u8; 255],
} }
impl APDU { impl APDU {
/// Get a mut pointer to this APDU /// Create a new APDU with the given instruction code
// TODO(tarcieri): eliminate pointers and use all safe references pub fn new(ins: u8) -> Self {
pub(crate) fn as_mut_ptr(&mut self) -> *mut APDU { let mut apdu = Self::default();
apdu.ins = ins;
apdu
}
/// Set this APDU's class
pub fn cla(&mut self, value: u8) -> &mut Self {
self.cla = value;
self self
} }
/// Set this APDU's first parameter only
pub fn p1(&mut self, value: u8) -> &mut Self {
self.p1 = value;
self
}
/// Set both parameters for this APDU
pub fn params(&mut self, p1: u8, p2: u8) -> &mut Self {
self.p1 = p1;
self.p2 = p2;
self
}
/// Set the command data for this APDU.
///
/// Panics if the byte slice is more than 255 bytes!
pub fn data(&mut self, bytes: impl AsRef<[u8]>) -> &mut Self {
assert_eq!(self.lc, 0, "APDU command already set!");
let bytes = bytes.as_ref();
assert!(
bytes.len() <= self.data.len(),
"APDU command data too large: {}-bytes",
bytes.len()
);
self.lc = bytes.len() as u8;
self.data[..bytes.len()].copy_from_slice(bytes);
self
}
/// Consume this APDU and return a self-zeroizing buffer
pub fn to_bytes(&self) -> Buffer {
let mut bytes = Vec::with_capacity(APDU_SIZE);
bytes.push(self.cla);
bytes.push(self.ins);
bytes.push(self.p1);
bytes.push(self.p2);
bytes.push(self.lc);
bytes.extend_from_slice(self.data.as_ref());
Zeroizing::new(bytes)
}
} }
impl Debug for APDU { impl Debug for APDU {
@@ -64,6 +123,12 @@ impl Default for APDU {
} }
} }
impl Drop for APDU {
fn drop(&mut self) {
self.zeroize();
}
}
impl Zeroize for APDU { impl Zeroize for APDU {
fn zeroize(&mut self) { fn zeroize(&mut self) {
self.cla.zeroize(); self.cla.zeroize();
+2 -1
View File
@@ -1607,12 +1607,13 @@ pub unsafe fn ykpiv_util_set_protected_mgm(
if ykrc.is_err() { if ykrc.is_err() {
// if set_mgmkey fails with KeyError, it means the generated key is weak // if set_mgmkey fails with KeyError, it means the generated key is weak
// otherwise, log a warning, since the device mgm key is corrupt or we're in // otherwise, log a warning, since the device mgm key is corrupt or we're in
// a yubikey where we can't set the mgm key // a state where we can't set the mgm key
if Err(Error::KeyError) != ykrc { if Err(Error::KeyError) != ykrc {
error!( error!(
"could not set new derived mgm key, err = {}", "could not set new derived mgm key, err = {}",
ykrc.as_ref().unwrap_err() ykrc.as_ref().unwrap_err()
); );
let _ = yubikey._ykpiv_end_transaction(); let _ = yubikey._ykpiv_end_transaction();
return ykrc; return ykrc;
} }
+145 -176
View File
@@ -42,7 +42,7 @@ use crate::{
use getrandom::getrandom; use getrandom::getrandom;
use libc::{c_char, free, malloc, memcmp, memcpy, memmove, memset, strlen, strncasecmp}; use libc::{c_char, free, malloc, memcmp, memcpy, memmove, memset, strlen, strncasecmp};
use log::{error, info, trace, warn}; use log::{error, info, trace, warn};
use std::{convert::TryInto, ffi::CStr, mem, os::raw::c_void, ptr, slice}; use std::{ffi::CStr, os::raw::c_void, ptr, slice};
use zeroize::Zeroize; use zeroize::Zeroize;
extern "C" { extern "C" {
@@ -90,7 +90,7 @@ extern "C" {
fn SCardTransmit( fn SCardTransmit(
hCard: i32, hCard: i32,
pioSendPci: *const c_void, pioSendPci: *const c_void,
pbSendBuffer: *mut c_char, pbSendBuffer: *const c_char,
cbSendLength: u32, cbSendLength: u32,
pioRecvPci: *const c_void, pioRecvPci: *const c_void,
pbRecvBuffer: *mut u8, pbRecvBuffer: *mut u8,
@@ -197,18 +197,13 @@ impl YubiKey {
let mut recv_len = data.len() as u32; let mut recv_len = data.len() as u32;
let mut sw = 0i32; let mut sw = 0i32;
let mut apdu = APDU::default(); let apdu = APDU::new(YKPIV_INS_SELECT_APPLICATION)
apdu.ins = YKPIV_INS_SELECT_APPLICATION; .p1(0x04)
apdu.p1 = 0x04; .data(&AID)
apdu.lc = AID.len() as u8; .to_bytes();
memcpy( if let Err(e) = self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, &mut sw)
apdu.data.as_mut_ptr() as *mut c_void, {
AID.as_ptr() as *const c_void,
AID.len(),
);
if let Err(e) = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw) {
error!("failed communicating with card: \'{}\'", e); error!("failed communicating with card: \'{}\'", e);
return Err(e); return Err(e);
} }
@@ -537,37 +532,33 @@ impl YubiKey {
let mut data = [0u8; 261]; let mut data = [0u8; 261];
recv_len = data.len() as u32; recv_len = data.len() as u32;
let mut apdu = APDU::default(); let cla = if in_ptr.offset(0xff) < in_data.offset(in_len) {
apdu.cla = *templ; 0x10
apdu.ins = *templ.offset(1);
apdu.p1 = *templ.offset(2);
apdu.p2 = *templ.offset(3);
if in_ptr.offset(0xff) < in_data.offset(in_len) {
apdu.cla = 0x10;
} else { } else {
this_size = in_data.offset(in_len) as usize - in_ptr as usize; this_size = in_data.offset(in_len) as usize - in_ptr as usize;
} *templ
};
trace!("going to send {} bytes in this go", this_size); trace!("going to send {} bytes in this go", this_size);
apdu.lc = this_size.try_into().unwrap(); let apdu = APDU::new(*templ.offset(1))
memcpy( .cla(cla)
apdu.data.as_mut_ptr() as *mut c_void, .params(*templ.offset(2), *templ.offset(3))
in_ptr as *const c_void, .data(slice::from_raw_parts(in_ptr, this_size))
this_size, .to_bytes();
);
res = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, sw); res = self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, sw);
if res.is_err() { if res.is_err() {
_currentBlock = 24; _currentBlock = 24;
break; break;
} }
if *sw != SW_SUCCESS && (*sw >> 8 != 0x61) { if *sw != SW_SUCCESS && (*sw >> 8 != 0x61) {
_currentBlock = 24; _currentBlock = 24;
break; break;
} }
if (*out_len) if (*out_len)
.wrapping_add(recv_len as (usize)) .wrapping_add(recv_len as (usize))
.wrapping_sub(2usize) .wrapping_sub(2usize)
@@ -610,9 +601,9 @@ impl YubiKey {
*sw & 0xff *sw & 0xff
); );
let mut apdu = APDU::default(); let apdu = APDU::new(YKPIV_INS_GET_RESPONSE_APDU).to_bytes();
apdu.ins = YKPIV_INS_GET_RESPONSE_APDU;
res = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, sw); res = self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, sw);
if res.is_err() { if res.is_err() {
_currentBlock = 24; _currentBlock = 24;
@@ -686,20 +677,21 @@ impl YubiKey {
/// Send data /// Send data
pub(crate) unsafe fn _send_data( pub(crate) unsafe fn _send_data(
&mut self, &mut self,
apdu: &mut APDU, apdu: impl AsRef<[u8]>,
data: *mut u8, data: *mut u8,
recv_len: *mut u32, recv_len: *mut u32,
sw: *mut i32, sw: *mut i32,
) -> Result<(), Error> { ) -> Result<(), Error> {
let send_len = apdu.lc as u32 + 5; let send_len = apdu.as_ref().len() as u32;
let apdu_ptr = apdu.as_ref().as_ptr();
let mut tmp_len = *recv_len; let mut tmp_len = *recv_len;
trace!("> {:?}", apdu); trace!("> {:?}", apdu.as_ref());
let rc = SCardTransmit( let rc = SCardTransmit(
self.card, self.card,
SCARD_PCI_T1, SCARD_PCI_T1,
apdu.as_mut_ptr() as *mut i8, apdu_ptr as *const i8,
send_len, send_len,
ptr::null(), ptr::null(),
data, data,
@@ -729,9 +721,6 @@ impl YubiKey {
&mut self, &mut self,
key: Option<&[u8; DES_LEN_3DES]>, key: Option<&[u8; DES_LEN_3DES]>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut data = [0u8; 261];
let mut recv_len = data.len() as u32;
let mut sw: i32 = 0;
let mut res = Ok(()); let mut res = Ok(());
self._ykpiv_begin_transaction()?; self._ykpiv_begin_transaction()?;
@@ -741,16 +730,16 @@ impl YubiKey {
let mgm_key = DesKey::from_bytes(*key.unwrap_or(DEFAULT_AUTH_KEY)); let mgm_key = DesKey::from_bytes(*key.unwrap_or(DEFAULT_AUTH_KEY));
// get a challenge from the card // get a challenge from the card
let mut apdu = APDU::default(); let apdu = APDU::new(YKPIV_INS_AUTHENTICATE)
apdu.ins = YKPIV_INS_AUTHENTICATE; .params(YKPIV_ALGO_3DES, YKPIV_KEY_CARDMGM)
apdu.p1 = YKPIV_ALGO_3DES; // triple des .data(&[0x7c, 0x02, 0x80, 0x00])
apdu.p2 = YKPIV_KEY_CARDMGM; // management key .to_bytes();
apdu.lc = 0x04;
apdu.data[0] = 0x7c;
apdu.data[1] = 0x02;
apdu.data[2] = 0x80;
res = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw); let mut data = [0u8; 261];
let mut recv_len = data.len() as u32;
let mut sw: i32 = 0;
res = self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, &mut sw);
if res.is_err() { if res.is_err() {
let _ = self._ykpiv_end_transaction(); let _ = self._ykpiv_end_transaction();
@@ -768,28 +757,30 @@ impl YubiKey {
des_decrypt(&mgm_key, &challenge, &mut response); des_decrypt(&mgm_key, &challenge, &mut response);
recv_len = data.len() as u32; recv_len = data.len() as u32;
apdu = APDU::default();
apdu.ins = YKPIV_INS_AUTHENTICATE; let mut data = [0u8; 22];
apdu.p1 = YKPIV_ALGO_3DES; // triple des data[0] = 0x7c;
apdu.p2 = YKPIV_KEY_CARDMGM; // management key data[1] = 20; // 2 + 8 + 2 +8
apdu.data[0] = 0x7c; data[2] = 0x80;
apdu.data[1] = 20; // 2 + 8 + 2 +8 data[3] = 8;
apdu.data[2] = 0x80; data[4..12].copy_from_slice(&response);
apdu.data[3] = 8; data[12] = 0x81;
apdu.data[4..12].copy_from_slice(&response); data[13] = 8;
apdu.data[12] = 0x81;
apdu.data[13] = 8;
if getrandom(&mut data[14..22]).is_err() { if getrandom(&mut data[14..22]).is_err() {
error!("failed getting randomness for authentication."); error!("failed getting randomness for authentication.");
let _ = self._ykpiv_end_transaction(); let _ = self._ykpiv_end_transaction();
return Err(Error::RandomnessError); return Err(Error::RandomnessError);
} }
challenge.copy_from_slice(&data[14..22]); challenge.copy_from_slice(&data[14..22]);
apdu.lc = 22; let apdu = APDU::new(YKPIV_INS_AUTHENTICATE)
.params(YKPIV_ALGO_3DES, YKPIV_KEY_CARDMGM)
.data(&data)
.to_bytes();
res = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw); res = self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, &mut sw);
if res.is_err() { if res.is_err() {
let _ = self._ykpiv_end_transaction(); let _ = self._ykpiv_end_transaction();
@@ -825,11 +816,7 @@ impl YubiKey {
new_key: &[u8; DES_LEN_3DES], new_key: &[u8; DES_LEN_3DES],
touch: u8, touch: u8,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut data = [0u8; 261];
let mut recv_len = data.len() as u32;
let mut sw: i32 = 0;
let mut res = Ok(()); let mut res = Ok(());
let mut apdu = APDU::default();
self._ykpiv_begin_transaction()?; self._ykpiv_begin_transaction()?;
@@ -839,36 +826,41 @@ impl YubiKey {
"won't set new key '{:?}' since it's weak (with odd parity)", "won't set new key '{:?}' since it's weak (with odd parity)",
new_key new_key
); );
res = Err(Error::KeyError);
} else {
apdu.ins = YKPIV_INS_SET_MGMKEY;
apdu.p1 = 0xff;
apdu.p2 = match touch { let _ = self._ykpiv_end_transaction();
0 => 0xff, return Err(Error::KeyError);
1 => 0xfe, }
_ => {
let _ = self._ykpiv_end_transaction();
return Err(Error::GenericError);
}
};
apdu.lc = DES_LEN_3DES as u8 + 3; let p2 = match touch {
apdu.data[0] = YKPIV_ALGO_3DES; 0 => 0xff,
apdu.data[1] = YKPIV_KEY_CARDMGM; 1 => 0xfe,
apdu.data[2] = DES_LEN_3DES as u8; _ => {
apdu.data[3..3 + DES_LEN_3DES].copy_from_slice(new_key); let _ = self._ykpiv_end_transaction();
return Err(Error::GenericError);
res = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw);
if res.is_ok() && sw != SW_SUCCESS {
res = Err(Error::GenericError);
} }
};
let mut data = [0u8; DES_LEN_3DES + 3];
data[0] = YKPIV_ALGO_3DES;
data[1] = YKPIV_KEY_CARDMGM;
data[2] = DES_LEN_3DES as u8;
data[3..3 + DES_LEN_3DES].copy_from_slice(new_key);
let apdu = APDU::new(YKPIV_INS_SET_MGMKEY)
.params(0xff, p2)
.data(&data)
.to_bytes();
let mut data = [0u8; 261];
let mut recv_len = data.len() as u32;
let mut sw: i32 = 0;
res = self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, &mut sw);
if res.is_ok() && sw != SW_SUCCESS {
res = Err(Error::GenericError);
} }
} }
apdu.zeroize();
let _ = self._ykpiv_end_transaction();
res res
} }
@@ -1046,10 +1038,9 @@ impl YubiKey {
} }
// get version from device // get version from device
let mut apdu = APDU::default(); let apdu = APDU::new(YKPIV_INS_GET_VERSION).to_bytes();
apdu.ins = YKPIV_INS_GET_VERSION;
self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw)?; self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, &mut sw)?;
if sw != SW_SUCCESS { if sw != SW_SUCCESS {
return Err(Error::GenericError); return Err(Error::GenericError);
@@ -1084,7 +1075,7 @@ impl YubiKey {
/// ///
/// NOTE: caller must make sure that this is wrapped in a transaction for synchronized operation /// NOTE: caller must make sure that this is wrapped in a transaction for synchronized operation
pub(crate) unsafe fn _ykpiv_get_serial(&mut self, f_force: bool) -> Result<u32, Error> { pub(crate) unsafe fn _ykpiv_get_serial(&mut self, f_force: bool) -> Result<u32, Error> {
let yk_applet: *const u8 = ptr::null(); let yk_applet = [0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01];
let mut data = [0u8; 255]; let mut data = [0u8; 255];
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;
@@ -1099,18 +1090,14 @@ impl YubiKey {
let mut temp = [0u8; 255]; let mut temp = [0u8; 255];
recv_len = temp.len() as u32; recv_len = temp.len() as u32;
let mut apdu = APDU::default(); let apdu = APDU::new(YKPIV_INS_SELECT_APPLICATION)
apdu.ins = YKPIV_INS_SELECT_APPLICATION; .p1(0x04)
apdu.p1 = 0x04; .data(&yk_applet)
apdu.lc = mem::size_of_val(&yk_applet) as u8; .to_bytes();
memcpy( if let Err(e) =
apdu.data.as_mut_ptr() as *mut c_void, self._send_data(apdu.as_slice(), temp.as_mut_ptr(), &mut recv_len, &mut sw)
yk_applet as *const c_void, {
mem::size_of_val(&yk_applet),
);
if let Err(e) = self._send_data(&mut apdu, temp.as_mut_ptr(), &mut recv_len, &mut sw) {
error!("failed communicating with card: '{}'", e); error!("failed communicating with card: '{}'", e);
return Err(e); return Err(e);
} }
@@ -1121,12 +1108,11 @@ impl YubiKey {
} }
recv_len = temp.len() as u32; recv_len = temp.len() as u32;
apdu = APDU::default(); let apdu = APDU::new(0x01).p1(0x10).to_bytes();
apdu.ins = 0x01;
apdu.p1 = 0x10;
apdu.lc = 0x00;
if let Err(e) = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw) { if let Err(e) =
self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, &mut sw)
{
error!("failed communicating with card: '{}'", e); error!("failed communicating with card: '{}'", e);
return Err(e); return Err(e);
} }
@@ -1137,18 +1123,14 @@ impl YubiKey {
} }
recv_len = temp.len() as u32; recv_len = temp.len() as u32;
apdu = APDU::default(); let apdu = APDU::new(YKPIV_INS_SELECT_APPLICATION)
apdu.ins = YKPIV_INS_SELECT_APPLICATION; .p1(0x04)
apdu.p1 = 0x04; .data(&AID)
apdu.lc = mem::size_of_val(&AID) as u8; .to_bytes();
memcpy( if let Err(e) =
apdu.data.as_mut_ptr() as *mut c_void, self._send_data(apdu.as_slice(), temp.as_mut_ptr(), &mut recv_len, &mut sw)
AID.as_ptr() as *const c_void, {
mem::size_of_val(&AID),
);
if let Err(e) = self._send_data(&mut apdu, temp.as_mut_ptr(), &mut recv_len, &mut sw) {
error!("failed communicating with card: '{}'", e); error!("failed communicating with card: '{}'", e);
return Err(e); return Err(e);
} }
@@ -1159,10 +1141,11 @@ impl YubiKey {
} }
} else { } else {
// get serial from yk5 and later devices using the f8 command // get serial from yk5 and later devices using the f8 command
let mut apdu = APDU::default(); let apdu = APDU::new(YKPIV_INS_GET_SERIAL).to_bytes();
apdu.ins = YKPIV_INS_GET_SERIAL;
if let Err(e) = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw) { if let Err(e) =
self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, &mut sw)
{
error!("failed communicating with card: '{}'", e); error!("failed communicating with card: '{}'", e);
return Err(e); return Err(e);
} }
@@ -1264,31 +1247,27 @@ impl YubiKey {
return Err(Error::SizeError); return Err(Error::SizeError);
} }
let mut apdu = APDU::default(); let mut apdu = APDU::new(YKPIV_INS_VERIFY);
apdu.ins = YKPIV_INS_VERIFY; apdu.params(0x00, 0x80);
apdu.p1 = 0x00;
apdu.p2 = 0x80;
apdu.lc = if pin.is_null() { 0 } else { 0x08 };
if !pin.is_null() { if !pin.is_null() {
let mut data = [0xFF; CB_PIN_MAX];
memcpy( memcpy(
apdu.data.as_mut_ptr() as *mut c_void, data.as_mut_ptr() as *mut c_void,
pin as *const c_void, pin as *const c_void,
pin_len, pin_len,
); );
if pin_len < CB_PIN_MAX { apdu.data(data);
memset(
apdu.data.as_mut_ptr().add(pin_len) as *mut c_void,
0xff,
CB_PIN_MAX - pin_len,
);
}
} }
let res = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw); let res = self._send_data(
apdu.to_bytes().as_slice(),
apdu.zeroize(); data.as_mut_ptr(),
&mut recv_len,
&mut sw,
);
if let Err(e) = res { if let Err(e) = res {
return Err(e); return Err(e);
@@ -1943,16 +1922,14 @@ impl YubiKey {
self._ykpiv_begin_transaction()?; self._ykpiv_begin_transaction()?;
if self._ykpiv_ensure_application_selected().is_ok() { if self._ykpiv_ensure_application_selected().is_ok() {
let mut apdu = APDU::default(); let apdu = APDU::new(YKPIV_INS_AUTHENTICATE)
apdu.ins = YKPIV_INS_AUTHENTICATE; .params(YKPIV_ALGO_3DES, YKPIV_KEY_CARDMGM)
apdu.p1 = YKPIV_ALGO_3DES; // triple des .data(&[0x7c, 0x02, 0x81, 0x00])
apdu.p2 = YKPIV_KEY_CARDMGM; // management key .to_bytes();
apdu.lc = 0x04;
apdu.data[0] = 0x7c;
apdu.data[1] = 0x02;
apdu.data[2] = 0x81; //0x80;
if let Err(e) = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw) { if let Err(e) =
self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, &mut sw)
{
res = Err(e) res = Err(e)
} else if sw != SW_SUCCESS { } else if sw != SW_SUCCESS {
res = Err(Error::AuthenticationError); res = Err(Error::AuthenticationError);
@@ -1969,31 +1946,29 @@ impl YubiKey {
/// Verify an auth response /// Verify an auth response
pub unsafe fn ykpiv_auth_verifyresponse(&mut self, response: [u8; 8]) -> Result<(), Error> { pub unsafe fn ykpiv_auth_verifyresponse(&mut self, response: [u8; 8]) -> Result<(), Error> {
self._ykpiv_begin_transaction()?;
let mut data = [
0x7c, 0x0a, 0x82, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
data[4..12].copy_from_slice(&response);
// send the response to the card and a challenge of our own.
let apdu = APDU::new(YKPIV_INS_AUTHENTICATE)
.params(YKPIV_ALGO_3DES, YKPIV_KEY_CARDMGM)
.data(&data)
.to_bytes();
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;
let mut res = self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, &mut sw);
self._ykpiv_begin_transaction()?;
// send the response to the card and a challenge of our own.
let mut apdu = APDU::default();
apdu.ins = YKPIV_INS_AUTHENTICATE;
apdu.p1 = YKPIV_ALGO_3DES; // triple des
apdu.p2 = YKPIV_KEY_CARDMGM; // management key
apdu.data[0] = 0x7c;
apdu.data[1] = 0x0a; // 2 + 8
apdu.data[2] = 0x82;
apdu.data[3] = 8;
apdu.data[4..12].copy_from_slice(&response);
apdu.lc = 12;
let mut res = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw);
if res.is_ok() && sw != SW_SUCCESS { if res.is_ok() && sw != SW_SUCCESS {
res = Err(Error::AuthenticationError); res = Err(Error::AuthenticationError);
} }
apdu.zeroize();
let _ = self._ykpiv_end_transaction(); let _ = self._ykpiv_end_transaction();
res res
} }
@@ -2006,18 +1981,12 @@ impl YubiKey {
self._ykpiv_begin_transaction()?; self._ykpiv_begin_transaction()?;
let mut apdu = APDU::default(); let apdu = APDU::new(YKPIV_INS_SELECT_APPLICATION)
apdu.ins = YKPIV_INS_SELECT_APPLICATION; .p1(0x04)
apdu.p1 = 0x04; .data(MGMT_AID)
apdu.lc = mem::size_of::<*const u8>() as u8; .to_bytes();
memcpy( let mut res = self._send_data(apdu.as_slice(), data.as_mut_ptr(), &mut recv_len, &mut sw);
apdu.data.as_mut_ptr() as *mut c_void,
MGMT_AID.as_ptr() as *const c_void,
MGMT_AID.len(),
);
let mut res = self._send_data(&mut apdu, data.as_mut_ptr(), &mut recv_len, &mut sw);
if let Err(e) = &res { if let Err(e) = &res {
error!("failed communicating with card: \'{}\'", e); error!("failed communicating with card: \'{}\'", e);