pcsc-lite backward & forward compatible with itself

pcsc-lite 2.4.1 now provides a backward & forward compatible mechanism that supports both the current and previous internal communication protocols.

The communication protocol we are talking about here is the one between the client (libpcsclite) and the server (pcscd) sides. It is an internal-only protocol that is specific to pcsc-lite.

Protocol negotiation

To ensure that the client and server are using the same protocol, they negotiate the procotol they know. If they are different, the server will refuse the connection. In the application (client side), the SCardEstablishContext() function will return the error code SCARD_E_SERVICE_STOPPED.

Up to version 2.4.0, both the server and the client only supported one protocol version (version 4:5).

Sandboxes

Flatpack, Snap, AppImage and other sandbox technologies are now used to distribute applications.

In some/many cases, the server (pcscd daemon) running on the host comes from a different version of pcsc-lite than the client used in the sandbox. If the internal communication protocol differs, the communication is not possible.

I receive requests to solve this problem. See:

Protocol History

pcsc-lite version

Release Date

Protocol version

Compatible with

2.4.1

1 Jan 2026

4:5

4:4 & 4:5

2.4.0

19 Oct 2025

4:5

4:5

2.3.3

2 Apr 2025

2.3.2

26 Mar 2025

2.3.1

24 Dec 2024

2.3.0

3 Aug 2024

2.2.3

26 May 2024

4:4

4:4

...

1.8.24

12 Oct 2018

1.8.23

18 Dec 2017

4:3

4:3

...

1.8.9

16 Oct 2013

1.8.8

16 Jan 2012

4:2

4:2

...

1.6.5

12 Oct 2010

New protocol negotiation

From pcsc-lite 2.4.1 onwards, the protocol negotiation is smarter.

The daemon side will accept the current version and also the previous one. Versions 4:5 and 4:4 are accepted. It is straightforward, as the only change with version 4:5 is the addition of a new command (command CMD_GET_READER_EVENTS introduced in commit 53f57ed700bcd0bc47d970dc674ba3fd5ee5b387). Old clients will simply not use the new command.

The client side will also accept the current version and the previous one. These are versions 4:5 and 4:4. Using a recent client (protocol 4:5) with an old server (protocol 4:4) will have a small side effect. The SCardGetStatusChange() function will not include the number of reader events (see Improved SCardGetStatusChange() for "\\?PnP?\Notification" special reader).

Applications using pcsc-lite 2.4.1 can use a daemon as old as pcsc-lite version 1.8.24, released in October 2018.

A pcscd daemon from pcsc-lite 2.4.1 can handle clients as old as the same pcsc-lite version 1.8.24 from October 2018.

Supporting the (older) protocol version 4:3 may be possible but would require more efforts and be more complex. Contact me if you require this.

Conclusion

This change should help mix PC/SC servers and clients from more different versions.

This should prevent people from using ugly hacks.

New version of pcsc-lite: 2.4.1

I have just released a new version of pcsc-lite 2.4.1.

pcsc-lite is a Free Software implementation of the PC/SC (also known as WinSCard) API for Unix systems. It provides an API for using smart cards and smart card readers.

This version offers backwards compatibility for both the client and server components. It should now be easier to mix and match different versions of pcscd and libpcsclite (and using different internal protocol versions).

Changes:

2.4.1: Ludovic Rousseau

1 January 2026

  • Add backward version support on the client side

  • Add backward version support on the server side

  • hotplug libudev: rescan the USB bus with pcscd --hotplug

  • fix a value in pcscd.service systemd file

  • meson: install systemd files even if libsystemd is not used

  • Some other minor improvements

Blog statistics for 2025

Dear readers,

I wish you a happy New Year 2026!

In 2025 I published 26 articles on this blog.

/images/2026/01/stats_2025.png

Statistics

/images/2026/01/usage.png

In 2025 the blog served 355,108 pages (+57%) totalling 35.89 GB (+35%). I would say that a large part of the increase in traffic is due to artificial intelligence bots scraping the website.

By month

Only the top 5 articles.

January 2025

#

Title

Hits

1

Apple's own CCID driver in Sonoma (November 2023)

372

2

macOS Sequoia and smart cards status (October 2024)

343

3

pcsc-lite now uses meson build tool (May 2024)

216

4

Ubuntu 22.04 and pcscd auto start failure (October 2022)

185

5

Blog statistics for 2024 (January 2025)

179

February 2025

#

Title

Hits

1

macOS Sequoia and smart cards status (October 2024)

399

2

Apple's own CCID driver in Sonoma (November 2023)

336

3

RSS feed for my blog (January 2025)

315

4

pcsc_scan on Windows (May 2017)

220

5

Ubuntu 22.04 and pcscd auto start failure (October 2022)

202

March 2025

#

Title

Hits

1

Apple's own CCID driver in Sonoma (November 2023)

376

2

macOS Sequoia and smart cards status (October 2024)

353

3

Results of the blog survey (March 2025)

302

4

pcsc-lite now uses meson build tool (May 2024)

205

5

pcsc_scan on Windows (May 2017)

202

April 2025

#

Title

Hits

1

Apple's own CCID driver in Sonoma (November 2023)

397

2

macOS Sequoia and smart cards status (October 2024)

342

3

Ignore readers using PCSCLITE_IGNORE udev property (April 2025)

322

4

New version of pcsc-lite: 2.3.3 (April 2025)

320

5

Resources release in PySCard (April 2025)

226

May 2025

#

Title

Hits

1

Card state synchronisation on SEC1210 reader 2 interfaces (April 2025)

399

2

Apple's own CCID driver in Sonoma (November 2023)

362

3

macOS Sequoia and smart cards status (October 2024)

302

4

PCSC sample in C (November 2010)

213

5

Card auto power on and off (October 2010)

181

June 2025

#

Title

Hits

1

Resources release in PySCard (April 2025)

522

2

macOS Sequoia and smart cards status (October 2024)

518

3

Apple's own CCID driver in Sonoma (November 2023)

489

4

Card state synchronisation on SEC1210 reader 2 interfaces (April 2025)

423

5

macOS Sonoma bug: SCardControl() (part 2) (February 2024)

362

July 2025

#

Title

Hits

1

Apple's own CCID driver in Sonoma (November 2023)

1220

2

Resources release in PySCard (April 2025)

1193

3

macOS Sonoma bug: SCardControl() (part 2) (February 2024)

1075

4

Ignore readers using PCSCLITE_IGNORE udev property (April 2025)

776

5

macOS Sonoma: The reader name should include the USB serial number (October 2023)

744

August 2025

#

Title

Hits

1

macOS Sonoma bug: SCardControl() (part 2) (February 2024)

1195

2

Resources release in PySCard (April 2025)

1174

3

macOS Sonoma: The reader name should include the USB serial number (October 2023)

946

4

Apple's own CCID driver in Sonoma (November 2023)

832

5

macOS Sequoia and smart cards status (October 2024)

630

September 2025

#

Title

Hits

1

Apple's own CCID driver in Sonoma (November 2023)

1677

2

macOS Sonoma bug: SCardControl() (part 2) (February 2024)

1634

3

Resources release in PySCard (April 2025)

1372

4

Improved SCardGetStatusChange() for "\\?PnP?\Notification" special reader (August 2024)

1214

5

macOS Sonoma: The reader name should include the USB serial number (October 2023)

1050

October 2025

#

Title

Hits

1

Apple's own CCID driver in Sonoma (November 2023)

1631

2

macOS Sonoma bug: SCardControl() (part 2) (February 2024)

1611

3

Resources release in PySCard (April 2025)

1595

4

macOS Sonoma: The reader name should include the USB serial number (October 2023)

1243

5

Improved SCardGetStatusChange() for "\\?PnP?\Notification" special reader (August 2024)

1071

November 2025

#

Title

Hits

1

Apple's own CCID driver in Sonoma (November 2023)

1377

2

Improved SCardGetStatusChange() for "\\?PnP?\Notification" special reader (August 2024)

1299

3

pcscd runs as pcscd user (October 2025)

1231

4

macOS Sonoma bug: SCardControl() (part 2) (February 2024)

1115

5

macOS Sonoma: The reader name should include the USB serial number (October 2023)

1015

December 2025

#

Title

Hits

1

macOS Sonoma bug: SCardControl() (part 2) (February 2024)

1607

2

Improved SCardGetStatusChange() for "\\?PnP?\Notification" special reader (August 2024)

1006

3

pcscd runs as pcscd user (October 2025)

940

4

Resources release in PySCard (April 2025)

895

5

Apple's own CCID driver in Sonoma (November 2023)

847

Full year 2025

Only the top 20 articles

Complete year 2025

#

Title

Hits

1

Apple's own CCID driver in Sonoma (November 2023)

9916

2

macOS Sonoma bug: SCardControl() (part 2) (February 2024)

8953

3

Resources release in PySCard (April 2025)

8152

4

macOS Sequoia and smart cards status (October 2024)

6859

5

macOS Sonoma: The reader name should include the USB serial number (October 2023)

6313

6

Improved SCardGetStatusChange() for "\\?PnP?\Notification" special reader (August 2024)

6143

7

Ignore readers using PCSCLITE_IGNORE udev property (April 2025)

4800

8

CCID driver and Multiple Enabled Profiles (MEP) (June 2024)

4601

9

pcsc-lite and polkit (November 2023)

4062

10

macOS Sonoma bug: SCardControl() returns SCARD_E_NOT_TRANSACTED (September 2023)

3993

11

GnuPG and PC/SC conflicts, episode 3 (December 2024)

3926

12

PCSC sample in C (November 2010)

3466

13

Reading a SIM card (in Hackable magazine) (August 2025)

3294

14

Card state synchronisation on SEC1210 reader 2 interfaces (April 2025)

3047

15

pcscd runs as pcscd user (October 2025)

2774

16

pcsc_scan on Windows (May 2017)

2583

17

In case of smart card issues on macOS (June 2025)

2556

18

pcsc-lite now uses meson build tool (May 2024)

2503

19

Ubuntu 22.04 and pcscd auto start failure (October 2022)

2497

20

pcscd auto start using systemd (November 2011)

2267

Analysis

Conclusion

Last year, I asked people to contact me with suggestions for new subjects or tools. However, I received nothing.

This blog does not contain any advertising. If you would like to support me you can become a GitHub Sponsors.

ssh-add -s: Could not add card: agent refused operation

Problem

I wanted to use ssh-agent with a PKCS#11 library on macOS. So I tried adding the smart card using the command ssh-add -s but I received the following error:

 $ ssh-add -s /Library/Frameworks/xyz.framework/Versions/A/libxyz.dylib
 Enter passphrase for PKCS#11:
 Could not add card "/Library/Frameworks/xyz.framework/Versions/A/libxyz.dylib": agent refused operation

The error agent refused operation is not very informative. From the logs of the PKCS#11 library, I can see that the library is not being used at all. The problem does not come from the library, which would have returned an error.

Analysis

In order to analyse the problem, I tried debugging the version of OpenSSH provided by Apple. However, I encountered another issue. See my previous article Apple and OpenSSH modified source code.

To find out exactly what is happening, we need to obtain the logs from ssh-agent command, rather than the ssh-add command. So I restart ssh-agent in debug mode and I re-run the ssh-add command.

 $ ssh-agent -d
 [...]
 debug1: new_socket: type = CONNECTION
 debug2: fd 4 setting O_NONBLOCK
 debug1: process_message: socket 1 (fd=4) type 20
 debug2: process_add_smartcard_key: entering
 refusing PKCS#11 add of "/Library/Frameworks/xyz.framework/Versions/A/libxyz.dylib": provider not allowed

