Devin Reade

GNO Consortium | Home | GNO/ME

Public Projects | System Administration | General Computing | Parallel Computing | Compilers | Linux

Cryptography and Security | Physics Resources

Other Pages of Interest

Up


CentOS/RedHat 5.4+ Full-Disk Encryption With a USB Key Device

This page is only applicable to CentOS/RHEL 5.4 and later. Equivalent instructions are available for CentOS/RHEL 5.0 to 5.3 and 6.5+.

Introduction

As of CentOS 5.4, the default installation now allows one to use encrypted disks. If you have encrypted devices, you will be prompted at boot time for your LUKS passphrase.

This is perfect for laptop users, but crypto is sometimes desired in other situations as well where you might not necessarily want to be typing in a passphrase. This page documents a method by which you can place a second LUKS key on a USB stick to boot your machine. Note that if an antagonist gets both your USB stick and disk, your data is compromised.

This mechanism is designed to fail safe: If you don't have the USB stick, or if the patched mkinitrd gets overwritten (and not noticed), or if you have to boot from CD/DVD, then you will be prompted for the original LUKS key, which is a whole lot better than saying "oops ... too bad". (In this way, the current mechanism is more robust than the pre-CentOS-5.4 method.)


Technical Overview

This procedure assumes that you have already performed a fresh install of CentOS 5.4+ where:

  1. There is a single disk (this procedure also works with mirrored disks).
  2. /boot is unencrypted
  3. The remaining disk is encrypted, and contains the LVM physical volume vg1. We will further assume for this example that /boot is on /dev/sda1 and vg1 is on /dev/sda2. (If you were using mirroring it might be, for example, /dev/md0 and /dev/md1.
    Figure 1
  4. Swap and the remaining filesystems were created as LVM logical volumes on vg1
  5. The OS is currently prompting for the LUKS passphrase during boot.
  6. You will be using VFAT-formatted USB device for your LUKS key. This is the most common format for USB key fobs and similar devices.

The procedure is outlined as follows:

  1. Preparation
  2. Setup the USB Device
  3. Patch mkinitrd
  4. Configure mkinitrd
  5. Build New Initial Ramdisk
  6. Test the result


Preparation

You will be modifying your boot procedure. While this should be benign, you should be paranoid, especially since your data is already encrypted. Take some time to be paranoid.

  1. Unless you have a virgin system containing no useful information, back up your system before you start.

  2. If you have automated system updates enabled, disable them during this procedure.

  3. Next, you should configure a copy of your existing (working) initrd. This will allow you, during the testing phase, a boot mechanism should something go wrong. (You can delete the copy later.)

    If you're using the Grub bootloader, then edit your /etc/grub.conf file. Duplicate one of the entries, changing the entry title and the name of the initrd image. Make sure create a copy of the initrd image to match the modified name.

    Reboot your system with your backup bootloader configuration to make sure it works.


Setup the USB Device

You should now set up your USB device that will hold the LUKS key.

  1. Attach the USB device to your machine. Your dmesg output and /var/log/messages should show the device attach, and you should be able to determine the device name. You should see something like the following:

        SCSI device sdc: 3940479 512-byte hdwr sectors (2018 MB)
        sdc: Write Protect is off
        sdc: Mode Sense: 45 00 00 08
        sdc: assuming drive cache: write through
        
    In this case, the device is /dev/sdc and the FAT partition that will contain our crypto key is /dev/sdc1

  2. Because the sd device names can get dynamically renamed under some circumstances, you need to be able to identify the USB device in some other fashion. Because of the limited environment that is available at boot time, practically this means that you will need to give your USB device a label.

    You can see if your USB device already has a label via the blkid command. Continuing with our example:

        # blkid /dev/sdc1
        /dev/sdc1: SEC_TYPE="msdos" UUID="AB12-34CD" TYPE="vfat"
        
    If there is no LABEL output from the above command (or if you would prefer a different label), you can use the mlabel command to set it:
        mlabel -i /dev/sdc1 ::luks_key
        
    The choice of label is arbitrary; you need only later configure mkinitrd to use the same label. Note that the above usage of mlabel, while valid, is not documented in the mlabel man page.

    You should now see the new label (which will be upper-cased):

        # blkid /dev/sdc1
        /dev/sdc1: SEC_TYPE="msdos" UUID="AB12-34CD" TYPE="vfat" LABEL="LUKS_KEY"
        

  3. Temporarily mount the USB device somewhere appropriate:

        mount /dev/sdc1 /mnt
        
    or
        mkdir -p /flash/key
        mount /dev/sdc1 /flash/key
        
    If you'd like to have an entry in your /etc/fstab file, you should use the device label, ID or UID to identify it, because of the sd dynamic rename problem. I'd also suggest setting a restrictive umask and not automounting it:
        /dev/disk/by-label/LUKS_KEY /flash/key  vfat  noatime,umask=0377,noauto  0 0
        

  4. Now create a file that will contain the LUKS key. Again the file name is arbitrary (as long as it later matches the mkinitrd configuration). The content of the file is also arbitrary, but it should follow the usual conventions for good, strong, passphrases. Since you will likely never type in this passphrase, you can use a randomly generated one:

        dd if=/dev/random bs=1 count=32 | od -An -t x4 -w32 | perl -pe 's,\n,,;' > /flash/key/luks.key
        
    The reason for the perl command above is to ensure that the key is all on one line, in the unlikely event that you have to ever type it in. See the discussion of the --key-file in the cryptsetup(8) man page for details.

  5. Add the new key to your encrypted device:

        cryptsetup luksAddKey /dev/sda2 /flash/key/luks.key
        
    Where /dev/sda2 is the encrypted device holding vg1. You will be asked for your existing passphrase, twice. You should now see two keys in the LUKS header:
        cryptsetup luksDump /dev/sda2
        


Patch mkinitrd

The stock mkinitrd(8), when unlocking LUKS devices, assumes that doing so will always be interactive. In order to have the key to be taken from a device such as a USB fob, it is necessary to patch mkinitrd(8)

Download the mkinitrd.patch file, and apply it:

    cd /sbin
    patch -b -p0 < mkinitrd.patch
This will leave the original as mkinitrd.orig.

Next, we want to know if a system update or anything else undoes the patch. To monitor this, download check-mkinitrd, chmod it 0755, and place it in /etc/cron.daily. (Note that there is a different version of this file for CentOS 5.3 and earlier in other directories of that FTP site — make sure you're getting the correct version as specified above.)


Configure mkinitrd

Unless you configure the newly patched mkinitrd, it will behave the same way as the stock one (this is a fail-safe behavior).

First, create the config file with appropriate permissions:

    touch /etc/sysconfig/mkinitrd/usb-crypto-key
    chmod 0755 /etc/sysconfig/mkinitrd/usb-crypto-key
Then edit it so that it contains the following variables. The values must match those you selected when you labelled your USB device and created the key file:
    CRYPTO_KEY_DEVICE="LABEL=LUKS_KEY"
    CRYPTO_KEY_FILESYSTEM="vfat"
    CRYPTO_KEY_MOUNT_POINT="/flash/key"
    CRYPTO_KEY_FILE="$CRYPTO_KEY_MOUNT_POINT/luks.key"

    MODULES="$MODULES usb-storage vfat"
The mount point does not necessarily need to match; mkinitrd will create it if necessary. If you have the USB device listed in your /etc/fstab file, keeping the same mount point may cause less confusion, though.

If you prefer, you can instead download a sample usb-crypto-key file and edit it appropriately for your machine.


Build New Initial Ramdisk

Before you do this step, you've already configured a backup bootloader entry, right?

After performing all the steps above, you're now ready to create your new initial ram disk. Assuming you're building it for the currently running kernel, issue the following command:

    mkinitrd -f /boot/initrd-`uname -r`.img `uname -r`
There should not be any errors or other output.


Test the Result

Test by rebooting your machine a couple of times:

  1. If the USB device is attached, it should boot without intervention.
  2. If the USB device is not attached, then you should be prompted for your passphrase (you can use the LUKS passphrase you used when doing the initial install; you do not need to memorize what is on the USB device).

If you have problems, then boot using your backup bootloader entry and go splunking. If you have problems with the backup bootloader, you can boot the DVD/CD in rescue mode.

After you're finished testing, don't forget to reenable your automated updates, if you had previously disabled them.


Contact Me

Up

Last Updated: 22 May 2014