Add Result alias (#271)

Adds a `yubikey::Result` alias with `yubikey::Error` as the error type.

Since we only have one `Error` type, this simplifies the return types
where a `Result` is returned.
This commit is contained in:
Tony Arcieri (iqlusion)
2021-07-11 09:44:08 -07:00
committed by GitHub
parent 1051eaf26d
commit de51b0cc46
23 changed files with 210 additions and 223 deletions
+2 -2
View File
@@ -30,7 +30,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{error::Error, transaction::Transaction, Buffer};
use crate::{transaction::Transaction, Buffer, Result};
use log::trace;
use zeroize::{Zeroize, Zeroizing};
@@ -109,7 +109,7 @@ impl Apdu {
}
/// Transmit this APDU using the given card transaction
pub fn transmit(&self, txn: &Transaction<'_>, recv_len: usize) -> Result<Response, Error> {
pub fn transmit(&self, txn: &Transaction<'_>, recv_len: usize) -> Result<Response> {
trace!(">>> {:?}", self);
let response = Response::from(txn.transmit(&self.to_bytes(), recv_len)?);
trace!("<<< {:?}", &response);
+5 -5
View File
@@ -30,7 +30,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{error::Error, yubikey::YubiKey};
use crate::{Error, Result, YubiKey};
use getrandom::getrandom;
use std::fmt::{self, Debug, Display};
use subtle_encoding::hex;
@@ -68,7 +68,7 @@ pub struct CardId(pub [u8; CCCID_SIZE]);
impl CardId {
/// Generate a random CCC Card ID
pub fn generate() -> Result<Self, Error> {
pub fn generate() -> Result<Self> {
let mut id = [0u8; CCCID_SIZE];
getrandom(&mut id).map_err(|_| Error::RandomnessError)?;
Ok(Self(id))
@@ -81,14 +81,14 @@ pub struct Ccc(pub [u8; CCC_SIZE]);
impl Ccc {
/// Return CardId component of CCC
pub fn card_id(&self) -> Result<CardId, Error> {
pub fn card_id(&self) -> Result<CardId> {
let mut cccid = [0u8; CCCID_SIZE];
cccid.copy_from_slice(&self.0[CCC_ID_OFFS..(CCC_ID_OFFS + CCCID_SIZE)]);
Ok(CardId(cccid))
}
/// Get Cardholder Capability Container (CCC) ID
pub fn get(yubikey: &mut YubiKey) -> Result<Self, Error> {
pub fn get(yubikey: &mut YubiKey) -> Result<Self> {
let txn = yubikey.begin_transaction()?;
let response = txn.fetch_object(OBJ_CAPABILITY)?;
@@ -103,7 +103,7 @@ impl Ccc {
/// Set 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<()> {
let mut buf = CCC_TMPL.to_vec();
buf[0..self.0.len()].copy_from_slice(&self.0);
+17 -22
View File
@@ -31,7 +31,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{
error::Error,
error::{Error, Result},
key::{sign_data, AlgorithmId, SlotId},
serialization::*,
transaction::Transaction,
@@ -82,13 +82,13 @@ impl From<[u8; 20]> for Serial {
}
impl TryFrom<&[u8]> for Serial {
type Error = ();
type Error = Error;
fn try_from(bytes: &[u8]) -> Result<Serial, ()> {
fn try_from(bytes: &[u8]) -> Result<Serial> {
if bytes.len() <= 20 {
Ok(Serial(BigUint::from_bytes_be(&bytes)))
} else {
Err(())
Err(Error::ParseError)
}
}
}
@@ -112,7 +112,7 @@ pub enum CertInfo {
impl TryFrom<u8> for CertInfo {
type Error = Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
fn try_from(value: u8) -> Result<Self> {
match value {
0x00 => Ok(CertInfo::Uncompressed),
0x01 => Ok(CertInfo::Gzip),
@@ -190,7 +190,7 @@ impl fmt::Debug for PublicKeyInfo {
}
impl PublicKeyInfo {
fn parse(subject_pki: &SubjectPublicKeyInfo<'_>) -> Result<Self, Error> {
fn parse(subject_pki: &SubjectPublicKeyInfo<'_>) -> Result<Self> {
match subject_pki.algorithm.algorithm.to_string().as_str() {
OID_RSA_ENCRYPTION => {
let pubkey = read_pki::rsa_pubkey(subject_pki.subject_public_key.data)?;
@@ -330,7 +330,7 @@ pub struct Certificate {
impl<'a> TryFrom<&'a [u8]> for Certificate {
type Error = Error;
fn try_from(bytes: &'a [u8]) -> Result<Self, Error> {
fn try_from(bytes: &'a [u8]) -> Result<Self> {
Self::from_bytes(bytes.to_vec())
}
}
@@ -350,7 +350,7 @@ impl Certificate {
subject: &[RelativeDistinguishedName<'_>],
subject_pki: PublicKeyInfo,
extensions: &[x509::Extension<'_, O>],
) -> Result<Self, Error> {
) -> Result<Self> {
let serial = serial.into();
let mut tbs_cert = Buffer::new(Vec::with_capacity(CB_OBJ_MAX));
@@ -453,7 +453,7 @@ impl Certificate {
}
/// Read a certificate from the given slot in the YubiKey
pub fn read(yubikey: &mut YubiKey, slot: SlotId) -> Result<Self, Error> {
pub fn read(yubikey: &mut YubiKey, slot: SlotId) -> Result<Self> {
let txn = yubikey.begin_transaction()?;
let buf = read_certificate(&txn, slot)?;
@@ -465,25 +465,20 @@ impl Certificate {
}
/// Write this certificate into the YubiKey in the given slot
pub fn write(
&self,
yubikey: &mut YubiKey,
slot: SlotId,
certinfo: CertInfo,
) -> Result<(), Error> {
pub fn write(&self, yubikey: &mut YubiKey, slot: SlotId, certinfo: CertInfo) -> Result<()> {
let txn = yubikey.begin_transaction()?;
write_certificate(&txn, slot, Some(&self.data), certinfo)
}
/// Delete a certificate located at the given slot of the given YubiKey
#[cfg(feature = "untested")]
pub fn delete(yubikey: &mut YubiKey, slot: SlotId) -> Result<(), Error> {
pub fn delete(yubikey: &mut YubiKey, slot: SlotId) -> Result<()> {
let txn = yubikey.begin_transaction()?;
write_certificate(&txn, slot, None, CertInfo::Uncompressed)
}
/// Initialize a local certificate struct from the given bytebuffer
pub fn from_bytes(cert: impl Into<Buffer>) -> Result<Self, Error> {
pub fn from_bytes(cert: impl Into<Buffer>) -> Result<Self> {
let cert = cert.into();
if cert.is_empty() {
@@ -544,7 +539,7 @@ impl AsRef<[u8]> for Certificate {
}
/// Read certificate
pub(crate) fn read_certificate(txn: &Transaction<'_>, slot: SlotId) -> Result<Buffer, Error> {
pub(crate) fn read_certificate(txn: &Transaction<'_>, slot: SlotId) -> Result<Buffer> {
let object_id = slot.object_id();
let buf = match txn.fetch_object(object_id) {
@@ -572,7 +567,7 @@ pub(crate) fn write_certificate(
slot: SlotId,
data: Option<&[u8]>,
certinfo: CertInfo,
) -> Result<(), Error> {
) -> Result<()> {
let object_id = slot.object_id();
if data.is_none() {
@@ -602,7 +597,7 @@ mod read_pki {
use rsa::{BigUint, RSAPublicKey};
use super::{OID_NIST_P256, OID_NIST_P384};
use crate::{error::Error, key::AlgorithmId};
use crate::{key::AlgorithmId, Error, Result};
/// From [RFC 8017](https://tools.ietf.org/html/rfc8017#appendix-A.1.1):
/// ```text
@@ -611,7 +606,7 @@ mod read_pki {
/// publicExponent INTEGER -- e
/// }
/// ```
pub(super) fn rsa_pubkey(encoded: &[u8]) -> Result<RSAPublicKey, Error> {
pub(super) fn rsa_pubkey(encoded: &[u8]) -> Result<RSAPublicKey> {
fn parse_rsa_pubkey(i: &[u8]) -> IResult<&[u8], DerObject<'_>, BerError> {
parse_der_sequence_defined!(i, parse_der_integer >> parse_der_integer)
}
@@ -650,7 +645,7 @@ mod read_pki {
/// -- specifiedCurve SpecifiedECDomain
/// }
/// ```
pub(super) fn ec_parameters(parameters: &DerObject<'_>) -> Result<AlgorithmId, Error> {
pub(super) fn ec_parameters(parameters: &DerObject<'_>) -> Result<AlgorithmId> {
let curve_oid = parameters.as_oid_val().map_err(|_| Error::InvalidObject)?;
match curve_oid.to_string().as_str() {
+7 -7
View File
@@ -30,7 +30,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{error::Error, yubikey::YubiKey};
use crate::{Error, Result, YubiKey};
use getrandom::getrandom;
use std::fmt::{self, Debug, Display};
use subtle_encoding::hex;
@@ -87,7 +87,7 @@ pub struct Uuid(pub [u8; CARDID_SIZE]);
impl Uuid {
/// Generate a random Cardholder Unique Identifier (CHUID) UUID
pub fn generate() -> Result<Self, Error> {
pub fn generate() -> Result<Self> {
let mut id = [0u8; CARDID_SIZE];
getrandom(&mut id).map_err(|_| Error::RandomnessError)?;
Ok(Self(id))
@@ -100,14 +100,14 @@ pub struct ChuId(pub [u8; CHUID_SIZE]);
impl ChuId {
/// Return FASC-N component of CHUID
pub fn fascn(&self) -> Result<[u8; FASCN_SIZE], Error> {
pub fn fascn(&self) -> Result<[u8; FASCN_SIZE]> {
let mut fascn = [0u8; FASCN_SIZE];
fascn.copy_from_slice(&self.0[CHUID_FASCN_OFFS..(CHUID_FASCN_OFFS + FASCN_SIZE)]);
Ok(fascn)
}
/// Return Card UUID/GUID component of CHUID
pub fn uuid(&self) -> Result<[u8; CARDID_SIZE], Error> {
pub fn uuid(&self) -> Result<[u8; CARDID_SIZE]> {
let mut uuid = [0u8; CARDID_SIZE];
uuid.copy_from_slice(&self.0[CHUID_GUID_OFFS..(CHUID_GUID_OFFS + CARDID_SIZE)]);
Ok(uuid)
@@ -115,7 +115,7 @@ impl ChuId {
/// Return expiration date component of CHUID
// TODO(tarcieri): parse expiration?
pub fn expiration(&self) -> Result<[u8; EXPIRATION_SIZE], Error> {
pub fn expiration(&self) -> Result<[u8; EXPIRATION_SIZE]> {
let mut expiration = [0u8; EXPIRATION_SIZE];
expiration.copy_from_slice(
&self.0[CHUID_EXPIRATION_OFFS..(CHUID_EXPIRATION_OFFS + EXPIRATION_SIZE)],
@@ -124,7 +124,7 @@ impl ChuId {
}
/// Get Cardholder Unique Identifier (CHUID)
pub fn get(yubikey: &mut YubiKey) -> Result<ChuId, Error> {
pub fn get(yubikey: &mut YubiKey) -> Result<ChuId> {
let txn = yubikey.begin_transaction()?;
let response = txn.fetch_object(OBJ_CHUID)?;
@@ -140,7 +140,7 @@ impl 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<()> {
let mut buf = CHUID_TMPL.to_vec();
buf[0..self.0.len()].copy_from_slice(&self.0);
+2 -3
View File
@@ -31,11 +31,10 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{
error::Error,
metadata::{AdminData, ProtectedData},
mgm::{MgmType, ADMIN_FLAGS_1_PROTECTED_MGM},
yubikey::{YubiKey, ADMIN_FLAGS_1_PUK_BLOCKED},
TAG_ADMIN_FLAGS_1, TAG_ADMIN_SALT, TAG_ADMIN_TIMESTAMP, TAG_PROTECTED_FLAGS_1,
Result, TAG_ADMIN_FLAGS_1, TAG_ADMIN_SALT, TAG_ADMIN_TIMESTAMP, TAG_PROTECTED_FLAGS_1,
TAG_PROTECTED_MGM,
};
use log::error;
@@ -68,7 +67,7 @@ pub struct Config {
impl Config {
/// Get YubiKey config
pub fn get(yubikey: &mut YubiKey) -> Result<Config, Error> {
pub fn get(yubikey: &mut YubiKey) -> Result<Config> {
let mut config = Config {
protected_data_available: false,
puk_blocked: false,
+72 -70
View File
@@ -32,65 +32,69 @@
use std::fmt::{self, Display};
/// Result type with [`Error`].
pub type Result<T> = core::result::Result<T, Error>;
/// Kinds of errors
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Error {
/// Algorithm error
AlgorithmError,
/// Applet error
AppletError,
/// Argument error
ArgumentError,
/// Authentication error
AuthenticationError,
/// Generic error
GenericError,
/// Invalid object
InvalidObject,
/// Key error
KeyError,
/// Memory error
MemoryError,
/// Not supported
NotSupported,
/// Not found
NotFound,
/// Parse error
ParseError,
/// PCSC error
PcscError {
/// Original PC/SC error
inner: Option<pcsc::Error>,
},
/// Size error
SizeError,
/// Applet error
AppletError,
/// Authentication error
AuthenticationError,
/// PIN locked
PinLocked,
/// Randomness error
RandomnessError,
/// Generic error
GenericError,
/// Range error
RangeError,
/// Key error
KeyError,
/// Parse error
ParseError,
/// Size error
SizeError,
/// Wrong PIN
WrongPin {
/// Number of tries remaining
tries: u8,
},
/// Invalid object
InvalidObject,
/// Algorithm error
AlgorithmError,
/// PIN locked
PinLocked,
/// Argument error
ArgumentError,
/// Range error
RangeError,
/// Not supported
NotSupported,
/// Not found
NotFound,
}
impl Error {
@@ -98,48 +102,48 @@ impl Error {
///
/// These names map to the legacy names from the Yubico C library, to
/// assist in web searches for relevant information for these errors.
pub fn name(self) -> &'static str {
match self {
Error::MemoryError => "YKPIV_MEMORY_ERROR",
Error::PcscError { .. } => "YKPIV_PCSC_ERROR",
Error::SizeError => "YKPIV_SIZE_ERROR",
Error::AppletError => "YKPIV_APPLET_ERROR",
Error::AuthenticationError => "YKPIV_AUTHENTICATION_ERROR",
Error::RandomnessError => "YKPIV_RANDOMNESS_ERROR",
Error::GenericError => "YKPIV_GENERIC_ERROR",
Error::KeyError => "YKPIV_KEY_ERROR",
Error::ParseError => "YKPIV_PARSE_ERROR",
Error::WrongPin { .. } => "YKPIV_WRONG_PIN",
Error::InvalidObject => "YKPIV_INVALID_OBJECT",
pub fn name(self) -> Option<&'static str> {
Some(match self {
Error::AlgorithmError => "YKPIV_ALGORITHM_ERROR",
Error::PinLocked => "YKPIV_PIN_LOCKED",
Error::AppletError => "YKPIV_APPLET_ERROR",
Error::ArgumentError => "YKPIV_ARGUMENT_ERROR",
Error::RangeError => "YKPIV_RANGE_ERROR",
Error::AuthenticationError => "YKPIV_AUTHENTICATION_ERROR",
Error::GenericError => "YKPIV_GENERIC_ERROR",
Error::InvalidObject => "YKPIV_INVALID_OBJECT",
Error::KeyError => "YKPIV_KEY_ERROR",
Error::MemoryError => "YKPIV_MEMORY_ERROR",
Error::NotSupported => "YKPIV_NOT_SUPPORTED",
Error::NotFound => "<not found>",
}
Error::ParseError => "YKPIV_PARSE_ERROR",
Error::PcscError { .. } => "YKPIV_PCSC_ERROR",
Error::PinLocked => "YKPIV_PIN_LOCKED",
Error::RandomnessError => "YKPIV_RANDOMNESS_ERROR",
Error::RangeError => "YKPIV_RANGE_ERROR",
Error::SizeError => "YKPIV_SIZE_ERROR",
Error::WrongPin { .. } => "YKPIV_WRONG_PIN",
_ => return None,
})
}
/// Error message
pub fn msg(self) -> &'static str {
match self {
Error::MemoryError => "memory error",
Error::PcscError { .. } => "PCSC error",
Error::SizeError => "size error",
Error::AppletError => "applet error",
Error::AuthenticationError => "authentication error",
Error::RandomnessError => "randomness error",
Error::GenericError => "generic error",
Error::KeyError => "key error",
Error::ParseError => "parse error",
Error::WrongPin { .. } => "wrong pin",
Error::InvalidObject => "invalid object",
Error::AlgorithmError => "algorithm error",
Error::PinLocked => "PIN locked",
Error::AppletError => "applet error",
Error::ArgumentError => "argument error",
Error::RangeError => "range error",
Error::AuthenticationError => "authentication error",
Error::GenericError => "generic error",
Error::InvalidObject => "invalid object",
Error::KeyError => "key error",
Error::MemoryError => "memory error",
Error::NotSupported => "not supported",
Error::NotFound => "not found",
Error::ParseError => "parse error",
Error::PcscError { .. } => "PC/SC error",
Error::PinLocked => "PIN locked",
Error::RandomnessError => "randomness error",
Error::RangeError => "range error",
Error::SizeError => "size error",
Error::WrongPin { .. } => "wrong pin",
}
}
}
@@ -159,10 +163,8 @@ impl From<pcsc::Error> for Error {
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
#[allow(trivial_casts)] // why doesn't this work without the cast???
Error::PcscError { inner } => inner
.as_ref()
.map(|err| err as &(dyn std::error::Error + 'static)),
#[allow(trivial_casts)]
Error::PcscError { inner } => inner.as_ref().map(|err| err as &_),
_ => None,
}
}
+18 -22
View File
@@ -39,23 +39,19 @@
use crate::{
apdu::{Ins, StatusWords},
certificate::{self, Certificate},
error::Error,
certificate::{self, Certificate, PublicKeyInfo},
error::{Error, Result},
policy::{PinPolicy, TouchPolicy},
serialization::*,
settings,
yubikey::YubiKey,
ObjectId,
Buffer, ObjectId,
};
use log::debug;
use std::convert::TryFrom;
#[cfg(feature = "untested")]
use crate::CB_OBJ_MAX;
use crate::{
certificate::PublicKeyInfo,
policy::{PinPolicy, TouchPolicy},
Buffer,
};
use elliptic_curve::sec1::EncodedPoint as EcPublicKey;
use log::{error, warn};
#[cfg(feature = "untested")]
@@ -126,7 +122,7 @@ pub enum SlotId {
impl TryFrom<u8> for SlotId {
type Error = Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
fn try_from(value: u8) -> Result<Self> {
match value {
0x9a => Ok(SlotId::Authentication),
0x9c => Ok(SlotId::Signature),
@@ -154,7 +150,7 @@ impl From<SlotId> for u8 {
impl TryFrom<String> for SlotId {
type Error = Error;
fn try_from(s: String) -> Result<SlotId, Error> {
fn try_from(s: String) -> Result<SlotId> {
match s.as_ref() {
"9a" => Ok(SlotId::Authentication),
"9c" => Ok(SlotId::Signature),
@@ -209,7 +205,7 @@ pub enum RetiredSlotId {
impl TryFrom<u8> for RetiredSlotId {
type Error = Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
fn try_from(value: u8) -> Result<Self> {
match value {
0x82 => Ok(RetiredSlotId::R1),
0x83 => Ok(RetiredSlotId::R2),
@@ -239,7 +235,7 @@ impl TryFrom<u8> for RetiredSlotId {
impl TryFrom<String> for RetiredSlotId {
type Error = Error;
fn try_from(value: String) -> Result<Self, Self::Error> {
fn try_from(value: String) -> Result<Self> {
match value.as_ref() {
"82" => Ok(RetiredSlotId::R1),
"83" => Ok(RetiredSlotId::R2),
@@ -365,7 +361,7 @@ pub enum AlgorithmId {
impl TryFrom<u8> for AlgorithmId {
type Error = Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
fn try_from(value: u8) -> Result<Self> {
match value {
0x06 => Ok(AlgorithmId::Rsa1024),
0x07 => Ok(AlgorithmId::Rsa2048),
@@ -389,7 +385,7 @@ impl From<AlgorithmId> for u8 {
impl AlgorithmId {
/// Writes the `AlgorithmId` in the format the YubiKey expects during key generation.
pub(crate) fn write(self, buf: &mut [u8]) -> Result<usize, Error> {
pub(crate) fn write(self, buf: &mut [u8]) -> Result<usize> {
Tlv::write(buf, 0x80, &[self.into()])
}
@@ -424,7 +420,7 @@ pub struct Key {
impl Key {
/// List Personal Identity Verification (PIV) keys stored in a YubiKey
pub fn list(yubikey: &mut YubiKey) -> Result<Vec<Self>, Error> {
pub fn list(yubikey: &mut YubiKey) -> Result<Vec<Self>> {
let mut keys = vec![];
let txn = yubikey.begin_transaction()?;
@@ -465,7 +461,7 @@ pub fn generate(
algorithm: AlgorithmId,
pin_policy: PinPolicy,
touch_policy: TouchPolicy,
) -> Result<PublicKeyInfo, Error> {
) -> Result<PublicKeyInfo> {
// Keygen messages
// TODO(tarcieri): extract these into an I18N-handling type?
const SZ_SETTING_ROCA: &str = "Enable_Unsafe_Keygen_ROCA";
@@ -671,7 +667,7 @@ fn write_key(
pin_policy: PinPolicy,
touch_policy: TouchPolicy,
algorithm: AlgorithmId,
) -> Result<(), Error> {
) -> Result<()> {
let mut key_data = Buffer::new(vec![0u8; KEYDATA_LEN]);
let templ = [0, Ins::ImportKey.code(), algorithm.into(), slot.into()];
let mut offset = 0;
@@ -780,7 +776,7 @@ pub fn import_rsa_key(
key_data: RsaKeyData,
touch_policy: TouchPolicy,
pin_policy: PinPolicy,
) -> Result<(), Error> {
) -> Result<()> {
match algorithm {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => (),
_ => return Err(Error::AlgorithmError),
@@ -814,7 +810,7 @@ pub fn import_ecc_key(
key_data: &[u8],
touch_policy: TouchPolicy,
pin_policy: PinPolicy,
) -> Result<(), Error> {
) -> Result<()> {
match algorithm {
AlgorithmId::EccP256 | AlgorithmId::EccP384 => (),
_ => return Err(Error::AlgorithmError),
@@ -834,7 +830,7 @@ pub fn import_ecc_key(
/// Generate an attestation certificate for a stored key.
/// <https://developers.yubico.com/PIV/Introduction/PIV_attestation.html>
#[cfg(feature = "untested")]
pub fn attest(yubikey: &mut YubiKey, key: SlotId) -> Result<Buffer, Error> {
pub fn attest(yubikey: &mut YubiKey, key: SlotId) -> Result<Buffer> {
let templ = [0, Ins::Attest.code(), key.into(), 0];
let txn = yubikey.begin_transaction()?;
let response = txn.transfer_data(&templ, &[], CB_OBJ_MAX)?;
@@ -860,7 +856,7 @@ pub fn sign_data(
raw_in: &[u8],
algorithm: AlgorithmId,
key: SlotId,
) -> Result<Buffer, Error> {
) -> Result<Buffer> {
let txn = yubikey.begin_transaction()?;
// don't attempt to reselect in crypt operations to avoid problems with PIN_ALWAYS
@@ -874,7 +870,7 @@ pub fn decrypt_data(
input: &[u8],
algorithm: AlgorithmId,
key: SlotId,
) -> Result<Buffer, Error> {
) -> Result<Buffer> {
let txn = yubikey.begin_transaction()?;
// don't attempt to reselect in crypt operations to avoid problems with PIN_ALWAYS
+1 -1
View File
@@ -149,7 +149,7 @@ mod transaction;
pub mod yubikey;
pub use self::{
error::Error,
error::{Error, Result},
key::Key,
mgm::MgmKey,
readers::Readers,
+6 -6
View File
@@ -33,7 +33,7 @@
use std::marker::PhantomData;
use zeroize::Zeroizing;
use crate::{error::Error, serialization::*, transaction::Transaction, Buffer};
use crate::{serialization::*, transaction::Transaction, Buffer, Error, Result};
#[cfg(feature = "untested")]
use crate::{CB_OBJ_MAX, CB_OBJ_TAG_MAX};
@@ -78,7 +78,7 @@ impl<T: MetadataType> Default for Metadata<T> {
impl<T: MetadataType> Metadata<T> {
/// Read metadata
pub(crate) fn read(txn: &Transaction<'_>) -> Result<Self, Error> {
pub(crate) fn read(txn: &Transaction<'_>) -> Result<Self> {
let data = txn.fetch_object(T::obj_id())?;
Ok(Metadata {
inner: Tlv::parse_single(data, T::tag())?,
@@ -88,7 +88,7 @@ impl<T: MetadataType> Metadata<T> {
/// Write metadata
#[cfg(feature = "untested")]
pub(crate) fn write(&self, txn: &Transaction<'_>) -> Result<(), Error> {
pub(crate) fn write(&self, txn: &Transaction<'_>) -> Result<()> {
if self.inner.len() > CB_OBJ_MAX - CB_OBJ_TAG_MAX {
return Err(Error::GenericError);
}
@@ -105,12 +105,12 @@ impl<T: MetadataType> Metadata<T> {
/// Delete metadata
#[cfg(feature = "untested")]
pub(crate) fn delete(txn: &Transaction<'_>) -> Result<(), Error> {
pub(crate) fn delete(txn: &Transaction<'_>) -> Result<()> {
txn.save_object(T::obj_id(), &[])
}
/// Get metadata item
pub(crate) fn get_item(&self, tag: u8) -> Result<&[u8], Error> {
pub(crate) fn get_item(&self, tag: u8) -> Result<&[u8]> {
let mut data = &self.inner[..];
while !data.is_empty() {
@@ -128,7 +128,7 @@ impl<T: MetadataType> Metadata<T> {
/// Set metadata item
#[cfg(feature = "untested")]
pub(crate) fn set_item(&mut self, tag: u8, item: &[u8]) -> Result<(), Error> {
pub(crate) fn set_item(&mut self, tag: u8, item: &[u8]) -> Result<()> {
let mut cb_temp: usize = 0;
let mut tag_temp: u8 = 0;
let mut cb_len: usize = 0;
+10 -10
View File
@@ -30,7 +30,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::error::Error;
use crate::{Error, Result};
use getrandom::getrandom;
use log::error;
use std::convert::{TryFrom, TryInto};
@@ -97,7 +97,7 @@ pub struct MgmKey([u8; DES_LEN_3DES]);
impl MgmKey {
/// Generate a random MGM key
pub fn generate() -> Result<Self, Error> {
pub fn generate() -> Result<Self> {
let mut key_bytes = [0u8; DES_LEN_3DES];
if getrandom(&mut key_bytes).is_err() {
@@ -110,14 +110,14 @@ impl MgmKey {
/// Create an MGM key from byte slice.
///
/// Returns an error if the slice is the wrong size or the key is weak.
pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, Error> {
pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self> {
bytes.as_ref().try_into()
}
/// Create an MGM key from the given byte array.
///
/// Returns an error if the key is weak.
pub fn new(key_bytes: [u8; DES_LEN_3DES]) -> Result<Self, Error> {
pub fn new(key_bytes: [u8; DES_LEN_3DES]) -> Result<Self> {
if is_weak_key(&key_bytes) {
error!(
"blacklisting key '{:?}' since it's weak (with odd parity)",
@@ -132,7 +132,7 @@ impl MgmKey {
/// Get derived management key (MGM)
#[cfg(feature = "untested")]
pub fn get_derived(yubikey: &mut YubiKey, pin: &[u8]) -> Result<Self, Error> {
pub fn get_derived(yubikey: &mut YubiKey, pin: &[u8]) -> Result<Self> {
let txn = yubikey.begin_transaction()?;
// recover management key
@@ -157,7 +157,7 @@ impl MgmKey {
/// Get protected management key (MGM)
#[cfg(feature = "untested")]
pub fn get_protected(yubikey: &mut YubiKey) -> Result<Self, Error> {
pub fn get_protected(yubikey: &mut YubiKey) -> Result<Self> {
let txn = yubikey.begin_transaction()?;
let protected_data = ProtectedData::read(&txn).map_err(|e| {
@@ -187,7 +187,7 @@ impl MgmKey {
///
/// This will wipe any metadata related to derived and PIN-protected management keys.
#[cfg(feature = "untested")]
pub fn set_default(yubikey: &mut YubiKey) -> Result<(), Error> {
pub fn set_default(yubikey: &mut YubiKey) -> Result<()> {
MgmKey::default().set_manual(yubikey, false)
}
@@ -198,7 +198,7 @@ impl MgmKey {
///
/// This will wipe any metadata related to derived and PIN-protected management keys.
#[cfg(feature = "untested")]
pub fn set_manual(&self, yubikey: &mut YubiKey, require_touch: bool) -> Result<(), Error> {
pub fn set_manual(&self, yubikey: &mut YubiKey, require_touch: bool) -> Result<()> {
let txn = yubikey.begin_transaction()?;
txn.set_mgm_key(&self, require_touch).map_err(|e| {
@@ -257,7 +257,7 @@ impl MgmKey {
///
/// This enables key management operations to be performed with access to the PIN.
#[cfg(feature = "untested")]
pub fn set_protected(&self, yubikey: &mut YubiKey) -> Result<(), Error> {
pub fn set_protected(&self, yubikey: &mut YubiKey) -> Result<()> {
let txn = yubikey.begin_transaction()?;
txn.set_mgm_key(self, false).map_err(|e| {
@@ -364,7 +364,7 @@ impl Drop for MgmKey {
impl<'a> TryFrom<&'a [u8]> for MgmKey {
type Error = Error;
fn try_from(key_bytes: &'a [u8]) -> Result<Self, Error> {
fn try_from(key_bytes: &'a [u8]) -> Result<Self> {
Self::new(key_bytes.try_into().map_err(|_| Error::SizeError)?)
}
}
+6 -6
View File
@@ -33,7 +33,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{error::Error, key::SlotId, serialization::*, yubikey::YubiKey, CB_OBJ_MAX};
use crate::{key::SlotId, serialization::*, Error, Result, YubiKey, CB_OBJ_MAX};
use log::error;
use std::convert::{TryFrom, TryInto};
@@ -77,7 +77,7 @@ pub struct Container {
impl Container {
/// Read MS Container Map records
pub fn read_mscmap(yubikey: &mut YubiKey) -> Result<Vec<Self>, Error> {
pub fn read_mscmap(yubikey: &mut YubiKey) -> Result<Vec<Self>> {
let txn = yubikey.begin_transaction()?;
let response = txn.fetch_object(OBJ_MSCMAP)?;
let mut containers = vec![];
@@ -103,7 +103,7 @@ impl Container {
}
/// Write MS Container Map records.
pub fn write_mscmap(yubikey: &mut YubiKey, containers: &[Self]) -> Result<(), Error> {
pub fn write_mscmap(yubikey: &mut YubiKey, containers: &[Self]) -> Result<()> {
let n_containers = containers.len();
let data_len = n_containers * CONTAINER_REC_LEN;
@@ -124,7 +124,7 @@ impl Container {
}
/// Parse a container record from a byte slice
pub fn new(bytes: &[u8]) -> Result<Self, Error> {
pub fn new(bytes: &[u8]) -> Result<Self> {
if bytes.len() != CONTAINER_REC_LEN {
error!(
"couldn't parse PIV container: expected {}-bytes, got {}-bytes",
@@ -161,7 +161,7 @@ impl Container {
}
/// Parse the container name as a UTF-16 string
pub fn parse_name(&self) -> Result<String, Error> {
pub fn parse_name(&self) -> Result<String> {
String::from_utf16(&self.name).map_err(|_| Error::ParseError)
}
@@ -188,7 +188,7 @@ impl Container {
impl<'a> TryFrom<&'a [u8]> for Container {
type Error = Error;
fn try_from(bytes: &'a [u8]) -> Result<Self, Error> {
fn try_from(bytes: &'a [u8]) -> Result<Self> {
Self::new(bytes)
}
}
+4 -4
View File
@@ -37,7 +37,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{error::Error, serialization::*, yubikey::YubiKey};
use crate::{serialization::*, Error, Result, YubiKey};
use crate::{CB_OBJ_MAX, CB_OBJ_TAG_MAX};
use log::error;
@@ -58,12 +58,12 @@ pub struct MsRoots(Vec<u8>);
impl MsRoots {
/// Initialize a local certificate struct from the given bytebuffer
pub fn new(msroots: impl AsRef<[u8]>) -> Result<Self, Error> {
pub fn new(msroots: impl AsRef<[u8]>) -> Result<Self> {
Ok(MsRoots(msroots.as_ref().into()))
}
/// Read `msroots` file from YubiKey
pub fn read(yubikey: &mut YubiKey) -> Result<Option<Self>, Error> {
pub fn read(yubikey: &mut YubiKey) -> Result<Option<Self>> {
let txn = yubikey.begin_transaction()?;
// allocate first page
@@ -100,7 +100,7 @@ impl MsRoots {
}
/// Write `msroots` file to YubiKey
pub fn write(&self, yubikey: &mut YubiKey) -> Result<(), Error> {
pub fn write(&self, yubikey: &mut YubiKey) -> Result<()> {
let mut buf = [0u8; CB_OBJ_MAX];
let mut offset: usize;
let mut data_offset: usize = 0;
+3 -3
View File
@@ -1,6 +1,6 @@
//! Enums representing key policies.
use crate::{error::Error, serialization::Tlv};
use crate::{serialization::Tlv, Result};
/// Specifies how often the PIN needs to be entered for access to the credential in a
/// given slot. This policy must be set upon key generation or importation, and cannot be
@@ -37,7 +37,7 @@ impl From<PinPolicy> for u8 {
impl PinPolicy {
/// Writes the `PinPolicy` in the format the YubiKey expects during key generation or
/// importation.
pub(crate) fn write(self, buf: &mut [u8]) -> Result<usize, Error> {
pub(crate) fn write(self, buf: &mut [u8]) -> Result<usize> {
match self {
PinPolicy::Default => Ok(0),
_ => Tlv::write(buf, 0xaa, &[self.into()]),
@@ -81,7 +81,7 @@ impl From<TouchPolicy> for u8 {
impl TouchPolicy {
/// Writes the `TouchPolicy` in the format the YubiKey expects during key generation
/// or importation.
pub(crate) fn write(self, buf: &mut [u8]) -> Result<usize, Error> {
pub(crate) fn write(self, buf: &mut [u8]) -> Result<usize> {
match self {
TouchPolicy::Default => Ok(0),
_ => Tlv::write(buf, 0xab, &[self.into()]),
+5 -5
View File
@@ -1,6 +1,6 @@
//! Support for enumerating available readers
use crate::{error::Error, yubikey::YubiKey};
use crate::{Result, YubiKey};
use std::{
borrow::Cow,
convert::TryInto,
@@ -23,7 +23,7 @@ pub struct Readers {
impl Readers {
/// Open a PC/SC context, which can be used to enumerate available PC/SC
/// readers (which can be used to connect to YubiKeys).
pub fn open() -> Result<Self, Error> {
pub fn open() -> Result<Self> {
let ctx = pcsc::Context::establish(pcsc::Scope::System)?;
let reader_names = vec![0u8; ctx.list_readers_len()?];
Ok(Self {
@@ -33,7 +33,7 @@ impl Readers {
}
/// Iterate over the available readers
pub fn iter(&mut self) -> Result<Iter<'_>, Error> {
pub fn iter(&mut self) -> Result<Iter<'_>> {
let Self { ctx, reader_names } = self;
let reader_cstrs: Vec<_> = {
@@ -77,12 +77,12 @@ impl<'ctx> Reader<'ctx> {
}
/// Open a connection to this reader, returning a `YubiKey` if successful
pub fn open(&self) -> Result<YubiKey, Error> {
pub fn open(&self) -> Result<YubiKey> {
self.try_into()
}
/// Connect to this reader, returning its `pcsc::Card`
pub(crate) fn connect(&self) -> Result<pcsc::Card, Error> {
pub(crate) fn connect(&self) -> Result<pcsc::Card> {
let ctx = self.ctx.lock().unwrap();
Ok(ctx.connect(self.name, pcsc::ShareMode::Shared, pcsc::Protocols::T1)?)
}
+6 -6
View File
@@ -30,7 +30,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{error::Error, Buffer, ObjectId, CB_OBJ_TAG_MIN};
use crate::{Buffer, Error, ObjectId, Result, CB_OBJ_TAG_MIN};
pub const OBJ_DISCOVERY: u32 = 0x7e;
@@ -44,7 +44,7 @@ pub(crate) struct Tlv<'a> {
impl<'a> Tlv<'a> {
/// Parses a `Tlv` from a buffer, returning the remainder of the buffer.
pub(crate) fn parse(buffer: &'a [u8]) -> Result<(&'a [u8], Self), Error> {
pub(crate) fn parse(buffer: &'a [u8]) -> Result<(&'a [u8], Self)> {
if buffer.len() < CB_OBJ_TAG_MIN || !has_valid_length(&buffer[1..], buffer.len() - 1) {
return Err(Error::SizeError);
}
@@ -61,7 +61,7 @@ impl<'a> Tlv<'a> {
/// Takes a [`Buffer`] containing a single `Tlv` with the given tag, and returns a
/// `Buffer` containing only the value part of the `Tlv`.
pub(crate) fn parse_single(mut buffer: Buffer, tag: u8) -> Result<Buffer, Error> {
pub(crate) fn parse_single(mut buffer: Buffer, tag: u8) -> Result<Buffer> {
if buffer.len() < CB_OBJ_TAG_MIN || !has_valid_length(&buffer[1..], buffer.len() - 1) {
return Err(Error::SizeError);
}
@@ -79,7 +79,7 @@ impl<'a> Tlv<'a> {
}
/// Writes a TLV to the given buffer.
pub(crate) fn write(buffer: &mut [u8], tag: u8, value: &[u8]) -> Result<usize, Error> {
pub(crate) fn write(buffer: &mut [u8], tag: u8, value: &[u8]) -> Result<usize> {
if buffer.len() < CB_OBJ_TAG_MIN {
return Err(Error::SizeError);
}
@@ -103,7 +103,7 @@ impl<'a> Tlv<'a> {
tag: u8,
length: usize,
value: Gen,
) -> Result<usize, Error>
) -> Result<usize>
where
Gen: FnOnce(&mut [u8]),
{
@@ -124,7 +124,7 @@ impl<'a> Tlv<'a> {
}
/// Set length
pub(crate) fn set_length(buffer: &mut [u8], length: usize) -> Result<usize, Error> {
pub(crate) fn set_length(buffer: &mut [u8], length: usize) -> Result<usize> {
if length < 0x80 {
if buffer.is_empty() {
Err(Error::SizeError)
+13 -18
View File
@@ -3,7 +3,7 @@
use crate::{
apdu::Response,
apdu::{Apdu, Ins, StatusWords},
error::Error,
error::{Error, Result},
key::{AlgorithmId, SlotId},
serialization::*,
yubikey::*,
@@ -32,7 +32,7 @@ pub(crate) struct Transaction<'tx> {
impl<'tx> Transaction<'tx> {
/// Create a new transaction with the given card.
pub fn new(card: &'tx mut pcsc::Card) -> Result<Self, Error> {
pub fn new(card: &'tx mut pcsc::Card) -> Result<Self> {
Ok(Transaction {
inner: card.transaction()?,
})
@@ -45,7 +45,7 @@ impl<'tx> Transaction<'tx> {
/// single APDU messages at a time. For larger messages that need to be
/// split into multiple APDUs, use the [`Transaction::transfer_data`]
/// method instead.
pub fn transmit(&self, send_buffer: &[u8], recv_len: usize) -> Result<Vec<u8>, Error> {
pub fn transmit(&self, send_buffer: &[u8], recv_len: usize) -> Result<Vec<u8>> {
trace!(">>> {:?}", send_buffer);
let mut recv_buffer = vec![0u8; recv_len];
@@ -60,7 +60,7 @@ impl<'tx> Transaction<'tx> {
}
/// Select application.
pub fn select_application(&self) -> Result<(), Error> {
pub fn select_application(&self) -> Result<()> {
let response = Apdu::new(Ins::SelectApplication)
.p1(0x04)
.data(&PIV_AID)
@@ -82,7 +82,7 @@ impl<'tx> Transaction<'tx> {
}
/// Get the version of the PIV application installed on the YubiKey.
pub fn get_version(&self) -> Result<Version, Error> {
pub fn get_version(&self) -> Result<Version> {
// get version from device
let response = Apdu::new(Ins::GetVersion).transmit(self, 261)?;
@@ -98,7 +98,7 @@ impl<'tx> Transaction<'tx> {
}
/// Get YubiKey device serial number.
pub fn get_serial(&self, version: Version) -> Result<Serial, Error> {
pub fn get_serial(&self, version: Version) -> Result<Serial> {
let response = if version.major < 5 {
// YK4 requires switching to the yk applet to retrieve the serial
let sw = Apdu::new(Ins::SelectApplication)
@@ -157,7 +157,7 @@ impl<'tx> Transaction<'tx> {
}
/// Verify device PIN.
pub fn verify_pin(&self, pin: &[u8]) -> Result<(), Error> {
pub fn verify_pin(&self, pin: &[u8]) -> Result<()> {
if pin.len() > CB_PIN_MAX {
return Err(Error::SizeError);
}
@@ -191,7 +191,7 @@ impl<'tx> Transaction<'tx> {
action: ChangeRefAction,
current_pin: &[u8],
new_pin: &[u8],
) -> Result<(), Error> {
) -> Result<()> {
if current_pin.len() > CB_PIN_MAX || new_pin.len() > CB_PIN_MAX {
return Err(Error::SizeError);
}
@@ -229,7 +229,7 @@ impl<'tx> Transaction<'tx> {
/// Set the management key (MGM).
#[cfg(feature = "untested")]
pub fn set_mgm_key(&self, new_key: &MgmKey, require_touch: bool) -> Result<(), Error> {
pub fn set_mgm_key(&self, new_key: &MgmKey, require_touch: bool) -> Result<()> {
let p2 = if require_touch { 0xfe } else { 0xff };
let mut data = [0u8; DES_LEN_3DES + 3];
@@ -263,7 +263,7 @@ impl<'tx> Transaction<'tx> {
algorithm: AlgorithmId,
key: SlotId,
decipher: bool,
) -> Result<Buffer, Error> {
) -> Result<Buffer> {
let in_len = sign_in.len();
let mut indata = [0u8; 1024];
let templ = [0, Ins::Authenticate.code(), algorithm.into(), key.into()];
@@ -358,12 +358,7 @@ impl<'tx> Transaction<'tx> {
/// messages into smaller APDU-sized messages (using the provided APDU
/// template to construct them), and then sending those via
/// [`Transaction::transmit`].
pub fn transfer_data(
&self,
templ: &[u8],
in_data: &[u8],
max_out: usize,
) -> Result<Response, Error> {
pub fn transfer_data(&self, templ: &[u8], in_data: &[u8], max_out: usize) -> Result<Response> {
let mut in_offset = 0;
let mut out_data = vec![];
let mut sw;
@@ -441,7 +436,7 @@ impl<'tx> Transaction<'tx> {
}
/// Fetch an object.
pub fn fetch_object(&self, object_id: ObjectId) -> Result<Buffer, Error> {
pub fn fetch_object(&self, object_id: ObjectId) -> Result<Buffer> {
let mut indata = [0u8; 5];
let templ = [0, Ins::GetData.code(), 0x3f, 0xff];
@@ -475,7 +470,7 @@ impl<'tx> Transaction<'tx> {
}
/// Save an object.
pub fn save_object(&self, object_id: ObjectId, indata: &[u8]) -> Result<(), Error> {
pub fn save_object(&self, object_id: ObjectId, indata: &[u8]) -> Result<()> {
let templ = [0, Ins::PutData.code(), 0x3f, 0xff];
// TODO(tarcieri): replace with vector
+25 -25
View File
@@ -35,7 +35,7 @@ use crate::{
cccid::Ccc,
chuid::ChuId,
config::Config,
error::Error,
error::{Error, Result},
mgm::MgmKey,
readers::{Reader, Readers},
transaction::Transaction,
@@ -92,7 +92,7 @@ impl From<Serial> for u32 {
impl FromStr for Serial {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Error> {
fn from_str(s: &str) -> Result<Self> {
u32::from_str(s).map(Serial).map_err(|_| Error::ParseError)
}
}
@@ -157,7 +157,7 @@ impl YubiKey {
/// attached to the same system, use [`YubiKey::open_by_serial`] or
/// [`yubikey::Readers`][`Readers`] to select from the available
/// PC/SC readers.
pub fn open() -> Result<Self, Error> {
pub fn open() -> Result<Self> {
let mut readers = Readers::open().map_err(|e| match e {
Error::PcscError {
inner: Some(pcsc::Error::NoReadersAvailable),
@@ -180,7 +180,7 @@ impl YubiKey {
}
/// Open a YubiKey with a specific serial number.
pub fn open_by_serial(serial: Serial) -> Result<Self, Error> {
pub fn open_by_serial(serial: Serial) -> Result<Self> {
let mut readers = Readers::open().map_err(|e| match e {
Error::PcscError {
inner: Some(pcsc::Error::NoReadersAvailable),
@@ -205,7 +205,7 @@ impl YubiKey {
/// Reconnect to a YubiKey
#[cfg(feature = "untested")]
pub fn reconnect(&mut self) -> Result<(), Error> {
pub fn reconnect(&mut self) -> Result<()> {
info!("trying to reconnect to current reader");
self.card.reconnect(
@@ -230,7 +230,7 @@ impl YubiKey {
}
/// Begin a transaction.
pub(crate) fn begin_transaction(&mut self) -> Result<Transaction<'_>, Error> {
pub(crate) fn begin_transaction(&mut self) -> Result<Transaction<'_>> {
// TODO(tarcieri): reconnect support
Transaction::new(&mut self.card)
}
@@ -255,22 +255,22 @@ impl YubiKey {
}
/// Get device configuration.
pub fn config(&mut self) -> Result<Config, Error> {
pub fn config(&mut self) -> Result<Config> {
Config::get(self)
}
/// Get CHUID
pub fn chuid(&mut self) -> Result<ChuId, Error> {
pub fn chuid(&mut self) -> Result<ChuId> {
ChuId::get(self)
}
/// Get CCCID
pub fn cccid(&mut self) -> Result<Ccc, Error> {
pub fn cccid(&mut self) -> Result<Ccc> {
Ccc::get(self)
}
/// Authenticate to the card using the provided management key (MGM).
pub fn authenticate(&mut self, mgm_key: MgmKey) -> Result<(), Error> {
pub fn authenticate(&mut self, mgm_key: MgmKey) -> Result<()> {
let txn = self.begin_transaction()?;
// get a challenge from the card
@@ -325,7 +325,7 @@ impl YubiKey {
/// Deauthenticate
#[cfg(feature = "untested")]
pub fn deauthenticate(&mut self) -> Result<(), Error> {
pub fn deauthenticate(&mut self) -> Result<()> {
let txn = self.begin_transaction()?;
let status_words = Apdu::new(Ins::SelectApplication)
@@ -346,7 +346,7 @@ impl YubiKey {
}
/// Verify device PIN.
pub fn verify_pin(&mut self, pin: &[u8]) -> Result<(), Error> {
pub fn verify_pin(&mut self, pin: &[u8]) -> Result<()> {
{
let txn = self.begin_transaction()?;
txn.verify_pin(pin)?;
@@ -360,7 +360,7 @@ impl YubiKey {
}
/// Get the number of PIN retries
pub fn get_pin_retries(&mut self) -> Result<u8, Error> {
pub fn get_pin_retries(&mut self) -> Result<u8> {
let txn = self.begin_transaction()?;
// Force a re-select to unverify, because once verified the spec dictates that
@@ -378,7 +378,7 @@ impl YubiKey {
/// Set the number of PIN retries
#[cfg(feature = "untested")]
pub fn set_pin_retries(&mut self, pin_tries: u8, puk_tries: u8) -> Result<(), Error> {
pub fn set_pin_retries(&mut self, pin_tries: u8, puk_tries: u8) -> Result<()> {
// Special case: if either retry count is 0, it's a successful no-op
if pin_tries == 0 || puk_tries == 0 {
return Ok(());
@@ -402,7 +402,7 @@ impl YubiKey {
///
/// The default PIN code is 123456
#[cfg(feature = "untested")]
pub fn change_pin(&mut self, current_pin: &[u8], new_pin: &[u8]) -> Result<(), Error> {
pub fn change_pin(&mut self, current_pin: &[u8], new_pin: &[u8]) -> Result<()> {
{
let txn = self.begin_transaction()?;
txn.change_ref(ChangeRefAction::ChangePin, current_pin, new_pin)?;
@@ -417,7 +417,7 @@ impl YubiKey {
/// Set PIN last changed
#[cfg(feature = "untested")]
pub fn set_pin_last_changed(yubikey: &mut YubiKey) -> Result<(), Error> {
pub fn set_pin_last_changed(yubikey: &mut YubiKey) -> Result<()> {
let txn = yubikey.begin_transaction()?;
let mut admin_data = AdminData::read(&txn)?;
@@ -452,14 +452,14 @@ impl YubiKey {
///
/// The default PUK code is 12345678.
#[cfg(feature = "untested")]
pub fn change_puk(&mut self, current_puk: &[u8], new_puk: &[u8]) -> Result<(), Error> {
pub fn change_puk(&mut self, current_puk: &[u8], new_puk: &[u8]) -> Result<()> {
let txn = self.begin_transaction()?;
txn.change_ref(ChangeRefAction::ChangePuk, current_puk, new_puk)
}
/// Block PUK: permanently prevent the PIN from becoming unblocked
#[cfg(feature = "untested")]
pub fn block_puk(yubikey: &mut YubiKey) -> Result<(), Error> {
pub fn block_puk(yubikey: &mut YubiKey) -> Result<()> {
let mut puk = [0x30, 0x42, 0x41, 0x44, 0x46, 0x30, 0x30, 0x44];
let mut tries_remaining: i32 = -1;
let mut flags = [0];
@@ -523,28 +523,28 @@ impl YubiKey {
/// Unblock a Personal Identification Number (PIN) using a previously
/// configured PIN Unblocking Key (PUK).
#[cfg(feature = "untested")]
pub fn unblock_pin(&mut self, puk: &[u8], new_pin: &[u8]) -> Result<(), Error> {
pub fn unblock_pin(&mut self, puk: &[u8], new_pin: &[u8]) -> Result<()> {
let txn = self.begin_transaction()?;
txn.change_ref(ChangeRefAction::UnblockPin, puk, new_pin)
}
/// Fetch an object from the YubiKey
#[cfg(feature = "untested")]
pub fn fetch_object(&mut self, object_id: ObjectId) -> Result<Buffer, Error> {
pub fn fetch_object(&mut self, object_id: ObjectId) -> Result<Buffer> {
let txn = self.begin_transaction()?;
txn.fetch_object(object_id)
}
/// Save an object
#[cfg(feature = "untested")]
pub fn save_object(&mut self, object_id: ObjectId, indata: &mut [u8]) -> Result<(), Error> {
pub fn save_object(&mut self, object_id: ObjectId, indata: &mut [u8]) -> Result<()> {
let txn = self.begin_transaction()?;
txn.save_object(object_id, indata)
}
/// Get an auth challenge
#[cfg(feature = "untested")]
pub fn get_auth_challenge(&mut self) -> Result<[u8; 8], Error> {
pub fn get_auth_challenge(&mut self) -> Result<[u8; 8]> {
let txn = self.begin_transaction()?;
let response = Apdu::new(Ins::Authenticate)
@@ -561,7 +561,7 @@ impl YubiKey {
/// Verify an auth response
#[cfg(feature = "untested")]
pub fn verify_auth_response(&mut self, response: [u8; 8]) -> Result<(), Error> {
pub fn verify_auth_response(&mut self, response: [u8; 8]) -> Result<()> {
let mut data = [0u8; 12];
data[0] = 0x7c;
data[1] = 0x0a;
@@ -591,7 +591,7 @@ impl YubiKey {
///
/// The reset function is only available when both pins are blocked.
#[cfg(feature = "untested")]
pub fn reset_device(&mut self) -> Result<(), Error> {
pub fn reset_device(&mut self) -> Result<()> {
let templ = [0, Ins::Reset.code(), 0, 0];
let txn = self.begin_transaction()?;
let status_words = txn.transfer_data(&templ, &[], 255)?.status_words();
@@ -607,7 +607,7 @@ impl YubiKey {
impl<'a> TryFrom<&'a Reader<'_>> for YubiKey {
type Error = Error;
fn try_from(reader: &'a Reader<'_>) -> Result<Self, Error> {
fn try_from(reader: &'a Reader<'_>) -> Result<Self> {
let mut card = reader.connect().map_err(|e| {
error!("error connecting to reader '{}': {}", reader.name(), e);
e