openpgp-card: rename Algo -> AlgorithmAttributes

This commit is contained in:
Heiko Schaefer 2023-08-29 10:15:43 +02:00
parent 8e4ee08802
commit e6658713cb
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
10 changed files with 93 additions and 64 deletions

View file

@ -140,7 +140,7 @@
//! ```
use card_backend::{CardBackend, SmartcardError};
use openpgp_card::algorithm::{Algo, AlgoInfo, AlgoSimple};
use openpgp_card::algorithm::{AlgoInfo, AlgoSimple, AlgorithmAttributes};
use openpgp_card::card_do::{
ApplicationIdentifier, CardholderRelatedData, ExtendedCapabilities, ExtendedLengthInfo,
Fingerprint, HistoricalBytes, KeyGenerationTime, KeyInformation, Lang, PWStatusBytes,
@ -467,7 +467,7 @@ impl<'a> Card<Transaction<'a>> {
self.state.ard.extended_capabilities()
}
pub fn algorithm_attributes(&self, key_type: KeyType) -> Result<Algo, Error> {
pub fn algorithm_attributes(&self, key_type: KeyType) -> Result<AlgorithmAttributes, Error> {
self.state.ard.algorithm_attributes(key_type)
}
@ -617,7 +617,9 @@ impl<'a> Card<Transaction<'a>> {
self.state.ard.attestation_key_fingerprint()
}
pub fn attestation_key_algorithm_attributes(&mut self) -> Result<Option<Algo>, Error> {
pub fn attestation_key_algorithm_attributes(
&mut self,
) -> Result<Option<AlgorithmAttributes>, Error> {
self.state.ard.attestation_key_algorithm_attributes()
}

View file

@ -3,7 +3,7 @@
//! Re-exports of openpgp-card types to enable standalone-use of openpgp-card-sequoia.
pub use openpgp_card::algorithm::{Algo, AlgoSimple, Curve};
pub use openpgp_card::algorithm::{AlgoSimple, AlgorithmAttributes, Curve};
pub use openpgp_card::card_do::{Fingerprint, Sex, TouchPolicy};
pub use openpgp_card::crypto_data::{EccType, PublicKeyMaterial};
pub use openpgp_card::{Error, KeyType, StatusBytes};

View file

@ -7,7 +7,7 @@ use std::convert::TryFrom;
use std::convert::TryInto;
use anyhow::Result;
use openpgp_card::algorithm::{Algo, Curve};
use openpgp_card::algorithm::{AlgorithmAttributes, Curve};
use openpgp_card::card_do::{Fingerprint, KeyGenerationTime};
use openpgp_card::crypto_data::{CardUploadableKey, PublicKeyMaterial};
use openpgp_card::{Error, KeyType};
@ -235,7 +235,7 @@ pub fn public_key_material_to_key(
}
PublicKeyMaterial::E(ecc) => {
let algo = ecc.algo().clone(); // FIXME?
if let Algo::Ecc(algo_ecc) = algo {
if let AlgorithmAttributes::Ecc(algo_ecc) = algo {
let curve = match algo_ecc.curve() {
Curve::NistP256r1 => sequoia_openpgp::types::Curve::NistP256,
Curve::NistP384r1 => sequoia_openpgp::types::Curve::NistP384,

View file

@ -3,7 +3,7 @@
//! Data structures that define OpenPGP algorithms.
//!
//! [`Algo`] and its components model "Algorithm Attributes" as described in
//! [`AlgorithmAttributes`] and its components model "Algorithm Attributes" as described in
//! the OpenPGP card specification.
//!
//! [`AlgoSimple`] offers a shorthand for specifying an algorithm,
@ -85,31 +85,39 @@ impl AlgoSimple {
key_type: KeyType,
ard: &ApplicationRelatedData,
algo_info: Option<AlgoInfo>,
) -> Result<Algo, crate::Error> {
) -> Result<AlgorithmAttributes, crate::Error> {
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(keys::determine_ecc_attrs(
Self::RSA1k => {
AlgorithmAttributes::Rsa(keys::determine_rsa_attrs(1024, key_type, ard, algo_info)?)
}
Self::RSA2k => {
AlgorithmAttributes::Rsa(keys::determine_rsa_attrs(2048, key_type, ard, algo_info)?)
}
Self::RSA3k => {
AlgorithmAttributes::Rsa(keys::determine_rsa_attrs(3072, key_type, ard, algo_info)?)
}
Self::RSA4k => {
AlgorithmAttributes::Rsa(keys::determine_rsa_attrs(4096, key_type, ard, algo_info)?)
}
Self::NIST256 => AlgorithmAttributes::Ecc(keys::determine_ecc_attrs(
Curve::NistP256r1.oid(),
Self::ecc_type(key_type),
key_type,
algo_info,
)?),
Self::NIST384 => Algo::Ecc(keys::determine_ecc_attrs(
Self::NIST384 => AlgorithmAttributes::Ecc(keys::determine_ecc_attrs(
Curve::NistP384r1.oid(),
Self::ecc_type(key_type),
key_type,
algo_info,
)?),
Self::NIST521 => Algo::Ecc(keys::determine_ecc_attrs(
Self::NIST521 => AlgorithmAttributes::Ecc(keys::determine_ecc_attrs(
Curve::NistP521r1.oid(),
Self::ecc_type(key_type),
key_type,
algo_info,
)?),
Self::Curve25519 => Algo::Ecc(keys::determine_ecc_attrs(
Self::Curve25519 => AlgorithmAttributes::Ecc(keys::determine_ecc_attrs(
Self::curve_for_25519(key_type).oid(),
Self::ecc_type_25519(key_type),
key_type,
@ -127,7 +135,7 @@ impl AlgoSimple {
/// algorithms for each key type. This list specifies which "Algorithm
/// Attributes" can be set for key generation or key import.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct AlgoInfo(pub(crate) Vec<(KeyType, Algo)>);
pub struct AlgoInfo(pub(crate) Vec<(KeyType, AlgorithmAttributes)>);
/// 4.4.3.9 Algorithm Attributes
///
@ -139,13 +147,13 @@ pub struct AlgoInfo(pub(crate) Vec<(KeyType, Algo)>);
/// - Export of public key data from the card (e.g. after key generation)
#[derive(Debug, Clone, Eq, PartialEq)]
#[non_exhaustive]
pub enum Algo {
pub enum AlgorithmAttributes {
Rsa(RsaAttrs),
Ecc(EccAttrs),
Unknown(Vec<u8>),
}
impl fmt::Display for Algo {
impl fmt::Display for AlgorithmAttributes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Rsa(rsa) => {
@ -181,13 +189,13 @@ impl fmt::Display for Algo {
}
}
impl Algo {
impl AlgorithmAttributes {
/// Get a DO representation of the Algo, for setting algorithm
/// attributes on the card.
pub(crate) fn to_data_object(&self) -> Result<Vec<u8>, Error> {
match self {
Algo::Rsa(rsa) => Self::rsa_algo_attrs(rsa),
Algo::Ecc(ecc) => Self::ecc_algo_attrs(ecc.oid(), ecc.ecc_type()),
AlgorithmAttributes::Rsa(rsa) => Self::rsa_algo_attrs(rsa),
AlgorithmAttributes::Ecc(ecc) => Self::ecc_algo_attrs(ecc.oid(), ecc.ecc_type()),
_ => Err(Error::UnsupportedAlgo(format!("Unexpected Algo {self:?}"))),
}
}
@ -225,7 +233,7 @@ impl Algo {
}
}
/// RSA specific attributes of [`Algo`] ("Algorithm Attributes")
/// RSA specific attributes of [`AlgorithmAttributes`]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct RsaAttrs {
len_n: u16,
@ -255,7 +263,7 @@ impl RsaAttrs {
}
}
/// ECC specific attributes of [`Algo`] ("Algorithm Attributes")
/// ECC specific attributes of [`AlgorithmAttributes`]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct EccAttrs {
ecc_type: EccType,

View file

@ -9,7 +9,7 @@ use std::time::{Duration, UNIX_EPOCH};
use chrono::{DateTime, Utc};
use crate::{algorithm::Algo, tlv::Tlv, Error, KeySet, KeyType, Tags};
use crate::{algorithm::AlgorithmAttributes, tlv::Tlv, Error, KeySet, KeyType, Tags};
mod algo_attrs;
mod algo_info;
@ -105,11 +105,11 @@ impl ApplicationRelatedData {
}
/// Get algorithm attributes (for each key type)
pub fn algorithm_attributes(&self, key_type: KeyType) -> Result<Algo, Error> {
pub fn algorithm_attributes(&self, key_type: KeyType) -> Result<AlgorithmAttributes, Error> {
let aa = self.0.find(key_type.algorithm_tag());
if let Some(aa) = aa {
Algo::try_from(&aa.serialize()[..])
AlgorithmAttributes::try_from(&aa.serialize()[..])
} else {
Err(Error::NotFound(format!(
"Failed to get algorithm attributes for {key_type:?}."
@ -235,10 +235,14 @@ impl ApplicationRelatedData {
}
/// Get Attestation key algorithm attributes.
pub fn attestation_key_algorithm_attributes(&mut self) -> Result<Option<Algo>, Error> {
pub fn attestation_key_algorithm_attributes(
&mut self,
) -> Result<Option<AlgorithmAttributes>, Error> {
match self.0.find(Tags::AlgorithmAttributesAttestation) {
None => Ok(None),
Some(data) => Ok(Some(Algo::try_from(data.serialize().as_slice())?)),
Some(data) => Ok(Some(AlgorithmAttributes::try_from(
data.serialize().as_slice(),
)?)),
}
}

View file

@ -10,7 +10,7 @@ use nom::bytes::complete::tag;
use nom::combinator::map;
use nom::{branch, bytes::complete as bytes, number::complete as number};
use crate::algorithm::{Algo, Curve, EccAttrs, RsaAttrs};
use crate::algorithm::{AlgorithmAttributes, Curve, EccAttrs, RsaAttrs};
use crate::card_do::complete;
use crate::crypto_data::EccType;
@ -80,14 +80,17 @@ fn parse_oid(input: &[u8]) -> nom::IResult<&[u8], Curve> {
))(input)
}
fn parse_rsa(input: &[u8]) -> nom::IResult<&[u8], Algo> {
fn parse_rsa(input: &[u8]) -> nom::IResult<&[u8], AlgorithmAttributes> {
let (input, _) = bytes::tag([0x01])(input)?;
let (input, len_n) = number::be_u16(input)?;
let (input, len_e) = number::be_u16(input)?;
let (input, import_format) = number::u8(input)?;
Ok((input, Algo::Rsa(RsaAttrs::new(len_n, len_e, import_format))))
Ok((
input,
AlgorithmAttributes::Rsa(RsaAttrs::new(len_n, len_e, import_format)),
))
}
fn parse_import_format(input: &[u8]) -> nom::IResult<&[u8], Option<u8>> {
@ -99,7 +102,7 @@ fn default_import_format(input: &[u8]) -> nom::IResult<&[u8], Option<u8>> {
Ok((input, None))
}
fn parse_ecdh(input: &[u8]) -> nom::IResult<&[u8], Algo> {
fn parse_ecdh(input: &[u8]) -> nom::IResult<&[u8], AlgorithmAttributes> {
let (input, _) = bytes::tag([0x12])(input)?;
let (input, curve) = parse_oid(input)?;
@ -107,11 +110,11 @@ fn parse_ecdh(input: &[u8]) -> nom::IResult<&[u8], Algo> {
Ok((
input,
Algo::Ecc(EccAttrs::new(EccType::ECDH, curve, import_format)),
AlgorithmAttributes::Ecc(EccAttrs::new(EccType::ECDH, curve, import_format)),
))
}
fn parse_ecdsa(input: &[u8]) -> nom::IResult<&[u8], Algo> {
fn parse_ecdsa(input: &[u8]) -> nom::IResult<&[u8], AlgorithmAttributes> {
let (input, _) = bytes::tag([0x13])(input)?;
let (input, curve) = parse_oid(input)?;
@ -119,11 +122,11 @@ fn parse_ecdsa(input: &[u8]) -> nom::IResult<&[u8], Algo> {
Ok((
input,
Algo::Ecc(EccAttrs::new(EccType::ECDSA, curve, import_format)),
AlgorithmAttributes::Ecc(EccAttrs::new(EccType::ECDSA, curve, import_format)),
))
}
fn parse_eddsa(input: &[u8]) -> nom::IResult<&[u8], Algo> {
fn parse_eddsa(input: &[u8]) -> nom::IResult<&[u8], AlgorithmAttributes> {
let (input, _) = bytes::tag([0x16])(input)?;
let (input, curve) = parse_oid(input)?;
@ -131,15 +134,15 @@ fn parse_eddsa(input: &[u8]) -> nom::IResult<&[u8], Algo> {
Ok((
input,
Algo::Ecc(EccAttrs::new(EccType::EdDSA, curve, import_format)),
AlgorithmAttributes::Ecc(EccAttrs::new(EccType::EdDSA, curve, import_format)),
))
}
pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], Algo> {
pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], AlgorithmAttributes> {
branch::alt((parse_rsa, parse_ecdsa, parse_eddsa, parse_ecdh))(input)
}
impl TryFrom<&[u8]> for Algo {
impl TryFrom<&[u8]> for AlgorithmAttributes {
type Error = crate::Error;
fn try_from(data: &[u8]) -> Result<Self, crate::Error> {

View file

@ -10,12 +10,12 @@ use nom::branch::alt;
use nom::combinator::map;
use nom::{branch, bytes::complete as bytes, combinator, multi, sequence};
use crate::algorithm::{Algo, AlgoInfo};
use crate::algorithm::{AlgoInfo, AlgorithmAttributes};
use crate::card_do::{algo_attrs, complete};
use crate::KeyType;
impl AlgoInfo {
pub fn filter_by_keytype(&self, kt: KeyType) -> Vec<&Algo> {
pub fn filter_by_keytype(&self, kt: KeyType) -> Vec<&AlgorithmAttributes> {
self.0
.iter()
.filter(|(k, _)| *k == kt)
@ -48,11 +48,11 @@ fn key_type(input: &[u8]) -> nom::IResult<&[u8], KeyType> {
))(input)
}
fn unknown(input: &[u8]) -> nom::IResult<&[u8], Algo> {
Ok((&[], Algo::Unknown(input.to_vec())))
fn unknown(input: &[u8]) -> nom::IResult<&[u8], AlgorithmAttributes> {
Ok((&[], AlgorithmAttributes::Unknown(input.to_vec())))
}
fn parse_one(input: &[u8]) -> nom::IResult<&[u8], Algo> {
fn parse_one(input: &[u8]) -> nom::IResult<&[u8], AlgorithmAttributes> {
let (input, a) = combinator::map(
combinator::flat_map(crate::tlv::length::length, bytes::take),
|i| alt((combinator::all_consuming(algo_attrs::parse), unknown))(i),
@ -61,18 +61,18 @@ fn parse_one(input: &[u8]) -> nom::IResult<&[u8], Algo> {
Ok((input, a?.1))
}
fn parse_list(input: &[u8]) -> nom::IResult<&[u8], Vec<(KeyType, Algo)>> {
fn parse_list(input: &[u8]) -> nom::IResult<&[u8], Vec<(KeyType, AlgorithmAttributes)>> {
multi::many0(sequence::pair(key_type, parse_one))(input)
}
fn parse_tl_list(input: &[u8]) -> nom::IResult<&[u8], Vec<(KeyType, Algo)>> {
fn parse_tl_list(input: &[u8]) -> nom::IResult<&[u8], Vec<(KeyType, AlgorithmAttributes)>> {
let (input, (_, _, list)) =
sequence::tuple((bytes::tag([0xfa]), crate::tlv::length::length, parse_list))(input)?;
Ok((input, list))
}
fn parse(input: &[u8]) -> nom::IResult<&[u8], Vec<(KeyType, Algo)>> {
fn parse(input: &[u8]) -> nom::IResult<&[u8], Vec<(KeyType, AlgorithmAttributes)>> {
// Handle two variations of input format:
// a) TLV format (e.g. YubiKey 5)
// b) Plain list (e.g. Gnuk, FOSS-Store Smartcard 3.4)
@ -99,7 +99,7 @@ impl TryFrom<&[u8]> for AlgoInfo {
mod test {
use std::convert::TryFrom;
use crate::algorithm::{Algo::*, AlgoInfo, Curve::*, EccAttrs, RsaAttrs};
use crate::algorithm::{AlgoInfo, AlgorithmAttributes::*, Curve::*, EccAttrs, RsaAttrs};
use crate::crypto_data::EccType::*;
use crate::KeyType::*;

View file

@ -5,7 +5,7 @@
//! Private key data, public key data, cryptograms for decryption, hash
//! data for signing.
use crate::algorithm::Algo;
use crate::algorithm::AlgorithmAttributes;
use crate::card_do::{Fingerprint, KeyGenerationTime};
use crate::{oid, Error};
@ -169,18 +169,18 @@ impl RSAPub {
#[non_exhaustive]
pub struct EccPub {
data: Vec<u8>,
algo: Algo,
algo: AlgorithmAttributes,
}
impl EccPub {
pub fn new(data: Vec<u8>, algo: Algo) -> Self {
pub fn new(data: Vec<u8>, algo: AlgorithmAttributes) -> Self {
Self { data, algo }
}
pub fn data(&self) -> &[u8] {
&self.data
}
pub fn algo(&self) -> &Algo {
pub fn algo(&self) -> &AlgorithmAttributes {
&self.algo
}
}

View file

@ -6,7 +6,7 @@
use std::convert::TryFrom;
use std::time::{SystemTime, UNIX_EPOCH};
use crate::algorithm::{Algo, AlgoInfo, Curve, EccAttrs, RsaAttrs};
use crate::algorithm::{AlgoInfo, AlgorithmAttributes, Curve, EccAttrs, RsaAttrs};
use crate::apdu::command::Command;
use crate::apdu::commands;
use crate::card_do::{ApplicationRelatedData, Fingerprint, KeyGenerationTime};
@ -32,7 +32,7 @@ pub(crate) fn gen_key_with_metadata(
card_tx: &mut OpenPgpTransaction,
fp_from_pub: fn(&PublicKeyMaterial, KeyGenerationTime, KeyType) -> Result<Fingerprint, Error>,
key_type: KeyType,
algo: Option<&Algo>,
algo: Option<&AlgorithmAttributes>,
) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> {
// Set algo on card if it's Some
if let Some(target_algo) = algo {
@ -91,7 +91,7 @@ pub(crate) fn gen_key_with_metadata(
}
/// Transform a public key Tlv from the card into PublicKeyMaterial
fn tlv_to_pubkey(tlv: &Tlv, algo: &Algo) -> Result<PublicKeyMaterial, crate::Error> {
fn tlv_to_pubkey(tlv: &Tlv, algo: &AlgorithmAttributes) -> Result<PublicKeyMaterial, crate::Error> {
let n = tlv.find(Tags::PublicKeyDataRsaModulus);
let v = tlv.find(Tags::PublicKeyDataRsaExponent);
@ -193,7 +193,7 @@ pub(crate) fn key_import(
let key_cmd = rsa_key_import_cmd(key_type, rsa_key, &rsa_attrs)?;
(Algo::Rsa(rsa_attrs), key_cmd)
(AlgorithmAttributes::Rsa(rsa_attrs), key_cmd)
}
PrivateKeyMaterial::E(ecc_key) => {
let ecc_attrs =
@ -201,7 +201,7 @@ pub(crate) fn key_import(
let key_cmd = ecc_key_import_cmd(key_type, ecc_key, &ecc_attrs)?;
(Algo::Ecc(ecc_attrs), key_cmd)
(AlgorithmAttributes::Ecc(ecc_attrs), key_cmd)
}
};
@ -249,7 +249,7 @@ pub(crate) fn determine_rsa_attrs(
let algo = ard.algorithm_attributes(key_type)?;
// Is the algorithm on the card currently set to RSA?
if let Algo::Rsa(rsa) = algo {
if let AlgorithmAttributes::Rsa(rsa) = algo {
// If so, use the algorithm parameters from the card and
// adjust the bit length based on the user-provided key.
RsaAttrs::new(rsa_bits, rsa.len_e(), rsa.import_format())
@ -322,7 +322,13 @@ fn card_algo_rsa(algo_info: AlgoInfo, key_type: KeyType, rsa_bits: u16) -> Resul
// Get RSA algo attributes
let rsa_algos: Vec<_> = keytype_algos
.iter()
.filter_map(|a| if let Algo::Rsa(r) = a { Some(r) } else { None })
.filter_map(|a| {
if let AlgorithmAttributes::Rsa(r) = a {
Some(r)
} else {
None
}
})
.collect();
// Filter card algorithms by rsa bitlength of the key we want to upload
@ -355,7 +361,13 @@ fn check_card_algo_ecc(algo_info: AlgoInfo, key_type: KeyType, oid: &[u8]) -> Ve
// Get attributes
let ecc_algos: Vec<_> = keytype_algos
.iter()
.filter_map(|a| if let Algo::Ecc(e) = a { Some(e) } else { None })
.filter_map(|a| {
if let AlgorithmAttributes::Ecc(e) = a {
Some(e)
} else {
None
}
})
.collect();
// Find entries with this OID in the algorithm information for key_type

View file

@ -5,7 +5,7 @@ use std::convert::{TryFrom, TryInto};
use card_backend::{CardBackend, CardCaps, CardTransaction, PinType, SmartcardError};
use crate::algorithm::{Algo, AlgoInfo, AlgoSimple};
use crate::algorithm::{AlgoInfo, AlgoSimple, AlgorithmAttributes};
use crate::apdu::command::Command;
use crate::apdu::commands;
use crate::apdu::response::RawResponse;
@ -905,7 +905,7 @@ impl<'a> OpenPgpTransaction<'a> {
pub fn set_algorithm_attributes(
&mut self,
key_type: KeyType,
algo: &Algo,
algo: &AlgorithmAttributes,
) -> Result<(), Error> {
log::info!("OpenPgpTransaction: set_algorithm_attributes");
@ -1107,7 +1107,7 @@ impl<'a> OpenPgpTransaction<'a> {
KeyType,
) -> Result<Fingerprint, Error>,
key_type: KeyType,
algo: Option<&Algo>,
algo: Option<&AlgorithmAttributes>,
) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> {
keys::gen_key_with_metadata(self, fp_from_pub, key_type, algo)
}