Implement discrete handling of v2 and v3 ExtendedCapabilities.
This commit is contained in:
parent
f2e5fea0fc
commit
3cc9a09290
3 changed files with 69 additions and 26 deletions
|
@ -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)
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue