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 fileInfo.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.htmlThe 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
IFD CCID (my driver) enabled
The result is 1 so the "external" (non-Apple) CCID driver is enabled.
To dump the complete configuration of com.apple.security.smartcard
do:
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:
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.