Refactor: move accessor fn for "Application Related Data" into the struct ApplicationRelatedData.

This commit is contained in:
Heiko Schaefer 2021-08-20 21:41:11 +02:00
parent 50499dc15d
commit c872e46e80
11 changed files with 201 additions and 201 deletions

View file

@ -8,7 +8,7 @@ use anyhow::{anyhow, Result};
use serde_derive::Deserialize; use serde_derive::Deserialize;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use openpgp_card::card_app::CardApp; use openpgp_card::CardApp;
use openpgp_card_pcsc::PcscClient; use openpgp_card_pcsc::PcscClient;
use openpgp_card_scdc::ScdClient; use openpgp_card_scdc::ScdClient;
@ -102,7 +102,7 @@ impl TestCard {
// Set Card Capabilities (chaining, command length, ..) // Set Card Capabilities (chaining, command length, ..)
let ard = ca.get_app_data()?; let ard = ca.get_app_data()?;
let app_id = CardApp::get_aid(&ard)?; let app_id = ard.get_aid()?;
if app_id.ident().as_str() == ident { if app_id.ident().as_str() == ident {
ca.init_caps(&ard)?; ca.init_caps(&ard)?;

View file

@ -12,9 +12,8 @@ use sequoia_openpgp::types::Timestamp;
use sequoia_openpgp::Cert; use sequoia_openpgp::Cert;
use openpgp_card::algorithm::AlgoSimple; use openpgp_card::algorithm::AlgoSimple;
use openpgp_card::card_app::CardApp;
use openpgp_card::errors::{OcErrorStatus, OpenpgpCardError}; use openpgp_card::errors::{OcErrorStatus, OpenpgpCardError};
use openpgp_card::{KeyType, Sex}; use openpgp_card::{CardApp, KeyType, Sex};
use openpgp_card_sequoia::{ use openpgp_card_sequoia::{
make_cert, public_key_material_to_key, public_to_fingerprint, make_cert, public_key_material_to_key, public_to_fingerprint,
}; };
@ -100,7 +99,7 @@ fn check_key_upload_metadata(
let ard = ca.get_app_data()?; let ard = ca.get_app_data()?;
// check fingerprints // check fingerprints
let card_fp = CardApp::get_fingerprints(&ard)?; let card_fp = ard.get_fingerprints()?;
let sig = card_fp.signature().expect("signature fingerprint"); let sig = card_fp.signature().expect("signature fingerprint");
assert_eq!(format!("{:X}", sig), meta[0].0); assert_eq!(format!("{:X}", sig), meta[0].0);
@ -114,7 +113,7 @@ fn check_key_upload_metadata(
assert_eq!(format!("{:X}", auth), meta[2].0); assert_eq!(format!("{:X}", auth), meta[2].0);
// get_key_generation_times // get_key_generation_times
let card_kg = CardApp::get_key_generation_times(&ard)?; let card_kg = ard.get_key_generation_times()?;
let sig: u32 = let sig: u32 =
card_kg.signature().expect("signature creation time").into(); card_kg.signature().expect("signature creation time").into();
@ -148,13 +147,13 @@ pub fn test_print_caps(
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let ard = ca.get_app_data()?; let ard = ca.get_app_data()?;
let hist = CardApp::get_historical(&ard)?; let hist = ard.get_historical()?;
println!("hist: {:#?}", hist); println!("hist: {:#?}", hist);
let ecap = CardApp::get_extended_capabilities(&ard)?; let ecap = ard.get_extended_capabilities()?;
println!("ecap: {:#?}", ecap); println!("ecap: {:#?}", ecap);
let eli = CardApp::get_extended_length_information(&ard)?; let eli = ard.get_extended_length_information()?;
println!("eli: {:#?}", eli); println!("eli: {:#?}", eli);
Ok(vec![]) Ok(vec![])
@ -166,7 +165,7 @@ pub fn test_print_algo_info(
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let ard = ca.get_app_data()?; let ard = ca.get_app_data()?;
let dec = CardApp::get_algorithm_attributes(&ard, KeyType::Decryption)?; let dec = ard.get_algorithm_attributes(KeyType::Decryption)?;
println!("Current algorithm for the decrypt slot: {}", dec); println!("Current algorithm for the decrypt slot: {}", dec);
println!(); println!();
@ -262,7 +261,7 @@ pub fn test_get_pub(
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let ard = ca.get_app_data()?; let ard = ca.get_app_data()?;
let key_gen = CardApp::get_key_generation_times(&ard)?; let key_gen = ard.get_key_generation_times()?;
// -- // --
@ -428,7 +427,7 @@ pub fn run_test(
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let mut ca = card.get_card_app()?; let mut ca = card.get_card_app()?;
let ard = ca.get_app_data()?; let ard = ca.get_app_data()?;
let _app_id = CardApp::get_aid(&ard)?; let _app_id = ard.get_aid()?;
t(&mut ca, param) t(&mut ca, param)
} }

View file

@ -18,8 +18,7 @@ use sequoia_openpgp::serialize::stream::{
}; };
use sequoia_openpgp::Cert; use sequoia_openpgp::Cert;
use openpgp_card::card_app::CardApp; use openpgp_card::{CardApp, KeyType};
use openpgp_card::KeyType;
use openpgp_card_sequoia::vka_as_uploadable_key; use openpgp_card_sequoia::vka_as_uploadable_key;
pub const SP: &StandardPolicy = &StandardPolicy::new(); pub const SP: &StandardPolicy = &StandardPolicy::new();

View file

@ -16,10 +16,9 @@ use openpgp::Cert;
use sequoia_openpgp as openpgp; use sequoia_openpgp as openpgp;
use openpgp_card::errors::OpenpgpCardError; use openpgp_card::errors::OpenpgpCardError;
use openpgp_card::DecryptMe; use openpgp_card::{CardApp, DecryptMe};
use crate::PublicKey; use crate::PublicKey;
use openpgp_card::card_app::CardApp;
pub(crate) struct CardDecryptor<'a> { pub(crate) struct CardDecryptor<'a> {
/// The OpenPGP card (authenticated to allow decryption operations) /// The OpenPGP card (authenticated to allow decryption operations)
@ -41,7 +40,7 @@ impl<'a> CardDecryptor<'a> {
) -> Result<CardDecryptor<'a>, OpenpgpCardError> { ) -> Result<CardDecryptor<'a>, OpenpgpCardError> {
// Get the fingerprint for the decryption key from the card. // Get the fingerprint for the decryption key from the card.
let ard = ca.get_app_data()?; let ard = ca.get_app_data()?;
let fps = CardApp::get_fingerprints(&ard)?; let fps = ard.get_fingerprints()?;
let fp = fps.decryption(); let fp = fps.decryption();
if let Some(fp) = fp { if let Some(fp) = fp {

View file

@ -32,13 +32,12 @@ use openpgp::{Cert, Packet};
use sequoia_openpgp as openpgp; use sequoia_openpgp as openpgp;
use openpgp_card::algorithm::{Algo, AlgoInfo, Curve}; use openpgp_card::algorithm::{Algo, AlgoInfo, Curve};
use openpgp_card::apdu::response::Response;
use openpgp_card::card_app::{CardApp, ARD};
use openpgp_card::{ use openpgp_card::{
errors::OpenpgpCardError, ApplicationId, CardClientBox, CardUploadableKey, errors::OpenpgpCardError, ApplicationId, ApplicationRelatedData, CardApp,
Cardholder, DecryptMe, EccKey, EccType, ExtendedCap, ExtendedLengthInfo, CardClientBox, CardUploadableKey, Cardholder, DecryptMe, EccKey, EccType,
Features, Fingerprint, Hash, Historical, KeySet, KeyType, PWStatus, ExtendedCap, ExtendedLengthInfo, Features, Fingerprint, Hash, Historical,
PrivateKeyMaterial, PublicKeyMaterial, RSAKey, Sex, KeySet, KeyType, PWStatus, PrivateKeyMaterial, PublicKeyMaterial, RSAKey,
Response, Sex,
}; };
use crate::signer::CardSigner; use crate::signer::CardSigner;
@ -558,11 +557,11 @@ pub struct CardBase {
// //
// FIXME: Should be invalidated when changing data on the card! // FIXME: Should be invalidated when changing data on the card!
// (e.g. uploading keys, etc) // (e.g. uploading keys, etc)
ard: ARD, ard: ApplicationRelatedData,
} }
impl CardBase { impl CardBase {
pub fn new(card_app: CardApp, ard: ARD) -> Self { pub fn new(card_app: CardApp, ard: ApplicationRelatedData) -> Self {
Self { card_app, ard } Self { card_app, ard }
} }
@ -590,22 +589,22 @@ impl CardBase {
/// ///
/// This is done once, after opening the OpenPGP card applet /// This is done once, after opening the OpenPGP card applet
/// (the data is stored in the OpenPGPCard object). /// (the data is stored in the OpenPGPCard object).
fn get_app_data(&mut self) -> Result<ARD> { fn get_app_data(&mut self) -> Result<ApplicationRelatedData> {
self.card_app.get_app_data() self.card_app.get_app_data()
} }
pub fn get_aid(&self) -> Result<ApplicationId, OpenpgpCardError> { pub fn get_aid(&self) -> Result<ApplicationId, OpenpgpCardError> {
CardApp::get_aid(&self.ard) self.ard.get_aid()
} }
pub fn get_historical(&self) -> Result<Historical, OpenpgpCardError> { pub fn get_historical(&self) -> Result<Historical, OpenpgpCardError> {
CardApp::get_historical(&self.ard) self.ard.get_historical()
} }
pub fn get_extended_length_information( pub fn get_extended_length_information(
&self, &self,
) -> Result<Option<ExtendedLengthInfo>> { ) -> Result<Option<ExtendedLengthInfo>> {
CardApp::get_extended_length_information(&self.ard) self.ard.get_extended_length_information()
} }
pub fn get_general_feature_management() -> Option<bool> { pub fn get_general_feature_management() -> Option<bool> {
@ -619,22 +618,22 @@ impl CardBase {
pub fn get_extended_capabilities( pub fn get_extended_capabilities(
&self, &self,
) -> Result<ExtendedCap, OpenpgpCardError> { ) -> Result<ExtendedCap, OpenpgpCardError> {
CardApp::get_extended_capabilities(&self.ard) self.ard.get_extended_capabilities()
} }
pub fn get_algorithm_attributes(&self, key_type: KeyType) -> Result<Algo> { pub fn get_algorithm_attributes(&self, key_type: KeyType) -> Result<Algo> {
CardApp::get_algorithm_attributes(&self.ard, key_type) self.ard.get_algorithm_attributes(key_type)
} }
/// PW status Bytes /// PW status Bytes
pub fn get_pw_status_bytes(&self) -> Result<PWStatus> { pub fn get_pw_status_bytes(&self) -> Result<PWStatus> {
CardApp::get_pw_status_bytes(&self.ard) self.ard.get_pw_status_bytes()
} }
pub fn get_fingerprints( pub fn get_fingerprints(
&self, &self,
) -> Result<KeySet<Fingerprint>, OpenpgpCardError> { ) -> Result<KeySet<Fingerprint>, OpenpgpCardError> {
CardApp::get_fingerprints(&self.ard) self.ard.get_fingerprints()
} }
pub fn get_ca_fingerprints(&self) { pub fn get_ca_fingerprints(&self) {

View file

@ -8,8 +8,7 @@ use std::error::Error;
use sequoia_openpgp::parse::Parse; use sequoia_openpgp::parse::Parse;
use sequoia_openpgp::Cert; use sequoia_openpgp::Cert;
use openpgp_card::card_app::CardApp; use openpgp_card::{CardApp, KeyType};
use openpgp_card::KeyType;
use openpgp_card_pcsc::PcscClient; use openpgp_card_pcsc::PcscClient;
// use openpgp_card_scdc::ScdClient; // use openpgp_card_scdc::ScdClient;
@ -241,7 +240,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut ca = CardApp::new(c); let mut ca = CardApp::new(c);
let ard = ca.get_app_data()?; let ard = ca.get_app_data()?;
let app_id = CardApp::get_aid(&ard)?; let app_id = ard.get_aid()?;
let ident = app_id.ident(); let ident = app_id.ident();
println!(" '{}'", ident); println!(" '{}'", ident);

View file

@ -10,9 +10,8 @@ use openpgp::policy::Policy;
use openpgp::types::{Curve, PublicKeyAlgorithm}; use openpgp::types::{Curve, PublicKeyAlgorithm};
use sequoia_openpgp as openpgp; use sequoia_openpgp as openpgp;
use openpgp_card::card_app::CardApp;
use openpgp_card::errors::OpenpgpCardError; use openpgp_card::errors::OpenpgpCardError;
use openpgp_card::Hash; use openpgp_card::{CardApp, Hash};
use crate::PublicKey; use crate::PublicKey;
@ -36,7 +35,7 @@ impl<'a> CardSigner<'a> {
) -> Result<CardSigner<'a>, OpenpgpCardError> { ) -> Result<CardSigner<'a>, OpenpgpCardError> {
// Get the fingerprint for the signing key from the card. // Get the fingerprint for the signing key from the card.
let ard = ca.get_app_data()?; let ard = ca.get_app_data()?;
let fps = CardApp::get_fingerprints(&ard)?; let fps = ard.get_fingerprints()?;
let fp = fps.signature(); let fp = fps.signature();
if let Some(fp) = fp { if let Some(fp) = fp {

View file

@ -1,14 +1,6 @@
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name> // SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
//! Direct, low-level, access to OpenPGP card functionality.
//!
//! No checks are performed here (e.g. for valid data lengths).
//! Such checks should be performed on a higher layer, if needed.
//!
//! Also, no caching of data is done here. If necessary, caching should
//! be done on a higher layer.
use std::borrow::BorrowMut; use std::borrow::BorrowMut;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::convert::TryInto; use std::convert::TryInto;
@ -28,8 +20,149 @@ use crate::{
PublicKeyMaterial, Sex, PublicKeyMaterial, Sex,
}; };
pub struct ARD(Tlv); /// Application Related Data
///
/// The "application related data" DO contains a set of DOs.
/// This struct offers read access to these DOs.
///
/// Note that when any of the information in this DO changes on the card, you
/// need to read ApplicationRelatedData from the card again to receive the
/// current values.
pub struct ApplicationRelatedData(Tlv);
impl ApplicationRelatedData {
pub fn get_aid(&self) -> Result<ApplicationId, OpenpgpCardError> {
// get from cached "application related data"
let aid = self.0.find(&Tag::from([0x4F]));
if let Some(aid) = aid {
Ok(ApplicationId::try_from(&aid.serialize()[..])?)
} else {
Err(anyhow!("Couldn't get Application ID.").into())
}
}
pub fn get_historical(&self) -> Result<Historical, OpenpgpCardError> {
// get from cached "application related data"
let hist = self.0.find(&Tag::from([0x5F, 0x52]));
if let Some(hist) = hist {
log::debug!("Historical bytes: {:x?}", hist);
Historical::from(&hist.serialize())
} else {
Err(anyhow!("Failed to get historical bytes.").into())
}
}
pub fn get_extended_length_information(
&self,
) -> Result<Option<ExtendedLengthInfo>> {
// get from cached "application related data"
let eli = self.0.find(&Tag::from([0x7F, 0x66]));
log::debug!("Extended length information: {:x?}", eli);
if let Some(eli) = eli {
// The card has returned extended length information
Ok(Some(ExtendedLengthInfo::from(&eli.serialize()[..])?))
} else {
// The card didn't return this (optional) DO. That is ok.
Ok(None)
}
}
pub fn get_general_feature_management() -> Option<bool> {
unimplemented!()
}
pub fn get_discretionary_data_objects() {
unimplemented!()
}
pub fn get_extended_capabilities(
&self,
) -> Result<ExtendedCap, OpenpgpCardError> {
// get from cached "application related data"
let ecap = self.0.find(&Tag::from([0xc0]));
if let Some(ecap) = ecap {
Ok(ExtendedCap::try_from(&ecap.serialize()[..])?)
} else {
Err(anyhow!("Failed to get extended capabilities.").into())
}
}
pub fn get_algorithm_attributes(&self, key_type: KeyType) -> Result<Algo> {
// get from cached "application related data"
let aa = self.0.find(&Tag::from([key_type.get_algorithm_tag()]));
if let Some(aa) = aa {
Algo::try_from(&aa.serialize()[..])
} else {
Err(anyhow!(
"Failed to get algorithm attributes for {:?}.",
key_type
))
}
}
/// PW status Bytes
pub fn get_pw_status_bytes(&self) -> Result<PWStatus> {
// get from cached "application related data"
let psb = self.0.find(&Tag::from([0xc4]));
if let Some(psb) = psb {
let pws = PWStatus::try_from(&psb.serialize())?;
log::debug!("PW Status: {:x?}", pws);
Ok(pws)
} else {
Err(anyhow!("Failed to get PW status Bytes."))
}
}
pub fn get_fingerprints(
&self,
) -> Result<KeySet<Fingerprint>, OpenpgpCardError> {
// Get from cached "application related data"
let fp = self.0.find(&Tag::from([0xc5]));
if let Some(fp) = fp {
let fp = fingerprint::from(&fp.serialize())?;
log::debug!("Fp: {:x?}", fp);
Ok(fp)
} else {
Err(anyhow!("Failed to get fingerprints.").into())
}
}
pub fn get_key_generation_times(
&self,
) -> Result<KeySet<KeyGeneration>, OpenpgpCardError> {
let kg = self.0.find(&Tag::from([0xCD]));
if let Some(kg) = kg {
let kg = key_generation_times::from(&kg.serialize())?;
log::debug!("Key generation: {:x?}", kg);
Ok(kg)
} else {
Err(anyhow!("Failed to get key generation times.").into())
}
}
}
/// Direct, low-level, access to OpenPGP card functionality.
///
/// No checks are performed here (e.g. for valid data lengths).
/// Such checks should be performed on a higher layer, if needed.
///
/// Also, no caching of data is done here. If necessary, caching should
/// be done on a higher layer.
pub struct CardApp { pub struct CardApp {
card_client: CardClientBox, card_client: CardClientBox,
} }
@ -47,7 +180,7 @@ impl CardApp {
/// ///
/// Also initializes the underlying CardClient with the caps - some /// Also initializes the underlying CardClient with the caps - some
/// implementations may need this information. /// implementations may need this information.
pub fn init_caps(&mut self, ard: &ARD) -> Result<()> { pub fn init_caps(&mut self, ard: &ApplicationRelatedData) -> Result<()> {
// Determine chaining/extended length support from card // Determine chaining/extended length support from card
// metadata and cache this information in CardApp (as a // metadata and cache this information in CardApp (as a
// CardCaps) // CardCaps)
@ -55,16 +188,15 @@ impl CardApp {
let mut ext_support = false; let mut ext_support = false;
let mut chaining_support = false; let mut chaining_support = false;
if let Ok(hist) = CardApp::get_historical(ard) { if let Ok(hist) = ard.get_historical() {
if let Some(cc) = hist.get_card_capabilities() { if let Some(cc) = hist.get_card_capabilities() {
chaining_support = cc.get_command_chaining(); chaining_support = cc.get_command_chaining();
ext_support = cc.get_extended_lc_le(); ext_support = cc.get_extended_lc_le();
} }
} }
let (max_cmd_bytes, max_rsp_bytes) = if let Ok(Some(eli)) = let (max_cmd_bytes, max_rsp_bytes) =
CardApp::get_extended_length_information(ard) if let Ok(Some(eli)) = ard.get_extended_length_information() {
{
(eli.max_command_bytes, eli.max_response_bytes) (eli.max_command_bytes, eli.max_response_bytes)
} else { } else {
(255, 255) (255, 255)
@ -102,127 +234,14 @@ impl CardApp {
/// This data should probably cached in a higher layer, some parts of /// This data should probably cached in a higher layer, some parts of
/// it are needed regularly, and it will not usually change, during /// it are needed regularly, and it will not usually change, during
/// normal use of a card. /// normal use of a card.
pub fn get_app_data(&mut self) -> Result<ARD> { pub fn get_app_data(&mut self) -> Result<ApplicationRelatedData> {
let ad = commands::get_application_data(); let ad = commands::get_application_data();
let resp = apdu::send_command(&mut self.card_client, ad, true)?; let resp = apdu::send_command(&mut self.card_client, ad, true)?;
let entry = TlvEntry::from(resp.data()?, true)?; let entry = TlvEntry::from(resp.data()?, true)?;
log::debug!(" App data TlvEntry: {:x?}", entry); log::debug!(" App data TlvEntry: {:x?}", entry);
Ok(ARD(Tlv(Tag::from([0x6E]), entry))) Ok(ApplicationRelatedData(Tlv(Tag::from([0x6E]), entry)))
}
// --- pieces of application related data ---
pub fn get_aid(ard: &ARD) -> Result<ApplicationId, OpenpgpCardError> {
// get from cached "application related data"
let aid = ard.0.find(&Tag::from([0x4F]));
if let Some(aid) = aid {
Ok(ApplicationId::try_from(&aid.serialize()[..])?)
} else {
Err(anyhow!("Couldn't get Application ID.").into())
}
}
pub fn get_historical(ard: &ARD) -> Result<Historical, OpenpgpCardError> {
// get from cached "application related data"
let hist = ard.0.find(&Tag::from([0x5F, 0x52]));
if let Some(hist) = hist {
log::debug!("Historical bytes: {:x?}", hist);
Historical::from(&hist.serialize())
} else {
Err(anyhow!("Failed to get historical bytes.").into())
}
}
pub fn get_extended_length_information(
ard: &ARD,
) -> Result<Option<ExtendedLengthInfo>> {
// get from cached "application related data"
let eli = ard.0.find(&Tag::from([0x7F, 0x66]));
log::debug!("Extended length information: {:x?}", eli);
if let Some(eli) = eli {
// The card has returned extended length information
Ok(Some(ExtendedLengthInfo::from(&eli.serialize()[..])?))
} else {
// The card didn't return this (optional) DO. That is ok.
Ok(None)
}
}
pub fn get_general_feature_management() -> Option<bool> {
unimplemented!()
}
pub fn get_discretionary_data_objects() {
unimplemented!()
}
pub fn get_extended_capabilities(
ard: &ARD,
) -> Result<ExtendedCap, OpenpgpCardError> {
// get from cached "application related data"
let ecap = ard.0.find(&Tag::from([0xc0]));
if let Some(ecap) = ecap {
Ok(ExtendedCap::try_from(&ecap.serialize()[..])?)
} else {
Err(anyhow!("Failed to get extended capabilities.").into())
}
}
pub fn get_algorithm_attributes(
ard: &ARD,
key_type: KeyType,
) -> Result<Algo> {
// get from cached "application related data"
let aa = ard.0.find(&Tag::from([key_type.get_algorithm_tag()]));
if let Some(aa) = aa {
Algo::try_from(&aa.serialize()[..])
} else {
Err(anyhow!(
"Failed to get algorithm attributes for {:?}.",
key_type
))
}
}
/// PW status Bytes
pub fn get_pw_status_bytes(ard: &ARD) -> Result<PWStatus> {
// get from cached "application related data"
let psb = ard.0.find(&Tag::from([0xc4]));
if let Some(psb) = psb {
let pws = PWStatus::try_from(&psb.serialize())?;
log::debug!("PW Status: {:x?}", pws);
Ok(pws)
} else {
Err(anyhow!("Failed to get PW status Bytes."))
}
}
pub fn get_fingerprints(
ard: &ARD,
) -> Result<KeySet<Fingerprint>, OpenpgpCardError> {
// Get from cached "application related data"
let fp = ard.0.find(&Tag::from([0xc5]));
if let Some(fp) = fp {
let fp = fingerprint::from(&fp.serialize())?;
log::debug!("Fp: {:x?}", fp);
Ok(fp)
} else {
Err(anyhow!("Failed to get fingerprints.").into())
}
} }
// --- // ---
@ -231,22 +250,6 @@ impl CardApp {
unimplemented!() unimplemented!()
} }
pub fn get_key_generation_times(
ard: &ARD,
) -> Result<KeySet<KeyGeneration>, OpenpgpCardError> {
let kg = ard.0.find(&Tag::from([0xCD]));
if let Some(kg) = kg {
let kg = key_generation_times::from(&kg.serialize())?;
log::debug!("Key generation: {:x?}", kg);
Ok(kg)
} else {
Err(anyhow!("Failed to get key generation times.").into())
}
}
pub fn get_key_information() { pub fn get_key_information() {
unimplemented!() unimplemented!()
} }
@ -575,7 +578,7 @@ impl CardApp {
let ard = self.get_app_data()?; let ard = self.get_app_data()?;
// FIXME: reuse "e" from card, if no algo list is available // FIXME: reuse "e" from card, if no algo list is available
let _cur_algo = Self::get_algorithm_attributes(&ard, key_type)?; let _cur_algo = ard.get_algorithm_attributes(key_type)?;
let data = match algo { let data = match algo {
Algo::Rsa(rsa) => Self::rsa_algo_attrs(rsa)?, Algo::Rsa(rsa) => Self::rsa_algo_attrs(rsa)?,

View file

@ -37,7 +37,7 @@ pub(crate) fn gen_key_with_metadata(
// algo // algo
let ard = card_app.get_app_data()?; // no caching, here! let ard = card_app.get_app_data()?; // no caching, here!
let algo = CardApp::get_algorithm_attributes(&ard, key_type)?; let algo = ard.get_algorithm_attributes(key_type)?;
// generate key // generate key
let tlv = gen_key(card_app, key_type)?; let tlv = gen_key(card_app, key_type)?;
@ -124,7 +124,7 @@ pub(crate) fn get_pub_key(
// algo // algo
let ard = card_app.get_app_data()?; // FIXME: caching let ard = card_app.get_app_data()?; // FIXME: caching
let algo = CardApp::get_algorithm_attributes(&ard, key_type)?; let algo = ard.get_algorithm_attributes(key_type)?;
// get public key // get public key
let crt = get_crt(key_type)?; let crt = get_crt(key_type)?;
@ -166,7 +166,7 @@ pub(crate) fn upload_key(
// FIXME: caching? // FIXME: caching?
let ard = card_app.get_app_data()?; let ard = card_app.get_app_data()?;
let algo = CardApp::get_algorithm_attributes(&ard, key_type)?; let algo = ard.get_algorithm_attributes(key_type)?;
if let Algo::Rsa(mut rsa) = algo { if let Algo::Rsa(mut rsa) = algo {
rsa.len_n = rsa_bits; rsa.len_n = rsa_bits;

View file

@ -10,10 +10,6 @@
//! - access to all features in the OpenPGP card specification, //! - access to all features in the OpenPGP card specification,
//! - without relying on a particular OpenPGP implementation. //! - without relying on a particular OpenPGP implementation.
//! //!
//! The [openpgp-card-sequoia](https://crates.io/crates/openpgp-card-sequoia)
//! crate offers a higher level wrapper based on the
//! [Sequoia PGP](https://sequoia-pgp.org/) implementation.
//!
//! This library doesn't itself implement a means to access cards. Instead, //! This library doesn't itself implement a means to access cards. Instead,
//! users need to supply an implementation of the [`CardClient`] trait, for //! users need to supply an implementation of the [`CardClient`] trait, for
//! access to cards. //! access to cards.
@ -22,6 +18,10 @@
//! [openpgp-card-pcsc](https://crates.io/crates/openpgp-card-pcsc) //! [openpgp-card-pcsc](https://crates.io/crates/openpgp-card-pcsc)
//! offers a backend that uses [pcsclite](https://pcsclite.apdu.fr/) to //! offers a backend that uses [pcsclite](https://pcsclite.apdu.fr/) to
//! communicate with smartcards. //! communicate with smartcards.
//!
//! The [openpgp-card-sequoia](https://crates.io/crates/openpgp-card-sequoia)
//! crate offers a higher level wrapper based on the
//! [Sequoia PGP](https://sequoia-pgp.org/) implementation.
use anyhow::Result; use anyhow::Result;
use std::collections::HashSet; use std::collections::HashSet;
@ -29,13 +29,17 @@ use std::collections::HashSet;
use crate::algorithm::Algo; use crate::algorithm::Algo;
pub mod algorithm; pub mod algorithm;
pub mod apdu; mod apdu;
pub mod card_app; mod card_app;
pub mod errors; pub mod errors;
mod keys; mod keys;
mod parse; mod parse;
mod tlv; mod tlv;
pub use crate::apdu::response::Response;
pub use crate::card_app::ApplicationRelatedData;
pub use crate::card_app::CardApp;
/// The CardClient trait defines communication with an OpenPGP card via a /// The CardClient trait defines communication with an OpenPGP card via a
/// backend implementation (e.g. the pcsc backend in the crate /// backend implementation (e.g. the pcsc backend in the crate
/// openpgp-card-pcsc). /// openpgp-card-pcsc).

View file

@ -4,9 +4,8 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use pcsc::{Card, Context, Error, Protocols, Scope, ShareMode}; use pcsc::{Card, Context, Error, Protocols, Scope, ShareMode};
use openpgp_card::card_app::CardApp;
use openpgp_card::errors::{OpenpgpCardError, SmartcardError}; use openpgp_card::errors::{OpenpgpCardError, SmartcardError};
use openpgp_card::{CardCaps, CardClient, CardClientBox}; use openpgp_card::{CardApp, CardCaps, CardClient, CardClientBox};
pub struct PcscClient { pub struct PcscClient {
card: Card, card: Card,
@ -131,7 +130,7 @@ impl PcscClient {
ident: &str, ident: &str,
) -> Result<Option<CardClientBox>, OpenpgpCardError> { ) -> Result<Option<CardClientBox>, OpenpgpCardError> {
let ard = ca.get_app_data()?; let ard = ca.get_app_data()?;
let aid = CardApp::get_aid(&ard)?; let aid = ard.get_aid()?;
if aid.ident() == ident { if aid.ident() == ident {
Ok(Some(ca.take_card())) Ok(Some(ca.take_card()))