I've promised my past self to write this howto for my future self to avoid frustration of getting Nitrokey working on FreeBSD.
At the moment of writing this, I'm using Enlightenment desktop environment, that's why I'm installing efl flavoured pinentry.
You can find alternatives that better fit your needs with pkg search
This will update /etc/rc.conf, but you already know that.
Disable ccid in scdaemon
~/.gnupg/scdaemon.conf
If case you don't have ~/.gpupg directory, just execute
~/.gpupg/gpg-agent.conf
Naturally specify pinentry that you prefer.
If you see something like message above, then all is good.
If it doesn't work try killing scdaemon before retrying:
If you have your public GPG key stored somewhere on the net and your Nitorkey has configured URL of key you can simply run:
and type `fetch` in gpg/card prompt.
gpg will fetch and import your public key. Finally type `quit`
At this point you should set key owner trust.
Naturally I trust my key Ultimately (5).
You need to whilelist your key for SSH usage via gpg-agent. For this you need to obtain keygrip of your key
I have multiple subkeys. You are looking for Keygrip of certification key (`[C]`). In my case, keygrip is `B3A158D440DC6DFBF1E8C1AD6F741164702C72E6`
You need to add this keygrip to ~/.gnupg/sshcontrol
It's also possible to explicitly disable key in sshcontrol by prefixing it with `!`.
In some time in the future this step may change:
Since we're going to use Nitrokey for SSH authentication, we will not use ssh-agent. Instead we will use gpg-agent.
We need to configure `SSH_AUTH_SOCK` environment variable.
There are multiple places where this can be done, I generally work in GUI environment, so one option is to set it in ~/.xinitrc, which is how I currently start my desktop environment (with
Whatever the case something like this needs to be set:
Log out and log in, to ensure that `u2f` group as well as `SSH_AUTH_SOCK` is properly set. In fact verify that
Assuming you have GitLab account simply run:
If it works you will be asked for smartcard pin (via pinentry). Once you enter correct code ssh will login and you will be greeted by GitLab.
Sometimes I've noticed that SSH will not trigger pinentry, a simple workaround is to decrypt some encrypted file.
Step 1: Install stuff
Code:
pkg install gnupg pinentry-efl pcsc-lite u2f-devd libccid
At the moment of writing this, I'm using Enlightenment desktop environment, that's why I'm installing efl flavoured pinentry.
You can find alternatives that better fit your needs with pkg search
Code:
pkg search pinentry
# pinentry-1.3.3 Collection of simple PIN or passphrase entry dialogs
# pinentry-curses-1.3.3 Curses version of the GnuPG password dialog
# pinentry-efl-1.3.3 EFL version of the GnuPG password dialog
# pinentry-fltk-1.3.3 FLTK version of the GnuPG password dialog
# pinentry-gnome-1.3.3 GNOME version of the GnuPG password dialog
# pinentry-gtk2-1.3.3 GTK 2.0 version of the GnuPG password dialog
# pinentry-qt5-1.3.3 Qt 5 version of the GnuPG password dialog
# pinentry-qt6-1.3.3 Qt 6 version of the GnuPG password dialog
# pinentry-tty-1.3.3 Console version of the GnuPG password dialog
Step 2: configure and enable and start pcsc
Code:
sysrc pcscd_flags=--disable-polkit
sysrc pcscd_enable="YES"
This will update /etc/rc.conf, but you already know that.
Code:
service pscsd start
Step 3: Add users to u2f group
Code:
pw groupmod u2f -m graudeejs
Step 4: Configure gpg as/for user
Disable ccid in scdaemon
~/.gnupg/scdaemon.conf
Code:
disable-ccid
If case you don't have ~/.gpupg directory, just execute
gpg. I'll create it with proper permissionsstep 5: Set point GPG agent to pinentry app and enable SSH support
~/.gpupg/gpg-agent.conf
Code:
pinentry-program /usr/local/bin/pinentry-efl
enable-ssh-support
Naturally specify pinentry that you prefer.
Step 6: Use your gpg card
Code:
gpg --card-status
# Reader ...........: Nitrokey Nitrokey 3 [CCID/ICCD Interface] 00 00
# Application ID ...: D276000124010304000F586595D90000
# Application type .: OpenPGP
# Version ..........: 3.4
# Manufacturer .....: Nitrokey
# Serial number ....: 12345768
# Name of cardholder: Aldis Berjoza
# Language prefs ...: en
# Salutation .......: Mr.
# URL of public key : https://redacted.example.com/keys/v3.asc
# Login data .......: graudeejs
# Signature PIN ....: forced
# Key attributes ...: ed25519 cv25519 ed25519
# Max. PIN lengths .: 127 127 127
# PIN retry counter : 3 3 3
# Signature counter : 351
# KDF setting ......: off
# UIF setting ......: Sign=on Decrypt=off Auth=off
# Signature key ....: 2BDD 19C3 9A56 6942 3703 9A87 F1BB EF0C C2C0 6754
# created ....: 2023-08-01 19:53:43
# Encryption key....: A94D 0E0C 6468 9DD7 E7D4 C0A8 4805 B465 25AA 22DA
# created ....: 2023-08-01 19:54:26
# Authentication key: 03FD DEA1 6A91 DB58 BCF0 5446 7FD1 4316 DF90 887E
# created ....: 2023-08-01 19:55:27
# General key info..: sub ed25519/F1BBEF0CC2C06754 2023-08-01 Aldis Berjoza <redacted@example.com>
# sec# ed25519/D5112D740F5544E7 created: 2023-08-01 expires: 2030-01-17
# ssb> ed25519/F1BBEF0CC2C06754 created: 2023-08-01 expires: 2027-01-18
# card-no: 000F 586595D9
# ssb> cv25519/4805B46525AA22DA created: 2023-08-01 expires: 2027-01-18
# card-no: 000F 586595D9
# ssb> ed25519/7FD14316DF90887E created: 2023-08-01 expires: 2027-01-18
# card-no: 000F 586595D9
If you see something like message above, then all is good.
If it doesn't work try killing scdaemon before retrying:
Code:
killall -KILL scdaemon
Step 7: Import your GPG public key
If you have your public GPG key stored somewhere on the net and your Nitorkey has configured URL of key you can simply run:
Code:
gpg --card-edit
and type `fetch` in gpg/card prompt.
gpg will fetch and import your public key. Finally type `quit`
At this point you should set key owner trust.
Code:
gpg --edit-key aldis
Code:
gpg> trust
5
Naturally I trust my key Ultimately (5).
Step 8: configure SSH agent
You need to whilelist your key for SSH usage via gpg-agent. For this you need to obtain keygrip of your key
Code:
gpg --list-keys --with-keygrip
# pub ed25519 2023-08-01 [C] [expires: 2030-01-17]
# 075BA1E783175EA818C534F3D5112D740F5544E7
# Keygrip = B3A158D440DC6DFBF1E8C1AD6F741164702C72E6
# uid [ultimate] Aldis Berjoza <redacted@example.com>
# sub ed25519 2023-08-01 [S] [expires: 2027-01-18]
# 2BDD19C39A56694237039A87F1BBEF0CC2C06754
# Keygrip = BE08C2B39A1381DD23AE70A5750B9B064FCF9503
# sub cv25519 2023-08-01 [E] [expires: 2027-01-18]
# A94D0E0C64689DD7E7D4C0A84805B46525AA22DA
# Keygrip = 77787AC2EF7E600814A7CB5B6A76D1B554F42E74
# sub ed25519 2023-08-01 [A] [expires: 2027-01-18]
# 03FDDEA16A91DB58BCF054467FD14316DF90887E
# Keygrip = 1BC18F9FF4F6F81BED82EF0A91E70DF1AEA03DF3
I have multiple subkeys. You are looking for Keygrip of certification key (`[C]`). In my case, keygrip is `B3A158D440DC6DFBF1E8C1AD6F741164702C72E6`
You need to add this keygrip to ~/.gnupg/sshcontrol
Code:
B3A158D440DC6DFBF1E8C1AD6F741164702C72E6
It's also possible to explicitly disable key in sshcontrol by prefixing it with `!`.
In some time in the future this step may change:
Step 9: Configure your environment
Since we're going to use Nitrokey for SSH authentication, we will not use ssh-agent. Instead we will use gpg-agent.
We need to configure `SSH_AUTH_SOCK` environment variable.
There are multiple places where this can be done, I generally work in GUI environment, so one option is to set it in ~/.xinitrc, which is how I currently start my desktop environment (with
startx)Whatever the case something like this needs to be set:
Code:
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
Step 10: Log out
Log out and log in, to ensure that `u2f` group as well as `SSH_AUTH_SOCK` is properly set. In fact verify that
Step 11: Test
Assuming you have GitLab account simply run:
Code:
ssh -T git@gitlab.com
# Welcome to GitLab, @graudeejs!
If it works you will be asked for smartcard pin (via pinentry). Once you enter correct code ssh will login and you will be greeted by GitLab.
Sometimes I've noticed that SSH will not trigger pinentry, a simple workaround is to decrypt some encrypted file.
Code:
gpg --decrypt previously_encrypted_file.gpg
Random notes
- Depending on your Nitrokey firmware version it may be necessary to update it. Some old firmware versions would not work on FreeBSD, but if you received new Nitrokey recently than firmware is already recent enough.
- Sometimes you need to decrypt something to unlock GPG key before you can SSH into server. Don't know why but sometimes SSHing into server doesn't trigger GPG key/pinentry.