Apple's own CCID driver in Sonoma

OS X has built-in support for USB CCID class-compliant SmartCard readers

From SmartCardServices(7) manpage in macOS Sonoma:

USB SMART CARD READER DRIVERS

OS X has built-in support for USB CCID class-compliant SmartCard readers. For other readers, install the reader driver in /usr/local/libexec/SmartCardServices/drivers. Each driver is a bundle. The bundle contains an XML file Info.plist which contains the device's USB vendor ID and product ID. For detailed description of the plist format and how to write a reader driver, see http://pcsclite.alioth.debian.org/api/group__IFDHandler.html

The built-in SmarCard reader driver is prefered by the System and it is possible to change the preference to the IFD CCID by setting the global preference:

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

Check status

it is easy to check which CCID driver is enabled on macOS Sonoma.

Built-in (Apple) driver enabled

% defaults read /Library/Preferences/com.apple.security.smartcard.plist useIFDCCID
2023-09-29 13:38:28.133 defaults[1145:25704]
The domain/default pair of (/Library/Preferences/com.apple.security.smartcard.plist, useIFDCCID) does not exist

IFD CCID (my driver) enabled

% defaults read /Library/Preferences/com.apple.security.smartcard.plist useIFDCCID
1

The result is 1 so the "external" (non-Apple) CCID driver is enabled.

To dump the complete configuration of com.apple.security.smartcard do:

% defaults read /Library/Preferences/com.apple.security.smartcard.plist
{
    CardsNeedsBaseFiDi =     (
        3B6E000080318065B00302015E8300009000,
        3BD518008131FE7D8073C82110F4
    );
    Logging = 0;
    useIFDCCID = 1;
}

Logs

You can use my script log_macOS_ifdbundle.sh to have some logs when you connect a reader:

% ./log_macOS_ifdbundle.sh -d
2023-09-28 14:49:11.678646+0200 0x22aa     Debug       0x0                  858    0    com.apple.ifdreader: [com.apple.CryptoTokenKit:smartcard] deviceRemovalHandler invoked (entryId=4294970735)
2023-09-28 14:49:11.678780+0200 0x22aa     Debug       0x0                  858    0    com.apple.ifdreader: [com.apple.CryptoTokenKit:smartcard] installed device removal notification
2023-09-28 14:49:11.680320+0200 0x22aa     Debug       0x0                  858    0    com.apple.ifdreader: (CoreFoundation) [com.apple.defaults:User Defaults] found no value for key useIFDCCID in CFPrefsPlistSource<0x14a906640> (Domain: com.apple.security.smartcard, User: kCFPreferencesAnyUser, ByHost: Yes, Container: (null), Contents Need Refresh: No)
2023-09-28 14:49:11.681744+0200 0x22aa     Info        0x0                  858    0    com.apple.ifdreader: [com.apple.CryptoTokenKit:smartcard] new device skipped: 0x0529/0x0620 100000 (entryId=4294970735)

The com.apple.ifdreader component is looking for the useIFDCCID key. Here the key is not found so the Apple driver will be used.

Enable my CCID driver

So it is possible to switch from the Apple driver to my CCID driver (also included in macOS Sonoma) using the command:

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

Apple driver

The Apple own CCID driver is /System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd.

It contains typical CCID names:

% strings /System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd/Contents/MacOS/usbsmartcardreaderd | grep PC_
PC_to_RDR_IccPowerOn
PC_to_RDR_IccPowerOff
PC_to_RDR_GetSlotStatus
PC_to_RDR_XfrBlock
PC_to_RDR_GetParameters
PC_to_RDR_ResetParameters
PC_to_RDR_SetParameters
PC_to_RDR_Escape
PC_to_RDR_IccClock
PC_to_RDR_T0APDU
PC_to_RDR_Secure
PC_to_RDR_Mechanical
PC_to_RDR_Abort
PC_to_RDR_SetDataRateAndClockFrequency
RDR_to_PC_DataBlock
RDR_to_PC_SlotStatus
RDR_to_PC_Parameters
RDR_to_PC_Escape
RDR_to_PC_DataRateAndClockFrequency
RDR_to_PC_NotifySlotChange
RDR_to_PC_HardwareError

These names are the command names used in the USB CCID specification.

I note that this file was already present in the previous macOS version: Ventura. But this driver was not enabled by default.

I guess Apple now decided its own CCID driver was mature enough to enable it by default.

Source code?

I don't think Apple will publish the source code of its CCID driver. At least I was not able to find it at Open Source at Apple for the version of macOS Sonoma 14.0 or 14.1.

Apple already replaced pcsc-lite by their own version of the resource manager in macOS Yosemite in 2014 (OS X Yosemite and smart cards status). They now replace the Free Software CCID driver by their own version.

