Run each test in a PCSC Transaction.

(Disabled scdc support in the tests, for now)
This commit is contained in:
Heiko Schaefer 2022-01-14 22:29:15 +01:00
parent 5e7fcd079b
commit 514d055c90
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
4 changed files with 49 additions and 26 deletions

View file

@ -32,6 +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"
sequoia-openpgp = "1.3" sequoia-openpgp = "1.3"
anyhow = "1" anyhow = "1"
thiserror = "1.0" thiserror = "1.0"

View file

@ -38,9 +38,7 @@ pub struct TestCardApp {
} }
impl TestCardApp { impl TestCardApp {
pub(crate) fn get_card_client( pub(crate) fn get_card_client(&self) -> Result<Box<PcscClient>> {
&self,
) -> Result<Box<dyn CardClient + Send + Sync>> {
self.tc.open() self.tc.open()
} }
@ -91,7 +89,7 @@ pub enum TestCard {
} }
impl TestCard { impl TestCard {
pub fn open(&self) -> Result<Box<dyn CardClient + Send + Sync>> { pub fn open(&self) -> Result<Box<PcscClient>> {
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.
@ -102,8 +100,9 @@ impl TestCard {
Ok(Box::new(PcscClient::open_by_ident(ident)?)) Ok(Box::new(PcscClient::open_by_ident(ident)?))
} }
Self::Scdc(serial) => { Self::Scdc(serial) => {
// println!("open scdc card {}", serial); unimplemented!();
Ok(Box::new(ScdClient::open_by_serial(None, serial)?)) println!("open scdc card {}", serial);
// Ok(Box::new(ScdClient::open_by_serial(None, serial)?))
} }
} }
} }

View file

@ -16,6 +16,7 @@ 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::{CardApp, CardClient, Error, KeyType, StatusBytes}; use openpgp_card::{CardApp, CardClient, Error, KeyType, StatusBytes};
use openpgp_card_pcsc::{PcscClient, PcscTxClient};
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,
@ -698,8 +699,19 @@ pub fn run_test(
param: &[&str], param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let mut card_client = card.get_card_client()?; let mut card_client = card.get_card_client()?;
let ard = CardApp::application_related_data(&mut *card_client)?;
use anyhow::anyhow;
use openpgp_card::SmartcardError;
use openpgp_card_pcsc::PcscTxClient;
use pcsc::Transaction;
let mut tx: Transaction = openpgp_card_pcsc::start_tx!(card_client.card())
.map_err(|e| anyhow!(e))?;
let mut txc = PcscTxClient::new(&mut tx);
let ard = CardApp::application_related_data(&mut txc)?;
let _app_id = ard.application_id()?; let _app_id = ard.application_id()?;
t(&mut *card_client, param) t(&mut txc, param)
} }

View file

