Implement discrete handling of v2 and v3 ExtendedCapabilities.

This commit is contained in:
Heiko Schaefer 2021-09-15 17:39:47 +02:00
parent f2e5fea0fc
commit 3cc9a09290
3 changed files with 69 additions and 26 deletions

View file

@ -70,10 +70,15 @@ impl CardApp {
} }
} }
let ext_cap = ard.get_extended_capabilities()?;
let (max_cmd_bytes, max_rsp_bytes) = let (max_cmd_bytes, max_rsp_bytes) =
// FIXME: handle cmd/resp limits in ex-cap, for card <3.0 (?) // FIXME: handle cmd/resp limits in ex-cap, for card <3.0 (?)
if let Ok(Some(eli)) = ard.get_extended_length_information() { if let Ok(Some(eli)) = ard.get_extended_length_information() {
(eli.max_command_bytes(), eli.max_response_bytes()) (eli.max_command_bytes(), eli.max_response_bytes())
} else if let (Some(cmd), Some(rsp))
= (ext_cap.max_cmd_len(), ext_cap.max_resp_len()) {
(cmd, rsp)
} else { } else {
(255, 255) (255, 255)
}; };

View file

@ -254,9 +254,13 @@ pub struct ExtendedCapabilities {
sm_algo: u8, sm_algo: u8,
max_len_challenge: u16, max_len_challenge: u16,
max_len_cardholder_cert: u16, max_len_cardholder_cert: u16,
max_len_special_do: u16,
pin_block_2_format_support: bool, max_cmd_len: Option<u16>, // v2
mse_command_support: bool, max_resp_len: Option<u16>, // v2
max_len_special_do: Option<u16>, // v3
pin_block_2_format_support: Option<bool>, // v3
mse_command_support: Option<bool>, // v3
} }
/// 4.1.3.1 Extended length information /// 4.1.3.1 Extended length information

View file

@ -10,23 +10,35 @@ use crate::card_do::ExtendedCapabilities;
use crate::Error; use crate::Error;
impl ExtendedCapabilities { impl ExtendedCapabilities {
pub fn max_len_special_do(&self) -> u16 { pub fn max_len_special_do(&self) -> Option<u16> {
self.max_len_special_do self.max_len_special_do
} }
pub fn algo_attrs_changeable(&self) -> bool { pub fn algo_attrs_changeable(&self) -> bool {
self.algo_attrs_changeable self.algo_attrs_changeable
} }
pub fn max_cmd_len(&self) -> Option<u16> {
self.max_cmd_len
}
pub fn max_resp_len(&self) -> Option<u16> {
self.max_resp_len
}
} }
impl TryFrom<(&[u8], u16)> for ExtendedCapabilities { impl TryFrom<(&[u8], u16)> for ExtendedCapabilities {
type Error = Error; type Error = Error;
fn try_from((input, version): (&[u8], u16)) -> Result<Self, Self::Error> { fn try_from((input, version): (&[u8], u16)) -> Result<Self, Self::Error> {
// FIXME: handle different card versions. // FIXME: check that this fn is not called excessively often
// e.g. bytes 07/08 and 09/0A have different meanings before and
// after V3.0
let version = ((version >> 8) as u8, (version & 0xff) as u8);
// FIXME: earlier versions have shorter extended capabilities
assert!(version.0 >= 2);
// v2.x and v3.x should have 10 byte sized extended caps
assert_eq!( assert_eq!(
input.len(), input.len(),
10, 10,
@ -48,25 +60,43 @@ impl TryFrom<(&[u8], u16)> for ExtendedCapabilities {
let max_len_challenge = input[2] as u16 * 256 + input[3] as u16; let max_len_challenge = input[2] as u16 * 256 + input[3] as u16;
let max_len_cardholder_cert = input[4] as u16 * 256 + input[5] as u16; let max_len_cardholder_cert = input[4] as u16 * 256 + input[5] as u16;
let max_len_special_do = input[6] as u16 * 256 + input[7] as u16;
let pin_block_2_format_support = input[8]; let mut max_cmd_len = None;
let mse_command_support = input[9]; let mut max_resp_len = None;
if pin_block_2_format_support > 1 { let mut max_len_special_do = None;
return Err(anyhow!( let mut pin_block_2_format_support = None;
"Illegal value '{}' for pin_block_2_format_support", let mut mse_command_support = None;
pin_block_2_format_support
)
.into());
}
if mse_command_support > 1 { if version.0 == 2 {
return Err(anyhow!( // v2.0 until v2.2
"Illegal value '{}' for mse_command_support", max_cmd_len = Some(input[6] as u16 * 256 + input[7] as u16);
mse_command_support max_resp_len = Some(input[8] as u16 * 256 + input[9] as u16);
) } else {
.into()); // from v3.0
max_len_special_do = Some(input[6] as u16 * 256 + input[7] as u16);
let i8 = input[8];
let i9 = input[9];
if i8 > 1 {
return Err(anyhow!(
"Illegal value '{}' for pin_block_2_format_support",
i8
)
.into());
}
pin_block_2_format_support = Some(i8 != 0);
if i9 > 1 {
return Err(anyhow!(
"Illegal value '{}' for mse_command_support",
i9
)
.into());
}
mse_command_support = Some(i9 != 0);
} }
Ok(Self { Ok(Self {
@ -82,9 +112,13 @@ impl TryFrom<(&[u8], u16)> for ExtendedCapabilities {
sm_algo, sm_algo,
max_len_challenge, max_len_challenge,
max_len_cardholder_cert, max_len_cardholder_cert,
max_len_special_do,
pin_block_2_format_support: pin_block_2_format_support != 0, max_cmd_len, // v2
mse_command_support: mse_command_support != 0, max_resp_len, // v2
max_len_special_do, // v3
pin_block_2_format_support, // v3
mse_command_support, // v3
}) })
} }
} }