Convert AlgorithmId into an enum
3DES also has an algorithm ID, but it is completely disjoint from the key algorithms, and can be handled separately later.
This commit is contained in:
@@ -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";
|
||||
|
||||
|
||||
+48
-17
@@ -45,7 +45,7 @@ use crate::{
|
||||
serialization::*,
|
||||
settings,
|
||||
yubikey::YubiKey,
|
||||
AlgorithmId, Buffer, ObjectId,
|
||||
Buffer, ObjectId,
|
||||
};
|
||||
use log::{debug, error, warn};
|
||||
use std::convert::TryFrom;
|
||||
@@ -273,6 +273,44 @@ pub const SLOTS: [SlotId; 24] = [
|
||||
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 {
|
||||
@@ -377,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);
|
||||
|
||||
@@ -414,13 +454,8 @@ 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()?;
|
||||
@@ -433,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 {
|
||||
@@ -487,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;
|
||||
|
||||
@@ -515,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
|
||||
@@ -542,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+10
-13
@@ -9,7 +9,7 @@ use crate::{
|
||||
use crate::{
|
||||
apdu::{Response, StatusWords},
|
||||
consts::*,
|
||||
key::SlotId,
|
||||
key::{AlgorithmId, SlotId},
|
||||
mgm::MgmKey,
|
||||
serialization::*,
|
||||
Buffer, ObjectId,
|
||||
@@ -267,18 +267,18 @@ impl<'tx> Transaction<'tx> {
|
||||
pub(crate) fn authenticated_command(
|
||||
&self,
|
||||
sign_in: &[u8],
|
||||
algorithm: 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.into()];
|
||||
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
|
||||
@@ -288,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
|
||||
@@ -300,7 +300,6 @@ impl<'tx> Transaction<'tx> {
|
||||
return Err(Error::SizeError);
|
||||
}
|
||||
}
|
||||
_ => return Err(Error::AlgorithmError),
|
||||
}
|
||||
|
||||
let bytes = if in_len < 0x80 {
|
||||
@@ -315,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;
|
||||
|
||||
+11
-12
@@ -36,7 +36,7 @@
|
||||
#[cfg(feature = "untested")]
|
||||
use crate::{
|
||||
apdu::{Ins, StatusWords, APDU},
|
||||
key::SlotId,
|
||||
key::{AlgorithmId, SlotId},
|
||||
metadata,
|
||||
mgm::MgmKey,
|
||||
serialization::*,
|
||||
@@ -356,7 +356,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()?;
|
||||
@@ -370,7 +370,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()?;
|
||||
@@ -598,7 +598,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]>,
|
||||
@@ -609,7 +609,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.into()];
|
||||
let templ = [0, Ins::ImportKey.code(), algorithm.into(), key.into()];
|
||||
|
||||
// Only slot we want to exclude is CardManagement, which isn't in the enum.
|
||||
// TODO: Decide whether to add it or not.
|
||||
@@ -634,7 +634,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);
|
||||
@@ -642,8 +642,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],
|
||||
@@ -652,7 +652,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.
|
||||
@@ -661,8 +661,8 @@ impl YubiKey {
|
||||
|
||||
(
|
||||
match algorithm {
|
||||
YKPIV_ALGO_ECCP256 => 32,
|
||||
YKPIV_ALGO_ECCP384 => 48,
|
||||
AlgorithmId::EccP256 => 32,
|
||||
AlgorithmId::EccP384 => 48,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
vec![ec_data],
|
||||
@@ -671,7 +671,6 @@ impl YubiKey {
|
||||
}
|
||||
_ => return Err(Error::GenericError),
|
||||
},
|
||||
_ => return Err(Error::AlgorithmError),
|
||||
};
|
||||
|
||||
let mut offset = 0;
|
||||
|
||||
Reference in New Issue
Block a user