backend: add CardBackend::limit_card_caps
This mechanism allows the pcsc backend to signal to openpgp-card that a reader doesn't support "extended length".
This commit is contained in:
parent
e476103e6d
commit
31eee9e738
4 changed files with 44 additions and 16 deletions
|
@ -12,6 +12,11 @@
|
||||||
/// A [CardBackend] is only used to get access to a [CardTransaction] object,
|
/// A [CardBackend] is only used to get access to a [CardTransaction] object,
|
||||||
/// which supports transmitting commands to the card.
|
/// which supports transmitting commands to the card.
|
||||||
pub trait CardBackend {
|
pub trait CardBackend {
|
||||||
|
/// If a CardBackend introduces a additional (possibly backend-specific)
|
||||||
|
/// limits for any fields in CardCaps, this fn can indicate that limit by
|
||||||
|
/// returning an amended [`CardCaps`].
|
||||||
|
fn limit_card_caps(&self, card_caps: CardCaps) -> CardCaps;
|
||||||
|
|
||||||
fn transaction(
|
fn transaction(
|
||||||
&mut self,
|
&mut self,
|
||||||
reselect_application: Option<&[u8]>,
|
reselect_application: Option<&[u8]>,
|
||||||
|
|
|
@ -188,7 +188,7 @@ impl Card {
|
||||||
let ext_cap = ard.extended_capabilities()?;
|
let ext_cap = ard.extended_capabilities()?;
|
||||||
|
|
||||||
// Get max command/response byte sizes from card
|
// Get max command/response byte sizes from card
|
||||||
let (mut max_cmd_bytes, max_rsp_bytes) = if let Ok(Some(eli)) =
|
let (max_cmd_bytes, max_rsp_bytes) = if let Ok(Some(eli)) =
|
||||||
ard.extended_length_information()
|
ard.extended_length_information()
|
||||||
{
|
{
|
||||||
// In card 3.x, max lengths come from ExtendedLengthInfo
|
// In card 3.x, max lengths come from ExtendedLengthInfo
|
||||||
|
@ -205,21 +205,6 @@ impl Card {
|
||||||
let pw1_max = pw_status.pw1_max_len();
|
let pw1_max = pw_status.pw1_max_len();
|
||||||
let pw3_max = pw_status.pw3_max_len();
|
let pw3_max = pw_status.pw3_max_len();
|
||||||
|
|
||||||
// If the CardTransaction implementation has an inherent limit for the cmd
|
|
||||||
// size, take that limit into account.
|
|
||||||
// (E.g. when using scdaemon as a CardTransaction backend, there is a
|
|
||||||
// limitation to 1000 bytes length for Assuan commands, which
|
|
||||||
// translates to maximum command length of a bit under 500 bytes)
|
|
||||||
if let Some(max_card_cmd_bytes) = tx.tx.max_cmd_len() {
|
|
||||||
max_cmd_bytes = u16::min(max_cmd_bytes, max_card_cmd_bytes as u16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: add a more general mechanism to ask the backend for
|
|
||||||
// amendments to the CardCaps (e.g. to change support for
|
|
||||||
// "extended length")
|
|
||||||
//
|
|
||||||
// Also see https://blog.apdu.fr/posts/2011/05/extended-apdu-status-per-reader/
|
|
||||||
|
|
||||||
let caps = CardCaps::new(
|
let caps = CardCaps::new(
|
||||||
ext_support,
|
ext_support,
|
||||||
chaining_support,
|
chaining_support,
|
||||||
|
@ -239,6 +224,12 @@ impl Card {
|
||||||
|
|
||||||
drop(tx);
|
drop(tx);
|
||||||
|
|
||||||
|
// General mechanism to ask the backend for amendments to
|
||||||
|
// the CardCaps (e.g. to change support for "extended length")
|
||||||
|
//
|
||||||
|
// Also see https://blog.apdu.fr/posts/2011/05/extended-apdu-status-per-reader/
|
||||||
|
let caps = op.card.limit_card_caps(caps);
|
||||||
|
|
||||||
(caps, imm)
|
(caps, imm)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -546,6 +546,25 @@ impl PcscBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardBackend for PcscBackend {
|
impl CardBackend for PcscBackend {
|
||||||
|
fn limit_card_caps(&self, card_caps: CardCaps) -> CardCaps {
|
||||||
|
let mut ext = card_caps.ext_support();
|
||||||
|
|
||||||
|
// Disable "extended length" support when the card reader is known not to support it
|
||||||
|
if self.reader_name.starts_with("ACS ACR122U") {
|
||||||
|
log::debug!("Disabling ext_support for reader {}", self.reader_name);
|
||||||
|
ext = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CardCaps::new(
|
||||||
|
ext,
|
||||||
|
card_caps.chaining_support(),
|
||||||
|
card_caps.max_cmd_bytes(),
|
||||||
|
card_caps.max_rsp_bytes(),
|
||||||
|
card_caps.pw1_max_len(),
|
||||||
|
card_caps.pw3_max_len(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a CardTransaction for this PcscBackend (this starts a transaction)
|
/// Get a CardTransaction for this PcscBackend (this starts a transaction)
|
||||||
fn transaction(
|
fn transaction(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -212,6 +212,19 @@ impl ScdBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardBackend for ScdBackend {
|
impl CardBackend for ScdBackend {
|
||||||
|
fn limit_card_caps(&self, card_caps: CardCaps) -> CardCaps {
|
||||||
|
let max_cmd_bytes = u16::min(APDU_CMD_BYTES_MAX as u16, card_caps.max_cmd_bytes());
|
||||||
|
|
||||||
|
CardCaps::new(
|
||||||
|
card_caps.ext_support(),
|
||||||
|
card_caps.chaining_support(),
|
||||||
|
max_cmd_bytes,
|
||||||
|
card_caps.max_rsp_bytes(),
|
||||||
|
card_caps.pw1_max_len(),
|
||||||
|
card_caps.pw3_max_len(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn transaction(
|
fn transaction(
|
||||||
&mut self,
|
&mut self,
|
||||||
_reselect_application: Option<&[u8]>,
|
_reselect_application: Option<&[u8]>,
|
||||||
|
|
Loading…
Reference in a new issue