str4d/age-plugin-yubikey

Updating touch-policy to "cached"&pin-policy to "once": no effect on existing slots

antifuchs opened this issue ยท 9 comments

Environment

  • OS: macOS ventura
  • age-plugin-yubikey version: 0.3.2

What were you trying to do

I used age-plugin-yubikey --pin-policy once --touch-policy cached to reduce the number of times I have to provide my PIN and touch the key (especially for rekeying secrets with https://github.com/ryantm/agenix).

What happened

:;    age-plugin-yubikey --pin-policy once --touch-policy cached
โœจ Let's get your YubiKey set up for age! โœจ

This tool can create a new age identity in a free slot of your YubiKey.
It will generate an identity file that you can use with an age client,
along with the corresponding recipient. You can also do this directly
with:
    age-plugin-yubikey --generate

If you are already using a YubiKey with age, you can select an existing
slot to recreate its corresponding identity file and recipient.

When asked below to select an option, use the up/down arrow keys to
make your choice, or press [Esc] or [q] to quit.

๐Ÿ”‘ Select a YubiKey: Yubico YubiKey FIDO+CCID (Serial: 6900832)
๐Ÿ•ณ๏ธ  Select a slot for your age identity: Slot 1 (asf personal 4c, created: Sun, 05 Jun 2022 14:25:06 +0000)
Use existing identity in slot 1? yes

๐Ÿ“ File name to write this identity to: age-yubikey-identity-18fdcdd5.txt
File exists. Overwrite it? yes

โœ… Done! This YubiKey identity is ready to go.

๐Ÿ”‘ Here's the corresponding YubiKey recipient:
  age1yubikey1q0m3cprmex0d2thamkx9pwvhsqwcm2gel50rdxmeclvkgqtem9dxz4smpwv

Here are some example things you can do with it:

- Encrypt a file to this identity:
  $ cat foo.txt | rage -r age1yubikey1q0m3cprmex0d2thamkx9pwvhsqwcm2gel50rdxmeclvkgqtem9dxz4smpwv -o foo.txt.age

- Decrypt a file with this identity:
  $ cat foo.txt.age | rage -d -i age-yubikey-identity-18fdcdd5.txt > foo.txt

- Recreate the identity file:
  $ age-plugin-yubikey -i --serial 6900832 --slot 1 > age-yubikey-identity-18fdcdd5.txt

- Recreate the recipient:
  $ age-plugin-yubikey -l --serial 6900832 --slot 1

๐Ÿ’ญ Remember: everything breaks, have a backup plan for when this YubiKey does.

and then,

:;    cat age-yubikey-identity-18fdcdd5.txt
#       Serial: 6900832, Slot: 1
#         Name: asf personal 4c
#      Created: Sun, 05 Jun 2022 14:25:06 +0000
#   PIN policy: Once   (A PIN is required once per session, if set)
# Touch policy: Always (A physical touch is required for every decryption)
#    Recipient: age1yubikey1q0m3cprmex0d2thamkx9pwvhsqwcm2gel50rdxmeclvkgqtem9dxz4smpwv
AGE-PLUGIN-YUBIKEY-1VPXXJQYZRR7UM4GESUNXL
:;    rage -i identities/personal-4c.txt -d some-secret.age
Enter PIN for YubiKey with serial 6900832:
yay!
:;    rage -i identities/personal-4c.txt -d some-secret.age
Enter PIN for YubiKey with serial 6900832:
yay!

Note that each PIN prompt also requires a touch of the yubikey. I'm not sure what's going on here, but my hypothesis is that existing slots' settings can't be changed? Is that right?

str4d commented

There is no way in this plugin to alter the PIN or touch policies of an existing YubiKey slot. I don't recall if that is because it is simply not possible for YubiKeys, or only because the yubikey crate doesn't implement the capability; that would need to be investigated.

If you select an existing slot via the text UI, the existing identity in that slot gets its identity file recreated (equivalent to age-plugin-yubikey --identity). Selecting an empty slot is equivalent to age-plugin-yubikey --generate; the latter programmatic command can be used to overwrite a slot with a fresh identity.

You certainly can't change the policy to a laxer one, otherwise an attacker would just do that, and bypass the point of e.g. always having to touch the key to do an operation.

OK, I think then I'll add a laxer yubikey slot. I was surprised by this because gpg --card-edit does let you change this, IIRC - I guess there, in order to go from strict to laxer, you still have to authenticate once.

So, update: I generated a new age key in a second slot, with --pin-policy=once --touch-policy=cached and that seems to work... half-way: It doesn't require a touch on every decryption (only once every 15s, as advertised!), but still prompts for a PIN every time I run rage -d. Is that intentional?

I'm only running rage -d twice in a row, not touching the yubikey outside the initial touch; if I'm reading the "Agent" section of the readme right, this ought to only prompt once?

str4d commented

You're reading the "Agent" section for current main, not for 0.3.2. Until a few days ago, that section documented that "once" policies were treated like "always" policies, but we've managed to fix this (at least partially; there still seems to be some kind of cache eviction going on over longer timescales that we don't fully understand). Feel free to try installing current main to test and give feedback ๐Ÿ™‚

You're reading the "Agent" section for current main, not for 0.3.2.

Ooooooops ๐Ÿ˜“

I did try with latest main just now, and same result: It prompts for the PIN again, despite the slot being configured as follows:

#       Serial: 6900832, Slot: 3
#         Name: age identity d96b79b2
#      Created: Thu, 05 Jan 2023 21:54:16 +0000
#   PIN policy: Once   (A PIN is required once per session, if set)
# Touch policy: Cached (A physical touch is required for decryption, and is cached for 15 seconds)
age1yubikey1qt6xfjt40g22etwzkeyzakhe23k9hjfgjef78nhzn8wwtqsj5qfl2zlrdnr

The touch cache works, just as it did on 0.3.2.

str4d commented

We've found and fixed several bugs in the initial implementation of the PIN cache, and at least one more needs to be fixed by making changes to the yubikey crate. I'm hoping to get enough fixes into the 0.4.0 release that it is reliable enough to leave documented, so I expect to be publishing an RC or two for people to test.

Ahhh, I just read through d9c5aba#diff-f8cca32b0c315d712da3375dab4d6c52abd816618850f4c0ce5578d35efe7deaR79 and now I get why it keeps asking me the PIN every time: I am using a yubikey4c nano.

Does the 5 series fare better / do the PINs get cached there?

str4d commented

Ah yep, the YubiKey 4 problem is a recent discovery.

Does the 5 series fare better / do the PINs get cached there?

As far as I can tell, yes. We had some initial bugs as I mentioned above, but it seems to be working pretty well now (I haven't been receiving bug reports for YubiKey 5s recently, and IIRC those who reported previous bugs have said they are now fixed).