Next Previous Contents

4. Encrypting Disks

In this section I will show how to configure the kernel and some of its utilities to use the loop device mechanism to encrypt block devices (i.e. partitions or regular files containing whole filesystems). This is the preferred method, as it is fast, simple and reliable.

There are, however, some restrictions still not resolved that avoid its use in all and every situation (e.g. swap partitions and root filesystems cannot yet be encrypted reliably), so I will briefly discuss other approaches that may fix some of these issues in section Other Disk Encryption Approaches.

4.1 Configuring the Kernel

After successfully applying the patch to the kernel source tree, we are in the position to configure the kernel to actually use the encryption routines. As usual, this includes re-compilation of the kernel. If this should be the first time you compile a custom kernel yourself, get yourself the help of a friend or read the Kernel HOWTO.

make oldconfig will prompt you for only the new kernel options, while make xconfig or make menuconfig will somewhat hide the new features as they are spread over all the menus, as we will see in a minute.

After configuring the options you want (see below), you re-compile and install the kernel as usual and then reboot it. Your kernel has now all it needs to support encryption of disks.

Overview of kernel options

This is a short summary of disk encryption related kernel config options. See section Encrypting Network Traffic for options related to network traffic encryption. As of 2.2.11.2, the help texts of most of these options do not contain much information.

CONFIG_CIPHERS (Crypto Ciphers):

This enables the use of a wide variety of crypto ciphers (= routines that de/encrypt data) for the Crypto API. The Crypto API can be employed to disk encryption via the generic crypto driver for the loop device (CONFIG_BLK_DEV_LOOP_GEN). That obsoletes the concept that the ``direct'' drivers CONFIG_BLK_DEV_LOOP_CAST and CONFIG_BLK_DEV_LOOP_FISH2 are using. Use of the generic driver is strongly recommended.

CONFIG_CIPHER_*:

This set of options enables specific ciphers (= routines that de/encrypt data) to be used in CBC mode by the Crypto API (see above).

CONFIG_BLK_DEV_LOOP (Loopback device support):

This options has nothing to do with encryption per se. However, as the current disk encryption implementation uses the loop device, you must say ``Y'' here.

CONFIG_BLK_DEV_LOOP_USE_REL_BLOCK (Use relative block numbers...):

This options allows you to copy around the file containing your encrypted file system without affecting it's usability. Without this option enabled, you have to make sure it stays at the exact same place on the disk in order to use it, because the (absolute, as opposed to relative) block numbers the file occupies on disk affect the crypto cipher, see the question on copying files in the FAQ section.

CONFIG_BLK_DEV_LOOP_GEN (General encryption support):

This option provides an additional layer of abstraction for crypto ciphers. With this option enabled, you can use any of the ciphers (CONFIG_CIPHER_*) the Crypto API supports.

CONFIG_BLK_DEV_LOOP_CAST (CAST128 encryption):

This option provides 128-bit key CAST encryption in ECB mode for use with the loop device. This option does not depend on the general encryption support (CONFIG_BLK_DEV_LOOP_GEN) or the Crypto API above. Use of this option is deprecated.

CONFIG_BLK_DEV_LOOP_FISH2 (Twofish encryption):

This option provides Twofish encryption in CBC mode for use with the loop device. This options does not depend on the general encryption support (CONFIG_BLK_DEV_LOOP_GEN) or the Crypto API above. Use of this option is deprecated.

Selecting the right options

This is easy. First, you choose which cipher you want to use. Make sure that you know what using a particular cipher implies (licensing fees and/or even break of law). The help texts as well as the glossary at the end of this document will help you with that, although these sources are not to be considered authorative.

Next, if you want to use CAST-128 or Twofish, then say ``yes'' to CONFIG_BLK_DEV_LOOP and CONFIG_BLK_DEV_LOOP_CAST or CONFIG_BLK_DEV_LOOP_FISH2. Note that the implementation of these ciphers will likely change in future releases, as they will become accessible through the Crypto API. I'm not sure the future implementation will be compatible with existing encryption, so use these only if you have no choice or want to experiment. Also, they conflict with the loop_gen driver, so you can only have one of them in the kernel at any given time.

If you want to use one of the ciphers in the Crypto API, then you need to say ``yes'' to CONFIG_CIPHERS, CONFIG_BLK_DEV_LOOP, CONFIG_BLK_DEV_LOOP_GEN and the cipher you wish to use under ``Crypto options''. I recommend to also enable CONFIG_BLK_DEV_LOOP_USE_REL_BLOCKS (available in patch-int-2.2.10.4 and later), as this solves problems with physically moving around the encrypted file on disk.

NOTE: Using relative block numbers will probably not help you if you plan to move the file containing the encrypted filesystem between underlying filesystems with different block sizes. I nearly lost my gigabyte of encrypted data while trying to do so. A solution is in the work. It will allow you to choose the encryption block size (currently equal to the block size of the underlying filesystem - this where the trouble stems from) on setup via losetup.

