Handle SW_EXACT_LENGTH (0x6c??) in send_command()
This commit is contained in:
parent
60c67d3ebe
commit
a39f25d8a3
2 changed files with 36 additions and 9 deletions
|
@ -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() {
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue