Page MenuHome GnuPG

gpg-agent 2.3.1: PIN caching not working for decrypt operations
Closed, ResolvedPublic

Description

First of all, thanks for your continuous work on maintaining and improving this project!

A few days ago I installed gnupg on my new MacBook using Homebrew, which comes with version 2.3.1, and trying to use a YubiKey. First I got bitten by T5415, which I fixed as described in that ticket - by adding disable-ccid to ~/.gnupg/scdaemon.conf.

After some time of using it, I realized that it asked for the PIN for every operation, whereas I remembered the PIN should be cached for some time. To verify this assumption, I installed gnupg@2.2, and indeed, the PIN was cached after first entering it.

As this didn't seem an intended difference in behavior between versions, I decided to debug it further. I enabled gpg-agent debug logging, and noticed some interesting messages:

  • when writing to the cache:
2021-05-10 23:55:50 gpg-agent[61532] DBG: chan_9 <- S PINCACHE_PUT 0/openpgp/2 *redacted*
2021-05-10 23:55:50 gpg-agent[61532] DBG: handle_pincache_put: caching 'PINCACHE_PUT'->'0/openpgp/2 *redacted*'
2021-05-10 23:55:50 gpg-agent[61532] DBG: agent_put_cache 'PINCACHE_PUT'.-1 (mode 6) requested ttl=-1
  • when reading from the cache:
2021-05-10 23:56:05 gpg-agent[61532] DBG: handle_pincache_get: enter '0/openpgp/2'
2021-05-10 23:56:05 gpg-agent[61532] DBG: agent_get_cache '0/openpgp/2'.-1 (mode 6) ...
2021-05-10 23:56:05 gpg-agent[61532] DBG: ... miss

So it looked like writing to the cache wasn't working. Taking a look at handle_pincache_put(), it should log handle_pincache_put: caching 'key'->'pin', but instead it was logging handle_pincache_put: caching 'PINCACHE_PUT'->'pin key', so somehow it was called with a string including the PINCACHE_PUT command. Looking at all the call sites, I noticed this:

  • call-scd.c:548
else if ((s=has_leading_keyword (line, "PINCACHE_PUT")))
  err = handle_pincache_put (line);

Although it seemed weird to me the padding_info_cb() callback would get called when asking for the PIN, this was the only place where handle_pincache_put() was called with the whole command line. I downloaded the source, added some debug logging, and confirmed my hunch. Also, changing the call to handle_pincache_put (s); fixed the cache writing issue, and asking for the PIN now behaved as expected.

If this is not too urgent a fix, I will send a patch later today.

Details

Version
2.3.1

Revisions and Commits

Event Timeline

werner added a subscriber: werner.

The pincache is actually not what you think it is. It is only used to allow switching between different application on a Yubikey which reqieres a new VERIFY command after switching back to the first application the card. What you feel as caching is the state of the card, which usually keeps its verification state until the card is powered down.

Nevertheless, there might be problems with macOS on 2.3; for example T5415.

Yes, I already linked to T5415, but that breaks YubiKey completely, and I fixed it with disable-ccid.

Still, PIN caching is not working in 2.3 as it did in 2.2. Also, looking at the code, that call of handle_pincache_put(line) seems wrong, and changing it to handle_pincache_put(s) fixes PIN caching, so I’m not sure how this is not related?

So I did a bit more reading on smartcard PIN caching, and took a better look at the debug logging of gnupg 2.2, and learned that, indeed, the PIN is cached by the card and not by any one gnupg component.

What's weird is that with gnupg 2.3 and a YubiKey, PIN caching is not working properly - meaning I'm asked for the PIN on every operation. What's even weirder is that fixing that handle_pincache_put() wrong call "fixes" caching, however the PIN is cached by the agent, as far as I can tell.

Is this expected behaviour in 2.3? I didn't see it mentioned in the changelog, so I guess not. And if not, is it possible that the logic introduced with this commit might ask for the PIN every time, when used with a smartcard?

Funnily enough, this behaviour is actually a feature request in T3362. :-)

