GnuPG and PC/SC conflicts, episode 2

Ubuntu 24.04 provides a new version of GnuPG (GNU Privacy Guard): 2.4.4, instead of version 2.2.27 in Ubuntu 22.04. This new version changed its way to access smart card readers.

A new bug has already been opened: Yubikey stopped working after noble upgrade

The problem

GnuPG2 (or in fact its scdaemon component) tries to directly access smart card readers using GnuPG2 own implementation of the USB CCID protocol.

This access conflicts with pcsc-lite also accessing the smart card readers.

The Solution

As already seen in GnuPG and PC/SC conflicts from 2019 the solution is to disable the CCID driver provided by GnuPG.

From scdaemon documentation https://www.gnupg.org/documentation/manuals/gnupg/Scdaemon-Options.html#index-disable_002dccid

--disable-ccid

The integrated CCID driver for CCID compliant devices can be available when libusb was detected at build time, and it is used to access the smartcard reader. If access via PC/SC driver is needed, please configure this option to disable CCID driver support (if any). In GnuPG 2.2, there was a fallback mechanism from CCID driver to PC/SC driver. The fallback mechanism worked, because scdaemon in GnuPG 2.2 only supported a single token/reader. To support of multiple tokens/readers at the same time, fallback mechanism was removed.

Since GnuPG v2.4 removed the fallback mechanism to use PC/SC it is even more important to use the disable-ccid configuration.

To be safe, edit your file ~/.gnupg/scdaemon.conf and add the line:

disable-ccid

Conclusion

If you use GnuPG and also one (or more) PC/SC application then you need this change.

PCSC API spy using LIBPCSCLITE_DELEGATE

As explained in How to use LIBPCSCLITE_DELEGATE? a new mechanism has been introduced for PC/SC calls debug.

Changes

Compared to the previous version documented in PCSC API spy, update:

  • no need to play with LD_PRELOAD any more

  • no need to install/uninstall a spy library

Demo

Run your program (here pcsc_scan) with LIBPCSCLITE_DELEGATE defined.

$ LIBPCSCLITE_DELEGATE=libpcscspy.so.0 pcsc_scan
PC/SC device scanner
V 1.7.1 (c) 2001-2022, Ludovic Rousseau <ludovic.rousseau@free.fr>
Using reader plug'n play mechanism
Scanning present readers...
Waiting for the first reader...
^C
SCardGetStatusChange: Command cancelled.

I used Control-C to abort the program because pcsc_scan never ends.

Traces

In another window I get:

$ pcsc-spy
SCardEstablishContext
 i dwScope: SCARD_SCOPE_SYSTEM (0x00000002)
 o hContext: 0x72EC0CEF
 => SCARD_S_SUCCESS [0x00000000]  [0.046759]
SCardGetStatusChange
 i hContext: 0x72EC0CEF
 i dwTimeout: 0x00000000 (0)
 i cReaders: 1
 i szReader: \\?PnP?\Notification
 i  dwCurrentState:  (0x00000000)
 i  dwEventState: SCARD_STATE_IGNORE, SCARD_STATE_CHANGED, SCARD_STATE_UNKNOWN, SCARD_STATE_UNAVAILABLE, SCARD_STATE_PRESENT, SCARD_STATE_EXCLUSIVE, SCARD_STATE_INUSE, SCARD_STATE_MUTE (0x55A373FA63AF)
 i  Atr length: 0x55A373FA63BE (94160513819582)
 i  Atr: NULL
 o szReader: \\?PnP?\Notification
 o  dwCurrentState:  (0x00000000)
 o  dwEventState:  (0x00000000)
 o  Atr length: 0x55A373FA63BE (94160513819582)
 o  Atr: NULL
 => SCARD_E_TIMEOUT [0x8010000A]  [0.002514]
SCardListReaders
 i hContext: 0x72EC0CEF
 i mszGroups: (null)
 o pcchReaders: 0x00000001
 o mszReaders: NULL
 => SCARD_E_NO_READERS_AVAILABLE [0x8010002E]  [0.000045]
SCardListReaders
 i hContext: 0x72EC0CEF
 i mszGroups: (null)
 o pcchReaders: 0x00000001
 o mszReaders: NULL
 => SCARD_E_NO_READERS_AVAILABLE [0x8010002E]  [0.000434]