The error here is different: provider not allowed.

The ssh-agent manpage indicates an option [-P allowed_providers].

-P allowed_providers
        Specify  a pattern-list of acceptable paths for PKCS#11 provider
        and FIDO authenticator middleware shared libraries that  may  be
        used with the -S or -s options to ssh-add(1).  Libraries that do
        not match the pattern list will be refused.  The default list is
        "/usr/lib*/*,/usr/local/lib*/*".

The problem is clear. The PKCS#11 library is located in /Library/Frameworks/, which is not included in the default list of allowed directories.

Solutions

Update the way ssh-agent is started by adding the -P '/Library/Frameworks/*' option.

Alternatively, copy or install the PKCS#11 library somewhere in the /usr/local/lib/ directory.

Conclusion

I wrote this blog article to ensure that it is indexed by web search engines, so that other people can find it when searching for the ssh-add error agent refused operation message.

Using Free Software is really helpful when you need to debug an issue. You can read (and modify) the source code to identify the problem.

I should sometimes read a program's manpage before looking at its source code 😀.

Apple and OpenSSH modified source code

I encountered a problem with the ssh-add command on macOS. Since OpenSSH is a Free Software project I had a look at the Open Source at Apple page and I found the source code for ssh provided by Apple in macOS Tahoe 26 at Releases.

Source code

The source code is available in the github repository: apple-oss-distributions/OpenSSH.

Very well. An Xcode project is also inlcuded. It should be a breeze to rebuild the command I need and debug it.

Rebuild

When compiling, I get the following error:

error: unable to find sdk 'macosx.internal' (in target 'ssh' from project 'OpenSSH')

This is because the configured SDK (SDKROOT) is set to macosx.internal. See https://github.com/apple-oss-distributions/OpenSSH/blob/OpenSSH-354.0.3/xcconfigs/base.xcconfig#L9.

//  Copyright © 2023 Apple Inc. All rights reserved.
//
//  NOTE: We use MixedCase for user-defined settings.

PRODUCT_NAME = $(TARGET_NAME)
PRODUCT_MODULE_NAME = $(TARGET_NAME:identifier)
PRODUCT_BUNDLE_IDENTIFIER = com.apple.$(TARGET_NAME:rfc1034identifier)

SDKROOT = macosx.internal
MACOSX_DEPLOYMENT_TARGET = 14.0
[...]

Of course I don't have this internal SDK.

OK. I can try using the default SDK (while searching for "macosx.internal", I found a tool that does just that: fix-macos-internal-sdk). But now I get the following error:

.../OpenSSH/sshd-keygen-wrapper/SystemProperties.swift:3:8: error: Unable to find module dependency: 'DarwinPrivate'
import DarwinPrivate.os.variant
           ^ (in target 'sshd-keygen-wrapper' from project 'OpenSSH')
.../OpenSSH/sshd-keygen-wrapper/SystemProperties.swift:3:8: note: A dependency of main module 'sshd_keygen_wrapper'
import DarwinPrivate.os.variant
           ^ (in target 'sshd-keygen-wrapper' from project 'OpenSSH')

Unsurprisingly, some dependencies are now missing. DarwinPrivate is required.

Of course, I don't have the DarwinPrivate package used here https://github.com/apple-oss-distributions/OpenSSH/blob/OpenSSH-354.0.3/sshd-keygen-wrapper/SystemProperties.swift#L3.

import IOKit
import System
import DarwinPrivate.os.variant

protocol SystemPropertiesStrategy {
[...]

Other packages are also required and missing:

import AppleKeyStore
import CoreAnalytics
import Foundation
import System

struct SSHDWrapper {
[...]

Another option

Rebuilding OpenSSH as provided by Apple is not working. However, it is possible is to try rebuilding OpenSSH from its upstream source code i.e. OpenSSH Portable Release.

This is what I did. I managed to compile OpenSSH Portable (very easily) and debug my problem (we'll come back to that later).

Conclusion

The source code of the modified OpenSSH is provided by Apple. But you cannot recompile it without components that are internal (to my knowledge) to Apple and, of course, not provided by Apple.

This may be the difference between Open Source and Free Software.

Outdated and broken PC/SC drivers with pcsc-lite 2.4.0

Since pcsc-lite 2.4.0 and the fact that pcscd can now run as a normal user (see pcscd runs as pcscd user), the driver must configure the reader's device access rights. Otherwise, the pcscd process will not be able to use the device.

Unmaintained drivers

Some older, unmaintained drivers will no longer work with pcscd. I have requested their removal from Debian unstable.

They are:

I am the Debian maintainer of these packages, so it is my responsibility to open tickets to remove the packages.

I also filed a release critical bug #1119081 on libgcr410 so that this driver will not be included in the next version of Debian (unless the issue is fixed).

Old hardware

These drivers are intended for very old serial smart card readers (who still has a serial port on their computer?) or USB readers from the last century.

The advantage of Free Software is that if someone still has such a device, they can obtain the source code of the driver (still available online), adapt it and use it.

Old software

There has been no new version of the asedriveiiie software since September 2010. The source code is no longer available from the publisher (a commecial company).

The ifd-gempc software is maintained upstream by me. The latest major version dates from April 2012 and was mostly compiler warnings fixes. The source code is still available at https://ifd-gempc.apdu.fr/.

The libgcr410 software was also written by me. I wrote it before ifd-gempc and I am surprised to see it packaged in Debian, as it should be replaced by ifd-gempc. The Debian package has been abandonned by its Debian maintainer since March 2008. More recent Debian versions have been produced by the Debian Quality Assurance (QA) team.

Popularity

I have already published an article on the popularity of Debian packages for smart cards in 2020 in Smart card Usage in Debian: pcscd and drivers.

With updated graphics, we now have:

  • asedriveiiie

Popularity contest statistics for asedriveiiie
  • ifd-gempc

Popularity contest statistics for ifd-gempc
  • libgcr410

Popularity contest statistics for libgcr410

Very few people still have these packages installed. And even fewer use them.

Changes required

I also filed the bug #39 "Set group to pcscd in the udev rules file" on the upstream acsccid driver.

This driver is a fork of my CCID driver and is still actively maintained. The problem should therefore be resolved in a new version.

Conclusion

I don't have enough free time to maintain software that is no longer in use.

I haven't used these drivers for at least 10 years. And I don't plan on using them in the future, because I discovered that I no longer have the smart card readers.

New version of PySCard: 2.3.1

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.3.1 (October 2025)

  • Add support of SWIG 4.4.0

  • Add support of Mac OS X Snow Leopard

  • Minor changes

pcscd runs as pcscd user

With pcsc-lite 2.4.0 (New version of pcsc-lite: 2.4.0) the pcscd daemon process now runs (if systemd is used) as user pcscd in group pcscd.

Possible problem

For example if I use libccid version 1.6.2 (so before the update to set the access rights, implemented in version 1.7.0, New version of libccid: 1.7.0) I get the error:

$ journalctl -u pcscd -f
oct. 21 21:41:26 MacBookPro pcscd[25848]: 00000000 ccid_usb.c:564:OpenUSBByName() Can't libusb_open(4/6): LIBUSB_ERROR_ACCESS

If I start pcscd in foreground and debug mode I get more details:

$ sudo -u pcscd -g pcscd LIBCCID_ifdLogLevel=0x000F pcscd --foreground --debug
00000000 [140406854371648] ../src/debuglog.c:395:DebugLogSetLevel() debug level=debug
00000369 [140406854371648] ../src/configfile.l:293:DBGetReaderListDir() Parsing conf directory: /etc/reader.conf.d
00000055 [140406854371648] ../src/configfile.l:326:DBGetReaderListDir() Skipping non regular file: ..
00000010 [140406854371648] ../src/configfile.l:365:DBGetReaderList() Parsing conf file: /etc/reader.conf.d/libccidtwin
00000096 [140406854371648] ../src/configfile.l:326:DBGetReaderListDir() Skipping non regular file: .
00000037 [140406854371648] ../src/pcscdaemon.c:669:main() pcsc-lite 2.4.0 daemon ready.
00000111 [140406854371648] ../src/pcscdaemon.c:752:main() Using drivers directory: /usr/lib/pcsc/drivers
00008375 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/003/001
00000275 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/003/001
00000240 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8242, path: /dev/bus/usb/003/002
00000311 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/003/001
00000325 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x0237, path: /dev/bus/usb/003/003
00000237 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x0237, path: /dev/bus/usb/003/003
00000237 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x0237, path: /dev/bus/usb/003/003
00000408 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/002/001
00000239 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/002/001
00000271 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8507, path: /dev/bus/usb/002/002
00000417 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/004/001
00000246 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/004/001
00000254 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x0A5C, PID: 0x4500, path: /dev/bus/usb/004/002
00000266 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8213, path: /dev/bus/usb/004/003
00000254 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8213, path: /dev/bus/usb/004/003
00000266 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8213, path: /dev/bus/usb/004/003
00000258 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8213, path: /dev/bus/usb/004/003
00000298 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x0A5C, PID: 0x4500, path: /dev/bus/usb/004/002
00000242 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/004/001
00000260 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x08E6, PID: 0x3438, path: /dev/bus/usb/004/006
00000186 [140406854371648] ../src/hotplug_libudev.c:430:HPAddDevice() Adding USB device: Gemalto USB Shell Token V2
00000089 [140406854371648] ../src/readerfactory.c:1103:RFInitializeReader() Attempting startup of Gemalto USB Shell Token V2 00 00 using /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/libccid.so
00000597 [140406854371648] ../src/readerfactory.c:977:RFBindFunctions() Loading IFD Handler 3.0
00000083 [140406854371648] ../src/ifdhandler.c:2130:init_driver() Driver version: 1.6.2
00001019 [140406854371648] ../src/ifdhandler.c:2152:init_driver() LogLevel: 0x0003
00000012 [140406854371648] ../src/ifdhandler.c:2163:init_driver() DriverOptions: 0x0000
00000370 [140406854371648] ../src/ifdhandler.c:2176:init_driver() LogLevel from LIBCCID_ifdLogLevel: 0x000F
00000040 [140406854371648] ../src/ifdhandler.c:93:CreateChannelByNameOrChannel() Lun: 0, device: usb:08e6/3438:libudev:0:/dev/bus/usb/004/006
00000011 [140406854371648] ../src/ccid_usb.c:261:OpenUSBByName() Reader index: 0, Device: usb:08e6/3438:libudev:0:/dev/bus/usb/004/006
00000069 [140406854371648] ../src/ccid_usb.c:293:OpenUSBByName() interface_number: 0
00000008 [140406854371648] ../src/ccid_usb.c:294:OpenUSBByName() usb bus/device: 4/6
00000006 [140406854371648] ../src/ccid_usb.c:331:OpenUSBByName() Using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
00001026 [140406854371648] ../src/ccid_usb.c:349:OpenUSBByName() ifdManufacturerString: Ludovic Rousseau (ludovic.rousseau@free.fr)
00000008 [140406854371648] ../src/ccid_usb.c:350:OpenUSBByName() ifdProductString: Generic CCID driver
00000007 [140406854371648] ../src/ccid_usb.c:351:OpenUSBByName() Copyright: This driver is protected by terms of the GNU Lesser General Public License version 2.1, or (at your option) any later version.
00011059 [140406854371648] ../src/ccid_usb.c:435:OpenUSBByName() Try device: 4/6
00000062 [140406854371648] ../src/ccid_usb.c:445:OpenUSBByName() vid/pid : 08E6/3438
00000007 [140406854371648] ../src/ccid_usb.c:561:OpenUSBByName() Checking device: 4/6
00000005 [140406854371648] ../src/ccid_usb.c:632:OpenUSBByName() Trying to open USB bus/device: 4/6
00000136 [140406854371648] ../src/ccid_usb.c:638:OpenUSBByName() Can't libusb_open(4/6): LIBUSB_ERROR_ACCESS
00000706 [140406854371648] ../src/ccid_usb.c:208:close_libusb_if_needed() libusb_exit
00000239 [140406854371648] ../src/ccid_usb.c:892:OpenUSBByName() Device not found?
00000103 [140406854371648] ../src/ifdhandler.c:134:CreateChannelByNameOrChannel() failed
00000042 [140406854371648] ../src/readerfactory.c:1144:RFInitializeReader() Open Port 0x200000 Failed (usb:08e6/3438:libudev:0:/dev/bus/usb/004/006)
00000007 [140406854371648] ../src/readerfactory.c:371:RFAddReader() Gemalto USB Shell Token V2 init failed.
00000008 [140406854371648] ../src/readerfactory.c:627:RFRemoveReader() UnrefReader() count was: 1
00000005 [140406854371648] ../src/readerfactory.c:1157:RFUnInitializeReader() Attempting shutdown of Gemalto USB Shell Token V2 00 00.
00000006 [140406854371648] ../src/readerfactory.c:1014:RFUnloadReader() Unloading reader driver.
00000830 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001
00000225 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001
00000223 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8403, path: /dev/bus/usb/001/003

And the reader is not available for PC/SC applications:

$ pcsc_scan -r
No reader found.

Solution

The reader driver must set the access rights of the device file, such as /dev/bus/usb/004/006 in the example above, so that the pcscd group has read and write access rights.

$ ls -l /dev/bus/usb/004/006
crw-rw-r--+ 1 root pcscd 189, 389 21 oct.  21:41 /dev/bus/usb/004/006

Please note that the file belongs to the pcscd group and not the root group.

Implementation

Create a udev rule file that contains something like:

# If not adding the device, go away
ACTION!="add", GOTO="foobar_rules_end"
SUBSYSTEM!="usb", GOTO="foobar_rules_end"
ENV{DEVTYPE}!="usb_device", GOTO="foobar_rules_end"

# CherrySmartTerminalST2XXX.txt
ATTRS{idVendor}=="046A", ATTRS{idProduct}=="003E", GROUP="pcscd"

# All done
LABEL="foobar_rules_end"

For example the libccid udev rule file is available at https://salsa.debian.org/rousseau/CCID/-/blob/master/src/92_pcscd_ccid.rules?ref_type=heads#L12. The important part for the generic CCID driver is:

# Generic CCID device (bInterfaceClass = 0x0b)
ENV{ID_USB_INTERFACES}=="*:0b0000:*", GROUP="pcscd"

For earch USB device with an interface equal to 0x0b, i.e. CCID class, then set the group to pcscd.

The pcscd group should be created by the installation of pcsc-lite package. If it is not the case for your distribution, you should report it as a bug to your distribution pcsc-lite package.

Build requirements

To build the CCID driver with this new feature, you need to have udev pkg-config file installed.

You need to be able to get the udevdir variable from the udev.pc file:

$ pkg-config --variable=udevdir udev
/usr/lib/udev

For Debian/Ubuntu and derivatives distributions just install the package systemd-dev.

Conclusion

This change significantly improves your system security. A bug in pcsc-lite, or in a smart card reader driver used by pcsc-lite, will not allow an attacker to gain access to the root account. The attacker would only have access to a normal/unprivileged account.

This mechanism cannot be used everywhere, for example on systems without systemd or udev. However, most GNU/Linux systems should be covered.

New version of pcsc-lite: 2.4.0

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

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

The major change in this release is that the pcscd daemon process now runs as a normal user instead of root (when systemd is used).

You must use drivers that configure the reader device access rights so that a user in the pcscd group can access it for reading and writing. That is the case for libccid 1.7.0. See New version of libccid: 1.7.0.

Changes:

2.4.0: Ludovic Rousseau

19 October 2025

  • Run pcscd under a pcscd user instead of root when using systemd

  • Set PIDFile in systemd service file

  • Protect contextMapList modifications using a mutex

  • meson:

    • Fix libpcsclite.pc file

    • respect builtin meson default_library option

    • build and install spy lib & tool only when needed

  • UnitaryTests/*.py: fix pylint warnings

  • Improve Doxygen documentation

macOS Tahoe and smart cards status

I will compare this version to the previous one, Sequoia, which I presented in macOS Sequoia and smart cards status.

/images/2025/10/macOS-Tahoe.jpg

CCID

% grep -A 1 CFBundleShortVersionString /usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
  <key>CFBundleShortVersionString</key>
  <string>1.5.1</string>

My CCID driver has not been updated in macOS since Sonoma (released in 2023). It is still version 1.5.1.

Updated CCID driver

If you need a CCID driver newer than the version 1.5.1 provided by Apple, you can contact me.

I just released version 1.7.0 today.

Apple Open Source

The Open Source components included in macOS are listed at <https://opensource.apple.com/releases/>

The Open Source components for Tahoe 26.0 are not yet available.

Apple CCID driver

% defaults read /Library/Preferences/com.apple.security.smartcard.plist
Domain /Library/Preferences/com.apple.security.smartcard.plist does not exist

The Apple CCID driver is enabled by default (as expected).

If you want or need to use my CCID driver, simply follow follow the instructions at Apple's own CCID driver in Sonoma.

Changes compared to Sequoia

% diff -u /Volumes/Sequoia/System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd//Contents/Info.plist /System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd//Contents/Info.plist
--- /Volumes/Sequoia/System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd//Contents/Info.plist       2025-09-05 17:46:41
+++ /System/Library/CryptoTokenKit/usbsmartcardreaderd.slotd//Contents/Info.plist       2025-09-09 09:15:49
@@ -27,21 +27,21 @@
        <key>DTCompiler</key>
        <string>com.apple.compilers.llvm.clang.1_0</string>
        <key>DTPlatformBuild</key>
-       <string></string>
+       <string>25A336</string>
        <key>DTPlatformName</key>
        <string>macosx</string>
        <key>DTPlatformVersion</key>
-       <string>15.7</string>
+       <string>26.0</string>
        <key>DTSDKBuild</key>
-       <string>24G201t</string>
+       <string>25A336</string>
        <key>DTSDKName</key>
-       <string>macosx15.7.internal</string>
+       <string>macosx26.0.internal</string>
        <key>DTXcode</key>
-       <string>1630</string>
+       <string>2600</string>
        <key>DTXcodeBuild</key>
-       <string>16E6052g</string>
+       <string>17A6264k</string>
        <key>LSMinimumSystemVersion</key>
-       <string>15.7</string>
+       <string>26.0</string>
        <key>NSHumanReadableCopyright</key>
        <string>Copyright © 2020 Apple. All rights reserved.</string>
 </dict>

The source code for the Apple driver is not available. Therefore, I cannot say much about it.

Known bugs

The page listing the bugs I found in Sonoma is available at macOS Sonoma and smart cards: known bugs.

Apple has not informed me that a bug has been fixed in Tahoe (or Sequoia). I therefore assume that the bugs are still present.

Conclusion

As I wrote for Sequoia, if you encounter a problem with your smart card under macOS Tahoe, I suggest you first switch from the Apple driver to my CCID driver, then check again.