Written by Jari Ruusu , October 26 2004 Copyright 2001,2002,2003,2004 by Jari Ruusu. Redistribution of this file is permitted under the GNU Public License. Table of Contents ~~~~~~~~~~~~~~~~~ 1. Loop device primer 2. General information 2.1. Key setup and IV modes 2.2. Use of journaling file systems on loop device 2.3. Use of offsets and sizelimits 2.4. Use of software suspend 2.5. File system soft block sizes 2.6. Compatibility with earlier versions 3. Instructions for building loop.o driver 4. Instructions for building new mount, umount, losetup, swapon and swapoff 5. Instructions for building new gpg 6. Testing the loop.o driver and losetup program 7. Examples 7.1 Example 1 - Encrypting swap on 2.4 and newer kernels 7.2. Example 2 - Partition backed loop with gpg encrypted key file 7.3. Example 3 - Encrypted partition that multiple users can mount 7.4. Example 4 - Encrypting /tmp partition with random keys 7.5. Example 5 - Encrypting root partition 7.6. Example 6 - Boot from CD-ROM + encrypted root partition 8. Security levels 9. Performance tuning for 2.4 and newer kernels 10. Files 11. Credits 1. Loop device primer ~~~~~~~~~~~~~~~~~~~~~ Loop devices are block devices that do not store any data directly but loop all reads and writes to underlying block device or file, possibly encrypting and decrypting data in the process. Normally you don't write to a loop device directly, but set up a file system on it. The file system will then read from and write to loop device. By default, 8 loop devices are available: /dev/loop0, /dev/loop1 ... /dev/loop7 (on devfs /dev/loop/0 ... /dev/loop/7). All devices are identical, and each can be tied to one real block device or one file on some file system. You have to decide and allocate which loop to use for which purpose. losetup(8) program is used to make and tear down the connection between a loop device and underlying device or file. You don't have to specify type of underlying device as loop driver detects that automatically. mount(8), umount(8), swapon(8) and swapoff(8) programs can also set up and tear down loop devices. File backed loops may deadlock under some kernel + file system combinations. So, if you can choose between device backed and file backed, choose device backed even if it means that you have to re-partition your disks. 2. General information ~~~~~~~~~~~~~~~~~~~~~~ This package provides loadable Linux kernel module (loop.o or loop.ko on 2.6 kernels) that has AES cipher built-in. The AES cipher can be used to encrypt local file systems and disk partitions. Loop device encrypts data but does not authenticate ciphertext. In other words, it delivers data privacy, but does not guarantee that data has not been tampered with. Admins setting up encrypted file systems should ensure that neither ciphertext, nor tools used to access ciphertext (kernel + kernel modules, mount, losetup, and other utilities) can be trojaned or tampered. This package does *not* modify your kernel in any way, so you are free to use kernels of your choice, with or without cool patches. This package works with 2.0.x, 2.2.x, 2.4.x (2.4.7 or later) and 2.6.x kernels. Latest version of this package can be found at: http://loop-aes.sourceforge.net/ http://members.tiscali.fi/ce6c8edf/ (limited downloads) New versions are announced to linux-crypto mailing list: http://mail.nl.linux.org/linux-crypto/ http://www.spinics.net/lists/crypto/ List-subscribe: 2.1. Key setup and IV modes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The AES cipher is used in CBC (cipher block chaining) mode. Data is encrypted and decrypted in 512 byte chains. Two key setup modes are supported; single-key mode and multi-key mode. Single-key mode uses simple sector IV and one AES key to encrypt and decrypt all sectors in the loop device. Multi-key mode uses cryptographically more secure MD5 IV and 64 different AES keys to encrypt and decrypt sectors in the loop device. In multi-key mode first key is used for first sector, second key for second sector, and so on. Password string has a minimum length of 20 characters. Optional password seed (salt) and key iteration count can be used to slow down dictionary attacks. Password seed is appended to user supplied password before password is hashed using one way hash. If password iteration count is specified, password hash output is encrypted N thousand times using AES-256. Unique seed prevents an adversary from precomputing hashes of passwords in his dictionary in advance, and thus making an optimized attack slower. Large password iteration count makes dictionary attack painfully slow. If encryption type is specified as AES128 or AES, password string is hashed with SHA-256, and 128 bit AES encryption is used. If encryption type is specified as AES192, password string is hashed with SHA-384, and 192 bit AES encryption is used. If encryption type is specified as AES256, password string is hashed with SHA-512, and 256 bit AES encryption is used. 2.2. Use of journaling file systems on loop device ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Don't use a journaling file system on top of file backed loop device. Device backed loop device can be used with journaling file systems as device backed loops guarantee that writes reach disk platters in order required by journaling file system (write caching must be disabled on the disk drive, of course). With file backed loop devices, correct write ordering may extend only to page cache (which resides in RAM) of underlying file system. VM can write such pages to disk in any order it wishes, and thus break write order expectation of journaling file system. 2.3. Use of offsets and sizelimits ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ losetup and mount programs support using offset to underlying device or file. 2.4.x and later kernels also support use of sizelimit that limit size of device to some subset of full underlying device or file size. Both offset and sizelimit are specified in bytes. If no offset is specified, zero offset is used. If no sizelimit is specified, full device/file size is used. If you do use nonzero offsets, make sure offset is integer multiple of 512 bytes. Nonzero offsets that are not integer multiple of 512 bytes are NOT supported as they may be nonportable and/or nonworking. 2.4. Use of software suspend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Encryption keys are kept in kernel RAM while loop is active. Key is immediately erased when loop is deactivated. Use of suspend-to-disk while there are active encrypted loops should be used with caution: it would be really bad security wise because encryption keys are written to disk when kernel RAM is saved to disk. Once key is written to disk it may be recoverable from that disk pretty much forever. Security of data encrypted with such recoverable key is void. 2.5. File system soft block sizes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you intend to move encrypted file system to some other device (CD-ROM for example), be sure to create file system with soft block size that is integer multiple of device hard sector size. CD-ROMs have 2048 byte sectors. File system with 1024 byte soft block size is not going to work with all CD-ROM drives and/or drivers. 2.6. Compatibility with earlier versions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This version is compatible with on-disk formats of all previous relased versions. This version is compatible with recommended mount, losetup and swapon command line syntax and /etc/fstab option syntax since loop-AES-v1.1b. Unhashed encryption type as created using ancient loop-AES-v1.0c, now needs 'mount -o phash=unhashed1' or 'losetup -H unhashed1' options. Mount and losetup programs from loop-AES-v2.0g and older accepted unlimited long passphrase when passphrase was read from a file descriptor using '-p 0' option. To prevent abuse of mlock()ed RAM by non-root users, mount and losetup programs from loop-AES-v2.1a and newer limit max passphrase length to 4094 bytes. 3. Instructions for building loop.o driver ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Before you attempt to build loop.o driver (loop.ko on 2.6 kernels), you *must* configure, compile and install new kernel so that CONFIG_MODULES=y and CONFIG_BLK_DEV_LOOP=n. Also, CONFIG_KMOD=y is recommended but not required (kernel 2.0 doesn't have CONFIG_KMOD, set CONFIG_KERNELD=y instead). Configuring your kernel so that loop driver is built-in (CONFIG_BLK_DEV_LOOP=y) or module (CONFIG_BLK_DEV_LOOP=m) will *not* work. After building and installing your new kernel, do not attempt to clean kernel tree, or rename path to kernel sources. (Re)configuring and (re)compiling your kernel are required for following reasons: (1) to disable loop driver in your kernel, (2) to get your kernel sources to match your running kernel, (3) to get your kernel .config to match your running kernel, (4) to set up configure time generated links properly, (5) to generate compile time created header files properly to match your kernel configuration. Failure to fulfill *all* above requirements may cause loop.o driver compilation to fail or generate incorrectly operating code. If you are just upgrading existing loop-AES with newer version, there is no need to recompile kernel or reboot. Just unmount all file systems using old loop driver, and remove loop driver from kernel with rmmod command before compiling new loop driver. This is how loop.o is compiled and installed: 2.2 and older kernels: Makefile copies your kernel's loop.c to this directory. Then, Makefile patches that copy with a kernel version specific patch. If patching a copy of your kernel's loop.c fails, then a local copy of known-to-work and patch-able loop.c-2.X.original is used instead. 2.4 and newer kernels: Makefile copies pre-patched loop.c-2.X.patched to file called patched-loop.c. Resulting patched-loop.c along with other source files is then compiled and linked to form a new loop.o driver that is (usually) installed in /lib/modules/`uname -r`/block directory. AES cipher is permanently glued to loop.o driver so that when loop.o is loaded it automagically has AES support built in. There is no need to define any aliases in /etc/modules.conf file. To compile and install loop.o driver, as root, use commands: make clean make Makefile tries to locate running kernel source directory, steal definitions from kernel Makefile, and build a version that matches your running kernel. Following directories are tried, in this order: /lib/modules/`uname -r`/source /lib/modules/`uname -r`/build /usr/src/linux /usr/src/linux-`uname -r` /usr/src/kernel-source-`uname -r` You can override automatic kernel source directory detection by specifying LINUX_SOURCE like this: make LINUX_SOURCE=/usr/src/linux-2.4.22aa1 Both LINUX_SOURCE and KBUILD_OUTPUT must be specified when compiling for 2.6.x kernel with separate object directory. You can disable automatic module installation and creation of module dependencies by specifying MODINST=n RUNDM=n on make command line. Automatic kernel source directory detection is not foolproof. For best results, always specify LINUX_SOURCE, especially if loop.o module appears to compile for wrong kernel. Observe last five lines of make output for clues. If you are upgrading your kernel and you need loop.o module during boot, you probably need to build new version of loop.o module that matches your new kernel *before* you boot the new kernel. To build loop.o module for other kernel than running kernel, you *must* specify LINUX_SOURCE parameter to make. You can override default installation root directory by specifying INSTALL_MOD_PATH like this: make INSTALL_MOD_PATH=/path/to/destination/root Makefile detects processor type from kernel configuration. If selected processor type is x86 processor or AMD64 processor, optimized assembler implementations of AES and MD5 are used instead of C implementations. If you want to unconditionally disable x86 assembler AES and MD5 implementations, specify X86_ASM=n on make command line. If you want to unconditionally disable AMD64 assembler AES and MD5 implementations, specify AMD64_ASM=n on make command line. If you want to enable encryption key scrubbing, specify KEYSCRUB=y on make command line. Loop encryption key scrubbing moves and inverts key bits in kernel RAM so that the thin oxide which forms the storage capacitor dielectric of DRAM cells is not permitted to develop detectable property. For more info, see Peter Gutmann's paper: http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html Note: If your patch program is very old, it may not understand the --dry-run option, and may puke lengthy error messages. Even if that happens, the build process should still produce a working loop driver. 4. Instructions for building new mount, umount, losetup, swapon and swapoff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In order to support AES and other ciphers, mount, umount, losetup, swapon and swapoff need to be patched and recompiled. A patch is included. Mount, umount, losetup, swapon and swapoff sources are in util-linux package which you can get from: ftp://ftp.win.tue.nl/pub/linux-local/utils/util-linux/ or ftp://ftp.kernel.org/pub/linux/utils/util-linux/ Just in case if the tarball is not properly signed, the md5 sum of util-linux-2.12h.tar.gz is f8f1b2096abbf52fadf86d470c5035dd Do *not* install all the utilities in the util-linux package without thinking. You may ruin your system if you do that. Read the INSTALL file provided with util-linux tarball. These commands, as root user, will recompile and install mount, umount, losetup, swapon, swapoff and their man pages: zcat util-linux-2.12h.tar.gz | tar xvf - cd util-linux-2.12h patch -p1 <../util-linux-2.12h.diff CFLAGS=-O2 ./configure make SUBDIRS="lib mount" cd mount install -m 4755 -o root mount umount /bin install -m 755 losetup swapon /sbin rm -f /sbin/swapoff && ( cd /sbin && ln -s swapon swapoff ) rm -f /usr/share/man/man8/{mount,umount,losetup,swapon,swapoff}.8.gz install -m 644 mount.8 umount.8 losetup.8 /usr/share/man/man8 install -m 644 swapon.8 swapoff.8 /usr/share/man/man8 rm -f /usr/share/man/man5/fstab.5.gz install -m 644 fstab.5 /usr/share/man/man5 mandb cd ../.. Debian users may want to put mount package on hold like this: echo mount hold | dpkg --set-selections 5. Instructions for building new gpg ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When gpg encrypts data with symmetric cipher only or when gpg encrypts secret keyring keys with secret passphrase, gpg uses seeded (salted) and iterated key setup. However, default amount of iteration is tuned for slow processors and can be increased for better resistance against dictionary attacks. Larger key iteration makes key setup much slower, but also makes dictionary attacks much slower too. Included optional gpg patch makes gpg password iteration 128 times slower. gpg stores new iteration value along with seed bytes into symmetric cipher encrypted output file or secret keyring, so unpatched gpg versions will read and decrypt the data just fine. gpg sources are available from: ftp://ftp.gnupg.org/gcrypt/gnupg/ These commands, as root user, will recompile and install gpg and gpgv and their man pages: zcat gnupg-1.2.6.tar.gz | tar xvf - cd gnupg-1.2.6 patch -p1 <../gnupg-1.2.6.diff CFLAGS="-O2" LDFLAGS="-static -s" ./configure --prefix=/usr --enable-static-rnd=linux make rm -f /usr/share/man/man1/{gpg,gpgv}.1.gz make install chown root.root /usr/bin/gpg chmod 4755 /usr/bin/gpg Note: Above instructions create statically linked version of gpg. Static linking is necessary if you ever decide to encrypt your root partition. If /usr/bin directory is not on your root partition, then it is necessary to move gpg to /bin directory on your root partition: cd /usr/bin mv gpg ../../bin ln -s ../../bin/gpg gpg Debian users may want to put gnupg package on hold like this: echo gnupg hold | dpkg --set-selections 6. Testing the loop.o driver and losetup program ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Run this command, as root, and Makefile will run series of tests. make tests Makefile will display "*** Test results ok ***" message if tests are completed successfully. If tests fail, do not use the driver as it is broken. If gpg isn't available, then tests that involve decrypting gpg encrypted key files will fail. You can skip gpg key file tests by specifying TEST_GPG_TYPES=n on make command line. 7. Examples ~~~~~~~~~~~ Many of following examples depend on gpg encrypted key file. gpg appears to prevent its own keys from being leaked to swap, but does not appear to prevent data handled by it from being leaked to swap. In gpg encrypted key file cases, the data handled by gpg are loop encryption keys, and they may leak to swap. Therefore, use of gpg encrypted key file depends on encrypted swap. When using gpg encrypted key file, the password that is used to encrypt the key file is the password that losetup and mount programs want. losetup and mount programs run gpg to decrypt the key file, and pipe the password to gpg. gpg then decrypts the file and pipes the real loop keys back to losetup or mount program. Many of following examples need uuencode program. Not all boxes have it installed by default. If you need to install uuencode program, it is usually part of sharutils package. Many of following examples attempt to use loop in multi-key mode and thus *require* losetup/mount programs from loop-AES-v2.0b or later. Setting up multi-key gpg key-file and using that key-file with old single-key only aware losetup/mount programs is *dangerous*. In multi-key loop cases "losetup -a" command run by root user should output "multi-key" indicating that loop is really in multi-key mode. If no "multi-key" string shows up, your loop setup is a time bomb. If you later upgrade your losetup/mount programs to version that can understand multi-key mode, those new losetup/mount programs will correctly setup loop in multi-key mode instead of single-key mode, and you may not be able to access your data any more. New losetup/mount programs are compatible with both single-key and multi-key key-files. New losetup/mount programs will recognize single-key key-files and set up loop in single-key mode in those cases. Old single-key only aware losetup/mount programs need single-key examples. None of the following gpg key-file examples are such. 7.1. Example 1 - Encrypting swap on 2.4 and newer kernels ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Device backed (partition backed) loop is capable of encrypting swap on 2.4 and newer kernels. File backed loops can't be used for swap. First, run "swapoff -a" to turn off swap devices in your /etc/fstab file. Second, add "loop=/dev/loop?" and "encryption=AES128" options to swap lines in your /etc/fstab file. Example: /dev/hda666 none swap sw,loop=/dev/loop6,encryption=AES128 0 0 ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ Third, there may be old unencrypted data on your swap devices, in which case you can try to overwrite that data with command like this: dd if=/dev/zero of=/dev/hda666 bs=64k conv=notrunc mkswap /dev/hda666 Fourth, run "swapon -a" and "rm -rf /var/log/ksymoops" and you are done. Running "swapon -a" will set up loop devices using random keys, run mkswap on them, and enable encrypted swap on specified loop devices. Usually your distro's startup scripts will run the "swapon -a" command so you don't need to change your startup scripts at all. As expected, "swapoff -a" will tear down such loop devices. Removing /var/log/ksymoops directory is often required because some versions of modprobe (part of modutils package) try to log loaded modules to /var/log/ksymoops/*.log files. This is bad because swap is often enabled (and loop.o modprobe'd to kernel) before any partitions are mounted writable. Without /var/log/ksymoops directory on root partition, modprobe will not try to log loaded modules, and you won't see annoying error messages. Note: If you are using encrypted swap and you are upgrading your kernel, you probably need to build new version of loop.o module that matches your new kernel *before* you boot the new kernel. See "Instructions for building loop.o driver" section for more details. 7.2. Example 2 - Partition backed loop with gpg encrypted key file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This example, originally from Michael H. Warfield, shows how to create an ext2 file system on encrypted hard disk partition, and creates 64 random encryption keys that are encrypted using gpg. Store the key file where ever you like, on separate removable media, USB dongle, or on a smart card if you like. You have to have both your passphrase and that key file in order to mount that file system. This example uses a fictitious partition /dev/hda666 for storage and fictitious directory /mnt666 as mount point. A removable USB dongle is assumed to be (auto-)mounted at /a/usbdongle directory. Create 64 random encryption keys and encrypt those keys using gpg. Reading from /dev/random may take indefinitely long if kernel's random entropy pool is empty. If that happens, do some other work on some other console (use keyboard, mouse and disks). Use of gpg encrypted key file depends on encrypted swap. head -c 2880 /dev/random | uuencode -m - | head -n 65 | tail -n 64 \ | gpg --symmetric -a >/a/usbdongle/keyfile.gpg Fill the partition with random looking data. "dd" command may take a while to execute if partition is large. head -c 15 /dev/urandom | uuencode -m - | head -n 2 | tail -n 1 \ | losetup -p 0 -e AES128 /dev/loop3 /dev/hda666 dd if=/dev/zero of=/dev/loop3 bs=4k conv=notrunc 2>/dev/null losetup -d /dev/loop3 Add this to your /etc/fstab file: /dev/hda666 /mnt666 ext2 defaults,noauto,loop=/dev/loop3,encryption=AES128,gpgkey=/a/usbdongle/keyfile.gpg 0 0 The "losetup -F" command asks for passphrase to unlock your key file. Losetup -F option reads loop related options from /etc/fstab. Partition name /dev/hda666, encryption=AES128 and gpgkey=/a/usbdongle/keyfile.gpg come from /etc/fstab. losetup -F /dev/loop3 mkfs -t ext2 /dev/loop3 losetup -d /dev/loop3 mkdir /mnt666 Now you should be able to mount the file system like this. The "mount" command asks for passphrase to unlock your key file. mount /mnt666 Check that loop is really in multi-key mode. Losetup -a output should include string "multi-key" indicating that loop is really in multi-key mode. If no "multi-key" string shows up, you somehow managed to mess up gpg key file generation part or you are trying to use old losetup/mount programs that only understand single-key mode. losetup -a You can unmount partition like this: umount /mnt666 Unmounted filesystem can be fsck'ed like this. -F option reads loop related options from /etc/fstab. Partition name /dev/hda666, encryption=AES128 and gpgkey=/a/usbdongle/keyfile.gpg come from /etc/fstab. losetup -F /dev/loop3 fsck -t ext2 -f -y /dev/loop3 losetup -d /dev/loop3 7.3. Example 3 - Encrypted partition that multiple users can mount ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This example shows how to create encrypted partition that multiple non-root users can mount, each with their own gpg key. Non-root users don't have access to file system key that is actually used to encrypt data. Root can add or remove user's permission to mount encrypted partition at any time. This example uses a fictitious partition /dev/hda666 for storage and fictitious directory /secret1 as mount point. Create 64 random file system keys and encrypt those keys using root's gpg public key. Reading from /dev/random may take indefinitely long if kernel's random entropy pool is empty. If that happens, do some other work on some other console (use keyboard, mouse and disks). Use of gpg encrypted key file depends on encrypted swap. umask 077 head -c 2880 /dev/random | uuencode -m - | head -n 65 | tail -n 64 \ | gpg -e -a -r "Superuser" > /root/masterkey-secret1.gpg Fill the partition with random looking data. "dd" command may take a while to execute if partition is large. head -c 15 /dev/urandom | uuencode -m - | head -n 2 | tail -n 1 \ | losetup -p 0 -e AES128 /dev/loop0 /dev/hda666 dd if=/dev/zero of=/dev/loop0 bs=4k conv=notrunc 2>/dev/null losetup -d /dev/loop0 Use file system keys to setup /dev/loop0 to partition /dev/hda666 and create encrypted ext2 file system. The "losetup -e" command asks for root's gpg passphrase to unlock root's secret gpg key. losetup -e AES128 -K /root/masterkey-secret1.gpg /dev/loop0 /dev/hda666 mkfs -t ext2 /dev/loop0 losetup -d /dev/loop0 mkdir /secret1 Add mount information to /etc/fstab file. Something like this: /dev/hda666 /secret1 ext2 defaults,user,noauto,encryption=AES128,loop=/dev/loop0,gpgkey=/etc/userkey-secret1.gpg 0 0 ^^^^ You may want to check non-obvious side effects of above "user" mount option. It's all explained in mount man page. Create root-only-readable /etc/userkey-secret1.gpg file which contains file system key encrypted with each user's public key. List all users as recipient who should be able to mount /secret1 encrypted partition. Repeat this every time you want to add or remove users. umask 077 gpg --decrypt < /root/masterkey-secret1.gpg | gpg -e -a --always-trust \ -r "Superuser" -r "John Doe" -r "Tea Lipton" > /etc/userkey-secret1.gpg Users can mount encrypted partition like this. mount asks for gpg passphrase to unlock user's secret gpg key. Each user can use their own gpg key. mount /secret1 Root user can check that loop is really in multi-key mode. Losetup -a output should include string "multi-key" indicating that loop is really in multi-key mode. If no "multi-key" string shows up, you somehow managed to mess up gpg key file generation part or you are trying to use old losetup/mount programs that only understand single-key mode. losetup -a You can unmount partition like this: umount /secret1 Root user can fsck unmounted filesystem like this. -F option reads loop related options from /etc/fstab. Partition name /dev/hda666, encryption=AES128 and gpgkey=/etc/userkey-secret1.gpg come from /etc/fstab. losetup -F /dev/loop0 fsck -t ext2 -f -y /dev/loop0 losetup -d /dev/loop0 7.4. Example 4 - Encrypting /tmp partition with random keys ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When mount passphrase hash function is specified as random, mount does not ask for password but sets up 64 random keys and attempts to put loop to multi-key mode and creates new file system on that encrypted loop device before that file system is mounted. First, unmount your existing /tmp partition by running "umount /tmp". There may be open files in there, so you may have to do this from single user mode. Second, add loop= encryption= and phash=random mount options to /etc/fstab file. The sixth /etc/fstab field (fs_passno) must be zero so that fcsk will not attempt to check this partition. /dev/hda555 /tmp ext2 defaults,loop=/dev/loop2,encryption=AES128,phash=random/1777 0 0 ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^ Third, run "mount /tmp" command and you are done. Octal digits after phash=random/ mount option specify initial permissions of file system root directory that gets created on the loop device. 1777 means read+write+search permissions for all and sticky bit set. Type "man 2 stat" for more info about what each bit stands for. Encryption keys and plaintext data on above type mount vanish on unmount or power off. Using journaled file system in such case does not make much sense, because file system is re-created with different encryption keys on each mount, and file system jounal is never used. This example requires that mount program is derived from util-linux patch found in loop-AES-v2.2d or later version. 7.5. Example 5 - Encrypting root partition ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Encrypting root partition requires a small unencrypted /boot partition. Everything else (root, swap and other partitions) can be encrypted. Kernels and tools required to boot kernels reside in the /boot partition. Included build-initrd.sh script builds a small "initrd" ram-disk that works with 2.2 2.4, and 2.6 kernels. build-initrd.sh script depends on having minix file system support in the kernel and working mkfs.minix program binary. Util-linux includes source for mkfs.minix if you don't have it and need to build it yourself. You need to temporarily boot from rescue floppy/CD-ROM or other partition to do the actual encrypting work. The rescue floppy/CD-ROM or other partition kernel doesn't need to support loop crypto, so just about anything that boots will work. 1) build-initrd.sh script needs dietlibc. Dietlibc source is available from: http://www.fefe.de/dietlibc/ ftp://ftp.kernel.org/pub/linux/libs/dietlibc/ To compile and install dietlibc, follow instructions in the dietlibc README file. For example, on a x86 box, do this: make install bin-i386/diet /usr/local/bin 2) You need to use aespipe program (v2.2a or later) with your rescue floppy/CD-ROM or other partition. aespipe source is available from: http://loop-aes.sourceforge.net/ http://members.tiscali.fi/ce6c8edf/ (limited downloads) Download latest version of aespipe-*.tar.bz2 Dynamically linked aespipe program may have library dependency problems with rescue floppy/CD-ROM or other partition C library. To avoid such trouble, aespipe program needs to be linked statically. Static linking with glibc makes aespipe much bigger (hundreds of kilobytes), and may also create link warning about 'getpwuid'. Big program size and link warning can be ignored here. Compile aespipe program like this: CFLAGS="-O2" LDFLAGS="-static -s" ./configure make make tests Copy statically linked aespipe program to /boot partition. cp -p aespipe /boot 3) If you followed advise about recompiling and statically linking gpg program, you don't need to do that again. However, if you don't have statically linked gpg, you need to do that now because later steps in root partition encryption depend on it. 4) Backup all important data before proceeding with root partition encryption. 5) Recompile your kernel. These are required: CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_MINIX_FS=y CONFIG_PROC_FS=y CONFIG_CRAMFS=n (or CONFIG_CRAMFS=m) CONFIG_BLK_DEV_{RAM,INITRD}=y are needed because kernel needs to support initial ramdisk. CONFIG_MINIX_FS=y is needed because file system on initrd is minix. CONFIG_CRAMFS=n is needed because cramfs code may incorrectly detect initrd's compressed minix file system as cramfs file system. If cramfs must be built-in, then build-initrd.sh must be configured with USEPIVOT=1, and kernel parameter "rootfstype=minix" must be added to bootloader configuration file. 2.2.x and older kernels have neither CONFIG_CRAMFS nor cramfs, so that kernel configuration setting can be ignored on those kernels. All kernel subsystems needed by root and /boot file systems must be compiled directly into kernel (and not be modules). cd /usr/src/linux-2.4.22aa1 cp .config ../somewhere/somename.config make distclean cp ../somewhere/somename.config .config make config make dep && make clean && make bzImage make modules && make modules_install cat arch/i386/boot/bzImage >/boot/vmlinuz cp System.map /boot/System.map-2.4.22aa1 6) Compile loop-AES loop.o module for your kernel. cd ../loop-AES-* make LINUX_SOURCE=/usr/src/linux-2.4.22aa1 7) Copy kernel version specific loop.o (2.4 and older kernels) or loop.ko (2.6 kernels) to /boot/modules-KERNELRELEASE/ mkdir /boot/modules-2.4.22aa1 ^^^^^^^^^ cp -p /lib/modules/2.4.22aa1/block/loop.*o /boot/modules-2.4.22aa1/ ^^^^^^^^^ ^^^^^^^^^ Note: You need to have a kernel version specific loop.o or loop.ko module in /boot/modules-KERNELRELEASE/ directory for every kernel you intend to use. 8) If your boot scripts automatically run "umount /initrd" and "blockdev --flushbufs /dev/ram0" commands, you may want to disable those commands. If you don't disable them, you may see annoying error messages when booting to encrypted root partition. Root partition loop device node is inside initrd, and that device node will remain busy forever. This means that encrypted root initrd can't be unmounted and RAM used by initrd file system can't be freed. This unable-to-unmount side effect is the reason why initrd is intentionally made as small as possible. 9) Create 64 random encryption keys and encrypt those keys using gpg. Reading from /dev/random may take indefinitely long if kernel's random entropy pool is empty. If that happens, do some other work on some other console (use keyboard, mouse and disks). Use of gpg encrypted key file depends on encrypted swap. umask 077 head -c 2880 /dev/random | uuencode -m - | head -n 65 | tail -n 64 \ | gpg --symmetric -a >/boot/rootkey.gpg 10) Edit build-initrd.sh to match your setup. Set BOOTDEV, BOOTTYPE, CRYPTROOT and ROOTTYPE variables to correct values. If you are using 2.2 or older kernels, set USEPIVOT=0 because 2.2 and older kernels do not have pivot_root functionality. You may also want to set LOADNATIONALKEYB=1 and manually copy your uncompressed national keyboard layout file (in "loadkeys" format) to /boot/default.kmap loadkeys configuration files for some popular distros: Debian: /etc/console/boottime.kmap.gz Mandrake: /usr/lib/kbd/keymaps/i386/qwert[yz]/*.kmap.gz Red Hat: /lib/kbd/keymaps/i386/qwert[yz]/*.kmap.gz SuSE: /usr/lib/kbd/keymaps/i386/qwert[yz]/*.map.gz Slackware: /usr/share/kbd/keymaps/i386/qwert[yz]/*.map.gz Or alternatively, you can create keyboard map using your current keyboard layout. Like this: dumpkeys >/boot/default.kmap devfs enabled kernel users (CONFIG_DEVFS_FS=y and CONFIG_DEVFS_MOUNT=y in kernel configuration) need to pay special attention to comments above these build-initrd.sh options: USEDEVFS, BOOTDEV, CRYPTROOT and EXTERNALGPGDEV. 11) Edit /etc/lilo.conf (or whatever) and set root= initrd= and append= as explained in comments at beginning of build-initrd.sh script. 12) Build a new /boot/initrd.gz ./build-initrd.sh Note: /boot/initrd.gz is supposed to be small (2 KB to 3 KB). All other utilities (loop.o module, insmod, losetup, loadkeys and possibly libraries) are copied to /boot directory. Libraries are not copied if programs are statically linked. 13) Run lilo (or whatever) lilo 14) Reboot your computer from rescue floppy/CD-ROM or other partition, so that the partition you are about to encrypt is *not* mounted. 15) Now you should be running a shell from rescue floppy/CD-ROM or other partition. This example assumes that /dev/hda1 is your /boot partition and /dev/hda2 is your root partition. Temporarily mount your root partition under /mnt mount -t ext2 /dev/hda2 /mnt 16) Edit root partition entry in /mnt/etc/fstab file. Replace old /dev/hda2 with /dev/loop5 or whatever loop you are using for root partition. Loop device number must match ROOTLOOPINDEX= in build-initrd.sh configuration. The default in build-initrd.sh is 5, meaning /dev/loop5. Old /etc/fstab line: /dev/hda2 / ext2 defaults 0 1 New /etc/fstab line: /dev/loop5 / ext2 defaults 0 1 devfs enabled kernel users (CONFIG_DEVFS_FS=y and CONFIG_DEVFS_MOUNT=y in kernel configuration) need to substitute /dev/loop5 with /dev/loop/5 17) Unmount your root partition (and sync for extra safety). umount /mnt sync 18) Mount your normal /boot partition under /mnt so that you can use previously built statically linked aespipe and gpg programs and read gpg encrypted key file 'rootkey.gpg'. Statically linked gpg program was copied there by build-initrd.sh script. mount -r -t ext2 /dev/hda1 /mnt 19) Use dd program to read your root partition contents, pipe that data through aespipe program, and finally write encrypted data back to same partition with another dd program. This is going to take a while if partition is large. dd if=/dev/hda2 bs=64k \ | /mnt/aespipe -e AES128 -K /mnt/rootkey.gpg -G / \ | dd of=/dev/hda2 bs=64k conv=notrunc aespipe program tries to run gpg from obvious locations on your rescue floppy/CD-ROM file system, but if it can't find gpg from those obvious locations, aespipe finally tries to run gpg from same directory that aespipe was run from (/mnt/) and should find statically linked gpg program there. 20) Clean up and reboot your computer. umount /mnt sync reboot If you are upgrading kernel of a system where root partition is already encrypted, only steps 5 to 7 and 13 are needed. /boot/initrd.gz is kernel independent and there is no need to re-create it for each kernel. However, if you are upgrading from 2.4 kernel to 2.6 kernel, new insmod may need to be copied to /boot directory by running step 12 before running step 13. If you want to fsck and mount partitions automatically and are indeed encrypting root partition, it may be easier to just losetup required partitions early in init scripts (before partitions are fsck'ed and mounted). Don't losetup root partition again, as root partition has already been losetup'ed by /linuxrc program in the "initrd" ram-disk. Init scripts reside on root partition and encryption keys within such init scripts are protected by root partition encryption. Of course, init scripts containing sensitive keys must be readable only by root user: -rwx------ 1 root root 162 Nov 24 19:23 /etc/rcS.d/S07losetup.sh Here is an example of /etc/rcS.d/S07losetup.sh Debian init script. Other distros may store such init scripts in different directory under different name. On SuSE, /etc/init.d/boot.d/S01losetup.sh may be more appropriate. #!/bin/sh echo "Pd1eXapMJk0XAJnNSIzE" | losetup -p 0 -e AES128 -K /etc/swapkey.gpg /dev/loop6 /dev/hda666 echo "D0aZNSNnu6FdAph+zrHt" | losetup -p 0 -e AES128 -K /etc/homekey.gpg /dev/loop4 /dev/hdd666 Above partitions use gpg encrypted key files. Having encrypted files on encrypted partition may seem little bit silly, but currently -K option is the easiest way to activate multi-key mode with more secure MD5 IV computation. Here are example lines of /etc/fstab file. It's not necessary to give "loop=/dev/loop4,encryption=AES128" mount options as loop devices are already losetup'ed and there is no need for mount program to do that again. /dev/loop5 / ext2 defaults 0 1 /dev/loop6 none swap sw 0 0 /dev/loop4 /home ext2 defaults 0 2 In above example, device /dev/hda666 is used as encrypted swap with fixed key. If you set up swap with fixed key like in above example, don't forget to initialize swap space by running "mkswap /dev/loop6" once. /dev/hdd666 is used as encrypted /home partition. /dev/loop5 is encrypted root partition, and it set up by /linuxrc program in "initrd" ram-disk. 7.6. Example 6 - Boot from CD-ROM + encrypted root partition ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here is slight variation of above 'encrypting root partition' instructions. Computer gets booted from read-only CD-ROM and there is no need for any unencrypted partitions on the hard disk. 1-6) Same as above 'encrypting root partition' steps 1-6. 7) Copy kernel version specific loop.o or loop.ko module to CD-ROM source directory rm -r -f /boot/iso/modules-* mkdir -p /boot/iso/modules-2.4.22aa1 ^^^^^^^^^ cp -p /lib/modules/2.4.22aa1/block/loop.*o /boot/iso/modules-2.4.22aa1/ ^^^^^^^^^ ^^^^^^^^^ 8-9) Same as above 'encrypting root partition' steps 8-9, with exception that in step 9 you must write rootkey.gpg to /boot/iso directory instead of /boot directory. 10a) Contents of /boot/initrd.conf configuration file are below. BOOTDEV=/dev/hdc # CD-ROM device BOOTTYPE=iso9660 CRYPTROOT=/dev/hda2 ROOTTYPE=ext2 CIPHERTYPE=AES128 DESTINATIONPREFIX=/boot/iso INITRDGZNAME=../initrd.gz LOADNATIONALKEYB=1 devfs enabled kernel users (CONFIG_DEVFS_FS=y and CONFIG_DEVFS_MOUNT=y in kernel configuration) need to pay special attention to comments above these build-initrd.sh options: USEDEVFS, BOOTDEV, CRYPTROOT and EXTERNALGPGDEV. 10b) Copy your national keyboard layout to CD-ROM source directory in uncompressed form. dumpkeys >/boot/iso/default.kmap 11) Contents of /etc/lilo.conf configuration file are below. Two copies of '/dev/loop7' on first two lines refer to temporary file backed loop mount that is mounted on /mnt later in step 13a. boot=/dev/loop7 disk=/dev/loop7 bios=0x00 sectors=36 heads=2 cylinders=80 geometric compact read-only prompt timeout=30 vga=normal backup=/dev/null install=text map=/mnt/map image=/mnt/vmlinuz label=Linux append="init=/linuxrc rootfstype=minix" initrd=/mnt/initrd.gz root=/dev/ram0 12) Build new /boot/initrd.gz ./build-initrd.sh /boot/initrd.conf 13a) Build and mount minix file system on floppy image dd if=/dev/zero of=/boot/iso/fdimage.bin bs=1024 count=2880 mkfs -t minix -i 32 /boot/iso/fdimage.bin 2880 mount -t minix /boot/iso/fdimage.bin /mnt -o loop=/dev/loop7 13b) Copy kernel and initrd.gz to floppy image cp -p /boot/vmlinuz /mnt/vmlinuz cp -p /boot/initrd.gz /mnt/initrd.gz 13c) Run lilo and unmount floppy image lilo umount /mnt sync 13d) Create boot CD-ROM image mkisofs -r -b fdimage.bin /boot/iso >/boot/bootcdimage.iso 13e) Burn /boot/bootcdimage.iso to CD-R. Resulting CD-ROM is your boot CD-ROM that you use to boot to encrypted root, not the rescue CD-ROM referred to in above 'encrypting root partition' step 14. You may want to burn two copies or at least archive bootcdimage.iso to some unencrypted partition so that you can burn new copy if original CD-ROM gets damaged. 13f) Temporarily disable swap partitions and put a "temporary file system on swap" into one of swap partitions. This example assumes that /dev/hda3 is such swap partition. The 'dd' command clears first 64KB of that partition so that dangerously buggy rescue floppies/CD-ROMs don't enable swap on it. swapoff -a dd if=/dev/zero of=/dev/hda3 bs=64k count=1 conv=notrunc mkfs -t ext2 /dev/hda3 mount -t ext2 /dev/hda3 /mnt 13g) Copy statically linked aespipe and gpg programs and rootkey.gpg file to "temporary file system on swap" partition. cp -p /boot/aespipe /boot/iso/rootkey.gpg /usr/bin/gpg /mnt umount /mnt 14-19) Same as above 'encrypting root partition' steps 14-19, with exception that in step 18 you must rw mount (no -r option to mount) "temporary file system on swap" /dev/hda3 instead of /boot partition. 20) Clean up and reboot your computer. The 'dd' command attempts to overwrite gpg encrypted root partition key file and 'mkswap' command restores "temporary file system on swap" /dev/hda3 back to swap usage. dd if=/dev/zero of=/mnt/rootkey.gpg bs=64k count=1 conv=notrunc umount /mnt sync mkswap /dev/hda3 sync reboot If you are upgrading kernel of a system where root partition is already encrypted, only steps 5 to 7 and 13a to 13e are needed. However, if you are upgrading from 2.4 kernel to 2.6 kernel, new insmod may need to be copied to /boot/iso directory by running step 12 before running step 13a. 8. Security levels ~~~~~~~~~~~~~~~~~~ Loop encryption key can be set up in different ways. Just in case it isn't obvious how these different ways rank security wise, here is a list of security levels from 1 (highest security) to 4 (lowest security). 1) gpg encrypted 'multi-key' key file and/or gpg public+private keys are stored on separate removable USB dongle that is not available to attacker. If USB dongle and its key files are available to attacker, security level is equivalent to level 2. (Example 2) 2) gpg encrypted 'multi-key' key file and gpg public+private keys are stored on disk that is available to attacker. This assumes that included gpg patch is applied to gpg and symmetric cipher encrypted key file or private keyring password was created/changed with patched version. (Example 3) 3) Loop is used in single-key mode. Random password seed and iteration count are used to slow down optimized dictionary attacks. This level is vulnerable to watermark attacks. Watermarked files contain special bit patterns that can be detected without decryption. 4) Loop is used in single-key mode. Neither password seed nor gpg encrypted key file are used. This level is vulnerable to optimized dictionary attacks as well as watermark attacks. (mainline linux cryptoloop is example of this type of backdoored crypto) 9. Performance tuning for 2.4 and newer kernels ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Loop-AES driver for 2.4 and newer kernels understand two additional options: lo_prealloc and lo_nice. First number of 'lo_prealloc' is the default number of RAM pages to pre-allocate for each device backed (partition backed) loop. Every configured device backed loop pre-allocates this amount of RAM pages unless later 'lo_prealloc' numbers provide an override. 'lo_prealloc' overrides are defined in pairs: loop_index,number_of_pages. If 'lo_prealloc' is undefined, all pre-allocations default to 125 pages. A maximum of four overrides (four number pairs) can be used. This example line added to your /etc/modules.conf file means that each device backed loop device pre-allocates 100 pages of RAM at losetup/mount time, except that /dev/loop6 allocates 200 pages, and /dev/loop5 allocates 250 pages. options loop lo_prealloc=100,6,200,5,250 On x86 systems page size is 4 Kbytes, some other architectures have 8 Kbyte page size. lo_nice option sets scheduler nice for loop helper threads. Values between 0 (low priority) to -20 (high priority) can be used. If loop transfers are disk transfer rate limited, lowering loop thread priority may improve performance. If loop transfers are CPU processing power limited, increasing loop thread priority may improve performance. renice(8) command can be used to alter nice values of loop helper threads while loop is being used. Example /etc/modules.conf line: options loop lo_nice=-4 If lo_nice is not set, default nice value for kernels with old scheduler is -20. For kernels with O(1) scheduler, default nice value is -1. 2.6 kernels include anticipatory (the default) and deadline I/O schedulers. Deadline I/O scheduler may improve performance of device backed loop devices. Please read kernel's Documentation/as-iosched.txt file for more information. 10. Files ~~~~~~~~~ ChangeLog History of changes and public releases. Makefile Makefile to build and install loop.o module. README This README file. aes-GPL.diff A patch for aes-amd64.S and aes-x86.S files that updates licenses to be fully GPL compatible. aes-amd64.S and aes-x86.S files are derived from Brian Gladman's December 2001 published version that had no mention of GPL, but both Brian Gladman and Jari Ruusu permit this license change. aes-amd64.S Optimized assembler implementation of AES cipher for AMD64 and compatible processors. aes-x86.S Optimized assembler implementation of AES cipher for x86 processors. aes.[ch] AES encryption functions, portable and usable in kernel and in user space, as well as in other operating systems. build-initrd.sh Bash shell script to build a small initrd ram-disk that can be used when root partition is encrypted. dkms.conf Configuration file for Dynamic Kernel Module Support. http://linux.dell.com/dkms/dkms.html for more info. This dkms.conf can't be used to compile loop module with partial kernel sources that some distros provide. Build procedure depends on presence of full kernel sources, and using partial kernel source to build loop module will guarantee miscompiled loop module. glue.c Glue logic between loop driver and encryption functions in aes.c / aes-*.S and md5.c / md5-*.S gnupg-*.diff Optional patch for gpg that increases password iteration and thus slows down dictionary attacks against gpg encrypted key files. gpgkey[12].asc gpg encrypted key files that are used by Makefile when "make tests" command is run. These key files are encrypted with symmetric cipher using 12345678901234567890 password. kernel-2.[46].*.diff Kernel patch for those people who prefer not to use modules. Before this patch can be applied to your kernel, drivers/block/loop.c and include/linux/loop.h source files must be removed using 'rm' command. Obviously applying this patch changes your kernel sources, so this is not entirely hassle free. This patch is against recent mainline kernel. If this patch doesn't apply cleanly to your kernel, I don't want to know about it. Note: you only need to build loop.o module or apply this patch but not both. loop.c-2.[02].diff Kernel version specific patches that fix bugs and preregisters AES cipher transfer to latest loop.c source. loop.c-2.[02].original Unmodified loop.c sources that are used as secondary source if patch does not apply cleanly to primary source. Primary source is the loop.c of your kernel. loop.c-2.[46].patched Pre-patched loop.c sources for kernels where changes are so extensive that distributing *.original plus *.diff does not make sense. md5-amd64.S Optimized assembler implementation of MD5 transform function for AMD64 and compatible processors. md5-x86.S Optimized assembler implementation of MD5 transform function for x86 processors. md5.[ch] MD5 transform function implementation that is used to compute IVs. This source code was copied from Linux kernel CryptoAPI implementation. util-linux-2.12*.diff Util-linux patch that adds support for AES and other ciphers. 11. Credits ~~~~~~~~~~~ This package uses AES cipher sources that were originally written by Dr Brian Gladman: // Copyright (c) 2001, Dr Brian Gladman , Worcester, UK. // All rights reserved. // // TERMS // // Redistribution and use in source and binary forms, with or without // modification, are permitted subject to the following conditions: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. The copyright holder's name must not be used to endorse or promote // any products derived from this software without his specific prior // written permission. // // This software is provided 'as is' with no express or implied warranties // of correctness or fitness for purpose. Util-linux patch has few lines of documentation copied from international crypto patch: -p option documentation in losetup and mount man pages were written by Marc Mutz. Util-linux patch includes rmd160.[ch] files that were copied from international crypto patch: they were originally written by GnuPG team and modified by Marc Mutz.