Refactor for multiple card backends
This commit is contained in:
parent
610478695f
commit
0fffb0c91b
3 changed files with 62 additions and 33 deletions
|
@ -11,6 +11,8 @@ use std::convert::TryFrom;
|
|||
|
||||
use crate::apdu::command::Command;
|
||||
use crate::apdu::response::Response;
|
||||
use crate::card;
|
||||
use crate::card_app::CardApp;
|
||||
use crate::errors::{OcErrorStatus, OpenpgpCardError, SmartcardError};
|
||||
use crate::{CardBase, CardCaps, CardClient, CardClientBox};
|
||||
|
||||
|
@ -188,6 +190,14 @@ impl PcscClient {
|
|||
Self { card }
|
||||
}
|
||||
|
||||
pub fn list_cards() -> Result<Vec<PcscClient>> {
|
||||
Ok(card::get_cards()
|
||||
.map_err(|err| anyhow!(err))?
|
||||
.into_iter()
|
||||
.map(PcscClient::new)
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Take a PCSC Card object and try to open the OpenPGP card applet.
|
||||
/// If successful, wrap and return the resulting CardClient as a
|
||||
/// CardBase object (which involves caching the "application related
|
||||
|
@ -196,11 +206,11 @@ impl PcscClient {
|
|||
let card_client = PcscClient::new(card);
|
||||
let mut ccb = Box::new(card_client) as CardClientBox;
|
||||
|
||||
let select_openpgp = commands::select_openpgp();
|
||||
let resp = send_command(&mut ccb, select_openpgp, false, None)?;
|
||||
let mut ca = CardApp::new(ccb);
|
||||
let resp = ca.select()?;
|
||||
|
||||
if resp.is_ok() {
|
||||
CardBase::open_card(ccb)
|
||||
CardBase::open_card(ca.take_card())
|
||||
} else {
|
||||
Err(anyhow!("Couldn't open OpenPGP application").into())
|
||||
}
|
||||
|
|
|
@ -42,6 +42,43 @@ impl CardApp {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn take_card(self) -> CardClientBox {
|
||||
self.card_client
|
||||
}
|
||||
|
||||
/// Read capabilities from the card, and set them in the CardApp
|
||||
pub fn init_caps(mut self, ard: &Tlv) -> Result<Self> {
|
||||
// Determine chaining/extended length support from card
|
||||
// metadata and cache this information in CardApp (as a
|
||||
// CardCaps)
|
||||
|
||||
let mut ext_support = false;
|
||||
let mut chaining_support = false;
|
||||
|
||||
if let Ok(hist) = CardApp::get_historical(&ard) {
|
||||
if let Some(cc) = hist.get_card_capabilities() {
|
||||
chaining_support = cc.get_command_chaining();
|
||||
ext_support = cc.get_extended_lc_le();
|
||||
}
|
||||
}
|
||||
|
||||
let max_cmd_bytes = if let Ok(Some(eli)) =
|
||||
CardApp::get_extended_length_information(&ard)
|
||||
{
|
||||
eli.max_command_bytes
|
||||
} else {
|
||||
255
|
||||
};
|
||||
|
||||
let caps = CardCaps {
|
||||
ext_support,
|
||||
chaining_support,
|
||||
max_cmd_bytes,
|
||||
};
|
||||
|
||||
Ok(self.set_caps(caps))
|
||||
}
|
||||
|
||||
pub fn set_caps(self, card_caps: CardCaps) -> Self {
|
||||
Self {
|
||||
card_client: self.card_client,
|
||||
|
@ -57,6 +94,14 @@ impl CardApp {
|
|||
self.card_caps.as_ref()
|
||||
}
|
||||
|
||||
// --- select ---
|
||||
|
||||
/// "Select" the OpenPGP card application
|
||||
pub fn select(&mut self) -> Result<Response, OpenpgpCardError> {
|
||||
let select_openpgp = commands::select_openpgp();
|
||||
apdu::send_command(&mut self.card_client, select_openpgp, false, None)
|
||||
}
|
||||
|
||||
// --- application data ---
|
||||
|
||||
/// Load "application related data".
|
||||
|
|
|
@ -18,7 +18,7 @@ use crate::card_app::CardApp;
|
|||
use crate::errors::{OpenpgpCardError, SmartcardError};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
mod apdu;
|
||||
pub mod apdu;
|
||||
mod card;
|
||||
pub mod card_app;
|
||||
pub mod errors;
|
||||
|
@ -145,7 +145,7 @@ pub enum DecryptMe<'a> {
|
|||
ECDH(&'a [u8]),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Sex {
|
||||
NotKnown,
|
||||
Male,
|
||||
|
@ -314,36 +314,10 @@ impl CardBase {
|
|||
pub fn open_card(ccb: CardClientBox) -> Result<Self, OpenpgpCardError> {
|
||||
// read and cache "application related data"
|
||||
let mut card_app = CardApp::new(ccb);
|
||||
|
||||
let ard = card_app.get_app_data()?;
|
||||
|
||||
// Determine chaining/extended length support from card
|
||||
// metadata and cache this information in CardApp (as a
|
||||
// CardCaps)
|
||||
|
||||
let mut ext_support = false;
|
||||
let mut chaining_support = false;
|
||||
|
||||
if let Ok(hist) = CardApp::get_historical(&ard) {
|
||||
if let Some(cc) = hist.get_card_capabilities() {
|
||||
chaining_support = cc.get_command_chaining();
|
||||
ext_support = cc.get_extended_lc_le();
|
||||
}
|
||||
}
|
||||
|
||||
let max_cmd_bytes = if let Ok(Some(eli)) =
|
||||
CardApp::get_extended_length_information(&ard)
|
||||
{
|
||||
eli.max_command_bytes
|
||||
} else {
|
||||
255
|
||||
};
|
||||
|
||||
let caps = CardCaps {
|
||||
ext_support,
|
||||
chaining_support,
|
||||
max_cmd_bytes,
|
||||
};
|
||||
let card_app = card_app.set_caps(caps);
|
||||
card_app = card_app.init_caps(&ard)?;
|
||||
|
||||
Ok(Self { card_app, ard })
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue