[PATCH gnupg] scd: Add Nitrokey 3 to pcsc-shared interference detection

Artemii Bigdan artem at bigdan.in
Tue Jun 23 19:07:56 CEST 2026


Hello,

The patch was tested against a Nitrokey 3 in my possession.

It was heavily inspired by Arnaud Patard's earlier patch at
https://gist.github.com/apatard/2049a50505a482c3e1e7906cba40fd72

I do not have documentation from Nitrokey on the CCID behavior of the
device. The observations below are from testing. More information
about the hardware can be found at https://www.nitrokey.com

The setup: scdaemon.conf with disable-ccid and pcsc-shared. KeePassXC
accesses the same token through pcscd for database unlock.

The symptom: after KeePassXC touches the token, gpg --card-status returns
"Card error". The error stays until scdaemon is restarted. The USB
device is still visible (lsusb shows it), but scdaemon cannot communicate
with it anymore.

What happens: KeePassXC triggers a state change on the CCID interface.
scdaemon detects the change and reconnects through pcscd, but the OpenPGP
applet on the card has been de-selected. The next LEARN APDU fails, and
scdaemon has no way to recover. It returns "Card error" on every attempt
after that.

Why: check_external_interference() only handled Yubikey cards.
Nitrokey is CARDTYPE_GENERIC, so the function skipped the AID check,
the applet was never re-selected, and the error never cleared.

The fix has two parts.

The first part is generic. check_external_interference() no longer checks
the cardtype. The early-return condition changed from
"!opt.pcsc_shared || cardtype != YUBIKEY" to just "!opt.pcsc_shared".
When pcsc-shared is active, any card can be disturbed by another pcsc
client, not just Yubikey. I also removed the Yubikey guard from
do_reselect() in app-openpgp.c. Sending the OpenPGP SELECT APDU is
harmless for any card that supports OpenPGP. maybe_switch_app() now
checks for interference on every operation when pcsc-shared is active,
not only after direct APDU use.

The second part adds explicit Nitrokey 3 support: CARDTYPE_NK3 enum,
ATR string detection ("Nitrokey" at offset 5), and parity with Yubikey
in the PIV and OpenPGP app switching paths. This part follows Arnaud's
approach.

The difference from Arnaud's approach is in the interference detection.
His patch kept a per-card whitelist (YUBIKEY || NK3). This patch uses
no cardtype check at all. When pcsc-shared is active, the interference
detection applies to all cards. The stale applet problem is not specific
to any particular token, it is a consequence of sharing the pcsc reader.

Hope that clarifies,

- Artemii

On 6/22/26 6:29 AM, NIIBE Yutaka wrote:
> Hello,
>
> Thank you for your patch.
>
> Artemii Bigdan <artem at bigdan.in> wrote:
>> this patch extends the pcsc-shared interference detection introduced
>> in commit rG044e5a3c3801 (T5484) to also cover Nitrokey 3 tokens.
> Is there any information available for Nitrokey 3 tokens?  If any,
> please let us know.  With no information, it's mostly impossible to
> understand the changes.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0x4BBCA36FA9E37526.asc
Type: application/pgp-keys
Size: 1314 bytes
Desc: OpenPGP public key
URL: <https://lists.gnupg.org/pipermail/gnupg-devel/attachments/20260623/13701425/attachment.key>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: OpenPGP digital signature
URL: <https://lists.gnupg.org/pipermail/gnupg-devel/attachments/20260623/13701425/attachment.sig>


More information about the Gnupg-devel mailing list