Since May 2023 I host the blog myself (on my own server using my own
domain name) and no more on Google blogger servers. I am very happy
with this change.
Statistics
For 2024 the blog served 225977 pages (~25 pages per hour) for a total of 26.41 GB.
More and more applications are using smart cards. So they all need to
behave cooperatively to share the access to the card.
PC/SC provides a way to connect to a smart card and get an exclusive
access to it. That is the parameter dwShareMode of SCardConnect(). It
can take 3 values:
SCARD_SHARE_SHARED - This application will allow others to share the reader.
SCARD_SHARE_EXCLUSIVE - This application will NOT allow others to
share the reader.
SCARD_SHARE_DIRECT - Direct control of the reader, even without a
card. SCARD_SHARE_DIRECT can be used before using SCardControl()
to send control commands to the reader even if a card is not present
in the reader. Contrary to Windows winscard behavior, the reader is
accessed in shared mode and not exclusive mode.
If you use SCARD_SHARE_EXCLUSIVE then no other application can use the
reader, and the card inserted in the reader, until the application calls
SCardDisconnect().
If you try to use SCARD_SHARE_EXCLUSIVE while another application already
has a connection to the reader then your own call fails with
SCARD_E_SHARING_VIOLATION. Only one application can connect to the
reader when SCARD_SHARE_EXCLUSIVE is used.
$ gpg2--card-status
gpg: selecting card failed: No such devicegpg: OpenPGP card not available: No such device
I tried to reproduce the problem and log the GnuPG PC/SC calls as
described in PCSC API spy using LIBPCSCLITE_DELEGATE.
Unfortunately the environment variable LIBPCSCLITE_DELEGATE is
ignored by scdaemon (GnuPG program used to access the smart card). I
guess that is because scdaemon sanitizes its environment to limit
attacks.
I had to slightly modify pcsc-lite to force the use of the spying
library:
SCardEstablishContext i dwScope: SCARD_SCOPE_SYSTEM (0x00000002) o hContext: 0x43293756
=> SCARD_S_SUCCESS [0x00000000] [0.010792]
SCardListReaders i hContext: 0x43293756 i mszGroups: (null) o pcchReaders: 0x0000001A o mszReaders: NULL
=> SCARD_S_SUCCESS [0x00000000] [0.000161]
SCardListReaders i hContext: 0x43293756 i mszGroups: (null) o pcchReaders: 0x0000001A o mszReaders: Alcor Micro AU9540 00 00 o mszReaders:
=> SCARD_S_SUCCESS [0x00000000] [0.000287]
SCardConnect i hContext: 0x43293756 i szReader Alcor Micro AU9540 00 00 i dwShareMode: SCARD_SHARE_EXCLUSIVE (0x00000001) i dwPreferredProtocols: 0x00000003 (T=0, T=1) i phCard 0x00000000 (0) i pdwActiveProtocol 0x00000000 (0) o phCard 0x00000000 (0) o dwActiveProtocol: T=1 (0x00000002) => SCARD_E_SHARING_VIOLATION [0x8010000B] [0.007124]
SCardReleaseContext i hContext: 0x43293756
=> SCARD_S_SUCCESS [0x00000000] [0.000101]
The call to SCardConnect() fails with SCARD_E_SHARING_VIOLATION.
I then modified my ~/.gnupg/scdaemon.conf file to contain:
disable-ccid
pcsc-shared
And it now works better:
SCardEstablishContext i dwScope: SCARD_SCOPE_SYSTEM (0x00000002) o hContext: 0x4EFB8700
=> SCARD_S_SUCCESS [0x00000000] [0.011911]
SCardListReaders i hContext: 0x4EFB8700 i mszGroups: (null) o pcchReaders: 0x0000001A o mszReaders: NULL
=> SCARD_S_SUCCESS [0x00000000] [0.000177]
SCardListReaders i hContext: 0x4EFB8700 i mszGroups: (null) o pcchReaders: 0x0000001A o mszReaders: Alcor Micro AU9540 00 00 o mszReaders:
=> SCARD_S_SUCCESS [0x00000000] [0.000162]
SCardConnect i hContext: 0x4EFB8700 i szReader Alcor Micro AU9540 00 00 i dwShareMode: SCARD_SHARE_SHARED (0x00000002) i dwPreferredProtocols: 0x00000003 (T=0, T=1) i phCard 0x00000000 (0) i pdwActiveProtocol 0x00000000 (0) o phCard 0x1EF6C421 (519488545) o dwActiveProtocol: T=1 (0x00000002)
=> SCARD_S_SUCCESS [0x00000000] [0.009658]
SCarControl i hCard: 0x1EF6C421 i dwControlCode: CM_IOCTL_GET_FEATURE_REQUEST (0x42000D48) i bSendLength 0x00000000 (0) i bSendBuffer i NULL o bRecvLength 0x00000006 (6) o bRecvBuffer o 0000 12 04 42 33 00 12 ..B3..
=> SCARD_S_SUCCESS [0x00000000] [0.000267]
parsing CM_IOCTL_GET_FEATURE_REQUEST results:
Tag FEATURE_GET_TLV_PROPERTIES is 0x42330012
[...]
The call to SCardConnect() now works ang GnuPG continues with
SCarControl(), etc.
Author: Werner Koch <wk@gnupg.org>
Date: Fri Mar 12 09:21:57 2021 +0100
scd: New option --pcsc-shared.
* scd/scdaemon.h (opt): Add field opcsc_shared.
* scd/scdaemon.c (opcscShared): New.
(opts): Add "--pcsc-shared".
(main): Set flag.
* scd/apdu.c (connect_pcsc_card): Use it.
(pcsc_get_status): Take flag in account.
* scd/app-openpgp.c (cache_pin): Bypass in shared mode.
(verify_chv2: Do not auto verify chv1 in shared mode.
* scd/app-piv.c (cache_pin): By pass caceh in shared mode.
--
This option should in general not be used. The patch tries to limit
bad effects but using shared mode is somewhat dangerous depending on
the other PC/SC users.
err = pcsc_connect (pcsc.context,
reader_table[slot].rdrname,
- PCSC_SHARE_EXCLUSIVE,
+ opt.pcsc_shared? PCSC_SHARE_SHARED:PCSC_SHARE_EXCLUSIVE,
PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1,
&reader_table[slot].pcsc.card,
&reader_table[slot].pcsc.protocol);
Temporary exclusive access
It is possible to get an exclusive access to a card but still share the
reader with other applications.
The idea is to request an exclusive access for a short time, only when
needed, using PC/SC transactions.
SCardBeginTransaction()
Establishes a temporary exclusive access mode for doing a series
of commands in a transaction.
You might want to use this when you are selecting a few files
and then writing a large file so you can make sure that another
application will not change the current file. If another
application has a lock on this reader or this application is in
SCARD_SHARE_EXCLUSIVE the function will block until it can
continue.
SCardEndTransaction()
Ends a previously begun transaction.
The calling application must be the owner of the previously
begun transaction or an error will occur.
The application connects to the reader using SCARD_SHARE_SHARED. And
then uses SCardBeginTransaction()/SCardEndTransaction()
to send a list of APDU without any interruption. Typically the
application does something like:
start a transaction
submit the user PIN code
perform a protected operation like signing
invalidate the user PIN code
end the transaction
With this algorithm another application cannot inject a command between
steps 1 and 5 and benefit from the verified user PIN.
GnuPG and transactions
I had a look at the GnuPG source code and no PC/SC transaction is ever used.
Conclusion
Using an exclusive access at SCardConnect() is problematic in a multi
applications system.
Using the static library libpcsclite.a instead of the dynamic one
libpcsclite.so.1 has pros and cons.
Pros
The application binary does not depend on an external library. It is
then easier to use on a minimal system that works on "any" x86_64
GNU/Linux distribution.
If the library libpcsclite.a uses a protocol version that is
different from the protocol version used by the installed pcscd
server then client/server communication will fail. It will not "run
everywhere". (See Accessing smart cards from inside a flatpak sandbox).
Conclusion
The Debian package does NOT provide the static version of the library
because of the cons listed above.
But it may make sens for Alpine Linux or another specialized
distribution to provide a static version of the library.
My CCID driver has not been updated in macOS since Sonoma. It is still
version 1.5.1.
The CCID version 1.5.2 was released in January 2023 but that version was
not included by Apple in macOS Sonoma. That was a bit surprising when
Sonoma was released in 2023. It is now worrying.
The current/latest version is 1.6.1 released in July 2024.
I guess Apple provides my CCID driver as a backup only. They do not plan
to invest much time and update to the latest version.
Updated CCID driver
If you need a CCID driver more recent than the version 1.5.1 provided by
Apple you can contact me.
The Open Source components of Sequoia 15.0 are already available.
The component SmartcardCCID-55036 points to the GitHub project
apple-oss-distributions/SmartcardCCID. The patch
for version 55036 released on September 24th, 2024 for Sequoia compared
to version 55033 released on September 22th, 2023 for Sonoma is limited
to changes in the way the software is patched by Apple. You can see the
difference at SmartcardCCID-55036.
The repository owner is Classic Values described as "Software Development
and Design Corporation built by Freelancing Solo-entrepreneur" with more
than 5000 projects.
This fork is more interesting. Some minor patches have been applied.
One patch is slow down ccid communication
and it adds a delay of 10ms on each USB write. I have no idea why.
Maybe to allow a slow/bogus swissbit reader to correctly interact with the
driver.
As with Sonoma, the driver used by default for CCID smart card readers is
a driver written by Apple.
See the chapter "Reader name dynamically generated" from macOS Sonoma
and smart cards status
to know how I know that. It is related to the reader name reported by PC/SC,
for example by pcsctest installed by default on macOS.
If I compare the Info.plist of the usbsmartcardreaderd.slotd with the
latest macOS Sonoma I get:
I have not been notified by Apple that a bug has been fixed in Sequoia.
So I guess the bugs are still present.
I discovered a new problem with Apple driver: the error returned by
SCardConnect() call is "Card is unresponsive."
% pcsctest
MUSCLE PC/SC Lite Test Program Testing SCardEstablishContext : Command successful. Testing SCardGetStatusChange Please insert a working reader : Command successful. Testing SCardListReaders : Command successful. Reader 01: Gemplus USB SmartCard Reader Enter the reader number : 1 Waiting for card insertion : Command successful. Testing SCardConnect : Card is unresponsive.
I get this result even if the card is correctly powered. The reader LED
is fixed, indicating the card is powered.
I was able to sometimes get the card ATR. Very strange to have such a
simple bug unnoticed by QA.
After enabling my CCID driver (see Enable my CCID driver),
of course, the problem is fixed.
Conclusion
If you have a smart card issue on macOS Sequoia, my first suggestion is
to switch from the Apple driver to my CCID driver and check again.