Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save hy37id/b9ae23dd1ff2c0cf2b54d2c90a876086 to your computer and use it in GitHub Desktop.

Select an option

Save hy37id/b9ae23dd1ff2c0cf2b54d2c90a876086 to your computer and use it in GitHub Desktop.

Revisions

  1. @huntrar huntrar revised this gist Dec 31, 2019. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions full-disk-encryption-arch-uefi.md
    Original file line number Diff line number Diff line change
    @@ -106,7 +106,7 @@ mount /dev/nvme0n1p2 /mnt/efi
    ## Installation
    ### Install necessary packages
    ```
    pacstrap /mnt base linux linux-firmware mkinitcpio lvm2 vi
    pacstrap /mnt base linux linux-firmware mkinitcpio lvm2 vi dhcpcd wpa_supplicant
    ```

    ## Configure the system
    @@ -116,7 +116,7 @@ genfstab -U /mnt >> /mnt/etc/fstab
    ```

    #### (optional) Change `relatime` option to `noatime`
    ```mnt/etc/fstab```
    ```/mnt/etc/fstab```
    ```
    # /dev/mapper/vg-root
    UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx / ext4 rw,noatime 0 1
  2. @huntrar huntrar revised this gist Oct 19, 2019. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions full-disk-encryption-arch-uefi.md
    Original file line number Diff line number Diff line change
    @@ -104,9 +104,9 @@ mount /dev/nvme0n1p2 /mnt/efi
    ```

    ## Installation
    ### Install the base packages
    ### Install necessary packages
    ```
    pacstrap /mnt base
    pacstrap /mnt base linux linux-firmware mkinitcpio lvm2 vi
    ```

    ## Configure the system
  3. @huntrar huntrar revised this gist Sep 12, 2019. 1 changed file with 13 additions and 8 deletions.
    21 changes: 13 additions & 8 deletions full-disk-encryption-arch-uefi.md
    Original file line number Diff line number Diff line change
    @@ -49,7 +49,7 @@ w
    ```

    #### Create the LUKS1 encrypted container on the Linux LUKS partition (GRUB does not support LUKS2 as of May 2019)
    ```cryptsetup luksFormat --type luks1 /dev/nvme0n1p3```
    ```cryptsetup luksFormat --type luks1 --use-random -S 1 -s 512 -h sha512 -i 5000 /dev/nvme0n1p3```

    #### Open the container (decrypt it and make available at /dev/mapper/cryptlvm)
    ```
    @@ -189,7 +189,7 @@ This is a unique name for identifying your machine on a network.
    ```

    ### Initramfs
    #### Add the ```keyboard```, ```encrypt```, and ```lvm2``` hooks to /etc/mkinitcpio.conf
    #### Add the ```keyboard```, ```encrypt```, and ```lvm2``` hooks to ```/etc/mkinitcpio.conf```
    *Note:* ordering matters.
    ```
    HOOKS=(base udev autodetect keyboard modconf block encrypt lvm2 filesystems fsck)
    @@ -222,7 +222,7 @@ GRUB_ENABLE_CRYPTODISK=y
    ##### UUID is the partition containing the LUKS container
    ```blkid```
    ```
    /dev/mapper/nvme0n1p3: UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" TYPE="crypto_LUKS" PARTLABEL="Linux LUKS" PARTUUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    /dev/nvme0n1p3: UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" TYPE="crypto_LUKS" PARTLABEL="Linux LUKS" PARTUUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    ```

    ```/etc/default/grub```
    @@ -255,15 +255,15 @@ This is done to avoid having to enter the encryption passphrase twice (once for

    #### Create a keyfile and add it as LUKS key
    ```
    dd bs=512 count=4 if=/dev/random of=/root/cryptlvm.keyfile iflag=fullblock
    chmod 000 /root/cryptlvm.keyfile
    cryptsetup -v luksAddKey /dev/nvme0n1p3 /root/cryptlvm.keyfile
    mkdir /root/secrets && chmod 700 /root/secrets
    head -c 64 /dev/urandom > /root/secrets/crypto_keyfile.bin && chmod 600 /root/secrets/crypto_keyfile.bin
    cryptsetup -v luksAddKey -i 1 /dev/nvme0n1p3 /root/secrets/crypto_keyfile.bin
    ```

    #### Add the keyfile to the initramfs image
    ```/etc/mkinitcpio.conf```
    ```
    FILES=(/root/cryptlvm.keyfile)
    FILES=(/root/secrets/crypto_keyfile.bin)
    ```

    #### Recreate the initramfs image
    @@ -274,14 +274,19 @@ mkinitcpio -p linux
    #### Set kernel parameters to unlock the LUKS partition with the keyfile using ```encrypt``` hook
    ```/etc/default/grub```
    ```
    GRUB_CMDLINE_LINUX="... cryptkey=rootfs:/root/cryptlvm.keyfile"
    GRUB_CMDLINE_LINUX="... cryptkey=rootfs:/root/secrets/crypto_keyfile.bin"
    ```

    #### Regenerate GRUB's configuration file
    ```
    grub-mkconfig -o /boot/grub/grub.cfg
    ```

    #### Restrict ```/boot``` permissions
    ```
    chmod 700 /boot
    ```

    The installation is now complete. Exit the chroot and reboot.
    ```
    exit
  4. @huntrar huntrar revised this gist May 24, 2019. No changes.
  5. @huntrar huntrar created this gist May 24, 2019.
    464 changes: 464 additions & 0 deletions full-disk-encryption-arch-uefi.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,464 @@
    # Arch Linux Full-Disk Encryption Installation Guide
    This guide provides instructions for an Arch Linux installation featuring full-disk encryption via LVM on LUKS and an encrypted boot partition (GRUB) for UEFI systems.

    Following the main installation are further instructions to harden against Evil Maid attacks via UEFI Secure Boot custom key enrollment and self-signed kernel and bootloader.

    ## Preface
    You will find most of this information pulled from the [Arch Wiki](https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system#Encrypted_boot_partition_(GRUB)) and other resources linked thereof.

    *Note:* The system was installed on an NVMe SSD, substitute ```/dev/nvme0nX``` with ```/dev/sdX``` or your device as needed.

    ## Pre-installation
    ### Connect to the internet
    Plug in your Ethernet and go, or for wireless consult the all-knowing [Arch Wiki](https://wiki.archlinux.org/index.php/installation_guide#Connect_to_the_internet).

    ### Update the system clock
    ```
    timedatectl set-ntp true
    ```

    ### Preparing the disk
    #### Create EFI System and Linux LUKS partitions
    ##### Create a 1MiB BIOS boot partition at start just in case it is ever needed in the future

    Number | Start (sector) | End (sector) | Size | Code | Name |
    -------|----------------|--------------|------------|------|---------------------|
    1 | 2048 | 4095 | 1024.0 KiB | EF02 | BIOS boot partition |
    2 | 4096 | 1130495 | 550.0 MiB | EF00 | EFI System |
    3 | 1130496 | 976773134 | 465.2 GiB | 8309 | Linux LUKS |

    ```gdisk /dev/nvme0n1```
    ```
    o
    n
    [Enter]
    0
    +1M
    ef02
    n
    [Enter]
    [Enter]
    +550M
    ef00
    n
    [Enter]
    [Enter]
    [Enter]
    8309
    w
    ```

    #### Create the LUKS1 encrypted container on the Linux LUKS partition (GRUB does not support LUKS2 as of May 2019)
    ```cryptsetup luksFormat --type luks1 /dev/nvme0n1p3```

    #### Open the container (decrypt it and make available at /dev/mapper/cryptlvm)
    ```
    cryptsetup open /dev/nvme0n1p3 cryptlvm
    ```

    ### Preparing the logical volumes
    #### Create physical volume on top of the opened LUKS container
    ```
    pvcreate /dev/mapper/cryptlvm
    ```

    #### Create the volume group and add physical volume to it
    ```
    vgcreate vg /dev/mapper/cryptlvm
    ```

    #### Create logical volumes on the volume group for swap, root, and home
    ```
    lvcreate -L 8G vg -n swap
    lvcreate -L 32G vg -n root
    lvcreate -l 100%FREE vg -n home
    ```

    The size of the swap and root partitions are a matter of personal preference.

    #### Format filesystems on each logical volume
    ```
    mkfs.ext4 /dev/vg/root
    mkfs.ext4 /dev/vg/home
    mkswap /dev/vg/swap
    ```

    #### Mount filesystems
    ```
    mount /dev/vg/root /mnt
    mkdir /mnt/home
    mount /dev/vg/home /mnt/home
    swapon /dev/vg/swap
    ```

    ### Preparing the EFI partition
    #### Create FAT32 filesystem on the EFI system partition
    ```
    mkfs.fat -F32 /dev/nvme0n1p2
    ```

    #### Create mountpoint for EFI system partition at /efi for compatibility with grub-install and mount it
    ```
    mkdir /mnt/efi
    mount /dev/nvme0n1p2 /mnt/efi
    ```

    ## Installation
    ### Install the base packages
    ```
    pacstrap /mnt base
    ```

    ## Configure the system
    ### Generate an fstab file
    ```
    genfstab -U /mnt >> /mnt/etc/fstab
    ```

    #### (optional) Change `relatime` option to `noatime`
    ```mnt/etc/fstab```
    ```
    # /dev/mapper/vg-root
    UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx / ext4 rw,noatime 0 1
    # /dev/mapper/vg-home
    UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx / ext4 rw,noatime 0 1
    ```

    Reduces writes to disk when reading from a file, but may cause issues with programs that rely on file access time

    ### Enter new system chroot
    ```
    arch-chroot /mnt
    ```

    #### At this point you should have the following partitions and logical volumes:
    ```lsblk```

    NAME | MAJ:MIN | RM | SIZE | RO | TYPE | MOUNTPOINT |
    ---------------|---------|-----|--------|-----|-------|------------|
    nvme0n1 | 259:0 | 0 | 465.8G | 0 | disk | |
    ├─nvme0n1p1 | 259:4 | 0 | 1M | 0 | part | |
    ├─nvme0n1p2 | 259:5 | 0 | 550M | 0 | part | /efi |
    ├─nvme0n1p3 | 259:6 | 0 | 465.2G | 0 | part | |
    ..└─cryptlvm | 254:0 | 0 | 465.2G | 0 | crypt | |
    ....├─vg-swap | 254:1 | 0 | 8G | 0 | lvm | [SWAP] |
    ....├─vg-root | 254:2 | 0 | 32G | 0 | lvm | / |
    ....└─vg-home | 254:3 | 0 | 425.2G | 0 | lvm | /home |

    ### Time zone
    #### Set the time zone
    Replace `America/Los_Angeles` with your respective timezone found in `/usr/share/zoneinfo`
    ```
    ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
    ```

    #### Run `hwclock` to generate ```/etc/adjtime```
    Assumes hardware clock is set to UTC
    ```
    hwclock --systohc
    ```

    ### Localization
    #### Uncomment ```en_US.UTF-8 UTF-8``` in ```/etc/locale.gen``` and generate locale
    ```
    locale-gen
    ```

    #### Create ```locale.conf``` and set the ```LANG``` variable
    ```/etc/locale.conf```
    ```
    LANG=en_US.UTF-8
    ```

    ### Network configuration
    #### Create the hostname file
    ```/etc/hostname```
    ```
    myhostname
    ```

    This is a unique name for identifying your machine on a network.

    #### Add matching entries to hosts
    ```/etc/hosts```
    ```
    127.0.0.1 localhost
    ::1 localhost
    127.0.1.1 myhostname.localdomain myhostname
    ```

    ### Initramfs
    #### Add the ```keyboard```, ```encrypt```, and ```lvm2``` hooks to /etc/mkinitcpio.conf
    *Note:* ordering matters.
    ```
    HOOKS=(base udev autodetect keyboard modconf block encrypt lvm2 filesystems fsck)
    ```

    #### Recreate the initramfs image
    ```
    mkinitcpio -p linux
    ```

    ### Root password
    #### Set the root password
    ```
    passwd
    ```

    ### Boot loader
    #### Install GRUB
    ```
    pacman -S grub
    ```

    #### Configure GRUB to allow booting from /boot on a LUKS1 encrypted partition
    ```/etc/default/grub```
    ```
    GRUB_ENABLE_CRYPTODISK=y
    ```

    #### Set kernel parameter to unlock the LVM physical volume at boot using ```encrypt``` hook
    ##### UUID is the partition containing the LUKS container
    ```blkid```
    ```
    /dev/mapper/nvme0n1p3: UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" TYPE="crypto_LUKS" PARTLABEL="Linux LUKS" PARTUUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    ```

    ```/etc/default/grub```
    ```
    GRUB_CMDLINE_LINUX="... cryptdevice=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:cryptlvm root=/dev/vg/root ..."
    ```

    #### Install GRUB to the mounted ESP for UEFI booting
    ```
    pacman -S efibootmgr
    grub-install --target=x86_64-efi --efi-directory=/efi
    ```

    #### Enable microcode updates
    ##### grub-mkconfig will automatically detect microcode updates and configure appropriately
    ```
    pacman -S intel-ucode
    ```

    Use intel-ucode for Intel CPUs and amd-ucode for AMD CPUs.

    #### Generate GRUB's configuration file
    ```
    grub-mkconfig -o /boot/grub/grub.cfg
    ```

    ### (recommended) Embed a keyfile in initramfs

    This is done to avoid having to enter the encryption passphrase twice (once for GRUB, once for initramfs.)

    #### Create a keyfile and add it as LUKS key
    ```
    dd bs=512 count=4 if=/dev/random of=/root/cryptlvm.keyfile iflag=fullblock
    chmod 000 /root/cryptlvm.keyfile
    cryptsetup -v luksAddKey /dev/nvme0n1p3 /root/cryptlvm.keyfile
    ```

    #### Add the keyfile to the initramfs image
    ```/etc/mkinitcpio.conf```
    ```
    FILES=(/root/cryptlvm.keyfile)
    ```

    #### Recreate the initramfs image
    ```
    mkinitcpio -p linux
    ```

    #### Set kernel parameters to unlock the LUKS partition with the keyfile using ```encrypt``` hook
    ```/etc/default/grub```
    ```
    GRUB_CMDLINE_LINUX="... cryptkey=rootfs:/root/cryptlvm.keyfile"
    ```

    #### Regenerate GRUB's configuration file
    ```
    grub-mkconfig -o /boot/grub/grub.cfg
    ```

    The installation is now complete. Exit the chroot and reboot.
    ```
    exit
    reboot
    ```

    ## Post-installation
    Your system should now be fully installed, bootable, and fully encrypted.

    If you embedded the keyfile in the initramfs image, it should only require your encryption passphrase once to unlock to the system.

    For the standard Arch Linux post-installation steps, [RTFM](https://wiki.archlinux.org/index.php/General_recommendations).

    ### (recommended) Hardening against Evil Maid attacks
    With an encrypted boot partition, nobody can see or modify your kernel image or initramfs, but you would be still vulnerable to [Evil Maid](https://www.schneier.com/blog/archives/2009/10/evil_maid_attac.html) attacks.

    One possible solution is to use UEFI Secure Boot. Get rid of preloaded Secure Boot keys (you really don't want to trust Microsoft and OEM), enroll [your own Secure Boot keys](https://wiki.archlinux.org/index.php/Secure_Boot#Using_your_own_keys) and sign the GRUB boot loader with your keys. Evil Maid would be unable to boot modified boot loader (not signed by your keys) and the attack is prevented.

    #### Creating keys
    The following steps should be performed as the `root` user, with accompanying files stored in the `/root` directory.

    ##### Install `efitools`
    ```
    pacman -S efitools
    ```

    ##### Create a GUID for owner identification
    ```
    uuidgen --random > GUID.txt
    ```

    ##### Platform key
    CN is a Common Name, which can be written as anything.

    ```
    openssl req -newkey rsa:4096 -nodes -keyout PK.key -new -x509 -sha256 -days 3650 -subj "/CN=my Platform Key/" -out PK.crt
    openssl x509 -outform DER -in PK.crt -out PK.cer
    cert-to-efi-sig-list -g "$(< GUID.txt)" PK.crt PK.esl
    sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt PK PK.esl PK.auth
    ```

    ##### Sign an empty file to allow removing Platform Key when in "User Mode"
    ```
    sign-efi-sig-list -g "$(< GUID.txt)" -c PK.crt -k PK.key PK /dev/null rm_PK.auth
    ```

    ##### Key Exchange Key
    ```
    openssl req -newkey rsa:4096 -nodes -keyout KEK.key -new -x509 -sha256 -days 3650 -subj "/CN=my Key Exchange Key/" -out KEK.crt
    openssl x509 -outform DER -in KEK.crt -out KEK.cer
    cert-to-efi-sig-list -g "$(< GUID.txt)" KEK.crt KEK.esl
    sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt KEK KEK.esl KEK.auth
    ```

    ##### Signature Database key
    ```
    openssl req -newkey rsa:4096 -nodes -keyout db.key -new -x509 -sha256 -days 3650 -subj "/CN=my Signature Database key/" -out db.crt
    openssl x509 -outform DER -in db.crt -out db.cer
    cert-to-efi-sig-list -g "$(< GUID.txt)" db.crt db.esl
    sign-efi-sig-list -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db db.esl db.auth
    ```

    #### Signing bootloader and kernel
    When Secure Boot is active (i.e. in "User Mode") you will only be able to launch signed binaries, so you need to sign your kernel and boot loader.

    Install `sbsigntools`
    ```
    pacman -S sbsigntools
    ```
    ```
    sbsign --key db.key --cert db.crt --output /boot/vmlinuz-linux /boot/vmlinuz-linux
    sbsign --key db.key --cert db.crt --output /efi/EFI/arch/grubx64.efi /efi/EFI/arch/grubx64.efi
    ```

    ##### Automatically sign bootloader and kernel on install and updates
    It is necessary to sign GRUB with your UEFI Secure Boot keys every time the system is updated via `pacman`. This can be accomplished with a [pacman hook](https://jlk.fjfi.cvut.cz/arch/manpages/man/alpm-hooks.5).

    Create the hooks directory
    ```
    mkdir -p /etc/pacman.d/hooks
    ```

    Create hooks for both the `linux` and `grub` packages

    ```/etc/pacman.d/hooks/99-secureboot-linux.hook```
    ```
    [Trigger]
    Operation = Install
    Operation = Upgrade
    Type = Package
    Target = linux
    [Action]
    Description = Signing Kernel for SecureBoot
    When = PostTransaction
    Exec = /usr/bin/find /boot/ -maxdepth 1 -name 'vmlinuz-*' -exec /usr/bin/sh -c 'if ! /usr/bin/sbverify --list {} 2>/dev/null | /usr/bin/grep -q "signature certificates"; then /usr/bin/sbsign --key /root/db.key --cert /root/db.crt --output {} {}; fi' \ ;
    Depends = sbsigntools
    Depends = findutils
    Depends = grep
    ```

    ```/etc/pacman.d/hooks/98-secureboot-grub.hook```
    ```
    [Trigger]
    Operation = Install
    Operation = Upgrade
    Type = Package
    Target = grub
    [Action]
    Description = Signing GRUB for SecureBoot
    When = PostTransaction
    Exec = /usr/bin/find /efi/ -name 'grubx64*' -exec /usr/bin/sh -c 'if ! /usr/bin/sbverify --list {} 2>/dev/null | /usr/bin/grep -q "signature certificates"; then /usr/bin/sbsign --key /root/db.key --cert /root/db.crt --output {} {}; fi' \ ;
    Depends = sbsigntools
    Depends = findutils
    Depends = grep
    ```

    #### Enroll keys in firmware
    ##### Copy all `*.cer`, `*.esl`, `*.auth` to the EFI system partition
    ```
    cp /root/*.cer /root/*.esl /root/*.auth /efi/
    ```

    ##### Boot into UEFI firmware setup utility (frequently but incorrectly referred to as "BIOS")
    ```
    systemctl reboot --firmware
    ```

    Firmwares have various different interfaces, see [Replacing Keys Using Your Firmware's Setup Utility](http://www.rodsbooks.com/efi-bootloaders/controlling-sb.html#setuputil) if the following instructions are unclear or unsuccessful.

    ##### Set OS Type to `Windows UEFI mode`
    Find the Secure Boot options and set OS Type to `Windows UEFI mode` (yes, even if we're not on Windows.) This may be necessary for Secure Boot to function.

    ##### Clear preloaded Secure Boot keys


    Using Key Management, clear all preloaded Secure Boot keys (Microsoft and OEM).

    By clearing all Secure Boot keys, you will enter into Setup Mode (so you can enroll your own Secure Boot keys).

    ##### Set or append the new keys
    The keys must be set in the following order:

    ```db => KEK => PK```

    This is due to some systems exiting setup mode as soon as a `PK` is entered.

    Do not load the factory defaults, instead navigate the available filesystems in search of the files previously copied to the EFI System partition.

    Choose any of the formats. The firmware should prompt you to enter the type (*Note:* type names may differ slightly.)
    ```
    *.cer is a Public Key Certificate
    *.esl is a UEFI Secure Variable
    *.auth is an Authenticated Variable
    ```

    Certain firmware (such as my own) require you use the *.auth files. Try various ones until they work.

    ##### Set UEFI supervisor (administrator) password
    You must also set your UEFI firmware supervisor (administrator) password in the Security settings, so nobody can simply boot into UEFI setup utility and turn off Secure Boot.

    You should never use the same UEFI firmware supervisor password as your encryption password, because on some old laptops, the supervisor password could be recovered as plaintext from the EEPROM chip.

    ##### Exit and save changes
    Once you've loaded all three keys and set your supervisor password, hit F10 to exit and save your changes.

    If everything was done properly, your boot loader should appear on reboot.

    #### Check if Secure Boot was enabled
    ```
    od -An -t u1 /sys/firmware/efi/efivars/SecureBoot-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
    ```
    The characters denoted by XXXX differ from machine to machine. To help with this, you can use tab completion or list the EFI variables.

    If Secure Boot is enabled, this command returns 1 as the final integer in a list of five, for example:

    ```6 0 0 0 1```

    If Secure Boot was enabled and your UEFI supervisor password set, you may now consider yourself protected against Evil Maid attacks.