Convert PIN and touch policies into enums
This commit is contained in:
@@ -158,15 +158,3 @@ pub const YKPIV_OBJ_MSROOTS2: u32 = 0x005f_ff12;
|
||||
pub const YKPIV_OBJ_MSROOTS3: u32 = 0x005f_ff13;
|
||||
pub const YKPIV_OBJ_MSROOTS4: u32 = 0x005f_ff14;
|
||||
pub const YKPIV_OBJ_MSROOTS5: u32 = 0x005f_ff15;
|
||||
|
||||
pub const YKPIV_PINPOLICY_TAG: u8 = 0xaa;
|
||||
pub const YKPIV_PINPOLICY_DEFAULT: u8 = 0;
|
||||
pub const YKPIV_PINPOLICY_NEVER: u8 = 1;
|
||||
pub const YKPIV_PINPOLICY_ONCE: u8 = 2;
|
||||
pub const YKPIV_PINPOLICY_ALWAYS: u8 = 3;
|
||||
|
||||
pub const YKPIV_TOUCHPOLICY_TAG: u8 = 0xab;
|
||||
pub const YKPIV_TOUCHPOLICY_DEFAULT: u8 = 0;
|
||||
pub const YKPIV_TOUCHPOLICY_NEVER: u8 = 1;
|
||||
pub const YKPIV_TOUCHPOLICY_ALWAYS: u8 = 2;
|
||||
pub const YKPIV_TOUCHPOLICY_CACHED: u8 = 3;
|
||||
|
||||
+15
-17
@@ -42,6 +42,7 @@ use crate::{
|
||||
certificate::{self, Certificate},
|
||||
consts::*,
|
||||
error::Error,
|
||||
policy::{PinPolicy, TouchPolicy},
|
||||
serialization::*,
|
||||
settings,
|
||||
yubikey::YubiKey,
|
||||
@@ -408,8 +409,8 @@ pub fn generate(
|
||||
yubikey: &mut YubiKey,
|
||||
slot: SlotId,
|
||||
algorithm: AlgorithmId,
|
||||
pin_policy: u8,
|
||||
touch_policy: u8,
|
||||
pin_policy: PinPolicy,
|
||||
touch_policy: TouchPolicy,
|
||||
) -> Result<GeneratedKey, Error> {
|
||||
let mut in_data = [0u8; 11];
|
||||
let mut templ = [0, Ins::GenerateAsymmetric.code(), 0, 0];
|
||||
@@ -476,16 +477,13 @@ pub fn generate(
|
||||
return Err(Error::AlgorithmError);
|
||||
}
|
||||
|
||||
if pin_policy != YKPIV_PINPOLICY_DEFAULT {
|
||||
in_data[1] += 3;
|
||||
in_data[offset..(offset + 3)].copy_from_slice(&[YKPIV_PINPOLICY_TAG, 1, pin_policy]);
|
||||
offset += 3;
|
||||
}
|
||||
let pin_len = pin_policy.write(&mut in_data[offset..]);
|
||||
in_data[1] += pin_len as u8;
|
||||
offset += pin_len;
|
||||
|
||||
if touch_policy != YKPIV_TOUCHPOLICY_DEFAULT {
|
||||
in_data[1] += 3;
|
||||
in_data[offset..(offset + 3)].copy_from_slice(&[YKPIV_TOUCHPOLICY_TAG, 1, touch_policy]);
|
||||
}
|
||||
let touch_len = touch_policy.write(&mut in_data[offset..]);
|
||||
in_data[1] += touch_len as u8;
|
||||
offset += touch_len;
|
||||
|
||||
let response = txn.transfer_data(&templ, &in_data[..offset], 1024)?;
|
||||
|
||||
@@ -498,12 +496,12 @@ pub fn generate(
|
||||
return Err(Error::KeyError);
|
||||
}
|
||||
StatusWords::IncorrectParamError => {
|
||||
if pin_policy != YKPIV_PINPOLICY_DEFAULT {
|
||||
error!("{} (pin policy not supported?)", err_msg);
|
||||
} else if touch_policy != YKPIV_TOUCHPOLICY_DEFAULT {
|
||||
error!("{} (touch policy not supported?)", err_msg);
|
||||
} else {
|
||||
error!("{} (algorithm not supported?)", err_msg);
|
||||
match pin_policy {
|
||||
PinPolicy::Default => match touch_policy {
|
||||
TouchPolicy::Default => error!("{} (algorithm not supported?)", err_msg),
|
||||
_ => error!("{} (touch policy not supported?)", err_msg),
|
||||
},
|
||||
_ => error!("{} (pin policy not supported?)", err_msg),
|
||||
}
|
||||
|
||||
return Err(Error::AlgorithmError);
|
||||
|
||||
@@ -156,6 +156,8 @@ mod metadata;
|
||||
pub mod mgm;
|
||||
#[cfg(feature = "untested")]
|
||||
pub mod msroots;
|
||||
#[cfg(feature = "untested")]
|
||||
pub mod policy;
|
||||
pub mod readers;
|
||||
#[cfg(feature = "untested")]
|
||||
mod serialization;
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
//! Enums representing key policies.
|
||||
|
||||
/// 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
|
||||
/// changed later.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum PinPolicy {
|
||||
/// Use the default PIN policy for the slot. See the slot's documentation for details.
|
||||
Default,
|
||||
|
||||
/// The end user PIN is **NOT** required to perform private key operations.
|
||||
Never,
|
||||
|
||||
/// The end user PIN is required to perform any private key operations. Once the
|
||||
/// correct PIN has been provided, multiple private key operations may be performed
|
||||
/// without additional cardholder consent.
|
||||
Once,
|
||||
|
||||
/// The end user PIN is required to perform any private key operations. The PIN must
|
||||
/// be submitted immediately before each operation to ensure cardholder participation.
|
||||
Always,
|
||||
}
|
||||
|
||||
impl From<PinPolicy> for u8 {
|
||||
fn from(policy: PinPolicy) -> u8 {
|
||||
match policy {
|
||||
PinPolicy::Default => 0,
|
||||
PinPolicy::Never => 1,
|
||||
PinPolicy::Once => 2,
|
||||
PinPolicy::Always => 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PinPolicy {
|
||||
/// Writes the `PinPolicy` in the format the YubiKey expects during key generation or
|
||||
/// importation.
|
||||
pub(crate) fn write(self, buf: &mut [u8]) -> usize {
|
||||
match self {
|
||||
PinPolicy::Default => 0,
|
||||
_ => {
|
||||
buf[0] = 0xaa;
|
||||
buf[1] = 0x01;
|
||||
buf[2] = self.into();
|
||||
3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies under what conditions a physical touch on the metal contact is required, in
|
||||
/// addition to the [`PinPolicy`]. This policy must be set upon key generation or
|
||||
/// importation, and cannot be changed later.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum TouchPolicy {
|
||||
/// Use the default touch policy for the slot.
|
||||
Default,
|
||||
|
||||
/// A physical touch is **NOT** required to perform private key operations.
|
||||
Never,
|
||||
|
||||
/// A physical touch is required to perform any private key operations. The metal
|
||||
/// contact must be touched during each operation to ensure cardholder participation.
|
||||
Always,
|
||||
|
||||
/// A physical touch is required to perform any private key operations. Each touch
|
||||
/// is cached for 15 seconds, during which time multiple private key operations may be
|
||||
/// performed without additional cardholder interaction. After 15 seconds the cached
|
||||
/// touch is cleared, and further operations require another physical touch.
|
||||
Cached,
|
||||
}
|
||||
|
||||
impl From<TouchPolicy> for u8 {
|
||||
fn from(policy: TouchPolicy) -> u8 {
|
||||
match policy {
|
||||
TouchPolicy::Default => 0,
|
||||
TouchPolicy::Never => 1,
|
||||
TouchPolicy::Always => 2,
|
||||
TouchPolicy::Cached => 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TouchPolicy {
|
||||
/// Writes the `TouchPolicy` in the format the YubiKey expects during key generation
|
||||
/// or importation.
|
||||
pub(crate) fn write(self, buf: &mut [u8]) -> usize {
|
||||
match self {
|
||||
TouchPolicy::Default => 0,
|
||||
_ => {
|
||||
buf[0] = 0xab;
|
||||
buf[1] = 0x01;
|
||||
buf[2] = self.into();
|
||||
3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-31
@@ -39,6 +39,7 @@ use crate::{
|
||||
key::{AlgorithmId, SlotId},
|
||||
metadata,
|
||||
mgm::MgmKey,
|
||||
policy::{PinPolicy, TouchPolicy},
|
||||
serialization::*,
|
||||
Buffer, ObjectId,
|
||||
};
|
||||
@@ -552,28 +553,12 @@ impl YubiKey {
|
||||
dq: Option<&[u8]>,
|
||||
qinv: Option<&[u8]>,
|
||||
ec_data: Option<&[u8]>,
|
||||
pin_policy: u8,
|
||||
touch_policy: u8,
|
||||
pin_policy: PinPolicy,
|
||||
touch_policy: TouchPolicy,
|
||||
) -> Result<(), Error> {
|
||||
let mut key_data = Zeroizing::new(vec![0u8; 1024]);
|
||||
let templ = [0, Ins::ImportKey.code(), algorithm.into(), key.into()];
|
||||
|
||||
if pin_policy != YKPIV_PINPOLICY_DEFAULT
|
||||
&& pin_policy != YKPIV_PINPOLICY_NEVER
|
||||
&& pin_policy != YKPIV_PINPOLICY_ONCE
|
||||
&& pin_policy != YKPIV_PINPOLICY_ALWAYS
|
||||
{
|
||||
return Err(Error::GenericError);
|
||||
}
|
||||
|
||||
if touch_policy != YKPIV_TOUCHPOLICY_DEFAULT
|
||||
&& touch_policy != YKPIV_TOUCHPOLICY_NEVER
|
||||
&& touch_policy != YKPIV_TOUCHPOLICY_ALWAYS
|
||||
&& touch_policy != YKPIV_TOUCHPOLICY_CACHED
|
||||
{
|
||||
return Err(Error::GenericError);
|
||||
}
|
||||
|
||||
let (elem_len, params, param_tag) = match algorithm {
|
||||
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => match (p, q, dp, dq, qinv) {
|
||||
(Some(p), Some(q), Some(dp), Some(dq), Some(qinv)) => {
|
||||
@@ -637,19 +622,8 @@ impl YubiKey {
|
||||
offset += param.len();
|
||||
}
|
||||
|
||||
if pin_policy != YKPIV_PINPOLICY_DEFAULT {
|
||||
key_data[offset] = YKPIV_PINPOLICY_TAG;
|
||||
key_data[offset + 1] = 0x01;
|
||||
key_data[offset + 2] = pin_policy;
|
||||
offset += 3;
|
||||
}
|
||||
|
||||
if touch_policy != YKPIV_TOUCHPOLICY_DEFAULT {
|
||||
key_data[offset] = YKPIV_TOUCHPOLICY_TAG;
|
||||
key_data[offset + 1] = 0x01;
|
||||
key_data[offset + 2] = touch_policy;
|
||||
offset += 3;
|
||||
}
|
||||
offset += pin_policy.write(&mut key_data[offset..]);
|
||||
offset += touch_policy.write(&mut key_data[offset..]);
|
||||
|
||||
let txn = self.begin_transaction()?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user