From c37c34e52530960ebee9220bf0343463b17f8b90 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Thu, 2 Dec 2021 13:19:27 +0100 Subject: [PATCH] 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. --- openpgp-card/src/algorithm.rs | 77 ++++++++++++++++------------------- openpgp-card/src/card_app.rs | 18 ++++++-- openpgp-card/src/keys.rs | 6 +-- openpgp-card/src/lib.rs | 2 +- 4 files changed, 53 insertions(+), 50 deletions(-) diff --git a/openpgp-card/src/algorithm.rs b/openpgp-card/src/algorithm.rs index c50ef7c..490efda 100644 --- a/openpgp-card/src/algorithm.rs +++ b/openpgp-card/src/algorithm.rs @@ -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, + ) -> Result { + 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) } } diff --git a/openpgp-card/src/card_app.rs b/openpgp-card/src/card_app.rs index 3459bac..48c6076 100644 --- a/openpgp-card/src/card_app.rs +++ b/openpgp-card/src/card_app.rs @@ -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, 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)) } diff --git a/openpgp-card/src/keys.rs b/openpgp-card/src/keys.rs index d823f1b..88a8f6a 100644 --- a/openpgp-card/src/keys.rs +++ b/openpgp-card/src/keys.rs @@ -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(), )); } diff --git a/openpgp-card/src/lib.rs b/openpgp-card/src/lib.rs index 425f2ff..c2da8ed 100644 --- a/openpgp-card/src/lib.rs +++ b/openpgp-card/src/lib.rs @@ -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;