Yubikey 5 on Void linux

Posted on Jan 11, 2023

I recently (finally) got myself a yubikey which i plan to use with pass - and hence gpg.

In this article, we take a look into the basic setup required to make the yubikey work on void linux.

Install required packages

First, we need to install a couple of packets such as a pcsc daemon and the yubikey manager:

$ xbps-install -Su u2f-hidraw-policy gnupg2-scdaemon yubikey-manager pcsc-ccid pcsclite

Also make sure that your user is a member of the plugdev group to use the key via gnupg2 (more on that later).

Basic setup

ykman and pcscd

ykman requires pcscd to be running. Since i won’t be fiddling with ykman too often and don’t fancy running yet another daemon permanently as root, i’m stating pcscd just ‘on-demand’ by manually launching it:

# /etc/sv/pcscd/run

After that, you should be able to launch ykman as your normal user:

$ ykman list
WARNING: No OTP HID backend available. OTP protocols will not function.
ERROR: Unable to list devices for connection
YubiKey 5C NFC (5.4.3) [CCID] Serial: 20111000

ykman configuration

First, we disable applets we don’t need for USB and NFC:

$ ykman config usb -d OTP
$ ykman config usb -d U2F
$ ykman config nfc -d OTP
$ ykman config nfc -d U2F
...
$ ykman config usb -l
OpenPGP

Then, we configure the key to auto eject itself on touch and after 30 seconds:

$ ykman config usb --touch-eject --autoeject-timeout 30

…and we finally reset the openpgp applet:

$ ykman openpgp reset
WARNING! This will delete all stored OpenPGP keys and data and restore factory settings. Proceed? [y/N]: y
Resetting OpenPGP data, don't remove the YubiKey...
Success! All data has been cleared and default PINs are set.
PIN:         123456
Reset code:  NOT SET
Admin PIN:   12345678

(Don’t forget to touch your key due to auto-eject to ‘insert’ it before executing this (and following) commands).

Now, we can change the admin and access pin:

$ ykman openpgp access change-admin-pin
...
$ ykman openpgp access change-pin
...

GPG setup

We can now finally start using our new yubikey using GPG.

First, let’s see if gpg can access it using the --card-status command.

Note: By default, gpg does not use pcscd, so you must kill it before gpg can access your yubi key (and if pcscd fails, you might want to kill the gpg-agent…).

Anway, thats what you should be seeing: (Tap the key if gpg complains about failing to find a device if you setup auto-eject)

$ gpg --card-status
Reader ...........: 1050:0404:X:0
Application ID ...: D2760001240100000006206929530000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 20692953
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......: 
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
UIF setting ......: Sign=off Decrypt=off Auth=off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

Generate a new key

$ gpg --expert --full-generate-key
gpg (GnuPG) 2.3.8; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC (sign and encrypt) *default*
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (13) Existing key
  (14) Existing key from card
Your selection? 9
Please select which elliptic curve you want:
   (1) Curve 25519 *default*
   (2) Curve 448
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 
Key does not expire at all
Is this correct? (y/N) y

Now, that’s all fine and dandy, but openkeychain will not be able to decrypt messages with such a key as of January 2023 if a recent version of gnupg was used to create the key, so we edit the key to disable AEAD:

Set key prefs (optional if you don’t care about openkeychain)

$ gpg --edit-key $your_key_id

gpg> showpref
[ultimate] (1). Yubikey HSM <yubikey-hsm@blinkenlights.ch>
     Cipher: AES256, AES192, AES, 3DES
     AEAD: OCB
     Digest: SHA512, SHA384, SHA256, SHA224, SHA1
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, AEAD, Keyserver no-modify

# Note 'AEAD: OCB' - we will now *set* all prefs excluding that.
gpg> setpref AES256, AES192, AES, 3DES, SHA512, SHA384, SHA256, SHA224, SHA1, ZLIB, BZIP2, ZIP, Uncompressed
	Set preference list to:
     Cipher: AES256, AES192, AES, 3DES
     AEAD: 
     Digest: SHA512, SHA384, SHA256, SHA224, SHA1
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
Really update the preferences? (y/N) y
                                      
gpg> save

Exporting the key

In order to have a backup (in case the Yubikey breaks or is lost), we will take a backup of the key and store it in a very secret place.

$ gpg -a --export-secret-key this-key@example.com > privkey.asc

Move key to YubiKey

First, we move the signature and authentication key:

$ gpg --edit-key $your-key
gpg> keytocard
Really move the primary key? (y/N) y
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1
                 
gpg> keytocard
Really move the primary key? (y/N) y
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 3
gpg> save

After that, --card-status should confirm that the signature and authentication key are moved - but not the secret key, so let’s do that now:

$ gpg --edit-key $your-key

gpg> key 1
gpg> keytocard
Please select where to store the key:
   (2) Encryption key
Your selection? 2
gpg> save

# we are all done, so also publish the key to the keyserver:
$ gpg --keyserver keys.openpgp.org --send-keys $your-key
# Now wait for the e-mail to confirm the upload.

…and that’s it!

Recovery

Re-adding the stub

If you somehow lost your .gpg directory (or want to use the same key on a different computer), you’ll have to re add a stub key to your installation.

First, import the public key using gpg --import, like you’d do with any other key.

Then, run this strange command:

$ gpg-connect-agent "scd serialno" "learn --force" /bye
S SERIALNO D1230001250200000006000000000000
OK
S PROGRESS learncard k 0 0
S PROGRESS learncard k 0 0
S PROGRESS learncard k 0 0
OK

After that, gpg --list-secret-keys should show the secret (stub) key.