SCardGetStatusChange
 i hContext: 0x72EC0CEF
 i dwTimeout: 0x0036EE80 (3600000)
 i cReaders: 1
 i szReader: \\?PnP?\Notification
 i  dwCurrentState:  (0x00000000)
 i  dwEventState:  (0x00000000)
 i  Atr length: 0x55A373FA63BE (94160513819582)
 i  Atr: NULL
   SCardCancel
    i hCard: 0x72EC0CEF
    => SCARD_S_SUCCESS [0x00000000]  [0.000741]
 o szReader: \\?PnP?\Notification
 o  dwCurrentState:  (0x00000000)
 o  dwEventState:  (0x00000000)
 o  Atr length: 0x55A373FA63BE (94160513819582)
 o  Atr: NULL
 => SCARD_E_CANCELLED [0x80100002]  [1.015056]
SCardReleaseContext
 i hContext: 0x72EC0CEF
 => SCARD_S_SUCCESS [0x00000000]  [0.000632]

Thread 1/2
Results sorted by total execution time
total time: 1.065758 sec
1.017570 sec (  2 calls) 95.48% SCardGetStatusChange
0.046759 sec (  1 calls)  4.39% SCardEstablishContext
0.000632 sec (  1 calls)  0.06% SCardReleaseContext
0.000479 sec (  2 calls)  0.04% SCardListReaders

Thread 2/2
Results sorted by total execution time
total time: 1.065758 sec
0.000741 sec (  1 calls)  0.07% SCardCancel

The (Python) program pcsc-spy is provided by pcsc-lite. It is included in the Debian libpcsclite-dev package.

Absolute filename

If you want to use a specific spy library or if the library is installed in a directory not handled by the GNU/Linux dynamic loader ld.so you can use an absolute filename.

The script setup_spy.sh is provided by pcsc-lite. It is also included in the Debian libpcsclite-dev package.

$ sh /usr/share/doc/libpcsclite-dev/setup_spy.sh
export LIBPCSCLITE_DELEGATE=/lib/x86_64-linux-gnu/libpcscspy.so.0

If you want to have LIBPCSCLITE_DELEGATE defined and used for all the future executions (maybe not recommanded) you can execute the export command using:

$ source /usr/share/doc/libpcsclite-dev/setup_spy.sh
export LIBPCSCLITE_DELEGATE=/lib/x86_64-linux-gnu/libpcscspy.so.0

Conclusion

It should now be a bit simpler to generate PC/SC call traces.

How to use LIBPCSCLITE_DELEGATE?

pcsc-lite 2.1.0 introduced a new mechanism that uses the environement variable LIBPCSCLITE_DELEGATE (see New version of pcsc-lite: 2.1.0).

The idea is that all the PC/SC calls of an application can be redirected to another library. This has been designed to be used in 2 use cases:

  • trace PC/SC calls for debug, performance analysis, etc.

  • redirect PC/SC calls to a different resource manager, like a remote one.

Remote session

Redirecting PC/SC calls is needed if you use a remote desktop and you want to use your local smart card reader in an application running in a distant GNU/Linux server.

On the server side the RDP server component will define LIBPCSCLITE_DELEGATE to use its own RDP library instead of the default libpcsclite library. The RDP PC/SC library will be in charge of communicating with the RDP client side.

You can use RDP (Remote Desktop Protocol) defined by Microsoft or another protocol.

The use of LIBPCSCLITE_DELEGATE should allow xrdp (an open-source Remote Desktop Protocol server) to redirect smart card accesses to RDP clients (from GNU/Linux or Windows clients).

This solution has been discussed in Delegate WinSCard calls to another library (for a RDP server for example) #161 and XRDP smartcard passthrough via windows RDP client #2625.

Spy the remote session

LIBPCSCLITE_DELEGATE can also be used to trace all the PC/SC calls (see PCSC API spy using LIBPCSCLITE_DELEGATE).

To do that you define LIBPCSCLITE_DELEGATE to use libpcscspy.so.0 and you define LIBPCSCLITE_SPY_DELEGATE (used by libpcscspy.so.0) to use your xrdp library instead of the default libpcsclite library.

