add support for rsa3072 and rsa4096 (#598)

This commit is contained in:
Joost van Dijk
2025-02-12 22:48:29 +01:00
committed by GitHub
parent 13bdf9a585
commit 0d8096f50d
6 changed files with 100 additions and 20 deletions
+16
View File
@@ -369,6 +369,22 @@ pub mod yubikey_signer {
const ALGORITHM: AlgorithmId = AlgorithmId::Rsa2048;
}
/// RSA 3072 bits key
pub struct Rsa3072;
impl RsaLength for Rsa3072 {
const BIT_LENGTH: usize = 3072;
const ALGORITHM: AlgorithmId = AlgorithmId::Rsa3072;
}
/// RSA 4096 bits key
pub struct Rsa4096;
impl RsaLength for Rsa4096 {
const BIT_LENGTH: usize = 4096;
const ALGORITHM: AlgorithmId = AlgorithmId::Rsa4096;
}
/// RSA keys used to sign certificates
pub struct YubiRsa<N: RsaLength> {
_len: PhantomData<N>,
+31 -7
View File
@@ -6,10 +6,10 @@
//! Supported algorithms:
//!
//! - **Encryption**:
//! - RSA: `RSA1024`, `RSA2048`
//! - RSA: `RSA1024`, `RSA2048`, `RSA3072`, `RSA4096`
//! - ECC: `ECCP256`, `ECCP384` (NIST curves: P-256, P-384)
//! - **Signatures**:
//! - RSASSA-PKCS#1v1.5: `RSA1024`, `RSA2048`
//! - RSASSA-PKCS#1v1.5: `RSA1024`, `RSA2048`, `RSA3072`, `RSA4096`
//! - ECDSA: `ECCP256`, `ECCP384` (NIST curves: P-256, P-384)
// Adapted from yubico-piv-tool:
@@ -485,6 +485,12 @@ pub enum AlgorithmId {
/// 2048-bit RSA.
Rsa2048,
/// 3072-bit RSA. Requires firmware 5.7 or newer
Rsa3072,
/// 4096-bit RSA. Requires firmware 5.7 or newer
Rsa4096,
/// ECDSA with the NIST P256 curve.
EccP256,
@@ -499,6 +505,8 @@ impl TryFrom<u8> for AlgorithmId {
match value {
0x06 => Ok(AlgorithmId::Rsa1024),
0x07 => Ok(AlgorithmId::Rsa2048),
0x05 => Ok(AlgorithmId::Rsa3072),
0x16 => Ok(AlgorithmId::Rsa4096),
0x11 => Ok(AlgorithmId::EccP256),
0x14 => Ok(AlgorithmId::EccP384),
_ => Err(Error::AlgorithmError),
@@ -511,6 +519,8 @@ impl From<AlgorithmId> for u8 {
match id {
AlgorithmId::Rsa1024 => 0x06,
AlgorithmId::Rsa2048 => 0x07,
AlgorithmId::Rsa3072 => 0x05,
AlgorithmId::Rsa4096 => 0x16,
AlgorithmId::EccP256 => 0x11,
AlgorithmId::EccP384 => 0x14,
}
@@ -528,6 +538,8 @@ impl AlgorithmId {
match self {
AlgorithmId::Rsa1024 => 64,
AlgorithmId::Rsa2048 => 128,
AlgorithmId::Rsa3072 => 192,
AlgorithmId::Rsa4096 => 256,
AlgorithmId::EccP256 => 32,
AlgorithmId::EccP384 => 48,
}
@@ -536,7 +548,10 @@ impl AlgorithmId {
#[cfg(feature = "untested")]
fn get_param_tag(self) -> u8 {
match self {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => 0x01,
AlgorithmId::Rsa1024
| AlgorithmId::Rsa2048
| AlgorithmId::Rsa3072
| AlgorithmId::Rsa4096 => 0x01,
AlgorithmId::EccP256 | AlgorithmId::EccP384 => 0x6,
}
}
@@ -609,7 +624,10 @@ pub fn generate(
let setting_roca: setting::Setting;
match algorithm {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => {
AlgorithmId::Rsa1024
| AlgorithmId::Rsa2048
| AlgorithmId::Rsa3072
| AlgorithmId::Rsa4096 => {
if yubikey.version.major == 4
&& (yubikey.version.minor < 3
|| yubikey.version.minor == 3 && (yubikey.version.patch < 5))
@@ -813,7 +831,7 @@ impl RsaKeyData {
/// Imports a private RSA encryption or signing key into the YubiKey.
///
/// Errors if `algorithm` isn't `AlgorithmId::Rsa1024` or `AlgorithmId::Rsa2048`.
/// Errors if `algorithm` isn't `AlgorithmId::Rsa1024` or `AlgorithmId::Rsa2048` or `AlgorithmId::Rsa3072` or `AlgorithmId::Rsa4096`.
#[cfg(feature = "untested")]
pub fn import_rsa_key(
yubikey: &mut YubiKey,
@@ -824,7 +842,10 @@ pub fn import_rsa_key(
pin_policy: PinPolicy,
) -> Result<()> {
match algorithm {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => (),
AlgorithmId::Rsa1024
| AlgorithmId::Rsa2048
| AlgorithmId::Rsa3072
| AlgorithmId::Rsa4096 => (),
_ => return Err(Error::AlgorithmError),
}
@@ -1101,7 +1122,10 @@ fn read_public_key(
//
// 0x7f 0x49 -> Application | Constructed | 0x49
match algorithm {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => {
AlgorithmId::Rsa1024
| AlgorithmId::Rsa2048
| AlgorithmId::Rsa3072
| AlgorithmId::Rsa4096 => {
// It appears that the inner application-specific value returned by the
// YubiKey is constructed such that RSA pubkeys can be parsed in two ways:
//
+17 -8
View File
@@ -289,14 +289,23 @@ impl<'tx> Transaction<'tx> {
let templ = [0, Ins::Authenticate.code(), algorithm.into(), key.into()];
match algorithm {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => {
let key_len = if let AlgorithmId::Rsa1024 = algorithm {
128
} else {
256
};
if in_len != key_len {
AlgorithmId::Rsa1024 => {
if in_len != 128 {
return Err(Error::SizeError);
}
}
AlgorithmId::Rsa2048 => {
if in_len != 256 {
return Err(Error::SizeError);
}
}
AlgorithmId::Rsa3072 => {
if in_len != 384 {
return Err(Error::SizeError);
}
}
AlgorithmId::Rsa4096 => {
if in_len != 512 {
return Err(Error::SizeError);
}
}