History

Since the source code is not public it will be difficult to know what are the changes in the Apple CCID driver.

In Sonoma 14.0 we had:

$ codesign --verbose=3 --verify --display /System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd
Executable=/System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd/Contents/MacOS/usbsmartcardreaderd
Identifier=com.apple.usbsmartcardreaderd
Format=bundle with Mach-O universal (x86_64 arm64e)
CodeDirectory v=20400 size=2102 flags=0x0(none) hashes=55+7 location=embedded
Platform identifier=15
Hash type=sha256 size=32
CandidateCDHash sha256=555a981af8457fcb972e0301c087361e410a52ef
CandidateCDHashFull sha256=555a981af8457fcb972e0301c087361e410a52ef76c7cea851f838ecb7393f62
Hash choices=sha256
CMSDigest=555a981af8457fcb972e0301c087361e410a52ef76c7cea851f838ecb7393f62
CMSDigestType=2
CDHash=555a981af8457fcb972e0301c087361e410a52ef
Signature size=4442
Authority=Software Signing
Authority=Apple Code Signing Certification Authority
Authority=Apple Root CA
Signed Time=15 Sep 2023 at 23:49:40
Info.plist entries=20
TeamIdentifier=not set
Sealed Resources version=2 rules=2 files=0
Internal requirements count=1 size=80

In Sonoma 14.1 we now have:

$ codesign --verbose=3 --verify --display /System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd
Executable=/System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd/Contents/MacOS/usbsmartcardreaderd
Identifier=com.apple.usbsmartcardreaderd
Format=bundle with Mach-O universal (x86_64 arm64e)
CodeDirectory v=20400 size=2102 flags=0x0(none) hashes=55+7 location=embedded
Platform identifier=15
Hash type=sha256 size=32
CandidateCDHash sha256=b1723b968b6f316aca6172bea0ee75cc4c9de56a
CandidateCDHashFull sha256=b1723b968b6f316aca6172bea0ee75cc4c9de56a962ab2d8bc00659d000f860d
Hash choices=sha256
CMSDigest=b1723b968b6f316aca6172bea0ee75cc4c9de56a962ab2d8bc00659d000f860d
CMSDigestType=2
CDHash=b1723b968b6f316aca6172bea0ee75cc4c9de56a
Signature size=4442
Authority=Software Signing
Authority=Apple Code Signing Certification Authority
Authority=Apple Root CA
Signed Time=6 Oct 2023 at 05:45:18
Info.plist entries=20
TeamIdentifier=not set
Sealed Resources version=2 rules=2 files=0
Internal requirements count=1 size=80

The signature date changed from "15 Sep 2023" to "6 Oct 2023" and the SHA256 hash also changed.

I do not plan to reverse engineer the Apple driver.

My comments

Class driver

The Apple driver is a class driver. Any USB device declared with bInterfaceClass set to 0x0b (Smart Card) should work.

Tweaks

My CCID driver is now old (The first commit was in August 2003. My CCID driver: 20 years anniversary). And I added a lot of special patches to support specific readers.

If you have such a reader the Apple driver may not work for you. In that case you can install a custom driver, or enable my CCID driver 1.5.1 included in macOS Sonoma as seen above in Enable my CCID driver.

Can Apple reuse my tweaks to improve their driver?

The source code of my driver is available so Apple developers can read it.

My driver is protected by the GNU Lesser General Public License version 2.1+ (LGPL). So if Apple wants to reuse some of my code it has to use the same LGPL license for its code. My guess is that Apple worked on its own CCID driver in particular to avoid any use of a GPL or LGPL protected code in macOS.

So Apple will have to design its own tweaks, or do not support some readers.

Bugs reported in Sonoma

The bug macOS Sonoma bug: SCardControl() returns SCARD_E_NOT_TRANSACTED is now easy to understand.

The Apple driver does NOT support SCardControl(). And since it was enabled by default in Sonoma 14.0 all the applications that use SCardControl() failed to work.

What happened in Sonoma 14.1?

I started this article using Sonoma 14.0, the initial release of Sonoma. Apple now provides a first update of Sonoma with a version 14.1.

In this version the Apple CCID driver is no more enabled by default and my CCID driver is enabled instead.

$ defaults read /Library/Preferences/com.apple.security.smartcard.plist
{
    Logging = 0;
    useIFDCCID = 1;
}

I guess Apple received (too) many bug reports and decided to revert the change and keep using my CCID driver for now.

If your smart card application fails to work with Sonoma 14.0 the best thing to do is to upgrade to Sonoma 14.1.

Conclusion

Writing a CCID driver is not an easy task. It is even more complex if you want to support a many different models.

Apple tries to do that but is not ready yet.