From c23f23c6194335f8173547617289dca068fa689b Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Thu, 17 Feb 2022 20:22:52 +0100 Subject: [PATCH] Introduce the new CardBackend trait. A CardBackend represents a card without an open transaction (a CardTransaction implementation can be acquired from a CardBackend). --- card-functionality/src/list-cards.rs | 5 ++-- card-functionality/src/tests.rs | 9 ++++--- openpgp-card-examples/src/bin/decrypt.rs | 6 ++--- openpgp-card-examples/src/bin/detach-sign.rs | 6 ++--- openpgp-card-sequoia/src/lib.rs | 25 ++++++++++++-------- openpgp-card-sequoia/src/main.rs | 9 +++---- openpgp-card/src/lib.rs | 6 +++++ pcsc/src/lib.rs | 22 ++++++++++------- tools/src/bin/opgpcard-pin/main.rs | 4 ++-- tools/src/bin/opgpcard/main.rs | 17 ++++++------- 10 files changed, 66 insertions(+), 43 deletions(-) diff --git a/card-functionality/src/list-cards.rs b/card-functionality/src/list-cards.rs index d94fdd0..ff500a5 100644 --- a/card-functionality/src/list-cards.rs +++ b/card-functionality/src/list-cards.rs @@ -3,6 +3,7 @@ use anyhow::Result; +use openpgp_card::CardBackend; use openpgp_card_pcsc::PcscCard; use openpgp_card_sequoia::card::Open; @@ -10,9 +11,9 @@ fn main() -> Result<()> { println!("The following OpenPGP cards are connected to your system:"); for mut card in PcscCard::cards(None)? { - let mut txc = card.transaction()?; + let mut txc = ::transaction(&mut card)?; - let open = Open::new(&mut txc)?; + 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 02c4b18..ea36cdb 100644 --- a/card-functionality/src/tests.rs +++ b/card-functionality/src/tests.rs @@ -15,7 +15,9 @@ use sequoia_openpgp::Cert; use openpgp_card; use openpgp_card::algorithm::AlgoSimple; use openpgp_card::card_do::{KeyGenerationTime, Sex}; -use openpgp_card::{CardTransaction, Error, KeyType, StatusBytes}; +use openpgp_card::{ + CardBackend, 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, @@ -678,7 +680,8 @@ pub fn run_test( param: &[&str], ) -> Result { let mut card = tc.get_card()?; - let mut txc = card.transaction().map_err(|e| anyhow!(e))?; + let mut txc = + ::transaction(&mut *card).map_err(|e| anyhow!(e))?; - t(&mut txc, param) + t(&mut *txc, param) } diff --git a/openpgp-card-examples/src/bin/decrypt.rs b/openpgp-card-examples/src/bin/decrypt.rs index 89819f1..f14e13a 100644 --- a/openpgp-card-examples/src/bin/decrypt.rs +++ b/openpgp-card-examples/src/bin/decrypt.rs @@ -1,8 +1,8 @@ // SPDX-FileCopyrightText: 2021 Wiktor Kwapisiewicz // SPDX-License-Identifier: MIT OR Apache-2.0 +use openpgp_card::CardBackend; use openpgp_card_pcsc::PcscCard; - use openpgp_card_sequoia::card::Open; use openpgp::parse::{stream::DecryptorBuilder, Parse}; @@ -23,9 +23,9 @@ fn main() -> Result<(), Box> { let cert_file = &args[2]; let mut card = PcscCard::open_by_ident(card_ident, None)?; - let mut txc = card.transaction()?; + let mut txc = ::transaction(&mut card)?; - let mut open = Open::new(&mut txc)?; + let mut open = Open::new(&mut *txc)?; let pin = std::fs::read_to_string(pin_file)?; diff --git a/openpgp-card-examples/src/bin/detach-sign.rs b/openpgp-card-examples/src/bin/detach-sign.rs index 114f9a9..6cbd38b 100644 --- a/openpgp-card-examples/src/bin/detach-sign.rs +++ b/openpgp-card-examples/src/bin/detach-sign.rs @@ -1,8 +1,8 @@ // SPDX-FileCopyrightText: 2021 Wiktor Kwapisiewicz // SPDX-License-Identifier: MIT OR Apache-2.0 +use openpgp_card::CardBackend; use openpgp_card_pcsc::PcscCard; - use openpgp_card_sequoia::card::Open; use openpgp::parse::Parse; @@ -23,9 +23,9 @@ fn main() -> Result<(), Box> { let cert_file = &args[2]; let mut card = PcscCard::open_by_ident(card_ident, None)?; - let mut txc = card.transaction()?; + let mut txc = ::transaction(&mut card)?; - let mut open = Open::new(&mut txc)?; + let mut open = Open::new(&mut *txc)?; let pin = std::fs::read_to_string(pin_file)?; diff --git a/openpgp-card-sequoia/src/lib.rs b/openpgp-card-sequoia/src/lib.rs index 7c02bad..1b7fe11 100644 --- a/openpgp-card-sequoia/src/lib.rs +++ b/openpgp-card-sequoia/src/lib.rs @@ -16,9 +16,10 @@ //! use openpgp_card_pcsc::PcscCard; //! //! # fn main() -> Result<(), Box> { +//! # use openpgp_card::CardBackend; //! for mut card in PcscCard::cards(None)? { -//! let mut txc = card.transaction()?; -//! let open = Open::new(&mut txc)?; +//! let mut txc = ::transaction(&mut card)?; +//! let open = Open::new(&mut *txc)?; //! println!("Found OpenPGP card with ident '{}'", //! open.application_identifier()?.ident()); //! } @@ -33,9 +34,10 @@ //! use openpgp_card_pcsc::PcscCard; //! //! # fn main() -> Result<(), Box> { +//! # use openpgp_card::CardBackend; //! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; -//! let mut txc = card.transaction()?; -//! let mut open = Open::new(&mut txc)?; +//! let mut txc = ::transaction(&mut card)?; +//! let mut open = Open::new(&mut *txc)?; //! # Ok(()) //! # } //! ``` @@ -56,9 +58,10 @@ //! # 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 = card.transaction()?; -//! let mut open = Open::new(&mut txc)?; +//! let mut txc = ::transaction(&mut card)?; +//! let mut open = Open::new(&mut *txc)?; //! //! // Get authorization for user access to the card with password //! open.verify_user("123456")?; @@ -96,11 +99,12 @@ //! use openpgp_card_pcsc::PcscCard; //! //! # 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 = card.transaction()?; -//! let mut open = Open::new(&mut txc)?; +//! let mut txc = ::transaction(&mut card)?; +//! let mut open = Open::new(&mut *txc)?; //! //! // Get authorization for signing access to the card with password //! open.verify_user_for_signing("123456")?; @@ -128,10 +132,11 @@ //! use openpgp_card_pcsc::PcscCard; //! //! # 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 = card.transaction()?; -//! let mut open = Open::new(&mut txc)?; +//! let mut txc = ::transaction(&mut card)?; +//! let mut open = Open::new(&mut *txc)?; //! //! // Get authorization for admin access to the card with password //! open.verify_admin("12345678")?; diff --git a/openpgp-card-sequoia/src/main.rs b/openpgp-card-sequoia/src/main.rs index f3e0bc1..508d4d5 100644 --- a/openpgp-card-sequoia/src/main.rs +++ b/openpgp-card-sequoia/src/main.rs @@ -10,6 +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_pcsc::PcscCard; @@ -38,7 +39,7 @@ fn main() -> Result<(), Box> { let mut card = PcscCard::open_by_ident(&test_card_ident, None)?; let mut txc = card.transaction()?; - let mut open = Open::new(&mut txc)?; + let mut open = Open::new(&mut *txc)?; // card metadata @@ -149,7 +150,7 @@ fn main() -> Result<(), Box> { let mut card = PcscCard::open_by_ident(&test_card_ident, None)?; let mut txc = card.transaction()?; - let mut open = Open::new(&mut txc)?; + let mut open = Open::new(&mut *txc)?; // Check that we're still using the expected card let app_id = open.application_identifier()?; @@ -190,7 +191,7 @@ fn main() -> Result<(), Box> { let mut card = PcscCard::open_by_ident(&test_card_ident, None)?; let mut txc = card.transaction()?; - let mut open = Open::new(&mut txc)?; + let mut open = Open::new(&mut *txc)?; // Sign open.verify_user_for_signing("123456")?; @@ -222,7 +223,7 @@ fn main() -> Result<(), Box> { for mut card in PcscCard::cards(None)? { let mut txc = card.transaction()?; - let open = Open::new(&mut txc)?; + let open = Open::new(&mut *txc)?; println!(" {}", open.application_identifier()?.ident()); } } diff --git a/openpgp-card/src/lib.rs b/openpgp-card/src/lib.rs index 95dd0a7..81934f0 100644 --- a/openpgp-card/src/lib.rs +++ b/openpgp-card/src/lib.rs @@ -55,6 +55,12 @@ use crate::tlv::tag::Tag; use crate::tlv::value::Value; use crate::tlv::Tlv; +pub trait CardBackend { + fn transaction( + &mut self, + ) -> Result, Error>; +} + /// The CardTransaction trait defines communication with an OpenPGP card via a /// backend implementation (e.g. the pcsc backend in the crate /// [openpgp-card-pcsc](https://crates.io/crates/openpgp-card-pcsc)), diff --git a/pcsc/src/lib.rs b/pcsc/src/lib.rs index db2fd1a..8f1ecdb 100644 --- a/pcsc/src/lib.rs +++ b/pcsc/src/lib.rs @@ -12,7 +12,9 @@ use std::collections::HashMap; use std::convert::TryInto; use openpgp_card::card_do::ApplicationRelatedData; -use openpgp_card::{CardCaps, CardTransaction, Error, SmartcardError}; +use openpgp_card::{ + CardBackend, CardCaps, CardTransaction, Error, SmartcardError, +}; const FEATURE_VERIFY_PIN_DIRECT: u8 = 0x06; const FEATURE_MODIFY_PIN_DIRECT: u8 = 0x07; @@ -61,7 +63,7 @@ impl<'b> TxClient<'b> { /// `reselect` set to `false` is only used internally in this crate, /// during initial setup of cards. Otherwise it must be `true`, to /// cause a select() call on cards that have been reset. - fn new(card: &'b mut PcscCard, reselect: bool) -> Result { + fn new(card: &'b mut PcscCard, reselect: bool) -> Result { use pcsc::Disposition; let mut was_reset = false; @@ -452,11 +454,6 @@ impl PcscCard { self.mode } - /// Get a TxClient for this PcscCard (this starts a transaction) - pub fn transaction(&mut self) -> Result { - TxClient::new(self, true) - } - /// A list of "raw" opened PCSC Cards (without selecting the OpenPGP card /// application) fn raw_pcsc_cards(mode: ShareMode) -> Result, SmartcardError> { @@ -647,7 +644,7 @@ impl PcscCard { let mut h: HashMap = HashMap::default(); - let mut txc = self.transaction()?; + let mut txc = TxClient::new(&mut self, true)?; // Get Features from reader (pinpad verify/modify) if let Ok(feat) = txc.features() { @@ -680,3 +677,12 @@ impl PcscCard { self.reader_caps.clone() } } + +impl CardBackend for PcscCard { + /// Get a TxClient for this PcscCard (this starts a transaction) + fn transaction( + &mut self, + ) -> Result, Error> { + Ok(Box::new(TxClient::new(self, true)?)) + } +} diff --git a/tools/src/bin/opgpcard-pin/main.rs b/tools/src/bin/opgpcard-pin/main.rs index d5075db..dea8b10 100644 --- a/tools/src/bin/opgpcard-pin/main.rs +++ b/tools/src/bin/opgpcard-pin/main.rs @@ -4,7 +4,7 @@ use anyhow::Result; use structopt::StructOpt; -use openpgp_card::{CardTransaction, Error, StatusBytes}; +use openpgp_card::{CardBackend, Error, StatusBytes}; use openpgp_card_pcsc::PcscCard; use openpgp_card_sequoia::card::Open; @@ -21,7 +21,7 @@ fn main() -> Result<(), Box> { let pinpad_verify = txc.feature_pinpad_verify(); let pinpad_modify = txc.feature_pinpad_modify(); - let mut open = Open::new(&mut txc)?; + let mut open = Open::new(&mut *txc)?; match cli.cmd { cli::Command::SetUserPin {} => { diff --git a/tools/src/bin/opgpcard/main.rs b/tools/src/bin/opgpcard/main.rs index aaa1df4..b2cef1f 100644 --- a/tools/src/bin/opgpcard/main.rs +++ b/tools/src/bin/opgpcard/main.rs @@ -12,7 +12,8 @@ use sequoia_openpgp::serialize::SerializeInto; use sequoia_openpgp::Cert; use openpgp_card::algorithm::AlgoSimple; -use openpgp_card::{card_do::Sex, CardTransaction, KeyType}; +use openpgp_card::CardBackend; +use openpgp_card::{card_do::Sex, KeyType}; use openpgp_card_sequoia::card::{Admin, Open}; use openpgp_card_sequoia::util::{make_cert, public_key_material_to_key}; @@ -73,7 +74,7 @@ fn main() -> Result<(), Box> { let mut card = util::open_card(&ident)?; let mut txc = card.transaction()?; - let mut open = Open::new(&mut txc)?; + let mut open = Open::new(&mut *txc)?; match cmd { cli::AdminCommand::Name { name } => { @@ -140,7 +141,7 @@ fn list_cards() -> Result<()> { for mut card in cards { let mut txc = card.transaction()?; - let open = Open::new(&mut txc)?; + let open = Open::new(&mut *txc)?; println!(" {}", open.application_identifier()?.ident()); } } else { @@ -156,7 +157,7 @@ fn set_identity( let mut card = util::open_card(ident)?; let mut txc = card.transaction()?; - ::set_identity(&mut txc, id)?; + txc.set_identity(id)?; Ok(()) } @@ -175,7 +176,7 @@ fn print_status(ident: Option, verbose: bool) -> Result<()> { let mut txc = card.transaction()?; - let mut open = Open::new(&mut txc)?; + let mut open = Open::new(&mut *txc)?; let ident = open.application_identifier()?.ident(); @@ -336,7 +337,7 @@ fn decrypt( let mut card = util::open_card(ident)?; let mut txc = card.transaction()?; - let mut open = Open::new(&mut txc)?; + let mut open = Open::new(&mut *txc)?; let mut user = util::verify_to_user(&mut open, pin_file)?; let d = user.decryptor(&cert)?; @@ -362,7 +363,7 @@ fn sign_detached( let mut card = util::open_card(ident)?; let mut txc = card.transaction()?; - let mut open = Open::new(&mut txc)?; + let mut open = Open::new(&mut *txc)?; let mut sign = util::verify_to_sign(&mut open, pin_file)?; let s = sign.signer(&cert)?; @@ -381,7 +382,7 @@ fn factory_reset(ident: &str) -> Result<()> { let mut card = util::open_card(ident)?; let mut txc = card.transaction()?; - Open::new(&mut txc)?.factory_reset() + Open::new(&mut *txc)?.factory_reset() } fn key_import_yolo(mut admin: Admin, key: &Cert) -> Result<()> {