@werner Please let me know if there's anything I can do to debug this further.

I just wanted to chime in that I've had exactly the same experience as @lbogdan: gnupg 2.3 stopped recognizing my yubikey entirely on MacOS until the T5415 workaround (disable-ccid). After that, pin caching was broken until I applied his patch to call-scd.c:548, which makes it work as before. Without these two changes the experience with gnupg 2.3 is degraded relative to 2.2.

It's not clear whether you are talking about PIN caching related to signing operations or decryption operations.

Regarding signing operations the Functional Specification of the OpenPGP application on ISO Smart Card Operating Systems says in section 4.3:

The command PSO:CDS [Compute Digital Signature] uses PW1 in a different mode then the other commands, it is valid for one command only and has to be presented again for the next signature calculation, for that reason terminals and software should not cache the passwords of a card! This behaviour is defined in the 1st byte of the 'PW status' DO can be changed by the user by option (announced in Extended Capabilities), so that the password remains valid in the card up to a reset or changing the application.

So:

  1. gpg is following the specs by not caching the PIN.
  2. If you do not want to enter the PIN for every signing operation, then you need to tell the OpenPGP application on your YubiKey that you want the password to remain "valid in the card up to a reset or changing the application".

@ikloecker Sorry for not being clear, I was not aware different operations have different behaviors in regard to entering / caching the PIN.

I was specifically talking about decrypt operations. And as I said, caching behavior differs between 2.2 and 2.3, so one of them has to be inaccurate.

@znull You can also fix the detection issue by building with ./configure --disable-ccid-driver, in which case you won't need the disable-ccid setting anymore.

For reference, this is discussed in this Homebrew PR.

lbogdan renamed this task from gpg-agent 2.3.1: PIN caching not working to gpg-agent 2.3.1: PIN caching not working for decrypt operations.May 17 2021, 11:21 AM

Just got around to testing this on Linux, and I can confirm the same behavior: decryption PIN caching works on 2.2 and doesn't work on 2.3.

It's not clear whether you are talking about PIN caching related to signing operations or decryption operations.

In my use case (signing git commits), it's signing and not decryption.

So:

  1. gpg is following the specs by not caching the PIN.

Having to enter a pin on every git commit is too cumbersome; if that were the only way this worked I wouldn't use a yubikey at all.

  1. If you do not want to enter the PIN for every signing operation, then you need to tell the OpenPGP application on your YubiKey that you want the password to remain "valid in the card up to a reset or changing the application".

Is that the signature PIN force bit? If so it's not having any effect for me - I need @lbogdan's patch.

➤ gpg --card-status | grep force
Signature PIN ....: not forced
gniibe added a subscriber: gniibe.

Thanks. I push the fix of yours.

It's a bit complicated.

In 2.3, for Yubikey, support of PIV application of the card was added. Now, there are two: OpenPGP and PIV.

To support switching OpenPGP<->PIV, scdaemon uses gpg-agent feature of PIN caching.

The PIN caching by gpg-agent is only used by scdaemon when the switch between OpenPGP<->PIV. In theory, if a user only uses a single application (OpenPGP only, this time), PIN caching doesn't matter.

However, when KEYGRIP based access is in action (scd/app.c:app_do_with_keygrip), all applications are scanned. And this time, application switch between OpenPGP<->PIV occurs.

So, in fact, PIN caching matters.

gniibe triaged this task as High priority.May 28 2021, 7:18 AM
gniibe edited projects, added yubikey; removed MacOS.

Based on the info about this being caused by the added support of PIV, I poked around on the docs at https://gnupg.org/documentation/manuals/gnupg/gpg_002dcard.html and noticed the disable-application stuff. I added "disable-application piv" to ~/.gnupg/scdaemon.conf and the behavior went back to pin caching working as before. Since I don't use PIV, this is an acceptable workaround for me.

I added "disable-application piv" to ~/.gnupg/scdaemon.conf and the behavior went back to pin caching working as before. Since I don't use PIV, this is an acceptable workaround for me.

Second that. This fixed the issue for me.