CCCID/CHUID: add basic tests and do some cleanups
- Adds tests for CCCID/CHUID, allowing not found (is that ok?) - Move constants under their respective modules and remove `YKPIV_`
This commit is contained in:
@@ -65,13 +65,13 @@ functions of the YubiKey:
|
|||||||
| | Module | Issue | Description |
|
| | Module | Issue | Description |
|
||||||
|----|---------------|-------|-------------|
|
|----|---------------|-------|-------------|
|
||||||
| 🚧 | `yubikey` | [#20] | Core functionality: auth, keys, PIN/PUK, encrypt, sign, attest |
|
| 🚧 | `yubikey` | [#20] | Core functionality: auth, keys, PIN/PUK, encrypt, sign, attest |
|
||||||
| ⚠️ | `cccid` | [#21] | Cardholder Capability Container (CCC) IDs |
|
| 🚧 | `cccid` | [#21] | Cardholder Capability Container (CCC) IDs |
|
||||||
| 🚧️ | `certificate` | [#22] | Certificates for stored keys |
|
| 🚧️ | `certificate` | [#22] | Certificates for stored keys |
|
||||||
| ⚠️ | `chuid` | [#23] | Cardholder Unique Identifier (CHUID) |
|
| 🚧 | `chuid` | [#23] | Cardholder Unique Identifier (CHUID) |
|
||||||
| ✅️ | `config` | [#24] | Support for reading on-key configuration |
|
| ✅️ | `config` | [#24] | Support for reading on-key configuration |
|
||||||
| ⚠️ | `container` | [#25] | MS Container Map Records |
|
| ⚠️ | `container` | [#25] | MS Container Map Records |
|
||||||
| 🚧 | `key` | [#26] | Crypto key management: list, generate, import |
|
| 🚧 | `key` | [#26] | Crypto key management: list, generate, import |
|
||||||
| ⚠️ | `mgm` | [#26] | Management Key (MGM) support: set, get, derive |
|
| 🚧 | `mgm` | [#26] | Management Key (MGM) support: set, get, derive |
|
||||||
| ⚠️ | `msroots` | [#28] | `msroots` file: PKCS#7 formatted certificate store for enterprise trusted roots |
|
| ⚠️ | `msroots` | [#28] | `msroots` file: PKCS#7 formatted certificate store for enterprise trusted roots |
|
||||||
|
|
||||||
Legend:
|
Legend:
|
||||||
|
|||||||
+30
-10
@@ -30,8 +30,21 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
use crate::{consts::*, error::Error, yubikey::YubiKey};
|
use crate::{error::Error, yubikey::YubiKey};
|
||||||
use getrandom::getrandom;
|
use getrandom::getrandom;
|
||||||
|
use std::fmt::{self, Debug};
|
||||||
|
|
||||||
|
/// CCCID size
|
||||||
|
pub const CCCID_SIZE: usize = 14;
|
||||||
|
|
||||||
|
/// CCC size
|
||||||
|
pub const CCC_SIZE: usize = 51;
|
||||||
|
|
||||||
|
/// CCCID offset
|
||||||
|
const CCC_ID_OFFS: usize = 9;
|
||||||
|
|
||||||
|
/// CCC Object ID
|
||||||
|
const OBJ_CAPABILITY: u32 = 0x005f_c107;
|
||||||
|
|
||||||
/// Cardholder Capability Container (CCC) Template
|
/// Cardholder Capability Container (CCC) Template
|
||||||
///
|
///
|
||||||
@@ -50,12 +63,12 @@ const CCC_TMPL: &[u8] = &[
|
|||||||
|
|
||||||
/// Cardholder Capability Container (CCC) Identifier Card ID
|
/// Cardholder Capability Container (CCC) Identifier Card ID
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct CardId(pub [u8; YKPIV_CCCID_SIZE]);
|
pub struct CardId(pub [u8; CCCID_SIZE]);
|
||||||
|
|
||||||
impl CardId {
|
impl CardId {
|
||||||
/// Generate a random CCC Card ID
|
/// Generate a random CCC Card ID
|
||||||
pub fn generate() -> Result<Self, Error> {
|
pub fn generate() -> Result<Self, Error> {
|
||||||
let mut id = [0u8; YKPIV_CCCID_SIZE];
|
let mut id = [0u8; CCCID_SIZE];
|
||||||
getrandom(&mut id).map_err(|_| Error::RandomnessError)?;
|
getrandom(&mut id).map_err(|_| Error::RandomnessError)?;
|
||||||
Ok(Self(id))
|
Ok(Self(id))
|
||||||
}
|
}
|
||||||
@@ -63,36 +76,43 @@ impl CardId {
|
|||||||
|
|
||||||
/// Cardholder Capability Container (CCC) Identifier
|
/// Cardholder Capability Container (CCC) Identifier
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct CCC(pub [u8; YKPIV_CCC_SIZE]);
|
pub struct CCC(pub [u8; CCC_SIZE]);
|
||||||
|
|
||||||
impl CCC {
|
impl CCC {
|
||||||
/// Return CardId component of CCC
|
/// Return CardId component of CCC
|
||||||
pub fn cccid(&self) -> Result<CardId, Error> {
|
pub fn cccid(&self) -> Result<CardId, Error> {
|
||||||
let mut cccid = [0u8; YKPIV_CCCID_SIZE];
|
let mut cccid = [0u8; CCCID_SIZE];
|
||||||
cccid.copy_from_slice(&self.0[CCC_ID_OFFS..(CCC_ID_OFFS + YKPIV_CCCID_SIZE)]);
|
cccid.copy_from_slice(&self.0[CCC_ID_OFFS..(CCC_ID_OFFS + CCCID_SIZE)]);
|
||||||
Ok(CardId(cccid))
|
Ok(CardId(cccid))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get Cardholder Capability Container (CCC) ID
|
/// Get Cardholder Capability Container (CCC) ID
|
||||||
pub fn get(yubikey: &mut YubiKey) -> Result<Self, Error> {
|
pub fn get(yubikey: &mut YubiKey) -> Result<Self, Error> {
|
||||||
let txn = yubikey.begin_transaction()?;
|
let txn = yubikey.begin_transaction()?;
|
||||||
let response = txn.fetch_object(YKPIV_OBJ_CAPABILITY)?;
|
let response = txn.fetch_object(OBJ_CAPABILITY)?;
|
||||||
|
|
||||||
if response.len() != CCC_TMPL.len() {
|
if response.len() != CCC_TMPL.len() {
|
||||||
return Err(Error::GenericError);
|
return Err(Error::GenericError);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ccc = [0u8; YKPIV_CCC_SIZE];
|
let mut ccc = [0u8; CCC_SIZE];
|
||||||
ccc.copy_from_slice(&response[0..YKPIV_CCC_SIZE]);
|
ccc.copy_from_slice(&response[0..CCC_SIZE]);
|
||||||
Ok(Self(ccc))
|
Ok(Self(ccc))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get Cardholder Capability Container (CCC) ID
|
/// Get Cardholder Capability Container (CCC) ID
|
||||||
|
#[cfg(feature = "untested")]
|
||||||
pub fn set(&self, yubikey: &mut YubiKey) -> Result<(), Error> {
|
pub fn set(&self, yubikey: &mut YubiKey) -> Result<(), Error> {
|
||||||
let mut buf = CCC_TMPL.to_vec();
|
let mut buf = CCC_TMPL.to_vec();
|
||||||
buf[0..self.0.len()].copy_from_slice(&self.0);
|
buf[0..self.0.len()].copy_from_slice(&self.0);
|
||||||
|
|
||||||
let txn = yubikey.begin_transaction()?;
|
let txn = yubikey.begin_transaction()?;
|
||||||
txn.save_object(YKPIV_OBJ_CAPABILITY, &buf)
|
txn.save_object(OBJ_CAPABILITY, &buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for CCC {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "CCC({:?})", &self.0[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-18
@@ -30,8 +30,33 @@
|
|||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
use crate::{consts::*, error::Error, yubikey::YubiKey};
|
use crate::{error::Error, yubikey::YubiKey};
|
||||||
use getrandom::getrandom;
|
use getrandom::getrandom;
|
||||||
|
use std::fmt::{self, Debug};
|
||||||
|
|
||||||
|
/// CHUID size
|
||||||
|
pub const CHUID_SIZE: usize = 59;
|
||||||
|
|
||||||
|
/// CARDID size
|
||||||
|
pub const CARDID_SIZE: usize = 16;
|
||||||
|
|
||||||
|
/// FASC-N component size
|
||||||
|
pub const FASCN_SIZE: usize = 25;
|
||||||
|
|
||||||
|
/// Expiration size
|
||||||
|
pub const EXPIRATION_SIZE: usize = 8;
|
||||||
|
|
||||||
|
/// FASC-N offset
|
||||||
|
const CHUID_FASCN_OFFS: usize = 2;
|
||||||
|
|
||||||
|
/// GUID offset
|
||||||
|
const CHUID_GUID_OFFS: usize = 29;
|
||||||
|
|
||||||
|
/// Expiration offset
|
||||||
|
const CHUID_EXPIRATION_OFFS: usize = 47;
|
||||||
|
|
||||||
|
/// CHUID Object ID
|
||||||
|
const OBJ_CHUID: u32 = 0x005f_c102;
|
||||||
|
|
||||||
/// Cardholder Unique Identifier (CHUID) Template
|
/// Cardholder Unique Identifier (CHUID) Template
|
||||||
///
|
///
|
||||||
@@ -57,12 +82,12 @@ const CHUID_TMPL: &[u8] = &[
|
|||||||
|
|
||||||
/// Cardholder Unique Identifier (CHUID) Card UUID/GUID value
|
/// Cardholder Unique Identifier (CHUID) Card UUID/GUID value
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct Uuid(pub [u8; YKPIV_CARDID_SIZE]);
|
pub struct Uuid(pub [u8; CARDID_SIZE]);
|
||||||
|
|
||||||
impl Uuid {
|
impl Uuid {
|
||||||
/// Generate a random Cardholder Unique Identifier (CHUID)
|
/// Generate a random Cardholder Unique Identifier (CHUID) UUID
|
||||||
pub fn generate() -> Result<Self, Error> {
|
pub fn generate() -> Result<Self, Error> {
|
||||||
let mut id = [0u8; YKPIV_CARDID_SIZE];
|
let mut id = [0u8; CARDID_SIZE];
|
||||||
getrandom(&mut id).map_err(|_| Error::RandomnessError)?;
|
getrandom(&mut id).map_err(|_| Error::RandomnessError)?;
|
||||||
Ok(Self(id))
|
Ok(Self(id))
|
||||||
}
|
}
|
||||||
@@ -70,28 +95,29 @@ impl Uuid {
|
|||||||
|
|
||||||
/// Cardholder Unique Identifier (CHUID)
|
/// Cardholder Unique Identifier (CHUID)
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct CHUID(pub [u8; YKPIV_CHUID_SIZE]);
|
pub struct CHUID(pub [u8; CHUID_SIZE]);
|
||||||
|
|
||||||
impl CHUID {
|
impl CHUID {
|
||||||
/// Return FASC-N component of CHUID
|
/// Return FASC-N component of CHUID
|
||||||
pub fn fascn(&self) -> Result<[u8; YKPIV_FASCN_SIZE], Error> {
|
pub fn fascn(&self) -> Result<[u8; FASCN_SIZE], Error> {
|
||||||
let mut fascn = [0u8; YKPIV_FASCN_SIZE];
|
let mut fascn = [0u8; FASCN_SIZE];
|
||||||
fascn.copy_from_slice(&self.0[CHUID_FASCN_OFFS..(CHUID_FASCN_OFFS + YKPIV_FASCN_SIZE)]);
|
fascn.copy_from_slice(&self.0[CHUID_FASCN_OFFS..(CHUID_FASCN_OFFS + FASCN_SIZE)]);
|
||||||
Ok(fascn)
|
Ok(fascn)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return Card UUID/GUID component of CHUID
|
/// Return Card UUID/GUID component of CHUID
|
||||||
pub fn uuid(&self) -> Result<[u8; YKPIV_CARDID_SIZE], Error> {
|
pub fn uuid(&self) -> Result<[u8; CARDID_SIZE], Error> {
|
||||||
let mut uuid = [0u8; YKPIV_CARDID_SIZE];
|
let mut uuid = [0u8; CARDID_SIZE];
|
||||||
uuid.copy_from_slice(&self.0[CHUID_GUID_OFFS..(CHUID_GUID_OFFS + YKPIV_CARDID_SIZE)]);
|
uuid.copy_from_slice(&self.0[CHUID_GUID_OFFS..(CHUID_GUID_OFFS + CARDID_SIZE)]);
|
||||||
Ok(uuid)
|
Ok(uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return expiration date component of CHUID
|
/// Return expiration date component of CHUID
|
||||||
pub fn expiration(&self) -> Result<[u8; YKPIV_EXPIRATION_SIZE], Error> {
|
// TODO(tarcieri): parse expiration?
|
||||||
let mut expiration = [0u8; YKPIV_EXPIRATION_SIZE];
|
pub fn expiration(&self) -> Result<[u8; EXPIRATION_SIZE], Error> {
|
||||||
|
let mut expiration = [0u8; EXPIRATION_SIZE];
|
||||||
expiration.copy_from_slice(
|
expiration.copy_from_slice(
|
||||||
&self.0[CHUID_EXPIRATION_OFFS..(CHUID_EXPIRATION_OFFS + YKPIV_EXPIRATION_SIZE)],
|
&self.0[CHUID_EXPIRATION_OFFS..(CHUID_EXPIRATION_OFFS + EXPIRATION_SIZE)],
|
||||||
);
|
);
|
||||||
Ok(expiration)
|
Ok(expiration)
|
||||||
}
|
}
|
||||||
@@ -99,24 +125,32 @@ impl CHUID {
|
|||||||
/// Get Cardholder Unique Identifier (CHUID)
|
/// Get Cardholder Unique Identifier (CHUID)
|
||||||
pub fn get(yubikey: &mut YubiKey) -> Result<CHUID, Error> {
|
pub fn get(yubikey: &mut YubiKey) -> Result<CHUID, Error> {
|
||||||
let txn = yubikey.begin_transaction()?;
|
let txn = yubikey.begin_transaction()?;
|
||||||
let response = txn.fetch_object(YKPIV_OBJ_CHUID)?;
|
let response = txn.fetch_object(OBJ_CHUID)?;
|
||||||
|
|
||||||
if response.len() != CHUID_TMPL.len() {
|
if response.len() != CHUID_TMPL.len() {
|
||||||
return Err(Error::GenericError);
|
return Err(Error::GenericError);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut chuid = [0u8; YKPIV_CHUID_SIZE];
|
let mut chuid = [0u8; CHUID_SIZE];
|
||||||
chuid.copy_from_slice(&response[0..YKPIV_CHUID_SIZE]);
|
chuid.copy_from_slice(&response[0..CHUID_SIZE]);
|
||||||
let retval = CHUID { 0: chuid };
|
let retval = CHUID { 0: chuid };
|
||||||
Ok(retval)
|
Ok(retval)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set Cardholder Unique Identifier (CHUID)
|
/// Set Cardholder Unique Identifier (CHUID)
|
||||||
|
#[cfg(feature = "untested")]
|
||||||
|
|
||||||
pub fn set(&self, yubikey: &mut YubiKey) -> Result<(), Error> {
|
pub fn set(&self, yubikey: &mut YubiKey) -> Result<(), Error> {
|
||||||
let mut buf = CHUID_TMPL.to_vec();
|
let mut buf = CHUID_TMPL.to_vec();
|
||||||
buf[0..self.0.len()].copy_from_slice(&self.0);
|
buf[0..self.0.len()].copy_from_slice(&self.0);
|
||||||
|
|
||||||
let txn = yubikey.begin_transaction()?;
|
let txn = yubikey.begin_transaction()?;
|
||||||
txn.save_object(YKPIV_OBJ_CHUID, &buf)
|
txn.save_object(OBJ_CHUID, &buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for CHUID {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "CHUID({:?})", &self.0[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,12 +67,6 @@ pub const CB_OBJ_TAG_MAX: usize = (CB_OBJ_TAG_MIN + 2); // 1 byte tag + 3 bytes
|
|||||||
pub const CB_PAGE: usize = 4096;
|
pub const CB_PAGE: usize = 4096;
|
||||||
pub const CB_PIN_MAX: usize = 8;
|
pub const CB_PIN_MAX: usize = 8;
|
||||||
|
|
||||||
pub const CCC_ID_OFFS: usize = 9;
|
|
||||||
|
|
||||||
pub const CHUID_FASCN_OFFS: usize = 2;
|
|
||||||
pub const CHUID_GUID_OFFS: usize = 29;
|
|
||||||
pub const CHUID_EXPIRATION_OFFS: usize = 47;
|
|
||||||
|
|
||||||
pub const CHREF_ACT_CHANGE_PIN: i32 = 0;
|
pub const CHREF_ACT_CHANGE_PIN: i32 = 0;
|
||||||
pub const CHREF_ACT_UNBLOCK_PIN: i32 = 1;
|
pub const CHREF_ACT_UNBLOCK_PIN: i32 = 1;
|
||||||
pub const CHREF_ACT_CHANGE_PUK: i32 = 2;
|
pub const CHREF_ACT_CHANGE_PUK: i32 = 2;
|
||||||
@@ -128,21 +122,11 @@ pub const TAG_ECC_POINT: u8 = 0x86;
|
|||||||
|
|
||||||
pub const YKPIV_ALGO_3DES: u8 = 0x03;
|
pub const YKPIV_ALGO_3DES: u8 = 0x03;
|
||||||
|
|
||||||
pub const YKPIV_CHUID_SIZE: usize = 59;
|
|
||||||
pub const YKPIV_CARDID_SIZE: usize = 16;
|
|
||||||
pub const YKPIV_FASCN_SIZE: usize = 25;
|
|
||||||
pub const YKPIV_EXPIRATION_SIZE: usize = 8;
|
|
||||||
|
|
||||||
pub const YKPIV_CCCID_SIZE: usize = 14;
|
|
||||||
pub const YKPIV_CCC_SIZE: usize = 51;
|
|
||||||
|
|
||||||
pub const YKPIV_CERTINFO_UNCOMPRESSED: u8 = 0;
|
pub const YKPIV_CERTINFO_UNCOMPRESSED: u8 = 0;
|
||||||
pub const YKPIV_CERTINFO_GZIP: u8 = 1;
|
pub const YKPIV_CERTINFO_GZIP: u8 = 1;
|
||||||
|
|
||||||
pub const YKPIV_KEY_CARDMGM: u8 = 0x9b;
|
pub const YKPIV_KEY_CARDMGM: u8 = 0x9b;
|
||||||
|
|
||||||
pub const YKPIV_OBJ_CAPABILITY: u32 = 0x005f_c107;
|
|
||||||
pub const YKPIV_OBJ_CHUID: u32 = 0x005f_c102;
|
|
||||||
pub const YKPIV_OBJ_FINGERPRINTS: u32 = 0x005f_c103;
|
pub const YKPIV_OBJ_FINGERPRINTS: u32 = 0x005f_c103;
|
||||||
pub const YKPIV_OBJ_SECURITY: u32 = 0x005f_c106;
|
pub const YKPIV_OBJ_SECURITY: u32 = 0x005f_c106;
|
||||||
pub const YKPIV_OBJ_FACIAL: u32 = 0x005f_c108;
|
pub const YKPIV_OBJ_FACIAL: u32 = 0x005f_c108;
|
||||||
|
|||||||
@@ -88,6 +88,9 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Not supported
|
/// Not supported
|
||||||
NotSupported,
|
NotSupported,
|
||||||
|
|
||||||
|
/// Not found
|
||||||
|
NotFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
@@ -113,6 +116,7 @@ impl Error {
|
|||||||
Error::ArgumentError => "YKPIV_ARGUMENT_ERROR",
|
Error::ArgumentError => "YKPIV_ARGUMENT_ERROR",
|
||||||
Error::RangeError => "YKPIV_RANGE_ERROR",
|
Error::RangeError => "YKPIV_RANGE_ERROR",
|
||||||
Error::NotSupported => "YKPIV_NOT_SUPPORTED",
|
Error::NotSupported => "YKPIV_NOT_SUPPORTED",
|
||||||
|
Error::NotFound => "<not found>",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,6 +139,7 @@ impl Error {
|
|||||||
Error::ArgumentError => "argument error",
|
Error::ArgumentError => "argument error",
|
||||||
Error::RangeError => "range error",
|
Error::RangeError => "range error",
|
||||||
Error::NotSupported => "not supported",
|
Error::NotSupported => "not supported",
|
||||||
|
Error::NotFound => "not found",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-6
@@ -136,10 +136,8 @@
|
|||||||
)]
|
)]
|
||||||
|
|
||||||
mod apdu;
|
mod apdu;
|
||||||
#[cfg(feature = "untested")]
|
|
||||||
pub mod cccid;
|
pub mod cccid;
|
||||||
pub mod certificate;
|
pub mod certificate;
|
||||||
#[cfg(feature = "untested")]
|
|
||||||
pub mod chuid;
|
pub mod chuid;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod consts;
|
pub mod consts;
|
||||||
@@ -159,10 +157,7 @@ pub mod settings;
|
|||||||
mod transaction;
|
mod transaction;
|
||||||
pub mod yubikey;
|
pub mod yubikey;
|
||||||
|
|
||||||
pub use self::{readers::Readers, yubikey::YubiKey};
|
pub use self::{error::Error, key::Key, mgm::MgmKey, readers::Readers, yubikey::YubiKey};
|
||||||
|
|
||||||
#[cfg(feature = "untested")]
|
|
||||||
pub use self::{key::Key, mgm::MgmKey};
|
|
||||||
|
|
||||||
/// Object identifiers
|
/// Object identifiers
|
||||||
pub type ObjectId = u32;
|
pub type ObjectId = u32;
|
||||||
|
|||||||
@@ -448,8 +448,12 @@ impl<'tx> Transaction<'tx> {
|
|||||||
let response = self.transfer_data(&templ, &indata[..inlen], CB_BUF_MAX)?;
|
let response = self.transfer_data(&templ, &indata[..inlen], CB_BUF_MAX)?;
|
||||||
|
|
||||||
if !response.is_success() {
|
if !response.is_success() {
|
||||||
|
if response.status_words() == StatusWords::NotFoundError {
|
||||||
|
return Err(Error::NotFound);
|
||||||
|
} else {
|
||||||
return Err(Error::GenericError);
|
return Err(Error::GenericError);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let data = Buffer::new(response.data().into());
|
let data = Buffer::new(response.data().into());
|
||||||
let mut outlen = 0;
|
let mut outlen = 0;
|
||||||
|
|||||||
+13
-4
@@ -31,6 +31,8 @@
|
|||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
cccid::CCC,
|
||||||
|
chuid::CHUID,
|
||||||
config::Config,
|
config::Config,
|
||||||
error::Error,
|
error::Error,
|
||||||
readers::{Reader, Readers},
|
readers::{Reader, Readers},
|
||||||
@@ -152,12 +154,9 @@ impl YubiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
error!("no YubiKey detected!");
|
error!("no YubiKey detected!");
|
||||||
Err(Error::GenericError)
|
Err(Error::NotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a connection to a YubiKey with the given serial number.
|
|
||||||
|
|
||||||
|
|
||||||
/// Reconnect to a YubiKey
|
/// Reconnect to a YubiKey
|
||||||
#[cfg(feature = "untested")]
|
#[cfg(feature = "untested")]
|
||||||
pub fn reconnect(&mut self) -> Result<(), Error> {
|
pub fn reconnect(&mut self) -> Result<(), Error> {
|
||||||
@@ -209,6 +208,16 @@ impl YubiKey {
|
|||||||
Config::get(self)
|
Config::get(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get CHUID
|
||||||
|
pub fn chuid(&mut self) -> Result<CHUID, Error> {
|
||||||
|
CHUID::get(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get CCCID
|
||||||
|
pub fn cccid(&mut self) -> Result<CCC, Error> {
|
||||||
|
CCC::get(self)
|
||||||
|
}
|
||||||
|
|
||||||
/// Authenticate to the card using the provided management key (MGM).
|
/// Authenticate to the card using the provided management key (MGM).
|
||||||
#[cfg(feature = "untested")]
|
#[cfg(feature = "untested")]
|
||||||
pub fn authenticate(&mut self, mgm_key: MgmKey) -> Result<(), Error> {
|
pub fn authenticate(&mut self, mgm_key: MgmKey) -> Result<(), Error> {
|
||||||
|
|||||||
+33
-1
@@ -6,7 +6,7 @@
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::{env, sync::Mutex};
|
use std::{env, sync::Mutex};
|
||||||
use yubikey_piv::{key::Key, YubiKey};
|
use yubikey_piv::{key::Key, Error, YubiKey};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// Provide thread-safe access to a YubiKey
|
/// Provide thread-safe access to a YubiKey
|
||||||
@@ -27,6 +27,38 @@ fn init_yubikey() -> Mutex<YubiKey> {
|
|||||||
Mutex::new(yubikey)
|
Mutex::new(yubikey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// CCCID support
|
||||||
|
//
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_get_cccid() {
|
||||||
|
let mut yubikey = YUBIKEY.lock().unwrap();
|
||||||
|
|
||||||
|
match yubikey.cccid() {
|
||||||
|
Ok(cccid) => trace!("CCCID: {:?}", cccid),
|
||||||
|
Err(Error::NotFound) => trace!("CCCID not found"),
|
||||||
|
Err(err) => panic!("error getting CCCID: {:?}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// CHUID support
|
||||||
|
//
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_get_chuid() {
|
||||||
|
let mut yubikey = YUBIKEY.lock().unwrap();
|
||||||
|
|
||||||
|
match yubikey.chuid() {
|
||||||
|
Ok(chuid) => trace!("CHUID: {:?}", chuid),
|
||||||
|
Err(Error::NotFound) => trace!("CHUID not found"),
|
||||||
|
Err(err) => panic!("error getting CHUID: {:?}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Device config support
|
// Device config support
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user