Encrypted Root Filesystem HOWTO

Christophe Devine

Revision History                                                             
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 brief 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. Setting up the partition layout
2. Enabling strong crypto in your system
    2.1. Installing Linux-2.4.22
    2.2. Installing util-linux-2.12pre
   
   
3. Creating the encrypted root filesystem
4. Installing your encrypted Linux system
    4.1. If you use a GNU/Linux distribution
    4.2. If you use the Linux From Scratch book
   
   
5. Setting up the boot device
    5.1. Creating the ramdisk
    5.2. Setting up the boot partition
    5.3. Booting with a CD-ROM
   
   
6. Setting up the bootscripts
7. About this HOWTO

1. Setting up the partition layout

Your hard disk (hda) should have 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 encrypted partition will contain your root filesystem.
   
*hda3: this partition holds the current GNU/Linux system.
   

-----------------------------------------------------------------------------
2. Enabling strong crypto in your system

2.1. Installing Linux-2.4.22

There are two main projects which add strong crypto support in the kernel:
CryptoAPI and loop-aes. This howto uses 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 kernel sources:

[ftp://ftp.kernel.org/pub/linux/kernel/v2.4/linux-2.4.22.tar.bz2] ftp://
ftp.kernel.org/pub/linux/kernel/v2.4/linux-2.4.22.tar.bz2

You also have to download and unpack:

[http://loop-aes.sourceforge.net/loop-AES/loop-AES-v1.7e.tar.bz2] http://
loop-aes.sourceforge.net/loop-AES/loop-AES-v1.7e.tar.bz2

Then you must patch the kernel:

+---------------------------------------------------------------------------+
|linux-2.4.22 $ patch -Np1 -i ../loop-AES-v1.7e/kernel-2.4.22.diff          |
+---------------------------------------------------------------------------+

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

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

Setup the keyboard map:

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

Compile the kernel, install it and reboot.
-----------------------------------------------------------------------------

2.2. Installing util-linux-2.12pre

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

Download and unpack:

[http://ftp.cwi.nl/aeb/util-linux/util-linux-2.12pre.tar.gz] http://
ftp.cwi.nl/aeb/util-linux/util-linux-2.12pre.tar.gz

cd into util-linux-2.12pre and apply this patch:

+---------------------------------------------------------------------------+
|$ patch -Np1 -i ../loop-AES-v1.7e/util-linux-2.12pre.diff                  |
+---------------------------------------------------------------------------+

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

+---------------------------------------------------------------------------+
|$ CFLAGS="-O2 -DLOOP_PASSWORD_MIN_LENGTH=12"; 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 mount/losetup /sbin                                                   |
|# rm -f /usr/share/man/man8/losetup.8.gz                                   |
|# cp mount/losetup.8 /usr/share/man/man8                                   |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

3. 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 aes128 -S xxxxxxxxxx /dev/loop0 /dev/hda2                     |
+---------------------------------------------------------------------------+

For better security, it is recommended to use the -S xxxxxxxxxx option, where
"xxxxxxxxxx" is your (randomly) chosen seed. This prevents optimized
dictionary attacks.

Also, note that using 256-bit AES would not be any more secure, since even
128-bit AES is impossible to crack by brute-force. Furthermore, AES-256 is
about 25% slower than AES-128.

Now create the ext2 (or ext3 or reiserfs) filesystem:

+---------------------------------------------------------------------------+
|# mke2fs /dev/loop0                                                        |
+---------------------------------------------------------------------------+

Check that you correctly entered the password:

+---------------------------------------------------------------------------+
|# losetup -d /dev/loop0                                                    |
|# losetup -e aes128 -S xxxxxxxxxx /dev/loop0 /dev/hda2                     |
|Password:                                                                  |
|# mount /dev/loop0 /mnt                                                    |
+---------------------------------------------------------------------------+

You can compare the encrypted and unencrypted data:

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

4. Installing your encrypted Linux system

4.1. If you use a GNU/Linux distribution

This command works on all distributions, including Debian, Gentoo, Mandrake
and Redhat:

+---------------------------------------------------------------------------+
|# cp -avx / /mnt                                                           |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

4.2. 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 Chapter 5 of this howto.
   

-----------------------------------------------------------------------------
5. Setting up the boot device

5.1. Creating the ramdisk

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

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

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

+---------------------------------------------------------------------------+
|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/{sh,mount,umount} ramdisk/bin/                                     |
|cp -a /dev/{console,hda2,loop0} ramdisk/dev/                               |
|cp /lib/{ld-linux.so.2,libc.so.6,libdl.so.2,libncurses.so.5} \             |
|    ramdisk/lib/                                                           |
|cp /sbin/{losetup,pivot_root} ramdisk/sbin/                                |
+---------------------------------------------------------------------------+

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

+---------------------------------------------------------------------------+
|cat > ramdisk/sbin/init << "EOF"                                           |
|#!/bin/sh                                                                  |
|                                                                           |
|/sbin/losetup -e aes128 -S xxxxxxxxxx /dev/loop0 /dev/hda2                 |
|/bin/mount -n -t ext2 /dev/loop0 /mnt                                      |
|                                                                           |
|while [ $? -ne 0 ]                                                         |
|do                                                                         |
|    /sbin/losetup -d /dev/loop0                                            |
|    /sbin/losetup -e aes128 -S xxxxxxxxxx /dev/loop0 /dev/hda2             |
|    /bin/mount -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                                                                |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

5.2. Setting up the boot partition

Create and mount the ext2 filesystem:

+---------------------------------------------------------------------------+
|mke2fs /dev/hda1                                                           |
|mount -t ext2 /dev/hda1 /loader                                            |
+---------------------------------------------------------------------------+

Copy the kernel compiled in Chapter 2.1 and the initial ramdisk:

+---------------------------------------------------------------------------+
|cp /path/to/vmlinuz /loader/                                               |
|cp /path/to/initrd.gz /loader/                                             |
+---------------------------------------------------------------------------+

Configure and run LILO:

+---------------------------------------------------------------------------+
|mkdir /loader/{boot,dev,etc}                                               |
|cp /boot/boot.b /loader/boot/                                              |
|cp -a /dev/{hda,hda1,ram0} /loader/dev/                                    |
|cat > /loader/etc/lilo.conf << EOF                                         |
|lba32                                                                      |
|boot=/dev/hda                                                              |
|root=/dev/ram0                                                             |
|vga=4                                                                      |
|read-only                                                                  |
|image=/vmlinuz                                                             |
|    label=Linux                                                            |
|    initrd=/initrd.gz                                                      |
|EOF                                                                        |
|lilo -r /loader                                                            |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

5.3. Booting with a CD-ROM

You may also choose not to use /dev/hda1 as a boot device at all, but instead
burn the kernel and the ramdisk on a bootable cd-rom. Download and unpack
syslinux:

[ftp://ftp.kernel.org/pub/linux/utils/boot/syslinux/syslinux-2.06.tar.gz]
ftp://ftp.kernel.org/pub/linux/utils/boot/syslinux/syslinux-2.06.tar.gz

Configure isolinux:

+---------------------------------------------------------------------------+
|mkdir bootcd                                                               |
|cp /path/to/vmlinuz bootcd/                                                |
|cp /path/to/initrd.gz bootcd/                                              |
|cp syslinux-2.06/isolinux.bin bootcd/                                      |
|echo "DEFAULT vmlinuz initrd=initrd.gz 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 16 -v bootcd.iso                                |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

6. Setting up the bootscripts

Make sure your /etc/fstab contains:

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

At this point, hda3 is not needed anymore, so you can create an encrypted
filesystem on this partition and use it as a backup.

Also, it is a good idea to check the boot partition integrity inside the
encrypted partition, in order to spot if a government agency like the FBI or
the NSA has modified your boot partition so as to grab your password. Add the
following script, which can be called for example S00checkloader, in the
system startup directory (/etc/rcS.d/ under Debian):

+---------------------------------------------------------------------------+
|#!/bin/sh                                                                  |
|                                                                           |
|echo -n "Checking master boot record integrity: "                          |
|if [ "`dd if=/dev/hda count=1 2>/dev/null | md5sum`" = \                   |
|     "e051a4532356709c73b86789acfbdbbd  -" ]                               |
|then                                                                       |
|    echo "OK."                                                             |
|else                                                                       |
|    echo -n "FAILED! press Enter to continue."                             |
|    read                                                                   |
|fi                                                                         |
|                                                                           |
|echo -n "Checking boot partition integrity: "                              |
|if [ "`dd if=/dev/hda1 2>/dev/null | md5sum`" = \                          |
|     "f3686a17fac8a1090d962bef59c86d3b  -" ]                               |
|then                                                                       |
|    echo "OK."                                                             |
|else                                                                       |
|    echo -n "FAILED! press Enter to continue."                             |
|    read                                                                   |
|fi                                                                         |
+---------------------------------------------------------------------------+

(you should replace the two md5sums above with the correct ones).

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 aes128 /dev/loop1 /dev/hda4                                   |
|# mkswap /dev/loop1                                                        |
+---------------------------------------------------------------------------+

Then add the following lines at the end of S00checkloader:

+---------------------------------------------------------------------------+
|echo "password chosen above" | \                                           |
|    losetup -p 0 -e aes128 /dev/loop1 /dev/hda4                            |
|swapon /dev/loop1                                                          |
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------

7. About this HOWTO

The Encrypted Root Filesystem HOWTO was first written in november 2002 for
the Linux >From Scratch project. I'd like to thank the people who have since
helped me improve this howto (in reverse chronological order): Josh Purinton,
Jari Ruusu and Zibeli Aton.

Please send any comment to <devine (at) cr0.net>.

The latest version of this document is located at:

[http://www.cr0.net:8040/code/crypto/efs-howto.php] http://www.cr0.net:8040/
code/crypto/efs-howto.php
