Tweak ergonomics of openpgp-card-pcsc usage and simplify client code.

This commit is contained in:
Heiko Schaefer 2022-02-18 11:11:37 +01:00
parent 635fa0e6ac
commit e01c79e857
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
10 changed files with 47 additions and 44 deletions

View file

@ -9,7 +9,7 @@ use pcsc::ShareMode;
use serde_derive::Deserialize;
use std::collections::BTreeMap;
use openpgp_card::Error;
use openpgp_card::{CardBackend, Error};
use openpgp_card_pcsc::PcscCard;
use openpgp_card_scdc::ScdClient;
@ -41,7 +41,7 @@ pub struct TestCardData {
}
impl TestCardData {
pub(crate) fn get_card(&self) -> Result<Box<PcscCard>> {
pub(crate) fn get_card(&self) -> Result<Box<dyn CardBackend>> {
self.tc.open()
}
@ -92,7 +92,7 @@ pub enum TestCard {
}
impl TestCard {
pub fn open(&self) -> Result<Box<PcscCard>> {
pub fn open(&self) -> Result<Box<dyn CardBackend>> {
match self {
Self::Pcsc(ident) => {
// Attempt to shutdown SCD, if it is running.
@ -103,11 +103,11 @@ impl TestCard {
// Make three attempts to open the card before failing
// (this can be useful in ShareMode::Exclusive)
let mut i = 1;
let card: Result<PcscCard, Error> = loop {
let card: Result<Box<dyn CardBackend>, Error> = loop {
let res = PcscCard::open_by_ident(ident, SHARE_MODE);
if i == 3 || res.is_ok() {
break res;
break res.map(Into::into);
}
// sleep for 100ms
@ -116,7 +116,7 @@ impl TestCard {
i += 1;
};
Ok(Box::new(card?))
Ok(card?)
}
Self::Scdc(serial) => {
unimplemented!();

View file

@ -11,7 +11,7 @@ fn main() -> Result<()> {
println!("The following OpenPGP cards are connected to your system:");
for mut card in PcscCard::cards(None)? {
let mut txc = <dyn CardBackend>::transaction(&mut card)?;
let mut txc = card.transaction()?;
let open = Open::new(&mut *txc)?;
println!(" {}", open.application_identifier()?.ident());

View file

@ -15,9 +15,7 @@ use sequoia_openpgp::Cert;
use openpgp_card;
use openpgp_card::algorithm::AlgoSimple;
use openpgp_card::card_do::{KeyGenerationTime, Sex};
use openpgp_card::{
CardBackend, CardTransaction, Error, KeyType, StatusBytes,
};
use openpgp_card::{CardTransaction, Error, KeyType, StatusBytes};
use openpgp_card_sequoia::card::Open;
use openpgp_card_sequoia::util::{
make_cert, public_key_material_to_key, public_to_fingerprint,
@ -680,8 +678,7 @@ pub fn run_test(
param: &[&str],
) -> Result<TestOutput, TestError> {
let mut card = tc.get_card()?;
let mut txc =
<dyn CardBackend>::transaction(&mut *card).map_err(|e| anyhow!(e))?;
let mut txc = card.transaction().map_err(|e| anyhow!(e))?;
t(&mut *txc, param)
}

View file

@ -23,7 +23,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let cert_file = &args[2];
let mut card = PcscCard::open_by_ident(card_ident, None)?;
let mut txc = <dyn CardBackend>::transaction(&mut card)?;
let mut txc = card.transaction()?;
let mut open = Open::new(&mut *txc)?;

View file

@ -23,7 +23,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let cert_file = &args[2];
let mut card = PcscCard::open_by_ident(card_ident, None)?;
let mut txc = <dyn CardBackend>::transaction(&mut card)?;
let mut txc = card.transaction()?;
let mut open = Open::new(&mut *txc)?;

View file

@ -12,13 +12,13 @@
//! With `openpgp-card-pcsc` you can either open all available cards:
//!
//! ```no_run
//! use openpgp_card_sequoia::card::Open;
//! use openpgp_card_pcsc::PcscCard;
//! use openpgp_card::CardBackend;
//! use openpgp_card_sequoia::card::Open;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # use openpgp_card::CardBackend;
//! for mut card in PcscCard::cards(None)? {
//! let mut txc = <dyn CardBackend>::transaction(&mut card)?;
//! let mut txc = card.transaction()?;
//! let open = Open::new(&mut *txc)?;
//! println!("Found OpenPGP card with ident '{}'",
//! open.application_identifier()?.ident());
@ -30,13 +30,13 @@
//! Or you can open one particular card, by ident:
//!
//! ```no_run
//! use openpgp_card_sequoia::card::Open;
//! use openpgp_card_pcsc::PcscCard;
//! use openpgp_card::CardBackend;
//! use openpgp_card_sequoia::card::Open;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # use openpgp_card::CardBackend;
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
//! let mut txc = <dyn CardBackend>::transaction(&mut card)?;
//! let mut txc = card.transaction()?;
//! let mut open = Open::new(&mut *txc)?;
//! # Ok(())
//! # }
@ -52,15 +52,15 @@
//! that corresponds to the private encryption key on the card:
//!
//! ```no_run
//! use openpgp_card_sequoia::card::Open;
//! use openpgp_card_pcsc::PcscCard;
//! use openpgp_card::CardBackend;
//! use openpgp_card_sequoia::card::Open;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Open card via PCSC
//! use sequoia_openpgp::policy::StandardPolicy;
//! # use openpgp_card::CardBackend;
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
//! let mut txc = <dyn CardBackend>::transaction(&mut card)?;
//! let mut txc = card.transaction()?;
//! let mut open = Open::new(&mut *txc)?;
//!
//! // Get authorization for user access to the card with password
@ -95,15 +95,15 @@
//! user password before each signing operation!)
//!
//! ```no_run
//! use openpgp_card_sequoia::card::Open;
//! use openpgp_card_pcsc::PcscCard;
//! use openpgp_card::CardBackend;
//! use openpgp_card_sequoia::card::Open;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # use openpgp_card::CardBackend;
//! // Open card via PCSC
//! use sequoia_openpgp::policy::StandardPolicy;
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
//! let mut txc = <dyn CardBackend>::transaction(&mut card)?;
//! let mut txc = card.transaction()?;
//! let mut open = Open::new(&mut *txc)?;
//!
//! // Get authorization for signing access to the card with password
@ -128,14 +128,14 @@
//! # Setting up and configuring a card
//!
//! ```no_run
//! use openpgp_card_sequoia::card::Open;
//! use openpgp_card_pcsc::PcscCard;
//! use openpgp_card::CardBackend;
//! use openpgp_card_sequoia::card::Open;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # use openpgp_card::CardBackend;
//! // Open card via PCSC
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
//! let mut txc = <dyn CardBackend>::transaction(&mut card)?;
//! let mut txc = card.transaction()?;
//! let mut open = Open::new(&mut *txc)?;
//!
//! // Get authorization for admin access to the card with password

View file

@ -10,8 +10,7 @@ use sequoia_openpgp::policy::StandardPolicy;
use sequoia_openpgp::Cert;
use openpgp_card::card_do::Sex;
use openpgp_card::CardBackend;
use openpgp_card::KeyType;
use openpgp_card::{CardBackend, KeyType};
use openpgp_card_pcsc::PcscCard;
use openpgp_card_sequoia::card::Open;

View file

@ -40,6 +40,12 @@ pub struct PcscCard {
reader_caps: HashMap<u8, Tlv>,
}
impl From<PcscCard> for Box<dyn CardBackend> {
fn from(card: PcscCard) -> Box<dyn CardBackend> {
Box::new(card) as Box<dyn CardBackend>
}
}
/// An implementation of the CardTransaction trait that uses the PCSC lite
/// middleware to access the OpenPGP card application on smart cards, via a
/// PCSC "transaction".
@ -446,11 +452,11 @@ impl CardTransaction for TxClient<'_> {
}
impl PcscCard {
pub fn card(&mut self) -> &mut Card {
fn card(&mut self) -> &mut Card {
&mut self.card
}
pub fn mode(&self) -> ShareMode {
fn mode(&self) -> ShareMode {
self.mode
}
@ -529,8 +535,8 @@ impl PcscCard {
fn cards_filter(
ident: Option<&str>,
mode: ShareMode,
) -> Result<Vec<PcscCard>, Error> {
let mut cas: Vec<PcscCard> = vec![];
) -> Result<Vec<Self>, Error> {
let mut cards: Vec<Self> = vec![];
for mut card in
Self::raw_pcsc_cards(mode).map_err(|sce| Error::Smartcard(sce))?
@ -588,20 +594,20 @@ impl PcscCard {
if store_card {
let pcsc = PcscCard::new(card, mode);
cas.push(pcsc.initialize_card()?);
cards.push(pcsc.initialize_card()?);
}
}
log::debug!("cards_filter: found {} cards", cas.len());
log::debug!("cards_filter: found {} cards", cards.len());
Ok(cas)
Ok(cards)
}
/// Return all cards on which the OpenPGP application could be selected.
///
/// Each card has the OpenPGP application selected, card_caps and reader_caps have been
/// initialized.
pub fn cards(mode: Option<ShareMode>) -> Result<Vec<PcscCard>, Error> {
pub fn cards(mode: Option<ShareMode>) -> Result<Vec<Self>, Error> {
Self::cards_filter(None, default_mode(mode))
}
@ -611,7 +617,7 @@ impl PcscCard {
pub fn open_by_ident(
ident: &str,
mode: Option<ShareMode>,
) -> Result<PcscCard, Error> {
) -> Result<Self, Error> {
log::debug!("open_by_ident for {:?}", ident);
let mut cards = Self::cards_filter(Some(ident), default_mode(mode))?;

View file

@ -12,7 +12,6 @@ use sequoia_openpgp::serialize::SerializeInto;
use sequoia_openpgp::Cert;
use openpgp_card::algorithm::AlgoSimple;
use openpgp_card::CardBackend;
use openpgp_card::{card_do::Sex, KeyType};
use openpgp_card_sequoia::card::{Admin, Open};

View file

@ -6,16 +6,18 @@ use std::path::{Path, PathBuf};
use openpgp_card::algorithm::{Algo, Curve};
use openpgp_card::crypto_data::{EccType, PublicKeyMaterial};
use openpgp_card::Error;
use openpgp_card::{CardBackend, Error};
use openpgp_card_pcsc::PcscCard;
use openpgp_card_sequoia::card::{Admin, Open, Sign, User};
pub(crate) fn cards() -> Result<Vec<PcscCard>, Error> {
pub(crate) fn cards() -> Result<Vec<Box<dyn CardBackend>>, Error> {
PcscCard::cards(None)
.map(|cards| cards.into_iter().map(Into::into).collect())
}
pub(crate) fn open_card(ident: &str) -> Result<PcscCard, Error> {
pub(crate) fn open_card(ident: &str) -> Result<Box<dyn CardBackend>, Error> {
PcscCard::open_by_ident(ident, None)
.map(|pc| Box::new(pc) as Box<dyn CardBackend>)
}
pub(crate) fn verify_to_user<'app, 'open>(