Implement a macro "start_tx!" for DRY transaction starting
This commit is contained in:
parent
748c334403
commit
b367043a12
2 changed files with 67 additions and 87 deletions
152
pcsc/src/lib.rs
152
pcsc/src/lib.rs
|
@ -19,6 +19,65 @@ use openpgp_card::{CardApp, 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;
|
||||||
|
|
||||||
|
macro_rules! start_tx {
|
||||||
|
($card:expr) => {{
|
||||||
|
let mut was_reset = false;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let res = $card.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(&mut tx);
|
||||||
|
TxClient::select(&mut txc)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
break tx;
|
||||||
|
}
|
||||||
|
Err(pcsc::Error::ResetCard) => {
|
||||||
|
// Card was reset, need to reconnect
|
||||||
|
was_reset = true;
|
||||||
|
|
||||||
|
drop(res);
|
||||||
|
|
||||||
|
log::debug!("start_tx: do reconnect");
|
||||||
|
|
||||||
|
{
|
||||||
|
$card
|
||||||
|
.reconnect(
|
||||||
|
ShareMode::Shared,
|
||||||
|
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);
|
||||||
|
return Err(Error::Smartcard(SmartcardError::Error(
|
||||||
|
format!("Error: {:?}", e),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
/// An implementation of the CardClient trait that uses the PCSC lite
|
/// An implementation of the CardClient trait that uses the PCSC lite
|
||||||
/// middleware to access the OpenPGP card application on smart cards.
|
/// middleware to access the OpenPGP card application on smart cards.
|
||||||
pub struct PcscClient {
|
pub struct PcscClient {
|
||||||
|
@ -177,10 +236,12 @@ impl PcscClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cards_filter(ident: Option<&str>) -> Result<Vec<CardApp>> {
|
fn cards_filter(ident: Option<&str>) -> Result<Vec<CardApp>, Error> {
|
||||||
let mut cas: Vec<CardApp> = vec![];
|
let mut cas: Vec<CardApp> = vec![];
|
||||||
|
|
||||||
for mut card in Self::raw_pcsc_cards()? {
|
for mut card in
|
||||||
|
Self::raw_pcsc_cards().map_err(|sce| Error::Smartcard(sce))?
|
||||||
|
{
|
||||||
log::debug!("cards_filter: next card");
|
log::debug!("cards_filter: next card");
|
||||||
|
|
||||||
let stat = card.status2_owned();
|
let stat = card.status2_owned();
|
||||||
|
@ -190,37 +251,8 @@ impl PcscClient {
|
||||||
{
|
{
|
||||||
// start transaction
|
// start transaction
|
||||||
log::debug!("1");
|
log::debug!("1");
|
||||||
|
let mut tx: Transaction = start_tx!(card);
|
||||||
|
|
||||||
let mut tx = loop {
|
|
||||||
let res = card.transaction();
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Ok(tx) => break tx,
|
|
||||||
Err(pcsc::Error::ResetCard) => {
|
|
||||||
// Card was reset, need to reconnect
|
|
||||||
drop(res);
|
|
||||||
|
|
||||||
log::debug!("1a");
|
|
||||||
|
|
||||||
{
|
|
||||||
card.reconnect(
|
|
||||||
ShareMode::Shared,
|
|
||||||
Protocols::ANY,
|
|
||||||
Disposition::ResetCard,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
log::debug!("1b");
|
|
||||||
|
|
||||||
// try again
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
return Err(e.into());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
log::debug!("2");
|
|
||||||
let mut txc = TxClient::new(&mut tx);
|
let mut txc = TxClient::new(&mut tx);
|
||||||
log::debug!("3");
|
log::debug!("3");
|
||||||
{
|
{
|
||||||
|
@ -284,7 +316,7 @@ impl PcscClient {
|
||||||
///
|
///
|
||||||
/// Each card has the OpenPGP application selected, CardCaps have been
|
/// Each card has the OpenPGP application selected, CardCaps have been
|
||||||
/// initialized.
|
/// initialized.
|
||||||
pub fn cards() -> Result<Vec<CardApp>> {
|
pub fn cards() -> Result<Vec<CardApp>, Error> {
|
||||||
Self::cards_filter(None)
|
Self::cards_filter(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,62 +409,10 @@ impl CardClient for PcscClient {
|
||||||
cmd: &[u8],
|
cmd: &[u8],
|
||||||
buf_size: usize,
|
buf_size: usize,
|
||||||
) -> Result<Vec<u8>, Error> {
|
) -> Result<Vec<u8>, Error> {
|
||||||
let mut was_reset = false;
|
|
||||||
|
|
||||||
let stat = self.card.status2_owned();
|
let stat = self.card.status2_owned();
|
||||||
log::debug!("PcscClient transmit - status2: {:x?}", stat);
|
log::debug!("PcscClient transmit - status2: {:x?}", stat);
|
||||||
|
|
||||||
let mut tx = loop {
|
let mut tx: Transaction = start_tx!(self.card);
|
||||||
let res = self.card.transaction();
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Ok(mut tx) => {
|
|
||||||
// A transaction has been successfully started
|
|
||||||
|
|
||||||
if was_reset {
|
|
||||||
log::debug!("card was reset, select() openpgp");
|
|
||||||
|
|
||||||
let mut txc = TxClient::new(&mut tx);
|
|
||||||
TxClient::select(&mut txc)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
break tx;
|
|
||||||
}
|
|
||||||
Err(pcsc::Error::ResetCard) => {
|
|
||||||
// Error getting Transaction.
|
|
||||||
// Card was reset -> need to reconnect.
|
|
||||||
|
|
||||||
was_reset = true;
|
|
||||||
|
|
||||||
drop(res);
|
|
||||||
|
|
||||||
log::debug!("PcscClient transmit 1a");
|
|
||||||
|
|
||||||
{
|
|
||||||
self.card
|
|
||||||
.reconnect(
|
|
||||||
ShareMode::Shared,
|
|
||||||
Protocols::ANY,
|
|
||||||
Disposition::ResetCard,
|
|
||||||
)
|
|
||||||
.map_err(|e| {
|
|
||||||
Error::Smartcard(SmartcardError::Error(
|
|
||||||
format!("Reconnect failed: {:?}", e),
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
|
|
||||||
log::debug!("PcscClient transmit 1b");
|
|
||||||
|
|
||||||
// try again
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
return Err(Error::Smartcard(SmartcardError::Error(
|
|
||||||
format!("Error: {:?}", e),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
log::debug!("PcscClient transmit 2");
|
log::debug!("PcscClient transmit 2");
|
||||||
let mut txc = TxClient::new(&mut tx);
|
let mut txc = TxClient::new(&mut tx);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use openpgp_card::{CardApp, Error};
|
||||||
use openpgp_card_pcsc::PcscClient;
|
use openpgp_card_pcsc::PcscClient;
|
||||||
use openpgp_card_sequoia::card::{Admin, Open, Sign, User};
|
use openpgp_card_sequoia::card::{Admin, Open, Sign, User};
|
||||||
|
|
||||||
pub(crate) fn cards() -> Result<Vec<CardApp>> {
|
pub(crate) fn cards() -> Result<Vec<CardApp>, Error> {
|
||||||
PcscClient::cards()
|
PcscClient::cards()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue