Encrypted Root Filesystem HOWTO

Christophe Devine

Revision History                                                             
Revision v1.1            2003-12-01            Revised by: cd                
Added support for GRUB.                                                      
Revision v1.0            2003-09-24            Revised by: cd                
Initial release, reviewed by LDP.                                            
Revision v0.9            2003-09-11            Revised by: cd                
Updated and converted to DocBook XML.                                        


This document explains how to make your personal data secure by encrypting
your Linux root filesystem using strong cryptography.

This HOWTO is released under the GNU Free Documentation License Version 1.2.

-----------------------------------------------------------------------------
Table of Contents
1. Preparing the system
    1.1. Setting up the partition layout
    1.2. Installing Linux-2.4.23
    1.3. Installing util-linux-2.12
   
   
2. Creating the encrypted root filesystem
3. Setting up the boot device
    3.1. Creating the ramdisk
    3.2. Booting with a CD-ROM
    3.3. Booting from a partition
   
   
4. Final steps
5. About this HOWTO

1. Preparing the system

1.1. Setting up the partition layout

Your hard disk (hda) should contain at least three partitions:

*hda1: this small (~4 Mb) unencrypted partition will ask for a password in
    order to mount the encrypted root filesystem.
   
*hda2: this partition will contain your encrypted root filesystem; make
    sure it is large enough.
   
*hda3: this partition holds the current GNU/Linux system.
   

At this point, both hda1 and hda2 are unused. hda3 is where your Linux
distribution is currently installed; /usr and /boot must not be separated
from this partition.
-----------------------------------------------------------------------------

1.2. Installing Linux-2.4.23

There are two main projects which add strong crypto support in the kernel:
CryptoAPI and loop-AES. This howto is based on loop-AES, since it has an
extremely fast and highly optimized implementation of Rijndael in assembly
language, and therefore provides maximum performance if you have an IA-32
(x86) CPU.

First of all, download and unpack the loop-AES package:

+---------------------------------------------------------------------------+
|wget http://loop-aes.sourceforge.net/loop-AES/loop-AES-v2.0b.tar.bz2       |
|tar -xvjf loop-AES-v2.0b.tar.bz2                                           |
+---------------------------------------------------------------------------+

Then you must download and patch the kernel source:

+---------------------------------------------------------------------------+
|wget http://ftp.kernel.org/pub/linux/kernel/v2.4/linux-2.4.23.tar.bz2      |
|tar -xvjf linux-2.4.23.tar.bz2                                             |
|cd linux-2.4.23                                                            |
|patch -Np1 -i ../loop-AES-v2.0b/kernel-2.4.23.diff                         |
+---------------------------------------------------------------------------+

Setup the keyboard map:

+---------------------------------------------------------------------------+
|dumpkeys | loadkeys -m - > drivers/char/defkeymap.c                        |
+---------------------------------------------------------------------------+

Next, configure your kernel; make sure the following options are set:

+---------------------------------------------------------------------------+
|make menuconfig                                                            |
|                                                                           |
|    Block devices  --->                                                    |
|                                                                           |
|        <*> Loopback device support                                        |
|        [*]   AES encrypted loop device support (NEW)                      |
|                                                                           |
|        <*> RAM disk support                                               |
|        (4096)   Default RAM disk size (NEW)                               |
|        [*]   Initial RAM disk (initrd) support                            |
|                                                                           |
|    File systems  --->                                                     |
|                                                                           |
|        <*> Ext3 journalling file system support                           |
|        <*> Second extended fs support                                     |
|                                                                           |
|(important note: do not enable /dev file system support)                   |
+---------------------------------------------------------------------------+

Compile the kernel and install it:

+---------------------------------------------------------------------------+
|make dep bzImage                                                           |
|make modules modules_install                                               |
|cp arch/i386/boot/bzImage /boot/vmlinuz-2.4.23                             |
+---------------------------------------------------------------------------+

If grub is your bootloader, update /boot/grub/menu.lst or /boot/grub/
grub.conf:

+---------------------------------------------------------------------------+
|cat > /boot/grub/menu.lst << EOF                                           |
|default 0                                                                  |
|timeout 10                                                                 |
|color green/black light-green/black                                        |
|title Linux                                                                |
|    root (hd0,2)                                                           |
|    kernel /boot/vmlinuz-2.4.23 ro root=/dev/hda3 vga=4                    |
|EOF                                                                        |
+---------------------------------------------------------------------------+

