Full disk encryption secure boot
This material is work-in-progress ... Do not follow instructions here until this notice is removed. |
This guide is to explain step by step how to setup Alpine Linux with Full Disk Encryption using LUKS2, /boot & / together on the same partition, encrypted swap for hibernation on a nvme drive, with UEFI & Secure Boot. The goal of this guide is to follow the KISS principle, lvm can be added, another file system can be used, multiple partitions for /home; /var/log etc.. can also be added, if running everything in one partition is not meeting your requirements.
Sequence of Events
- Installing packages
- Partitioning the disk
- Configuring LUKS
- Mounting points and File System
- Installing Alpine
- mkinitfs settings & modules
- Grub settings
- Configuring Secure Boot
Installing packages
To facilitate the partitioning we will use gdisk :
# apk add lsblk gptfdisk
For encryption, we will use cryptsetup :
# apk add cryptsetup
For using and managing UEFI, multiple packages are needed :
# apk add efibootmgr e2fsprogs grub grub-efi
Partitioning the disk
Let's assume the disk is /dev/nvme0n1 and no partition is present, we will create three partitions :
- one for UEFI
- one for /
- one for swap (hibernation)
# gdisk /dev/nvme0n1 GPT fdisk (gdisk) version 1.0.9.1 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Command (? for help): d No partitions Command (? for help): n Partition number (1-128, default 1): First sector (2048-1000215182, default = 2048) or {+-}size{KMGTP}: Last sector (2048-1000215182, default = 1000214527) or {+-}size{KMGTP}: 512M Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): ef00 Changed type of partition to 'EFI system partition' Command (? for help): n Partition number (2-128, default 2): First sector (1048577-1000215182, default = 1050624) or {+-}size{KMGTP}: Last sector (1050624-1000215182, default = 1000214527) or {+-}size{KMGTP}: 16G Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): 8200 Changed type of partition to 'Linux swap' Command (? for help): n Partition number (3-128, default 3): First sector (1048577-1000215182, default = 33556480) or {+-}size{KMGTP}: Last sector (33556480-1000215182, default = 1000214527) or {+-}size{KMGTP}: Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): 8309 Changed type of partition to 'Linux LUKS' Command (? for help): w Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): Y OK; writing new GUID partition table (GPT) to /dev/nvme0n1. The operation has completed successfully.
Configuring LUKS
# cryptsetup -v -c aes-xts-plain64 -s 512 --hash sha512 --pbkdf pbkdf2 --iter-time 5000 --use-random luksFormat /dev/nvme0n1p2 WARNING! ======== This will overwrite data on /dev/nvme0n1p2 irrevocably. Are you sure? (Type 'yes' in capital letters): YES Enter passphrase for /dev/nvme0n1p2: Verify passphrase: Key slot 0 created. Command successful. # cryptsetup -v -c aes-xts-plain64 -s 512 --hash sha512 --pbkdf pbkdf2 --iter-time 5000 --use-random luksFormat /dev/nvme0n1p3 WARNING! ======== This will overwrite data on /dev/nvme0n1p3 irrevocably. Are you sure? (Type 'yes' in capital letters): YES Enter passphrase for /dev/nvme0n1p3: Verify passphrase: Key slot 0 created. Command successful.
Mounting points and File System
Open the LUKS partitiond we just created:
# cryptsetup luksOpen /dev/nvme0n1p2 nvme0n1p2-crypt # cryptsetup luksOpen /dev/nvme0n1p3 nvme0n1p3-crypt
Create vfat file system for UEFI partition:
# mkfs.vfat /dev/nvme0n1p1
Create ext4 file system for swap partition:
# mkfs.ext4 /dev/mapper/nvme0n1p2-crypt
Create ext4 file system for / partition:
# mkfs.ext4 /dev/mapper/nvme0n1p3-crypt
Create mounting points and mount partitions : Mount / partition to /mnt :
# mount -t ext4 /dev/mapper/nvme0n1p3-crypt /mnt
Create /boot/efi:
# mkdir /mnt/boot/efi -p
Mount UEFI partition to /mnt/boot/efi :
# mount -t vfat /dev/nvme0n1p1 /mnt/boot/efi
Activate SWAP:
# mkswap /dev/mapper/nvme0n1p2-crypt # swapon /dev/mapper/nvme0n1p2-crypt
Check partition scheme:
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS nvme0n1 259:0 0 476.9G 0 disk ├─nvme0n1p1 259:1 0 511M 0 part /mnt/boot/efi ├─nvme0n1p2 259:2 0 15.5G 0 part │ └─nvme0n1p2-crypt 253:0 0 15.5G 0 crypt [SWAP] └─nvme0n1p3 259:3 0 460.9G 0 part └─nvme0n1p3-crypt 253:1 0 460.9G 0 crypt /mnt
Installing Alpine
# setup-disk -m sys /mnt/
mkinitfs settings & modules
Edit the /mnt/etc/mkinitfs/mkinitfs.conf file and append the cryptsetup module to the features parameter (keymap only needed if QWERTY is not used):
features="...keymap cryptsetup cryptkey"
Regenerate the initram:
# mkinitfs -c /mnt/etc/mkinitfs/mkinitfs.conf -b /mnt/ $(ls /mnt/lib/modules/)
Grub settings
Create a crypto_keyfile.bin to avoid typing the passphrase twice during the boot process (one for Grub partition, one for Alpine partition):
# touch /mnt/crypto_keyfile.bin # chmod 600 /mnt/crypto_keyfile.bin # dd bs=512 count=4 if=/dev/urandom of=/mnt/crypto_keyfile.bin # cryptsetup luksAddKey /dev/nvme0n1p3 /mnt/crypto_keyfile.bin
Then, let's mount and chroot to our fresh installation:
# mount -t proc /proc /mnt/proc # mount --rbind /dev /mnt/dev # mount --make-rslave /mnt/dev # mount --rbind /sys /mnt/sys # chroot /mnt
Let's show the UUID of our partition scheme:
# lsblk -f
Edit /etc/default/grub and add a new line starting with GRUB_CMDLINE_LINUX parameter, replacing <UUID> with the UUID of the encrypted partition (in this case /dev/nvme0n1p3) and adding a new GRUB_PRELOAD_MODULES line like this:
GRUB_CMDLINE_LINUX="cryptroot=UUID=<UUID> cryptdm=nvme0n1p3-crypt cryptkey" GRUB_PRELOAD_MODULES="luks cryptodisk part_gpt"
Create a /root/grub-pre.cfg and replace <UUID_WITHOUT_HYPHENS> with your encrypted root partition UUID (here /dev/nvme0n1p3) without hyphens
set crypto_uuid=<UUID_WITHOUT_HYPHENS> cryptomount -u $crypto_uuid set root=crypto0 set prefix=($root)/boot/grub insmod normal normal
Configuring Secure Boot
# apk add efi-mkkeys efibootmgr sbsigntool # efi-mkkeys -s "Your Name" -o /etc/uefi-keys
Re-install Grub:
# grub-mkimage -p /boot/grub -O x86_64-efi -c /root/grub-pre.cfg -o /tmp/grubx64.efi luks2 part_gpt cryptodisk ext2 gcry_rijndael pbkdf2 gcry_sha512 # install -v /tmp/grubx64.efi /boot/efi/EFI/AlpineLinuxSecureBoot/ # sed -i 's/SecureBoot/SecureB00t/' /boot/efi/EFI/AlpineLinuxSecureBoot/grubx64.efi # cd /boot/efi/EFI/AlpineLinuxSecureBoot/ # sbsign --key /etc/uefi-keys/db.key --cert /etc/uefi-keys/db.crt --output grubx64.efi.signed grubx64.efi # grub-mkconfig -o /boot/grub/grub.cfg # efibootmgr --disk /dev/nvme0n1p1 --part 1 --create --label 'Alpine Linux Secure Boot Signed' --load /EFI/AlpineLinuxSecureBoot/grubx64.efi.signed --verbose
To check that your .efi is signed :
# sbverify --cert /etc/uefi-keys/db.crt /boot/efi/EFI/AlpineLinuxSecureBoot/grubx64.efi.signed Signature verification OK sbverify --list /boot/efi/EFI/AlpineLinuxSecureBoot/grubx64.efi.signed signature 1 image signature issuers: - /CN="Your Name" (db) image signature certificates: - subject: /CN="Your Name" (db) issuer: /CN="Your Name" (db)
Reboot
Import keys to UEFI
Copy db.auth, KEK.auth and PK.auth files from /etc/uefi-keys to a FAT formatted file system. This is just an example from an XPS laptop, each UEFI is unique.
- Go to Boot Configuration > Secure Boot
- Change Enable Secure Boot to ON
- Change Secure Boot Mode to Deployed Mode
- Change Enable Custom Mode to ON
- Go to Custom Mode Key Management
- Reset All Keys
- Select Key Database select db > Replace from file > select your Flash Drive > select db.auth
- Select Key Database select KEK > Replace from file > select your Flash Drive > select KEK.auth
- Select Key Database select PK > Replace from file > select your Flash Drive > select PK.auth
- APPLY CHANGES > EXIT
Check Secure Boot State:
# apk add mokutil # mokutil --sb-state SecureBoot enabled
Congrats!