Remove bitsize of e parameter for RSA from SimpleAlgo.

Use determine_rsa_attrs() to get a concrete Algo for a specific card from an AlgoSimple.
This commit is contained in:
Heiko Schaefer 2021-12-02 13:19:27 +01:00
parent 10bdb32c45
commit c37c34e525
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
4 changed files with 53 additions and 50 deletions

View file

@ -9,27 +9,22 @@
//! [`AlgoSimple`] offers a shorthand for specifying an algorithm,
//! specifically for key generation on the card.
use crate::card_do::ApplicationRelatedData;
use crate::crypto_data::EccType;
use crate::{Error, KeyType};
use crate::{keys, Error, KeyType};
use anyhow::anyhow;
use anyhow::{anyhow, Result};
use std::convert::TryFrom;
use std::fmt;
/// A shorthand way to specify algorithms (e.g. for key generation).
///
/// RSA variants require "number of bits in 'e'" as parameter.
///
/// There are (at least) two common supported values for e:
/// e=17 [YK4, YK5]
/// e=32 [YK5, Floss3.4, Gnuk1.2]
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub enum AlgoSimple {
RSA1k(u16),
RSA2k(u16),
RSA3k(u16),
RSA4k(u16),
RSA1k,
RSA2k,
RSA3k,
RSA4k,
NIST256,
NIST384,
NIST521,
@ -43,14 +38,10 @@ impl TryFrom<&str> for AlgoSimple {
use AlgoSimple::*;
Ok(match algo {
"RSA1k/17" => RSA1k(17),
"RSA1k/32" => RSA1k(32),
"RSA2k/17" => RSA2k(17),
"RSA2k/32" => RSA2k(32),
"RSA3k/17" => RSA3k(17),
"RSA3k/32" => RSA3k(32),
"RSA4k/17" => RSA4k(17),
"RSA4k/32" => RSA4k(32),
"RSA1k" => RSA1k,
"RSA2k" => RSA2k,
"RSA3k" => RSA3k,
"RSA4k" => RSA4k,
"NIST256" => NIST256,
"NIST384" => NIST384,
"NIST521" => NIST521,
@ -91,28 +82,26 @@ impl AlgoSimple {
}
}
pub(crate) fn as_algo(&self, key_type: KeyType) -> Algo {
match self {
Self::RSA1k(e) => Algo::Rsa(RsaAttrs {
len_n: 1024,
len_e: *e,
import_format: 0,
}),
Self::RSA2k(e) => Algo::Rsa(RsaAttrs {
len_n: 2048,
len_e: *e,
import_format: 0,
}),
Self::RSA3k(e) => Algo::Rsa(RsaAttrs {
len_n: 3072,
len_e: *e,
import_format: 0,
}),
Self::RSA4k(e) => Algo::Rsa(RsaAttrs {
len_n: 4096,
len_e: *e,
import_format: 0,
}),
pub(crate) fn determine_algo(
&self,
key_type: KeyType,
ard: &ApplicationRelatedData,
algo_info: Option<AlgoInfo>,
) -> Result<Algo> {
let algo = match self {
Self::RSA1k => Algo::Rsa(keys::determine_rsa_attrs(
1024, key_type, ard, algo_info,
)?),
Self::RSA2k => Algo::Rsa(keys::determine_rsa_attrs(
2048, key_type, ard, algo_info,
)?),
Self::RSA3k => Algo::Rsa(keys::determine_rsa_attrs(
3072, key_type, ard, algo_info,
)?),
Self::RSA4k => Algo::Rsa(keys::determine_rsa_attrs(
4096, key_type, ard, algo_info,
)?),
Self::NIST256 => Algo::Ecc(EccAttrs {
curve: Curve::NistP256r1,
ecc_type: Self::ecc_type(key_type),
@ -133,7 +122,9 @@ impl AlgoSimple {
ecc_type: Self::ecc_type_25519(key_type),
import_format: None,
}),
}
};
Ok(algo)
}
}

View file

@ -805,6 +805,10 @@ impl CardApp {
///
/// If the `algo` parameter is Some, then this algorithm will be set on
/// the card for "key_type".
///
/// Note: `algo` needs to precisely specify the RSA bitsize of e (if
/// applicable), and import format, with values that the current card
/// supports.
pub fn generate_key(
&mut self,
fp_from_pub: fn(
@ -821,8 +825,12 @@ impl CardApp {
/// Generate a key on the card.
/// (7.2.14 GENERATE ASYMMETRIC KEY PAIR)
///
/// This is a convenience wrapper around generate_key() which allows
/// This is a wrapper around generate_key() which allows
/// using the simplified `AlgoSimple` algorithm selector enum.
///
/// Note: AlgoSimple doesn't specify card specific details (such as
/// bitsize of e for RSA, and import format). This function determines
/// these values based on information from the card.
pub fn generate_key_simple(
&mut self,
fp_from_pub: fn(
@ -831,9 +839,13 @@ impl CardApp {
KeyType,
) -> Result<Fingerprint, Error>,
key_type: KeyType,
algo: AlgoSimple,
simple: AlgoSimple,
) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> {
let algo = algo.as_algo(key_type);
let ard = self.application_related_data()?;
let algo_info = self.algorithm_information()?;
let algo = simple.determine_algo(key_type, &ard, algo_info)?;
self.generate_key(fp_from_pub, key_type, Some(&algo))
}

View file

@ -64,7 +64,7 @@ pub(crate) fn gen_key_with_metadata(
}
}
// get new state of algo
// get current (possibly updated) state of algo
let ard = card_app.application_related_data()?; // no caching, here!
let cur_algo = ard.algorithm_attributes(key_type)?;
@ -230,7 +230,7 @@ pub(crate) fn key_import(
/// If available, via lookup in `algo_list`, otherwise the current
/// algorithm attributes are checked. If neither method yields a
/// result, we 'guess' the RsaAttrs setting.
fn determine_rsa_attrs(
pub(crate) fn determine_rsa_attrs(
rsa_bits: u16,
key_type: KeyType,
ard: &ApplicationRelatedData,
@ -299,7 +299,7 @@ fn determine_ecc_attrs(
if !algos.is_empty() {
return Ok(EccAttrs::new(
ecc_key.ecc_type(),
Curve::try_from(ecc_key.oid())?,
Curve::try_from(oid)?,
algos[0].import_format(),
));
}

View file

@ -31,7 +31,7 @@ mod card_app;
pub mod card_do;
pub mod crypto_data;
mod errors;
mod keys;
pub(crate) mod keys;
mod tlv;
pub use crate::apdu::response::Response;