diff --git a/card-functionality/src/cards.rs b/card-functionality/src/cards.rs index d4131f1..e3dc308 100644 --- a/card-functionality/src/cards.rs +++ b/card-functionality/src/cards.rs @@ -5,12 +5,15 @@ //! TestConfig configuration file use anyhow::Result; +use pcsc::ShareMode; use serde_derive::Deserialize; use std::collections::BTreeMap; use openpgp_card_pcsc::PcscCard; use openpgp_card_scdc::ScdClient; +const SHARE_MODE: Option = Some(ShareMode::Shared); + #[derive(Debug, Deserialize)] pub struct TestConfig { card: BTreeMap, @@ -96,7 +99,7 @@ impl TestCard { let res = ScdClient::shutdown_scd(None); log::trace!(" Attempt to shutdown scd: {:?}", res); - Ok(Box::new(PcscCard::open_by_ident(ident)?)) + Ok(Box::new(PcscCard::open_by_ident(ident, SHARE_MODE)?)) } Self::Scdc(serial) => { unimplemented!(); diff --git a/card-functionality/src/list-cards.rs b/card-functionality/src/list-cards.rs index 7d8116c..87fe392 100644 --- a/card-functionality/src/list-cards.rs +++ b/card-functionality/src/list-cards.rs @@ -9,7 +9,7 @@ use openpgp_card_sequoia::card::Open; fn main() -> Result<()> { println!("The following OpenPGP cards are connected to your system:"); - for mut card in PcscCard::cards()? { + for mut card in PcscCard::cards(None)? { let mut txc: TxClient = openpgp_card_pcsc::get_txc!(card)?; let open = Open::new(&mut txc)?; diff --git a/openpgp-card-examples/src/bin/decrypt.rs b/openpgp-card-examples/src/bin/decrypt.rs index f130daf..b41c3a9 100644 --- a/openpgp-card-examples/src/bin/decrypt.rs +++ b/openpgp-card-examples/src/bin/decrypt.rs @@ -22,7 +22,7 @@ fn main() -> Result<(), Box> { let pin_file = &args[1]; let cert_file = &args[2]; - let mut card = PcscCard::open_by_ident(card_ident)?; + let mut card = PcscCard::open_by_ident(card_ident, None)?; let mut txc = get_txc!(card)?; 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 17cf994..4be503a 100644 --- a/openpgp-card-examples/src/bin/detach-sign.rs +++ b/openpgp-card-examples/src/bin/detach-sign.rs @@ -22,7 +22,7 @@ fn main() -> Result<(), Box> { let pin_file = &args[1]; let cert_file = &args[2]; - let mut card = PcscCard::open_by_ident(card_ident)?; + let mut card = PcscCard::open_by_ident(card_ident, None)?; let mut txc = get_txc!(card)?; let mut open = Open::new(&mut txc)?; diff --git a/openpgp-card-sequoia/src/lib.rs b/openpgp-card-sequoia/src/lib.rs index dc4143c..d2e76a7 100644 --- a/openpgp-card-sequoia/src/lib.rs +++ b/openpgp-card-sequoia/src/lib.rs @@ -16,7 +16,7 @@ //! use openpgp_card_pcsc::{get_txc, PcscCard, TxClient}; //! //! # fn main() -> Result<(), Box> { -//! for mut card in PcscCard::cards()? { +//! for mut card in PcscCard::cards(None)? { //! let mut txc = get_txc!(card)?; //! let open = Open::new(&mut txc)?; //! println!("Found OpenPGP card with ident '{}'", @@ -33,7 +33,7 @@ //! use openpgp_card_pcsc::{get_txc, PcscCard, TxClient}; //! //! # fn main() -> Result<(), Box> { -//! let mut card = PcscCard::open_by_ident("abcd:12345678")?; +//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; //! let mut txc = get_txc!(card)?; //! let mut open = Open::new(&mut txc)?; //! # Ok(()) @@ -56,7 +56,7 @@ //! # fn main() -> Result<(), Box> { //! // Open card via PCSC //! use sequoia_openpgp::policy::StandardPolicy; -//! let mut card = PcscCard::open_by_ident("abcd:12345678")?; +//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; //! let mut txc = get_txc!(card)?; //! let mut open = Open::new(&mut txc)?; //! @@ -98,7 +98,7 @@ //! # fn main() -> Result<(), Box> { //! // Open card via PCSC //! use sequoia_openpgp::policy::StandardPolicy; -//! let mut card = PcscCard::open_by_ident("abcd:12345678")?; +//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; //! let mut txc = get_txc!(card)?; //! let mut open = Open::new(&mut txc)?; //! @@ -129,7 +129,7 @@ //! //! # fn main() -> Result<(), Box> { //! // Open card via PCSC -//! let mut card = PcscCard::open_by_ident("abcd:12345678")?; +//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?; //! let mut txc = get_txc!(card)?; //! let mut open = Open::new(&mut txc)?; //! diff --git a/openpgp-card-sequoia/src/main.rs b/openpgp-card-sequoia/src/main.rs index 2408ec2..aa62264 100644 --- a/openpgp-card-sequoia/src/main.rs +++ b/openpgp-card-sequoia/src/main.rs @@ -35,7 +35,7 @@ fn main() -> Result<(), Box> { let test_card_ident = env::var("TEST_CARD_IDENT"); if let Ok(test_card_ident) = test_card_ident { - let mut card = PcscCard::open_by_ident(&test_card_ident)?; + let mut card = PcscCard::open_by_ident(&test_card_ident, None)?; let mut txc = openpgp_card_pcsc::get_txc!(card)?; let mut open = Open::new(&mut txc)?; @@ -146,7 +146,7 @@ fn main() -> Result<(), Box> { // ----------------------------- // Open fresh Card for decrypt // ----------------------------- - let mut card = PcscCard::open_by_ident(&test_card_ident)?; + let mut card = PcscCard::open_by_ident(&test_card_ident, None)?; let mut txc = openpgp_card_pcsc::get_txc!(card)?; let mut open = Open::new(&mut txc)?; @@ -187,7 +187,7 @@ fn main() -> Result<(), Box> { // ----------------------------- // Open fresh Card for signing // ----------------------------- - let mut card = PcscCard::open_by_ident(&test_card_ident)?; + let mut card = PcscCard::open_by_ident(&test_card_ident, None)?; let mut txc = openpgp_card_pcsc::get_txc!(card)?; let mut open = Open::new(&mut txc)?; @@ -219,7 +219,7 @@ fn main() -> Result<(), Box> { println!("The following OpenPGP cards are connected to your system:"); - for mut card in PcscCard::cards()? { + for mut card in PcscCard::cards(None)? { let mut txc = openpgp_card_pcsc::get_txc!(card)?; let open = Open::new(&mut txc)?; diff --git a/pcsc/src/lib.rs b/pcsc/src/lib.rs index 760e29a..6d94a71 100644 --- a/pcsc/src/lib.rs +++ b/pcsc/src/lib.rs @@ -22,7 +22,7 @@ const FEATURE_MODIFY_PIN_DIRECT: u8 = 0x07; macro_rules! get_txc { ($card:expr $(, $reselect:expr)? ) => {{ use openpgp_card::{Error, SmartcardError}; - use pcsc::{Disposition, Protocols, ShareMode}; + use pcsc::{Disposition, Protocols}; #[allow(unused_assignments)] let mut reselect = true; @@ -34,6 +34,8 @@ macro_rules! get_txc { let card_caps = $card.card_caps(); let reader_caps = $card.reader_caps().clone(); + let mode = $card.mode(); + let c = $card.card(); loop { @@ -78,7 +80,7 @@ macro_rules! get_txc { { c.reconnect( - ShareMode::Shared, + mode, Protocols::ANY, Disposition::ResetCard, ) @@ -105,6 +107,14 @@ macro_rules! get_txc { }}; } +fn default_mode(mode: Option) -> ShareMode { + if let Some(mode) = mode { + mode + } else { + ShareMode::Shared + } +} + /// An opened PCSC Card (without open transaction). /// The OpenPGP application on the card is `select`-ed while setting up a PcscCard object. /// @@ -113,6 +123,7 @@ macro_rules! get_txc { /// `TxClient` object needs to be obtained (via the `get_txc!()` macro). pub struct PcscCard { card: Card, + mode: ShareMode, card_caps: Option, reader_caps: HashMap, } @@ -453,9 +464,13 @@ impl PcscCard { &mut self.card } + pub fn mode(&self) -> ShareMode { + self.mode + } + /// A list of "raw" opened PCSC Cards (without selecting the OpenPGP card /// application) - fn raw_pcsc_cards() -> Result, SmartcardError> { + fn raw_pcsc_cards(mode: ShareMode) -> Result, SmartcardError> { let ctx = match Context::establish(Scope::User) { Ok(ctx) => ctx, Err(err) => { @@ -488,23 +503,22 @@ impl PcscCard { log::debug!("Checking reader: {:?}", reader); // Try connecting to card in this reader - let card = - match ctx.connect(reader, ShareMode::Shared, Protocols::ANY) { - Ok(card) => card, - Err(pcsc::Error::NoSmartcard) => { - log::debug!("No Smartcard"); + let card = match ctx.connect(reader, mode, Protocols::ANY) { + Ok(card) => card, + Err(pcsc::Error::NoSmartcard) => { + log::debug!("No Smartcard"); - continue; // try next reader - } - Err(err) => { - log::warn!( - "Error connecting to card in reader: {:x?}", - err - ); + continue; // try next reader + } + Err(err) => { + log::warn!( + "Error connecting to card in reader: {:x?}", + err + ); - continue; - } - }; + continue; + } + }; log::debug!("Found card"); @@ -522,11 +536,14 @@ impl PcscCard { /// application identity with `ident` (if `ident` is None, all Cards are /// returned). Returns fully initialized PcscCard structs for all matching /// cards. - fn cards_filter(ident: Option<&str>) -> Result, Error> { + fn cards_filter( + ident: Option<&str>, + mode: ShareMode, + ) -> Result, Error> { let mut cas: Vec = vec![]; for mut card in - Self::raw_pcsc_cards().map_err(|sce| Error::Smartcard(sce))? + Self::raw_pcsc_cards(mode).map_err(|sce| Error::Smartcard(sce))? { log::debug!("cards_filter: next card"); @@ -537,7 +554,7 @@ impl PcscCard { { // start transaction log::debug!("1"); - let mut p = PcscCard::new(card); + let mut p = PcscCard::new(card, mode); let mut txc: TxClient = get_txc!(p, false)?; log::debug!("3"); @@ -607,7 +624,7 @@ impl PcscCard { } if store_card { - let pcsc = PcscCard::new(card); + let pcsc = PcscCard::new(card, mode); cas.push(pcsc.initialize_card()?); } } @@ -621,17 +638,20 @@ impl PcscCard { /// /// Each card has the OpenPGP application selected, card_caps and reader_caps have been /// initialized. - pub fn cards() -> Result, Error> { - Self::cards_filter(None) + pub fn cards(mode: Option) -> Result, Error> { + Self::cards_filter(None, default_mode(mode)) } /// Returns the OpenPGP card that matches `ident`, if it is available. /// A fully initialized PcscCard is returned: the OpenPGP application has /// been selected, card_caps and reader_caps have been initialized. - pub fn open_by_ident(ident: &str) -> Result { + pub fn open_by_ident( + ident: &str, + mode: Option, + ) -> Result { log::debug!("open_by_ident for {:?}", ident); - let mut cards = Self::cards_filter(Some(ident))?; + let mut cards = Self::cards_filter(Some(ident), default_mode(mode))?; if !cards.is_empty() { // FIXME: handle >1 cards found @@ -644,9 +664,10 @@ impl PcscCard { } } - fn new(card: Card) -> Self { + fn new(card: Card, mode: ShareMode) -> Self { Self { card, + mode, card_caps: None, reader_caps: HashMap::new(), } diff --git a/tools/src/bin/opgpcard-pin/main.rs b/tools/src/bin/opgpcard-pin/main.rs index 1c50f96..2f04492 100644 --- a/tools/src/bin/opgpcard-pin/main.rs +++ b/tools/src/bin/opgpcard-pin/main.rs @@ -15,7 +15,7 @@ fn main() -> Result<(), Box> { let cli = cli::Cli::from_args(); - let mut card = PcscCard::open_by_ident(&cli.ident)?; + let mut card = PcscCard::open_by_ident(&cli.ident, None)?; let mut txc = get_txc!(card)?; let pinpad_verify = txc.feature_pinpad_verify(); diff --git a/tools/src/bin/opgpcard/util.rs b/tools/src/bin/opgpcard/util.rs index 5ce0ff3..2ae51d5 100644 --- a/tools/src/bin/opgpcard/util.rs +++ b/tools/src/bin/opgpcard/util.rs @@ -9,11 +9,11 @@ use openpgp_card_pcsc::PcscCard; use openpgp_card_sequoia::card::{Admin, Open, Sign, User}; pub(crate) fn cards() -> Result, Error> { - PcscCard::cards() + PcscCard::cards(None) } pub(crate) fn open_card(ident: &str) -> Result { - PcscCard::open_by_ident(ident) + PcscCard::open_by_ident(ident, None) } pub(crate) fn verify_to_user<'app, 'open>(