Make ShareMode an optional parameter when opening cards via pcsc.

This commit is contained in:
Heiko Schaefer 2022-01-21 12:20:20 +01:00
parent e92cad5b6a
commit 7573361836
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
9 changed files with 67 additions and 43 deletions

View file

@ -5,12 +5,15 @@
//! TestConfig configuration file //! TestConfig configuration file
use anyhow::Result; use anyhow::Result;
use pcsc::ShareMode;
use serde_derive::Deserialize; use serde_derive::Deserialize;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use openpgp_card_pcsc::PcscCard; use openpgp_card_pcsc::PcscCard;
use openpgp_card_scdc::ScdClient; use openpgp_card_scdc::ScdClient;
const SHARE_MODE: Option<ShareMode> = Some(ShareMode::Shared);
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct TestConfig { pub struct TestConfig {
card: BTreeMap<String, Card>, card: BTreeMap<String, Card>,
@ -96,7 +99,7 @@ impl TestCard {
let res = ScdClient::shutdown_scd(None); let res = ScdClient::shutdown_scd(None);
log::trace!(" Attempt to shutdown scd: {:?}", res); 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) => { Self::Scdc(serial) => {
unimplemented!(); unimplemented!();

View file

@ -9,7 +9,7 @@ use openpgp_card_sequoia::card::Open;
fn main() -> Result<()> { 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()? { for mut card in PcscCard::cards(None)? {
let mut txc: TxClient = openpgp_card_pcsc::get_txc!(card)?; let mut txc: TxClient = openpgp_card_pcsc::get_txc!(card)?;
let open = Open::new(&mut txc)?; let open = Open::new(&mut txc)?;

View file

@ -22,7 +22,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let pin_file = &args[1]; let pin_file = &args[1];
let cert_file = &args[2]; 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 txc = get_txc!(card)?;
let mut open = Open::new(&mut txc)?; let mut open = Open::new(&mut txc)?;

View file

@ -22,7 +22,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let pin_file = &args[1]; let pin_file = &args[1];
let cert_file = &args[2]; 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 txc = get_txc!(card)?;
let mut open = Open::new(&mut txc)?; let mut open = Open::new(&mut txc)?;

View file

@ -16,7 +16,7 @@
//! use openpgp_card_pcsc::{get_txc, PcscCard, TxClient}; //! use openpgp_card_pcsc::{get_txc, PcscCard, TxClient};
//! //!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> { //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! for mut card in PcscCard::cards()? { //! for mut card in PcscCard::cards(None)? {
//! let mut txc = get_txc!(card)?; //! let mut txc = get_txc!(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 '{}'",
@ -33,7 +33,7 @@
//! use openpgp_card_pcsc::{get_txc, PcscCard, TxClient}; //! use openpgp_card_pcsc::{get_txc, PcscCard, TxClient};
//! //!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> { //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! 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 txc = get_txc!(card)?;
//! let mut open = Open::new(&mut txc)?; //! let mut open = Open::new(&mut txc)?;
//! # Ok(()) //! # Ok(())
@ -56,7 +56,7 @@
//! # 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;
//! 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 txc = get_txc!(card)?;
//! let mut open = Open::new(&mut txc)?; //! let mut open = Open::new(&mut txc)?;
//! //!
@ -98,7 +98,7 @@
//! # 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;
//! 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 txc = get_txc!(card)?;
//! let mut open = Open::new(&mut txc)?; //! let mut open = Open::new(&mut txc)?;
//! //!
@ -129,7 +129,7 @@
//! //!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> { //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Open card via PCSC //! // 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 txc = get_txc!(card)?;
//! let mut open = Open::new(&mut txc)?; //! let mut open = Open::new(&mut txc)?;
//! //!

View file

@ -35,7 +35,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let test_card_ident = env::var("TEST_CARD_IDENT"); let test_card_ident = env::var("TEST_CARD_IDENT");
if let Ok(test_card_ident) = 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 txc = openpgp_card_pcsc::get_txc!(card)?;
let mut open = Open::new(&mut txc)?; let mut open = Open::new(&mut txc)?;
@ -146,7 +146,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// ----------------------------- // -----------------------------
// Open fresh Card for decrypt // 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 txc = openpgp_card_pcsc::get_txc!(card)?;
let mut open = Open::new(&mut txc)?; let mut open = Open::new(&mut txc)?;
@ -187,7 +187,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// ----------------------------- // -----------------------------
// Open fresh Card for signing // 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 txc = openpgp_card_pcsc::get_txc!(card)?;
let mut open = Open::new(&mut txc)?; let mut open = Open::new(&mut txc)?;
@ -219,7 +219,7 @@ fn main() -> Result<(), Box<dyn Error>> {
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()? { for mut card in PcscCard::cards(None)? {
let mut txc = openpgp_card_pcsc::get_txc!(card)?; let mut txc = openpgp_card_pcsc::get_txc!(card)?;
let open = Open::new(&mut txc)?; let open = Open::new(&mut txc)?;

View file

@ -22,7 +22,7 @@ const FEATURE_MODIFY_PIN_DIRECT: u8 = 0x07;
macro_rules! get_txc { macro_rules! get_txc {
($card:expr $(, $reselect:expr)? ) => {{ ($card:expr $(, $reselect:expr)? ) => {{
use openpgp_card::{Error, SmartcardError}; use openpgp_card::{Error, SmartcardError};
use pcsc::{Disposition, Protocols, ShareMode}; use pcsc::{Disposition, Protocols};
#[allow(unused_assignments)] #[allow(unused_assignments)]
let mut reselect = true; let mut reselect = true;
@ -34,6 +34,8 @@ macro_rules! get_txc {
let card_caps = $card.card_caps(); let card_caps = $card.card_caps();
let reader_caps = $card.reader_caps().clone(); let reader_caps = $card.reader_caps().clone();
let mode = $card.mode();
let c = $card.card(); let c = $card.card();
loop { loop {
@ -78,7 +80,7 @@ macro_rules! get_txc {
{ {
c.reconnect( c.reconnect(
ShareMode::Shared, mode,
Protocols::ANY, Protocols::ANY,
Disposition::ResetCard, Disposition::ResetCard,
) )
@ -105,6 +107,14 @@ macro_rules! get_txc {
}}; }};
} }
fn default_mode(mode: Option<ShareMode>) -> ShareMode {
if let Some(mode) = mode {
mode
} else {
ShareMode::Shared
}
}
/// An opened PCSC Card (without open transaction). /// An opened PCSC Card (without open transaction).
/// The OpenPGP application on the card is `select`-ed while setting up a PcscCard object. /// 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). /// `TxClient` object needs to be obtained (via the `get_txc!()` macro).
pub struct PcscCard { pub struct PcscCard {
card: Card, card: Card,
mode: ShareMode,
card_caps: Option<CardCaps>, card_caps: Option<CardCaps>,
reader_caps: HashMap<u8, Tlv>, reader_caps: HashMap<u8, Tlv>,
} }
@ -453,9 +464,13 @@ impl PcscCard {
&mut self.card &mut self.card
} }
pub fn mode(&self) -> ShareMode {
self.mode
}
/// 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() -> Result<Vec<Card>, SmartcardError> { fn raw_pcsc_cards(mode: ShareMode) -> Result<Vec<Card>, SmartcardError> {
let ctx = match Context::establish(Scope::User) { let ctx = match Context::establish(Scope::User) {
Ok(ctx) => ctx, Ok(ctx) => ctx,
Err(err) => { Err(err) => {
@ -488,8 +503,7 @@ impl PcscCard {
log::debug!("Checking reader: {:?}", reader); log::debug!("Checking reader: {:?}", reader);
// Try connecting to card in this reader // Try connecting to card in this reader
let card = let card = match ctx.connect(reader, mode, Protocols::ANY) {
match ctx.connect(reader, ShareMode::Shared, Protocols::ANY) {
Ok(card) => card, Ok(card) => card,
Err(pcsc::Error::NoSmartcard) => { Err(pcsc::Error::NoSmartcard) => {
log::debug!("No Smartcard"); log::debug!("No Smartcard");
@ -522,11 +536,14 @@ impl PcscCard {
/// application identity with `ident` (if `ident` is None, all Cards are /// application identity with `ident` (if `ident` is None, all Cards are
/// returned). Returns fully initialized PcscCard structs for all matching /// returned). Returns fully initialized PcscCard structs for all matching
/// cards. /// cards.
fn cards_filter(ident: Option<&str>) -> Result<Vec<PcscCard>, Error> { fn cards_filter(
ident: Option<&str>,
mode: ShareMode,
) -> Result<Vec<PcscCard>, Error> {
let mut cas: Vec<PcscCard> = vec![]; let mut cas: Vec<PcscCard> = vec![];
for mut card in 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"); log::debug!("cards_filter: next card");
@ -537,7 +554,7 @@ impl PcscCard {
{ {
// start transaction // start transaction
log::debug!("1"); log::debug!("1");
let mut p = PcscCard::new(card); let mut p = PcscCard::new(card, mode);
let mut txc: TxClient = get_txc!(p, false)?; let mut txc: TxClient = get_txc!(p, false)?;
log::debug!("3"); log::debug!("3");
@ -607,7 +624,7 @@ impl PcscCard {
} }
if store_card { if store_card {
let pcsc = PcscCard::new(card); let pcsc = PcscCard::new(card, mode);
cas.push(pcsc.initialize_card()?); 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 /// Each card has the OpenPGP application selected, card_caps and reader_caps have been
/// initialized. /// initialized.
pub fn cards() -> Result<Vec<PcscCard>, Error> { pub fn cards(mode: Option<ShareMode>) -> Result<Vec<PcscCard>, Error> {
Self::cards_filter(None) Self::cards_filter(None, default_mode(mode))
} }
/// Returns the OpenPGP card that matches `ident`, if it is available. /// Returns the OpenPGP card that matches `ident`, if it is available.
/// A fully initialized PcscCard is returned: the OpenPGP application has /// A fully initialized PcscCard is returned: the OpenPGP application has
/// been selected, card_caps and reader_caps have been initialized. /// been selected, card_caps and reader_caps have been initialized.
pub fn open_by_ident(ident: &str) -> Result<PcscCard, Error> { pub fn open_by_ident(
ident: &str,
mode: Option<ShareMode>,
) -> Result<PcscCard, Error> {
log::debug!("open_by_ident for {:?}", ident); 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() { if !cards.is_empty() {
// FIXME: handle >1 cards found // FIXME: handle >1 cards found
@ -644,9 +664,10 @@ impl PcscCard {
} }
} }
fn new(card: Card) -> Self { fn new(card: Card, mode: ShareMode) -> Self {
Self { Self {
card, card,
mode,
card_caps: None, card_caps: None,
reader_caps: HashMap::new(), reader_caps: HashMap::new(),
} }

View file

@ -15,7 +15,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = cli::Cli::from_args(); 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 mut txc = get_txc!(card)?;
let pinpad_verify = txc.feature_pinpad_verify(); let pinpad_verify = txc.feature_pinpad_verify();

View file

@ -9,11 +9,11 @@ use openpgp_card_pcsc::PcscCard;
use openpgp_card_sequoia::card::{Admin, Open, Sign, User}; use openpgp_card_sequoia::card::{Admin, Open, Sign, User};
pub(crate) fn cards() -> Result<Vec<PcscCard>, Error> { pub(crate) fn cards() -> Result<Vec<PcscCard>, Error> {
PcscCard::cards() PcscCard::cards(None)
} }
pub(crate) fn open_card(ident: &str) -> Result<PcscCard, Error> { pub(crate) fn open_card(ident: &str) -> Result<PcscCard, Error> {
PcscCard::open_by_ident(ident) PcscCard::open_by_ident(ident, None)
} }
pub(crate) fn verify_to_user<'app, 'open>( pub(crate) fn verify_to_user<'app, 'open>(