Full disk encryption secure boot: Difference between revisions

From Alpine Linux
No edit summary
(converting the guide for LVM until Installing Alpine)
Line 1: Line 1:
{{Draft}}
{{Draft}}


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.
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 (and hopefully tpm as well : WIP). 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, 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.
 
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 13: Line 14:


For LVM:
For LVM:
<div class="toccolours mw-collapsible mw-collapsed">
Add LVM on top of luks partition
<div class="mw-collapsible-content">
<pre># apk add lvm2</pre>
<pre># apk add lvm2</pre>
</div>
 
</div>
For using and managing UEFI, multiple packages are needed :
<pre># apk add efibootmgr e2fsprogs grub grub-efi</pre>


To improve the entropy :
To improve the entropy :
<pre># apk add haveged
<pre># apk add haveged
# rc-service haveged start</pre>
# rc-service haveged start
</pre>
 
= Preparing / overwriting the disk =


For using and managing UEFI, multiple packages are needed :
This can take long, on my side for a 500GB nVME it tooks ~30 minutes.
<pre># apk add efibootmgr e2fsprogs grub grub-efi</pre>
<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 three partitions :
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
* one for swap (hibernation)


<pre># gdisk /dev/nvme0n1
<pre># gdisk /dev/nvme0n1
Line 59: Line 60:
Command (? for help): n
Command (? for help): n
Partition number (2-128, default 2):  
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}:  
First sector (1048577-1000215182, default = 33556480) or {+-}size{KMGTP}:  
Last sector (33556480-1000215182, default = 1000214527) or {+-}size{KMGTP}:  
Last sector (33556480-1000215182, default = 1000214527) or {+-}size{KMGTP}:  
Line 82: Line 75:
The operation has completed successfully.
The operation has completed successfully.
</pre>
</pre>
= Preparing the disks =
<pre># haveged -n 0 | dd of=/dev/nvme0n1p1
# haveged -n 0 | dd of=/dev/nvme0n1p2
# haveged -n 0 | dd of=/dev/nvme0n1p3</pre>


= Configuring LUKS =
= Configuring LUKS =


<pre># cryptsetup -v -c aes-xts-plain64 -s 512 --hash sha512 --pbkdf pbkdf2 --iter-time 5000 --use-random luksFormat /dev/nvme0n1p2
<pre># cryptsetup -v -c aes-xts-plain64 -s 512 --hash sha512 --pbkdf pbkdf2 --iter-time 1000 --use-random luksFormat /dev/nvme0n1p2


WARNING!
WARNING!
Line 103: Line 90:
Command successful.
Command successful.


# cryptsetup -v -c aes-xts-plain64 -s 512 --hash sha512 --pbkdf pbkdf2 --iter-time 5000 --use-random luksFormat /dev/nvme0n1p3
# cryptsetup luksOpen /dev/nvme0n1p2 lvmcrypt


WARNING!
= LVM : Physical & Logical Volumes creation=
========
<pre># pvcreate /dev/mapper/lvmcrypt
This will overwrite data on /dev/nvme0n1p3 irrevocably.
# vgcreate vg0 /dev/mapper/lvmcrypt
# lvcreate -L 20G vg0 -n swap (I have a 16GB RAM laptop)
# lvcreate -L 512M vg0 -n boot
# lvcreate -l 100%FREE vg0 -n root
</pre>


Are you sure? (Type 'yes' in capital letters): YES
To check the creation :
Enter passphrase for /dev/nvme0n1p3:
<pre># lvscan</pre>
Verify passphrase:
Key slot 0 created.
Command successful.
</pre>


= Mounting points and File System =
= Mounting points and File System =
Open the LUKS partitiond we just created:
<pre># cryptsetup luksOpen /dev/nvme0n1p2 nvme0n1p2-crypt
# cryptsetup luksOpen /dev/nvme0n1p3 nvme0n1p3-crypt
</pre>


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 swap partition:
Create ext4 file system for / partition:
<pre># mkfs.ext4 /dev/mapper/nvme0n1p2-crypt</pre>
<pre># mkfs.ext4 /dev/vg0/root</pre>


Create ext4 file system for / partition:
Activate SWAP:
<pre># mkfs.ext4 /dev/mapper/nvme0n1p3-crypt</pre>
<pre># mkswap /dev/vg0/swap
# swapon /dev/vg0/swap
</pre>


Create mounting points and mount partitions :
Mount / partition to /mnt :
Mount / partition to /mnt :
<pre># mount -t ext4 /dev/mapper/nvme0n1p3-crypt /mnt</pre>
<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>
Activate SWAP:
 
<pre># mkswap /dev/mapper/nvme0n1p2-crypt
# swapon /dev/mapper/nvme0n1p2-crypt</pre>
Check partition scheme:
Check partition scheme:
<pre># lsblk
<pre># 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
</pre>
</pre>


Line 158: Line 135:


= mkinitfs settings & modules =
= 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):
Edit the /mnt/etc/mkinitfs/mkinitfs.conf file and append the cryptsetup and lvm modules to the features parameter (keymap only needed if QWERTY is not used):
<pre>features="...keymap cryptsetup cryptkey"</pre>
<pre>features="...keymap cryptsetup cryptkey"</pre>
Regenerate the initram:
Regenerate the initram:

Revision as of 17:52, 7 August 2022

This material is work-in-progress ...

Do not follow instructions here until this notice is removed.
(Last edited by Blt on 7 Aug 2022.)

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 (and hopefully tpm as well : WIP). 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

To improve the entropy :

# apk add haveged
# rc-service haveged start

Preparing / overwriting the disk

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: 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 = 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 1000 --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 luksOpen /dev/nvme0n1p2 lvmcrypt

= LVM : Physical & Logical Volumes creation=
<pre># pvcreate /dev/mapper/lvmcrypt
# vgcreate vg0 /dev/mapper/lvmcrypt
# lvcreate -L 20G vg0 -n swap (I have a 16GB RAM laptop)
# lvcreate -L 512M vg0 -n boot
# lvcreate -l 100%FREE vg0 -n root

To check the creation :

# lvscan

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

Installing Alpine

# setup-disk -m sys /mnt/

mkinitfs settings & modules

Edit the /mnt/etc/mkinitfs/mkinitfs.conf file and append the cryptsetup and lvm modules 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 & enter into your UEFI (Fx key depending of your laptop)

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.

  1. Go to Boot Configuration > Secure Boot
  2. Change Enable Secure Boot to ON
  3. Change Secure Boot Mode to Deployed Mode
  4. Change Enable Custom Mode to ON
  5. 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
  6. APPLY CHANGES > EXIT

Check Secure Boot State:

# apk add mokutil
# mokutil --sb-state
SecureBoot enabled

Congrats!