Implement PcscCard::transaction() to replace the transaction!() macro.
(This currently requires unreleased pcsc from git)
This commit is contained in:
parent
50d8b89fd2
commit
0e94871189
14 changed files with 141 additions and 155 deletions
|
@ -32,7 +32,7 @@ openpgp-card = { path = "../openpgp-card" }
|
||||||
openpgp-card-sequoia = { path = "../openpgp-card-sequoia" }
|
openpgp-card-sequoia = { path = "../openpgp-card-sequoia" }
|
||||||
openpgp-card-scdc = { path = "../scdc" }
|
openpgp-card-scdc = { path = "../scdc" }
|
||||||
openpgp-card-pcsc = { path = "../pcsc" }
|
openpgp-card-pcsc = { path = "../pcsc" }
|
||||||
pcsc = "2"
|
pcsc = { git = "https://github.com/bluetech/pcsc-rust/", rev = "ac1feee16d54bd6ba1681a201fc8f25808aa346d" }
|
||||||
sequoia-openpgp = "1.3"
|
sequoia-openpgp = "1.3"
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use openpgp_card_pcsc::{transaction, PcscCard, TxClient};
|
use openpgp_card_pcsc::PcscCard;
|
||||||
use openpgp_card_sequoia::card::Open;
|
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(None)? {
|
for mut card in PcscCard::cards(None)? {
|
||||||
let mut txc: TxClient = transaction!(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());
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
|
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::{anyhow, Result};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
|
@ -16,7 +16,6 @@ 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::{CardClient, Error, KeyType, StatusBytes};
|
use openpgp_card::{CardClient, Error, KeyType, StatusBytes};
|
||||||
use openpgp_card_pcsc::{transaction, TxClient};
|
|
||||||
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,
|
||||||
|
@ -671,19 +670,15 @@ pub fn test_reset_retry_counter(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_test(
|
pub fn run_test(
|
||||||
card: &mut TestCardData,
|
tc: &mut TestCardData,
|
||||||
t: fn(
|
t: fn(
|
||||||
&mut (dyn CardClient + Send + Sync),
|
&mut (dyn CardClient + Send + Sync),
|
||||||
&[&str],
|
&[&str],
|
||||||
) -> Result<TestOutput, TestError>,
|
) -> Result<TestOutput, TestError>,
|
||||||
param: &[&str],
|
param: &[&str],
|
||||||
) -> Result<TestOutput, TestError> {
|
) -> Result<TestOutput, TestError> {
|
||||||
let mut card_client = card.get_card()?;
|
let mut card = tc.get_card()?;
|
||||||
|
let mut txc = card.transaction().map_err(|e| anyhow!(e))?;
|
||||||
use anyhow::anyhow;
|
|
||||||
|
|
||||||
let mut txc = transaction!(card_client).map_err(|e| anyhow!(e))?;
|
|
||||||
// let mut txc = TxClient::new(&mut tx, card_caps, reader_caps);
|
|
||||||
|
|
||||||
t(&mut txc, param)
|
t(&mut txc, param)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ sequoia-openpgp = "1.3"
|
||||||
nettle = "7"
|
nettle = "7"
|
||||||
openpgp-card = { path = "../openpgp-card", version = "0.1" }
|
openpgp-card = { path = "../openpgp-card", version = "0.1" }
|
||||||
openpgp-card-pcsc = { path = "../pcsc", version = "0.1" }
|
openpgp-card-pcsc = { path = "../pcsc", version = "0.1" }
|
||||||
pcsc="2"
|
|
||||||
openpgp-card-sequoia = { path = "../openpgp-card-sequoia", version = "0.0.7" }
|
openpgp-card-sequoia = { path = "../openpgp-card-sequoia", version = "0.0.7" }
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// 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_pcsc::{transaction, PcscCard, TxClient};
|
use openpgp_card_pcsc::PcscCard;
|
||||||
|
|
||||||
use openpgp_card_sequoia::card::Open;
|
use openpgp_card_sequoia::card::Open;
|
||||||
|
|
||||||
|
@ -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 = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut txc)?;
|
let mut open = Open::new(&mut txc)?;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// 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_pcsc::{transaction, PcscCard, TxClient};
|
use openpgp_card_pcsc::PcscCard;
|
||||||
|
|
||||||
use openpgp_card_sequoia::card::Open;
|
use openpgp_card_sequoia::card::Open;
|
||||||
|
|
||||||
|
@ -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 = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut txc)?;
|
let mut open = Open::new(&mut txc)?;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ sequoia-openpgp = "1.4"
|
||||||
nettle = "7"
|
nettle = "7"
|
||||||
openpgp-card = { path = "../openpgp-card", version = "0.1" }
|
openpgp-card = { path = "../openpgp-card", version = "0.1" }
|
||||||
openpgp-card-pcsc = { path = "../pcsc", version = "0.1" }
|
openpgp-card-pcsc = { path = "../pcsc", version = "0.1" }
|
||||||
pcsc = "2"
|
|
||||||
openpgp-card-scdc = { path = "../scdc", version = "0.1" }
|
openpgp-card-scdc = { path = "../scdc", version = "0.1" }
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use openpgp_card_sequoia::card::Open;
|
//! use openpgp_card_sequoia::card::Open;
|
||||||
//! use openpgp_card_pcsc::{transaction, PcscCard, TxClient};
|
//! use openpgp_card_pcsc::PcscCard;
|
||||||
//!
|
//!
|
||||||
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
//! for mut card in PcscCard::cards(None)? {
|
//! for mut card in PcscCard::cards(None)? {
|
||||||
//! let mut txc = transaction!(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,11 +30,11 @@
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use openpgp_card_sequoia::card::Open;
|
//! use openpgp_card_sequoia::card::Open;
|
||||||
//! use openpgp_card_pcsc::{transaction, PcscCard, TxClient};
|
//! use openpgp_card_pcsc::PcscCard;
|
||||||
//!
|
//!
|
||||||
//! # 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", None)?;
|
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
|
||||||
//! let mut txc = transaction!(card)?;
|
//! let mut txc = card.transaction()?;
|
||||||
//! let mut open = Open::new(&mut txc)?;
|
//! let mut open = Open::new(&mut txc)?;
|
||||||
//! # Ok(())
|
//! # Ok(())
|
||||||
//! # }
|
//! # }
|
||||||
|
@ -51,13 +51,13 @@
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use openpgp_card_sequoia::card::Open;
|
//! use openpgp_card_sequoia::card::Open;
|
||||||
//! use openpgp_card_pcsc::{transaction, PcscCard, TxClient};
|
//! use openpgp_card_pcsc::PcscCard;
|
||||||
//!
|
//!
|
||||||
//! # 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", None)?;
|
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
|
||||||
//! let mut txc = transaction!(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
|
||||||
|
@ -93,13 +93,13 @@
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use openpgp_card_sequoia::card::Open;
|
//! use openpgp_card_sequoia::card::Open;
|
||||||
//! use openpgp_card_pcsc::{transaction, PcscCard, TxClient};
|
//! use openpgp_card_pcsc::PcscCard;
|
||||||
//!
|
//!
|
||||||
//! # 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", None)?;
|
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
|
||||||
//! let mut txc = transaction!(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
|
||||||
|
@ -125,12 +125,12 @@
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use openpgp_card_sequoia::card::Open;
|
//! use openpgp_card_sequoia::card::Open;
|
||||||
//! use openpgp_card_pcsc::{transaction, PcscCard, TxClient};
|
//! use openpgp_card_pcsc::PcscCard;
|
||||||
//!
|
//!
|
||||||
//! # 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", None)?;
|
//! let mut card = PcscCard::open_by_ident("abcd:12345678", None)?;
|
||||||
//! let mut txc = transaction!(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
|
||||||
|
|
|
@ -11,7 +11,7 @@ use sequoia_openpgp::Cert;
|
||||||
|
|
||||||
use openpgp_card::card_do::Sex;
|
use openpgp_card::card_do::Sex;
|
||||||
use openpgp_card::KeyType;
|
use openpgp_card::KeyType;
|
||||||
use openpgp_card_pcsc::{transaction, PcscCard, TxClient};
|
use openpgp_card_pcsc::PcscCard;
|
||||||
|
|
||||||
use openpgp_card_sequoia::card::Open;
|
use openpgp_card_sequoia::card::Open;
|
||||||
use openpgp_card_sequoia::sq_util;
|
use openpgp_card_sequoia::sq_util;
|
||||||
|
@ -36,7 +36,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
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, None)?;
|
let mut card = PcscCard::open_by_ident(&test_card_ident, None)?;
|
||||||
let mut txc = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut txc)?;
|
let mut open = Open::new(&mut txc)?;
|
||||||
|
|
||||||
|
@ -147,7 +147,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, None)?;
|
let mut card = PcscCard::open_by_ident(&test_card_ident, None)?;
|
||||||
let mut txc = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut txc)?;
|
let mut open = Open::new(&mut txc)?;
|
||||||
|
|
||||||
|
@ -188,7 +188,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, None)?;
|
let mut card = PcscCard::open_by_ident(&test_card_ident, None)?;
|
||||||
let mut txc = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut txc)?;
|
let mut open = Open::new(&mut txc)?;
|
||||||
|
|
||||||
|
@ -220,7 +220,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(None)? {
|
for mut card in PcscCard::cards(None)? {
|
||||||
let mut txc = transaction!(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());
|
||||||
|
|
|
@ -14,6 +14,6 @@ documentation = "https://docs.rs/crate/openpgp-card-pcsc"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
openpgp-card = { path = "../openpgp-card", version = "0.1" }
|
openpgp-card = { path = "../openpgp-card", version = "0.1" }
|
||||||
iso7816-tlv = "0.4"
|
iso7816-tlv = "0.4"
|
||||||
pcsc = "2"
|
pcsc = { git = "https://github.com/bluetech/pcsc-rust/", rev = "ac1feee16d54bd6ba1681a201fc8f25808aa346d" }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
211
pcsc/src/lib.rs
211
pcsc/src/lib.rs
|
@ -16,101 +16,6 @@ use openpgp_card::{CardCaps, CardClient, 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;
|
||||||
|
|
||||||
/// Get a TxClient from a PcscCard (this starts a transaction on the card
|
|
||||||
/// in PcscCard)
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! transaction {
|
|
||||||
( $card:expr, $reselect:expr ) => {{
|
|
||||||
use openpgp_card::{Error, SmartcardError};
|
|
||||||
use pcsc::{Disposition, Protocols};
|
|
||||||
|
|
||||||
let mut was_reset = false;
|
|
||||||
|
|
||||||
let card_caps = $card.card_caps();
|
|
||||||
let reader_caps = $card.reader_caps().clone();
|
|
||||||
let mode = $card.mode();
|
|
||||||
|
|
||||||
let c = $card.card();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let res = c.transaction();
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Ok(mut tx) => {
|
|
||||||
// A transaction has been successfully started
|
|
||||||
|
|
||||||
if was_reset {
|
|
||||||
log::debug!(
|
|
||||||
"start_tx: card was reset, select() openpgp"
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut txc =
|
|
||||||
TxClient::new(tx, card_caps, reader_caps.clone());
|
|
||||||
|
|
||||||
// In contexts where the caller of this macro
|
|
||||||
// expects that the card has already been opened,
|
|
||||||
// re-open the card here.
|
|
||||||
// For initial card-opening, we don't do this, then
|
|
||||||
// the caller always expects a card that has not
|
|
||||||
// been "select"ed yet.
|
|
||||||
if $reselect {
|
|
||||||
match TxClient::select(&mut txc) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => break Err(err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tx = txc.tx();
|
|
||||||
}
|
|
||||||
|
|
||||||
let txc = TxClient::new(tx, card_caps, reader_caps);
|
|
||||||
|
|
||||||
break Ok(txc);
|
|
||||||
}
|
|
||||||
Err(pcsc::Error::ResetCard) => {
|
|
||||||
// Card was reset, need to reconnect
|
|
||||||
was_reset = true;
|
|
||||||
|
|
||||||
drop(res);
|
|
||||||
|
|
||||||
log::debug!("start_tx: do reconnect");
|
|
||||||
|
|
||||||
{
|
|
||||||
match c.reconnect(
|
|
||||||
mode,
|
|
||||||
Protocols::ANY,
|
|
||||||
Disposition::ResetCard,
|
|
||||||
) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => {
|
|
||||||
break Err(Error::Smartcard(
|
|
||||||
SmartcardError::Error(format!(
|
|
||||||
"Reconnect failed: {:?}",
|
|
||||||
err
|
|
||||||
)),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log::debug!("start_tx: reconnected.");
|
|
||||||
|
|
||||||
// -> try opening a transaction again
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::debug!("start_tx: error {:?}", e);
|
|
||||||
break Err(Error::Smartcard(SmartcardError::Error(
|
|
||||||
format!("Error: {:?}", e),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
( $card:expr ) => {
|
|
||||||
transaction!($card, true)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_mode(mode: Option<ShareMode>) -> ShareMode {
|
fn default_mode(mode: Option<ShareMode>) -> ShareMode {
|
||||||
if let Some(mode) = mode {
|
if let Some(mode) = mode {
|
||||||
mode
|
mode
|
||||||
|
@ -124,7 +29,7 @@ fn default_mode(mode: Option<ShareMode>) -> ShareMode {
|
||||||
///
|
///
|
||||||
/// This struct can be used to hold on to a Card, even while no operations
|
/// This struct can be used to hold on to a Card, even while no operations
|
||||||
/// are performed on the Card. To perform operations on the card, a
|
/// are performed on the Card. To perform operations on the card, a
|
||||||
/// `TxClient` object needs to be obtained (via the `get_txc!()` macro).
|
/// `TxClient` object needs to be obtained (via PcscCard::transaction()).
|
||||||
pub struct PcscCard {
|
pub struct PcscCard {
|
||||||
card: Card,
|
card: Card,
|
||||||
mode: ShareMode,
|
mode: ShareMode,
|
||||||
|
@ -136,8 +41,8 @@ pub struct PcscCard {
|
||||||
/// 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".
|
||||||
///
|
///
|
||||||
/// This struct is created from a PcscCard by opening a transaction, using the
|
/// This struct is created from a PcscCard by opening a transaction, using
|
||||||
/// `start_tx!` macro.
|
/// PcscCard::transaction().
|
||||||
///
|
///
|
||||||
/// Transactions on a card cannot be opened and left idle
|
/// Transactions on a card cannot be opened and left idle
|
||||||
/// (e.g. Microsoft documents that on Windows, they will be closed after
|
/// (e.g. Microsoft documents that on Windows, they will be closed after
|
||||||
|
@ -150,15 +55,95 @@ pub struct TxClient<'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> TxClient<'b> {
|
impl<'b> TxClient<'b> {
|
||||||
pub fn new(
|
/// Start a transaction on `card`.
|
||||||
tx: Transaction<'b>,
|
///
|
||||||
card_caps: Option<CardCaps>,
|
/// `reselect` set to `false` is only used internally in this crate,
|
||||||
reader_caps: HashMap<u8, Tlv>,
|
/// during initial setup of cards. Otherwise it must be `true`, to
|
||||||
) -> Self {
|
/// cause a select() call on cards that have been reset.
|
||||||
TxClient {
|
fn new(card: &'b mut PcscCard, reselect: bool) -> Result<Self> {
|
||||||
|
use pcsc::Disposition;
|
||||||
|
|
||||||
|
let mut was_reset = false;
|
||||||
|
|
||||||
|
let card_caps = card.card_caps();
|
||||||
|
let reader_caps = card.reader_caps().clone();
|
||||||
|
let mode = card.mode();
|
||||||
|
|
||||||
|
let mut c = card.card();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match c.transaction2() {
|
||||||
|
Ok(mut tx) => {
|
||||||
|
// A transaction has been successfully started
|
||||||
|
|
||||||
|
if was_reset {
|
||||||
|
log::debug!(
|
||||||
|
"start_tx: card was reset, select() openpgp"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut txc = Self {
|
||||||
tx,
|
tx,
|
||||||
card_caps,
|
card_caps,
|
||||||
reader_caps,
|
reader_caps: reader_caps.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// In contexts where the caller of this fn
|
||||||
|
// expects that the card has already been opened,
|
||||||
|
// re-open the card here.
|
||||||
|
// For initial card-opening, we don't do this, then
|
||||||
|
// the caller always expects a card that has not
|
||||||
|
// been "select"ed yet.
|
||||||
|
if reselect {
|
||||||
|
TxClient::select(&mut txc)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx = txc.tx();
|
||||||
|
}
|
||||||
|
|
||||||
|
let txc = Self {
|
||||||
|
tx,
|
||||||
|
card_caps,
|
||||||
|
reader_caps: reader_caps.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
break Ok(txc);
|
||||||
|
}
|
||||||
|
Err((c_, pcsc::Error::ResetCard)) => {
|
||||||
|
// Card was reset, need to reconnect
|
||||||
|
was_reset = true;
|
||||||
|
|
||||||
|
// drop(res);
|
||||||
|
|
||||||
|
c = c_;
|
||||||
|
|
||||||
|
log::debug!("start_tx: do reconnect");
|
||||||
|
|
||||||
|
{
|
||||||
|
c.reconnect(
|
||||||
|
mode,
|
||||||
|
Protocols::ANY,
|
||||||
|
Disposition::ResetCard,
|
||||||
|
)
|
||||||
|
.map_err(|e| {
|
||||||
|
Error::Smartcard(SmartcardError::Error(format!(
|
||||||
|
"Reconnect failed: {:?}",
|
||||||
|
e
|
||||||
|
)))
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
log::debug!("start_tx: reconnected.");
|
||||||
|
|
||||||
|
// -> try opening a transaction again
|
||||||
|
}
|
||||||
|
Err((_, e)) => {
|
||||||
|
log::debug!("start_tx: error {:?}", e);
|
||||||
|
break Err(Error::Smartcard(SmartcardError::Error(
|
||||||
|
format!("Error: {:?}", e),
|
||||||
|
))
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,6 +457,11 @@ 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> {
|
||||||
|
@ -563,7 +553,7 @@ impl PcscCard {
|
||||||
// start transaction
|
// start transaction
|
||||||
log::debug!("1");
|
log::debug!("1");
|
||||||
let mut p = PcscCard::new(card, mode);
|
let mut p = PcscCard::new(card, mode);
|
||||||
let mut txc: TxClient = transaction!(p, false)?;
|
let mut txc = TxClient::new(&mut p, false)?;
|
||||||
|
|
||||||
log::debug!("3");
|
log::debug!("3");
|
||||||
{
|
{
|
||||||
|
@ -588,7 +578,12 @@ impl PcscCard {
|
||||||
)))
|
)))
|
||||||
})?;
|
})?;
|
||||||
log::debug!("4b card status: {:x?}", stat);
|
log::debug!("4b card status: {:x?}", stat);
|
||||||
txc = TxClient::new(tx, None, HashMap::default());
|
txc = TxClient {
|
||||||
|
tx,
|
||||||
|
card_caps: None,
|
||||||
|
reader_caps: HashMap::default(),
|
||||||
|
};
|
||||||
|
|
||||||
// -- /debug: status --
|
// -- /debug: status --
|
||||||
|
|
||||||
if let Some(ident) = ident {
|
if let Some(ident) = ident {
|
||||||
|
@ -689,7 +684,7 @@ impl PcscCard {
|
||||||
|
|
||||||
let mut h: HashMap<u8, Tlv> = HashMap::default();
|
let mut h: HashMap<u8, Tlv> = HashMap::default();
|
||||||
|
|
||||||
let mut txc: TxClient = transaction!(self, true)?;
|
let mut txc = self.transaction()?;
|
||||||
|
|
||||||
// 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() {
|
||||||
|
|
|
@ -16,7 +16,6 @@ sequoia-openpgp = "1.3"
|
||||||
nettle = "7"
|
nettle = "7"
|
||||||
openpgp-card = { path = "../openpgp-card", version = "0.1" }
|
openpgp-card = { path = "../openpgp-card", version = "0.1" }
|
||||||
openpgp-card-pcsc = { path = "../pcsc", version = "0.1" }
|
openpgp-card-pcsc = { path = "../pcsc", version = "0.1" }
|
||||||
pcsc = "2"
|
|
||||||
openpgp-card-sequoia = { path = "../openpgp-card-sequoia", version = "0.0.7" }
|
openpgp-card-sequoia = { path = "../openpgp-card-sequoia", version = "0.0.7" }
|
||||||
sshkeys = "0.3"
|
sshkeys = "0.3"
|
||||||
rpassword = "5"
|
rpassword = "5"
|
||||||
|
|
|
@ -5,7 +5,7 @@ use anyhow::Result;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use openpgp_card::{CardClient, Error, StatusBytes};
|
use openpgp_card::{CardClient, Error, StatusBytes};
|
||||||
use openpgp_card_pcsc::{transaction, PcscCard, TxClient};
|
use openpgp_card_pcsc::PcscCard;
|
||||||
use openpgp_card_sequoia::card::Open;
|
use openpgp_card_sequoia::card::Open;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
@ -16,7 +16,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, None)?;
|
let mut card = PcscCard::open_by_ident(&cli.ident, None)?;
|
||||||
let mut txc = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
@ -13,7 +13,6 @@ use sequoia_openpgp::Cert;
|
||||||
|
|
||||||
use openpgp_card::algorithm::AlgoSimple;
|
use openpgp_card::algorithm::AlgoSimple;
|
||||||
use openpgp_card::{card_do::Sex, CardClient, KeyType};
|
use openpgp_card::{card_do::Sex, CardClient, KeyType};
|
||||||
use openpgp_card_pcsc::{transaction, TxClient};
|
|
||||||
|
|
||||||
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};
|
||||||
|
@ -72,7 +71,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
cmd,
|
cmd,
|
||||||
} => {
|
} => {
|
||||||
let mut card = util::open_card(&ident)?;
|
let mut card = util::open_card(&ident)?;
|
||||||
let mut txc = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut txc)?;
|
let mut open = Open::new(&mut txc)?;
|
||||||
|
|
||||||
|
@ -139,7 +138,7 @@ fn list_cards() -> Result<()> {
|
||||||
println!("Available OpenPGP cards:");
|
println!("Available OpenPGP cards:");
|
||||||
|
|
||||||
for mut card in cards {
|
for mut card in cards {
|
||||||
let mut txc = transaction!(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());
|
||||||
|
@ -155,7 +154,7 @@ fn set_identity(
|
||||||
id: u8,
|
id: u8,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut card = util::open_card(ident)?;
|
let mut card = util::open_card(ident)?;
|
||||||
let mut txc = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
<dyn CardClient>::set_identity(&mut txc, id)?;
|
<dyn CardClient>::set_identity(&mut txc, id)?;
|
||||||
|
|
||||||
|
@ -174,7 +173,7 @@ fn print_status(ident: Option<String>, verbose: bool) -> Result<()> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut txc = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut txc)?;
|
let mut open = Open::new(&mut txc)?;
|
||||||
|
|
||||||
|
@ -338,7 +337,7 @@ fn decrypt(
|
||||||
let input = util::open_or_stdin(input.as_deref())?;
|
let input = util::open_or_stdin(input.as_deref())?;
|
||||||
|
|
||||||
let mut card = util::open_card(ident)?;
|
let mut card = util::open_card(ident)?;
|
||||||
let mut txc = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut txc)?;
|
let mut open = Open::new(&mut txc)?;
|
||||||
|
|
||||||
|
@ -364,7 +363,7 @@ fn sign_detached(
|
||||||
let mut input = util::open_or_stdin(input.as_deref())?;
|
let mut input = util::open_or_stdin(input.as_deref())?;
|
||||||
|
|
||||||
let mut card = util::open_card(ident)?;
|
let mut card = util::open_card(ident)?;
|
||||||
let mut txc = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
let mut open = Open::new(&mut txc)?;
|
let mut open = Open::new(&mut txc)?;
|
||||||
|
|
||||||
|
@ -383,7 +382,7 @@ fn sign_detached(
|
||||||
fn factory_reset(ident: &str) -> Result<()> {
|
fn factory_reset(ident: &str) -> Result<()> {
|
||||||
println!("Resetting Card {}", ident);
|
println!("Resetting Card {}", ident);
|
||||||
let mut card = util::open_card(ident)?;
|
let mut card = util::open_card(ident)?;
|
||||||
let mut txc = transaction!(card)?;
|
let mut txc = card.transaction()?;
|
||||||
|
|
||||||
Open::new(&mut txc)?.factory_reset()
|
Open::new(&mut txc)?.factory_reset()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue