How to configure FreeBSD and applicable applications to work with Yubikey for authentication. This serves as my work-in-progress documentation of the configuration knobs needed to make this work properly. All tests were performed with an upto date FreeBSD 13.1 x64 installation as of Aug 2022.
- FreeBSD ssh with piv smartcard slot on Yubikey (pkcs11 via
libykcs11.so
) - FreeBSD ssh with fido support on Yubikey
- FreeBSD Firefox/Chromium with fido + webauthn support on Yubikey
- FreeBSD local console and gdm authentication using pam on Yubikey
- FreeBSD official YubiKey tools
These functions can co-exist without stomping on each other's usb usage (unlike gpg from my last test). See https://ludovicrousseau.blogspot.com/2019/06/gnupg-and-pcsc-conflicts.html for some background / workarounds.
Read the excellent documentation here: https://developers.yubico.com/PIV/Guides/SSH_with_PIV_and_PKCS11.html.
- If you need to do initial configuration or generate piv keys/certs follow these steps (save your PIV pin and puk somewhere safe). If you have already customized pin/puk, you can skip this step. Example below is the default pin/puk after piv applet reset, do not use the defaults for the new values.
pkg install py39-yubikey-manager
ykman piv access change-pin --pin 123456
ykman piv access change-puk --puk 12345678
- If you need to configure management key, and some piv-specific objects for better compatability. Use aes256 instead of default tdes for management (if f/w 5.4.0+), and save the management key on the yubikey protected by pin and touch. If you have f/w < 5.4.0, omit
-a aes256
, as the only supported management key algorithm was tdes .
ykman piv access change-management-key --generate --protect --touch -a aes256
ykman piv objects generate chuid
ykman piv objects generate ccc
ykman piv info
- If not already done, generate actual private key, and certificate based on resultant public key. Example shows eccp384 algorithm, but rsa2048 can also work (if using older openssh without ecc support). Pin/Touch policy can be customized as desired, but different slots have different default values. Slot numbers are 9a/9c/9d/9e for the primary 4 slots. If you need more, you can also use slots 82-95. https://developers.yubico.com/PIV/Introduction/Certificate_slots.html, and https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-generate-options-slot-public-key Feel free to customize the subject line, and the valid-days as desired. Subject line can be any RFC 4514 string.
ykman piv keys generate -a eccp384 --pin-policy once --touch-policy cached 9a 9a_pub.pem
ykman piv certificates generate --valid-days 730 --subject "Y5C_9A" 9a 9a_pub.pem
- Install the FreeBSD yubikey pkcs11 driver
- using pkg utility, install Yubico utilities and shared library
libykcs11.so
for full functionality (other pkcs11 libs can work as well, but untested for this writeup.) - Don't forget the ccid usb driver package, or pcsc-lite and libykcs11.so will not find your USB keys at all
pkg install yubico-piv-tool pcsc-lite ccid
- Setup pcscd to startup on boot (changes /etc/rc.conf for you), and manually start now
service pcscd enable
service pcscd start
- Extract public key (ecc or rsa) and save to id_rsa.pub, and copy to destination user@host authorized_keys file. (change
user@host
to a real host you have ssh access to)
ssh-keygen -D /usr/local/lib/libykcs11.so > ~/.ssh/id_rsa.pub
ssh-copy-id -i ~/.ssh/id_rsa.pub user@host
- Test out connectivity using ssh (change
user@host
to a real host you have ssh access to)
ssh -v -I /usr/local/lib/libykcs11.so user@host
- Configure ssh for current user to automatically load pkcs11 library without long CLI (can also be global if you want via
/etc/ssh/ssh_config
)
echo "PKCS11Provider /usr/local/lib/libykcs11.so" >>~/.ssh/config
- (optional) use with ssh-add and/or ssh-agent (will prompt for pin aka passphrase)
ssh-add -s /usr/local/lib/libykcs11.so
Starting with OpenSSH 8.2p1+ release, there is native support for FIDO authenticators (like Yubikey) for authentication using some new key formats. Background information here: https://developers.yubico.com/SSH/Securing_SSH_with_FIDO2.html and https://www.openssh.com/txt/release-8.2. Resident keys are best supported on the latest OpenSSH. All key types should require a PIN to be configured on the token.
- New Terms: Resident credentials are called “discoverable credentials” in CTAP 2.1.
- Yubikey firmware version 5.2.3 or newer is required for ed25519-sk key types (and is supported by both recent BLUE security key variant and recent Yubikey 5 variants)
FIDO Device | FIDO Device Version | Key Algorithms | [Non-]Resident | Notes |
---|---|---|---|---|
Yubikey Neo | f/w 3.4.9 | ecdsa-sk | Non-Resident | YSA-2018-01 in OATH, does not impact FIDO |
Yubikey Neo | f/w 3.5.0 | ecdsa-sk | Non-Resident | |
Yubikey 5 | f/w 5.1.1 | ecdsa-sk | Non-Resident | |
Yubikey 5 | f/w 5.2.3+ | ed25519-sk ecdsa-sk | Both | |
Yubikey 4 | f/w 4.3.1 | ecdsa-sk | Non-Resident | CVE-2017-15361 in rsa, but does not impact FIDO |
Yubikey 4 | f/w 4.3.5 | ecdsa-sk | Non-Resident | |
Yubikey FIDO U2F Security Key (BLUE) | f/w 3.0.0 | ecdsa-sk | Non-Resident | |
Yubikey FIDO2 Security Key NFC (BLUE) | f/w 5.4.3 | ed25519-sk ecdsa-sk | Both | |
Solo 2 | f/w 20220822+ | ed25519-sk ecdsa-sk | Both | Update your firmware from solo |
- Check your OpenSSH client version and make sure it is new enough (recommend 8.9+)
ssh -V
(If it is older than 8.9+, considerpkg install openssh
and execute ssh-keygen from /usr/local/bin/ssh-keygen) - Install libfido2 shared library, u2f-dev rules, and askpass utility (OpenSSH FIDO runtime dependancies):
pkg install libfido2 OpenSSH-askpass u2f-dev py39-fido2
- If you have not already, configure your user for u2f group privs, and your Yubikey token for a pin.
- Add local user to new u2f group to allow access to usb device mappings created by u2f-dev package.
pw group mod u2f -m user
(replaceuser
with your actual username) Failure to add your user to the correctu2f
group will result in that user not being able to access the USB device/YubiKey. Reboot or (restart devd and remove/re-insert yubikey). - Add an initial pin to the FIDO app on the Yubikey:
fido2-token -L
to attempt autodetection of Yubikey usb hid device name for use in other fido2-token commands.(replace /dev/uhid0 with actual device):fido2-token -S /dev/uhid0
- Generate the
ed25519-sk
ORecsda-sk
key (resident or non-resident) on the Yubikey. ReplaceFIDO2_Y5C
with your own friendly name as desired:- Resident ed25519-sk: (This will prompt for PIN and touch)
ssh-keygen -t ed25519-sk -O resident -O application=ssh:FIDO2_Y5C -O verify-required
- Resident ecdsa-sk: (This will prompt for PIN and touch)
ssh-keygen -t ecdsa-sk -O resident -O application=ssh:FIDO2_Y5C -O verify-required
- Non-Resident ed25519-sk: (This will generate a non-resident/non-discoverable key that can not be extracted onto a new machine with ssh-keygen -K)
ssh-keygen -t ed25519-sk
- Non-Resident ecdsa-sk: (This will generate a non-resident/non-discoverable key that can not be extracted onto a new machine with ssh-keygen -K)
ssh-keygen -t ecdsa-sk
-C "FIDO2_Y5C"
can be appended to the ssh-keygen cli arguments as desired to add a comment to give context to the owner/key.- Note: This will generate the private key with a specific SSH_SK_VERSION_MAJOR embedded, and you may only be able to extract the private key handle on a different host when the version is the same or newer (or when OpenSSH SSH_SK_VERSION_MAJOR is stable) Moving the public key around to different versions should not be an issue. YMMV. Windows ssh-keygen 8.9 and FreeBSD ssh-keygen 9.0 seem to be compatible. The purposeful changes to the middleware interface/version happened at OpenSSH version 8.4 and 8.9.
- Copy resultant public key to remote host as desired: (Change
user@host
to applicable remote host)
ssh-copy-id -i ~/.ssh/id_ed25519_sk user@host
- Optional Configuration
- Extract resident key on a new local box for use with FIDO/SSH:
cd ~/.ssh/ && ssh-keygen -K
orcd ~/.ssh/ && /usr/local/bin/ssh-keygen -K
(if you are using from ports)- Rename your private and public key files appropriately to match ssh_config of
id_ed25519_sk
[.pub] orid_ecdsa_sk
[.pub]
- Control
touch-required
,no-touch-required
,verify-required
,no-verify-required
on a destination host- Default is
touch-required
,no-verify-required
unless otherwise configured. - OpenSSH supports per-key configuration in
~/.ssh/authorized_keys
files, and global settings in/etc/ssh/sshd_config
- See https://man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT and https://man.openbsd.org/sshd_config#PubkeyAuthOptions for details.
- Default is
- Note: You can install OpenSSH v9.0 from pkg into the /usr/local/bin path if you need the updated ssh-keygen to support. The relevant error message when calling ssh-keygen with disparate SSH_SK_VERSION_MAJOR variants is "invalid format" on windows and "unsupported xxxx" on FreeBSD.
- (debugging) FIDO2 diagnostics using fido2-token
pkg install py39-fido2
(To install package)fido2-token -L
(To list out current FIDO2 tokens and associated devicenames eg:/dev/uhid0
)fido2-token -I /dev/uhid0
(To show current device configuration and capabilities)fido2-token -L -r /dev/uhid0
(To show currently configured resident credentials for FIDO eg:ssh:FIDO2_Y5C
) - Known issues.
- ssh-sk-helper internal module hangs roughly 50% of the time. This issue was identified, and a kernel bugfix committed to -current, stable/12, and stable/13. See https://bugs.freebsd.org/bugzilla//show_bug.cgi?id=263995
- usb port contention with gpg's scdaemon. There is a workaround documented here: https://ludovicrousseau.blogspot.com/2019/06/gnupg-and-pcsc-conflicts.html
This assumes that the user already has a working Xorg/gnome/gdm/dbus configuraton on FreeBSD. If you need help with this part, start with the FreeBSD handbook here: https://docs.freebsd.org/en/books/handbook/x11/
- Install libu2f-host, u2f-dev packages and firefox and/or chromium
pkg install libu2f-host u2f-dev firefox chromium
- Add local user to new u2f group to allow access to usb device mappings created by u2f-dev package.
pw group mod u2f -m user
(replaceuser
with your actual username,)
- Failure to add your user to the correct
u2f
group will result in that user not being able to access the USB device/YubiKey
- (optional) Restart the devd service if you want to test before rebooting
service devd restart
- Confirm Yubikey is detected and applicable permissions granted:
usbconfig show_ifdrv
should result in something like this:
ugen3.10: <Yubico YubiKey OTP+FIDO+CCID> at usbus3, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (30mA)
ugen3.10.0: ukbd0: <Yubico YubiKey OTP+FIDO+CCID, class 0/0, rev 2.00/5.27, addr 9>
ugen3.10.1: uhid0: <Yubico YubiKey OTP+FIDO+CCID, class 0/0, rev 2.00/5.27, addr 9>
- Make sure that
pwr=ON
is displayed for the master device (ugen3.10
in this case.) - Make sure that
FIDO
is displayed for the uhid device (may require reconfiguring your Yubikey with ykman) - Make sure that the device name (
uhid0
in this case) has the correct group permissionsls -alF /dev/uhid0
should result in something like:crw-rw-r-- 1 root u2f 0xc1 Aug 28 12:34 uhid0
- If the group
u2f
is not setup, verify your u2f-devd rules/package configuration
- Startup X and launch Firefox or Chromium
- Go to a website that has 2FA/Webauthn enabled (like github/gitlab/gmail)
- Firefox will display a little popup notification telling you that your browser is requesting Webauthn access
- Touch the Yubikey gold disk button when it starts blinking
Overview: PAM (Pluggable Authentication Modules) are supported for various services on FreeBSD and Linux. There is an open source implementation of pam_pkcs11 that provides a glue layer to allow PAM to query a configured pkcs11 library and module to authenticate using a PCS#11 token (like a Yubkikey PIV card slot). I chose a simple demonstration configuration below to allow public keys that are already in place (e.g. openssh ~/.ssh/authorized_keys) to be the authority. This was convienient since I already using PIV keys to authenticate using SSH, now I can use the same public/private keys to control authentication on the local console and Xorg/GDM as well.
- Documentation from OpenSC: https://opensc.github.io/pam_pkcs11/doc/pam_pkcs11.html and https://github.com/OpenSC/pam_pkcs11
- Install supporting pam_pkcs1 and libykcs11.so modules from FreeBSD package manager:
pkg install yubico-piv-tool pam_pkcs11 ccid pcsc-lite
will install the desired packages - Verify normal remote ssh works for a local (non-root) user authenticating using piv public/private SSH keys on your Yubikey. If this does not yet work, please follow the receipe above. Keep an active console (or two!) with root access live during testing so you can adjust/revert things without locking yourself out. You have been warned. Take backups/precautions as necessary.
- Configure pam_pkcs11 configuration files.
# Take a look at the example configuration to use different certificate/signature validations
mkdir /usr/local/etc/pam_pkcs11
cp /usr/local/share/doc/pam_pkcs11/pam_pkcs11.conf.example /usr/local/etc/pam_pkcs11/
cd /usr/local/etc/pam_pkcs11/
vi pam_pkcs11.conf
- Minimal
/usr/local/etc/pam_pkcs11/pam_pkcs11.conf
using openssh-style authenication (copy/paste contents below should be fine)
pam_pkcs11 {
use_pkcs11_module = ykcs11;
debug = false;
pkcs11_module ykcs11 {
module = /usr/local/lib/libykcs11.so
description = "Yubico Yubikey PKCS#11 so module";
slot_description = "none";
cert_policy = signature;
token_type = "Smart card";
}
use_mappers = openssh;
# Search public keys from $HOME/.ssh/authorized_keys to match users
mapper openssh {
debug = false;
module = /usr/local/lib/pam_pkcs11/openssh_mapper.so;
}
}
- Configure /etc/pam.d/system configuration file. Take a backup first
cp /etc/pam.d/system /etc/pam.d/system.good
Prependauth sufficient /usr/local/lib/security/pam_pkcs11.so
to the top of the configuration file - Test to ensure that you can authenticate any/all user(s) with valid authorized_keys file. If things do not work they way you would like, remove the yubikey, and the fallback authentications (password) in the pam system file should take effect. Note: Different keys slots (9a/9c/9d/9e) have different pin-policy and touch-policy defaults and settings. You can adjust as desired with Yubikey Manager, but only at private key generation time, not after a key has already been generated without deleting then re-creating keys. If you want to use slots other than 9a (slot 0 in pam_pkcs11.so parlance), you will have the most luck using the yubico
libykcs11.so
library. Using other libraries for pkcs11 can work, but YMMV, and extended features can be limited. - (optional) Force smartcard-only authentication by changing
sufficient
torequired
, then comment out the#auth required pam_unix.so no_warn try_first_pass nullok
line to force smartcard authentication only. You will be unable to login with any account that lacks an appropriate ~/.ssh/authorized_keys file that maps to your local Yubikey authentication. This includes loss of access to the root account. Also recommend having at least two Yubikeys (one on person, one stored in safe) to prevent a lost/damaged key from preventing access. Please be careful, especially if using encrypted root filesystem! - Test using all normal acccess methods to ensure no unexpected behavior(s). If things go horribly wrong, boot into single-user mode and adjust /etc/pam.d/system back to the original state.
- Debugging: You can turn on the debug flags
debug = true;
in/usr/local/etc/pam_pkcs11/pam_pkcs11.conf
to see lots more details on what is going on with both pkcs11 libraries, and with the openssh match backend as desired.
- Python 3.9 version as of Aug 2022
pkg install py39-yubikey-manager pcsc-lite ccid
- Enable and Startup pcsc daemon
service pcscd enable && service pcscd start
- Check status of Yubikey using ykman
ykman info
should result in something like this:
Device type: YubiKey 5C NFC
Serial number: XXXXX
Firmware version: 5.2.7
Form factor: Keychain (USB-C)
Enabled USB interfaces: OTP, FIDO, CCID
NFC transport is enabled.
Configured capabilities are protected by a lock code.
Applications USB NFC
FIDO2 Enabled Enabled
OTP Enabled Enabled
FIDO U2F Enabled Enabled
OATH Enabled Enabled
YubiHSM Auth Not available Not available
OpenPGP Enabled Enabled
PIV Enabled Enabled
- Requires ccid (bundle files for pcscd) and pcsc-lite packages and pcscd service running
- no need to edit devd rules
- Install packages:
pkg install yubico-piv-tool ccid
service pcscd enable && service pcscd start
- Use
pcscd --foreground --debug
to look at internals of pcsc-lite. Additional reading: https://ludovicrousseau.blogspot.com/2011/07/pcscd-debug-output.html - Check to see if it can find your Yubikey:
yubico-piv-tool -a list-readers
- WIP
pkg install py29-fido2