Tweak ergonomics of openpgp-card-pcsc usage and simplify client code.
This commit is contained in:
parent
635fa0e6ac
commit
e01c79e857
10 changed files with 47 additions and 44 deletions
|
@ -9,7 +9,7 @@ use pcsc::ShareMode;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use openpgp_card::Error;
|
use openpgp_card::{CardBackend, Error};
|
||||||
use openpgp_card_pcsc::PcscCard;
|
use openpgp_card_pcsc::PcscCard;
|
||||||
use openpgp_card_scdc::ScdClient;
|
use openpgp_card_scdc::ScdClient;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ pub struct TestCardData {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestCardData {
|
impl TestCardData {
|
||||||
pub(crate) fn get_card(&self) -> Result<Box<PcscCard>> {
|
pub(crate) fn get_card(&self) -> Result<Box<dyn CardBackend>> {
|
||||||
self.tc.open()
|
self.tc.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ pub enum TestCard {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestCard {
|
impl TestCard {
|
||||||
pub fn open(&self) -> Result<Box<PcscCard>> {
|
pub fn open(&self) -> Result<Box<dyn CardBackend>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Pcsc(ident) => {
|
Self::Pcsc(ident) => {
|
||||||
// Attempt to shutdown SCD, if it is running.
|
// Attempt to shutdown SCD, if it is running.
|
||||||
|
@ -103,11 +103,11 @@ impl TestCard {
|
||||||
// Make three attempts to open the card before failing
|
// Make three attempts to open the card before failing
|
||||||
// (this can be useful in ShareMode::Exclusive)
|
// (this can be useful in ShareMode::Exclusive)
|
||||||
let mut i = 1;
|
let mut i = 1;
|
||||||
let card: Result<PcscCard, Error> = loop {
|
let card: Result<Box<dyn CardBackend>, Error> = loop {
|
||||||
let res = PcscCard::open_by_ident(ident, SHARE_MODE);
|
let res = PcscCard::open_by_ident(ident, SHARE_MODE);
|
||||||
|
|
||||||
if i == 3 || res.is_ok() {
|
if i == 3 || res.is_ok() {
|
||||||
break res;
|
break res.map(Into::into);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sleep for 100ms
|
// sleep for 100ms
|
||||||
|
@ -116,7 +116,7 @@ impl TestCard {
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Box::new(card?))
|
Ok(card?)
|
||||||
}
|
}
|
||||||
Self::Scdc(serial) => {
|
Self::Scdc(serial) => {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
|
|
|
@ -11,7 +11,7 @@ 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 = <dyn CardBackend>::transaction(&mut card)?;
|
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());
|
||||||
|
|
|
@ -15,9 +15,7 @@ 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::{
|
use openpgp_card::{CardTransaction, Error, KeyType, StatusBytes};
|
||||||
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,
|
||||||
|
@ -680,8 +678,7 @@ 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 =
|
let mut txc = card.transaction().map_err(|e| anyhow!(e))?;
|
||||||
<dyn CardBackend>::transaction(&mut *card).map_err(|e| anyhow!(e))?;
|
|
||||||
|
|
||||||
t(&mut *txc, param)
|
t(&mut *txc, param)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ 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 = <dyn CardBackend>::transaction(&mut card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut *txc)?;
|
let mut open = Open::new(&mut *txc)?;
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ 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 = <dyn CardBackend>::transaction(&mut card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut *txc)?;
|
let mut open = Open::new(&mut *txc)?;
|
||||||
|
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
//! With `openpgp-card-pcsc` you can either open all available cards:
|
//! With `openpgp-card-pcsc` you can either open all available cards:
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use openpgp_card_sequoia::card::Open;
|
|
||||||
//! use openpgp_card_pcsc::PcscCard;
|
//! use openpgp_card_pcsc::PcscCard;
|
||||||
|
//! use openpgp_card::CardBackend;
|
||||||
|
//! use openpgp_card_sequoia::card::Open;
|
||||||
//!
|
//!
|
||||||
//! # 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 = <dyn CardBackend>::transaction(&mut card)?;
|
//! let mut txc = card.transaction()?;
|
||||||
//! 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());
|
||||||
|
@ -30,13 +30,13 @@
|
||||||
//! Or you can open one particular card, by ident:
|
//! Or you can open one particular card, by ident:
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use openpgp_card_sequoia::card::Open;
|
|
||||||
//! use openpgp_card_pcsc::PcscCard;
|
//! use openpgp_card_pcsc::PcscCard;
|
||||||
|
//! use openpgp_card::CardBackend;
|
||||||
|
//! use openpgp_card_sequoia::card::Open;
|
||||||
//!
|
//!
|
||||||
//! # 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 = <dyn CardBackend>::transaction(&mut card)?;
|
//! let mut txc = card.transaction()?;
|
||||||
//! let mut open = Open::new(&mut *txc)?;
|
//! let mut open = Open::new(&mut *txc)?;
|
||||||
//! # Ok(())
|
//! # Ok(())
|
||||||
//! # }
|
//! # }
|
||||||
|
@ -52,15 +52,15 @@
|
||||||
//! that corresponds to the private encryption key on the card:
|
//! that corresponds to the private encryption key on the card:
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use openpgp_card_sequoia::card::Open;
|
|
||||||
//! use openpgp_card_pcsc::PcscCard;
|
//! use openpgp_card_pcsc::PcscCard;
|
||||||
|
//! use openpgp_card::CardBackend;
|
||||||
|
//! use openpgp_card_sequoia::card::Open;
|
||||||
//!
|
//!
|
||||||
//! # 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 = <dyn CardBackend>::transaction(&mut card)?;
|
//! let mut txc = card.transaction()?;
|
||||||
//! 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
|
||||||
|
@ -95,15 +95,15 @@
|
||||||
//! user password before each signing operation!)
|
//! user password before each signing operation!)
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use openpgp_card_sequoia::card::Open;
|
|
||||||
//! use openpgp_card_pcsc::PcscCard;
|
//! use openpgp_card_pcsc::PcscCard;
|
||||||
|
//! use openpgp_card::CardBackend;
|
||||||
|
//! use openpgp_card_sequoia::card::Open;
|
||||||
//!
|
//!
|
||||||
//! # 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 = <dyn CardBackend>::transaction(&mut card)?;
|
//! let mut txc = card.transaction()?;
|
||||||
//! 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
|
||||||
|
@ -128,14 +128,14 @@
|
||||||
//! # Setting up and configuring a card
|
//! # Setting up and configuring a card
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use openpgp_card_sequoia::card::Open;
|
|
||||||
//! use openpgp_card_pcsc::PcscCard;
|
//! use openpgp_card_pcsc::PcscCard;
|
||||||
|
//! use openpgp_card::CardBackend;
|
||||||
|
//! use openpgp_card_sequoia::card::Open;
|
||||||
//!
|
//!
|
||||||
//! # 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 = <dyn CardBackend>::transaction(&mut card)?;
|
//! let mut txc = card.transaction()?;
|
||||||
//! 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
|
||||||
|
|
|
@ -10,8 +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::{CardBackend, KeyType};
|
||||||
use openpgp_card::KeyType;
|
|
||||||
use openpgp_card_pcsc::PcscCard;
|
use openpgp_card_pcsc::PcscCard;
|
||||||
|
|
||||||
use openpgp_card_sequoia::card::Open;
|
use openpgp_card_sequoia::card::Open;
|
||||||
|
|
|
@ -40,6 +40,12 @@ pub struct PcscCard {
|
||||||
reader_caps: HashMap<u8, Tlv>,
|
reader_caps: HashMap<u8, Tlv>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<PcscCard> for Box<dyn CardBackend> {
|
||||||
|
fn from(card: PcscCard) -> Box<dyn CardBackend> {
|
||||||
|
Box::new(card) as Box<dyn CardBackend>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An implementation of the CardTransaction trait that uses the PCSC lite
|
/// An implementation of the CardTransaction trait that uses the PCSC lite
|
||||||
/// middleware to access the OpenPGP card application on smart cards, via a
|
/// middleware to access the OpenPGP card application on smart cards, via a
|
||||||
/// PCSC "transaction".
|
/// PCSC "transaction".
|
||||||
|
@ -446,11 +452,11 @@ impl CardTransaction for TxClient<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PcscCard {
|
impl PcscCard {
|
||||||
pub fn card(&mut self) -> &mut Card {
|
fn card(&mut self) -> &mut Card {
|
||||||
&mut self.card
|
&mut self.card
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mode(&self) -> ShareMode {
|
fn mode(&self) -> ShareMode {
|
||||||
self.mode
|
self.mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,8 +535,8 @@ impl PcscCard {
|
||||||
fn cards_filter(
|
fn cards_filter(
|
||||||
ident: Option<&str>,
|
ident: Option<&str>,
|
||||||
mode: ShareMode,
|
mode: ShareMode,
|
||||||
) -> Result<Vec<PcscCard>, Error> {
|
) -> Result<Vec<Self>, Error> {
|
||||||
let mut cas: Vec<PcscCard> = vec![];
|
let mut cards: Vec<Self> = vec![];
|
||||||
|
|
||||||
for mut card in
|
for mut card in
|
||||||
Self::raw_pcsc_cards(mode).map_err(|sce| Error::Smartcard(sce))?
|
Self::raw_pcsc_cards(mode).map_err(|sce| Error::Smartcard(sce))?
|
||||||
|
@ -588,20 +594,20 @@ impl PcscCard {
|
||||||
|
|
||||||
if store_card {
|
if store_card {
|
||||||
let pcsc = PcscCard::new(card, mode);
|
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.
|
/// 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
|
/// Each card has the OpenPGP application selected, card_caps and reader_caps have been
|
||||||
/// initialized.
|
/// initialized.
|
||||||
pub fn cards(mode: Option<ShareMode>) -> Result<Vec<PcscCard>, Error> {
|
pub fn cards(mode: Option<ShareMode>) -> Result<Vec<Self>, Error> {
|
||||||
Self::cards_filter(None, default_mode(mode))
|
Self::cards_filter(None, default_mode(mode))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,7 +617,7 @@ impl PcscCard {
|
||||||
pub fn open_by_ident(
|
pub fn open_by_ident(
|
||||||
ident: &str,
|
ident: &str,
|
||||||
mode: Option<ShareMode>,
|
mode: Option<ShareMode>,
|
||||||
) -> Result<PcscCard, Error> {
|
) -> Result<Self, Error> {
|
||||||
log::debug!("open_by_ident for {:?}", ident);
|
log::debug!("open_by_ident for {:?}", ident);
|
||||||
|
|
||||||
let mut cards = Self::cards_filter(Some(ident), default_mode(mode))?;
|
let mut cards = Self::cards_filter(Some(ident), default_mode(mode))?;
|
||||||
|
|
|
@ -12,7 +12,6 @@ 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::CardBackend;
|
|
||||||
use openpgp_card::{card_do::Sex, KeyType};
|
use openpgp_card::{card_do::Sex, KeyType};
|
||||||
|
|
||||||
use openpgp_card_sequoia::card::{Admin, Open};
|
use openpgp_card_sequoia::card::{Admin, Open};
|
||||||
|
|
|
@ -6,16 +6,18 @@ use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use openpgp_card::algorithm::{Algo, Curve};
|
use openpgp_card::algorithm::{Algo, Curve};
|
||||||
use openpgp_card::crypto_data::{EccType, PublicKeyMaterial};
|
use openpgp_card::crypto_data::{EccType, PublicKeyMaterial};
|
||||||
use openpgp_card::Error;
|
use openpgp_card::{CardBackend, Error};
|
||||||
use openpgp_card_pcsc::PcscCard;
|
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<Box<dyn CardBackend>>, Error> {
|
||||||
PcscCard::cards(None)
|
PcscCard::cards(None)
|
||||||
|
.map(|cards| cards.into_iter().map(Into::into).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn open_card(ident: &str) -> Result<PcscCard, Error> {
|
pub(crate) fn open_card(ident: &str) -> Result<Box<dyn CardBackend>, Error> {
|
||||||
PcscCard::open_by_ident(ident, None)
|
PcscCard::open_by_ident(ident, None)
|
||||||
|
.map(|pc| Box::new(pc) as Box<dyn CardBackend>)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn verify_to_user<'app, 'open>(
|
pub(crate) fn verify_to_user<'app, 'open>(
|
||||||
|
|
Loading…
Reference in a new issue