Introduce the new CardBackend trait.

A CardBackend represents a card without an open transaction (a CardTransaction implementation can be acquired from a CardBackend).
This commit is contained in:
Heiko Schaefer 2022-02-17 20:22:52 +01:00
parent 5133051626
commit c23f23c619
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
10 changed files with 66 additions and 43 deletions

View file

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

View file

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

View file

@ -1,8 +1,8 @@
// SPDX-FileCopyrightText: 2021 Wiktor Kwapisiewicz <wiktor@metacode.biz> // SPDX-FileCopyrightText: 2021 Wiktor Kwapisiewicz <wiktor@metacode.biz>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
use openpgp_card::CardBackend;
use openpgp_card_pcsc::PcscCard; use openpgp_card_pcsc::PcscCard;
use openpgp_card_sequoia::card::Open; use openpgp_card_sequoia::card::Open;
use openpgp::parse::{stream::DecryptorBuilder, Parse}; use openpgp::parse::{stream::DecryptorBuilder, Parse};
@ -23,9 +23,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let cert_file = &args[2]; let cert_file = &args[2];
let mut card = PcscCard::open_by_ident(card_ident, None)?; let mut card = PcscCard::open_by_ident(card_ident, None)?;
let mut txc = card.transaction()?; let mut txc = <dyn CardBackend>::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)?; let pin = std::fs::read_to_string(pin_file)?;

View file

@ -1,8 +1,8 @@
// SPDX-FileCopyrightText: 2021 Wiktor Kwapisiewicz <wiktor@metacode.biz> // SPDX-FileCopyrightText: 2021 Wiktor Kwapisiewicz <wiktor@metacode.biz>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
use openpgp_card::CardBackend;
use openpgp_card_pcsc::PcscCard; use openpgp_card_pcsc::PcscCard;
use openpgp_card_sequoia::card::Open; use openpgp_card_sequoia::card::Open;
use openpgp::parse::Parse; use openpgp::parse::Parse;
@ -23,9 +23,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let cert_file = &args[2]; let cert_file = &args[2];
let mut card = PcscCard::open_by_ident(card_ident, None)?; let mut card = PcscCard::open_by_ident(card_ident, None)?;
let mut txc = card.transaction()?; let mut txc = <dyn CardBackend>::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)?; let pin = std::fs::read_to_string(pin_file)?;

View file

@ -16,9 +16,10 @@
//! use openpgp_card_pcsc::PcscCard; //! use openpgp_card_pcsc::PcscCard;
//! //!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> { //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # use openpgp_card::CardBackend;
//! for mut card in PcscCard::cards(None)? { //! for mut card in PcscCard::cards(None)? {
//! let mut txc = card.transaction()?; //! let mut txc = <dyn CardBackend>::transaction(&mut card)?;
//! let open = Open::new(&mut txc)?; //! let open = Open::new(&mut *txc)?;
//! println!("Found OpenPGP card with ident '{}'", //! println!("Found OpenPGP card with ident '{}'",
//! open.application_identifier()?.ident()); //! open.application_identifier()?.ident());
//! } //! }
@ -33,9 +34,10 @@
//! use openpgp_card_pcsc::PcscCard; //! use openpgp_card_pcsc::PcscCard;
//! //!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> { //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # use openpgp_card::CardBackend;
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; //! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
//! let mut txc = card.transaction()?; //! let mut txc = <dyn CardBackend>::transaction(&mut card)?;
//! let mut open = Open::new(&mut txc)?; //! let mut open = Open::new(&mut *txc)?;
//! # Ok(()) //! # Ok(())
//! # } //! # }
//! ``` //! ```
@ -56,9 +58,10 @@
//! # fn main() -> Result<(), Box<dyn std::error::Error>> { //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Open card via PCSC //! // Open card via PCSC
//! use sequoia_openpgp::policy::StandardPolicy; //! use sequoia_openpgp::policy::StandardPolicy;
//! # use openpgp_card::CardBackend;
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; //! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
//! let mut txc = card.transaction()?; //! let mut txc = <dyn CardBackend>::transaction(&mut card)?;
//! let mut open = Open::new(&mut txc)?; //! let mut open = Open::new(&mut *txc)?;
//! //!
//! // Get authorization for user access to the card with password //! // Get authorization for user access to the card with password
//! open.verify_user("123456")?; //! open.verify_user("123456")?;
@ -96,11 +99,12 @@
//! use openpgp_card_pcsc::PcscCard; //! use openpgp_card_pcsc::PcscCard;
//! //!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> { //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # use openpgp_card::CardBackend;
//! // Open card via PCSC //! // Open card via PCSC
//! use sequoia_openpgp::policy::StandardPolicy; //! use sequoia_openpgp::policy::StandardPolicy;
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; //! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
//! let mut txc = card.transaction()?; //! let mut txc = <dyn CardBackend>::transaction(&mut card)?;
//! let mut open = Open::new(&mut txc)?; //! let mut open = Open::new(&mut *txc)?;
//! //!
//! // Get authorization for signing access to the card with password //! // Get authorization for signing access to the card with password
//! open.verify_user_for_signing("123456")?; //! open.verify_user_for_signing("123456")?;
@ -128,10 +132,11 @@
//! use openpgp_card_pcsc::PcscCard; //! use openpgp_card_pcsc::PcscCard;
//! //!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> { //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # use openpgp_card::CardBackend;
//! // Open card via PCSC //! // Open card via PCSC
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; //! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
//! let mut txc = card.transaction()?; //! let mut txc = <dyn CardBackend>::transaction(&mut card)?;
//! let mut open = Open::new(&mut txc)?; //! let mut open = Open::new(&mut *txc)?;
//! //!
//! // Get authorization for admin access to the card with password //! // Get authorization for admin access to the card with password
//! open.verify_admin("12345678")?; //! open.verify_admin("12345678")?;

