diff --git a/card-backend/src/lib.rs b/card-backend/src/lib.rs index c0851a0..ef534c4 100644 --- a/card-backend/src/lib.rs +++ b/card-backend/src/lib.rs @@ -12,6 +12,11 @@ /// A [CardBackend] is only used to get access to a [CardTransaction] object, /// which supports transmitting commands to the card. 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( &mut self, reselect_application: Option<&[u8]>, diff --git a/openpgp-card/src/lib.rs b/openpgp-card/src/lib.rs index 3369f22..f327aea 100644 --- a/openpgp-card/src/lib.rs +++ b/openpgp-card/src/lib.rs @@ -188,7 +188,7 @@ impl Card { let ext_cap = ard.extended_capabilities()?; // 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() { // In card 3.x, max lengths come from ExtendedLengthInfo @@ -205,21 +205,6 @@ impl Card { let pw1_max = pw_status.pw1_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( ext_support, chaining_support, @@ -239,6 +224,12 @@ impl Card { 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) }; diff --git a/pcsc/src/lib.rs b/pcsc/src/lib.rs index 36fc681..71f5d18 100644 --- a/pcsc/src/lib.rs +++ b/pcsc/src/lib.rs @@ -546,6 +546,25 @@ impl 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) fn transaction( &mut self, diff --git a/scdc/src/lib.rs b/scdc/src/lib.rs index 9e80a08..9dacb4c 100644 --- a/scdc/src/lib.rs +++ b/scdc/src/lib.rs @@ -212,6 +212,19 @@ impl 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( &mut self, _reselect_application: Option<&[u8]>,