User:Cvlc/Drafts/Dm-crypt

From ArchWiki

LUKS on a partition with TPM2, Secure Boot, and PCR policies

This example is similar to #LUKS on a partition, but integrates the use of Secure Boot and a Trusted Platform Module (TPM), enhancing the overall security of the boot process. With this setup, the root volume can only be decrypted when booting a known Unified kernel image for which a signature can be provided. See systemd-cryptenroll(1) § TPM2_PCRs_and_policies, [1] and [2].

In this configuration, only the EFI system partition remains unencrypted, housing a unified kernel image and systemd-boot—both signed for use with Secure Boot. The TPM plays a crucial role by monitoring the boot phases. This approach is akin to BitLocker on Windows or FileVault on macOS. A recovery-key will also be created to make sure the data remains accessible in case of a problem with the TPM unlocking mechanism. The following tools will be needed:

Warning: Implementing this method on your root volume means your computer will automatically unlock at boot without requiring an encryption password under specific conditions. However, be cautious of the following risks:
  • On systems with multiple users, without additional protection, data is accessible between users.
  • Weak user passwords increase the risk of data exposure in case of theft.
  • The setup is susceptible to cold boot attacks, where an attacker, even after a prolonged power-off period, could exploit the automatic loading of the TPM key upon turning on the computer. This is particularly relevant for high-value targets.

In this example, partitions are created respecting systemd#GPT partition automounting, there is no need for an fstab or crypttab file.

+-----------------------+------------------------------------------------+
| ESP                   | Root partition                                 |
| unencrypted           | encrypted                                      |
|                       |                                                |
| /efi                  | /                                              |
|                       |                                                |
|                       | /dev/mapper/root                               |
|                       |------------------------------------------------|
| /dev/sda1             | /dev/sda2                                      |
+-----------------------+------------------------------------------------+

Follow the Installation guide up to step Installation guide#Partition the disks.

Preparing the disk

Prior to creating any partitions, you should inform yourself about the importance and methods to securely erase the disk, described in dm-crypt/Drive preparation.

Partition the drive with the GUID Partition Table (GPT). Then create the needed partitions.

Create an EFI system partition (/dev/sda1 in this example) with an appropriate size. It will later be mounted at /efi.

In the remaining space on the drive create a root partition (/dev/sda2 in this example) which will be encrypted and later mounted to /. Set its partition type GUID to 4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709 ("Linux root (x86-64)" in fdisk, 8304 in gdisk).

Preparing the root partition

The following commands create and mount the encrypted root partition. See dm-crypt/Encrypting a non-root file system#Partition (which, despite the title, can be applied to root partitions, as long as mkinitcpio and the boot loader are correctly configured).

If you want to use particular non-default encryption options (e.g. cipher, key length), or if you don't want to use TPM based decryption, see the encryption options before executing the first command.

Create the luks volume (you can simply use a blank password, as it will be wiped later) and mount it:

# cryptsetup luksFormat /dev/sda2
# cryptsetup open /dev/sda2 root
# mkfs.ext4 /dev/mapper/root
# mount /dev/mapper/root /mnt

Preparing the EFI system partition

Format the newly created EFI system partition as instructed in EFI system partition#Format the partition and mount it afterwards.

# mount --mkdir /dev/sda1 /mnt/efi

Continue the installation process until Installation guide#Install essential packages

Installing essential packages

Read the information in this step carefully, and append the following to your final pacstrap command:

# pacstrap -K /mnt base ..... systemd-ukify sbsigntools 

Continue the installation process until Installation guide#Initramfs, but skip Installation guide#Fstab.

Configuring the initramfs

To build a working systemd based initramfs, modify the HOOKS= line in mkinitcpio.conf as follows:

HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)

Also modify MODULES= if required.

Installing the boot loader

Install systemd-boot with:

# bootctl install

The generated Unified kernel image will be automatically recognized and does not need an entry in /efi/loader/entries/.

See systemd-boot#Updating the UEFI boot manager and systemd-boot#Loader configuration for further configuration.

Configuring the UKI

Next, we need three different configuration files for the UKI:

  • Configure any required kernel parameters in /etc/kernel/cmdline, eg:
/etc/kernel/cmdline
quiet bgrt_disable
Note: This setup does not require any root= parameter, nor any setting related to decryption of the Luks volume.
/etc/kernel/install.conf
layout=uki
  • Finally, configure the UKI:
/etc/kernel/uki.conf
[UKI]
SecureBootPrivateKey=/etc/kernel/secure-boot.key
SecureBootCertificate=/etc/kernel/secure-boot.cert
Splash=/usr/share/systemd/bootctl/splash-arch.bmp

[PCRSignature:system]
PCRPrivateKey=/etc/kernel/tpm2-pcr-key.pem
PCRPublicKey=/etc/systemd/tpm2-pcr-public-key.pem
Note: Splash= is optional. Do not modify the path to the PCRPublicKey, or systemd-cryptenroll(1) will fail to pick it up automatically.

Generate the necessary keys for Secure Boot and PCR policy signing:

# ukify genkey --config=/etc/kernel/uki.conf

Next, generate the UKI:

# kernel-install add-all
==> Starting build: '6.6.22-1-lts'
  -> Running build hook: [systemd]
  -> Running build hook: [autodetect]
  -> Running build hook: [microcode]
  -> Running build hook: [modconf]
  -> Running build hook: [kms]
  -> Running build hook: [keyboard]
  -> Running build hook: [block]
  -> Running build hook: [sd-vconsole]
  -> Running build hook: [sd-encrypt]
==> Generating module dependencies
==> Creating zstd-compressed initcpio image: '/tmp/kernel-install.staging.HGMao7/initrd'
  -> Early uncompressed CPIO image generation successful
==> Initcpio image generation successful
Using config file: /etc/kernel/uki.conf
+ sbverify --list /lib/modules/6.6.22-1-lts/vmlinuz
No signature table present
+ /usr/lib/systemd/systemd-measure sign --linux=/lib/modules/6.6.22-1-lts/vmlinuz --osrel=/etc/os-release --cmdline=/tmp/tmp.cmdliney7tgauck --uname=/tmp/tmp.unamewizaiscx --pcrpkey=/etc/systemd/tpm2-pcr-public-key.pem --initrd=/tmp/kernel-install.staging.HGMao7/initrd --sbat=/tmp/tmp.sbat3apz9lp1 --private-key=/etc/kernel/tpm2-pcr-key.pem --public-key=/etc/systemd/tpm2-pcr-public-key.pem
+ sbsign --key /etc/kernel/secure-boot.key --cert /etc/kernel/secure-boot.cert /tmp/uki9or_r7sx --output /tmp/kernel-install.staging.HGMao7/uki.efi
Signing Unsigned original image
Wrote signed /tmp/kernel-install.staging.HGMao7/uki.efi

If all went well, remove the leftover initramfs and vmlinuz files from /boot. They were automatically generated when pacstrap was run and are not needed any more.

Enroll the TPM PCR Policy in the Luks volume

The following commands will remove the empty passphrase created during the LUKS format process, create a key bound to the TPM PCR Policy, and create a recovery key to be used in case of any problems. The TPM will automatically release the key as long as the boot chain is not tampered with. See systemd-cryptenroll#Trusted Platform Module and systemd-cryptenroll(1).

# systemd-cryptenroll /dev/sda2 --recovery-key
# systemd-cryptenroll /dev/sda2 --wipe-slot=empty --tpm2-device=auto

The second command automatically picks up the previously created /etc/systemd/tp2-pcr-public-key, in order to bind the Luks encryption to the PCR policy instead of the literal PCR values.

Make sure you did not forget to set a root password, see Installation guide#Reboot to finish the installation.

Follow the steps in Kernel-install#Pacman hook to disable the mkinitcpio hooks, and automatically run kernel-install upon subsequent updates.

Secure Boot

The UKI is already automatically signed for Secure Boot. You also need to sign systemd-boot, see Systemd-boot#Signing for Secure Boot.

For a quick and easy way to implement Secure Boot, see Unified Extensible Firmware Interface/Secure Boot#Assisted process with sbctl.