Move 'Algo' and related data structures to lib.rs.

Implement the Display trait on Algo and AlgoInfo, for compact printing.
This commit is contained in:
Heiko Schaefer 2021-08-09 13:17:19 +02:00
parent 99be1fb7da
commit 608e6533a6
3 changed files with 168 additions and 92 deletions

View file

@ -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<u8>),
}
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<u8>,
}
impl EccAttrs {
pub fn new(
ecc_type: EccType,
curve: Curve,
import_format: Option<u8>,
) -> 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<Self> {
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<u8>,
}
/// RSA-specific container for public key material from an OpenPGP card.

View file

@ -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<u8>),
}
#[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<u8>,
pub import_format: Option<u8>,
}
impl EccAttrs {
pub fn new(
ecc_type: EccType,
curve: Curve,
import_format: Option<u8>,
) -> 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)

View file

@ -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() {