View file

@ -10,6 +10,7 @@ use sequoia_openpgp::policy::StandardPolicy;
use sequoia_openpgp::Cert; use sequoia_openpgp::Cert;
use openpgp_card::card_do::Sex; use openpgp_card::card_do::Sex;
use openpgp_card::CardBackend;
use openpgp_card::KeyType; use openpgp_card::KeyType;
use openpgp_card_pcsc::PcscCard; use openpgp_card_pcsc::PcscCard;
@ -38,7 +39,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut card = PcscCard::open_by_ident(&test_card_ident, None)?; let mut card = PcscCard::open_by_ident(&test_card_ident, None)?;
let mut txc = card.transaction()?; let mut txc = card.transaction()?;
let mut open = Open::new(&mut txc)?; let mut open = Open::new(&mut *txc)?;
// card metadata // card metadata
@ -149,7 +150,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut card = PcscCard::open_by_ident(&test_card_ident, None)?; let mut card = PcscCard::open_by_ident(&test_card_ident, None)?;
let mut txc = card.transaction()?; 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 // Check that we're still using the expected card
let app_id = open.application_identifier()?; let app_id = open.application_identifier()?;
@ -190,7 +191,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut card = PcscCard::open_by_ident(&test_card_ident, None)?; let mut card = PcscCard::open_by_ident(&test_card_ident, None)?;
let mut txc = card.transaction()?; let mut txc = card.transaction()?;
let mut open = Open::new(&mut txc)?; let mut open = Open::new(&mut *txc)?;
// Sign // Sign
open.verify_user_for_signing("123456")?; open.verify_user_for_signing("123456")?;
@ -222,7 +223,7 @@ fn main() -> Result<(), Box<dyn Error>> {
for mut card in PcscCard::cards(None)? { for mut card in PcscCard::cards(None)? {
let mut txc = card.transaction()?; let mut txc = card.transaction()?;
let open = Open::new(&mut txc)?; let open = Open::new(&mut *txc)?;
println!(" {}", open.application_identifier()?.ident()); println!(" {}", open.application_identifier()?.ident());
} }
} }

View file

@ -55,6 +55,12 @@ use crate::tlv::tag::Tag;
use crate::tlv::value::Value; use crate::tlv::value::Value;
use crate::tlv::Tlv; use crate::tlv::Tlv;
pub trait CardBackend {
fn transaction(
&mut self,
) -> Result<Box<dyn CardTransaction + Send + Sync + '_>, Error>;
}
/// The CardTransaction trait defines communication with an OpenPGP card via a /// The CardTransaction 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](https://crates.io/crates/openpgp-card-pcsc)), /// [openpgp-card-pcsc](https://crates.io/crates/openpgp-card-pcsc)),

View file

