diff --git a/openpgp-card-sequoia/src/decryptor.rs b/openpgp-card-sequoia/src/decryptor.rs index 0cc8e90..2f7838f 100644 --- a/openpgp-card-sequoia/src/decryptor.rs +++ b/openpgp-card-sequoia/src/decryptor.rs @@ -15,8 +15,9 @@ use openpgp::types::{Curve, SymmetricAlgorithm}; use openpgp::Cert; use sequoia_openpgp as openpgp; +use openpgp_card::crypto_data::Cryptogram; use openpgp_card::errors::OpenpgpCardError; -use openpgp_card::{CardApp, DecryptMe}; +use openpgp_card::CardApp; use crate::PublicKey; @@ -92,7 +93,7 @@ impl<'a> crypto::Decryptor for CardDecryptor<'a> { ) -> openpgp::Result { match (ciphertext, self.public.mpis()) { (mpi::Ciphertext::RSA { c: ct }, mpi::PublicKey::RSA { .. }) => { - let dm = DecryptMe::RSA(ct.value()); + let dm = Cryptogram::RSA(ct.value()); let dec = self.ca.decrypt(dm)?; let sk = openpgp::crypto::SessionKey::from(&dec[..]); @@ -104,10 +105,10 @@ impl<'a> crypto::Decryptor for CardDecryptor<'a> { ) => { let dm = if curve == &Curve::Cv25519 { // Ephemeral key without header byte 0x40 - DecryptMe::ECDH(&e.value()[1..]) + Cryptogram::ECDH(&e.value()[1..]) } else { // NIST curves: ephemeral key with header byte - DecryptMe::ECDH(e.value()) + Cryptogram::ECDH(e.value()) }; // Decryption operation on the card diff --git a/openpgp-card-sequoia/src/lib.rs b/openpgp-card-sequoia/src/lib.rs index 20d823d..544018d 100644 --- a/openpgp-card-sequoia/src/lib.rs +++ b/openpgp-card-sequoia/src/lib.rs @@ -37,10 +37,12 @@ use openpgp_card::card_data::{ ExtendedLengthInfo, Features, Fingerprint, Historical, KeySet, PWStatus, Sex, }; +use openpgp_card::crypto_data::{ + CardUploadableKey, Cryptogram, EccKey, EccType, Hash, PrivateKeyMaterial, + PublicKeyMaterial, RSAKey, +}; use openpgp_card::{ - errors::OpenpgpCardError, CardApp, CardClientBox, CardUploadableKey, - DecryptMe, EccKey, EccType, Hash, KeyType, PrivateKeyMaterial, - PublicKeyMaterial, RSAKey, Response, + errors::OpenpgpCardError, CardApp, CardClientBox, KeyType, Response, }; use crate::signer::CardSigner; @@ -775,7 +777,7 @@ impl CardUser { /// Decrypt the ciphertext in `dm`, on the card. pub fn decrypt( &mut self, - dm: DecryptMe, + dm: Cryptogram, ) -> Result, OpenpgpCardError> { self.card_app.decrypt(dm) } diff --git a/openpgp-card-sequoia/src/signer.rs b/openpgp-card-sequoia/src/signer.rs index 1967aad..6661e0b 100644 --- a/openpgp-card-sequoia/src/signer.rs +++ b/openpgp-card-sequoia/src/signer.rs @@ -10,8 +10,9 @@ use openpgp::policy::Policy; use openpgp::types::{Curve, PublicKeyAlgorithm}; use sequoia_openpgp as openpgp; +use openpgp_card::crypto_data::Hash; use openpgp_card::errors::OpenpgpCardError; -use openpgp_card::{CardApp, Hash}; +use openpgp_card::CardApp; use crate::PublicKey; diff --git a/openpgp-card/src/algorithm.rs b/openpgp-card/src/algorithm.rs index 7068e36..fef58b9 100644 --- a/openpgp-card/src/algorithm.rs +++ b/openpgp-card/src/algorithm.rs @@ -9,7 +9,9 @@ //! [`AlgoSimple`] offers a shorthand for specifying an algorithm, //! specifically for key generation on the card. -use crate::{EccType, KeyType}; +use crate::crypto_data::EccType; +use crate::KeyType; + use anyhow::anyhow; use std::convert::TryFrom; use std::fmt; @@ -119,7 +121,7 @@ impl AlgoSimple { } } -/// "Algorithm Information" +/// Algorithm Information /// /// Modern cards provide a list of supported algorithms for each key type. /// The list specifies which "Algorithm Attributes" can be set for key @@ -129,7 +131,7 @@ impl AlgoSimple { #[derive(Debug, Clone, Eq, PartialEq)] pub struct AlgoInfo(pub(crate) Vec<(KeyType, Algo)>); -/// "Algorithm Attributes" +/// Algorithm Attributes /// /// An `Algo` describes the algorithm settings for a key on the card. /// diff --git a/openpgp-card/src/card_app.rs b/openpgp-card/src/card_app.rs index 21397a6..0fdb02b 100644 --- a/openpgp-card/src/card_app.rs +++ b/openpgp-card/src/card_app.rs @@ -11,12 +11,12 @@ use anyhow::{anyhow, Result}; use crate::algorithm::{Algo, AlgoInfo, AlgoSimple, RsaAttrs}; use crate::apdu::{commands, response::Response}; use crate::card_data::{ApplicationRelatedData, Cardholder, Sex}; +use crate::crypto_data::{ + CardUploadableKey, Cryptogram, EccType, Hash, PublicKeyMaterial, +}; use crate::errors::OpenpgpCardError; use crate::tlv::{tag::Tag, Tlv, TlvEntry}; -use crate::{ - apdu, keys, CardCaps, CardClientBox, CardUploadableKey, DecryptMe, - EccType, Hash, KeyType, PublicKeyMaterial, -}; +use crate::{apdu, keys, CardCaps, CardClientBox, KeyType}; /// Direct, low-level, access to OpenPGP card functionality. /// @@ -274,17 +274,17 @@ impl CardApp { /// Decrypt the ciphertext in `dm`, on the card. pub fn decrypt( &mut self, - dm: DecryptMe, + dm: Cryptogram, ) -> Result, OpenpgpCardError> { match dm { - DecryptMe::RSA(message) => { + Cryptogram::RSA(message) => { let mut data = vec![0x0]; data.extend_from_slice(message); // Call the card to decrypt `data` self.pso_decipher(data) } - DecryptMe::ECDH(eph) => { + Cryptogram::ECDH(eph) => { // External Public Key let epk = Tlv(Tag(vec![0x86]), TlvEntry::S(eph.to_vec())); diff --git a/openpgp-card/src/card_data/algo_attrs.rs b/openpgp-card/src/card_data/algo_attrs.rs index 23db04d..c4cc60d 100644 --- a/openpgp-card/src/card_data/algo_attrs.rs +++ b/openpgp-card/src/card_data/algo_attrs.rs @@ -11,7 +11,7 @@ use nom::{branch, bytes::complete as bytes, number::complete as number}; use crate::algorithm::{Algo, Curve, EccAttrs, RsaAttrs}; use crate::card_data::complete; -use crate::EccType; +use crate::crypto_data::EccType; fn parse_oid_cv25519(input: &[u8]) -> nom::IResult<&[u8], Curve> { map(tag(Curve::Cv25519.oid()), |_| Curve::Cv25519)(input) diff --git a/openpgp-card/src/card_data/algo_info.rs b/openpgp-card/src/card_data/algo_info.rs index 4107e53..88835d3 100644 --- a/openpgp-card/src/card_data/algo_info.rs +++ b/openpgp-card/src/card_data/algo_info.rs @@ -102,7 +102,8 @@ mod test { use std::convert::TryFrom; use crate::algorithm::{Algo::*, AlgoInfo, Curve::*, EccAttrs, RsaAttrs}; - use crate::{EccType::*, KeyType::*}; + use crate::crypto_data::EccType::*; + use crate::KeyType::*; #[test] fn test_gnuk() { diff --git a/openpgp-card/src/crypto_data.rs b/openpgp-card/src/crypto_data.rs new file mode 100644 index 0000000..05645cd --- /dev/null +++ b/openpgp-card/src/crypto_data.rs @@ -0,0 +1,129 @@ +// SPDX-FileCopyrightText: 2021 Heiko Schaefer +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Data structures for cryptographic material: +//! Private key data, public key data, cryptograms for decryption, hash +//! data for signing. + +use anyhow::Result; + +use crate::algorithm::Algo; + +/// A hash value that can be signed by the card. +pub enum Hash<'a> { + SHA256([u8; 0x20]), + SHA384([u8; 0x30]), + SHA512([u8; 0x40]), + EdDSA(&'a [u8]), // FIXME? + ECDSA(&'a [u8]), // FIXME? +} + +impl Hash<'_> { + pub(crate) fn oid(&self) -> Option<&'static [u8]> { + match self { + Self::SHA256(_) => { + Some(&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01]) + } + Self::SHA384(_) => { + Some(&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02]) + } + Self::SHA512(_) => { + Some(&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03]) + } + Self::EdDSA(_) => None, + Self::ECDSA(_) => None, + } + } + + pub(crate) fn digest(&self) -> &[u8] { + match self { + Self::SHA256(d) => &d[..], + Self::SHA384(d) => &d[..], + Self::SHA512(d) => &d[..], + Self::EdDSA(d) => d, + Self::ECDSA(d) => d, + } + } +} + +/// Data that can be decrypted on the card. +pub enum Cryptogram<'a> { + // message/ciphertext + RSA(&'a [u8]), + + // ephemeral + ECDH(&'a [u8]), +} + +// --------- + +/// A PGP-implementation-agnostic wrapper for private key data, to upload +/// to an OpenPGP card +pub trait CardUploadableKey { + /// private key data + fn get_key(&self) -> Result; + + /// timestamp of (sub)key creation + fn get_ts(&self) -> u32; + + /// fingerprint + fn get_fp(&self) -> [u8; 20]; +} + +/// Algorithm-independent container for private key material to upload to +/// an OpenPGP card +pub enum PrivateKeyMaterial { + R(Box), + E(Box), +} + +/// RSA-specific container for private key material to upload to an OpenPGP +/// card. +pub trait RSAKey { + fn get_e(&self) -> &[u8]; + fn get_n(&self) -> &[u8]; + fn get_p(&self) -> &[u8]; + fn get_q(&self) -> &[u8]; +} + +/// ECC-specific container for private key material to upload to an OpenPGP +/// card. +pub trait EccKey { + fn get_oid(&self) -> &[u8]; + fn get_scalar(&self) -> &[u8]; + fn get_type(&self) -> EccType; +} + +/// Algorithm-independent container for public key material retrieved from +/// an OpenPGP card +#[derive(Debug)] +pub enum PublicKeyMaterial { + R(RSAPub), + E(EccPub), +} + +/// RSA-specific container for public key material from an OpenPGP card. +#[derive(Debug)] +pub struct RSAPub { + /// Modulus (a number denoted as n coded on x bytes) + pub n: Vec, + + /// Public exponent (a number denoted as v, e.g. 65537 dec.) + pub v: Vec, +} + +/// ECC-specific container for public key material from an OpenPGP card. +#[derive(Debug)] +pub struct EccPub { + pub data: Vec, + pub algo: Algo, +} + +/// A marker to distinguish between elliptic curve algorithms (ECDH, ECDSA, +/// EdDSA) +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum EccType { + ECDH, + EdDSA, + ECDSA, +} diff --git a/openpgp-card/src/keys.rs b/openpgp-card/src/keys.rs index ebb88cd..6717265 100644 --- a/openpgp-card/src/keys.rs +++ b/openpgp-card/src/keys.rs @@ -11,12 +11,13 @@ use crate::algorithm::{Algo, AlgoInfo, Curve, EccAttrs, RsaAttrs}; use crate::apdu::command::Command; use crate::apdu::commands; use crate::card_app::CardApp; +use crate::crypto_data::{ + CardUploadableKey, EccKey, EccPub, PrivateKeyMaterial, PublicKeyMaterial, + RSAKey, RSAPub, +}; use crate::errors::OpenpgpCardError; use crate::tlv::{tag::Tag, Tlv, TlvEntry}; -use crate::{ - apdu, tlv, CardUploadableKey, EccKey, EccPub, KeyType, PrivateKeyMaterial, - PublicKeyMaterial, RSAKey, RSAPub, -}; +use crate::{apdu, tlv, KeyType}; /// `gen_key_with_metadata` calculates the fingerprint for a public key /// data object diff --git a/openpgp-card/src/lib.rs b/openpgp-card/src/lib.rs index d6068b9..7a2a804 100644 --- a/openpgp-card/src/lib.rs +++ b/openpgp-card/src/lib.rs @@ -31,6 +31,7 @@ pub mod algorithm; mod apdu; mod card_app; pub mod card_data; +pub mod crypto_data; pub mod errors; mod keys; mod tlv; @@ -107,126 +108,6 @@ impl CardCaps { } } -/// Container for a hash value. -/// These hash values can be signed by the card. -pub enum Hash<'a> { - SHA256([u8; 0x20]), - SHA384([u8; 0x30]), - SHA512([u8; 0x40]), - EdDSA(&'a [u8]), // FIXME? - ECDSA(&'a [u8]), // FIXME? -} - -impl Hash<'_> { - fn oid(&self) -> Option<&'static [u8]> { - match self { - Self::SHA256(_) => { - Some(&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01]) - } - Self::SHA384(_) => { - Some(&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02]) - } - Self::SHA512(_) => { - Some(&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03]) - } - Self::EdDSA(_) => None, - Self::ECDSA(_) => None, - } - } - - fn digest(&self) -> &[u8] { - match self { - Self::SHA256(d) => &d[..], - Self::SHA384(d) => &d[..], - Self::SHA512(d) => &d[..], - Self::EdDSA(d) => d, - Self::ECDSA(d) => d, - } - } -} - -/// A PGP-implementation-agnostic wrapper for private key data, to upload -/// to an OpenPGP card -pub trait CardUploadableKey { - /// private key data - fn get_key(&self) -> Result; - - /// timestamp of (sub)key creation - fn get_ts(&self) -> u32; - - /// fingerprint - fn get_fp(&self) -> [u8; 20]; -} - -/// Algorithm-independent container for private key material to upload to -/// an OpenPGP card -pub enum PrivateKeyMaterial { - R(Box), - E(Box), -} - -/// RSA-specific container for private key material to upload to an OpenPGP -/// card. -pub trait RSAKey { - fn get_e(&self) -> &[u8]; - fn get_n(&self) -> &[u8]; - fn get_p(&self) -> &[u8]; - fn get_q(&self) -> &[u8]; -} - -/// ECC-specific container for private key material to upload to an OpenPGP -/// card. -pub trait EccKey { - fn get_oid(&self) -> &[u8]; - fn get_scalar(&self) -> &[u8]; - fn get_type(&self) -> EccType; -} - -/// Algorithm-independent container for public key material retrieved from -/// an OpenPGP card -#[derive(Debug)] -pub enum PublicKeyMaterial { - R(RSAPub), - E(EccPub), -} - -/// RSA-specific container for public key material from an OpenPGP card. -#[derive(Debug)] -pub struct RSAPub { - /// Modulus (a number denoted as n coded on x bytes) - pub n: Vec, - - /// Public exponent (a number denoted as v, e.g. 65537 dec.) - pub v: Vec, -} - -/// ECC-specific container for public key material from an OpenPGP card. -#[derive(Debug)] -pub struct EccPub { - pub data: Vec, - pub algo: Algo, -} - -/// A marker to distinguish between elliptic curve algorithms (ECDH, ECDSA, -/// EdDSA) -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub enum EccType { - ECDH, - EdDSA, - ECDSA, -} - -/// Container for data to be decrypted on an OpenPGP card. -pub enum DecryptMe<'a> { - // message/ciphertext - RSA(&'a [u8]), - - // ephemeral - ECDH(&'a [u8]), -} - -// ---------- - /// Enum to identify the Key-slots on an OpenPGP card #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum KeyType {