Handle SW_EXACT_LENGTH (0x6c??) in send_command()

This commit is contained in:
Heiko Schaefer 2021-09-17 13:36:20 +02:00
parent 60c67d3ebe
commit a39f25d8a3
2 changed files with 36 additions and 9 deletions

View file

@ -11,6 +11,7 @@ pub mod response;
use anyhow::Result;
use std::convert::TryFrom;
use crate::apdu::command::Expect;
use crate::apdu::{command::Command, response::RawResponse};
use crate::{CardClientBox, Error, StatusBytes};
@ -28,10 +29,22 @@ pub(crate) fn send_command(
) -> Result<RawResponse, Error> {
let mut resp = RawResponse::try_from(send_command_low_level(
card_client,
cmd,
expect_reply,
cmd.clone(),
if expect_reply {
Expect::Some
} else {
Expect::Empty
},
)?)?;
if let StatusBytes::UnknownStatus(0x6c, size) = resp.status() {
resp = RawResponse::try_from(send_command_low_level(
card_client,
cmd,
Expect::Short(size),
)?)?;
}
while let StatusBytes::OkBytesAvailable(_) = resp.status() {
// More data is available for this command from the card
log::debug!(" chained response, getting more data");
@ -40,7 +53,7 @@ pub(crate) fn send_command(
let next = RawResponse::try_from(send_command_low_level(
card_client,
commands::get_response(),
expect_reply,
Expect::Some,
)?)?;
match next.status() {
@ -71,7 +84,7 @@ pub(crate) fn send_command(
fn send_command_low_level(
card_client: &mut CardClientBox,
cmd: Command,
expect_response: bool,
expect_response: Expect,
) -> Result<Vec<u8>, Error> {
let (ext_support, chaining_support, mut max_cmd_bytes, max_rsp_bytes) =
if let Some(caps) = card_client.get_caps() {

View file

@ -6,6 +6,13 @@
use anyhow::Result;
#[derive(Clone, Copy)]
pub enum Expect {
Empty,
Some,
Short(u8),
}
#[derive(Clone, Debug)]
pub(crate) struct Command {
// Class byte (CLA)
@ -63,7 +70,7 @@ impl Command {
pub(crate) fn serialize(
&self,
ext_len: bool,
expect_response: bool,
expect_response: Expect,
) -> Result<Vec<u8>> {
// FIXME? (from scd/apdu.c):
// T=0 does not allow the use of Lc together with Le;
@ -101,18 +108,22 @@ impl Command {
/// Encode value for Le field
/// ("maximum number of bytes expected in the response data field").
fn make_le(nc: u16, ext_len: bool, expect_response: bool) -> Vec<u8> {
fn make_le(nc: u16, ext_len: bool, expect_response: Expect) -> Vec<u8> {
match (ext_len, expect_response) {
(_, false) => {
(_, Expect::Empty) => {
// No response data expected.
// "If the Le field is absent, then Ne is zero"
vec![]
}
(false, true) => {
(false, Expect::Some) => {
// A short Le field consists of one byte with any value
vec![0]
}
(true, true) => {
(false, Expect::Short(size)) => {
// A short Le field consists of one byte with any value
vec![size]
}
(true, Expect::Some) => {
if nc == 0 {
// "three bytes (one byte set to '00' followed by two
// bytes with any value) if the Lc field is absent"
@ -123,6 +134,9 @@ impl Command {
vec![0, 0]
}
}
_ => {
unreachable!("This should not happen")
}
}
}
}