If you want to compile crypto ciphers as modules, see the FAQ section for how.

4.2 Patching the util-linux source

After re-compiling the kernel and rebooting it, you need to patch some of its helper programs, namely losetup and/or mount. The patch used resides in the Documentation/crypto hierarchy of the kernel source tree.

losetup and mount need to be patched if you want to use any of the following ciphers:

Note that this collection is compiled from my own personal tests and is only valid for patch-int-2.2.17.7. As it is one short-term goal to unify the conceptional design of the crypto modules (i.e. all will use the loop_gen abstraction someday), the size of this list is likely to monotonically increase as new releases come out.

In order to patch the mount utilities to support encrypted filesystems over the loop device, you need to fetch a recent source tree of the util-linux package, e.g. from ftp.kernel.org/pub/linux/utils/util-linux/ or oneof it's mirrors.

As usual, you issue the following commands to apply the patch:

user$ tar xfzv util-linux*.tar.gz
user$ cd util-linux*
user$ patch -p1 < /usr/src/linux/Documentation/crypto/util-linux*.patch
It should apply cleanly if you use the patch only on util-linux trees that have a higher version number than the patch file shows.

Next you have to make sure that only the mount utilities are built. You can get in all sorts of troubles if you mess around with init or the password authentication programs. You can render your computer unusable if you do not make sure that you only compile mount and losetup!.

In order to avoid this mess, you need to install the executable files yourself, so you can gain control over what is being installed. But that is not hard to do:

After paching the util-linux source tree as described above, issue the following commands in the util-linux* directory. Make sure you have not currently mounted any filesystems using the loop device.

user$ ./configure
user$ make -C lib setproctitle.o    # mount depends on this
user$ cd mount
user$ make losetup mount umount
root# for i in losetup mount umount; do
root> j=$(locate bin/$i)
root> cp $j{,.old} && chattr +i $j.old
root> cp $i $j
root> done
If the make step fails, check that /usr/include/linux and /usr/include/asm resp. are symlinks to include/linux and include/asm-arch resp. Some distributions (e.g. Debian) only have a copy of the kernel include there. If you change the kernel, they become outdated.

Change the permissons and ownership of the new binaries according to your distribution's policy (check the old binaries for the right settings).

4.3 Making an Encrypted Folder

Create a file that will hold the encrypted data. We will call it .crypto for now and assume it is placed in the home diretory of user ``user''. You can use any other name, though. Note that this file will not grow dynamically as you feed more and more data into it. On the other hand, it will permanently block the amount of disk space you allocate to it, even if there is no data stored in the encrypted folder. However, you can always grow or shrink the filesystem manually, see FAQ section for how. Choose a reasonable size, e.g. 10M in the following command (calculated as bs * count):

user$ dd if=/dev/urandom of=~/.crypto bs=1024k count=10
This will take some time, as the urandom device emits random numbers that need to be created first. The above command takes about one minute to complete on my 300 MHz AMD K6-2. You might want to use /dev/zero instead, if you have a slow machine or want a huge crypto filesystem, but then your filesystem is said to be vulnerable to known-plaintext attacks. I cannot follow that argument, as we do not encrypt the zeros, but instead pretend they were the ciphertext. However, using zeros to create the file in the first place makes it possible for the attacker to know which blocks have not been written to. This may give him one or another hint as to how to attack your ciphertext.

You may also choose to encrypt a whole partition. Just make sure it contains no data and replace the filename ~/.config in the following discussion with the name of the block device that you wish to use (e.g. /dev/sda3).

Now set up this file as the target of a loop device. You must do this as superuser, unless the loop device files can be written to by everyone (not recommended). Choose a loop device that is not currently in use. Try mount|grep loop to see which loop devices are currently used by mounted filesystems.

root# losetup -e ciphername /dev/loop0 ~user/.crypto
Password :
Note that you should take your time as you enter the password, as you are not prompted to enter it again for typo checking! One way around this, if you have a recent bash (tested to work with bash-2.04, tested to not work with bash-2.01) and util-linux-2.10p or higher (which will hopefully include the -p option to losetup and mount), is to use the following little script:
#!/bin/bash

# the cipher is the first command line argument
CIPHER=$1
# the loop device to use is the second
LOOPDEV=$2
# the underlying file is third
UNDERLYING=$3

# until the two passphrases match and are not empty...
until [ "$PASS1" = "$PASS2" -a -n "$PASS1" ]; do
        # the bash read buitlin has to support the -s option.
        # Don't use read without -s!!
        read -s -p "Enter Passphrase: " PASS1; echo
        read -s -p "Re-enter Passphrase: " PASS2; echo
done

