This guide provides amendments to the original scripts by Paddy Landau, so as to provide the option for using BTRFS as the root file system. These changes have been collated into a modified version. Please note, the modified scripts still depend on the ancillary scripts provided with the original script.
In addition to the tweaks to support BTRFS, this guide also includes some tweaks for issues related to slow boot times and partitioning.
In particular I will cover the rough steps taken to:
- allow better shrinking of existing Windows partitions
- fix boot bug due to Secure Boot and GRUB modules
- tweak BIOS sleep state to support hybrid-suspend
- tweak creation scripts to support BRTFS
- change LUKS keys to reduce boot time (warning)
HERE BE DRAGONS please take anything said below with a pinch of salt and follow at your own risk. I have not double checked all the details and these amendments, to the original guide, have not been battle tested on other system configurations. Additionally, please first read: Manual Full System Encryption by Paddy Landau.
Given a laptop that is pre-installed with Windows, one does not necessarily want to format the whole drive. So shrinking the Windows C: is a good option. However, this will generally cause one to bump into the problem of unmovable files that prevents one from shrinking the partition as much as is desired. The following guide:
- “How to shrink a disk volume beyond the point where any unmovable files are located by Mihai Neacsu”
provides a concise list of temporary tweaks that will make it possible to shrink the partition to closer to the actual usage limits. It does this by:
- removing hiberfil.sys
- removing pagefile.sys
- removing swapfile.sys
- disabling rollback checkpoints
- disabling diagnostic memory dumps
All of these can be re-enabled again once the partition has been resized.
While Secure Boot may have its security benefits it certainly does tend to cause some problems. In the case of GRUB this turned out to be a rather silent issue that causes boot up, post installation, to fail.
The problems seems to be that while there are appropriately signed versions of
GRUB, this version does not actually include all needed modules. In particular
it does not include the
luks module. To compound the problem this does not
actually display an error. Instead, GRUB simply never prompts for the LUKS
grub> lsmod eventually shows the problem because it is evident that
the luks module is missing. However executing
grub> insmod luks doesn’t help
since the signed version does not seem to allow for module loading. But, it also
simply drops through silently without displaying a failure.
In short, it is necessary to disable “Secure Boot.”
Following this the boot process will do “the right thing”™ and prompt for a password:
Attempting to decrypt master key... Enter passphrase for hd?,gpt? (...): Slot 0 opened
The Lenovo ThinkPad X1 Carbon 6th Generation that I was installing Ubuntu on, with full system encryption, still had a bug that prevented Linux from making use of the S3 sleep state.
This has been fixed in later versions of the BIOS:
Simply upgrade to a newer BIOS version and then remember to toggle the power management sleep mode from “Windows 10” to “Linux.”
Following this, you can test if the OS exposes the necessary sleep state:
pm-is-supported --suspend-hybrid && echo true
And with the BIOS update it should do the “right thing”™.
I wanted to rather use BTRFS as my main filesystem. This will enable me to create and destroy subvolumes without making using of LVM.
I originally thought it would be a simple matter of swapping out
mkfs.btrfs. But, as always, the devil is in the details.
There are two related problems that show up due to the use of subvolumes. In particular, when Ubuntu performs an installation on BTRFS it creates two “magical” subvolumes be default:
@- used as the root subvolume to be mounted on
@home- used as the “user” subvolume and mounted on
The problem is that the
encryptinstallation script is not aware of these
changes. During the script execution one of the steps is to create a
environment. For this, it simply mounts the
system partition into the
root/ (it will also optionally mount a
data partition onto
root/home/ if chosen). But this script now needs to be amended to:
/with the additional mount option
and then (even when no explicit data partition has been selected):
- explicitly mount
/homewith the mount option
For sanity sake, also double check that the final
grub.cfg includes the
command line kernel option:
With all of the above issues sorted out the system will not boot. However, the boot sequence is surprising slow. More specifically, depending on your hardware combination you might find that GRUB seems to hang for over a minute before proceeding to boot Linux.
It turns out that this is by design - sort of ;)
This is actually a side effect of LUKS key handling, and in particular PBKDF2.
As part of using a “Password Based Key Derivation Function” the password is iteratively hashed in order to improve security against brute force attacks.
Unfortunately the GRUB cryptographic routines are not optimised in the same way
cryptsetup implementations. Apparently the GRUB versions either can
not, or do not, make use of the AES instructions and other 64 Bit instructions.
As a result the GRUB implementation is easily an order of magnitude slower that
The means that when a password is validated against the key slot it takes GRUB a lot longer to first perform the necessary number of iterations.
On my machine this stretched the validate from 1-2 seconds to ~70s. Unfortunately I found this to be simply too long when booting up.
The solution is to manually reset the key and force a lower iteration count.
WARNING this will weaken the security against brute force attacks.
I tuned my LUKS unlock time down to around 10 seconds in GRUB.
Creating new keys
Note, GRUB will iterate over each key slot sequentially. As such, if you have more than one key slot, then it is useful to make sure that the keys that are going to be used by GRUB are given lower key slot indicies.
Newer versions of
cryptsetup include a function:
the default version in Ubuntu 18.04 LTS is 2.0.2 and does not yet include this
function. As such, this guide uses
luksAddKey. But, as said, it is important
that the lower iteration count key also has a lower key slow index. So we do
following (after potentially using
luksHeaderBackup first; paying attention to
warnings regarding making copies of key material):
echo Add an extra key for use when removing and adding to slot 0 echo (A lower iteration count is not needed at this point in time) echo (Provide the passphrase for the exiting slot 0) cryptsetup luksAddKey /dev/nvme0n1p? echo Now remove key slot 0 echo (This is selected based on the first matching password.) echo (So enter the original passphrase and not the value entered above, if they differ) cryptsetup luksRemoveKey /dev/nvme0n1p? echo Now re-add a key that will then fill slot 0, but with a tuned iteration count cryptsetup luksAddKey --pbkdf-force-iterations 50000 /dev/nvme0n1p?
At this point in time it is probably worth performing a simply sanity check and dump the header just to check the layout:
cryptsetup luksDump /dev/nvme0n1p?
Key Slot 0 is
ENABLED and that the
Iterations: value matches
the number provided with
--pbkdf-force-iterations value above.
Be careful not to remove the “internal” key slot set up by
encryptinstallation. This corresponds to the key material stored in
/etc/crypt.system and is used to prevent asking for the key twice by having
initramfs image use this key instead.
However, if you remove it you can break your boot sequence…
No prizes for guessing how I realised that ;)
Thanks again to Paddy Landau for the original guide and scripts. These are high quality and robust scripts, with great source code documentation.
However, if you wish to set up full disk/system encryption with the addition of BTRFS then hopefully the above details will help you on you way.