Return to LinuxDig.Com HowTo's

Encrypted Root Filesystem HOWTO

Christophe Devine

Revision History
Revision v1.12003-12-01Revised by: cd
Added support for GRUB.
Revision v1.02003-09-24Revised by: cd
Initial release, reviewed by LDP.
Revision v0.92003-09-11Revised 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.


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