My LUKS2 model of smartcard integration stores the key in the luks header. Since this is different than traditional LUKS1 the methods for booting on encrypted root are different. This isn't manageable until my crypsetup plugin is done so for now I'm using the LUKS1 method for encrypting root which is to store the encrypted key in a file protected by gpg.
This assumes you have a working
working system with LUKS1 encrypted root.
If you haven't set that up yet do so before using these instructions
apt install pinentry-tty
gpg smartcard
public key for key on smartcard exported to ascii armor format or imported into gpg keyring
the email address associated with the gpg private key on the smartcard
encrypted root luks
Install prerequisites
SET variables
create binary key
add binary key to LUKS
encrypt key with gpg
copy encrypted binary key to somewhere it can be accessed on boot
set boot to use the smartcard
update grub
apt install pinentry-tty pinentry-curses opensc scdaemon libccid pcscd pcsc-tools
These instructions work with some variables. The first is the luks root device. Set it in LUKS_DEV. In this example we are using the 27th partition on the first drive => sda27. Change as needed for your system.
LUKS_TARGET_DEV=/dev/sda27
Then we get the UUID associated with this device
GUID=`sudo blkid -s UUID -o value $LUKS_TARGET_DEV`
We also need to know the luks device name for the encrypted root partition. It's the first column in /etc/crypttab for the root partition. if you have multiple encrypted partitions this command will not work and you will need to set this manually.
NAME=`awk '{print $1;}' /etc/crypttab `
create a binary key that will be added to a LUKS keyslot. I recommend putting this in a location with no hardware under it so that it minimizes risk of exposure. I've been using /run/
KEY=/run/user/1000/key
dd if=/dev/urandom of=$KEY bs=250 count=1
Now I add the new key to the encrypted LUKS root partition
sudo cryptsetup luksAddKey "${LUKS_TARGET_DEV}" ${KEY}
Encrypt key with gpg
Next, I use the gpg public key to encrypt the binary key so that it can be stored anywhere safely. If this is the first time I use this I need to import the public key associated with the smartcard.
gpg --import pubkey.asc
gpg --trust-model=always --yes --default-recipient-self --encrypt --armor $KEY
I prefer to keep the public key and the encrypted luks key in /boot since it is not encyrpted on my system. I also put the encyrpted luks key into the template for the initial ram disk that is created for booting the system.
sudo mv $KEY.asc /etc/cryptsetup-initramfs/cryptkey.gpg
sudo cp /etc/cryptsetup-initramfs/cryptkey.gpg /boot
sudo cp pubkey.asc /boot
Now all the keys are all in place for use in the boot process. Add another line to /etc/crypttab and comment out the first line. Lastly, update the ramdisk to make it all work. might want to backup the current working ramdisk too.
gpg --export > pubring.gpg
sudo mv pubring.gpg /etc/cryptsetup-initramfs/pubring.gpg
sudo sed -i "s/^$NAME/#$NAME/g" /etc/crypttab
echo "$NAME UUID=$GUID /etc/cryptsetup-initramfs/cryptkey.gpg luks,keyscript=decrypt_gnupg-sc" | sudo tee -a /etc/crypttab
sudo tar -czf /boot/initrd.bak.tar /boot/initrd*
sudo update-initramfs -u -k all
If I was using grub to boot I would update grub to remove splash screen because otherwise I can't see the prompt for pin entry.
sudo su
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"/GRUB_CMDLINE_LINUX_DEFAULT="quiet"/g' /etc/default/grub
update-grub
After a successful restart I customize the smartcard boot script to allow a fall back to passphrase.
This presumes we have a Linux system with encrypted root already booting. The /boot partition might be encrypted or not. That all depends on your setup. As long as the boot works how you like it now we dont care. If you are tying to boot with a smartcard using grub with encrypted /boot is likely not an option. In my case /boot is unencrypted and the files are signed with my smartcard so that I can detect tampering.
We also have to have cryptsetup 2.4.0 or later installed on the system. This can be tricky since most distros come with other versions at this time. Make sure the system boots after making this change and before moving to the next step.
Next the cryptsetup-smartcard and token-handle.sh scripts have to be installed. ?? does mkinitramfs copy /usr/local binaries?
I use my fork of cryptsetup to add the smartcard based binary key to the encrypted root.
cryptsetup-smartcard add /dev/sda2
If this works we can see the newly created token and new key in the header information
sudo cryptsetup luksDump /dev/sda2
Now we need to modify the boot process. This is where it gets difficult. The current smartcard boot workflow makes assumptions that are no longer valid which means we will need to build a new keyscript and/or modify the boot process to use a wrapper around cryptsetup until it supports this model natively....that is a mess and I will likely need to implement the C plugin to simplify this.
Assuming I have the C plugin working...
Boot process would start with the Linux kernel and initrd
the kernel starts mounting file systems and gets to the encrypted filesystem for / in fstab
next crypttab is checked to get the info needed to decrypt and mount /
crypttab would normally have keyscript=xyz which signifies that the key will be dumped to standard out by running the keyscript xyz
In this case cryptsetup will use the internal token to decrypt
we dont need keyscript? or we need keyscript=
cryptsetup must support the smartcard plugin
what if the smartcard is not entered? cryptsetup shoudl fall back to passphrase entry