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:
committed by
GitHub
parent
1051eaf26d
commit
de51b0cc46
Generated
+2
-2
@@ -820,9 +820,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.4"
|
||||
version = "0.12.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||
checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ pub struct YubiKeyCli {
|
||||
|
||||
impl YubiKeyCli {
|
||||
/// Print usage information
|
||||
pub fn print_usage() -> Result<(), io::Error> {
|
||||
pub fn print_usage() -> io::Result<()> {
|
||||
let mut stdout = STDOUT.lock();
|
||||
stdout.reset()?;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ impl ReadersCmd {
|
||||
index: usize,
|
||||
name: &str,
|
||||
serial: Serial,
|
||||
) -> Result<(), io::Error> {
|
||||
) -> io::Result<()> {
|
||||
stream.set_color(ColorSpec::new().set_bold(true))?;
|
||||
write!(stream, "{:>3}:", index)?;
|
||||
stream.reset()?;
|
||||
|
||||
@@ -51,7 +51,7 @@ impl StatusCmd {
|
||||
stream: &mut StandardStreamLock<'_>,
|
||||
name: &str,
|
||||
value: impl ToString,
|
||||
) -> Result<(), io::Error> {
|
||||
) -> io::Result<()> {
|
||||
stream.set_color(ColorSpec::new().set_bold(true))?;
|
||||
write!(stream, "{:>12}:", name)?;
|
||||
stream.reset()?;
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ pub fn print_cert_info(
|
||||
yubikey: &mut YubiKey,
|
||||
slot: SlotId,
|
||||
stream: &mut StandardStreamLock<'_>,
|
||||
) -> Result<(), io::Error> {
|
||||
) -> io::Result<()> {
|
||||
let cert = match Certificate::read(yubikey, slot) {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
@@ -82,7 +82,7 @@ fn print_cert_attr(
|
||||
stream: &mut StandardStreamLock<'_>,
|
||||
name: &str,
|
||||
value: impl ToString,
|
||||
) -> Result<(), io::Error> {
|
||||
) -> io::Result<()> {
|
||||
stream.set_color(ColorSpec::new().set_bold(true))?;
|
||||
write!(stream, "{:>12}:", name)?;
|
||||
stream.reset()?;
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ impl Status {
|
||||
}
|
||||
|
||||
/// Print the given message
|
||||
fn print(self, stream: &StandardStream, msg: impl AsRef<str>) -> Result<(), io::Error> {
|
||||
fn print(self, stream: &StandardStream, msg: impl AsRef<str>) -> io::Result<()> {
|
||||
let mut s = stream.lock();
|
||||
s.reset()?;
|
||||
s.set_color(ColorSpec::new().set_fg(self.color).set_bold(self.bold))?;
|
||||
|
||||
+2
-2
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)?)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user