@ -19,8 +19,14 @@ 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_export]
macro_rules! start_tx { macro_rules! start_tx {
($card:expr) => {{ ($card:expr) => {{
use pcsc::{
Card, Context, Disposition, Protocols, Scope, ShareMode,
Transaction,
};
let mut was_reset = false; let mut was_reset = false;
loop { loop {
@ -35,11 +41,11 @@ macro_rules! start_tx {
"start_tx: card was reset, select() openpgp" "start_tx: card was reset, select() openpgp"
); );
let mut txc = TxClient::new(&mut tx); let mut txc = PcscTxClient::new(&mut tx);
TxClient::select(&mut txc)?; PcscTxClient::select(&mut txc)?;
} }
break tx; break Ok(tx);
} }
Err(pcsc::Error::ResetCard) => { Err(pcsc::Error::ResetCard) => {
// Card was reset, need to reconnect // Card was reset, need to reconnect
@ -69,7 +75,7 @@ macro_rules! start_tx {
} }
Err(e) => { Err(e) => {
log::debug!("start_tx: error {:?}", e); log::debug!("start_tx: error {:?}", e);
return Err(Error::Smartcard(SmartcardError::Error( break Err(Error::Smartcard(SmartcardError::Error(
format!("Error: {:?}", e), format!("Error: {:?}", e),
))); )));
} }
@ -86,19 +92,19 @@ pub struct PcscClient {
reader_caps: HashMap<u8, Tlv>, reader_caps: HashMap<u8, Tlv>,
} }
struct TxClient<'a, 'b> { pub struct PcscTxClient<'a, 'b> {
tx: &'a mut Transaction<'b>, tx: &'a mut Transaction<'b>,
} }
impl<'a, 'b> TxClient<'a, 'b> { impl<'a, 'b> PcscTxClient<'a, 'b> {
pub fn new(tx: &'a mut Transaction<'b>) -> Self { pub fn new(tx: &'a mut Transaction<'b>) -> Self {
TxClient { tx } PcscTxClient { tx }
} }
} }
impl<'a, 'b> TxClient<'a, 'b> { impl<'a, 'b> PcscTxClient<'a, 'b> {
/// Try to select the OpenPGP application on a card /// Try to select the OpenPGP application on a card
fn select(card_client: &'a mut TxClient) -> Result<(), Error> { pub fn select(card_client: &'a mut PcscTxClient) -> Result<(), Error> {
if <dyn CardClient>::select(card_client).is_ok() { if <dyn CardClient>::select(card_client).is_ok() {
Ok(()) Ok(())
} else { } else {
@ -108,7 +114,7 @@ impl<'a, 'b> TxClient<'a, 'b> {
/// Get application_related_data from card /// Get application_related_data from card
fn application_related_data( fn application_related_data(
card_client: &mut TxClient, card_client: &mut PcscTxClient,
) -> Result<ApplicationRelatedData, Error> { ) -> Result<ApplicationRelatedData, Error> {
<dyn CardClient>::application_related_data(card_client).map_err(|e| { <dyn CardClient>::application_related_data(card_client).map_err(|e| {
Error::Smartcard(SmartcardError::Error(format!( Error::Smartcard(SmartcardError::Error(format!(
@ -119,7 +125,7 @@ impl<'a, 'b> TxClient<'a, 'b> {
} }
} }
impl CardClient for TxClient<'_, '_> { impl CardClient for PcscTxClient<'_, '_> {
fn transmit( fn transmit(
&mut self, &mut self,
cmd: &[u8], cmd: &[u8],
@ -171,6 +177,10 @@ impl CardClient for TxClient<'_, '_> {
} }
impl PcscClient { impl PcscClient {
pub fn card(&mut self) -> &mut Card {
&mut self.card
}
/// 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() -> Result<Vec<Card>, SmartcardError> {
@ -251,12 +261,12 @@ impl PcscClient {
{ {
// start transaction // start transaction
log::debug!("1"); log::debug!("1");
let mut tx: Transaction = start_tx!(card); let mut tx: Transaction = start_tx!(card)?;
let mut txc = TxClient::new(&mut tx); let mut txc = PcscTxClient::new(&mut tx);
log::debug!("3"); log::debug!("3");
{ {
if let Err(e) = TxClient::select(&mut txc) { if let Err(e) = PcscTxClient::select(&mut txc) {
log::debug!("4a"); log::debug!("4a");
log::debug!( log::debug!(
"cards_filter: error during select: {:?}", "cards_filter: error during select: {:?}",
@ -267,8 +277,9 @@ impl PcscClient {
// successfully opened the OpenPGP application // successfully opened the OpenPGP application
if let Some(ident) = ident { if let Some(ident) = ident {
let ard = let ard = PcscTxClient::application_related_data(
TxClient::application_related_data(&mut txc)?; &mut txc,
)?;
let aid = ard.application_id()?; let aid = ard.application_id()?;
if aid.ident() == ident.to_ascii_uppercase() { if aid.ident() == ident.to_ascii_uppercase() {
@ -414,10 +425,10 @@ impl CardClient for PcscClient {
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: Transaction = start_tx!(self.card); let mut tx: Transaction = start_tx!(self.card)?;
log::debug!("PcscClient transmit 2"); log::debug!("PcscClient transmit 2");
let mut txc = TxClient::new(&mut tx); let mut txc = PcscTxClient::new(&mut tx);
log::debug!("PcscClient transmit 3 (got TxClient!)"); log::debug!("PcscClient transmit 3 (got TxClient!)");
let res = txc.transmit(cmd, buf_size); let res = txc.transmit(cmd, buf_size);