Encrypted Boot

My Linux laptop uses full disk encryption which makes the boot process slightly more complicated.

Disk Layout

The partion table:

/dev/nvme0n1

Device           Size  Type						Mount
/dev/nvme0n1p1   512M  EFI System				/boot/efi
/dev/nvme0n1p2   732M  Linux filesystem         /boot
/dev/nvme0n1p3    75G  Linux filesystem (LUKS)	LUKS ([SWAP] and /)
/dev/nvme0n1p4   400G  Unknown (LUKS)			Steves Data

The disk layout:

nvme0n1
│                                                                             
├─nvme0n1p1
│    vfat   FAT32       44BA-16B5                                  /boot/efi
├─nvme0n1p2
│    ext4   1.0         5e7309a6-6f5b-44e3-aff7-e92b969bdb97       /boot
├─nvme0n1p3
│    crypto 2           b6a7071a-e553-4e95-9544-9dc9ddcfed61                  
│ └─nvme0n1p3_crypt
│    LVM2_m LVM2        T25pQf-qlNw-pwNV-5dvg-xOTO-KoKG-tW3CjD                
│   ├─vgubuntu--budgie-swap_1
│   │  swap   1           b02b828e-f0bf-4ecb-910a-b88392056049     [SWAP]
│   └─vgubuntu--budgie-root
│      ext4   1.0         108f19e8-9b45-48b1-9eb6-d20fd8f011d4     /

The setup is as follows:

If you are using full disk encryption or encrypted root partition, a separate /boot partition is necessary. When using encryption, the boot process needs to access the necessary bootloader and kernel from an unencrypted boot partition to allow the system to access files to decrypt the encrypted partitions and start the system. This leaves the boot-loader second stage file-system unencrypted and therefore vulnerable to tampering of the GRUB configuration, Linux kernel or more likely, the initial RAM file-system (initrd.img).

However, GRUB2 is (since Jessie) able to unlock LUKS devices with its cryptomount command, which therefore enables encryption of the /boot partition as well

It is possible, in UEFI Secure Boot mode, to have every stage cryptographically signed, in which case any tampering can be detected and boot aborted. But Secure Boot and Hibernate do not work because something to do with the random signing code and keys for swap decryption.

Boot Order

The UEFI-based platform (i.e. what we used to know as the BIOS, but is now called UEFI) reads the partition table on the system storage and mounts the EFI System Partition (ESP).

Turn on your computer -> UEFI (BIOS) -> EFI image (/boot/efi) -> grub -> initrd (/boot) -> LUKS decryption -> boot.

The partion table:

nvme0n1
Device           Size  Type						Mount
/dev/nvme0n1p1   512M  EFI System				/boot/efi
/dev/nvme0n1p2   732M  Linux filesystem         /boot
/dev/nvme0n1p3    75G  Linux filesystem (LUKS)	[SWAP]
/dev/nvme0n1p4   400G  Unknown (LUKS)			Steves Data

UEFI Bootloader

The UEFI-based platform reads the partition table on the system storage and mounts the EFI System Partition (ESP), a VFAT partition labeled with a particular globally unique identifier (GUID). The ESP contains EFI applications such as bootloaders and utility software, stored in directories specific to software vendors. The ESP is /boot/efi/, and EFI software provided by Ubuntu is stored in /boot/efi/EFI/ubuntu/

The /boot/efi/EFI/ubuntu/ directory contains grub64.efi, a version of GRUB (Grand Unified Bootloader) compiled for the EFI firmware architecture as an EFI application. In the simplest case, the EFI boot manager selects grub.efi as the default bootloader and reads it into memory.

/boot/efi

/boot/efi/EFI:
BOOT
ubuntu

/boot/efi/EFI/BOOT:
BOOTX64.EFI
fbx64.efi
mmx64.efi

/boot/efi/EFI/ubuntu:
BOOTX64.CSV
grub.cfg
grubx64.efi
mmx64.efi
shimx64.efi

GRUB Bootloader

GRUB determines which operating system or kernel to start, loads it into memory, and transfers control of the machine to that operating system. It is the kernel’s job to finish the boot process, including decrypting any disks.

/boot

grub
initrd.img
initrd.img-5.15.0-89-generic
System.map-5.15.0-89-generic
vmlinuz
vmlinuz-5.15.0-89-generic

The partion /boot contains the grub config initramfs and vmlinuz.

Grub (/boot/grub/grub.cfg)

The config file /boot/grub/grub.cfg is automatically generated by grub-mkconfig. The utility grub-mkconfig (and update-grub) runs shell scripts in /etc/grub.d. One of them is /etc/grub.d/10_linux, which uses the shell function version_find_latest to keep iterating through the list of remaining Linux kernels, from latest to oldest. It also settings from /etc/default/grub file.

To see the menus and submenus available at boot time generated by grub-mkconfig:

awk -F\' '$1=="menuentry " || $1=="submenu " {print i++ " : " $2}; /\smenuentry / {print "\t" i-1">"j++ " : " $2};' /boot/grub/grub.cfg
 
0 : Ubuntu
1 : Advanced options for Ubuntu
	1>0 : Ubuntu, with Linux 5.15.0-89-generic
	1>1 : Ubuntu, with Linux 5.15.0-89-generic (recovery mode)
	1>2 : Ubuntu, with Linux 5.15.0-88-generic
	1>3 : Ubuntu, with Linux 5.15.0-88-generic (recovery mode)
2 : UEFI Firmware Settings

From the GRUB_DEFAULT in /etc/default/grub file we can see which version of Ubuntu will boot if none selected:

/etc/default/grub

# GRUB_DEFAULT="1>2"
GRUB_DEFAULT=0

The actual setting for each Linux option are in the /boot/grub/grub.cfg, which is built by grub-mkconfig which runs script /etc/grub.d/10_linux referencing /etc/fstab and /etc/default/grub:

/etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=/dev/mapper/vgubuntu--budgie-swa
p_1"

Here is an example for Option 0:

grep vml /boot/grub/grub.cfg

	linux	/vmlinuz-5.15.0-89-generic root=/dev/mapper/vgubuntu--budgie-root ro  quiet splash resume=/dev/mapper/vgubuntu--budgie-swap_1 $vt_handoff

But /dev/mapper/vgubuntu--budgie-root is actually encrypted inside nvme0n1p3:

lsblk --fs

nvme0n1
├─nvme0n1p3
│    crypto 2           b6a7071a-e553-4e95-9544-9dc9ddcfed61                  
│ └─nvme0n1p3_crypt
│    LVM2_m LVM2        T25pQf-qlNw-pwNV-5dvg-xOTO-KoKG-tW3CjD                
│   ├─vgubuntu--budgie-swap_1
│   │  swap   1           b02b828e-f0bf-4ecb-910a-b88392056049     [SWAP]
│   └─vgubuntu--budgie-root
│      ext4   1.0         108f19e8-9b45-48b1-9eb6-d20fd8f011d4     /

Physcial volume, volume group and logical volumes:

pvscan
  PV /dev/mapper/nvme0n1p3_crypt   VG vgubuntu-budgie   lvm2 [74.98 GiB / 0    free]
  Total: 1 [74.98 GiB] / in use: 1 [74.98 GiB] / in no VG: 0 [0   ]

vgscan
  Found volume group "vgubuntu-budgie" using metadata type lvm2

lvscan
  ACTIVE            '/dev/vgubuntu-budgie/swap_1' [9.00 GiB] inherit
  ACTIVE            '/dev/vgubuntu-budgie/root' [65.98 GiB] inherit

So at what point is decryption done?

/etc/crypttab

nvme0n1p3_crypt UUID=b6a7071a-e553-4e95-9544-9dc9ddcfed61 none luks,discard

It would seem that /etc/crypttab is copied into main/cryptroot/crypttab of initrd.img and this causes the boot kernel to prompt for a password for decryption. So /dev/mapper/vgubuntu--budgie-root is available when needed in the boot process.

Initrd/initramfs (/boot)

To see all files packaged in an the initrd (Init Ram Disk) use the following command.

lsinitramfs "/boot/initrd.img-$(uname -r)"

Note it contains Plymouth files, the graphical loader responsible for Splash screens.

To generate a new initrd use the following command:

update-initramfs -k all -c 

To update initrd after making changes use the following command:

update-initramfs -u