Refactor: move accessor fn for "Application Related Data" into the struct ApplicationRelatedData.
This commit is contained in:
parent
50499dc15d
commit
c872e46e80
11 changed files with 201 additions and 201 deletions
|
@ -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)?;
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,20 +188,19 @@ 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)
|
};
|
||||||
};
|
|
||||||
|
|
||||||
let caps = CardCaps {
|
let caps = CardCaps {
|
||||||
ext_support,
|
ext_support,
|
||||||
|
@ -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)?,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
Loading…
Reference in a new issue