# setup the loop device using the passphrase given on STDIN.
echo "$PASS1" | losetup -e $CIPHER -p 0 $LOOPDEV $UNDERLYING

What you have done so far is to set up a so-called encrypted block device /dev/loop0. It is functionally equivalent to a partition device (e.g. /dev/hda1), so you next need to do what you (or your installation tool) did with naked partitions: Make a filesystem on it. Ext2 should be your choice, as it is Linux' native filesystem: (FIXME: what about journalling?)

root# mke2fs /dev/loop0
Next, you mount it. We take the mount point to be ~/crypto (notice the omission of the leading dot!):
user$ mkdir ~/crypto
root# mount -t ext2 /dev/loop0 ~user/crypto
The last step needs to be done as root, as only the superuser is allowed to (un)mount filesystems, unless otherwise stated in /etc/fstab.

If all worked well, you now have a filesystem that encryptedly resides in the file ~/.crypto and is mounted on ~/crypto. You can enter it and look at the files in it (not many now as it is just newly created, only the lost+found folder should be visible).

Now, all this is nice but really clumsy to do everytime you want to access the encrypted data. But before you learn how to make mounting the encrypted file/folder more user-friendly, you first need to unmount and destroy the loop device. I'd like to make it very clear at this point that encryption does not buy you anything if you leave the filesystem mounted all the time and/or set the permissions not restrictive enough. You should be familiar with what the following commands do, so I will let them speak for themselves:

root# grep -q "lost+found" /dev/loop0 && echo 'found!'
root# chmod go= ~user/.crypto
root# chown user -R ~user/crypto
root# chmod go= -R ~user/crypto
Now unmount the filesytem:
root# umount /dev/loop0
and detach the loop device from the file:
root# losetup -d /dev/loop0

You next edit your /etc/fstab to include the following line:

/home/user/.crypto  /home/user/crypto  ext2  \
      defaults,noauto,loop,encryption=ciphername,user  0   0
where ciphername is the same as the one you used with the losetup command.

This approach has some advantages over the one previously used to initially create the filesystem:

  1. You don't need to be root to (un)mount the filesystem (option user; this is not meant to be the example username ``user'' we used throughout this section!)
  2. You don't need to call losetup yourself, as mount will do that for you (options loop, encryption)
  3. You don't need to keep track of already used loop devices, as mount will do this for you, choosing free loop devices by itself as needed.

Warning: mount currently has a bug that leads to the assignment of additional loop devices, e.g. when remounting. The symtoms are that the sequence

root# mount /my/crypto/fs.file
root# mount -o remount,ro /my/crypto/fs.file
root# umount /my/crypto/fs.file
will leave /dev/loop0 assigned to /my/crypto/fs.file. Temporary fix: issue losetup -d /dev/loop0 after the umount command. Util-linux version 2.10p should fix this problem.

4.4 Automagically Encrypting the Home Directory with ``EHD''

I cannot yet discuss this (additional) patch to the util-linux tree, as I have not yet successfully installed it on my system.

You may do your own experiments, though: The patch (written by Id Est) and some documentation can be obtained from http://members.home.net/id-est/.

Do not expect too much comfort from this patch, however. It does not work with rsh, which is OK, because rsh is inherently insecure, but also not with ssh (although you can instruct ssh to use login for access control) and su, which is not acceptable in a networked environment. Also, I have not seen how it should work for X sessions.

All these restrictions stem from the inherent need to enter the passphrase for decryption. Maybe PAM (pluggable authentication) modules are a better place to implement this functionality, but I have yet to see such an approach being taken. However, there is a quite concrete idea of how to do this floating around in my head. If you are interested, give my a call.

4.5 Other Disk Encryption Approaches

The loop device approach has several drawbacks. Some will be resolved sometime soon, some are deeply buried in the design of the loop device mechanism. Some can be overcome with scripts and tricks, some are not that easy.

Major drawbacks---and a good reason for other approaches to exist---include (in order of increasing chance to overcome them):

  1. You are not able to encrypt devices that are used for swap. Trying this will lead to deadlocks when swapping heavily: The kernel tries to free memory by swapping out some areas of memory, the device tries to encrypt the data, encryption requires memory---bingo.
  2. You are not able to export directories encryptedly via NFS (loop device over NFS-mounted files doesn't work in current kernels, as far as I know). So you must export directories in the clear.
  3. Root filesystem encryption is tricky.
  4. (Automated) incremental backups are difficult.
  5. Changing password. The hashed passphrase is used as the encryption key, so changing the passphrase changes the key, i.e. you are no longer able to access the encrypted data.
Other disk encryption approaches known to me are:

The rest of this section is copied with kind permission of the author from Doobee R. Tzeck's (drt@ailis.de) document "Encrypting your Disks with Linux" at http://drt.ailis.de/crypto/linux-disk.html.


Next Previous Contents