2024-03-01
Typing in a rather long password each time I log into my computer or need to complete a privileged task can be bothersome. Sometime ago I came across Solokeys, which are open source hardware and firmware security keys. I chose to build the Solo 1 (or five because that's the MOQ from most PCB manufacturers). Note, at the time of writing this, the solo1-cli tool is somewhat broken with the latest FIDO2 library, meaning it must be installed explicitly at 0.9.3.
$ pip install solo1
$ pip install fido2==0.9.3
After building, I didn't use it much, as many services don't support security keys quite yet, or required a paid subscription (I.e. Bitwarden). I found Yubico's PAM for U2F, which is a PAM module to provide authentication from a U2F device.
To use this, first ensure the kernel parameters
CONFIG_HIDRAW and CONFIG_USB_HIDDEV are enabled.
Next, obtain the module via package manager or compiling from source and
generate the authorisation mapping with your key inserted. The created
directory must be named Yubico, even if not using a Yubico
key. It can be overridden in
util.h
if you choose however.
$ mkdir ~/.config/Yubico
$ pamu2fcfg > ~/.config/Yubico/u2f_keys
Enter PIN for /dev/hidraw2:
Assuming all has been successful, you can configure PAM services to use
the device. The following configures
Doas to
utilise the U2F module in the /etc/pam.d/doas file. The same
line can be added in other files where needed (eg. display manager,
system-local-login, etc.)
auth sufficient pam_u2f.so cue pinverification=0
auth include system-auth
...
Above, sufficient indicates that authentication from the device alone is enough to fully authenticate. Use required instead if you want both password and device authentication to be required. cue simply displays a prompt to press the button on the device when needed to authenticate. pinverification=0 disables the need to entre the passphrase associated with your security key. Note, this means your system can be accessed only with your key, and no password entry of any type. Set the parameter to 1 if you'd like otherwise.
Another thing of interest was locking/unlocking my system automatically when the key is removed/inserted, respectively. This can be achieved via a custom Udev rule that executes a script when a device matching the key's VID/PID is plugged in. This script will use pamtester to test for authentication success.
#!/bin/bash
if [ "$1" == "lock" ]; then
# lock system (e.g. gtklock -d)
else
if [ echo "" | pamtester login >user< authenticate ]; then
# kill lock program
fi
fi
exit 0
Now, a custom udev rule that lives in
/etc/udev/rules.d/70-solokey.rules
and looks for a matching VID/PID and executes this script when found with
the appropriate argument.
ACTION::"remove", ENV{DEVTYPE}::"usb_device", ENV{PRODUCT}::"0483/a2Ca", RUN+:"/usr/local/sbin/keyauth.sh lock"
ACTION::"add", ENV{DEVTYPE}::"usb_device", ENV{ID_BUS}::"usb", ENV{PRODUCT}::"0483/a2Ca", RUN+:"/usr/local/sbin/keyauth.sh unlock"