Otherwise, update /etc/lilo.conf and run lilo:

+---------------------------------------------------------------------------+
|cat > /etc/lilo.conf << EOF                                                |
|lba32                                                                      |
|boot=/dev/hda                                                              |
|prompt                                                                     |
|timeout=100                                                                |
|image=/boot/vmlinuz-2.4.23                                                 |
|    label=Linux                                                            |
|    read-only                                                              |
|    root=/dev/hda3                                                         |
|    vga=4                                                                  |
|EOF                                                                        |
|lilo                                                                       |
+---------------------------------------------------------------------------+

You may now restart the system.
-----------------------------------------------------------------------------

1.3. Installing util-linux-2.12

The losetup program, which is part of the util-linux package, must be patched
and recompiled in order to add strong cryptography support. Download, unpack
and patch util-linux:

+---------------------------------------------------------------------------+
|wget http://ftp.cwi.nl/aeb/util-linux/util-linux-2.12.tar.gz               |
|tar -xvzf util-linux-2.12.tar.gz                                           |
|cd util-linux-2.12                                                         |
|patch -Np1 -i ../loop-AES-v2.0b/util-linux-2.12.diff                       |
+---------------------------------------------------------------------------+

To use passwords that are less than 20 characters, enter:

+---------------------------------------------------------------------------+
|CFLAGS="-O2 -DLOOP_PASSWORD_MIN_LENGTH=8"; export CFLAGS                   |
+---------------------------------------------------------------------------+

If security is important, please do not enable passwords shorter than 20
characters. Security is not free, one has to 'pay' in form of long passwords.

Compile losetup and install it as root:

+---------------------------------------------------------------------------+
|./configure && make lib mount                                              |
|cp -f mount/losetup /sbin                                                  |
|rm -f /usr/share/man/man8/losetup.8.gz                                     |
|cp -f mount/losetup.8 /usr/share/man/man8                                  |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

2. Creating the encrypted root filesystem

Fill the target partition with random data:

+---------------------------------------------------------------------------+
|shred -n 1 -v /dev/hda2                                                    |
+---------------------------------------------------------------------------+

Setup the encrypted loopback device:

+---------------------------------------------------------------------------+
|losetup -e aes256 -S xxxxxxxxxx /dev/loop0 /dev/hda2                       |
|Password:                                                                  |
+---------------------------------------------------------------------------+

To prevent optimized dictionary attacks, it is recommended to add the -S
xxxxxxxxxx option, where "xxxxxxxxxx" is your randomly chosen seed. Also, in
order to avoid boot-time problems with the keyboard map, do not use non-ASCII
characters (accents, etc.) in your password.

Now create the ext3 filesystem:

+---------------------------------------------------------------------------+
|mke2fs -j /dev/loop0                                                       |
+---------------------------------------------------------------------------+

Check that you correctly entered the password:

+---------------------------------------------------------------------------+
|losetup -d /dev/loop0                                                      |
|losetup -e aes256 -S xxxxxxxxxx /dev/loop0 /dev/hda2                       |
|Password:                                                                  |
+---------------------------------------------------------------------------+

+---------------------------------------------------------------------------+
|mkdir /mnt/efs                                                             |
|mount /dev/loop0 /mnt/efs                                                  |
+---------------------------------------------------------------------------+

You can compare the encrypted and unencrypted data:

+---------------------------------------------------------------------------+
|xxd /dev/hda2  | less                                                      |
|xxd /dev/loop0 | less                                                      |
+---------------------------------------------------------------------------+

It's time to install your encrypted Linux system. If you use a GNU/Linux
distribution (such as Debian, Slackware, Gentoo, Mandrake, RedHat/Fedora,
SuSE, etc.), run the following command:

+---------------------------------------------------------------------------+
|cp -avx / /mnt/efs                                                         |
+---------------------------------------------------------------------------+

If you use the Linux From Scratch book, proceed as described in the manual,
with the modifications below:

*Chapter 6 - Installing util-linux:
   
    Apply the loop-AES patch after unpacking the sources.
   
*Chapter 8 - Making the LFS system bootable:
   
    Refer to the next section.
   

-----------------------------------------------------------------------------
3. Setting up the boot device

3.1. Creating the ramdisk

To begin with, chroot inside the encrypted partition and create the boot
device mount point:

