Booting encrypted system from USB stick
From Gentoo Linux Wiki
Contents |
[edit] Introduction
This article is a somewhat less exhaustive version of SECURITY System Encryption DM-Crypt with LUKS. It focuses on a very specific setup that involves an encrypted hard disk and a bootable USB stick. In order to keep things short, there will be no background information provided by this article. For such things, please refer to other sources (like the aforementioned exhaustive article). If you already know your way around Gentoo Linux, and you want a no-frills, do it yourself guide on how to encrypt your entire hard disk and boot it from an USB stick, this article may be of use to you.
[edit] Requirements
Before following this guide, make sure that you meet at least the following requirements:
- A fast machine.
- Gentoo is no fun on slow machines and it is especially not fun if the CPU has to work extra for encryption.
- You absolutely must have at least one working backup copy of all your data.
- Encrypting your hard disk can go horribly wrong, no matter how experienced you are. If you mess up, neither you nor anybody else will be able to recover any of your data. Without a backup, you will suffer from complete data loss. You've been warned.
- Your system should be able to boot from USB.
- Booting from USB is still somewhat shaky, as there is only very rudimentary support for USB in the booting stage, even on modern hardware. If your board does not wait long enough, or your stick does not respond fast enough, chances are that it just won't work. Please verify first that it actually works for you (by installing /boot, i.e. grub and kernel, on a stick and booting from it). Otherwise you'll have an encrypted hard disk later and nothing to boot from.
- Linux LiveCD/DVD or similar.
- Any Linux system will do, as long as it comes with a current kernel and support for LUKS and LVM.
From here on, this article will assume that you already booted the LiveDVD and are ready to go.
[edit] Encrypting the system
In this section, you will wipe, encrypt, and partition your entire hard disk. All examples will use /dev/sda as device name for the hard disk.
[edit] Wiping the hard disk
When you set up encryption on your disk later, sectors will be encrypted as they are written. This leaves out free space, so old data in free regions of your encrypted hard drive may still be accessible. By wiping the disk, you will make sure that there is no unencrypted data left on that disk that could be restored without knowing your password. This step is necessary if the hard disk you're encrypting already has your unencrypted data on it. If the disk is new, or does not contain any data of interest, you may skip to the next step, unless of course you prefer to wipe it anyway.
The fastest way
The fastest way to wipe your hard disk is to fill it with zeroes. It will utilize the full speed of your disk. While it is not possible to restore any data from it, free space on your encrypted hard disk will be visible as zeroes.
# The fastest way: dd if=/dev/zero of=/dev/sda bs=1M
You can make dd print out the current progress on stderr by sending it the USR1 signal:
killall -SIGUSR1 dd
The secure way
The secure way is to encrypt the disk with a random key and then fill the encrypted device with zeroes. Provided that the encryption cipher you use is any good, this will result in what looks like random data being written on your disk. It will utilize the full speed that is possible to achieve with encryption load on your system. Have a look at your CPU load while you do this so you can get an idea of how CPU demanding encryption will be on your system.
# Wipe the space that will be occupied by the LUKS header: dd if=/dev/zero of=/dev/sda bs=1M count=8 # Encrypt the hard disk, using any disposable password: cryptsetup luksFormat -c aes-xts-plain -s 256 /dev/sda cryptsetup luksOpen /dev/sda luks # The fastest way with encryption: dd if=/dev/zero of=/dev/mapper/luks bs=1M # Don't forget to clean up afterwards: cryptsetup luksClose luks
The useful way
You can also run a destructive badblocks test on your hard disk. In terms of security, it's no better than the fastest way, because it does not write really random data on the disk. It's also very slow. The only advantage of this method is that badblocks will test your hard disk for errors. The hard disk getting wiped in the process is just a side effect.
# Run a destructive badblocks test with random patterns: badblocks -w -t random -c 1024 -s /dev/sda
Other ways
In other guides, you will find mention of many other ways to wipe a hard disk. They usually involve /dev/urandom and/or shred. The downside of these methods is that they are slow as heck (10-100 times slower than any of the above) and they do not actually enhance anything in terms of security. Seriously, please don't do this, unless you have a lot of time to waste (on modern hard disks it will take a couple of days instead of just a couple of hours).
[edit] Setting up LUKS
Now you're going to put a layer of encryption on top of your hard disk. LUKS is one of the best tools for this task, as it makes things easy. You can have more than one password, and you can change them any time, allowing you to recover if you leak a password by accident. Everything that is necessary to unlock the encrypted disk is stored on the disk itself, so you can mount your data even from a LiveDVD. This means you're safe if your USB stick gets stolen and you can recover easily when it breaks.
To encrypt the hard disk using LUKS, you have to decide on a cipher, key size, and a password, and then format the disk with an appropriate LUKS header. The following example uses the aes-xts-plain cipher and a key size of 256, which is a good choice regarding both security and performance.
# Format the drive using LUKS: # This will ask you for the same password twice to make sure that you typed it correctly. cryptsetup luksFormat -c aes-xts-plain -s 256 -y /dev/sda # Verify that the command worked by having a look at part of the LUKS header: hexdump -n 256 -C /dev/sda # 00000000 4c 55 4b 53 ba be 00 01 61 65 73 00 00 00 00 00 |LUKS....aes.....|
Now the hard disk is encrypted (even though the only thing that changed is the header of the disk). In order to access the encrypted data, you have to open it using your password.
# Open the drive: # This will ask you for your password. cryptsetup luksOpen /dev/sda luks # Verify that the above command worked using fdisk: fdisk -l /dev/mapper/luks # Disk /dev/mapper/luks: 500.1 GB, 500107862016 bytes # Disk /dev/mapper/luks doesn't contain a valid partition table
And that's all you have to do for your encryption needs. Until you reboot, you can treat this LUKS device as if it was a hard disk, the encryption will be done transparently through it. Right now, this hard disk will seem to have random data on it, as it's not partitioned or formatted yet.
[edit] Setting up LVM
Before you can install Gentoo, you have to partition the drive. Old fashioned partitions are hard to maintain (especially if the drive itself is encrypted), so use LVM instead for the task. Logical volumes can be added, removed, and resized any time, making it easy to manage lots of partitions on huge hard disks. In combination with a file system like XFS that can be easily resized as well, you don't have to worry about correct partition sizes that much anymore.
# Initialize the encrypted hard disk for LVM: pvcreate /dev/mapper/luks # Create a volume group: vgcreate lvm /dev/mapper/luks
With this, LVM is ready to be used. Any partitions you create will now show up as /dev/lvm/partitionname. This simple example will only create a 10GB root and a 2GB swap partition. Of course, you can create your own partitioning scheme instead, with separate partitions for usr, var, opt, home and more. You'll have to mount them later for chrooting though, so you may want to wait until your system actually boots and mounts these things automatically.
# Make a root partition and format it as XFS: lvcreate -L 10G -n root lvm mkfs.xfs /dev/lvm/root # Make a swap partition and enable it: lvcreate -L 2G -n swap lvm mkswap /dev/lvm/swap swapon /dev/lvm/swap
Finally you have an encrypted hard disk with usable partitions and swap on it.
[edit] Taking a break
If you want to take a break after the encryption ordeal above, you can shut down your PC, and reboot your LiveDVD sometime later. However, to make your encrypted hard disk and LVM partitions visible to the system again, you first have to open the disk again and enable the LVM volumes on it afterwards. This is also how you can access your data using any bootable Linux media anytime, in case something breaks and you need to go in and rescue it.
# You only need to do this if you took a break and rebooted the LiveDVD. # Open the disk using your password: cryptsetup luksOpen /dev/sda luks # Scan and enable any LVM volumes: vgscan vgchange -a y
Now you can access your disk as /dev/mapper/luks and your partitions as /dev/lvm/* again and continue where you left off.
[edit] Installing Gentoo
Finally you can proceed to actually installing Gentoo on your hard disk. In order to do this, you first have to mount the root partition you created.
# Mount the root partition: mount /dev/lvm/root /mnt/gentoo
From here on, follow the standard Gentoo installation procedure: download a stage3 tarball, extract it, configure it, update it, until you would usually be ready to boot the system for the first time. If you're not installing Gentoo from scratch, this is the point where you have to copy your old working installation over to the new encrypted partitions, with minor modifications to /etc/fstab so it will find the LVM partitions when you boot it later.
Since your new system is based on LUKS and LVM, you will have to emerge the corresponding packages. Make sure to set your USE flags correctly: the LUKS and LVM tools must not be dynamically linked, because they will be used in the initramfs later. In baselayout-1, no additional configuration of the packages should be necessary, for baselayout-2, you may have to add their init scripts to runlevel boot.
USE="static -dynamic" emerge sys-apps/busybox sys-fs/cryptsetup sys-fs/lvm2 # Only if you are using baselayout-2: rc-update add lvm boot
With this, your system should be ready to use, except for the fact that it does not actually boot yet.
[edit] Preparing the USB stick
In order to boot your USB stick, you will need a kernel with an initramfs that contains all the necessary tools to open the disk and enable the LVM root partition. The kernel will be stored on the USB stick, and booted by GRUB. If you do not like to compile the kernel and build the initramfs manually, you can use genkernel instead. However, how to make genkernel actually work is beyond the scope of this document, so please refer to the genkernel documentation instead. The examples will use /dev/sdu as device name for the USB stick.
[edit] Building the initramfs
In this section you will learn the easy and straightforward way to initramfs creation. Actually, creating an initial ramdisk was quite complicated in the past, because you had to fiddle around with compressed archives and such. You don't need to do any of that in this guide, in the end it comes down to writing a shell script. You will be provided with a very simplistic one that should get you up and running, if you want more comfort, that is up to you and your shell scripting skills.
First, you have to create a directory that will later become your initramfs root. Since it's necessary for the kernel, just put it where the kernel sources are.
# Create initramfs root directory from inside the chroot mkdir /usr/src/initramfs cd /usr/src/initramfs # Create basic directory layout mkdir bin dev etc mnt proc root sbin sys # Add necessary device nodes, including the device for your hard disk cp -a /dev/console /dev/null /dev/sda dev/ # The busybox binary will provide basic shell and commands in the initramfs stage cp -a /bin/busybox bin/ # The cryptsetup binary will be used to open the disc cp -a /sbin/cryptsetup sbin/ # The lvm binary will be used to enable the logical volumes cp -a /sbin/lvm sbin/
With this, the file structure of the initramfs is almost complete. The only thing that is missing is init, an executable in the root of the ram disk, that is executed by the kernel once the ramdisk is loaded. The following example realizes this executable as a minimalistic shell script, based on the busybox shell.
| File: /usr/src/initramfs/init |
#!/bin/busybox sh # mount proc and sys mount -t proc none /proc mount -t sysfs none /sys # unlock the hard disk cryptsetup -T 5 luksOpen /dev/sda luks # make lvm volumes available lvm vgscan lvm vgchange -a y # mount the root filesystem mount -o ro /dev/lvm/root /root # clean up umount /proc umount /sys # boot the real thing exec switch_root /root /sbin/init |
Now make the init executable.
chmod +x init
Now you have a ready to use initramfs structure that will later be included into the kernel.
[edit] Configuring the kernel
If you do not have yet any kernel sources installed in /usr/src/linux, you should go and fetch the current version of the Linux kernel now and run make menuconfig. You need to enable the device mapper (used by both cryptsetup and lvm), cryptographic options (which ones depends on the cipher you're using), as well as support for initramfs integration. When you compile the kernel using make clean bzImage modules modules_install, it will automatically integrate the initramfs directory you created before into the kernel for you.
| Linux Kernel Configuration: General setup |
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support (/usr/src/initramfs/) Initramfs source file(s) (0) User ID to map to 0 (user root) (0) Group ID to map to 0 (group root) CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="/usr/src/initramfs/" |
| Linux Kernel Configuration: Multiple devices driver support (RAID and LVM) |
<*> Device mapper support [ ] Device mapper debugging support <*> Crypt target support CONFIG_BLK_DEV_DM=y # CONFIG_DM_DEBUG is not set CONFIG_DM_CRYPT=y |
| Linux Kernel Configuration: Cryptographic API |
<*> SHA1 digest algorithm <*> SHA224 and SHA256 digest algorithm <*> XTS support (EXPERIMENTAL) <*> AES cipher algorithms CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_XTS=y CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_X86_64=y |
[edit] Installing GRUB
In this section, you will create the boot partition on your USB stick, and make it boot using GRUB.
You'll have to create the partition that will be later used for storing GRUB and kernel images. GRUB is around 1MB, kernel around 5MB, so even a very small partition will get you going. However, unless you're actually trying to boot from a stone age 16MB USB stick, you should make the partition a lot bigger for comfort, so you can have more than just one kernel and maybe even additional software like memtest86 on it. If you have a really big stick, you could even add the Gentoo LiveDVD as a rescue system to it later.
# In this example, /dev/sdu is the USB stick. # Create a bootable primary partition using cfdisk, 128MB in size: cfdisk /dev/sdu # Format the boot partition mkfs.ext2 /dev/sdu1 # Label the boot partition e2label /dev/sdu1 boot_stick # The label may only be detected when you reconnect the USB stick.
Since hot pluggable devices get a different device name every time, it can be hard to identify the boot partition properly. This problem is avoided by giving the ext2 file system an unique label. When plugging in the USB stick, you should be able to access the correct device as /dev/disk/by-label/boot_stick. You can also create a proper fstab entry for your boot partition, which allows it to be mounted properly later.
| File: /mnt/gentoo/etc/fstab |
# <fs> <mountpoint> <type> <opts> <dump/pass> LABEL=boot_stick /boot ext2 noauto,noatime 1 2 |
Now you can mount boot and install grub onto it.
# Mount the boot partition. mount LABEL=boot_stick /mnt/gentoo/boot # Create a boot -> . symlink ln -s . /mnt/gentoo/boot/boot # Run grub-install. grub-install --root-directory=/mnt/gentoo/boot /dev/sdu # Create a menu.lst -> grub.conf symlink ln -s grub.conf /mnt/gentoo/boot/grub/menu.lst
Of course, you have to create the grub.conf itself for grub to know what it is supposed to boot. The following example is sufficient for booting a kernel with integrated ram disk, like the one you compiled earlier.
| File: /mnt/gentoo/boot/grub.conf |
timeout 30 default 0 title=Gentoo Linux (2.6.25.4) root (hd0,0) kernel /bzImage-2.6.25.4 |
Don't forget to copy the kernel image and System.map onto the USB key.
cp System.map /boot/System.map-2.6.25.4 cp arch/x86_64/boot/bzImage /boot/bzImage-2.6.25.4
[edit] Booting the encrypted system
Exit the chroot, umount all disks, cross your fingers and reboot. GRUB from the USB stick should come up, load the kernel, prompt you for the LUKS password, and boot the system you just installed. If it does not work, find out what's wrong and fix it. The following section lists some common errors and how to solve them.
[edit] Troubleshooting
While there is no room for a fully fledged troubleshooting section in this article, maybe we can offer simple solutions to the most common problems here.
- I'm getting GRUB error 16, 17, 25
- A possible cause is that booting from USB does not work reliably with your hardware. Try another USB stick, try attaching it directly to one of the boards USB ports instead of going through a front panel / hub or similar.
- LUKS says my password is wrong
- If you can't unlock it from the LiveDVD again either, chances are that you forgot your password. If it works from the LiveDVD, your kernel is lacking device mapper / cryptographic API support. Another possibility is that you are using a keyboard layout different from US english while in your LiveDVD, but you are required to type it with an US english keyboard when rebooting. You can avoid this problem by adding both passwords to LUKS (pressing the same keys, once in your native layout, and once in the US layout, so both passwords will be valid).
- I'm getting a kernel panic because init was killed
- There is something wrong with your init script then. If you can't find out what it is, make it drop you to an interactive shell busybox --install -s; exec sh and investigate. If that does not work either, then the init of your initramfs may not be even executed. This may be due to a wrong path in your kernel config, a missing executable flag, or because the binaries you put in your initramfs are not statically linked.
- The stick is plugged in and shows up as /dev/disk/by-label/boot_stick, but mount says the device does not exist.
- This is a bug which will hopefully be fixed soon, see http://bugs.gentoo.org/show_bug.cgi?id=225669 for details and a hackish workaround.
[edit] Addendum
The following topics go far beyond the scope of this article, but maybe they can give you some directions and ideas.
- Batten down the hatches
- The easiest way to get at encrypted data is hacking or simply accessing the system while it is running. So don't give others carelessly access to your machine via SSH, and don't go away from your machine without locking the screen and keyboard with a password first. There are many ways to lock down your system properly, think about which ones are useful, required, and simple to implement to fit your needs.
- Backups
- If your data is important enough for you to encrypt it, you will also want to protect against data loss due to hardware failure or human error. If you encrypted your hard disk because it's a laptop and you don't want a thief to be able to access your data, it's probably fine to have unencrypted backups at home. If you're worried about the security of your data in general, all copies of your data will have to be encrypted as well. Encryption methods depend on your backup media; for hard disks you can use LUKS as shown in this article, for read-only devices like CD/DVD-R there are better solutions.
- Live or Rescue System
- Since you are already booting from USB, if your stick has some capacity (>=1GB), consider adding a Linux LiveCD/DVD of your choice to it. It will make your USB stick more useful than it is already, because you can use it with more than only one machine, and in case something goes wrong on your own system, you can use it as a rescue system to boot and repair from.
Concerns or Compliments? Please use the Discussion section.
