Full disk encryption secure boot: Difference between revisions
No edit summary |
|||
(29 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
'''Disclaimer : this is not to be followed, only for testing purposes. This will be updated when GRUB 2.12 rc1 will be available for LUKSv2, GRUB and FDE to work''' | |||
This guide is to explain step by step how to setup Alpine Linux with Full Disk Encryption using LUKS2, /boot & | This guide is to explain, step-by-step, how to setup Alpine Linux with Full Disk Encryption using LUKS2, LVM (one Physical Volume Partition with three Logical Volume Partitions (/ /boot & swap) with hibernation on a NVMe drive, with UEFI & Secure Boot. This guide has been written using Alpine Linux Std 3.16.1, please adapt some commands if needed. | ||
The goal of this guide is to follow the KISS principle, | |||
The goal of this guide is to follow the KISS principle, but another file system can be used, multiple partitions for /home; /var/log etc.. can also be added, if the proposed configuration is not meeting your requirements. | |||
= Installing packages = | = Installing packages = | ||
Line 12: | Line 13: | ||
<pre># apk add cryptsetup</pre> | <pre># apk add cryptsetup</pre> | ||
For LVM: | |||
<pre># apk add | <pre># apk add lvm2</pre> | ||
For using and managing UEFI, multiple packages are needed : | For using and managing UEFI, multiple packages are needed : | ||
<pre># apk add efibootmgr e2fsprogs grub grub-efi</pre> | <pre># apk add efibootmgr e2fsprogs grub grub-efi</pre> | ||
= Preparing / overwriting the disk = | |||
<pre># apk add haveged</pre> | |||
This can take long, on my side for a 500GB nVME it tooks ~30 minutes. | |||
<pre># haveged -n 0 | dd of=/dev/nvme0n1</pre> | |||
= Partitioning the disk = | = Partitioning the disk = | ||
Let's assume the disk is /dev/nvme0n1 and no partition is present, we will create | Let's assume the disk is /dev/nvme0n1 and no partition is present, we will create two partitions : | ||
* one for UEFI | * one for UEFI | ||
* one for | * one for LVM | ||
<pre># gdisk /dev/nvme0n1 | <pre> # gdisk /dev/nvme0n1 | ||
GPT fdisk (gdisk) version 1.0.9.1 | GPT fdisk (gdisk) version 1.0.9.1 | ||
Partition table scan: | Partition table scan: | ||
MBR: | MBR: not present | ||
BSD: not present | BSD: not present | ||
APM: not present | APM: not present | ||
GPT: present | GPT: not present | ||
Creating new GPT entries in memory. | |||
Command (? for help): n | Command (? for help): n | ||
Partition number (1-128, default 1): | Partition number (1-128, default 1): | ||
First sector ( | First sector (34-1000215182, default = 2048) or {+-}size{KMGTP}: | ||
Last sector (2048-1000215182, default = 1000214527) or {+-}size{KMGTP}: 512M | Last sector (2048-1000215182, default = 1000214527) or {+-}size{KMGTP}: 512M | ||
Current type is 8300 (Linux filesystem) | Current type is 8300 (Linux filesystem) | ||
Line 51: | Line 52: | ||
Command (? for help): n | Command (? for help): n | ||
Partition number (2-128, default 2): | Partition number (2-128, default 2): | ||
First sector ( | First sector (34-1000215182, default = 1050624) or {+-}size{KMGTP}: | ||
Last sector (1050624 | Last sector (1050624-1000215182, default = 1000214527) or {+-}size{KMGTP}: | ||
Current type is 8300 (Linux filesystem) | Current type is 8300 (Linux filesystem) | ||
Hex code or GUID (L to show codes, Enter = 8300): 8309 | Hex code or GUID (L to show codes, Enter = 8300): 8309 | ||
Line 75: | Line 68: | ||
</pre> | </pre> | ||
Populate /dev with the new partitions | |||
<pre> # partprobe /dev/nvme0n1</pre> | |||
<pre># | |||
= Configuring LUKS = | = Configuring LUKS = | ||
<pre># cryptsetup -v -c aes-xts-plain64 -s 512 --hash sha512 --pbkdf pbkdf2 --iter-time | Using luks2 (unsupported by GRUB at the moment): | ||
<pre># cryptsetup -v -c aes-xts-plain64 -s 512 --hash sha512 --pbkdf pbkdf2 --iter-time 1000 --use-random luksFormat /dev/nvme0n1p2</pre> | |||
Using luks1: | |||
<pre># cryptsetup -v -c aes-xts-plain64 -s 512 --hash sha512 --iter-time 1000 --use-urandom --type luks1 luksFormat /dev/nvme0n1p2</pre> | |||
<pre> | |||
WARNING! | WARNING! | ||
======== | ======== | ||
Line 95: | Line 89: | ||
Command successful. | Command successful. | ||
# cryptsetup | # cryptsetup luksOpen /dev/nvme0n1p2 lvmcrypt | ||
</pre> | |||
= LVM : Physical & Logical Volumes creation = | |||
<pre># pvcreate /dev/mapper/lvmcrypt | |||
Physical volume "/dev/mapper/lvmcrypt" successfully created. | |||
# vgcreate vg0 /dev/mapper/lvmcrypt | |||
Volume group "vg0" successfully created | |||
# lvcreate -L 20G vg0 -n swap (I have a 16GB RAM laptop) | |||
Logical volume "swap" created. | |||
# lvcreate -l 100%FREE vg0 -n root | |||
Logical volume "root" created. | |||
</pre> | |||
To check the creation : | |||
<pre># lvscan | |||
ACTIVE '/dev/vg0/swap' [20.00 GiB] inherit | |||
ACTIVE '/dev/vg0/root' [455.92 GiB] inherit | |||
</pre> | </pre> | ||
= Mounting points and File System = | = Mounting points and File System = | ||
Create vfat file system for UEFI partition: | Create vfat file system for UEFI partition: | ||
<pre># mkfs.vfat /dev/nvme0n1p1</pre> | <pre># mkfs.vfat /dev/nvme0n1p1</pre> | ||
Create ext4 file system for | Create ext4 file system for / partition: | ||
<pre># mkfs.ext4 /dev/ | <pre># mkfs.ext4 /dev/vg0/root</pre> | ||
Activate SWAP: | |||
<pre># | <pre># mkswap /dev/vg0/swap | ||
# swapon /dev/vg0/swap | |||
</pre> | |||
Mount / partition to /mnt : | Mount / partition to /mnt : | ||
<pre># mount -t ext4 /dev/ | <pre># mount -t ext4 /dev/vg0/root /mnt</pre> | ||
Create /boot/efi: | Create /boot/efi: | ||
<pre># mkdir /mnt/boot/efi -p</pre> | <pre># mkdir /mnt/boot/efi -p</pre> | ||
Mount UEFI partition to /mnt/boot/efi : | Mount UEFI partition to /mnt/boot/efi : | ||
<pre># mount -t vfat /dev/nvme0n1p1 /mnt/boot/efi</pre> | <pre># mount -t vfat /dev/nvme0n1p1 /mnt/boot/efi</pre> | ||
Check partition scheme: | Check partition scheme: | ||
<pre># lsblk | <pre># lsblk | ||
nvme0n1 259:0 0 476.9G 0 disk | |||
nvme0n1 | ├─nvme0n1p1 259:1 0 511M 0 part /mnt/boot/efi | ||
├─nvme0n1p1 | └─nvme0n1p2 259:2 0 476.4G 0 part | ||
└─lvmcrypt 253:0 0 476.4G 0 crypt | |||
├─vg0-swap 253:1 0 20G 0 lvm [SWAP] | |||
└─vg0-root 253:2 0 456.4G 0 lvm /mnt | |||
</pre> | </pre> | ||
Line 150: | Line 146: | ||
= mkinitfs settings & modules = | = mkinitfs settings & modules = | ||
Edit the /mnt/etc/mkinitfs/mkinitfs.conf file and append the | Edit the /mnt/etc/mkinitfs/mkinitfs.conf file and append the modules to the features parameters (keymap only needed if your keyboard is not QWERTY): | ||
<pre>features=" | <pre>features="ata base ide scsi usb virtio ext4 lvm nvme keymap cryptsetup cryptkey resume"</pre> | ||
Regenerate the initram: | Regenerate the initram: | ||
<pre># mkinitfs -c /mnt/etc/mkinitfs/mkinitfs.conf -b /mnt/ $(ls /mnt/lib/modules/)</pre> | <pre># mkinitfs -c /mnt/etc/mkinitfs/mkinitfs.conf -b /mnt/ $(ls /mnt/lib/modules/)</pre> | ||
Line 160: | Line 156: | ||
<pre># touch /mnt/crypto_keyfile.bin | <pre># touch /mnt/crypto_keyfile.bin | ||
# chmod 600 /mnt/crypto_keyfile.bin | # chmod 600 /mnt/crypto_keyfile.bin | ||
# dd bs=512 count=4 | # dd if=/dev/random bs=512 count=4 | xxd -p -c999 | tr -d '\n' > /mnt/crypto_keyfile.bin | ||
# cryptsetup luksAddKey /dev/ | # cryptsetup luksAddKey /dev/nvme0n1p2 /mnt/crypto_keyfile.bin | ||
</pre> | </pre> | ||
Line 171: | Line 167: | ||
# chroot /mnt | # chroot /mnt | ||
</pre> | </pre> | ||
Edit /etc/default/grub and add cryptkey after cryptdm=root parameter like this: | |||
<pre>GRUB_TIMEOUT=2 | |||
GRUB_DISABLE_SUBMENU=y | |||
GRUB_DISABLE_RECOVERY=true | |||
GRUB_CMDLINE_LINUX_DEFAULT="modules=sd-mod,usb-storage,ext4,nvme cryptroot=UUID=XXXX cryptdm=lvmcrypt cryptkey quiet rootfstype=ext4" | |||
</pre> | |||
XXXX could be found with blkid command | |||
Add a new GRUB_PRELOAD_MODULES line like this: | |||
<pre>GRUB_PRELOAD_MODULES="luks cryptodisk part_gpt lvm" | |||
</pre> | |||
Finally, add the cryptodisk parameter : | |||
<pre>GRUB_ENABLE_CRYPTODISK=y</pre> | |||
Let's show the UUID of our partition scheme: | Let's show the UUID of our partition scheme: | ||
<pre># lsblk -f</pre> | <pre># lsblk -f</pre> | ||
Create a /root/grub-pre.cfg and replace <XXXX-UUID_WITHOUT_HYPHENS> with your encrypted lvm partition UUID (here /dev/nvme0n1p2) without hyphens, replace <YYYY> with VG UUID from vgdisplay and replace <ZZZZ> with LV UUID from lvdisplay of your /dev/vg0/root | |||
Create a /root/grub-pre.cfg and replace <UUID_WITHOUT_HYPHENS> with your encrypted | |||
<pre> | <pre> | ||
set crypto_uuid=<UUID_WITHOUT_HYPHENS> | set crypto_uuid=<XXXX-UUID_WITHOUT_HYPHENS> | ||
cryptomount -u $crypto_uuid | cryptomount -u $crypto_uuid | ||
set root= | set root='lvmid/<YYYY>/<ZZZZ>' | ||
set prefix=($root)/boot/grub | set prefix=($root)/boot/grub | ||
insmod normal | insmod normal | ||
Line 196: | Line 202: | ||
Re-install Grub: | Re-install Grub: | ||
<pre># 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 | <pre># mkdir /boot/efi/EFI/AlpineLinuxSecureBoot | ||
# grub-mkimage -p /boot/grub -O x86_64-efi -c /root/grub-pre.cfg -o /tmp/grubx64.efi luks2 part_gpt cryptodisk lvm ext2 gcry_rijndael pbkdf2 gcry_sha512 | |||
# install -v /tmp/grubx64.efi /boot/efi/EFI/AlpineLinuxSecureBoot/ | # install -v /tmp/grubx64.efi /boot/efi/EFI/AlpineLinuxSecureBoot/ | ||
# sed -i 's/SecureBoot/SecureB00t/' /boot/efi/EFI/AlpineLinuxSecureBoot/grubx64.efi | # sed -i 's/SecureBoot/SecureB00t/' /boot/efi/EFI/AlpineLinuxSecureBoot/grubx64.efi | ||
Line 216: | Line 223: | ||
issuer: /CN="Your Name" (db) | issuer: /CN="Your Name" (db) | ||
</pre> | </pre> | ||
Copy db.auth, KEK.auth and PK.auth files from /etc/uefi-keys to a FAT formatted file system. | |||
Reboot & enter into your UEFI (Fx key depending of your laptop) | Reboot & enter into your UEFI (Fx key depending of your laptop) | ||
Line 221: | Line 230: | ||
== Import keys to UEFI == | == Import keys to UEFI == | ||
This is just an example from an XPS laptop, each UEFI is unique. | This is just an example from an XPS laptop, each UEFI is unique. | ||
Line 243: | Line 251: | ||
Congrats! | Congrats! | ||
== Hibernate on encrypted LVM swap partition == | |||
< | Find your vg0-swap UUID : | ||
<pre>lsblk -f</pre> | |||
<pre> | |||
</ | Add resume parameter to your /etc/default/grub : | ||
</ | <pre>GRUB_CMDLINE_LINUX_DEFAULT=....resume=UUID=<UUID of your vg0-swap partition> | ||
</pre> | |||
Add a line to your /etc/fstab : | |||
<pre>/dev/vg0/swap none swap sw 0 0</pre> | |||
Enable swap service during boot : | |||
<pre>rc-update add swap default</pre> | |||
Install zzz and test it | |||
<pre># apk add zzz | |||
zzz- Z</pre> | |||
Done and congrats ! | |||
[[Category:Security]] |
Latest revision as of 21:50, 18 December 2023
Disclaimer : this is not to be followed, only for testing purposes. This will be updated when GRUB 2.12 rc1 will be available for LUKSv2, GRUB and FDE to work
This guide is to explain, step-by-step, how to setup Alpine Linux with Full Disk Encryption using LUKS2, LVM (one Physical Volume Partition with three Logical Volume Partitions (/ /boot & swap) with hibernation on a NVMe drive, with UEFI & Secure Boot. This guide has been written using Alpine Linux Std 3.16.1, please adapt some commands if needed.
The goal of this guide is to follow the KISS principle, but another file system can be used, multiple partitions for /home; /var/log etc.. can also be added, if the proposed configuration is not meeting your requirements.
Installing packages
To facilitate the partitioning we will use gdisk :
# apk add lsblk gptfdisk
For encryption, we will use cryptsetup :
# apk add cryptsetup
For LVM:
# apk add lvm2
For using and managing UEFI, multiple packages are needed :
# apk add efibootmgr e2fsprogs grub grub-efi
Preparing / overwriting the disk
# apk add haveged
This can take long, on my side for a 500GB nVME it tooks ~30 minutes.
# haveged -n 0 | dd of=/dev/nvme0n1
Partitioning the disk
Let's assume the disk is /dev/nvme0n1 and no partition is present, we will create two partitions :
- one for UEFI
- one for LVM
# gdisk /dev/nvme0n1 GPT fdisk (gdisk) version 1.0.9.1 Partition table scan: MBR: not present BSD: not present APM: not present GPT: not present Creating new GPT entries in memory. Command (? for help): n Partition number (1-128, default 1): First sector (34-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 (34-1000215182, default = 1050624) or {+-}size{KMGTP}: Last sector (1050624-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.
Populate /dev with the new partitions
# partprobe /dev/nvme0n1
Configuring LUKS
Using luks2 (unsupported by GRUB at the moment):
# cryptsetup -v -c aes-xts-plain64 -s 512 --hash sha512 --pbkdf pbkdf2 --iter-time 1000 --use-random luksFormat /dev/nvme0n1p2
Using luks1:
# cryptsetup -v -c aes-xts-plain64 -s 512 --hash sha512 --iter-time 1000 --use-urandom --type luks1 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 luksOpen /dev/nvme0n1p2 lvmcrypt
LVM : Physical & Logical Volumes creation
# pvcreate /dev/mapper/lvmcrypt Physical volume "/dev/mapper/lvmcrypt" successfully created. # vgcreate vg0 /dev/mapper/lvmcrypt Volume group "vg0" successfully created # lvcreate -L 20G vg0 -n swap (I have a 16GB RAM laptop) Logical volume "swap" created. # lvcreate -l 100%FREE vg0 -n root Logical volume "root" created.
To check the creation :
# lvscan ACTIVE '/dev/vg0/swap' [20.00 GiB] inherit ACTIVE '/dev/vg0/root' [455.92 GiB] inherit
Mounting points and File System
Create vfat file system for UEFI partition:
# mkfs.vfat /dev/nvme0n1p1
Create ext4 file system for / partition:
# mkfs.ext4 /dev/vg0/root
Activate SWAP:
# mkswap /dev/vg0/swap # swapon /dev/vg0/swap
Mount / partition to /mnt :
# mount -t ext4 /dev/vg0/root /mnt
Create /boot/efi:
# mkdir /mnt/boot/efi -p
Mount UEFI partition to /mnt/boot/efi :
# mount -t vfat /dev/nvme0n1p1 /mnt/boot/efi
Check partition scheme:
# lsblk nvme0n1 259:0 0 476.9G 0 disk ├─nvme0n1p1 259:1 0 511M 0 part /mnt/boot/efi └─nvme0n1p2 259:2 0 476.4G 0 part └─lvmcrypt 253:0 0 476.4G 0 crypt ├─vg0-swap 253:1 0 20G 0 lvm [SWAP] └─vg0-root 253:2 0 456.4G 0 lvm /mnt
Installing Alpine
# setup-disk -m sys /mnt/
mkinitfs settings & modules
Edit the /mnt/etc/mkinitfs/mkinitfs.conf file and append the modules to the features parameters (keymap only needed if your keyboard is not QWERTY):
features="ata base ide scsi usb virtio ext4 lvm nvme keymap cryptsetup cryptkey resume"
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 if=/dev/random bs=512 count=4 | xxd -p -c999 | tr -d '\n' > /mnt/crypto_keyfile.bin # cryptsetup luksAddKey /dev/nvme0n1p2 /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
Edit /etc/default/grub and add cryptkey after cryptdm=root parameter like this:
GRUB_TIMEOUT=2 GRUB_DISABLE_SUBMENU=y GRUB_DISABLE_RECOVERY=true GRUB_CMDLINE_LINUX_DEFAULT="modules=sd-mod,usb-storage,ext4,nvme cryptroot=UUID=XXXX cryptdm=lvmcrypt cryptkey quiet rootfstype=ext4"
XXXX could be found with blkid command
Add a new GRUB_PRELOAD_MODULES line like this:
GRUB_PRELOAD_MODULES="luks cryptodisk part_gpt lvm"
Finally, add the cryptodisk parameter :
GRUB_ENABLE_CRYPTODISK=y
Let's show the UUID of our partition scheme:
# lsblk -f
Create a /root/grub-pre.cfg and replace <XXXX-UUID_WITHOUT_HYPHENS> with your encrypted lvm partition UUID (here /dev/nvme0n1p2) without hyphens, replace <YYYY> with VG UUID from vgdisplay and replace <ZZZZ> with LV UUID from lvdisplay of your /dev/vg0/root
set crypto_uuid=<XXXX-UUID_WITHOUT_HYPHENS> cryptomount -u $crypto_uuid set root='lvmid/<YYYY>/<ZZZZ>' 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:
# mkdir /boot/efi/EFI/AlpineLinuxSecureBoot # grub-mkimage -p /boot/grub -O x86_64-efi -c /root/grub-pre.cfg -o /tmp/grubx64.efi luks2 part_gpt cryptodisk lvm 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)
Copy db.auth, KEK.auth and PK.auth files from /etc/uefi-keys to a FAT formatted file system.
Reboot & enter into your UEFI (Fx key depending of your laptop)
Import keys to UEFI
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!
Hibernate on encrypted LVM swap partition
Find your vg0-swap UUID :
lsblk -f
Add resume parameter to your /etc/default/grub :
GRUB_CMDLINE_LINUX_DEFAULT=....resume=UUID=<UUID of your vg0-swap partition>
Add a line to your /etc/fstab :
/dev/vg0/swap none swap sw 0 0
Enable swap service during boot :
rc-update add swap default
Install zzz and test it
# apk add zzz zzz- Z
Done and congrats !