Merge pull request #44 from str4d/more-enums

Convert SlotId and AlgorithmId into enums
This commit is contained in:
Tony Arcieri
2019-11-30 14:28:36 -08:00
committed by GitHub
7 changed files with 333 additions and 202 deletions
+4 -9
View File
@@ -31,13 +31,8 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{
consts::*,
error::Error,
key::{self, SlotId},
serialization::*,
transaction::Transaction,
yubikey::YubiKey,
Buffer,
consts::*, error::Error, key::SlotId, serialization::*, transaction::Transaction,
yubikey::YubiKey, Buffer,
};
use log::error;
use zeroize::Zeroizing;
@@ -100,7 +95,7 @@ impl AsRef<[u8]> for Certificate {
/// Read certificate
pub(crate) fn read_certificate(txn: &Transaction<'_>, slot: SlotId) -> Result<Buffer, Error> {
let mut len: usize = 0;
let object_id = key::slot_object(slot)?;
let object_id = slot.object_id();
let mut buf = match txn.fetch_object(object_id) {
Ok(b) => b,
@@ -141,7 +136,7 @@ pub(crate) fn write_certificate(
let mut buf = [0u8; CB_OBJ_MAX];
let mut offset = 0;
let object_id = key::slot_object(slot)?;
let object_id = slot.object_id();
if data.is_none() {
return txn.save_object(object_id, &[]);
-55
View File
@@ -124,10 +124,6 @@ pub const TAG_ECC_POINT: u8 = 0x86;
pub const YKPIV_ALGO_TAG: u8 = 0x80;
pub const YKPIV_ALGO_3DES: u8 = 0x03;
pub const YKPIV_ALGO_RSA1024: u8 = 0x06;
pub const YKPIV_ALGO_RSA2048: u8 = 0x07;
pub const YKPIV_ALGO_ECCP256: u8 = 0x11;
pub const YKPIV_ALGO_ECCP384: u8 = 0x14;
pub const YKPIV_ATR_NEO_R3: &[u8] = b";\xFC\x13\0\0\x811\xFE\x15YubikeyNEOr3\xE1\0";
@@ -141,72 +137,21 @@ pub const YKPIV_CCCID_SIZE: usize = 14;
pub const YKPIV_CERTINFO_UNCOMPRESSED: u8 = 0;
pub const YKPIV_CERTINFO_GZIP: u8 = 1;
pub const YKPIV_KEY_AUTHENTICATION: u8 = 0x9a;
pub const YKPIV_KEY_CARDMGM: u8 = 0x9b;
pub const YKPIV_KEY_SIGNATURE: u8 = 0x9c;
pub const YKPIV_KEY_KEYMGM: u8 = 0x9d;
pub const YKPIV_KEY_CARDAUTH: u8 = 0x9e;
pub const YKPIV_KEY_RETIRED1: u8 = 0x82;
pub const YKPIV_KEY_RETIRED2: u8 = 0x83;
pub const YKPIV_KEY_RETIRED3: u8 = 0x84;
pub const YKPIV_KEY_RETIRED4: u8 = 0x85;
pub const YKPIV_KEY_RETIRED5: u8 = 0x86;
pub const YKPIV_KEY_RETIRED6: u8 = 0x87;
pub const YKPIV_KEY_RETIRED7: u8 = 0x88;
pub const YKPIV_KEY_RETIRED8: u8 = 0x89;
pub const YKPIV_KEY_RETIRED9: u8 = 0x8a;
pub const YKPIV_KEY_RETIRED10: u8 = 0x8b;
pub const YKPIV_KEY_RETIRED11: u8 = 0x8c;
pub const YKPIV_KEY_RETIRED12: u8 = 0x8d;
pub const YKPIV_KEY_RETIRED13: u8 = 0x8e;
pub const YKPIV_KEY_RETIRED14: u8 = 0x8f;
pub const YKPIV_KEY_RETIRED15: u8 = 0x90;
pub const YKPIV_KEY_RETIRED16: u8 = 0x91;
pub const YKPIV_KEY_RETIRED17: u8 = 0x92;
pub const YKPIV_KEY_RETIRED18: u8 = 0x93;
pub const YKPIV_KEY_RETIRED19: u8 = 0x94;
pub const YKPIV_KEY_RETIRED20: u8 = 0x95;
pub const YKPIV_KEY_ATTESTATION: u8 = 0xf9;
pub const YKPIV_OBJ_CAPABILITY: u32 = 0x005f_c107;
pub const YKPIV_OBJ_CHUID: u32 = 0x005f_c102;
pub const YKPIV_OBJ_AUTHENTICATION: u32 = 0x005f_c105; // cert for 9a key
pub const YKPIV_OBJ_FINGERPRINTS: u32 = 0x005f_c103;
pub const YKPIV_OBJ_SECURITY: u32 = 0x005f_c106;
pub const YKPIV_OBJ_FACIAL: u32 = 0x005f_c108;
pub const YKPIV_OBJ_PRINTED: u32 = 0x005f_c109;
pub const YKPIV_OBJ_SIGNATURE: u32 = 0x005f_c10a; // cert for 9c key
pub const YKPIV_OBJ_KEY_MANAGEMENT: u32 = 0x005f_c10b; // cert for 9d key
pub const YKPIV_OBJ_CARD_AUTH: u32 = 0x005f_c101; // cert for 9e key
pub const YKPIV_OBJ_DISCOVERY: u32 = 0x7e;
pub const YKPIV_OBJ_KEY_HISTORY: u32 = 0x005f_c10c;
pub const YKPIV_OBJ_IRIS: u32 = 0x005f_c121;
pub const YKPIV_OBJ_RETIRED1: u32 = 0x005f_c10d;
pub const YKPIV_OBJ_RETIRED2: u32 = 0x005f_c10e;
pub const YKPIV_OBJ_RETIRED3: u32 = 0x005f_c10f;
pub const YKPIV_OBJ_RETIRED4: u32 = 0x005f_c110;
pub const YKPIV_OBJ_RETIRED5: u32 = 0x005f_c111;
pub const YKPIV_OBJ_RETIRED6: u32 = 0x005f_c112;
pub const YKPIV_OBJ_RETIRED7: u32 = 0x005f_c113;
pub const YKPIV_OBJ_RETIRED8: u32 = 0x005f_c114;
pub const YKPIV_OBJ_RETIRED9: u32 = 0x005f_c115;
pub const YKPIV_OBJ_RETIRED10: u32 = 0x005f_c116;
pub const YKPIV_OBJ_RETIRED11: u32 = 0x005f_c117;
pub const YKPIV_OBJ_RETIRED12: u32 = 0x005f_c118;
pub const YKPIV_OBJ_RETIRED13: u32 = 0x005f_c119;
pub const YKPIV_OBJ_RETIRED14: u32 = 0x005f_c11a;
pub const YKPIV_OBJ_RETIRED15: u32 = 0x005f_c11b;
pub const YKPIV_OBJ_RETIRED16: u32 = 0x005f_c11c;
pub const YKPIV_OBJ_RETIRED17: u32 = 0x005f_c11d;
pub const YKPIV_OBJ_RETIRED18: u32 = 0x005f_c11e;
pub const YKPIV_OBJ_RETIRED19: u32 = 0x005f_c11f;
pub const YKPIV_OBJ_RETIRED20: u32 = 0x005f_c120;
// Internal object IDs
pub const YKPIV_OBJ_ADMIN_DATA: u32 = 0x005f_ff00;
pub const YKPIV_OBJ_ATTESTATION: u32 = 0x005f_ff01;
pub const YKPIV_OBJ_MSCMAP: u32 = 0x005f_ff10;
pub const YKPIV_OBJ_MSROOTS1: u32 = 0x005f_ff11;
pub const YKPIV_OBJ_MSROOTS2: u32 = 0x005f_ff12;
+3 -3
View File
@@ -158,7 +158,7 @@ impl Container {
Ok(Container {
name,
slot: bytes[name_bytes_len],
slot: bytes[name_bytes_len].try_into()?,
key_spec: bytes[name_bytes_len + 1],
key_size_bits: u16::from_le_bytes(
bytes[(name_bytes_len + 2)..(name_bytes_len + 4)]
@@ -185,7 +185,7 @@ impl Container {
bytes.extend_from_slice(&self.name[i].to_le_bytes());
}
bytes.push(self.slot);
bytes.push(self.slot.into());
bytes.push(self.key_spec);
bytes.extend_from_slice(&self.key_size_bits.to_le_bytes());
bytes.push(self.flags);
@@ -204,7 +204,7 @@ impl Debug for Container {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"PivContainer {{ name: {:?}, slot: {}, key_spec: {}, key_size_bits: {}, \
"PivContainer {{ name: {:?}, slot: {:?}, key_spec: {}, key_size_bits: {}, \
flags: {}, pin_id: {}, associated_echd_container: {}, cert_fingerprint: {:?} }}",
&self.name[..],
self.slot,
+266 -60
View File
@@ -45,61 +45,272 @@ use crate::{
serialization::*,
settings,
yubikey::YubiKey,
AlgorithmId, Buffer, ObjectId,
Buffer, ObjectId,
};
use log::{debug, error, warn};
use std::convert::TryFrom;
/// Slot identifiers.
/// <https://developers.yubico.com/PIV/Introduction/Certificate_slots.html>
// TODO(tarcieri): replace these with enums
pub type SlotId = u8;
#[derive(Clone, Copy, Debug)]
pub enum SlotId {
/// This certificate and its associated private key is used to authenticate the card
/// and the cardholder. This slot is used for things like system login. The end user
/// PIN is required to perform any private key operations. Once the PIN has been
/// provided successfully, multiple private key operations may be performed without
/// additional cardholder consent.
Authentication,
/// Get the [`ObjectId`] that corresponds to a given [`SlotId`]
// TODO(tarcieri): factor this into a slot ID enum
pub(crate) fn slot_object(slot: SlotId) -> Result<ObjectId, Error> {
let id = match slot {
YKPIV_KEY_AUTHENTICATION => YKPIV_OBJ_AUTHENTICATION,
YKPIV_KEY_SIGNATURE => YKPIV_OBJ_SIGNATURE,
YKPIV_KEY_KEYMGM => YKPIV_OBJ_KEY_MANAGEMENT,
YKPIV_KEY_CARDAUTH => YKPIV_OBJ_CARD_AUTH,
YKPIV_KEY_ATTESTATION => YKPIV_OBJ_ATTESTATION,
slot if slot >= YKPIV_KEY_RETIRED1 && (slot <= YKPIV_KEY_RETIRED20) => {
YKPIV_OBJ_RETIRED1 + (slot - YKPIV_KEY_RETIRED1) as u32
/// This certificate and its associated private key is used for digital signatures for
/// the purpose of document signing, or signing files and executables. The end user
/// PIN is required to perform any private key operations. The PIN must be submitted
/// every time immediately before a sign operation, to ensure cardholder participation
/// for every digital signature generated.
Signature,
/// This certificate and its associated private key is used for encryption for the
/// purpose of confidentiality. This slot is used for things like encrypting e-mails
/// or files. The end user PIN is required to perform any private key operations. Once
/// the PIN has been provided successfully, multiple private key operations may be
/// performed without additional cardholder consent.
KeyManagement,
/// This certificate and its associated private key is used to support additional
/// physical access applications, such as providing physical access to buildings via
/// PIV-enabled door locks. The end user PIN is NOT required to perform private key
/// operations for this slot.
CardAuthentication,
/// These slots are only available on the YubiKey 4 & 5. They are meant for previously
/// used Key Management keys to be able to decrypt earlier encrypted documents or
/// emails. In the YubiKey 4 & 5 all 20 of them are fully available for use.
Retired(RetiredSlotId),
/// This slot is only available on YubiKey version 4.3 and newer. It is only used for
/// attestation of other keys generated on device with instruction `f9`. This slot is
/// not cleared on reset, but can be overwritten.
Attestation,
}
_ => return Err(Error::InvalidObject),
};
Ok(id)
impl TryFrom<u8> for SlotId {
type Error = Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x9a => Ok(SlotId::Authentication),
0x9c => Ok(SlotId::Signature),
0x9d => Ok(SlotId::KeyManagement),
0x9e => Ok(SlotId::CardAuthentication),
0xf9 => Ok(SlotId::Attestation),
_ => RetiredSlotId::try_from(value).map(SlotId::Retired),
}
}
}
impl From<SlotId> for u8 {
fn from(slot: SlotId) -> u8 {
match slot {
SlotId::Authentication => 0x9a,
SlotId::Signature => 0x9c,
SlotId::KeyManagement => 0x9d,
SlotId::CardAuthentication => 0x9e,
SlotId::Retired(retired) => retired.into(),
SlotId::Attestation => 0xf9,
}
}
}
impl SlotId {
/// Returns the [`ObjectId`] that corresponds to a given [`SlotId`].
pub(crate) fn object_id(self) -> ObjectId {
match self {
SlotId::Authentication => 0x005f_c105,
SlotId::Signature => 0x005f_c10a,
SlotId::KeyManagement => 0x005f_c10b,
SlotId::CardAuthentication => 0x005f_c101,
SlotId::Retired(retired) => retired.object_id(),
SlotId::Attestation => 0x005f_ff01,
}
}
}
/// Retired slot IDs.
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum RetiredSlotId {
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
R15,
R16,
R17,
R18,
R19,
R20,
}
impl TryFrom<u8> for RetiredSlotId {
type Error = Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x82 => Ok(RetiredSlotId::R1),
0x83 => Ok(RetiredSlotId::R2),
0x84 => Ok(RetiredSlotId::R3),
0x85 => Ok(RetiredSlotId::R4),
0x86 => Ok(RetiredSlotId::R5),
0x87 => Ok(RetiredSlotId::R6),
0x88 => Ok(RetiredSlotId::R7),
0x89 => Ok(RetiredSlotId::R8),
0x8a => Ok(RetiredSlotId::R9),
0x8b => Ok(RetiredSlotId::R10),
0x8c => Ok(RetiredSlotId::R11),
0x8d => Ok(RetiredSlotId::R12),
0x8e => Ok(RetiredSlotId::R13),
0x8f => Ok(RetiredSlotId::R14),
0x90 => Ok(RetiredSlotId::R15),
0x91 => Ok(RetiredSlotId::R16),
0x92 => Ok(RetiredSlotId::R17),
0x93 => Ok(RetiredSlotId::R18),
0x94 => Ok(RetiredSlotId::R19),
0x95 => Ok(RetiredSlotId::R20),
_ => Err(Error::InvalidObject),
}
}
}
impl From<RetiredSlotId> for u8 {
fn from(slot: RetiredSlotId) -> u8 {
match slot {
RetiredSlotId::R1 => 0x82,
RetiredSlotId::R2 => 0x83,
RetiredSlotId::R3 => 0x84,
RetiredSlotId::R4 => 0x85,
RetiredSlotId::R5 => 0x86,
RetiredSlotId::R6 => 0x87,
RetiredSlotId::R7 => 0x88,
RetiredSlotId::R8 => 0x89,
RetiredSlotId::R9 => 0x8a,
RetiredSlotId::R10 => 0x8b,
RetiredSlotId::R11 => 0x8c,
RetiredSlotId::R12 => 0x8d,
RetiredSlotId::R13 => 0x8e,
RetiredSlotId::R14 => 0x8f,
RetiredSlotId::R15 => 0x90,
RetiredSlotId::R16 => 0x91,
RetiredSlotId::R17 => 0x92,
RetiredSlotId::R18 => 0x93,
RetiredSlotId::R19 => 0x94,
RetiredSlotId::R20 => 0x95,
}
}
}
impl RetiredSlotId {
/// Returns the [`ObjectId`] that corresponds to a given [`RetiredSlotId`].
pub(crate) fn object_id(self) -> ObjectId {
match self {
RetiredSlotId::R1 => 0x005f_c10d,
RetiredSlotId::R2 => 0x005f_c10e,
RetiredSlotId::R3 => 0x005f_c10f,
RetiredSlotId::R4 => 0x005f_c110,
RetiredSlotId::R5 => 0x005f_c111,
RetiredSlotId::R6 => 0x005f_c112,
RetiredSlotId::R7 => 0x005f_c113,
RetiredSlotId::R8 => 0x005f_c114,
RetiredSlotId::R9 => 0x005f_c115,
RetiredSlotId::R10 => 0x005f_c116,
RetiredSlotId::R11 => 0x005f_c117,
RetiredSlotId::R12 => 0x005f_c118,
RetiredSlotId::R13 => 0x005f_c119,
RetiredSlotId::R14 => 0x005f_c11a,
RetiredSlotId::R15 => 0x005f_c11b,
RetiredSlotId::R16 => 0x005f_c11c,
RetiredSlotId::R17 => 0x005f_c11d,
RetiredSlotId::R18 => 0x005f_c11e,
RetiredSlotId::R19 => 0x005f_c11f,
RetiredSlotId::R20 => 0x005f_c120,
}
}
}
/// Personal Identity Verification (PIV) key slots
pub const SLOTS: [u8; 24] = [
YKPIV_KEY_AUTHENTICATION,
YKPIV_KEY_SIGNATURE,
YKPIV_KEY_KEYMGM,
YKPIV_KEY_RETIRED1,
YKPIV_KEY_RETIRED2,
YKPIV_KEY_RETIRED3,
YKPIV_KEY_RETIRED4,
YKPIV_KEY_RETIRED5,
YKPIV_KEY_RETIRED6,
YKPIV_KEY_RETIRED7,
YKPIV_KEY_RETIRED8,
YKPIV_KEY_RETIRED9,
YKPIV_KEY_RETIRED10,
YKPIV_KEY_RETIRED11,
YKPIV_KEY_RETIRED12,
YKPIV_KEY_RETIRED13,
YKPIV_KEY_RETIRED14,
YKPIV_KEY_RETIRED15,
YKPIV_KEY_RETIRED16,
YKPIV_KEY_RETIRED17,
YKPIV_KEY_RETIRED18,
YKPIV_KEY_RETIRED19,
YKPIV_KEY_RETIRED20,
YKPIV_KEY_CARDAUTH,
pub const SLOTS: [SlotId; 24] = [
SlotId::Authentication,
SlotId::Signature,
SlotId::KeyManagement,
SlotId::Retired(RetiredSlotId::R1),
SlotId::Retired(RetiredSlotId::R2),
SlotId::Retired(RetiredSlotId::R3),
SlotId::Retired(RetiredSlotId::R4),
SlotId::Retired(RetiredSlotId::R5),
SlotId::Retired(RetiredSlotId::R6),
SlotId::Retired(RetiredSlotId::R7),
SlotId::Retired(RetiredSlotId::R8),
SlotId::Retired(RetiredSlotId::R9),
SlotId::Retired(RetiredSlotId::R10),
SlotId::Retired(RetiredSlotId::R11),
SlotId::Retired(RetiredSlotId::R12),
SlotId::Retired(RetiredSlotId::R13),
SlotId::Retired(RetiredSlotId::R14),
SlotId::Retired(RetiredSlotId::R15),
SlotId::Retired(RetiredSlotId::R16),
SlotId::Retired(RetiredSlotId::R17),
SlotId::Retired(RetiredSlotId::R18),
SlotId::Retired(RetiredSlotId::R19),
SlotId::Retired(RetiredSlotId::R20),
SlotId::CardAuthentication,
];
/// Algorithm identifiers
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AlgorithmId {
/// 1024-bit RSA.
Rsa1024,
/// 2048-bit RSA.
Rsa2048,
/// ECDSA with the NIST P256 curve.
EccP256,
/// ECDSA with the NIST P384 curve.
EccP384,
}
impl TryFrom<u8> for AlgorithmId {
type Error = Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x06 => Ok(AlgorithmId::Rsa1024),
0x07 => Ok(AlgorithmId::Rsa2048),
0x11 => Ok(AlgorithmId::EccP256),
0x14 => Ok(AlgorithmId::EccP384),
_ => Err(Error::AlgorithmError),
}
}
}
impl From<AlgorithmId> for u8 {
fn from(id: AlgorithmId) -> u8 {
match id {
AlgorithmId::Rsa1024 => 0x06,
AlgorithmId::Rsa2048 => 0x07,
AlgorithmId::EccP256 => 0x11,
AlgorithmId::EccP384 => 0x14,
}
}
}
/// PIV cryptographic keys stored in a YubiKey
#[derive(Clone, Debug)]
pub struct Key {
@@ -120,14 +331,16 @@ impl Key {
let buf = match certificate::read_certificate(&txn, slot) {
Ok(b) => b,
Err(e) => {
debug!("error reading certificate in slot {}: {}", slot, e);
debug!("error reading certificate in slot {:?}: {}", slot, e);
continue;
}
};
if !buf.is_empty() {
let cert = Certificate::new(buf)?;
keys.push(Key { slot, cert });
}
}
Ok(keys)
}
@@ -202,10 +415,12 @@ pub fn generate(
let mut templ = [0, Ins::GenerateAsymmetric.code(), 0, 0];
let setting_roca: settings::BoolValue;
match algorithm {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => {
if yubikey.device_model() == DEVTYPE_YK4
&& (algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048)
&& yubikey.version.major == 4
&& (yubikey.version.minor < 3 || yubikey.version.minor == 3 && (yubikey.version.patch < 5))
&& (yubikey.version.minor < 3
|| yubikey.version.minor == 3 && (yubikey.version.patch < 5))
{
setting_roca = settings::BoolValue::get(SZ_SETTING_ROCA, true);
@@ -239,18 +454,13 @@ pub fn generate(
return Err(Error::NotSupported);
}
}
match algorithm {
YKPIV_ALGO_RSA1024 | YKPIV_ALGO_RSA2048 | YKPIV_ALGO_ECCP256 | YKPIV_ALGO_ECCP384 => (),
_ => {
error!("invalid algorithm specified");
return Err(Error::GenericError);
}
_ => (),
}
let txn = yubikey.begin_transaction()?;
templ[3] = slot;
templ[3] = slot.into();
let mut offset = 5;
in_data[..offset].copy_from_slice(&[
@@ -258,7 +468,7 @@ pub fn generate(
3, // length sans this 2-byte header
YKPIV_ALGO_TAG,
1,
algorithm,
algorithm.into(),
]);
if in_data[4] == 0 {
@@ -312,7 +522,7 @@ pub fn generate(
let data = Buffer::new(response.data().into());
match algorithm {
YKPIV_ALGO_RSA1024 | YKPIV_ALGO_RSA2048 => {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => {
let mut offset = 5;
let mut len = 0;
@@ -340,10 +550,10 @@ pub fn generate(
exp,
})
}
YKPIV_ALGO_ECCP256 | YKPIV_ALGO_ECCP384 => {
AlgorithmId::EccP256 | AlgorithmId::EccP384 => {
let mut offset = 3;
let len = if algorithm == YKPIV_ALGO_ECCP256 {
let len = if let AlgorithmId::EccP256 = algorithm {
CB_ECC_POINTP256
} else {
CB_ECC_POINTP384
@@ -367,9 +577,5 @@ pub fn generate(
let point = data[offset..(offset + len)].to_vec();
Ok(GeneratedKey::Ecc { algorithm, point })
}
_ => {
error!("wrong algorithm");
Err(Error::AlgorithmError)
}
}
}
-4
View File
@@ -167,10 +167,6 @@ pub mod yubikey;
pub use self::{key::Key, mgm::MgmKey};
pub use yubikey::YubiKey;
/// Algorithm identifiers
// TODO(tarcieri): make this an enum
pub type AlgorithmId = u8;
/// Object identifiers
pub type ObjectId = u32;
+11 -13
View File
@@ -9,6 +9,7 @@ use crate::{
use crate::{
apdu::{Response, StatusWords},
consts::*,
key::{AlgorithmId, SlotId},
mgm::MgmKey,
serialization::*,
Buffer, ObjectId,
@@ -266,18 +267,18 @@ impl<'tx> Transaction<'tx> {
pub(crate) fn authenticated_command(
&self,
sign_in: &[u8],
algorithm: u8,
key: u8,
algorithm: AlgorithmId,
key: SlotId,
decipher: bool,
) -> Result<Buffer, Error> {
let in_len = sign_in.len();
let mut indata = [0u8; 1024];
let templ = [0, Ins::Authenticate.code(), algorithm, key];
let templ = [0, Ins::Authenticate.code(), algorithm.into(), key.into()];
let mut len: usize = 0;
match algorithm {
YKPIV_ALGO_RSA1024 | YKPIV_ALGO_RSA2048 => {
let key_len = if algorithm == YKPIV_ALGO_RSA1024 {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => {
let key_len = if let AlgorithmId::Rsa1024 = algorithm {
128
} else {
256
@@ -287,8 +288,8 @@ impl<'tx> Transaction<'tx> {
return Err(Error::SizeError);
}
}
YKPIV_ALGO_ECCP256 | YKPIV_ALGO_ECCP384 => {
let key_len = if algorithm == YKPIV_ALGO_ECCP256 {
AlgorithmId::EccP256 | AlgorithmId::EccP384 => {
let key_len = if let AlgorithmId::EccP256 = algorithm {
32
} else {
48
@@ -299,7 +300,6 @@ impl<'tx> Transaction<'tx> {
return Err(Error::SizeError);
}
}
_ => return Err(Error::AlgorithmError),
}
let bytes = if in_len < 0x80 {
@@ -314,11 +314,9 @@ impl<'tx> Transaction<'tx> {
let mut offset = 1 + set_length(&mut indata[1..], in_len + bytes + 3);
indata[offset] = 0x82;
indata[offset + 1] = 0x00;
indata[offset + 2] =
if (algorithm == YKPIV_ALGO_ECCP256 || algorithm == YKPIV_ALGO_ECCP384) && decipher {
0x85
} else {
0x81
indata[offset + 2] = match (algorithm, decipher) {
(AlgorithmId::EccP256, true) | (AlgorithmId::EccP384, true) => 0x85,
_ => 0x81,
};
offset += 3;
+12 -21
View File
@@ -36,7 +36,7 @@
#[cfg(feature = "untested")]
use crate::{
apdu::{Ins, StatusWords, APDU},
key::SlotId,
key::{AlgorithmId, SlotId},
metadata,
mgm::MgmKey,
serialization::*,
@@ -363,7 +363,7 @@ impl YubiKey {
pub fn sign_data(
&mut self,
raw_in: &[u8],
algorithm: u8,
algorithm: AlgorithmId,
key: SlotId,
) -> Result<Buffer, Error> {
let txn = self.begin_transaction()?;
@@ -377,7 +377,7 @@ impl YubiKey {
pub fn decrypt_data(
&mut self,
input: &[u8],
algorithm: u8,
algorithm: AlgorithmId,
key: SlotId,
) -> Result<Buffer, Error> {
let txn = self.begin_transaction()?;
@@ -605,7 +605,7 @@ impl YubiKey {
pub fn import_private_key(
&mut self,
key: SlotId,
algorithm: u8,
algorithm: AlgorithmId,
p: Option<&[u8]>,
q: Option<&[u8]>,
dp: Option<&[u8]>,
@@ -616,15 +616,7 @@ impl YubiKey {
touch_policy: u8,
) -> Result<(), Error> {
let mut key_data = Zeroizing::new(vec![0u8; 1024]);
let templ = [0, Ins::ImportKey.code(), algorithm, key];
if key == YKPIV_KEY_CARDMGM
|| key < YKPIV_KEY_RETIRED1
|| (key > YKPIV_KEY_RETIRED20 && key < YKPIV_KEY_AUTHENTICATION)
|| (key > YKPIV_KEY_CARDAUTH && key != YKPIV_KEY_ATTESTATION)
{
return Err(Error::KeyError);
}
let templ = [0, Ins::ImportKey.code(), algorithm.into(), key.into()];
if pin_policy != YKPIV_PINPOLICY_DEFAULT
&& pin_policy != YKPIV_PINPOLICY_NEVER
@@ -643,7 +635,7 @@ impl YubiKey {
}
let (elem_len, params, param_tag) = match algorithm {
YKPIV_ALGO_RSA1024 | YKPIV_ALGO_RSA2048 => match (p, q, dp, dq, qinv) {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => match (p, q, dp, dq, qinv) {
(Some(p), Some(q), Some(dp), Some(dq), Some(qinv)) => {
if p.len() + q.len() + dp.len() + dq.len() + qinv.len() >= key_data.len() {
return Err(Error::SizeError);
@@ -651,8 +643,8 @@ impl YubiKey {
(
match algorithm {
YKPIV_ALGO_RSA1024 => 64,
YKPIV_ALGO_RSA2048 => 128,
AlgorithmId::Rsa1024 => 64,
AlgorithmId::Rsa2048 => 128,
_ => unreachable!(),
},
vec![p, q, dp, dq, qinv],
@@ -661,7 +653,7 @@ impl YubiKey {
}
_ => return Err(Error::GenericError),
},
YKPIV_ALGO_ECCP256 | YKPIV_ALGO_ECCP384 => match ec_data {
AlgorithmId::EccP256 | AlgorithmId::EccP384 => match ec_data {
Some(ec_data) => {
if ec_data.len() >= key_data.len() {
// This can never be true, but check to be explicit.
@@ -670,8 +662,8 @@ impl YubiKey {
(
match algorithm {
YKPIV_ALGO_ECCP256 => 32,
YKPIV_ALGO_ECCP384 => 48,
AlgorithmId::EccP256 => 32,
AlgorithmId::EccP384 => 48,
_ => unreachable!(),
},
vec![ec_data],
@@ -680,7 +672,6 @@ impl YubiKey {
}
_ => return Err(Error::GenericError),
},
_ => return Err(Error::AlgorithmError),
};
let mut offset = 0;
@@ -737,7 +728,7 @@ impl YubiKey {
/// <https://developers.yubico.com/PIV/Introduction/PIV_attestation.html>
#[cfg(feature = "untested")]
pub fn attest(&mut self, key: SlotId) -> Result<Buffer, Error> {
let templ = [0, Ins::Attest.code(), key, 0];
let templ = [0, Ins::Attest.code(), key.into(), 0];
let txn = self.begin_transaction()?;
let response = txn.transfer_data(&templ, &[], CB_OBJ_MAX)?;