Certificate::generate_self_signed
This commit is contained in:
@@ -276,7 +276,6 @@ impl Response {
|
||||
}
|
||||
|
||||
/// Get the raw [`StatusWords`] code for this response.
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn code(&self) -> u16 {
|
||||
self.status_words.code()
|
||||
}
|
||||
|
||||
+221
-6
@@ -32,24 +32,27 @@
|
||||
|
||||
use crate::{
|
||||
error::Error,
|
||||
key::{AlgorithmId, SlotId},
|
||||
key::{sign_data, AlgorithmId, SlotId},
|
||||
serialization::*,
|
||||
transaction::Transaction,
|
||||
yubikey::YubiKey,
|
||||
Buffer,
|
||||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
use elliptic_curve::weierstrass::{
|
||||
curve::{NistP256, NistP384},
|
||||
PublicKey as EcPublicKey,
|
||||
};
|
||||
use log::error;
|
||||
use num_bigint::BigUint;
|
||||
use rsa::{PublicKey, RSAPublicKey};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::ops::DerefMut;
|
||||
use x509_parser::{parse_x509_der, x509::SubjectPublicKeyInfo};
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
use crate::CB_OBJ_MAX;
|
||||
|
||||
// TODO: Make these der_parser::oid::Oid constants when it has const fn support.
|
||||
@@ -59,9 +62,7 @@ const OID_NIST_P256: &str = "1.2.840.10045.3.1.7";
|
||||
const OID_NIST_P384: &str = "1.3.132.0.34";
|
||||
|
||||
const TAG_CERT: u8 = 0x70;
|
||||
#[cfg(feature = "untested")]
|
||||
const TAG_CERT_COMPRESS: u8 = 0x71;
|
||||
#[cfg(feature = "untested")]
|
||||
const TAG_CERT_LRC: u8 = 0xFE;
|
||||
|
||||
/// Information about how a [`Certificate`] is stored within a YubiKey.
|
||||
@@ -95,6 +96,40 @@ impl From<CertInfo> for u8 {
|
||||
}
|
||||
}
|
||||
|
||||
impl x509::AlgorithmIdentifier for AlgorithmId {
|
||||
type AlgorithmOid = &'static [u64];
|
||||
|
||||
fn algorithm(&self) -> Self::AlgorithmOid {
|
||||
match self {
|
||||
// RSA encryption
|
||||
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => &[1, 2, 840, 113_549, 1, 1, 1],
|
||||
// EC Public Key
|
||||
AlgorithmId::EccP256 | AlgorithmId::EccP384 => &[1, 2, 840, 10045, 2, 1],
|
||||
}
|
||||
}
|
||||
|
||||
fn parameters<W: std::io::Write>(
|
||||
&self,
|
||||
w: cookie_factory::WriteContext<W>,
|
||||
) -> cookie_factory::GenResult<W> {
|
||||
use x509::der::write::der_oid;
|
||||
|
||||
// From [RFC 5480](https://tools.ietf.org/html/rfc5480#section-2.1.1):
|
||||
// ```text
|
||||
// ECParameters ::= CHOICE {
|
||||
// namedCurve OBJECT IDENTIFIER
|
||||
// -- implicitCurve NULL
|
||||
// -- specifiedCurve SpecifiedECDomain
|
||||
// }
|
||||
// ```
|
||||
match self {
|
||||
AlgorithmId::EccP256 => der_oid(&[1, 2, 840, 10045, 3, 1, 7][..])(w),
|
||||
AlgorithmId::EccP384 => der_oid(&[1, 3, 132, 0, 34][..])(w),
|
||||
_ => Ok(w),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about a public key within a [`Certificate`].
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub enum PublicKeyInfo {
|
||||
@@ -161,6 +196,59 @@ impl PublicKeyInfo {
|
||||
}
|
||||
}
|
||||
|
||||
impl x509::SubjectPublicKeyInfo for PublicKeyInfo {
|
||||
type AlgorithmId = AlgorithmId;
|
||||
type SubjectPublicKey = Vec<u8>;
|
||||
|
||||
fn algorithm_id(&self) -> AlgorithmId {
|
||||
self.algorithm()
|
||||
}
|
||||
|
||||
fn public_key(&self) -> Vec<u8> {
|
||||
match self {
|
||||
PublicKeyInfo::Rsa { pubkey, .. } => {
|
||||
cookie_factory::gen_simple(write_pki::rsa_pubkey(pubkey), vec![])
|
||||
.expect("can write to Vec")
|
||||
}
|
||||
PublicKeyInfo::EcP256(pubkey) => pubkey.as_bytes().to_vec(),
|
||||
PublicKeyInfo::EcP384(pubkey) => pubkey.as_bytes().to_vec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum SignatureId {
|
||||
/// Public-Key Cryptography Standards (PKCS) #1 version 1.5 signature algorithm with
|
||||
/// Secure Hash Algorithm 256 (SHA256) and Rivest, Shamir and Adleman (RSA) encryption
|
||||
///
|
||||
/// See RFC 4055 and RFC 8017.
|
||||
Sha256WithRsaEncryption,
|
||||
|
||||
/// Elliptic Curve Digital Signature Algorithm (DSA) coupled with the Secure Hash
|
||||
/// Algorithm 256 (SHA256) algorithm
|
||||
///
|
||||
/// See RFC 5758.
|
||||
EcdsaWithSha256,
|
||||
}
|
||||
|
||||
impl x509::AlgorithmIdentifier for SignatureId {
|
||||
type AlgorithmOid = &'static [u64];
|
||||
|
||||
fn algorithm(&self) -> Self::AlgorithmOid {
|
||||
match self {
|
||||
SignatureId::Sha256WithRsaEncryption => &[1, 2, 840, 113_549, 1, 1, 11],
|
||||
SignatureId::EcdsaWithSha256 => &[1, 2, 840, 10045, 4, 3, 2],
|
||||
}
|
||||
}
|
||||
|
||||
fn parameters<W: std::io::Write>(
|
||||
&self,
|
||||
w: cookie_factory::WriteContext<W>,
|
||||
) -> cookie_factory::GenResult<W> {
|
||||
// No parameters for any SignatureId
|
||||
Ok(w)
|
||||
}
|
||||
}
|
||||
|
||||
/// Certificates
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Certificate {
|
||||
@@ -180,6 +268,107 @@ impl<'a> TryFrom<&'a [u8]> for Certificate {
|
||||
}
|
||||
|
||||
impl Certificate {
|
||||
/// Creates a new self-signed certificate for the given key. Writes the resulting
|
||||
/// certificate to the slot before returning it.
|
||||
pub fn generate_self_signed(
|
||||
yubikey: &mut YubiKey,
|
||||
key: SlotId,
|
||||
serial: BigUint,
|
||||
not_after: Option<DateTime<Utc>>,
|
||||
subject: String,
|
||||
subject_pki: PublicKeyInfo,
|
||||
) -> Result<Self, Error> {
|
||||
// Issuer and subject are the same in self-signed certificates
|
||||
let issuer = subject.clone();
|
||||
|
||||
let mut tbs_cert = Buffer::new(Vec::with_capacity(CB_OBJ_MAX));
|
||||
|
||||
let signature_algorithm = match subject_pki.algorithm() {
|
||||
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => SignatureId::Sha256WithRsaEncryption,
|
||||
AlgorithmId::EccP256 | AlgorithmId::EccP384 => SignatureId::EcdsaWithSha256,
|
||||
};
|
||||
|
||||
cookie_factory::gen(
|
||||
x509::write::tbs_certificate(
|
||||
&serial.to_bytes_be(),
|
||||
&signature_algorithm,
|
||||
&issuer,
|
||||
Utc::now(),
|
||||
not_after,
|
||||
&subject,
|
||||
&subject_pki,
|
||||
),
|
||||
tbs_cert.deref_mut(),
|
||||
)
|
||||
.expect("can serialize to Vec");
|
||||
|
||||
let signature = match signature_algorithm {
|
||||
SignatureId::Sha256WithRsaEncryption => {
|
||||
use cookie_factory::{combinator::slice, sequence::tuple};
|
||||
use x509::{
|
||||
der::write::{der_octet_string, der_sequence},
|
||||
write::algorithm_identifier,
|
||||
};
|
||||
|
||||
let em_len = if let AlgorithmId::Rsa1024 = subject_pki.algorithm() {
|
||||
128
|
||||
} else {
|
||||
256
|
||||
};
|
||||
|
||||
let h = Sha256::digest(&tbs_cert);
|
||||
|
||||
let t = cookie_factory::gen_simple(
|
||||
der_sequence((
|
||||
algorithm_identifier(&signature_algorithm),
|
||||
der_octet_string(&h),
|
||||
)),
|
||||
vec![],
|
||||
)
|
||||
.expect("can serialize into Vec");
|
||||
|
||||
let em = cookie_factory::gen_simple(
|
||||
tuple((
|
||||
slice(&[0x00, 0x01]),
|
||||
slice(&vec![0xff; em_len - t.len() - 3]),
|
||||
slice(&[0x00]),
|
||||
slice(t),
|
||||
)),
|
||||
vec![],
|
||||
)
|
||||
.expect("can serialize to Vec");
|
||||
|
||||
sign_data(yubikey, &em, subject_pki.algorithm(), key)
|
||||
}
|
||||
SignatureId::EcdsaWithSha256 => sign_data(
|
||||
yubikey,
|
||||
&Sha256::digest(&tbs_cert),
|
||||
subject_pki.algorithm(),
|
||||
key,
|
||||
),
|
||||
}?;
|
||||
|
||||
let mut data = Buffer::new(Vec::with_capacity(CB_OBJ_MAX));
|
||||
|
||||
cookie_factory::gen(
|
||||
x509::write::certificate(&tbs_cert, &signature_algorithm, &signature),
|
||||
data.deref_mut(),
|
||||
)
|
||||
.expect("can serialize to Vec");
|
||||
|
||||
let cert = Certificate {
|
||||
serial,
|
||||
issuer,
|
||||
subject,
|
||||
subject_pki,
|
||||
data,
|
||||
};
|
||||
|
||||
cert.write(yubikey, key, CertInfo::Uncompressed)?;
|
||||
|
||||
Ok(cert)
|
||||
}
|
||||
|
||||
/// Read a certificate from the given slot in the YubiKey
|
||||
pub fn read(yubikey: &mut YubiKey, slot: SlotId) -> Result<Self, Error> {
|
||||
let txn = yubikey.begin_transaction()?;
|
||||
@@ -193,7 +382,6 @@ impl Certificate {
|
||||
}
|
||||
|
||||
/// Write this certificate into the YubiKey in the given slot
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn write(
|
||||
&self,
|
||||
yubikey: &mut YubiKey,
|
||||
@@ -295,7 +483,6 @@ pub(crate) fn read_certificate(txn: &Transaction<'_>, slot: SlotId) -> Result<Bu
|
||||
}
|
||||
|
||||
/// Write certificate
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) fn write_certificate(
|
||||
txn: &Transaction<'_>,
|
||||
slot: SlotId,
|
||||
@@ -394,3 +581,31 @@ mod read_pki {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod write_pki {
|
||||
use cookie_factory::{SerializeFn, WriteContext};
|
||||
use rsa::{BigUint, PublicKey, RSAPublicKey};
|
||||
use std::io::Write;
|
||||
use x509::der::write::{der_integer, der_sequence};
|
||||
|
||||
/// Encodes a usize as an ASN.1 integer using DER.
|
||||
fn der_integer_biguint<'a, W: Write + 'a>(num: &'a BigUint) -> impl SerializeFn<W> + 'a {
|
||||
move |w: WriteContext<W>| der_integer(&num.to_bytes_be())(w)
|
||||
}
|
||||
|
||||
/// From [RFC 8017](https://tools.ietf.org/html/rfc8017#appendix-A.1.1):
|
||||
/// ```text
|
||||
/// RSAPublicKey ::= SEQUENCE {
|
||||
/// modulus INTEGER, -- n
|
||||
/// publicExponent INTEGER -- e
|
||||
/// }
|
||||
/// ```
|
||||
pub(super) fn rsa_pubkey<'a, W: Write + 'a>(
|
||||
pubkey: &'a RSAPublicKey,
|
||||
) -> impl SerializeFn<W> + 'a {
|
||||
der_sequence((
|
||||
der_integer_biguint(pubkey.n()),
|
||||
der_integer_biguint(pubkey.e()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
+5
-14
@@ -38,8 +38,11 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use crate::{
|
||||
apdu::{Ins, StatusWords},
|
||||
certificate::{self, Certificate},
|
||||
error::Error,
|
||||
serialization::*,
|
||||
settings,
|
||||
yubikey::YubiKey,
|
||||
ObjectId,
|
||||
};
|
||||
@@ -47,32 +50,23 @@ use log::debug;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
use crate::CB_OBJ_MAX;
|
||||
use crate::{
|
||||
apdu::{Ins, StatusWords},
|
||||
certificate::PublicKeyInfo,
|
||||
policy::{PinPolicy, TouchPolicy},
|
||||
serialization::*,
|
||||
settings, Buffer, CB_OBJ_MAX,
|
||||
Buffer,
|
||||
};
|
||||
#[cfg(feature = "untested")]
|
||||
use elliptic_curve::weierstrass::PublicKey as EcPublicKey;
|
||||
#[cfg(feature = "untested")]
|
||||
use log::{error, warn};
|
||||
#[cfg(feature = "untested")]
|
||||
use rsa::{BigUint, RSAPublicKey};
|
||||
#[cfg(feature = "untested")]
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
const CB_ECC_POINTP256: usize = 65;
|
||||
#[cfg(feature = "untested")]
|
||||
const CB_ECC_POINTP384: usize = 97;
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
const TAG_RSA_MODULUS: u8 = 0x81;
|
||||
#[cfg(feature = "untested")]
|
||||
const TAG_RSA_EXP: u8 = 0x82;
|
||||
#[cfg(feature = "untested")]
|
||||
const TAG_ECC_POINT: u8 = 0x86;
|
||||
|
||||
/// Slot identifiers.
|
||||
@@ -381,7 +375,6 @@ impl From<AlgorithmId> for u8 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
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> {
|
||||
@@ -435,7 +428,6 @@ impl Key {
|
||||
}
|
||||
|
||||
/// Generate key
|
||||
#[cfg(feature = "untested")]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub fn generate(
|
||||
yubikey: &mut YubiKey,
|
||||
@@ -758,7 +750,6 @@ pub fn attest(yubikey: &mut YubiKey, key: SlotId) -> Result<Buffer, Error> {
|
||||
}
|
||||
|
||||
/// Sign data using a PIV key
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn sign_data(
|
||||
yubikey: &mut YubiKey,
|
||||
raw_in: &[u8],
|
||||
|
||||
@@ -151,7 +151,6 @@ pub mod msroots;
|
||||
pub mod policy;
|
||||
pub mod readers;
|
||||
mod serialization;
|
||||
#[cfg(feature = "untested")]
|
||||
pub mod settings;
|
||||
mod transaction;
|
||||
pub mod yubikey;
|
||||
@@ -174,7 +173,6 @@ pub(crate) type Buffer = zeroize::Zeroizing<Vec<u8>>;
|
||||
pub(crate) const CB_BUF_MAX: usize = 3072;
|
||||
|
||||
/// YubiKey max object size
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) const CB_OBJ_MAX: usize = CB_BUF_MAX - 9;
|
||||
pub(crate) const CB_OBJ_TAG_MIN: usize = 2; // 1 byte tag + 1 byte len
|
||||
#[cfg(feature = "untested")]
|
||||
|
||||
@@ -41,7 +41,6 @@ use crate::{
|
||||
metadata, yubikey::YubiKey, CB_BUF_MAX, CB_OBJ_MAX, TAG_ADMIN, TAG_ADMIN_FLAGS_1,
|
||||
TAG_ADMIN_SALT, TAG_PROTECTED, TAG_PROTECTED_MGM,
|
||||
};
|
||||
#[cfg(feature = "untested")]
|
||||
use des::{
|
||||
block_cipher_trait::{generic_array::GenericArray, BlockCipher},
|
||||
TdesEde3,
|
||||
@@ -282,7 +281,6 @@ impl MgmKey {
|
||||
}
|
||||
|
||||
/// Encrypt with 3DES key
|
||||
#[cfg(feature = "untested")]
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub(crate) fn encrypt(&self, input: &[u8; DES_LEN_DES]) -> [u8; DES_LEN_DES] {
|
||||
let mut output = input.to_owned();
|
||||
@@ -292,7 +290,6 @@ impl MgmKey {
|
||||
}
|
||||
|
||||
/// Decrypt with 3DES key
|
||||
#[cfg(feature = "untested")]
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub(crate) fn decrypt(&self, input: &[u8; DES_LEN_DES]) -> [u8; DES_LEN_DES] {
|
||||
let mut output = input.to_owned();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//! Enums representing key policies.
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
use crate::{error::Error, serialization::Tlv};
|
||||
|
||||
/// Specifies how often the PIN needs to be entered for access to the credential in a
|
||||
@@ -38,7 +37,6 @@ impl From<PinPolicy> for u8 {
|
||||
impl PinPolicy {
|
||||
/// Writes the `PinPolicy` in the format the YubiKey expects during key generation or
|
||||
/// importation.
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) fn write(self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
match self {
|
||||
PinPolicy::Default => Ok(0),
|
||||
@@ -83,7 +81,6 @@ impl From<TouchPolicy> for u8 {
|
||||
impl TouchPolicy {
|
||||
/// Writes the `TouchPolicy` in the format the YubiKey expects during key generation
|
||||
/// or importation.
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) fn write(self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
match self {
|
||||
TouchPolicy::Default => Ok(0),
|
||||
|
||||
@@ -79,7 +79,6 @@ impl<'a> Tlv<'a> {
|
||||
}
|
||||
|
||||
/// Writes a TLV to the given buffer.
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) fn write(buffer: &mut [u8], tag: u8, value: &[u8]) -> Result<usize, Error> {
|
||||
if buffer.len() < CB_OBJ_TAG_MIN {
|
||||
return Err(Error::SizeError);
|
||||
@@ -99,7 +98,6 @@ impl<'a> Tlv<'a> {
|
||||
/// Writes a TLV to the given buffer.
|
||||
///
|
||||
/// `value` is guaranteed to be called with a mutable slice of length `length`.
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) fn write_as<Gen>(
|
||||
buffer: &mut [u8],
|
||||
tag: u8,
|
||||
@@ -126,7 +124,6 @@ impl<'a> Tlv<'a> {
|
||||
}
|
||||
|
||||
/// Set length
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) fn set_length(buffer: &mut [u8], length: usize) -> Result<usize, Error> {
|
||||
if length < 0x80 {
|
||||
if buffer.is_empty() {
|
||||
|
||||
+3
-8
@@ -4,20 +4,17 @@ use crate::{
|
||||
apdu::Response,
|
||||
apdu::{Ins, StatusWords, APDU},
|
||||
error::Error,
|
||||
key::{AlgorithmId, SlotId},
|
||||
serialization::*,
|
||||
yubikey::*,
|
||||
Buffer, ObjectId, CB_BUF_MAX, PIV_AID, YK_AID,
|
||||
Buffer, ObjectId, CB_BUF_MAX, CB_OBJ_MAX, PIV_AID, YK_AID,
|
||||
};
|
||||
use log::{error, trace};
|
||||
use std::convert::TryInto;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
use crate::{
|
||||
key::{AlgorithmId, SlotId},
|
||||
mgm::{MgmKey, DES_LEN_3DES},
|
||||
CB_OBJ_MAX,
|
||||
};
|
||||
use crate::mgm::{MgmKey, DES_LEN_3DES};
|
||||
|
||||
const CB_PIN_MAX: usize = 8;
|
||||
|
||||
@@ -252,7 +249,6 @@ impl<'tx> Transaction<'tx> {
|
||||
/// This is the common backend for all public key encryption and signing
|
||||
/// operations.
|
||||
// TODO(tarcieri): refactor this to be less gross/coupled.
|
||||
#[cfg(feature = "untested")]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn authenticated_command(
|
||||
&self,
|
||||
@@ -472,7 +468,6 @@ impl<'tx> Transaction<'tx> {
|
||||
}
|
||||
|
||||
/// Save an object.
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn save_object(&self, object_id: ObjectId, indata: &[u8]) -> Result<(), Error> {
|
||||
let templ = [0, Ins::PutData.code(), 0x3f, 0xff];
|
||||
|
||||
|
||||
+6
-15
@@ -31,48 +31,41 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use crate::{
|
||||
apdu::{Ins, APDU},
|
||||
cccid::CCC,
|
||||
chuid::CHUID,
|
||||
config::Config,
|
||||
error::Error,
|
||||
mgm::MgmKey,
|
||||
readers::{Reader, Readers},
|
||||
transaction::Transaction,
|
||||
};
|
||||
use log::{error, info};
|
||||
use pcsc::Card;
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt::{self, Display},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
use crate::{
|
||||
apdu::{Ins, StatusWords, APDU},
|
||||
metadata,
|
||||
mgm::MgmKey,
|
||||
Buffer, ObjectId, CB_BUF_MAX, CB_OBJ_MAX, MGMT_AID, TAG_ADMIN, TAG_ADMIN_FLAGS_1,
|
||||
TAG_ADMIN_TIMESTAMP,
|
||||
apdu::StatusWords, metadata, Buffer, ObjectId, CB_BUF_MAX, CB_OBJ_MAX, MGMT_AID, TAG_ADMIN,
|
||||
TAG_ADMIN_FLAGS_1, TAG_ADMIN_TIMESTAMP,
|
||||
};
|
||||
#[cfg(feature = "untested")]
|
||||
use getrandom::getrandom;
|
||||
#[cfg(feature = "untested")]
|
||||
use secrecy::ExposeSecret;
|
||||
#[cfg(feature = "untested")]
|
||||
use std::{
|
||||
convert::TryInto,
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
/// Flag for PUK blocked
|
||||
pub(crate) const ADMIN_FLAGS_1_PUK_BLOCKED: u8 = 0x01;
|
||||
|
||||
/// 3DES authentication
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) const ALGO_3DES: u8 = 0x03;
|
||||
|
||||
/// Card management key
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) const KEY_CARDMGM: u8 = 0x9b;
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
@@ -82,7 +75,6 @@ pub(crate) const CHREF_ACT_UNBLOCK_PIN: i32 = 1;
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) const CHREF_ACT_CHANGE_PUK: i32 = 2;
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
const TAG_DYN_AUTH: u8 = 0x7c;
|
||||
|
||||
/// Cached YubiKey PIN
|
||||
@@ -274,7 +266,6 @@ impl YubiKey {
|
||||
}
|
||||
|
||||
/// Authenticate to the card using the provided management key (MGM).
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn authenticate(&mut self, mgm_key: MgmKey) -> Result<(), Error> {
|
||||
let txn = self.begin_transaction()?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user