@ -12,7 +12,9 @@ use std::collections::HashMap;
use std::convert::TryInto; use std::convert::TryInto;
use openpgp_card::card_do::ApplicationRelatedData; 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_VERIFY_PIN_DIRECT: u8 = 0x06;
const FEATURE_MODIFY_PIN_DIRECT: u8 = 0x07; 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, /// `reselect` set to `false` is only used internally in this crate,
/// during initial setup of cards. Otherwise it must be `true`, to /// during initial setup of cards. Otherwise it must be `true`, to
/// cause a select() call on cards that have been reset. /// cause a select() call on cards that have been reset.
fn new(card: &'b mut PcscCard, reselect: bool) -> Result<Self> { fn new(card: &'b mut PcscCard, reselect: bool) -> Result<Self, Error> {
use pcsc::Disposition; use pcsc::Disposition;
let mut was_reset = false; let mut was_reset = false;
@ -452,11 +454,6 @@ impl PcscCard {
self.mode self.mode
} }
/// Get a TxClient for this PcscCard (this starts a transaction)
pub fn transaction(&mut self) -> Result<TxClient> {
TxClient::new(self, true)
}
/// A list of "raw" opened PCSC Cards (without selecting the OpenPGP card /// A list of "raw" opened PCSC Cards (without selecting the OpenPGP card
/// application) /// application)
fn raw_pcsc_cards(mode: ShareMode) -> Result<Vec<Card>, SmartcardError> { fn raw_pcsc_cards(mode: ShareMode) -> Result<Vec<Card>, SmartcardError> {
@ -647,7 +644,7 @@ impl PcscCard {
let mut h: HashMap<u8, Tlv> = HashMap::default(); let mut h: HashMap<u8, Tlv> = HashMap::default();
let mut txc = self.transaction()?; let mut txc = TxClient::new(&mut self, true)?;
// Get Features from reader (pinpad verify/modify) // Get Features from reader (pinpad verify/modify)
if let Ok(feat) = txc.features() { if let Ok(feat) = txc.features() {
@ -680,3 +677,12 @@ impl PcscCard {
self.reader_caps.clone() self.reader_caps.clone()
} }
} }
impl CardBackend for PcscCard {
/// Get a TxClient for this PcscCard (this starts a transaction)
fn transaction(
&mut self,
) -> Result<Box<dyn CardTransaction + Send + Sync + '_>, Error> {
Ok(Box::new(TxClient::new(self, true)?))
}
}

View file

@ -4,7 +4,7 @@
use anyhow::Result; use anyhow::Result;
use structopt::StructOpt; use structopt::StructOpt;
use openpgp_card::{CardTransaction, Error, StatusBytes}; use openpgp_card::{CardBackend, Error, StatusBytes};
use openpgp_card_pcsc::PcscCard; use openpgp_card_pcsc::PcscCard;
use openpgp_card_sequoia::card::Open; use openpgp_card_sequoia::card::Open;
@ -21,7 +21,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let pinpad_verify = txc.feature_pinpad_verify(); let pinpad_verify = txc.feature_pinpad_verify();
let pinpad_modify = txc.feature_pinpad_modify(); let pinpad_modify = txc.feature_pinpad_modify();
let mut open = Open::new(&mut txc)?; let mut open = Open::new(&mut *txc)?;
match cli.cmd { match cli.cmd {
cli::Command::SetUserPin {} => { cli::Command::SetUserPin {} => {

View file

@ -12,7 +12,8 @@ use sequoia_openpgp::serialize::SerializeInto;
use sequoia_openpgp::Cert; use sequoia_openpgp::Cert;
use openpgp_card::algorithm::AlgoSimple; 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::card::{Admin, Open};
use openpgp_card_sequoia::util::{make_cert, public_key_material_to_key}; use openpgp_card_sequoia::util::{make_cert, public_key_material_to_key};
@ -73,7 +74,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut card = util::open_card(&ident)?; let mut card = util::open_card(&ident)?;
let mut txc = card.transaction()?; let mut txc = card.transaction()?;
let mut open = Open::new(&mut txc)?; let mut open = Open::new(&mut *txc)?;
match cmd { match cmd {
cli::AdminCommand::Name { name } => { cli::AdminCommand::Name { name } => {
@ -140,7 +141,7 @@ fn list_cards() -> Result<()> {
for mut card in cards { for mut card in cards {
let mut txc = card.transaction()?; let mut txc = card.transaction()?;
let open = Open::new(&mut txc)?; let open = Open::new(&mut *txc)?;
println!(" {}", open.application_identifier()?.ident()); println!(" {}", open.application_identifier()?.ident());
} }
} else { } else {
@ -156,7 +157,7 @@ fn set_identity(
let mut card = util::open_card(ident)?; let mut card = util::open_card(ident)?;
let mut txc = card.transaction()?; let mut txc = card.transaction()?;
<dyn CardTransaction>::set_identity(&mut txc, id)?; txc.set_identity(id)?;
Ok(()) Ok(())
} }
@ -175,7 +176,7 @@ fn print_status(ident: Option<String>, verbose: bool) -> Result<()> {
let mut txc = card.transaction()?; 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(); let ident = open.application_identifier()?.ident();
@ -336,7 +337,7 @@ fn decrypt(
let mut card = util::open_card(ident)?; let mut card = util::open_card(ident)?;
let mut txc = card.transaction()?; 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 mut user = util::verify_to_user(&mut open, pin_file)?;
let d = user.decryptor(&cert)?; let d = user.decryptor(&cert)?;
@ -362,7 +363,7 @@ fn sign_detached(
let mut card = util::open_card(ident)?; let mut card = util::open_card(ident)?;
let mut txc = card.transaction()?; 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 mut sign = util::verify_to_sign(&mut open, pin_file)?;
let s = sign.signer(&cert)?; let s = sign.signer(&cert)?;
@ -381,7 +382,7 @@ fn factory_reset(ident: &str) -> Result<()> {
let mut card = util::open_card(ident)?; let mut card = util::open_card(ident)?;
let mut txc = card.transaction()?; 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<()> { fn key_import_yolo(mut admin: Admin, key: &Cert) -> Result<()> {