libpcsclite.so.1 will call libpcscspy.so.0 which will call your xrdp library.

Security

Is it a new security issue?

No. It was already easy to intercept libpcsclite.so.1 functions using the dynamic linker LD_PRELOAD mechanism. This was the mechanism documented to spy PC/SC calls. See PCSC API spy, third try or PCSC API spy, update.

Conclusion

If you find new/innovative ways to use LIBPCSCLITE_DELEGATE please tell me.

New version of pcsc-lite: 2.1.0

I just released a new version of pcsc-lite 2.1.0.

pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems.

Changes:

2.1.0: Ludovic Rousseau

12 April 2024

  • LIBPCSCLITE_DELEGATE is used to redirect to another libpcsclite library

  • setup_spy.sh displays the LIBPCSCLITE_DELEGATE value to use for spying

  • provides libfake.c as a sample source code

  • Some other minor improvements

PySCard 2.0.9 released

I just released a new version of pyscard. PySCard is a python module adding smart cards support (PC/SC) to Python.

The PySCard project is available at:

Changes:

2.0.9 (April 2024)

  • fix a bug with CardRequestTimeoutException introduced in 2.0.8

  • Minor changes

PySCard 2.0.8 released

I just released a new version of pyscard. PySCard is a python module adding smart cards support (PC/SC) to Python.

The PySCard project is available at:

Changes:

2.0.8 (march 2024)

  • Make CardMonitor() thread safe on Python 3.12

  • Add hresult value in exceptions

  • Improve documentation

  • Check swig is installed on build

  • Remove use of imp module for wx (GUI)

  • Makefile: modernize use of setup.py

  • Minor changes

New version of pcsc-lite: 2.0.3

I just released a new version of pcsc-lite 2.0.3.

pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems.

In version 2.0.2 I renamed SCARD_E_UNKNOWN_RES_MNG into SCARD_E_UNKNOWN_RES_MSG in this patch Fix typo in (unused) error code SCARD_E_UNKNOWN_RES_MSG to fix the reported issue Error symbol SCARD_E_UNKNOWN_RES_MNG should be SCARD_E_UNKNOWN_RES_MSG #169. The symbol is not used by pcsc-lite so I thought the change was harmless.

But this change made some software fail to build. For example ausweisapp2 fails to build with the error (Debian bug #1065380):

/<<PKGBUILDDIR>>/src/card/pcsc/PcscUtils.h:112:46: error: ‘SCARD_E_UNKNOWN_RES_MNG’ was not declared in this scope; did you mean ‘SCARD_E_UNKNOWN_RES_MSG’?
  112 |         Scard_E_Unknown_Res_Mng = returnCode(SCARD_E_UNKNOWN_RES_MNG),         /**< An unrecognized error code was returned from a layered component. */
          |                                              ^~~~~~~~~~~~~~~~~~~~~~~

I now discover that Windows does define BOTH values:

What The F... Microsoft?

Changes:

2.0.3: Ludovic Rousseau

3 March 2024

  • add SCARD_E_UNKNOWN_RES_MNGi back

New version of pcsc-lite: 2.0.2

I just released a new version of pcsc-lite 2.0.2.

pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems.

This version fixes issues with the protocol negotiation algorithm.

We should not try to use a protocol that is not in the preferred ones from the application. If the application requests to use T=1 only but the card does support T=0 & T=1, and the reader does support T=0 only we should NOT try to use T=0 but fail instead.

SCardConnect() & SCardReconnect() will now return SCARD_E_PROTO_MISMATCH.

This should match the Windows behaviour.

Changes:

2.0.2: Ludovic Rousseau

3 March 2024

  • SCardConnect() & SCardReconnect(): restrict the protocol used

  • negotiate PTS also for the backup protocol

  • pcscd.8 manpage:

    • document --disable-polkit

    • add "CONFIGURATION FILE" section

  • Some other minor improvements

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:

sudo defaults write /Library/Preferences/com.apple.security.smartcard useIFDCCID -bool yes

To enable Apple CCID driver you do:

sudo defaults write /Library/Preferences/com.apple.security.smartcard useIFDCCID -bool no

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).