'Can Le be part of the data passed to PCSC SCardTransmit for a Case 4 command regardless of protocol?
ISO/IEC 7816-3:2006 (12.1.2) defines the bytestring for a command to a Smart Card that sends data and is expected to produce some beyond a status word:
A command APDU of case 4 consists of a header, a LC field, a data field and a LE field.
ISO/IEC 7816-4:2020 (5.2) is similar. I restrict to the short case (4S) where
- LC is a byte in 01H…FFH directly coding integer NC (the number of bytes in the data field, thus discounting the 4-byte header)
- LE is a byte in 01H…FFH directly coding integer NE (the number of bytes expected from the card in response when no error occurs, discounting status words), or 00H meaning maximum (or equivalently NE=256).
In such case 4S, can LE be part of the data passed to PCSC SCardTransmit regardless of the protocol?
In other words, when passing such command to PCSC SCardTransmit, can we set cbSendLength to NC+6 regardless of the protocol?
I ask because I have a reproducible issue where including LE in a command (e.g. 00 A4 09 00 02 20 03 42 with cbSendLength = 8 in a context where the card will actually return a status word 6A 82 and no data) causes SCardTransmit to fail. The value of the LE byte is immaterial. That's with T=0 cards from different manufacturers and applications, several readers of different models but all with the same manufacturer-recommended Windows driver (GemPcCCID 4.1.4.0 of 2016-08-08 signed 2018-07-26, there). The problem vanishes with Microsoft's default CCID WUDF driver, or if I set cbSendLength to one less (thus removing LE). I have so far found no other reader/driver configuration triggering that issue, so I'm tented to say that's a driver issue (or at least an issue of the combination of that driver and the PCSC service it's supposed to work with).
I'd like some specification that tells if it's legit to include the LE byte to SCardTransmit, and I'd prefer something not Windows-specific.
I understand that if somewhat the application knows that the protocol T=0 is used, it's easy to omit the LE byte from the initial SCardTransmit, and I see how LE can be handled subsequently when the card sends a 61xx status word. However some contactless Smart Card readers pretend to be T=0 when they really use the ISO/IEC 14443-4 protocol, and then the LE byte is useful in some cases, thus I don't want to use that option.
Addition: the spec of ScardTransmit has:
For T=0, in the special case where no data is sent to the card and no data expected in return, this length (of the data passed to ScardTransmit) must reflect that the
bP3member is not being sent; the length should besizeof(CmdBytes) - sizeof(BYTE)(that is4, the length of the C-APDU).
Therefore, under in T=0, in cases 1, 2S, 3S, what's passed to ScardTransmit is the C-APDU, and in case 1 that differs from the C-TPDU. I'm asking if there is a reference settling about the imperative, in case 4S under T=0 specifically, to strip LE from a C-APDU (making it the C-TPDU) before passing it to ScardTransmit, similar to the above prescription to not make such conversion from C-APDU to C-TPDU in case 1 under T=0 (which ScardTransmit, the driver, or the reader will perform).
Solution 1:[1]
As stated in the other answer, it's not safe to pass a Case 4 command APDU to SCardTransmit complete with Le when under the T=0 protocol. The question also asks where that's documented.
Such restriction is currently stated neither in Microsoft's spec of SCardTansmit, nor in the pscsclite spec. However, SCardTransmit has historically been developed as an implementation (with different parameter passing but similar functionality) of IFD_Transmit_to_ICC specified by PC/SC in Part 3, paragraph 4.3.2.1 (caution: possibly slow loading) and that states:
Provisions for SCARD_PROTOCOL_T0 communication The
CommandDataneeds to be formatted as an APDU as described in the ISO/IEC 7816-4. The following cases are supported:
- Case 1: Command with no incoming or outgoing data byte:
CLAINSP1P2- Case 2: Command with outgoing data bytes:
CLAINSP1P2Le- Case 3: Command with incoming data bytes:
CLAINSP1P2Lc[Data bytes]Specific remarks:
- Only the short format of
LcandLeis supported, i.e. one byte long.- An incoming order with no data byte «
CLAINSP1P2» should be sent to the card as TPDU through a case 1 APDU.- A case 4 APDU cannot be used. It is the responsibility of the application or the service provider to generate a « get response » if they need it.
Hence when under the T=0 protocol, it's imprudent to pass SCardTransmit anything else than a Case 1, Case 2S, or Case 3S Command APDU.
If we pass a Case 4S Command APDU ( CLA INS P1 P2 Lc [Lc Data bytes] Le, with Lc in [0x01…0xff] ) that works fine with many drivers and readers. In my experience, both under Windows with Microsoft's Usbccid WUDF driver and many other vendor's drivers, and with pcsclite and it's companion libccid, the full C-APDU is passed to the reader, which filters out Le in the C-TPDU to the card, and everything is well. However there are exceptions, including the GemCCID 4.1.4 Windows driver, which performs no transfer and returns an error.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
