macOS Sonoma bug: SCardControl() (part 2)
In macOS Sonoma bug: SCardControl() returns SCARD_E_NOT_TRANSACTED I
presented the problems with SCardControl()
on macOS Sonoma. Then in
Apple's own CCID driver in Sonoma we saw that macOS Sonoma provides
two CCID drivers: one from Apple and one from me.
In Sonoma version 14.3 the situation evolved. The bug described in macOS Sonoma bug: SCardControl() returns SCARD_E_NOT_TRANSACTED is mostly fixed.
Switch CCID driver
It is easy to switch between Apple CCID driver and my CCID driver.
To enable my CCID driver you do:
To enable Apple CCID driver you do:
SCardControl
For my tests I used the sampe code scardcontrol included in my driver source code.
My CCID driver
$ ./scardcontrol SCardControl sample code V 1.4 © 2004-2010, Ludovic Rousseau [ludovic.rousseau@free.fr](mailto:ludovic.rousseau@free.fr) THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL! Do NOT use it unless you really know what you do. SCardListReaders: OK Available readers (use command line argument to select) 0: Gemalto Ezio Shield Using reader: Gemalto Ezio Shield Protocol: 1 SCardConnect: OK SCardControl: OK TLV (24): 06 04 42 33 00 06 07 04 42 33 00 07 0A 04 42 33 00 0A 12 04 42 33 00 12 SCardControl(CM_IOCTL_GET_FEATURE_REQUEST): OK Reader supports: FEATURE_VERIFY_PIN_DIRECT Reader supports: FEATURE_MODIFY_PIN_DIRECT Reader supports: FEATURE_IFD_PIN_PROPERTIES Reader supports: FEATURE_GET_TLV_PROPERTIES SCardControl(GET_TLV_PROPERTIES): OK GET_TLV_PROPERTIES (59): 01 02 11 04 04 02 11 00 05 02 04 00 03 01 00 08 10 47 65 6D 43 78 30 30 2D 56 37 2E 30 34 2E 30 35 06 01 04 07 01 10 02 01 02 09 01 00 0B 02 E6 08 0C 02 C0 34 0A 04 00 00 00 00 Display all the properties: wLcdLayout: 0x0411 Display with 4 lines of 17 columns wLcdMaxCharacters: 0x0011 wLcdMaxLines: 0x0004 bTimeOut2: 0x00 sFirmwareID: GemCx00-V7.04.05 bMinPINSize: 0x04 bMaxPINSize: 0x10 bEntryValidationCondition: 0x02 Validation key pressed (2) bPPDUSupport: 0x00 wIdVendor: 0x8E6 wIdProduct: 0x34C0 dwMaxAPDUDataSize: 0 Find a specific property: wIdVendor: 0x08E6 wIdProduct: 0x34C0 PIN min size defined: 4 PIN max size defined: 16 Entry Validation Condition defined: 2 SCardControl(pin_properties_ioctl): OK PIN PROPERTIES (4): 11 04 02 00 wLcdLayout: 0x0411 Display with 4 lines of 17 columns bEntryValidationCondition: 2 Validation key pressed (2) bTimeOut2: 0 Reader: Gemalto Ezio Shield (length 20 bytes) State: 0x0054 Prot: 1 ATR (length 18 bytes): 3B 6E 00 00 80 31 80 65 B0 03 02 01 5E 83 00 00 90 00 SCardStatus: OK Protocol: 1 SCardReconnect: OK Select applet: 00 A4 04 00 06 A0 00 00 00 18 FF SCardTransmit: OK card response: 90 00 Secure verify PIN command: 00 00 82 08 00 10 04 02 01 09 04 00 00 00 00 0D 00 00 00 00 20 00 00 08 30 30 30 30 00 00 00 00 Enter your PIN: SCardControl: OK card response [2 bytes]: 90 00: Success verify PIN dump: 00 40 00 00 FF SCardTransmit: OK card response: 00 20 00 00 08 31 32 33 34 35 36 37 38 90 00 SCardDisconnect: OK
Apple driver
$ ./scardcontrol SCardControl sample code V 1.4 © 2004-2010, Ludovic Rousseau [ludovic.rousseau@free.fr](mailto:ludovic.rousseau@free.fr) THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL! Do NOT use it unless you really know what you do. SCardListReaders: OK Available readers (use command line argument to select) 0: Gemalto Ezio Shield Pro SC Using reader: Gemalto Ezio Shield Pro SC Protocol: 1 SCardConnect: OK SCardControl: OK TLV (30): 12 04 42 33 00 12 06 04 42 33 00 06 07 04 42 33 00 07 0A 04 42 33 00 0A 13 04 42 00 00 01 SCardControl(CM_IOCTL_GET_FEATURE_REQUEST): OK Reader supports: FEATURE_GET_TLV_PROPERTIES Reader supports: FEATURE_VERIFY_PIN_DIRECT Reader supports: FEATURE_MODIFY_PIN_DIRECT Reader supports: FEATURE_IFD_PIN_PROPERTIES Reader supports: FEATURE_CCID_ESC_COMMAND SCardControl(GET_TLV_PROPERTIES): OK GET_TLV_PROPERTIES (34): 01 02 11 04 03 01 00 09 01 01 0B 02 E6 08 0C 02 C0 34 0A 04 05 01 00 00 08 00 04 02 11 00 05 02 04 00 Display all the properties: wLcdLayout: 0x0411 Display with 4 lines of 17 columns bTimeOut2: 0x00 bPPDUSupport: 0x01 PPDU is supported over SCardControl using FEATURE_CCID_ESC_COMMAND wIdVendor: 0x8E6 wIdProduct: 0x34C0 dwMaxAPDUDataSize: 261 sFirmwareID: wLcdMaxCharacters: 0x0011 wLcdMaxLines: 0x0004 Find a specific property: wIdVendor: 0x08E6 wIdProduct: 0x34C0 SCardControl(pin_properties_ioctl): OK PIN PROPERTIES (4): 11 04 07 00 wLcdLayout: 0x0411 Display with 4 lines of 17 columns bEntryValidationCondition: 7 Max size reached (1) Validation key pressed (2) Timeout occurred (4) bTimeOut2: 0 Reader: Gemalto Ezio Shield Pro SC (length 27 bytes) State: 0x0054 Prot: 1 ATR (length 18 bytes): 3B 6E 00 00 80 31 80 65 B0 03 02 01 5E 83 00 00 90 00 SCardStatus: OK Protocol: 1 SCardReconnect: OK Select applet: 00 A4 04 00 06 A0 00 00 00 18 FF SCardTransmit: OK card response: 90 00 Secure verify PIN command: 00 00 82 08 00 08 04 07 01 09 04 00 00 00 00 0D 00 00 00 00 20 00 00 08 30 30 30 30 00 00 00 00 Enter your PIN: SCardControl: OK card response [0 bytes]:: verify PIN dump: 00 40 00 00 FF SCardTransmit: OK card response: 00 20 00 00 08 31 32 33 34 35 36 37 38 90 00 SCardDisconnect: OK
Diff
Here is the diff between the two outputs above:
--- libccid_pinpad 2024-02-04 15:02:41.673189176 +0100 +++ apple_pinpad 2024-02-04 15:02:18.149970763 +0100 @@ -7,54 +7,51 @@ Do NOT use it unless you really know wha SCardListReaders: OK Available readers (use command line argument to select) -0: Gemalto Ezio Shield +0: Gemalto Ezio Shield Pro SC -Using reader: Gemalto Ezio Shield +Using reader: Gemalto Ezio Shield Pro SC Protocol: 1 SCardConnect: OK SCardControl: OK - TLV (24): 06 04 42 33 00 06 07 04 42 33 00 07 0A 04 42 33 00 0A 12 04 42 33 00 12 + TLV (30): 12 04 42 33 00 12 06 04 42 33 00 06 07 04 42 33 00 07 0A 04 42 33 00 0A 13 04 42 00 00 01 SCardControl(CM_IOCTL_GET_FEATURE_REQUEST): OK +Reader supports: FEATURE_GET_TLV_PROPERTIES Reader supports: FEATURE_VERIFY_PIN_DIRECT Reader supports: FEATURE_MODIFY_PIN_DIRECT Reader supports: FEATURE_IFD_PIN_PROPERTIES -Reader supports: FEATURE_GET_TLV_PROPERTIES +Reader supports: FEATURE_CCID_ESC_COMMAND SCardControl(GET_TLV_PROPERTIES): OK -GET_TLV_PROPERTIES (59): 01 02 11 04 04 02 11 00 05 02 04 00 03 01 00 08 10 47 65 6D 43 78 30 30 2D 56 37 2E 30 34 2E 30 35 06 01 04 07 01 10 02 01 02 09 01 00 0B 02 E6 08 0C 02 C0 34 0A 04 00 00 00 00 +GET_TLV_PROPERTIES (34): 01 02 11 04 03 01 00 09 01 01 0B 02 E6 08 0C 02 C0 34 0A 04 05 01 00 00 08 00 04 02 11 00 05 02 04 00 Display all the properties: wLcdLayout: 0x0411 Display with 4 lines of 17 columns - wLcdMaxCharacters: 0x0011 - wLcdMaxLines: 0x0004 bTimeOut2: 0x00 - sFirmwareID: GemCx00-V7.04.05 - bMinPINSize: 0x04 - bMaxPINSize: 0x10 - bEntryValidationCondition: 0x02 - Validation key pressed (2) - bPPDUSupport: 0x00 + bPPDUSupport: 0x01 + PPDU is supported over SCardControl using FEATURE_CCID_ESC_COMMAND wIdVendor: 0x8E6 wIdProduct: 0x34C0 - dwMaxAPDUDataSize: 0 + dwMaxAPDUDataSize: 261 + sFirmwareID: + wLcdMaxCharacters: 0x0011 + wLcdMaxLines: 0x0004 Find a specific property: wIdVendor: 0x08E6 wIdProduct: 0x34C0 - PIN min size defined: 4 - PIN max size defined: 16 - Entry Validation Condition defined: 2 SCardControl(pin_properties_ioctl): OK -PIN PROPERTIES (4): 11 04 02 00 +PIN PROPERTIES (4): 11 04 07 00 wLcdLayout: 0x0411 Display with 4 lines of 17 columns - bEntryValidationCondition: 2 + bEntryValidationCondition: 7 + Max size reached (1) Validation key pressed (2) + Timeout occurred (4) bTimeOut2: 0 - Reader: Gemalto Ezio Shield (length 20 bytes) + Reader: Gemalto Ezio Shield Pro SC (length 27 bytes) State: 0x0054 Prot: 1 ATR (length 18 bytes): 3B 6E 00 00 80 31 80 65 B0 03 02 01 5E 83 00 00 90 00 @@ -66,10 +63,10 @@ SCardTransmit: OK card response: 90 00 Secure verify PIN - command: 00 00 82 08 00 10 04 02 01 09 04 00 00 00 00 0D 00 00 00 00 20 00 00 08 30 30 30 30 00 00 00 00 + command: 00 00 82 08 00 08 04 07 01 09 04 00 00 00 00 0D 00 00 00 00 20 00 00 08 30 30 30 30 00 00 00 00 Enter your PIN: SCardControl: OK - card response [2 bytes]: 90 00: Success + card response [0 bytes]:: verify PIN dump: 00 40 00 00 FF ---
Some differences to note:
FEATURE_CCID_ESC_COMMAND
Apple driver reports it supports FEATURE_CCID_ESC_COMMAND
.
According to Interoperability Specification for ICCs and Personal Computer Systems, Part 10 IFDs with Secure PIN Entry Capabilities page 27:
2.6.15 FEATURE_CCID_ESC_COMMAND
This feature can be used to retrieve the control code to send a CCID escape command (PC_to_RDR_Escape see [4]) to the reader.
The input parameter for this feature is a pointer to the abData field (see [4]) containing the specific escape command.
The output parameter is a pointer to a buffer that will contain the reader response. Note that a CCID escape command is specific to a given reader, so before issuing this command, the application has to make sure it addresses the appropriate reader.
With my driver, for security reasons, this feature is active only if
enabled in the Info.plist
file for ifdDriverOptions
option.
bPPDUSupport
Apple driver reports bPPDUSupport: 0x01
.
According to Interoperability Specification for ICCs and Personal Computer Systems, Part 10 IFDs with Secure PIN Entry Capabilities page 25:
bPPDUSupport.
Bit0: If set to 1, PPDU is supported over SCardControl using FEATURE_CCID_ESC_COMMAND
Bit1: If set to 1, PPDU is supported over SCardTransmit
My driver does not support PPDU (Pseudo APDU) because SCardControl()
works fine so not need of PPDUs.
dwMaxAPDUDataSize
Apple driver reports: dwMaxAPDUDataSize: 261
.
According to Interoperability Specification for ICCs and Personal Computer Systems, Part 10 IFDs with Secure PIN Entry Capabilities page 26:
dwMaxAPDUDataSize
Maximal size of data the reader and its driver can support
0: short APDU only.
0<X<=256: forbidden values (RFU)
256 < X <= 0x10000: short and extended APDU of up to X bytes of data
0x10000 < X: invalid values (RFU)
261 is a very strange value. Even more strange if you know that this reader supports short APDU only. The correct value (as correctly reported by my driver) is 0 for this reader.
sFirmwareID
Apple driver reports: sFirmwareID:
.
The firmware string is empty. This is not suprising since a proprietary command is used to get the firmware release string from a Gemalto reader.
My driver reports: sFirmwareID: GemCx00-V7.04.05
.
Maybe the Apple driver should not report any sFirmwareID if no data is provided.
bEntryValidationCondition
Apple driver reports: bEntryValidationCondition: 7
.
7 (00000111b in binary) should be the default value. But this specific reader does only supports "Validation key pressed" but not "Max size reached" or "Timeout occurred" as wrongly indicated by the Apple driver.
My driver reports the correct value bEntryValidationCondition: 2
.
PIN min/max size defined
Apple driver does NOT report PIN min and max sizes.
This can be problematic if the application does not know what values to use with a specific reader. Not all readers support the same min and max values.
Secure Verify PIN comand
The most problematic issue is that the Secure Verify PIN command (FEATURE_VERIFY_PIN_DIRECT) using the Apple driver returns:
Secure verify PIN command: 00 00 82 08 00 08 04 07 01 09 04 00 00 00 00 0D 00 00 00 00 20 00 00 08 30 30 30 30 00 00 00 00 Enter your PIN: SCardControl: OK card response [0 bytes]::
The SCardControl()
returns SCARD_S_SUCCESS
(i.e. no error) but
the PIN is not asked by the pinpad reader, and of course not submitted
and verified by the card.
This command just silently fails. A pinpad reader can't be used with the Apple CCID driver.
Conclusion
You may have problems if you use the Apple driver with the
SCardControl()
function.
My advice is to enable my CCID driver and not use the Apple driver. It is very easy to do since both drivers are provided with macOS Sonoma (see Switch CCID driver from above).