I’ve written before on how I use a Yubikey for hardware-based GPG and 2FA on the web. I also use it for TOTP. That is, the Yubikey itself generates those common “authenticator codes” like many other Authenticator apps. But the secret seed is saved into hardware that does not support revealing it, instead of being handled by a regular app on a network-connected device.
A nasty issue I’ve been dealing with is that when I signed something using GPG,
the key would no longer work for TOTP unless I killed the gpg-agent
. And if I
used the key for TOTP, it wouldn’t work for GPG until I killed pcscd
.
For example, after having used gpg, trying to access the key for it TOTP functionality yields:
> ykman oath info
ERROR: Failed to connect to YubiKey.
And trying to use gpg
after having used the key for TOTP resulted in gpg
asking me to insert the key (even if it was right there).
The cause of the issue
pcscd
is a daemon allowing userspace applications to communicate with
smartcards (a Yubikey presents itself as a smartcard to the OS, so existing
tools just work with it). Tools that generate TOTP codes via the Yubikey (e.g.:
ykman
) use pcscd
to talk to the Yubikey itself.
gpg
however, uses scdaemon
to talk to the Yubikey, and scdaemon
tries to
use an “exclusive lock” on the key (this is because it caches data so wants to
make sure no other process is using the key). This is a problem, because if it
holds an exclusive lock, then it will work if and only if no other application
are holding a lock.
To be honest, I don’t really get why any of these applications hold ANY lock on the card when it’s not being used.
The Solution
scdaemon
needs to be configured to use only a shared lock. This can be done
by editing the file $GNUPGHOME/scdaemon.conf
and adding the line:
pcsc-shared
Note that, as the man page indicates, this has some caveats.
However, this was not enough in my case. This is because scdaemon
can use its
built-in support to talk to cards directly rather than via pcscd
. This can be
disabled by adding the follow extra directive to the same configuration file:
disable-ccid
For more notes on this, see the related issue in aports.