[Pcsclite-muscle] What's responsible to filter out Le in Case 4 C-APDUs under T=0?

Francois Grieu fgrieu at gmail.com
Tue Feb 8 08:29:51 PST 2022

On 2022-02-08 14:44, Bruno Jesus wrote:
> On Tue, Feb 8, 2022 at 6:59 AM Francois Grieu <fgrieu at gmail.com> wrote:
>     <snip>t is there an authoritative reference that it's
>     valid for an application to send complete C-APDU (thus including Le in
>     case 4S)
>     to SCardTransmit? And perhaps one that it's not SCardTransmit's job to
>     remove Le
>     under T=0?
> I believe there is a mix of concepts about T=0, T=1 and APDU commands. On T=0 
> there is no DATA+LE, T=0 is half-duplex, it either sends data or receives 
> responses. On T=1 you can send data and request a response length at the same 
> command since it uses a different approach to transmit data.

Per ISO/IEC 7816-3:2006 section 12, in case 4 (that is APDUs with data to and 
from the card), the Command APDU includes Le, regardless of the protocol. 
Quoting 12.3.1 about "Decoding conventions for command APDUs (..) Case 4S ⎯ The 
short Lc field consists of C(5) ≠ '00', encoding Nc from 1 to 255. The data 
field consists of C(6) to C(5+Nc). The short Le field consists of C(6+Nc) 
encoding Ne from 1 to 256 ('00' means the maximum, 256)."

> Just to add context: On T=0 if the command has 5 bytes the P3 is the "LE" and 
> for commands with more than 5 bytes the P3 is always the LC and the extra 
> bytes are command data. For example:
> 00C0000010 -> 10 is the LE.
> 00B2000004 00000000 -> the 04 is the LC followed by data.
> On T=0 for APDU with data (LC > 0) the transfer direction is switched after 
> sending the amount of data pointed at P3, so it can't receive the LE, sending 
> the LE (or any other extra bytes not accounted at LC) would mix the extra bits 
> being sent with a response being received. If you have the ISO IEC 7816-4 
> document you can check the Annex A (Transportation of APDU messages by T=0) 
> and B (Transportation of APDU messages by T=1).

That's what there is at the TPDU level (Transport Protocol Data Unit). The 
mapping from APDU to TPDU is explained in section 12.2 for T=0, 12.3 for T=1. 
The physical level has some more bytes.

> My answer to the original questions would be that it is up to the caller to 
> know the protocol it is using and format the commands correctly. I wouldn't 
> expect a driver to "fix" the command by removing the LE since you requested it 
> to be sent, I believe some drivers may be sending 5 + P3 value instead of 
> sending the size received by SCardTransmit, thus hiding the problem (e.g 
> 00B2000001 00 00 would send 5 + 1 and not 7).
> About the question on how to fix this on the client side it is not difficult. 
> When doing SCardConnect you can request the protocols supported and as a 
> response you will receive the one actually in use. You can use this to 
> properly format the commands by not adding LE to T=0. To account for the 
> missing LE the T=0 has the 61XX status word.  Always check the 61XX SW and 
> transmit the GET RESPONSE command. Then all remaining code is the same for T=0 
> and T=1 at the PCSC level.

In essence, the suggestion is to pass SCardTransmit a C-TPDU, rather than a 
C-APDU as I do. That's feasible, and fixes the problem I'm having with this 
particular driver. However:
- I don't know any specification suggesting to do this. It's not necessary in 
most contexts I've used SCardTransmit with, including pcsclite, and Windows 
except with one of >12 drivers I practice. If it was generally deemed necessary, 
I'd expect a plethora of standard wrappers on top of SCardConnect and 
ScardTransmit for that conditional stripping of Le, but Javax.smartcardio is the 
only such wrapper I know of.
- At least in cases 1, 2(S) and 3(S), the cbSendLength parameter of 
SCardTransmit is the length of the C-APDU, and in case 1 that differs from the 
length of the first C-TPDU: the spec ( 
) requires that "For T=0, in the special case where no data is sent to the card 
and no data expected in return",  cbSendLength is set to 4. This suggests 
ScardTransmit is designed to receive C-APDUs, not C-TPDUs.
- I fear that it could cause issue with some hypothetical readers, either ISO 
14443 contactless readers disguising as T=0, or readers capable of T=0 which 
incorporate the full APDU to TPDU translation layer (I admit I never met any 
CCID reader/driver doing either ).

So: is there some authoritative source on if and when ScardTransmit requires Le 
in a C-APDU to be stripped from it's input by the caller ?

   Francois Grieu

More information about the pcsclite-muscle mailing list