+---------------------------------------------------------------------------+
|chroot /mnt/efs                                                            |
|mkdir /loader                                                              |
+---------------------------------------------------------------------------+

Then, create the initial ramdisk (initrd), which will be needed afterwards:

+---------------------------------------------------------------------------+
|cd                                                                         |
|dd if=/dev/zero of=initrd bs=1k count=4096                                 |
|mke2fs -F initrd                                                           |
|mkdir ramdisk                                                              |
|mount -o loop initrd ramdisk                                               |
+---------------------------------------------------------------------------+

Create the filesystem hierarchy and copy the required files in it:

+---------------------------------------------------------------------------+
|mkdir ramdisk/{bin,dev,lib,mnt,sbin}                                       |
|cp /bin/{bash,mount,umount} ramdisk/bin/                                   |
|ln -s bash ramdisk/bin/sh                                                  |
|mknod -m 600 ramdisk/dev/console c 5 1                                     |
|mknod -m 600 ramdisk/dev/hda2    b 3 2                                     |
|mknod -m 600 ramdisk/dev/loop0   b 7 0                                     |
|cp /lib/{ld-linux.so.2,libc.so.6,libdl.so.2} ramdisk/lib/                  |
|cp /lib/{libncurses.so.5,libtermcap.so.2}    ramdisk/lib/                  |
|cp /sbin/{losetup,pivot_root} ramdisk/sbin/                                |
+---------------------------------------------------------------------------+

It's ok if you see a message like "/lib/libncurses.so.5: No such file or
directory", or "/lib/libtermcap.so.2: No such file or directory"; bash only
requires one of these two libraries. You can check which one is actually
needed with:

+---------------------------------------------------------------------------+
|ldd /bin/bash                                                              |
+---------------------------------------------------------------------------+

Create the init script (don't forget to replace "xxxxxxxxxx" with your chosen
seed):

+---------------------------------------------------------------------------+
|cat > ramdisk/sbin/init << "EOF"                                           |
|#!/bin/sh                                                                  |
|                                                                           |
|/sbin/losetup -e aes256 -S xxxxxxxxxx /dev/loop0 /dev/hda2                 |
|/bin/mount -r -n -t ext2 /dev/loop0 /mnt                                   |
|                                                                           |
|while [ $? -ne 0 ]                                                         |
|do                                                                         |
|    /sbin/losetup -d /dev/loop0                                            |
|    /sbin/losetup -e aes256 -S xxxxxxxxxx /dev/loop0 /dev/hda2             |
|    /bin/mount -r -n -t ext2 /dev/loop0 /mnt                               |
|done                                                                       |
|                                                                           |
|cd /mnt                                                                    |
|/sbin/pivot_root . loader                                                  |
|exec /usr/sbin/chroot . /sbin/init                                         |
|EOF                                                                        |
|                                                                           |
|chmod 755 ramdisk/sbin/init                                                |
+---------------------------------------------------------------------------+

Umount the loopback device and compress the initrd:

+---------------------------------------------------------------------------+
|umount -d ramdisk                                                          |
|rmdir ramdisk                                                              |
|gzip initrd                                                                |
|mv initrd.gz /boot/                                                        |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

3.2. Booting with a CD-ROM

I strongly advise you to start your system with a read-only media, such as a
bootable CD-ROM.

Download and unpack syslinux:

+-----------------------------------------------------------------------------+
|wget ftp://ftp.kernel.org/pub/linux/utils/boot/syslinux/syslinux-2.07.tar.gz |
|tar -xvzf syslinux-2.07.tar.gz                                               |
+-----------------------------------------------------------------------------+

Configure isolinux:

+---------------------------------------------------------------------------+
|mkdir bootcd                                                               |
|cp /boot/vmlinuz-2.4.23 bootcd/vmlinuz                                     |
|cp /boot/initrd.gz syslinux-2.07/isolinux.bin bootcd/                      |
|echo "DEFAULT vmlinuz initrd=initrd.gz ro root=/dev/ram0 vga=4" \          |
|    > bootcd/isolinux.cfg                                                  |
+---------------------------------------------------------------------------+

Create and burn the bootable cd-rom iso image:

