I use Kubuntu on a Librem 15 with Pureboot and on a UEFI based system. The process is mostly the same but there are a few differences related to the way the system boots.
The system installs and I use the Librem key to decrypt data. I also use the librem key for some authentication operations and am working toward never typing a password.
To get 21.04 to install successfully using LUKS for the root partition I ran the Kubuntu live environment. I updated it to get the latest bugfixes for the installer but that doesn't seem to make a difference.
sudo apt update && apt -y dist-upgrade
Then I ran the installer in kde mode and told it to NOT install the bootloader. On this system I use heads/pureboot so I don't need grub in the MBR of the drive.
ubiquity --no-bootloader kde_ui
There are bugs in the installer related to LUKs. If I choose a partition to be designated as encryption the system will not let me do anything else with it. In addition, after doing that if I click 'Back' I get an error that says something about problem creating keyfile.
To get around this issue I use what has been the standard method to install a LUKS root partition for a while now. Before partitioning I open the luks partition using the command line. I use the guid of the partition as the basis for the luks device after it is decrypted. This shows a relationship between the two.
sudo luksformat /dev/sdaX
guid=`blkid -s UUID -o value /dev/sdaX`
sudo cryptsetup luksOpen /dev/sdaX luks-$guid
I tried LVM for more flexibility and regretted this later as it makes the boot process more complicated and it broke. Ultimately, I abandoned LVM.
Unfortunately, this did not work. It fails with "The ext4 file system creation in partition #1 of Encrypted volume (xxxxxx) failed. It looks like since the installer setup the open LUKS partition as a drive and then created partitions inside of that the system doesn't know how to get to those partitions.
To get around this I will format the file system myself directly onto the luks open partition and try to have the installer just use it without formatting. This works and the install finishes.
I don't allow the installer to restart--opting instead for ' continue testing' in the live environment. There are more changes needed.
I need to modify files in the distro I just installed before it will boot properly. If it is not already mounted I mount the root partition at /target.
mount /dev/mapper/luks-$guid /target
Now I have to mount other filesystems needed for the setup and then use chroot to 'pretend' that I booted the distro. Lastly, I tell it to mount everything else.
cd /target
mount -o bind /dev dev
mount -o bind /proc proc
mount -o bind /sys sys
chroot /target
mount -a
This should have mounted the /boot partition. If not there is a bigger problem.
I need a grub.cfg for heads to find kernels to boot. Since I skipped installing it I have to generate it manually. Having mounted the system and used chroot before I can then run
grub-mkconfig -o /boot/grub/grub.cfg
After the install the initrd needs updates to allow Linux to boot and find the encrypted filesystem. Later I will add the Librem key. Since I already used chroot I will treat this as if I am in the system after it has booted. I need to know what the ID is for the root file system. Since I am still in the environment where I did the install I have the variable $guid and know that the luks device name is luks-$guid. The encrypted luks partition is /dev/sdaX.
I use blkid to get the UUID of the luks drive and echo the appropriate settings into crypttab.
echo "luks-$guid UUID=$guid none luks" >> /etc/crypttab
Next, I update the initrd files to get the encryption/decryption into the boot process. (this will also be done for me if I use apt to update the system which requires having network on and a nameserver specified in /etc/resolv.conf)
update-initramfs -u -k all
If I didn't use the same open luks device name in /etc/crypttab that was used to decrypt in the install environment the initrd updates will fail.
If I dont tear everything down the system may hang on restart.
umount -a
umount /proc
exit
cd /
umount /target
lvchange -an vg_kubuntu
cryptsetup luksClose /dev/mapper/luks-$guid
I now restart the system to make sure the boot process works. Once Kubuntu has booted I use the passphrase to decrypt root.
The next setup is to configure boot to use the smartcard instead of a passphrase. I have tried to combine this into the previous steps but not been able to make it work.
First, add smartcard utilities
sudo apt install opensc scdaemon libccid pcscd pcsc-tools pinentry-tty
You can try pinentry-curses but it has lots of problems every time I try it.
I have never been able to successfully retrive a public key from the smartcard for use with gpg. The only way I can get a public key is to use one exported from gpg itself. When I setup a new system I always have to find the original public key and import it into gpg. To make this easier I also copy the public key to /boot
sudo cp pubkey.asc /boot
gpg --import /boot/pubkey.asc
gpg --card-status
Export information from the smartcard for use in boot process. Note the the email address or key identifier from the previous command output.
GPG_RECIPIENT='myemail@somedomain.foo'
gpg --export $GPG_RECIPIENT > pubring.gpg
sudo mv pubring.gpg /etc/cryptsetup-initramfs/pubring.gpg
To add the smartcard (Librem key for me) to the boot process I create a new binary data key and add it to a keyslot on the luks root device. In addition, the key is encrypted using the smartcard. The boot process also needs the encrypted luks key for unlocking the disk to be placed in /etc/cryptsetup-initramfs/cryptkey.gpg
I cannot get gpg to accept the private key on standard input which requires that it be written to disk. This may be a security risk. To mitigate I use /run/user/1000/ since it is a ramdisk and should be lost on next boot. In addition I shred the file after I am finished.
GPG_RECIPIENT='myemail@somedomain.foo'
LUKS_TARGET_DEV=/dev/sdaX
dd if=/dev/urandom of=/run/user/1000/foo bs=1 count=245
gpg --trust-model=always -o ./root_cryptkey.gpg --recipient $GPG_RECIPIENT --yes --encrypt /run/user/1000/foo
sudo cryptsetup luksAddKey "${LUKS_TARGET_DEV}" /run/user/1000/foo
#if that works shred the key
shred /run/user/1000/foo
rm -f /run/user/1000/foo
sudo cp root_cryptkey.gpg /etc/cryptsetup-initramfs/cryptkey.gpg
sudo cp root_cryptkey.gpg /boot/root_cryptkey.gpg
I don't know if this is needed but better safe than sorry until I know more
echo "CRYPTSETUP=y" > /run/user/1000/conf-hook.part
cat /etc/cryptsetup-initramfs/conf-hook /run/user/1000/conf-hook.part
sudo mv /etc/cryptsetup-initramfs/conf-hook /etc/cryptsetup-initramfs/conf-hook.orig
sudo mv /run/user/1000/conf-hook /etc/cryptsetup-initramfs/
sudo chown root:root /etc/cryptsetup-initramfs/conf-hook /etc/cryptsetup-initramfs/pubring.gpg
If this all works the keys are all in place for use in the boot process. The boot process must be modified to put everything together. 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.
sudo su
LUKS_TARGET_DEV=/dev/sdaX
guid=`blkid -s UUID -o value ${LUKS_TARGET_DEV}`
LUKS_DEV=luks-$guid
sed -i 's/^/#/g' /etc/crypttab
echo "$LUKS_DEV UUID=$guid /etc/cryptsetup-initramfs/cryptkey.gpg luks,keyscript=decrypt_gnupg-sc" >> /etc/crypttab
tar -czf /boot/initrd.bak.tar /boot/initrd*
update-initramfs -u -k all
Since grub.cfg is used during boot I remove the splash screen because with it I can't see the prompt for pin entry to decrypt.
/etc/default/grub: GRUB_CMDLINE_LINUX_DEFAULT="quiet"
update grub for all settings just made
update-grub
If the boot up fails, you may need to run a rescue image such as the kubuntu installer environment. From there try to use the smart card to access the LUKS drive. Run konsole and mount the boot partition
sudo su
guid=`blkid -s UUID -o value /dev/sdaX`
echo $guid
mkdir /mnt/boot
mount /dev/sdaX /mnt/boot
apt install opensc scdaemon
gpg --import /mnt/boot/pubkey.asc
gpg --decrypt /mnt/boot/root_cryptkey.gpg | cryptsetup -q --key-file=- luksOpen /dev/disk/by-uuid/$guid luks-$guid
If this does not work you need to figure out what went wrong. Try regenerating the key and replacing on the LUKS container.
Once you can use cryptkey.gpg to open the LUKS partition you can mount root and try resetting the boot process. You may have to run it a few times before everything is put into the proper places. Pay close attention to the grub settings.
heads will prompt to re-sign boot files which is good. The Linux/Kubuntu boot process should ask for the PIN that leads to decrypting the hard disk rather than asking for the passphrase.