Refactor: move cryptographic data structures to the module crypto_data
This commit is contained in:
parent
44e915d3e0
commit
d599471be5
10 changed files with 163 additions and 145 deletions
|
@ -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<crypto::SessionKey> {
|
||||
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
|
||||
|
|
|
@ -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<Vec<u8>, OpenpgpCardError> {
|
||||
self.card_app.decrypt(dm)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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<Vec<u8>, 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()));
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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() {
|
||||
|
|
129
openpgp-card/src/crypto_data.rs
Normal file
129
openpgp-card/src/crypto_data.rs
Normal file
|
@ -0,0 +1,129 @@
|
|||
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
|
||||
// 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<PrivateKeyMaterial>;
|
||||
|
||||
/// 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<dyn RSAKey>),
|
||||
E(Box<dyn EccKey>),
|
||||
}
|
||||
|
||||
/// 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<u8>,
|
||||
|
||||
/// Public exponent (a number denoted as v, e.g. 65537 dec.)
|
||||
pub v: Vec<u8>,
|
||||
}
|
||||
|
||||
/// ECC-specific container for public key material from an OpenPGP card.
|
||||
#[derive(Debug)]
|
||||
pub struct EccPub {
|
||||
pub data: Vec<u8>,
|
||||
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,
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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<PrivateKeyMaterial>;
|
||||
|
||||
/// 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<dyn RSAKey>),
|
||||
E(Box<dyn EccKey>),
|
||||
}
|
||||
|
||||
/// 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<u8>,
|
||||
|
||||
/// Public exponent (a number denoted as v, e.g. 65537 dec.)
|
||||
pub v: Vec<u8>,
|
||||
}
|
||||
|
||||
/// ECC-specific container for public key material from an OpenPGP card.
|
||||
#[derive(Debug)]
|
||||
pub struct EccPub {
|
||||
pub data: Vec<u8>,
|
||||
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 {
|
||||
|
|
Loading…
Reference in a new issue