Unlocking LUKS2 with X509 Nitrokey during boot
A continuation of previous post with the instruction to unlock encrypted root partition during boot.
We will be setting up and installing a few components that will be run at a specific point during Linux boot, allowing
systemd-cryptsetup to prompt for the hardware token passphrase to unlock the LUKS2-encrypted partition. This procedure assumes that the partition is already configured to be unlocked using X509 certificate.
If you would like to use Nitrokey Storage to unlock LUKS2-encrypted device with the X509 certificate using systemd-cryptsetup, I recommend reading the previous post for configuration instructions.
I tried to write the instructions in this post in a generic way so they could be applicable regardless of the token device, Linux distribution or initramfs generation method.
In my configuration I use:
- Linux distribution: Gentoo
- Initramfs generation method: distribution kernel calling installkernel that uses dracut
- Token: Nitrokey Storage v2
If you use a similar setup – I have packaged my dracut module as a package in my overlay. Just install
sys-kernel/dracut-pcscd-cryptsetup and rebuild initramfs.
Please implement the following procedure with extreme caution. If something goes wrong – the partition will not be unlocked during the boot process. Make sure you have access to a rescue shell in your initramfs or have a backup way to boot your machine (like a live USB with chroot).
Also, using the language from the GPL license: this post is written in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
It is possible to fully rely on
systemd to manage the init process. If
/etc/crypttab is included in the initramfs,
systemd will try to start
cryptsetup.target. This target contains a set of automatically generated services that unlock devices specified in
crypttab. In version 248, systemd added support for pkcs#11 certificates into
systemd-cryptsetup, the binary that those services run to actually unlock the device and that can query the user for a passphrase.
When the system is fully booted,
pcscd and a set of other tools to communicate with the smartcard devices.
So, in order to use
systemd-cryptsetup to unlock our drive during boot, we will need to install everything it needs to talk to a card into initramfs.
Installing dependencies #
During my experiments I have found that the following packages are required, at least for Nitrokey Storage:
If you are using a different token, you may need some other drivers, or adjust opensc configuration.
On Gentoo, these packages need to be installed with specific use flags, see the ebuild for details.
Configuring initramfs creation #
As mentioned in the overview, we will need to include
/etc/crypttab in the initramfs. On dracut it can be done through the following configuration:
~# cat /etc/dracut.conf.d/cryptsetup.conf add_dracut_modules+=" crypt " install_items+=" /etc/crypttab "
(note the spaces before and after quotation marks)
man dracut.conf for more info on those configuration files.
This instructs dracut to include
/etc/crypttab as a file in the initramfs and triggers
module-install.sh from dracut crypt module. The crypt module (
/usr/lib/dracut/modules.d/90crypt) examines the system and includes
systemd-cryptsetup and related generators in the initramfs.
If using the dracut module created for this article, the
add_dracut_modules line would look like so:
add_dracut_modules+=" crypt pcscd-cryptsetup "
Including dependencies in initramfs #
In order to function properly, certain files provided by packages from “Installing dependencies” section need to be present in initramfs. This list is maintained in the dracut module, the files are installed by calls to
Allowing pcscd to start when requested by cryptsetup #
By default pcscd is socket-activated. Pcscd socket is wanted by
sockets.target, which causes it to start after
cryptsetup.target. When installing the
pcscd.socket into initramfs, we need to configure these units to allow starting without waiting
sockets.target, otherwise they will be put into systemd job queue and not start when
systemd-cryptsetup requests them.
To do that, we can leverage systemd’s drop-in files support.
For both socket and service, we will need to override the
DefaultDependencies setting and declare that the socket and service are wanted by
cryptsetup-pre.target is a special target that can be used to launch services before cryptsetup will need them.
The configuration drop-ins look like this:
[Unit] DefaultDependencies=no [Install] WantedBy=cryptsetup-pre.target
Final step #
The only remaining thing is to rebuild initramfs. After that is done, reboot, insert the token and wait for the prompt from cryptsetup. The message “Started PC/SC Smart Card Daemon” should appear right prior to the passphrase prompt.
This is a collection of notes and hints that I wrote down when configuring this setup. The most common error is that systemd-cryptsetup does not prompt for the passphrase. If using dracut it will result in emergency shell being offered after initqueue times out.
- If you want to continue the boot, you can unlock the encrypted device by hand. To do that, run
systemctl statusand check what
systemd-cryptsetup@service is trying to execute. You can manually call
/lib/systemd/systemd-cryptsetup attach $name /dev/disk/by-uuid/$UUIDto unlock the device
- You can try starting pcscd manually by calling
systemctl start pcscd. If this command hangs – probably something is wrong with the drop-in files. Check the systemd job queue to see what pcscd is waiting for (
systemctl list-jobs --after).
- If pcscd is running, you can use
opensc-toolto check if the token is visible at all. Both of these can be installed by
_debugfunction in the dracut module.
opensc-tool -lwill show if the system can see the token
systemd-cryptenroll --pkcs11-token=listwill tell if
systemdis capable of seeing the token
- Dracut has a module called
rescuewhich includes some extremely useful tools such as a text editor