diff --git a/openpgp-card/src/lib.rs b/openpgp-card/src/lib.rs index a46a23f..ca5d7a9 100644 --- a/openpgp-card/src/lib.rs +++ b/openpgp-card/src/lib.rs @@ -2,21 +2,20 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use anyhow::{anyhow, Result}; +use std::fmt; +use std::ops::{Deref, DerefMut}; -use apdu::response::Response; +use apdu::{response::Response, PcscClient}; +use card_app::CardApp; +use errors::{OpenpgpCardError, SmartcardError}; use parse::{ - algo_attrs::Algo, algo_info::AlgoInfo, application_id::ApplicationId, + algo_info::AlgoInfo, application_id::ApplicationId, cardholder::CardHolder, extended_cap::ExtendedCap, extended_cap::Features, extended_length_info::ExtendedLengthInfo, fingerprint, historical::Historical, pw_status::PWStatus, KeySet, }; use tlv::Tlv; -use crate::apdu::PcscClient; -use crate::card_app::CardApp; -use crate::errors::{OpenpgpCardError, SmartcardError}; -use std::ops::{Deref, DerefMut}; - pub mod apdu; mod card; pub mod card_app; @@ -66,6 +65,139 @@ impl CardCaps { } } +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Algo { + Rsa(RsaAttrs), + Ecc(EccAttrs), + Unknown(Vec), +} + +impl fmt::Display for Algo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Rsa(rsa) => { + write!(f, "RSA {}, {} ", rsa.len_n, rsa.len_e) + } + Self::Ecc(ecc) => { + write!(f, "{:?} ({:?})", ecc.curve, ecc.ecc_type) + } + Self::Unknown(u) => { + write!(f, "Unknown: {:?}", u) + } + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct RsaAttrs { + pub len_n: u16, + pub len_e: u16, + pub import_format: u8, +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct EccAttrs { + pub ecc_type: EccType, + pub curve: Curve, + pub import_format: Option, +} + +impl EccAttrs { + pub fn new( + ecc_type: EccType, + curve: Curve, + import_format: Option, + ) -> Self { + Self { + ecc_type, + curve, + import_format, + } + } + + pub fn oid(&self) -> &[u8] { + self.curve.oid() + } +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum Curve { + NistP256r1, + NistP384r1, + NistP521r1, + BrainpoolP256r1, + BrainpoolP384r1, + BrainpoolP512r1, + Secp256k1, + Ed25519, + Cv25519, + Ed448, + X448, +} + +impl Curve { + pub fn oid(&self) -> &[u8] { + use Curve::*; + match self { + NistP256r1 => &[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], + NistP384r1 => &[0x2B, 0x81, 0x04, 0x00, 0x22], + NistP521r1 => &[0x2B, 0x81, 0x04, 0x00, 0x23], + BrainpoolP256r1 => { + &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07] + } + BrainpoolP384r1 => { + &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0b] + } + BrainpoolP512r1 => { + &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0d] + } + Secp256k1 => &[0x2B, 0x81, 0x04, 0x00, 0x0A], + Ed25519 => &[0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], + Cv25519 => { + &[0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01] + } + Ed448 => &[0x2b, 0x65, 0x71], + X448 => &[0x2b, 0x65, 0x6f], + } + } + + // FIXME impl trait? + pub fn from(oid: &[u8]) -> Option { + use Curve::*; + match oid { + [0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07] => { + Some(NistP256r1) + } + [0x2B, 0x81, 0x04, 0x00, 0x22] => Some(NistP384r1), + [0x2B, 0x81, 0x04, 0x00, 0x23] => Some(NistP521r1), + + [0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07] => { + Some(BrainpoolP256r1) + } + [0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0b] => { + Some(BrainpoolP384r1) + } + [0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0d] => { + Some(BrainpoolP512r1) + } + + [0x2B, 0x81, 0x04, 0x00, 0x0A] => Some(Secp256k1), + + [0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01] => { + Some(Ed25519) + } + [0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01] => { + Some(Cv25519) + } + + [0x2b, 0x65, 0x71] => Some(Ed448), + [0x2b, 0x65, 0x6f] => Some(X448), + + _ => None, + } + } +} + /// An OpenPGP key generation Time #[derive(Clone, Eq, PartialEq, Debug)] pub struct KeyGeneration(u32); @@ -133,6 +265,14 @@ pub trait CardUploadableKey { pub enum PublicKeyMaterial { R(RSAPub), E(EccPub), + T(Tffon), // 25519 +} + +/// ed25519/cv25519 +#[derive(Debug)] +pub struct Tffon { + /// Public key + pub pk: Vec, } /// RSA-specific container for public key material from an OpenPGP card. diff --git a/openpgp-card/src/parse/algo_attrs.rs b/openpgp-card/src/parse/algo_attrs.rs index df56226..0b8a3e1 100644 --- a/openpgp-card/src/parse/algo_attrs.rs +++ b/openpgp-card/src/parse/algo_attrs.rs @@ -9,84 +9,7 @@ use nom::bytes::complete::tag; use nom::combinator::map; use nom::{branch, bytes::complete as bytes, number::complete as number}; -use crate::{parse, EccType}; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Algo { - Rsa(RsaAttrs), - Ecc(EccAttrs), - Unknown(Vec), -} - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct RsaAttrs { - pub len_n: u16, - pub len_e: u16, - pub import_format: u8, -} - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct EccAttrs { - pub ecc_type: EccType, - pub oid: Vec, - pub import_format: Option, -} - -impl EccAttrs { - pub fn new( - ecc_type: EccType, - curve: Curve, - import_format: Option, - ) -> Self { - Self { - ecc_type, - oid: curve.oid().to_vec(), - import_format, - } - } -} - -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub enum Curve { - NistP256r1, - NistP384r1, - NistP521r1, - BrainpoolP256r1, - BrainpoolP384r1, - BrainpoolP512r1, - Secp256k1, - Ed25519, - Cv25519, - Ed448, - X448, -} - -impl Curve { - pub fn oid(&self) -> &[u8] { - use Curve::*; - match self { - NistP256r1 => &[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], - NistP384r1 => &[0x2B, 0x81, 0x04, 0x00, 0x22], - NistP521r1 => &[0x2B, 0x81, 0x04, 0x00, 0x23], - BrainpoolP256r1 => { - &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07] - } - BrainpoolP384r1 => { - &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0b] - } - BrainpoolP512r1 => { - &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0d] - } - Secp256k1 => &[0x2B, 0x81, 0x04, 0x00, 0x0A], - Ed25519 => &[0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], - Cv25519 => { - &[0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01] - } - Ed448 => &[0x2b, 0x65, 0x71], - X448 => &[0x2b, 0x65, 0x6f], - } - } -} +use crate::{parse, Algo, Curve, EccAttrs, EccType, RsaAttrs}; fn parse_oid_cv25519(input: &[u8]) -> nom::IResult<&[u8], Curve> { map(tag(Curve::Cv25519.oid()), |_| Curve::Cv25519)(input) diff --git a/openpgp-card/src/parse/algo_info.rs b/openpgp-card/src/parse/algo_info.rs index 652ae81..6ad9218 100644 --- a/openpgp-card/src/parse/algo_info.rs +++ b/openpgp-card/src/parse/algo_info.rs @@ -7,10 +7,10 @@ use anyhow::Result; use nom::branch::alt; use nom::combinator::map; use nom::{branch, bytes::complete as bytes, combinator, multi, sequence}; +use std::fmt; use crate::parse::algo_attrs; -use crate::parse::algo_attrs::Algo; -use crate::KeyType; +use crate::{Algo, KeyType}; #[derive(Debug, Clone, Eq, PartialEq)] pub struct AlgoInfo(Vec<(KeyType, Algo)>); @@ -25,6 +25,21 @@ impl AlgoInfo { } } +impl fmt::Display for AlgoInfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (kt, a) in &self.0 { + let kt = match kt { + KeyType::Signing => "SIG", + KeyType::Decryption => "DEC", + KeyType::Authentication => "AUT", + KeyType::Attestation => "ATT", + }; + writeln!(f, "{}: {} ", kt, a)?; + } + Ok(()) + } +} + fn key_type(input: &[u8]) -> nom::IResult<&[u8], KeyType> { alt(( map(bytes::tag([0xc1]), |_| KeyType::Signing), @@ -88,12 +103,10 @@ impl TryFrom<&[u8]> for AlgoInfo { mod test { use std::convert::TryFrom; - use crate::parse::algo_attrs::Algo::*; - use crate::parse::algo_attrs::Curve::*; - use crate::parse::algo_attrs::*; use crate::parse::algo_info::AlgoInfo; - use crate::EccType::*; - use crate::KeyType::*; + use crate::{ + Algo::*, Curve::*, EccAttrs, EccType::*, KeyType::*, RsaAttrs, + }; #[test] fn test_gnuk() {