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 anyhow::Result;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
use crate::apdu::command::Expect;
|
||||||
use crate::apdu::{command::Command, response::RawResponse};
|
use crate::apdu::{command::Command, response::RawResponse};
|
||||||
use crate::{CardClientBox, Error, StatusBytes};
|
use crate::{CardClientBox, Error, StatusBytes};
|
||||||
|
|
||||||
|
@ -28,10 +29,22 @@ pub(crate) fn send_command(
|
||||||
) -> Result<RawResponse, Error> {
|
) -> Result<RawResponse, Error> {
|
||||||
let mut resp = RawResponse::try_from(send_command_low_level(
|
let mut resp = RawResponse::try_from(send_command_low_level(
|
||||||
card_client,
|
card_client,
|
||||||
cmd,
|
cmd.clone(),
|
||||||
expect_reply,
|
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() {
|
while let StatusBytes::OkBytesAvailable(_) = resp.status() {
|
||||||
// More data is available for this command from the card
|
// More data is available for this command from the card
|
||||||
log::debug!(" chained response, getting more data");
|
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(
|
let next = RawResponse::try_from(send_command_low_level(
|
||||||
card_client,
|
card_client,
|
||||||
commands::get_response(),
|
commands::get_response(),
|
||||||
expect_reply,
|
Expect::Some,
|
||||||
)?)?;
|
)?)?;
|
||||||
|
|
||||||
match next.status() {
|
match next.status() {
|
||||||
|
@ -71,7 +84,7 @@ pub(crate) fn send_command(
|
||||||
fn send_command_low_level(
|
fn send_command_low_level(
|
||||||
card_client: &mut CardClientBox,
|
card_client: &mut CardClientBox,
|
||||||
cmd: Command,
|
cmd: Command,
|
||||||
expect_response: bool,
|
expect_response: Expect,
|
||||||
) -> Result<Vec<u8>, Error> {
|
) -> Result<Vec<u8>, Error> {
|
||||||
let (ext_support, chaining_support, mut max_cmd_bytes, max_rsp_bytes) =
|
let (ext_support, chaining_support, mut max_cmd_bytes, max_rsp_bytes) =
|
||||||
if let Some(caps) = card_client.get_caps() {
|
if let Some(caps) = card_client.get_caps() {
|
||||||
|
|
|
@ -6,6 +6,13 @@
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum Expect {
|
||||||
|
Empty,
|
||||||
|
Some,
|
||||||
|
Short(u8),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct Command {
|
pub(crate) struct Command {
|
||||||
// Class byte (CLA)
|
// Class byte (CLA)
|
||||||
|
@ -63,7 +70,7 @@ impl Command {
|
||||||
pub(crate) fn serialize(
|
pub(crate) fn serialize(
|
||||||
&self,
|
&self,
|
||||||
ext_len: bool,
|
ext_len: bool,
|
||||||
expect_response: bool,
|
expect_response: Expect,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
// FIXME? (from scd/apdu.c):
|
// FIXME? (from scd/apdu.c):
|
||||||
// T=0 does not allow the use of Lc together with Le;
|
// T=0 does not allow the use of Lc together with Le;
|
||||||
|
@ -101,18 +108,22 @@ impl Command {
|
||||||
|
|
||||||
/// Encode value for Le field
|
/// Encode value for Le field
|
||||||
/// ("maximum number of bytes expected in the response data 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) {
|
match (ext_len, expect_response) {
|
||||||
(_, false) => {
|
(_, Expect::Empty) => {
|
||||||
// No response data expected.
|
// No response data expected.
|
||||||
// "If the Le field is absent, then Ne is zero"
|
// "If the Le field is absent, then Ne is zero"
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
(false, true) => {
|
(false, Expect::Some) => {
|
||||||
// A short Le field consists of one byte with any value
|
// A short Le field consists of one byte with any value
|
||||||
vec![0]
|
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 {
|
if nc == 0 {
|
||||||
// "three bytes (one byte set to '00' followed by two
|
// "three bytes (one byte set to '00' followed by two
|
||||||
// bytes with any value) if the Lc field is absent"
|
// bytes with any value) if the Lc field is absent"
|
||||||
|
@ -123,6 +134,9 @@ impl Command {
|
||||||
vec![0, 0]
|
vec![0, 0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!("This should not happen")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue