Linux with TrustedGRUB2

This appendix details the setup used for the analysis of TrustedGRUB2. The hardware configuration is identical to that described in Test system. TrustedGRUB2 is not utilized as the default bootloader in any Linux distribution. Furthermore, it is absent from the standard package repositories typically associated with Linux systems. Consequently, the choice of distribution was unrestricted and Arch Linux was selected for this study.

Unlike widely-used Linux distributions such as Ubuntu, Arch Linux does not provide a standard installation assistant. The installation is entirely manual, carried out by executing commands within a shell provided by the Arch live environment. This environment contains all the necessary tools to perform a complete Arch installation. While this process requires advanced technical knowledge, for instance, on system partitioning, it offers significant advantages, such as the ease of repeating the installation and creating a system that contains only the desired programs.

Arch Linux setup script

Listing 33 shows the complete installation script that was created as part of this work for the analysis of TrustedGRUB2. The exact version details of Arch Linux, under which the script was developed and tested, can be found in Listing 32. This also includes further versions of installed programs, such as gcc or make. Arch uses a rolling release model, which makes it more challenging to set up a system with matching versions at a later time. As will be evident throughout this chapter, this is desirable in order to avoid newly introduced compiler warnings when compiling TrustedGRUB2. For active open-source projects, this is not a problem, as patches for such issues are quickly made available.

Listing 32 Arch Linux Versions
 1 $ uname -a
 2 Linux arch-master 5.3.5-arch1-1-ARCH #1 SMP PREEMPT Mon Oct 7 19:03:00 UTC 2019 x86_64 GNU/Linux
 3
 4 $ gcc --version
 5 gcc (GCC) 9.2.0
 6
 7 $ make --version
 8 GNU Make 4.2.1
 9
10 $ python --version
11 Python 3.7.4

The remainder of this chapter focuses on explaining the script from Listing 33 and the setup of TrustedGRUB2. Any lines that are not specifically discussed here are directly taken from the Arch installation [70] guide and can be referenced there if needed.

Listing 33 Arch Linux Setup Script
 1 #!/bin/sh
 2
 3 if [[ $# -eq 0 ]]; then
 4    timedatectl set-ntp true
 5
 6    # disk setup
 7    parted -s -a optimal -- /dev/sda \
 8        mklabel msdos \
 9        unit MiB \
10        mkpart primary ext4 1 101 \
11        mkpart primary ext4 101 100% \
12        toggle 1 boot
13
14    # full disk encryption
15    cryptsetup -y -v luksFormat /dev/sda2
16    cryptsetup open /dev/sda2 cryptroot
17
18    mkfs.ext4 /dev/sda1
19    mkfs.ext4 /dev/mapper/cryptroot
20
21    mount /dev/mapper/cryptroot /mnt
22    mkdir /mnt/boot
23    mount /dev/sda1 /mnt/boot
24
25    # installation
26    TGRUB_PACKAGES='git autogen autoconf automake bison flex python gcc make'
27    pacstrap /mnt linux base grub iputils openssh vim dhclient cryptsetup $TGRUB_PACKAGES
28    genfstab -U /mnt >> /mnt/etc/fstab
29
30    SCRIPTNAME=$(basename $0)
31    cp $0 /mnt/
32    arch-chroot /mnt /$SCRIPTNAME 1
33    rm /mnt/$SCRIPTNAME
34 else
35     # timezone
36     ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
37     hwclock --systohc
38
39     # localization
40     sed -i 's/#en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen
41     locale-gen
42     echo 'LANG=en_US.UTF-8' > /etc/locale.conf
43     echo 'KEYMAP=de' > /etc/vconsole.conf
44
45     # network configuration
46     HOSTNAMEFILE=/etc/hostname
47     HOSTSFILE=/etc/hosts
48     HOSTNAME='arch-master'
49     echo "$HOSTNAME" > $HOSTNAMEFILE
50     echo "127.0.0.1        localhost" >> $HOSTSFILE
51     echo "::1              localhost" >> $HOSTSFILE
52     echo "127.0.0.1        $HOSTNAME.localdomain $HOSTNAME" >> $HOSTSFILE
53
54     # prepare boot for full disk encryption
55     sed -i -E 's/^HOOKS=\([a-z ]+\)$/HOOKS=(base udev autodetect keyboard keymap consolefont modconf block encrypt filesystems fsck)/' /etc/mkinitcpio.conf
56     mkinitcpio -P
57     CDEVUUID=$(blkid -o value /dev/sda2 | head -n 1)
58     sed -i -E "s/^GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"cryptdevice=UUID=$CDEVUUID:cryptroot\"/" /etc/default/grub
59
60     # grub setup
61     grub-install --target=i386-pc /dev/sda
62     grub-mkconfig -o /boot/grub/grub.cfg
63
64     # password
65     passwd
66 fi

Partitionierung und FDE

Lines 7 to 12 format and partition the disk. The disk is divided into Partition 1 with 100 MiB and Partition 2, which follows Partition 1 and occupies the remaining disk space. Additionally, the boot flag is enabled for Partition 1. A separate home or swap partition is deliberately omitted to avoid added complexity. This is the simplest possible partitioning scheme for a system with full disk encryption (FDE), where Partition 1 remains unencrypted and encryption is activated for Partition 2.

The encryption takes place in lines 15 and 16. There, cryptsetup, the Linux userspace tool for managing full disk encryption (FDE), is used to create a virtual block device, which transparently handles encryption and decryption. In the background, dm-crypt is employed, utilizing the device-mapper framework of the Linux kernel. The encryption keys are persisted on the disk through LUKS [21]. After entering the passphrase twice — once to create and once to open the encrypted volume — a virtual block device is created at /dev/mapper/cryptroot, which handles the encryption and decryption process and is used for further work.

Just like Partition 1, the encrypted partition is initialized with a file system. In both cases, ext4 is used, and the initialization is carried out in lines 18 and the following. After this step, Partition 2 is mounted at /mnt and Partition 1 at /mnt/boot. With the execution of line 23, the preparation of the disk is complete, and the installation of the operating system can now begin.

OS packages

In line 27, the pacstrap command is used to install the operating system and all necessary software components. The package linux installs the Linux kernel and the required modules. Along with the package base, which installs the init system systemd and other programs such as bash, this forms the minimal possible Arch Linux setup.

The grub package is used to install the bootloader of the same name. However, this does not yet include TrustedGRUB2. TrustedGRUB2 is only created and installed later, after the system installation is complete. The package includes grub-install, a program that will be used to complete the bootloader installation at a later stage.

The network configuration is handled by the iputils and dhclient packages. The openssh package allows for file transfers via scp, enabling the later availability of the patch file for TrustedGRUB2 on the system. vim is a text editor and is only necessary if further changes to text files are required. These tools do not directly relate to TrustedGRUB and are only intended to provide a minimal operating system for compiling the bootloader.

The packages summarized in the shell variable TGRUB_PACKAGES are necessary for compiling TrustedGRUB2. autogen, autoconf, automake, gcc, bison, and flex are explicitly mentioned in the README as prerequisites for building TrustedGRUB2. Additionally, it was found that python and make are also required. git, of course, is not needed for the compilation process itself but is used to clone the repository.

In the /mnt directory, all necessary files for a functional Linux system are placed. The arch-chroot command is used to set /mnt as the new root filesystem and execute the setup script with the parameter 1, triggering the else branch. This simplifies the setup by using a single script. The script is copied to the new root directory in line 31.

The execution starts in line 34, configuring the newly installed system rather than the live environment. Unlike the Arch installation guide, only the commands needed to enable the system to boot with an encrypted root partition are included.

Grub und initramfs

Lines 55 and 56 extend the initramfs to include the modules required by the kernel for booting with an encrypted root partition. The keyboard and keymap modules allow password entry using a German keyboard layout, while the ‘encrypt’ module is necessary for the kernel to handle encrypted partitions. After modifying the configuration file, the command mkinitcpio is used to generate a new initramfs image. This image is subsequently loaded into memory by the bootloader, in this case, GRUB, and passed to the kernel.

After the necessary tools for installing GRUB have been added to the system during package installation, the bootloader must be installed on the disk by executing grub-install, as performed in line 61. Line 62 generates the configuration file required by GRUB. Subsequently, the password for the root account is set. Once these commands in the else branch have been completed, the process concludes, triggering the execution of the final commands in the if branch. These include the removal of the setup script, signaling the completion of the installation. After a reboot, the system is ready for login with the root account, and the process of compiling TrustedGRUB2 can begin.

Setting up TrustedGRUB2

In order to successfully compile TrustedGRUB2 on the freshly installed system, several patches must be applied after cloning the repository [71]. This is necessary because new warning messages were introduced in GCC versions 8 and 9. The latest commit in the TrustedGRUB2 repository (e656aaa) was made on June 8, 2017, suggesting that the project was last compiled with GCC 7, as GCC 8.1 was released in May 2018.

Listing 34 presents all the applied patches. The first patch originates from a pull request on GitHub that was not merged into the master branch. Since this work only requires a functional system with TrustedGRUB2 for analysis, the patch was not further investigated, although it suggests an unused variable in the code. All subsequent patches are from the GRUB2 GitHub [72] repository and address issues introduced by the newer versions of GCC. The file fix_build_with_gcc9.patch is provided with this work, consolidating all changes into a single patch. These changes can be applied to the checked-out version using the git apply command.

Listing 34 Patches for TrustedGRUB2
 1 # Juni 2017
 2 de21808 disable unused-value warning
 3
 4 # März  2018
 5 563b1da Fix packed-not-aligned error on GCC 8
 6
 7 # April 2019
 8 4dd4cee efi: Fix gcc9 error -Waddress-of-packed-member
 9 4868e17 chainloader: Fix gcc9 error -Waddress-of-packed-member
10 85e08e1 usbtest: Fix gcc9 error -Waddress-of-packed-member
11 0b1bf39 acpi: Fix gcc9 error -Waddress-of-packed-member
12 6210240 hfsplus: Fix gcc9 error -Waddress-of-packed-member
13 0e49748 hfs: Fix gcc9 error -Waddress-of-packed-member
14 4f4128d jfs: Fix gcc9 error -Waddress-of-packed-member
15 7ea474c cpio: Fix gcc9 error -Waddress-of-packed-member

The compilation process follows the four commands outlined in the README. Afterward, the TrustedGRUB2 binaries are located in the directory specified by the prefix during configuration. Running grub-install from the sbin subdirectory installs TrustedGRUB2 on the hard drive. The exact commands are provided in the README. Following installation, a reboot should reflect the changes in the PCR (Platform Configuration Registers)

Listing 35 displays the contents of the PCR registers at the top, showing the values after a boot without TrustedGRUB2, and at the bottom, the values after booting with TrustedGRUB2. PCR registers 08 to 11 show their initial values at the top, but not at the bottom. This indicates that no extend operation was called for these PCR registers during the boot without TrustedGRUB2, but it was triggered during the boot with TrustedGRUB2. This outcome was expected and confirms that TrustedGRUB2 is functioning as intended.

Listing 35 PCR values Grub vs TrustedGrub
 1 # regular Grub
 2 PCR-06: EE 1B 0F 99 7D 75 17 B2 86 BC 9D 73 A4 CF 74 2C 65 A7 69 BE
 3 PCR-07: B2 A8 3B 0E BF 2F 83 74 29 9A 5B 2B DF C3 1E A9 55 AD 72 36
 4 PCR-08: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 5 PCR-09: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 6 PCR-10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 7 PCR-11: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 8
 9 # trusted Grub
10 PCR-06: EE 1B 0F 99 7D 75 17 B2 86 BC 9D 73 A4 CF 74 2C 65 A7 69 BE
11 PCR-07: B2 A8 3B 0E BF 2F 83 74 29 9A 5B 2B DF C3 1E A9 55 AD 72 36
12 PCR-08: D3 F6 C9 85 14 27 D4 09 F4 77 F9 F4 98 DD C3 5B 3C 7A 84 E4
13 PCR-09: F6 46 86 9A 9E B6 19 CF E1 63 40 1B B5 DA 55 6B 6A 0C 0A F5
14 PCR-10: C1 28 20 C2 A8 58 03 09 0E 4A C9 BB 23 D1 7F 53 B8 E4 D3 03
15 PCR-11: 94 B6 B9 E4 0E 8A 22 1E D0 23 CB CB B3 1F CF 2A 85 38 BF 30