User:grazzolini

From ArchWiki

Overview

There is a recent and virtually undocumented GRUB feature called cryptodisk, which enables GRUB to ask for a password to open a LUKS (and possibly plain Dm-Crypt) container, to read it's configuration from and load any initramfs and kernel from. This option try to solve the issue of having an unencrypted boot partition. A great deal of this information was based on this post by Pavel Kogan. Just be careful following the instructions on it, because it has some inaccuracies, such as, this grub bug, which is already solved in the current grub version.

Warning: This setup leaves the boot loader code unencrypted. Also, the machine is still vulnerable to boot loader code tampering, BIOS/UEFI/firmware tampering, hardware keyloggers, cold boot attacks, evil maid attacks and others that are beyond the scope of this article. For an overview of system-trust issues and how these related to full-disk encryption, refer to [1]. There is, however, the possibility of using the mkinitcpio-chkcryptobootAUR hook, which is similar to chkboot-gitAUR. This hook create a hash of the first 512 bytes of the boot disk or a hash of GRUB's efistub, in case of UEFI setups, and warn the user in the case of a compromised boot loader code. This can only be effective when using /boot in a dedicated partition.

Deciding where to place /boot

Using this feature, /boot can become a normal directory inside the / mount point. Also, it can be a separate logical volume, inside the same LVM on LUKS container as root. You can choose any partition scheme you want. You'll need to create and use a keyfile inside your initramfs to avoid having to unlock twice your container. This problem is explained on Pavel Kogan's post. Just keep in mind that, by making /boot as a directory inside /, or by creating a logical volume under the same container as root, you loose the ability of trying to check if your boot loader code was compromised with mkinitcpio-chkcryptobootAUR.

If you want that ability, /boot must be placed in a separate container than your root container. Accordingly, you should use a different passphrase and/or keyfile than your root container. This setup has the drawback of having to type two passphrases, one for opening the boot container and the other for opening the root container.

Placing /boot inside /

This will cover both the installation process and the conversion from an already installed arch system to a /boot cryptodisk setup. And both a BIOS/MBR or UEFI/GPR setup, with /boot residing inside /.

On the installation

BIOS/MBR setup

All your need to do is follow the advice on the LUKS page, skipping the creation of a separate boot partition. You can, optionally, follow the LVM on LUKS steps, creating a separate logical volume for boot. That way /boot will reside in the same root volume group, inside the same LUKS container as the swap and root logical volumes.

UEFI/GPT setup

In this case, the ESP must exist and, unfortunately, be left unencrypted. You can follow the partition scheme example on Beginners' guide for creating this partition. If it already exists, because you already have another operational system booting from it, then leave it alone. After that, you can follow either the simple partition layout or the LVM on LUKS setup. You will need to mount it under another mount point than /boot, because it is a directory under /. I suggest /esp. For the installation process, you will need to mount the ESP under the chosen alternative mount point and for the GRUB installation step, you will need to follow the GRUB alternative install method, passing the correct arguments to --efi-directory and --boot-directory options.

Converting an already installed system

Note: Always backup your data before changing partitions and filesystems! Depending on your setup, the conversion process might involve partitioning which has the potential of destroying your data. I highly advice you to try this process in a virtual machine environment before trying to convert a live system

BIOS/MBR

I assume your setup has a unencrypted boot partition and a encrypted root container. If you simply want to place /boot inside /, you need to copy it's contents:

# cp -a /boot /boot-new

Then unmount it:

# umount /boot

Now you'll need to delete the line in the /etc/fstab file regarding the /boot partition. After that, remove the existing mount point directory:

# rm -r /boot

After that, you need to rename the copy you made to replace the /boot path:

# mv /boot-new /boot
Note: This conversion will leave your boot unencrypted partition and it's space lying around in your disk. You can try to erase this partition, and try to rename and resize your luks container partition. But, since making this kind of changes on MBR is prone to error and data loss, I will not try to cover it in this article. You can always try to accomplish that in a virtual machine environment before trying to do it in your actual installation

UEFI/GPT

If you are using your ESP as /boot, then you can follow almost all the steps on the previous section. The difference here, is that you only need to move the files related with GRUB's configuration and any kernels and initramfs you might have on the partition. If you follow the steps for GRUB installation on UEFI, you must move every file inside the ESP, except the EFI directory:

# mkdir boot-new

Leave the EFI directory and move everything else to this new directory:

# mv /boot/grub /boot/initramfs-linux.img /boot/initramfs-linux-fallback.img /boot/vmlinuz-linux /boot-new

This should leave your ESP partition just like this:

# ls /boot
EFI

Now you can unmount your boot partition:

# umount /boot

Remove the directory mount point:

# rm -r /boot

And now move your new boot directory to it right place:

# mv /boot-new /boot

Now, since the ESP must be accessible for you being able to reinstall GRUB, if needed, it must have an entry in your /etc/fstab file. I suggest you use blkid then find your ESP partition id. Since your /boot is now a directory under / now, your ESP you need a different mount point. I suggest /esp, but this is up to you. After this change, for a GRUB reinstallation, you'll need to use GRUB alternative install method. Just pass your /esp mount point for the --efi-directory option and your /boot directory for the --boot-directory option.

/boot in a dedicated partition

Since you probably already have your boot as a separate partition, I will explain how to convert it to an encrypted one. The process for BIOS/MBR is quite simple, both in a fresh installation and the conversion process. For the UEFI/GPT case, the installation is also simple, but the conversion process involves partitioning.

On the installation

BIOS/MBR setup

You can follow the same partition scheme that is used for any LUKS installation. But, instead of the boot partition be unencrypted, it will be also encrypted with LUKS. If you want to boot faster, I suggest you use a smaller hash size, than 512 and don't change the default iter-time. If you want your boot partition to still be secure while having a relatively faster container unlock, I suggest that you use sha256. It is the perfect trade off between security and speed. After formating your root and boot partition with LUKS, just unlock then, create a filesystem on them, and mount them as you would for the rest of the installation process. After you run the genfstab command, you will note that in your /etc/fstab file will contain your an entry for your /boot mount point, but referring to the LUKS container. You will need to follow the instructions bellow for unlocking your boot partition automatically on boot.

UEFI/GPT setup

As already mentioned, your ESP must be left unencrypted. So, instead of just having a ESP and mount it as /boot, you will need two partitions. One for the ESP and another for your encrypted boot. The same suggestions as above regarding your encrypted boot partition formating and hash size apply. Also, as already mentioned here and here, your ESP must have a different mount point than /boot. For the installation, mount your /boot and /esp partitions in their respective mount points and follow the rest of the process. When you run genfstab it will have your ESP partition and your boot partition in /etc/fstab.

Converting an already installed system

Note: The same advice as before applies. Backup your data. Try this process in a virtual machine environment before trying to convert a live system. In the case of GPT, the conversion process involve resizing/creating/sorting partitions, so you will need to take great care.

BIOS/MBR

The conversion process of a BIOS/MBR installation is quite straightforward.

First copy the data in your boot partition:

# cp -a /boot /boot-new

Now umount the partition:

# umount /boot

Format your boot partition with LUKS:

# cryptsetup -v --hash sha256 --key-size 256 --cipher aes-xts-plain64 luksFormat /dev/sda1
Note: If you want to use the mkinitcpio-chkcryptobootAUR hook, format your boot partition with a different password than your root partition, for obvious reasons

Open your container:

# cryptsetup luksOpen /dev/sda1 sda1_crypt

Create the filesystem:

# mkfs.ext4 /dev/mapper/sda1_crypt

Now mount it back to /boot:

# mount /dev/mapper/sda1_crypt /boot

And copy the data you created in the first step:

# mv /boot-new/* /boot

Remove the created directory:

# rm -r /boot-new

Now follow the steps bellow for the remaining configuration.

UEFI/GPT

Warning: The UEFI/GPT conversion process involve changing your partition scheme. Take great care following it. The partitions numbers here assume a default UEFI installation with a ESP being mount as /boot. Change the commands to reflect your partition numbering.

First of all, I suggest you take notes on your current partition scheme. Running commands like

# parted -l

or

# gdisk -l /dev/sda

are good starting points. Also, I suggest that you backup your GPT partition table:

# sgdisk -b /gpt_backup

If you have a default GPT partition scheme with:

/dev/sda1 being your ESP

/dev/sda2 being your root LUKS container

What we are going to do is to resize your ESP partition, create a new one, and after that sort the partitions. Your scheme will become something like this:

/dev/sda1 still being your ESP, but smaller

/dev/sda2 being your new encrypted boot partition

/dev/sda3 being your root LUKS container

Start by copying your ESP files to another directory (beside the backup you made before):

# cp -a /boot /boot-new

Now umount it:

# umount /boot

The next step depends on the size of your ESP partition and if you boot another operational systems from it. If you followed the specification it will be at least 512MB. More than enough for our purposes. This setup might work with another ESP sizes, but depending on the number of kernels you use, your boot partition might not have space for them all. If you simply boot arch from your ESP and use only one kernel, you can resize the ESP partition to very small sizes. The last I checked, GRUB's efistub was smaller than 200KB. My instructions will be based on a 512MB ESP partition size, adapt then as needed.

I used both parted and the gdisk command in gptfdisk for this process.

Started parted on /dev/sda:

# parted /dev/sda

Print your partition scheme and note the end of your ESP partition and the start of your root LUKS container:

(parted) p
1      1049kB  538MB  537MB  fat32        EFI System        boot, esp 
2      538MB   <END OF DISK> <SIZE>       Linux filesystem

Now, we will resize the ESP partition and shrink it. Beware that the FAT filesystem on it, will most likely need to be recreated. If you mount it after the resize, it will probably mount with no issues, but I suggest you to reformat it:

(parted) resizepart 1 256MB
Warning: Shrinking a partition can cause data loss, are you sure you want to continue?
Yes/No? Yes

Now create a new partition, between your ESP and LUKS container partitions:

(parted) mkpart
Partition name?  []?
File system type?  [ext2]?
Start? 256MB                                                              
End? 538MB                                                                
Warning: The resulting partition is not properly aligned for best performance.
Ignore/Cancel? Ignore

If you print again your partition scheme, you will see your new partition, but the number of it will be wrong:

(parted) p
Number  Start   End     Size    File system  Name              Flags
 1      1049kB  256MB   255MB                EFI System        boot, esp
 3      256MB   538MB   282MB   ext2
 2      538MB   <END OF DISK> <SIZE>         Linux filesystem

Quit parted and call gdisk on your disk:

gdisk /dev/sda

Print your partition scheme on gdisk. It is clear why you need to sort your partitions:

{{hc|head=Command (? for help): p|output= Number Start (sector) End (sector) Size Code Name

  1            2048          500000   243.1 MiB   EF00  EFI System
  2         1050624    <LAST SECTOR> <SIZE> GiB   8300  Linux filesystem
  3          500001         1050623   268.9 MiB   8300  

Now sort your partitions:

Command (? for help): s
You may need to edit /etc/fstab and/or your boot loader configuration!

And write your new partition scheme:

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/sda.
The operation has completed successfully.

Despite the warning that gdisk displayed, telling you that you might need to update your /etc/fstab, if you use UUID to identify your partitions, you are probably safe.

Now, format your new boot partition with crypsetup and create a filesystem on it, as mentioned on the BIOS/MBR process.

/etc/crypttab configuration

This part of the setup is only relevant when boot is in a dedicated partition. Since your boot partition is a separate LUKS container than your root, you need to create a keyfile, so it will be mounted at boot time, without asking for a passphrase. I suggest you create a randomtext or binary keyfile and store it under your /etc directory, with restrictive permissions. Then add it to your LUKS container. After that you will need to add it to /etc/crypttab. Just take care to use the same device mapper name in both /etc/crypttab and /etc/fstab, as is shown here Dm-crypt/System_configuration#Mounting_at_boot_time. GRUB will not use this keyfile for opening your boot partition, both because it will not have any access to it, and also, as far as I know, GRUB do not have this feature at this moment.

GRUB configuration

This is the easiest part of the setup. You do not need to add any additional modules to GRUB configuration, nor change any of the parameters already on it. Assuming, of course, that you already have a functional LUKS setup.

Just open /etc/default/grub and add this to the end:

GRUB_ENABLE_CRYPTODISK=y

After that we need to recreated GRUB configuration and after that follow GRUB's alternative install method. For example, in a UEFI setup case, assuming you have your boot partition mounted or being a directory at /boot and that you have your ESP partition mounted at /esp, by issuing the following commands you will have a functional GRUB cryptodisk setup:

grub-mkconfig -o /boot/grub/grub.cfg
grub-install --target=x86_64-efi --efi-directory=/esp --bootloader-id=grub_uefi --boot-directory=/boot --recheck

All you need to do is reboot your machine, and GRUB should prompt for a password to open the partition containing it's configuration.