+---------------------------------------------------------------------------+
|mkisofs -o bootcd.iso -b isolinux.bin -c boot.cat \                        |
|        -no-emul-boot -boot-load-size 4 -boot-info-table \                 |
|        -J -hide-rr-moved -R bootcd/                                       |
|                                                                           |
|cdrecord -dev 0,0,0 -speed 4 -v bootcd.iso                                 |
|                                                                           |
|rm -rf bootcd{,.iso}                                                       |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

3.3. Booting from a partition

The boot partition is an alternate boot device: you might need it if your
bootable CD gets lost. Remember that hda1 is a writable media and is thus
insecure; use it only in case of emergency!

Create and mount the ext2 filesystem:

+---------------------------------------------------------------------------+
|dd if=/dev/zero of=/dev/hda1 bs=8192                                       |
|mke2fs /dev/hda1                                                           |
|mount /dev/hda1 /loader                                                    |
+---------------------------------------------------------------------------+

Copy the kernel and the initial ramdisk:

+---------------------------------------------------------------------------+
|cp /boot/vmlinuz-2.4.23 /loader/vmlinuz                                    |
|cp /boot/initrd.gz /loader/                                                |
+---------------------------------------------------------------------------+

If you use grub:

+---------------------------------------------------------------------------+
|mkdir /loader/boot                                                         |
|cp -av /boot/grub /loader/boot/                                            |
|cat > /loader/boot/grub/menu.lst << EOF                                    |
|default 0                                                                  |
|timeout 10                                                                 |
|color green/black light-green/black                                        |
|title Linux                                                                |
|    root (hd0,0)                                                           |
|    kernel /vmlinuz ro root=/dev/ram0 vga=4                                |
|    initrd /initrd.gz                                                      |
|EOF                                                                        |
|grub-install --root-directory=/loader /dev/hda                             |
|umount /loader                                                             |
+---------------------------------------------------------------------------+

If you use lilo:

+---------------------------------------------------------------------------+
|mkdir /loader/{boot,dev,etc}                                               |
|cp /boot/boot.b /loader/boot/                                              |
|mknod -m 600 /loader/dev/hda  b 3 0                                        |
|mknod -m 600 /loader/dev/hda1 b 3 1                                        |
|mknod -m 600 /loader/dev/ram0 b 1 0                                        |
|cat > /loader/etc/lilo.conf << EOF                                         |
|lba32                                                                      |
|boot=/dev/hda                                                              |
|prompt                                                                     |
|timeout=100                                                                |
|image=/vmlinuz                                                             |
|    label=Linux                                                            |
|    initrd=/initrd.gz                                                      |
|    read-only                                                              |
|    root=/dev/ram0                                                         |
|    vga=4                                                                  |
|EOF                                                                        |
|lilo -r /loader                                                            |
|umount /loader                                                             |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

4. Final steps

Modify /etc/fstab so that it contains:

+---------------------------------------------------------------------------+
|/dev/loop0      /      ext3    defaults             0 1                    |
+---------------------------------------------------------------------------+

Remove /etc/mtab and exit from chroot. Finally, run "umount -d /mnt/efs" and
reboot. hda3 is not needed anymore, so you can create an encrypted filesystem
on this partition and use it as a backup.

Now, if you're low on RAM you'll need some swap space. Let's suppose hda4
will hold your encrypted swap partition; you must create the swap device
first:

+---------------------------------------------------------------------------+
|shred -n 1 -v /dev/hda4                                                    |
|losetup -e aes256 /dev/loop1 /dev/hda4                                     |
|mkswap /dev/loop1                                                          |
+---------------------------------------------------------------------------+

Then create a script (S00swap) in the system startup directory (/etc/rcS.d/
under Debian):

+---------------------------------------------------------------------------+
|#!/bin/sh                                                                  |
|                                                                           |
|echo "password chosen above" | \                                           |
|    losetup -p 0 -e aes256 /dev/loop1 /dev/hda4                            |
|swapon /dev/loop1                                                          |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

5. About this HOWTO

The Encrypted Root Filesystem HOWTO was first written in november 2002 for
the [http://www.linuxfromscratch.org/lfs/news.html] Linux From Scratch
project. I'd like to thank the many people who have since helped me improve
this howto (in reverse chronological order): Julien Perrot, Grant Stephenson,
Cary W. Gilmer, James Howells, Pedro Baez, Josh Purinton, Jari Ruusu and
Zibeli Aton.

Please send any comment to [http://www.cr0.net:8040/about/] Christophe
Devine.
