Search:  
Gentoo Wiki

Booting_encrypted_system_from_USB_stick

Contents

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.

Requirements

Before following this guide, make sure that you meet at least the following requirements:

Gentoo is no fun on slow machines and it is especially not fun if the CPU has to work extra for encryption.
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.
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.
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.

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.

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.

Note: Wiping a modern hard disk may take a couple of hours due to sheer size.
Warning: It is impossible to recover any data from a wiped disk. Use with caution.

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).

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.

Note: The easiest way to attack your data is to guess your password, so make sure it's a good one.
Warning: If you forget your password, all data will be lost, so make sure you remember it well.

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.

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.

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.

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.

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.

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.

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
Note: Depending on which cipher you are using and which architecture you are on, you may have to deviate from these settings a little.
Warning: Modules required for booting have to be put into and loaded by the initramfs, which is complicated, so don't make them modules.

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

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.

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.

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.
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).
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.
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.

Addendum

The following topics go far beyond the scope of this article, but maybe they can give you some directions and ideas.

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.
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.
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.

Retrieved from "http://www.gentoo-wiki.info/Booting_encrypted_system_from_USB_stick"

Last modified: Thu, 02 Oct 2008 22:49:00 +0000 Hits: 4,881