openpgp-card: rename Openpgp and OpenpgpTransaction, restructure modules

This commit is contained in:
Heiko Schaefer 2023-08-29 13:18:53 +02:00
parent 01ef1ec4d1
commit 2d1bf919d4
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
13 changed files with 1537 additions and 1520 deletions

View file

@ -8,7 +8,7 @@ use std::string::FromUtf8Error;
use anyhow::Result; use anyhow::Result;
use openpgp_card::algorithm::AlgoSimple; use openpgp_card::algorithm::AlgoSimple;
use openpgp_card::card_do::{KeyGenerationTime, Sex}; use openpgp_card::card_do::{KeyGenerationTime, Sex};
use openpgp_card::{Error, KeyType, OpenPgp, StatusBytes}; use openpgp_card::{Error, KeyType, StatusBytes};
use openpgp_card_sequoia::sq_util; use openpgp_card_sequoia::sq_util;
use openpgp_card_sequoia::state::{Admin, Open, Transaction}; use openpgp_card_sequoia::state::{Admin, Open, Transaction};
use openpgp_card_sequoia::util::{ use openpgp_card_sequoia::util::{
@ -136,7 +136,10 @@ fn check_key_upload_algo_attrs() -> Result<()> {
Ok(()) Ok(())
} }
pub fn test_print_caps(pgp: &mut OpenPgp, _param: &[&str]) -> Result<TestOutput, TestError> { pub fn test_print_caps(
pgp: &mut openpgp_card::Card,
_param: &[&str],
) -> Result<TestOutput, TestError> {
let mut pgpt = pgp.transaction()?; let mut pgpt = pgp.transaction()?;
let ard = pgpt.application_related_data()?; let ard = pgpt.application_related_data()?;
@ -156,7 +159,10 @@ pub fn test_print_caps(pgp: &mut OpenPgp, _param: &[&str]) -> Result<TestOutput,
Ok(vec![]) Ok(vec![])
} }
pub fn test_print_algo_info(pgp: &mut OpenPgp, _param: &[&str]) -> Result<TestOutput, TestError> { pub fn test_print_algo_info(
pgp: &mut openpgp_card::Card,
_param: &[&str],
) -> Result<TestOutput, TestError> {
let mut pgpt = pgp.transaction()?; let mut pgpt = pgp.transaction()?;
let ard = pgpt.application_related_data()?; let ard = pgpt.application_related_data()?;

View file

@ -3,7 +3,7 @@
use anyhow::anyhow; use anyhow::anyhow;
use openpgp_card::crypto_data::Cryptogram; use openpgp_card::crypto_data::Cryptogram;
use openpgp_card::OpenPgpTransaction; use openpgp_card::Transaction;
use sequoia_openpgp::crypto::mpi; use sequoia_openpgp::crypto::mpi;
use sequoia_openpgp::crypto::SessionKey; use sequoia_openpgp::crypto::SessionKey;
use sequoia_openpgp::packet; use sequoia_openpgp::packet;
@ -15,7 +15,7 @@ use crate::PublicKey;
pub struct CardDecryptor<'a, 'app> { pub struct CardDecryptor<'a, 'app> {
/// The OpenPGP card (authenticated to allow decryption operations) /// The OpenPGP card (authenticated to allow decryption operations)
ca: &'a mut OpenPgpTransaction<'app>, ca: &'a mut Transaction<'app>,
/// The matching public key for the card's decryption key /// The matching public key for the card's decryption key
public: PublicKey, public: PublicKey,
@ -26,7 +26,7 @@ pub struct CardDecryptor<'a, 'app> {
impl<'a, 'app> CardDecryptor<'a, 'app> { impl<'a, 'app> CardDecryptor<'a, 'app> {
pub(crate) fn with_pubkey( pub(crate) fn with_pubkey(
ca: &'a mut OpenPgpTransaction<'app>, ca: &'a mut Transaction<'app>,
public: PublicKey, public: PublicKey,
touch_prompt: &'a (dyn Fn() + Send + Sync), touch_prompt: &'a (dyn Fn() + Send + Sync),
) -> CardDecryptor<'a, 'app> { ) -> CardDecryptor<'a, 'app> {

View file

@ -143,11 +143,11 @@ use card_backend::{CardBackend, SmartcardError};
use openpgp_card::algorithm::{AlgoInfo, AlgoSimple, AlgorithmAttributes}; use openpgp_card::algorithm::{AlgoInfo, AlgoSimple, AlgorithmAttributes};
use openpgp_card::card_do::{ use openpgp_card::card_do::{
ApplicationIdentifier, CardholderRelatedData, ExtendedCapabilities, ExtendedLengthInfo, ApplicationIdentifier, CardholderRelatedData, ExtendedCapabilities, ExtendedLengthInfo,
Fingerprint, HistoricalBytes, KeyGenerationTime, KeyInformation, Lang, PWStatusBytes, Fingerprint, HistoricalBytes, KeyGenerationTime, KeyInformation, KeySet, Lang, PWStatusBytes,
SecuritySupportTemplate, Sex, TouchPolicy, UIF, SecuritySupportTemplate, Sex, TouchPolicy, UIF,
}; };
use openpgp_card::crypto_data::PublicKeyMaterial; use openpgp_card::crypto_data::PublicKeyMaterial;
use openpgp_card::{Error, KeySet, KeyType, OpenPgp, OpenPgpTransaction}; use openpgp_card::{Error, KeyType};
use sequoia_openpgp::cert::prelude::ValidErasedKeyAmalgamation; use sequoia_openpgp::cert::prelude::ValidErasedKeyAmalgamation;
use sequoia_openpgp::packet::key::SecretParts; use sequoia_openpgp::packet::key::SecretParts;
use sequoia_openpgp::packet::{key, Key}; use sequoia_openpgp::packet::{key, Key};
@ -241,7 +241,7 @@ impl Card<Open> {
where where
B: Into<Box<dyn CardBackend + Send + Sync>>, B: Into<Box<dyn CardBackend + Send + Sync>>,
{ {
let pgp = OpenPgp::new(backend)?; let pgp = openpgp_card::Card::new(backend)?;
Ok(Card::<Open> { Ok(Card::<Open> {
state: Open { pgp }, state: Open { pgp },
@ -265,7 +265,7 @@ impl Card<Open> {
impl<'a> Card<Transaction<'a>> { impl<'a> Card<Transaction<'a>> {
// Internal constructor // Internal constructor
fn new(mut opt: OpenPgpTransaction<'a>) -> Result<Self, Error> { fn new(mut opt: openpgp_card::Transaction<'a>) -> Result<Self, Error> {
let ard = opt.application_related_data()?; let ard = opt.application_related_data()?;
Ok(Self { Ok(Self {
@ -715,7 +715,7 @@ impl<'a> Card<Transaction<'a>> {
impl<'app, 'open> Card<User<'app, 'open>> { impl<'app, 'open> Card<User<'app, 'open>> {
/// Helper fn to easily access underlying openpgp_card object /// Helper fn to easily access underlying openpgp_card object
fn card(&mut self) -> &mut OpenPgpTransaction<'app> { fn card(&mut self) -> &mut openpgp_card::Transaction<'app> {
&mut self.state.tx.state.opt &mut self.state.tx.state.opt
} }
@ -767,7 +767,7 @@ impl<'app, 'open> Card<User<'app, 'open>> {
impl<'app, 'open> Card<Sign<'app, 'open>> { impl<'app, 'open> Card<Sign<'app, 'open>> {
/// Helper fn to easily access underlying openpgp_card object /// Helper fn to easily access underlying openpgp_card object
fn card(&mut self) -> &mut OpenPgpTransaction<'app> { fn card(&mut self) -> &mut openpgp_card::Transaction<'app> {
&mut self.state.tx.state.opt &mut self.state.tx.state.opt
} }
@ -823,7 +823,7 @@ impl<'app, 'open> Card<Admin<'app, 'open>> {
} }
/// Helper fn to easily access underlying openpgp_card object /// Helper fn to easily access underlying openpgp_card object
fn card(&mut self) -> &mut OpenPgpTransaction<'app> { fn card(&mut self) -> &mut openpgp_card::Transaction<'app> {
&mut self.state.tx.state.opt &mut self.state.tx.state.opt
} }
} }

View file

@ -5,7 +5,7 @@ use std::convert::TryInto;
use anyhow::anyhow; use anyhow::anyhow;
use openpgp_card::crypto_data::Hash; use openpgp_card::crypto_data::Hash;
use openpgp_card::OpenPgpTransaction; use openpgp_card::Transaction;
use sequoia_openpgp::crypto; use sequoia_openpgp::crypto;
use sequoia_openpgp::crypto::mpi; use sequoia_openpgp::crypto::mpi;
use sequoia_openpgp::types::{Curve, PublicKeyAlgorithm}; use sequoia_openpgp::types::{Curve, PublicKeyAlgorithm};
@ -14,7 +14,7 @@ use crate::PublicKey;
pub struct CardSigner<'a, 'app> { pub struct CardSigner<'a, 'app> {
/// The OpenPGP card (authenticated to allow signing operations) /// The OpenPGP card (authenticated to allow signing operations)
ca: &'a mut OpenPgpTransaction<'app>, ca: &'a mut Transaction<'app>,
/// The matching public key for the card's signing key /// The matching public key for the card's signing key
public: PublicKey, public: PublicKey,
@ -28,7 +28,7 @@ pub struct CardSigner<'a, 'app> {
impl<'a, 'app> CardSigner<'a, 'app> { impl<'a, 'app> CardSigner<'a, 'app> {
pub(crate) fn with_pubkey( pub(crate) fn with_pubkey(
ca: &'a mut OpenPgpTransaction<'app>, ca: &'a mut Transaction<'app>,
public: PublicKey, public: PublicKey,
touch_prompt: &'a (dyn Fn() + Send + Sync), touch_prompt: &'a (dyn Fn() + Send + Sync),
) -> CardSigner<'a, 'app> { ) -> CardSigner<'a, 'app> {
@ -41,7 +41,7 @@ impl<'a, 'app> CardSigner<'a, 'app> {
} }
pub(crate) fn with_pubkey_for_auth( pub(crate) fn with_pubkey_for_auth(
ca: &'a mut OpenPgpTransaction<'app>, ca: &'a mut Transaction<'app>,
public: PublicKey, public: PublicKey,
touch_prompt: &'a (dyn Fn() + Send + Sync), touch_prompt: &'a (dyn Fn() + Send + Sync),
) -> CardSigner<'a, 'app> { ) -> CardSigner<'a, 'app> {
@ -84,9 +84,9 @@ impl<'a, 'app> crypto::Signer for CardSigner<'a, 'app> {
}; };
let sig_fn = if !self.auth { let sig_fn = if !self.auth {
OpenPgpTransaction::signature_for_hash Transaction::signature_for_hash
} else { } else {
OpenPgpTransaction::authenticate_for_hash Transaction::authenticate_for_hash
}; };
// Delegate a signing (or auth) operation to the OpenPGP card. // Delegate a signing (or auth) operation to the OpenPGP card.

View file

@ -4,7 +4,6 @@
//! States of a card are modeled by the types `Open`, `Transaction`, `User`, `Sign`, `Admin`. //! States of a card are modeled by the types `Open`, `Transaction`, `User`, `Sign`, `Admin`.
use openpgp_card::card_do::ApplicationRelatedData; use openpgp_card::card_do::ApplicationRelatedData;
use openpgp_card::{OpenPgp, OpenPgpTransaction};
use crate::Card; use crate::Card;
@ -23,7 +22,7 @@ impl State for Admin<'_, '_> {}
/// ///
/// A transaction can be started on the card, in this state. /// A transaction can be started on the card, in this state.
pub struct Open { pub struct Open {
pub(crate) pgp: OpenPgp, pub(crate) pgp: openpgp_card::Card,
} }
/// State of an OpenPGP card once a transaction has been started. /// State of an OpenPGP card once a transaction has been started.
@ -34,7 +33,7 @@ pub struct Open {
/// ///
/// (Note that a factory-reset can be performed in this base state.) /// (Note that a factory-reset can be performed in this base state.)
pub struct Transaction<'a> { pub struct Transaction<'a> {
pub(crate) opt: OpenPgpTransaction<'a>, pub(crate) opt: openpgp_card::Transaction<'a>,
// Cache of "application related data". // Cache of "application related data".
// //

View file

@ -1,15 +1,16 @@
// SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer <heiko@schaefer.name> // SPDX-FileCopyrightText: 2021-2023 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
//! Pre-defined `Command` values for the OpenPGP card application //! Pre-defined `Command` values for the OpenPGP card application
use crate::apdu::command::Command; use crate::apdu::command::Command;
use crate::{KeyType, ShortTag, Tags, OP_APP}; use crate::tags::{ShortTag, Tags};
use crate::{KeyType, OPENPGP_APPLICATION};
/// 7.2.1 SELECT /// 7.2.1 SELECT
/// (select the OpenPGP application on the card) /// (select the OpenPGP application on the card)
pub(crate) fn select_openpgp() -> Command { pub(crate) fn select_openpgp() -> Command {
Command::new(0x00, 0xA4, 0x04, 0x00, OP_APP.to_vec()) Command::new(0x00, 0xA4, 0x04, 0x00, OPENPGP_APPLICATION.to_vec())
} }
/// 7.2.6 GET DATA /// 7.2.6 GET DATA

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer <heiko@schaefer.name> // SPDX-FileCopyrightText: 2021-2023 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
//! OpenPGP card data objects (DO) //! OpenPGP card data objects (DO)
@ -9,7 +9,8 @@ use std::time::{Duration, UNIX_EPOCH};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use crate::{algorithm::AlgorithmAttributes, tlv::Tlv, Error, KeySet, KeyType, Tags}; use crate::tags::Tags;
use crate::{algorithm::AlgorithmAttributes, tlv::Tlv, Error, KeyType};
mod algo_attrs; mod algo_attrs;
mod algo_info; mod algo_info;
@ -22,7 +23,7 @@ mod historical;
mod key_generation_times; mod key_generation_times;
mod pw_status; mod pw_status;
/// 4.4.3.1 Application Related Data /// Application Related Data [Spec section 4.4.3.1]
/// ///
/// The "application related data" DO contains a set of DOs. /// The "application related data" DO contains a set of DOs.
/// This struct offers read access to these DOs. /// This struct offers read access to these DOs.
@ -274,7 +275,7 @@ impl ApplicationRelatedData {
} }
} }
/// Security support template (see spec pg. 24) /// Security support template [Spec page 24]
#[derive(Debug)] #[derive(Debug)]
pub struct SecuritySupportTemplate { pub struct SecuritySupportTemplate {
// Digital signature counter [3 bytes] // Digital signature counter [3 bytes]
@ -288,7 +289,7 @@ impl SecuritySupportTemplate {
} }
} }
/// An OpenPGP key generation Time (see spec pg. 24) /// An OpenPGP key generation Time [Spec page 24]
#[derive(Clone, Copy, Eq, PartialEq, Debug)] #[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub struct KeyGenerationTime(u32); pub struct KeyGenerationTime(u32);
@ -309,7 +310,7 @@ impl Display for KeyGenerationTime {
} }
} }
/// User Interaction Flag (UIF) (see spec pg. 24) /// User Interaction Flag (UIF) [Spec page 24]
#[derive(Clone, Copy, Eq, PartialEq, Debug)] #[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub struct UIF([u8; 2]); pub struct UIF([u8; 2]);
@ -422,7 +423,7 @@ impl From<u8> for TouchPolicy {
} }
} }
/// "additional hardware for user interaction" (see spec 4.1.3.2) /// "additional hardware for user interaction" [Spec section 4.1.3.2]
pub struct Features(u8); pub struct Features(u8);
impl From<u8> for Features { impl From<u8> for Features {
@ -464,7 +465,7 @@ impl Display for Features {
} }
} }
/// 4.4.3.8 Key Information /// Key Information [Spec section 4.4.3.8]
pub struct KeyInformation(Vec<u8>); pub struct KeyInformation(Vec<u8>);
impl From<Vec<u8>> for KeyInformation { impl From<Vec<u8>> for KeyInformation {
@ -583,7 +584,7 @@ impl Display for KeyStatus {
} }
} }
/// 4.2.1 Application Identifier (AID) /// Application Identifier (AID) [Spec section 4.2.1]
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub struct ApplicationIdentifier { pub struct ApplicationIdentifier {
application: u8, application: u8,
@ -602,7 +603,7 @@ impl Display for ApplicationIdentifier {
} }
} }
/// 6 Historical Bytes /// Historical Bytes [Spec chapter 6]
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct HistoricalBytes { pub struct HistoricalBytes {
/// category indicator byte /// category indicator byte
@ -618,7 +619,7 @@ pub struct HistoricalBytes {
sib: u8, sib: u8,
} }
/// Card Capabilities (see 6 Historical Bytes) /// Card Capabilities [Spec chapter 6 (Historical Bytes)]
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct CardCapabilities { pub struct CardCapabilities {
command_chaining: bool, command_chaining: bool,
@ -642,7 +643,7 @@ impl Display for CardCapabilities {
} }
} }
/// Card service data (see 6 Historical Bytes) /// Card service data [Spec chapter 6 (Historical Bytes)]
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct CardServiceData { pub struct CardServiceData {
select_by_full_df_name: bool, // Application Selection by full DF name (AID) select_by_full_df_name: bool, // Application Selection by full DF name (AID)
@ -689,7 +690,7 @@ impl Display for CardServiceData {
} }
} }
/// 4.4.3.7 Extended Capabilities /// Extended Capabilities [Spec section 4.4.3.7]
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub struct ExtendedCapabilities { pub struct ExtendedCapabilities {
secure_messaging: bool, secure_messaging: bool,
@ -779,7 +780,7 @@ impl Display for ExtendedCapabilities {
} }
} }
/// 4.1.3.1 Extended length information /// Extended length information [Spec section 4.1.3.1]
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub struct ExtendedLengthInfo { pub struct ExtendedLengthInfo {
max_command_bytes: u16, max_command_bytes: u16,
@ -794,7 +795,7 @@ impl Display for ExtendedLengthInfo {
} }
} }
/// Cardholder Related Data (see spec pg. 22) /// Cardholder Related Data [Spec page 22]
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct CardholderRelatedData { pub struct CardholderRelatedData {
name: Option<Vec<u8>>, name: Option<Vec<u8>>,
@ -819,7 +820,7 @@ impl Display for CardholderRelatedData {
} }
} }
/// 4.4.3.5 Sex /// Sex [Spec section 4.4.3.5]
/// ///
/// Encoded in accordance with <https://en.wikipedia.org/wiki/ISO/IEC_5218> /// Encoded in accordance with <https://en.wikipedia.org/wiki/ISO/IEC_5218>
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
@ -867,7 +868,9 @@ impl From<u8> for Sex {
} }
} }
/// Individual language for Language Preferences (4.4.3.4), accessible via `CardholderRelatedData`. /// Individual language for Language Preferences [Spec section 4.4.3.4]
///
/// This field is accessible via `CardholderRelatedData`.
/// ///
/// Encoded according to <https://en.wikipedia.org/wiki/ISO_639-1> /// Encoded according to <https://en.wikipedia.org/wiki/ISO_639-1>
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
@ -922,7 +925,7 @@ impl From<&[u8; 2]> for Lang {
} }
} }
/// PW status Bytes (see spec page 23) /// PW status Bytes [Spec page 23]
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct PWStatusBytes { pub struct PWStatusBytes {
pub(crate) pw1_cds_valid_once: bool, pub(crate) pw1_cds_valid_once: bool,
@ -992,7 +995,7 @@ impl PWStatusBytes {
} }
} }
/// Fingerprint (see spec pg. 23) /// Fingerprint [Spec page 23]
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]
pub struct Fingerprint([u8; 20]); pub struct Fingerprint([u8; 20]);
@ -1026,3 +1029,35 @@ pub(crate) fn complete<O>(result: nom::IResult<&[u8], O>) -> Result<O, Error> {
))) )))
} }
} }
/// A KeySet binds together a triple of information about each Key slot on a card
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KeySet<T> {
signature: Option<T>,
decryption: Option<T>,
authentication: Option<T>,
}
impl<T> From<(Option<T>, Option<T>, Option<T>)> for KeySet<T> {
fn from(tuple: (Option<T>, Option<T>, Option<T>)) -> Self {
Self {
signature: tuple.0,
decryption: tuple.1,
authentication: tuple.2,
}
}
}
impl<T> KeySet<T> {
pub fn signature(&self) -> Option<&T> {
self.signature.as_ref()
}
pub fn decryption(&self) -> Option<&T> {
self.decryption.as_ref()
}
pub fn authentication(&self) -> Option<&T> {
self.authentication.as_ref()
}
}

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer <heiko@schaefer.name> // SPDX-FileCopyrightText: 2021-2023 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
//! Cardholder Related Data (see spec pg. 22) //! Cardholder Related Data (see spec pg. 22)
@ -6,8 +6,8 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use crate::card_do::{CardholderRelatedData, Lang, Sex}; use crate::card_do::{CardholderRelatedData, Lang, Sex};
use crate::tags::Tags;
use crate::tlv::{value::Value, Tlv}; use crate::tlv::{value::Value, Tlv};
use crate::Tags;
impl CardholderRelatedData { impl CardholderRelatedData {
pub fn name(&self) -> Option<&[u8]> { pub fn name(&self) -> Option<&[u8]> {

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer <heiko@schaefer.name> // SPDX-FileCopyrightText: 2021-2023 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
//! Generate and import keys //! Generate and import keys
@ -14,9 +14,9 @@ use crate::crypto_data::{
CardUploadableKey, EccKey, EccPub, EccType, PrivateKeyMaterial, PublicKeyMaterial, RSAKey, CardUploadableKey, EccKey, EccPub, EccType, PrivateKeyMaterial, PublicKeyMaterial, RSAKey,
RSAPub, RSAPub,
}; };
use crate::openpgp::OpenPgpTransaction; use crate::tags::Tags;
use crate::tlv::{length::tlv_encode_length, value::Value, Tlv}; use crate::tlv::{length::tlv_encode_length, value::Value, Tlv};
use crate::{Error, KeyType, Tag, Tags}; use crate::{Error, KeyType, Tag, Transaction};
/// Generate asymmetric key pair on the card. /// Generate asymmetric key pair on the card.
/// ///
@ -29,7 +29,7 @@ use crate::{Error, KeyType, Tag, Tags};
/// `fp_from_pub` calculates the fingerprint for a public key data object and /// `fp_from_pub` calculates the fingerprint for a public key data object and
/// creation timestamp /// creation timestamp
pub(crate) fn gen_key_with_metadata( pub(crate) fn gen_key_with_metadata(
card_tx: &mut OpenPgpTransaction, card_tx: &mut Transaction,
fp_from_pub: fn(&PublicKeyMaterial, KeyGenerationTime, KeyType) -> Result<Fingerprint, Error>, fp_from_pub: fn(&PublicKeyMaterial, KeyGenerationTime, KeyType) -> Result<Fingerprint, Error>,
key_type: KeyType, key_type: KeyType,
algo: Option<&AlgorithmAttributes>, algo: Option<&AlgorithmAttributes>,
@ -121,7 +121,7 @@ fn tlv_to_pubkey(tlv: &Tlv, algo: &AlgorithmAttributes) -> Result<PublicKeyMater
/// This runs the low level key generation primitive on the card. /// This runs the low level key generation primitive on the card.
/// (This does not set algorithm attributes, creation time or fingerprint) /// (This does not set algorithm attributes, creation time or fingerprint)
pub(crate) fn generate_asymmetric_key_pair( pub(crate) fn generate_asymmetric_key_pair(
card_tx: &mut OpenPgpTransaction, card_tx: &mut Transaction,
key_type: KeyType, key_type: KeyType,
) -> Result<Tlv, Error> { ) -> Result<Tlv, Error> {
log::info!("OpenPgpTransaction: generate_asymmetric_key_pair"); log::info!("OpenPgpTransaction: generate_asymmetric_key_pair");
@ -145,7 +145,7 @@ pub(crate) fn generate_asymmetric_key_pair(
/// ///
/// (See 7.2.14 GENERATE ASYMMETRIC KEY PAIR) /// (See 7.2.14 GENERATE ASYMMETRIC KEY PAIR)
pub(crate) fn public_key( pub(crate) fn public_key(
card_tx: &mut OpenPgpTransaction, card_tx: &mut Transaction,
key_type: KeyType, key_type: KeyType,
) -> Result<PublicKeyMaterial, Error> { ) -> Result<PublicKeyMaterial, Error> {
log::info!("OpenPgpTransaction: public_key"); log::info!("OpenPgpTransaction: public_key");
@ -173,7 +173,7 @@ pub(crate) fn public_key(
/// caused by checks before attempting to upload the key to the card, or by /// caused by checks before attempting to upload the key to the card, or by
/// an error that the card reports during an attempt to upload the key). /// an error that the card reports during an attempt to upload the key).
pub(crate) fn key_import( pub(crate) fn key_import(
card_tx: &mut OpenPgpTransaction, card_tx: &mut Transaction,
key: Box<dyn CardUploadableKey>, key: Box<dyn CardUploadableKey>,
key_type: KeyType, key_type: KeyType,
algo_info: Option<AlgoInfo>, algo_info: Option<AlgoInfo>,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

259
openpgp-card/src/tags.rs Normal file
View file

@ -0,0 +1,259 @@
// SPDX-FileCopyrightText: 2021-2023 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0
use crate::tlv::tag::Tag;
/// Tags, as specified and used in the OpenPGP card 3.4.1 spec.
/// All tags in OpenPGP card are either 1 or 2 bytes long.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[non_exhaustive]
#[allow(dead_code)]
pub(crate) enum Tags {
// BER identifiers
OctetString,
Null,
ObjectIdentifier,
Sequence,
// GET DATA
PrivateUse1,
PrivateUse2,
PrivateUse3,
PrivateUse4,
ApplicationIdentifier,
LoginData,
Url,
HistoricalBytes,
CardholderRelatedData,
Name,
LanguagePref,
Sex,
ApplicationRelatedData,
ExtendedLengthInformation,
GeneralFeatureManagement,
DiscretionaryDataObjects,
ExtendedCapabilities,
AlgorithmAttributesSignature,
AlgorithmAttributesDecryption,
AlgorithmAttributesAuthentication,
PWStatusBytes,
Fingerprints,
CaFingerprints,
GenerationTimes,
KeyInformation,
UifSig,
UifDec,
UifAuth,
UifAttestation,
SecuritySupportTemplate,
DigitalSignatureCounter,
CardholderCertificate,
AlgorithmAttributesAttestation,
FingerprintAttestation,
CaFingerprintAttestation,
GenerationTimeAttestation,
KdfDo,
AlgorithmInformation,
CertificateSecureMessaging,
AttestationCertificate,
// PUT DATA (additional Tags that don't get used for GET DATA)
FingerprintSignature,
FingerprintDecryption,
FingerprintAuthentication,
CaFingerprint1,
CaFingerprint2,
CaFingerprint3,
GenerationTimeSignature,
GenerationTimeDecryption,
GenerationTimeAuthentication,
// FIXME: +D1, D2
ResettingCode,
PsoEncDecKey,
// OTHER
// 4.4.3.12 Private Key Template
ExtendedHeaderList,
CardholderPrivateKeyTemplate,
ConcatenatedKeyData,
CrtKeySignature,
CrtKeyConfidentiality,
CrtKeyAuthentication,
PrivateKeyDataRsaPublicExponent,
PrivateKeyDataRsaPrime1,
PrivateKeyDataRsaPrime2,
PrivateKeyDataRsaPq,
PrivateKeyDataRsaDp1,
PrivateKeyDataRsaDq1,
PrivateKeyDataRsaModulus,
PrivateKeyDataEccPrivateKey,
PrivateKeyDataEccPublicKey,
// 7.2.14 GENERATE ASYMMETRIC KEY PAIR
PublicKey,
PublicKeyDataRsaModulus,
PublicKeyDataRsaExponent,
PublicKeyDataEccPoint,
// 7.2.11 PSO: DECIPHER
Cipher,
ExternalPublicKey,
// 7.2.5 SELECT DATA
GeneralReference,
TagList,
}
impl From<Tags> for Vec<u8> {
fn from(t: Tags) -> Self {
ShortTag::from(t).into()
}
}
impl From<Tags> for Tag {
fn from(t: Tags) -> Self {
ShortTag::from(t).into()
}
}
impl From<Tags> for ShortTag {
fn from(t: Tags) -> Self {
match t {
// BER identifiers https://en.wikipedia.org/wiki/X.690#BER_encoding
Tags::OctetString => [0x04].into(),
Tags::Null => [0x05].into(),
Tags::ObjectIdentifier => [0x06].into(),
Tags::Sequence => [0x30].into(),
// GET DATA
Tags::PrivateUse1 => [0x01, 0x01].into(),
Tags::PrivateUse2 => [0x01, 0x02].into(),
Tags::PrivateUse3 => [0x01, 0x03].into(),
Tags::PrivateUse4 => [0x01, 0x04].into(),
Tags::ApplicationIdentifier => [0x4f].into(),
Tags::LoginData => [0x5e].into(),
Tags::Url => [0x5f, 0x50].into(),
Tags::HistoricalBytes => [0x5f, 0x52].into(),
Tags::CardholderRelatedData => [0x65].into(),
Tags::Name => [0x5b].into(),
Tags::LanguagePref => [0x5f, 0x2d].into(),
Tags::Sex => [0x5f, 0x35].into(),
Tags::ApplicationRelatedData => [0x6e].into(),
Tags::ExtendedLengthInformation => [0x7f, 0x66].into(),
Tags::GeneralFeatureManagement => [0x7f, 0x74].into(),
Tags::DiscretionaryDataObjects => [0x73].into(),
Tags::ExtendedCapabilities => [0xc0].into(),
Tags::AlgorithmAttributesSignature => [0xc1].into(),
Tags::AlgorithmAttributesDecryption => [0xc2].into(),
Tags::AlgorithmAttributesAuthentication => [0xc3].into(),
Tags::PWStatusBytes => [0xc4].into(),
Tags::Fingerprints => [0xc5].into(),
Tags::CaFingerprints => [0xc6].into(),
Tags::GenerationTimes => [0xcd].into(),
Tags::KeyInformation => [0xde].into(),
Tags::UifSig => [0xd6].into(),
Tags::UifDec => [0xd7].into(),
Tags::UifAuth => [0xd8].into(),
Tags::UifAttestation => [0xd9].into(),
Tags::SecuritySupportTemplate => [0x7a].into(),
Tags::DigitalSignatureCounter => [0x93].into(),
Tags::CardholderCertificate => [0x7f, 0x21].into(),
Tags::AlgorithmAttributesAttestation => [0xda].into(),
Tags::FingerprintAttestation => [0xdb].into(),
Tags::CaFingerprintAttestation => [0xdc].into(),
Tags::GenerationTimeAttestation => [0xdd].into(),
Tags::KdfDo => [0xf9].into(),
Tags::AlgorithmInformation => [0xfa].into(),
Tags::CertificateSecureMessaging => [0xfb].into(),
Tags::AttestationCertificate => [0xfc].into(),
// PUT DATA
Tags::FingerprintSignature => [0xc7].into(),
Tags::FingerprintDecryption => [0xc8].into(),
Tags::FingerprintAuthentication => [0xc9].into(),
Tags::CaFingerprint1 => [0xca].into(),
Tags::CaFingerprint2 => [0xcb].into(),
Tags::CaFingerprint3 => [0xcc].into(),
Tags::GenerationTimeSignature => [0xce].into(),
Tags::GenerationTimeDecryption => [0xcf].into(),
Tags::GenerationTimeAuthentication => [0xd0].into(),
Tags::ResettingCode => [0xd3].into(),
Tags::PsoEncDecKey => [0xd5].into(),
// OTHER
// 4.4.3.12 Private Key Template
Tags::ExtendedHeaderList => [0x4d].into(),
Tags::CardholderPrivateKeyTemplate => [0x7f, 0x48].into(),
Tags::ConcatenatedKeyData => [0x5f, 0x48].into(),
Tags::CrtKeySignature => [0xb6].into(),
Tags::CrtKeyConfidentiality => [0xb8].into(),
Tags::CrtKeyAuthentication => [0xa4].into(),
Tags::PrivateKeyDataRsaPublicExponent => [0x91].into(),
Tags::PrivateKeyDataRsaPrime1 => [0x92].into(), // Note: value reused!
Tags::PrivateKeyDataRsaPrime2 => [0x93].into(),
Tags::PrivateKeyDataRsaPq => [0x94].into(),
Tags::PrivateKeyDataRsaDp1 => [0x95].into(),
Tags::PrivateKeyDataRsaDq1 => [0x96].into(),
Tags::PrivateKeyDataRsaModulus => [0x97].into(),
Tags::PrivateKeyDataEccPrivateKey => [0x92].into(), // Note: value reused!
Tags::PrivateKeyDataEccPublicKey => [0x99].into(),
// 7.2.14 GENERATE ASYMMETRIC KEY PAIR
Tags::PublicKey => [0x7f, 0x49].into(),
Tags::PublicKeyDataRsaModulus => [0x81].into(),
Tags::PublicKeyDataRsaExponent => [0x82].into(),
Tags::PublicKeyDataEccPoint => [0x86].into(),
// 7.2.11 PSO: DECIPHER
Tags::Cipher => [0xa6].into(),
Tags::ExternalPublicKey => [0x86].into(),
// 7.2.5 SELECT DATA
Tags::GeneralReference => [0x60].into(),
Tags::TagList => [0x5c].into(),
}
}
}
/// A ShortTag is a Tlv tag that is guaranteed to be either 1 or 2 bytes long.
///
/// This covers any tag that can be used in the OpenPGP card context (the spec doesn't describe how
/// longer tags might be used.)
///
/// (The type tlv::Tag will usually/always contain 1 or 2 byte long tags, in this library.
/// But its length is not guaranteed by the type system)
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ShortTag {
One(u8),
Two(u8, u8),
}
impl From<ShortTag> for Tag {
fn from(n: ShortTag) -> Self {
match n {
ShortTag::One(t0) => [t0].into(),
ShortTag::Two(t0, t1) => [t0, t1].into(),
}
}
}
impl From<[u8; 1]> for ShortTag {
fn from(v: [u8; 1]) -> Self {
ShortTag::One(v[0])
}
}
impl From<[u8; 2]> for ShortTag {
fn from(v: [u8; 2]) -> Self {
ShortTag::Two(v[0], v[1])
}
}
impl From<ShortTag> for Vec<u8> {
fn from(t: ShortTag) -> Self {
match t {
ShortTag::One(t0) => vec![t0],
ShortTag::Two(t0, t1) => vec![t0, t1],
}
}
}

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer <heiko@schaefer.name> // SPDX-FileCopyrightText: 2021-2023 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
pub(crate) mod length; pub(crate) mod length;
@ -87,7 +87,8 @@ mod test {
use hex_literal::hex; use hex_literal::hex;
use super::{Tlv, Value}; use super::{Tlv, Value};
use crate::{Error, Tags}; use crate::tags::Tags;
use crate::Error;
#[test] #[test]
fn test_tlv0() { fn test_tlv0() {