Skip to content

Instantly share code, notes, and snippets.

@darrenldl
Last active July 14, 2023 17:18
Show Gist options
  • Save darrenldl/6b10dcab7eafcd88c4c65ff60e91f32e to your computer and use it in GitHub Desktop.
Save darrenldl/6b10dcab7eafcd88c4c65ff60e91f32e to your computer and use it in GitHub Desktop.
Ubuntu keyfile boot

Ubuntu LUKS keyfile guide

Goal

We want to be able to set up an encrypted Ubuntu installation where we can unlock using just an external USB key without entering any passwords

We do not consider evil maid attacks in this case, and are only worried about data leak

We also assume USB key is kept securely, thus we are not concerned with USB key not being encrypted

Example disk layout used in this guide

  • /dev/sda - system disk as set up by Ubuntu installer

    • /dev/sda1 - /boot partition
    • /dev/sda2 - extended partition
    • /dev/sda5 - logical partition inside extended partition, / partition
  • /dev/sdb - USB key, to be be set up in this guide

Preliminaries

Ubuntu's use of /etc/crypttab

When setting up the kernel RAM images Ubuntu uses /etc/crypttab to derive what needs to be decrypted

This is different to Arch where you have to instead tell the kernel via boot parameters (e.g. via /etc/default/grub), and /etc/crypttab only comes into play after the system has been booted, and plays no role during kernel image generation

As a result, guides which utilise updating /etc/default/grub may not be very applicable on Ubuntu, or not as straightforward

/etc/crypttab format

Following shows the example /etc/crypttab used in this guide as generated by the Ubuntu installer

sda5_crypt UUID=6d479dcf-4819-4bd3-a617-c6b11779f526 none luks,discard

The file consists of four columns, and fields on each row are space separated

The meaning of four fields of each row is as follows

  • First field holds the mapper name (the mapped device name which shows up in /dev/mapper)
  • Second field holds the device identifier, where the file system UUID is the usual choice
    • File system UUID stays static throughout the lifespan of the file system, and is stable
    • This however means if you format the device, then you will need to update the UUID in config files accordingly
    • In this case, the UUID is set up by LUKS (think LUKS as file system in this case)
  • Third field holds the key authentication method, none means password authentication is used
    • We will modify this field later to utilise key file
  • Fourth field holds the options to be passed to LUKS
    • We will add one more option to allow usage of key file

Generating key file

Generating and transporting key file safely is difficult

It is usually not advisable to generate key file on live CD due to limited entropy, but if you decide to generate one on a trusted system, you also require an encrypted device to transport the key file safely (you cannot wipe most devices securely, so encrypted device should be considered a strict requirement)

In this example, we will just generate key file on live CD directly, but the rest of the procedures are the same should you decide to generate your own key file separately

We will use /dev/urandom to generate a 4096 bit key file sys.key via the following command

dd if=/dev/urandom of=sys.key bs=512 count=8

bs=512 means "set block size to 512 bytes". We picked 512 bytes as block size as sometimes block sizes too big will cause reads to fail.

count=8 just means we'll read from /dev/urandom at block size specified 8 times, totally 4096 bytes

Above gives us sys.key, which we'll use below

Setting up USB key

We will use a plain ext4 partition for the USB key

We only need the partition to be large enough to accommodate sys.key. You can use any partitioning techniques here, and format it to ext4

Afterwards, the partition should be accessible via path /dev/sdb1

Getting UUID of USB key

We will need to specify the path to sys.key in /etc/crypttab, where using UUID is again the most reliable option

To retrieve the UUID (or just the entire path in this case), we use ls -l /dev/disk/by-uuid which lists all partitions along with the linked path

# ls -l /dev/disk/by-uuid
total 0
lrwxrwxrwx 1 root root  9 Sep 28 12:51 2019-08-05-19-22-27-00 -> ../../sr0
lrwxrwxrwx 1 root root 10 Sep 28 12:51 68c3e2a2-5820-4531-8a3d-1a8671b965fa -> ../../dm-2
lrwxrwxrwx 1 root root 10 Sep 28 12:51 6d479dcf-4819-4bd3-a617-c6b11779f526 -> ../../sda5
lrwxrwxrwx 1 root root 10 Sep 28 12:51 aecf5d9c-971a-41ce-b5e4-f5807bad5379 -> ../../sda1
lrwxrwxrwx 1 root root 10 Sep 28 12:51 c3a06bff-1699-40ae-b159-ff3d0fc1b8b0 -> ../../dm-1
lrwxrwxrwx 1 root root 10 Sep 28 12:51 f4f6ca46-945d-47cf-8e33-040c3735d3ad -> ../../sdb1

We observe /dev/disk/by-uuid/f4f6ca46-945d-47cf-8e33-040c3735d3ad points to sdb1 which is the USB key, this gives us the path we will want to use in /etc/crypttab later

Installing the key file onto USB key

We will simply put the key file directly in the file system

mount /dev/sdb1 /mnt
cp sys.key /mnt
umount /mnt

Updating /etc/crypttab

We then update our /etc/crypttab so it becomes as follows

sda5_crypt UUID=6d479dcf-4819-4bd3-a617-c6b11779f526 /dev/disk/by-uuid/f4f6ca46-945d-47cf-8e33-040c3735d3ad:/sys.key luks,discard,keyscript=/lib/cryptsetup/scripts/passdev

Only the third and fourth field differ from the original file, which we'll examine below

  • Third field now reads /dev/disk/by-uuid/f4f6ca46-945d-47cf-8e33-040c3735d3ad:/sys.key, which is just path_to_device:file_sys_path_to_file
    • We obtained the path to device in above Getting UUID of USB key step
    • Path to the file is simply /sys.key as we copied sys.key into root of the USB key file system
  • Fourth field has keyscript=/lib/cryptsetup/scripts/passdev appended, this simply allows Ubuntu to use a device for key file purposes (I think)

Recreate kernel images

Kernel images are stored in /boot, and we'll use the mkinitramfs command to recreate the kernel image to utilise the new info we've supplied to /etc/crypttab

We can do so via the following command

# mkinitramfs -o /boot/initrd.img-$(uname -r) $(uname -r)

$(uname -r) gives us the current kernel release string of the current kernel we're using, which reads 5.0.0-23-generic in the example system used in this guide

Reboot

After the above procedure is done, you may reboot

Ubuntu should unlock the root partition without asking for a passphrase if the USB key is plugged in on the next boot

@andreyddk
Copy link

andreyddk commented Jun 24, 2021

Thank you, its work with debian buster.
But how prevent message after success unlock?

A start job is running for /dev/disk/by-uuid/XXXXX:/keyfile

I found solution)
Just need add to grub cmd
rd.luks.crypttab=yes luks.crypttab=no

Origin link

@meunomemauricio
Copy link

Awesome! @andreyddk answer solved my issue!

For future reference on how to update GRUB:

sudo vi /etc/default/grub

Add kernel boot parameter to:

GRUB_CMDLINE_LINUX_DEFAULT="quiet rd.luks.crypttab=yes luks.crypttab=no"

Update grub:

 sudo update-grub

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment