From e01c79e8574b5a2106b023892bbc154589df0a87 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 18 Feb 2022 11:11:37 +0100 Subject: [PATCH] Tweak ergonomics of openpgp-card-pcsc usage and simplify client code. --- card-functionality/src/cards.rs | 12 ++++---- card-functionality/src/list-cards.rs | 2 +- card-functionality/src/tests.rs | 7 ++--- openpgp-card-examples/src/bin/decrypt.rs | 2 +- openpgp-card-examples/src/bin/detach-sign.rs | 2 +- openpgp-card-sequoia/src/lib.rs | 30 ++++++++++---------- openpgp-card-sequoia/src/main.rs | 3 +- pcsc/src/lib.rs | 24 ++++++++++------ tools/src/bin/opgpcard/main.rs | 1 - tools/src/bin/opgpcard/util.rs | 8 ++++-- 10 files changed, 47 insertions(+), 44 deletions(-) diff --git a/card-functionality/src/cards.rs b/card-functionality/src/cards.rs index 34b5025..d4daf59 100644 --- a/card-functionality/src/cards.rs +++ b/card-functionality/src/cards.rs @@ -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> { + pub(crate) fn get_card(&self) -> Result> { self.tc.open() } @@ -92,7 +92,7 @@ pub enum TestCard { } impl TestCard { - pub fn open(&self) -> Result> { + pub fn open(&self) -> Result> { 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 = loop { + let card: Result, 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!(); diff --git a/card-functionality/src/list-cards.rs b/card-functionality/src/list-cards.rs index ff500a5..4fd417c 100644 --- a/card-functionality/src/list-cards.rs +++ b/card-functionality/src/list-cards.rs @@ -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 = ::transaction(&mut card)?; + let mut txc = card.transaction()?; let open = Open::new(&mut *txc)?; println!(" {}", open.application_identifier()?.ident()); diff --git a/card-functionality/src/tests.rs b/card-functionality/src/tests.rs index ea36cdb..db868de 100644 --- a/card-functionality/src/tests.rs +++ b/card-functionality/src/tests.rs @@ -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 { let mut card = tc.get_card()?; - let mut txc = - ::transaction(&mut *card).map_err(|e| anyhow!(e))?; + let mut txc = card.transaction().map_err(|e| anyhow!(e))?; t(&mut *txc, param) } diff --git a/openpgp-card-examples/src/bin/decrypt.rs b/openpgp-card-examples/src/bin/decrypt.rs index f14e13a..1ce5f81 100644 --- a/openpgp-card-examples/src/bin/decrypt.rs +++ b/openpgp-card-examples/src/bin/decrypt.rs @@ -23,7 +23,7 @@ fn main() -> Result<(), Box> { let cert_file = &args[2]; let mut card = PcscCard::open_by_ident(card_ident, None)?; - let mut txc = ::transaction(&mut card)?; + let mut txc = card.transaction()?; let mut open = Open::new(&mut *txc)?; diff --git a/openpgp-card-examples/src/bin/detach-sign.rs b/openpgp-card-examples/src/bin/detach-sign.rs index 6cbd38b..3632fa9 100644 --- a/openpgp-card-examples/src/bin/detach-sign.rs +++ b/openpgp-card-examples/src/bin/detach-sign.rs @@ -23,7 +23,7 @@ fn main() -> Result<(), Box> { let cert_file = &args[2]; let mut card = PcscCard::open_by_ident(card_ident, None)?; - let mut txc = ::transaction(&mut card)?; + let mut txc = card.transaction()?; let mut open = Open::new(&mut *txc)?; diff --git a/openpgp-card-sequoia/src/lib.rs b/openpgp-card-sequoia/src/lib.rs index 1b7fe11..b50605e 100644 --- a/openpgp-card-sequoia/src/lib.rs +++ b/openpgp-card-sequoia/src/lib.rs @@ -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> { -//! # use openpgp_card::CardBackend; //! for mut card in PcscCard::cards(None)? { -//! let mut txc = ::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> { -//! # use openpgp_card::CardBackend; //! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; -//! let mut txc = ::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> { //! // 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 = ::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> { -//! # 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 = ::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> { -//! # use openpgp_card::CardBackend; //! // Open card via PCSC //! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; -//! let mut txc = ::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 diff --git a/openpgp-card-sequoia/src/main.rs b/openpgp-card-sequoia/src/main.rs index 508d4d5..0a43a76 100644 --- a/openpgp-card-sequoia/src/main.rs +++ b/openpgp-card-sequoia/src/main.rs @@ -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; diff --git a/pcsc/src/lib.rs b/pcsc/src/lib.rs index 0c3ede0..a38b4f9 100644 --- a/pcsc/src/lib.rs +++ b/pcsc/src/lib.rs @@ -40,6 +40,12 @@ pub struct PcscCard { reader_caps: HashMap, } +impl From for Box { + fn from(card: PcscCard) -> Box { + Box::new(card) as Box + } +} + /// 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, Error> { - let mut cas: Vec = vec![]; + ) -> Result, Error> { + let mut cards: Vec = 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) -> Result, Error> { + pub fn cards(mode: Option) -> Result, Error> { Self::cards_filter(None, default_mode(mode)) } @@ -611,7 +617,7 @@ impl PcscCard { pub fn open_by_ident( ident: &str, mode: Option, - ) -> Result { + ) -> Result { log::debug!("open_by_ident for {:?}", ident); let mut cards = Self::cards_filter(Some(ident), default_mode(mode))?; diff --git a/tools/src/bin/opgpcard/main.rs b/tools/src/bin/opgpcard/main.rs index b2cef1f..067c704 100644 --- a/tools/src/bin/opgpcard/main.rs +++ b/tools/src/bin/opgpcard/main.rs @@ -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}; diff --git a/tools/src/bin/opgpcard/util.rs b/tools/src/bin/opgpcard/util.rs index c89634d..24a786c 100644 --- a/tools/src/bin/opgpcard/util.rs +++ b/tools/src/bin/opgpcard/util.rs @@ -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, Error> { +pub(crate) fn cards() -> Result>, Error> { PcscCard::cards(None) + .map(|cards| cards.into_iter().map(Into::into).collect()) } -pub(crate) fn open_card(ident: &str) -> Result { +pub(crate) fn open_card(ident: &str) -> Result, Error> { PcscCard::open_by_ident(ident, None) + .map(|pc| Box::new(pc) as Box) } pub(crate) fn verify_to_user<'app, 'open>(