encrypted disc hint

Robert Connolly robert at linuxfromscratch.org
Mon May 30 14:14:49 PDT 2005

Hello. I'm working on an encrypted disc hint. I'm not sure if any of you have 
experience with this. I think its okay so far, I'm not sure if there's an 
easier way to do the partition offsets. I combined what I gathered from the 
disc encryption howto, the encrypted root filesystem howto, and the loop-aes 
readme. I think I found a way to use random keys/passwords for swap without 
having a clear partition table.

Anyway. If anyone of you could look it over and comment on it I would 
appreciate it.

-------------- next part --------------
AUTHOR:		Robert Connolly <robert at linuxfromscratch dot org> (ashes)

DATE:		2005-05-30

LICENSE:	Public Domain

SYNOPSIS:	Encrypted disc hint

PRIMARY URL:	http://www.linuxfromscratch.org/hints/

This hint describes how to install HLFS, or LFS, to a disc which is encrypted
end to end. This hint is different from other documents in that the entire drive
(and partition information) is encrypted, GnuPG is used to encrypt the disc
key, and the swap space gets a random key. Encrypted discs are popular on
laptops, and other mobile storage media, to protect data from physical theift.

Using this hint, if the disc drive is stolen and installed to another computer,
the data will be unreadable without the encryption key. The encryption key (in
this hint) is a 65 line random sequence generated by the Linux-2.6 random number
generator, which is generally considered quite good quality. This key is also
encrypted with GnuPG to password protect it. With the key encrypted the password
can be changed in the future, and if the key is also stolen it too is
unreadable. Both the drive and key are encrypted with Advanced Encryption
Standard (AES), also known as Rijndael. The AES cipher algorithm is currently
considered the most secure algorithm available. The passphrase for the
encrypted key is hashed with the sha512 algorithm. It is currently believed both
AES and sha512 could not be cracked by the combined power of every computer on
earth with thousands of years of time.

There are a few issues you should be aware of. Anytime the drive is mounted the
key is in memory in plain text. The root user has permssion to access this
memory. If an intruder gains root access they can make a copy of the decrypted
key to use it anytime. Second, any user on the computer can read the filesystem
of the encrypted discs, depending on the filesystem permissions, and make
copies of the decrypted files. One way to protect against intruders is with a
password protected screen saver. Lastly, there is no deniability with this. It
is completely obvious that you have encrypted the entire drive, and it is
impossible for you to claim you didn't.

This hint uses loop-AES, a third party kernel patch. The cryptoloop driver that
is included with the 2.6 series kernel will be removed because of design
problems, and it is not suggested that you use it.

Also see:
The README file in the loop-AES source is also good to read.

One extra disc drive, large enough to install LFS on to with room to spare
(about 2GB or more).


# This is a long hint. You should probably read the whole thing before you start
# it.

# Some things needs to be done before starting the HLFS/LFS installation. A new
# modified kernel will need to be installed, and new mount and swap utilities
# are needed. A new GnuPG is also suggested. Because the entire drive is
# encrypted we will have to boot from something else, like two floppies or a
# compact disc. I prefer two floppies because the 2.6 kernel changes often. To
# make the initial ramdisk image I use SquashFS with LZMA compression. LZMA
# compression is up to 30% better than the standard Zlib. The kernel team
# currently believes Zlib is good enough, so there are some politics at the
# moment preventing the SquashFS team from implementing LZMA.. but I'll use it
# regardless.


GnuPG download:

For squashfs download:

# Before you start anything here you should do backups, and have a rescue disc.

# --- Part 1 - Setting up the host ---

# Unpack loop-AES and the new kernel:
tar jxf loop-AES-v3.0c.tar.bz2 &&
tar jxf linux- &&
cd linux-

# And patch the new kernel:
rm drivers/block/loop.c include/linux/loop.h &&
patch -Np1 -i ../loop-AES-v3.0c/kernel-2.6.11.diff &&
patch -Np1 -i ../linux-2.6.9-squashfs-2.1_lzma-mc1.patch &&
patch -Np1 -i ../linux- &&
make mrproper

# By default there's a limit of 8 loop devices. We need one loop device for
# each partition we plan to mount, plus a few to spare. The maximium is 256.
# Raise the limit to 32 with this:
sed -e 's/max_loop = 8/max_loop = 32/' -i drivers/block/loop.c

# Make your entropy poolsize bigger (double size):
sed -e 's/^\(.*DEFAULT_POOL_SIZE.*\) 512/\1 1024/' -i drivers/char/random.c &&
sed -e 's/^\(.*SECONDARY_POOL_SIZE.*\) 128/\1 256/' -i drivers/char/random.c &&
sed -e 's/^\(.*BATCH_ENTROPY_SIZE.*\) 256/\1 512/' -i drivers/char/random.c

# Build the kernel normally, be sure to leave CONFIG_FRANDOM built in (not
# CONFIG_BLK_DEV_LOOP_KEYSCRUB should also be built in for now. CONFIG_SQUASHFS
# is not enabled by default, be sure to build that in too, it is under
# "Miscellaneous filesystems". Note that this kernel may be unable to decompress
# third-party initrd's compressed with the standard zlib.

# Install the new kernel and reboot it.

# Unpack the SquashFS and LZMA utils:
tar zxf squashfs2.1-r2.tar.gz &&
mkdir lzma417/ &&
tar jxf lzma417.tar.bz2 -C lzma417/

# Patch LZMA and mksquashfs:
cd lzma417/ &&
patch -Np1 -i ../lzma-406-zlib-stream.patch
cd ../squashfs2.1-r2/ &&
patch -Np1 -i ../squashfs2.0-tools-lzma.patch

# Build mksquashfs:
make -C squashfs-tools/ &&
install squashfs-tools/mksquashfs /sbin &&
cd ..

# Unpack util-linux:
tar jxf util-linux-2.12q.tar.bz2 &&
cd util-linux-2.12q

# Patch, configure, build and install the util-linux programs:
patch -Np1 -i ../loop-AES-v3.0c/util-linux-2.12q.diff &&
./configure &&
make SUBDIRS="lib mount" &&
cd mount &&
install -d /root/loop-AES-utils/{bin,man}/ &&
install mount umount losetup swapon /root/loop-AES-utils/bin/ &&
install -m 644 {mount,umount,losetup,swapon,swapoff}.8 /root/loop-AES-utils/man/ &&
install -m 644 fstab.5 /root/loop-AES-utils/man/ &&
cd ../../

# Set a new $PATH
export PATH=/root/loop-AES-utils/bin:$PATH

# You might want to read the entropy.txt hint, and install and run rngd and/or
# audio-entropyd before proceeding.

# To encrypt the swap space, first turn on swapping:
swapoff -a

# Next edit /etc/fstab and add "loop=/dev/loop?" and "encryption=AES256" to the
# swap lines, so it looks like this:
# /dev/hdb5 swap swap loop=/dev/loop6,encryption=AES256,pri=1 0 0

# Clear and remake your swap space:
dd if=/dev/zero of=/dev/SWAP_PARTITION bs=64k conv=notrunc &&
mkswap /dev/SWAP_PARTITION

# And finally enable encrypted swap:
swapon -a &&
rm -rf /var/log/ksymoops

# Now we can install GnuPG. Unpack, patch, configure, make, and install it:
tar jxf gnupg-1.4.1.tar.bz2 &&
cd gnupg-1.4.1 &&
patch -Np1 -i ../gnupg-1.4.1-loop_AES-3.0c.patch &&
./configure --prefix=/root/loop-AES-utils --enable-static-rnd=linux \
	--libexecdir=/usr/lib --enable-noexecstack &&
make &&
make install &&
cd ../

# Run the loop-AES tests (this should return "*** Test results ok ***"):
cd loop-AES-v3.0c &&
make tests &&
cd ../

# Wipe the disc you are going to install to, for me HLFS_DISC=hda. This can
# take a long time:
dd if=/dev/frandom of=/dev/HLFS_DISC

# Now we make a key. The secret used as a key for losetup is a random 65 line
# sequence. This secret is piped to our new GnuPG (using increased password
# iteration, and randomly encrypted swap). GnuPG will ask you for a password.
# This GnuPG encrypted key will be kept on floppy, or any other media you wish,
# but try to write it to media sparingly. The less access other people have to
# this key, the better. I write this key to tmpfs (to RAM) until the HLFS/LFS is
# installed, then I copy it to compact flash, compact disc, or floppy. You can
# do whatever you like. I shouldn't have to explain to you how important the
# password is here. Using GnuPG you will be able to change the password later if
# you wish.

# First setup a tmpfs directory with root-only permissions:
install -d -o0 -m0700 /root/keys/ &&
mount -t tmpfs -o rw,size=8k,mode=0700 none /root/keys/

# You can check your available entropy with:
cat /proc/sys/kernel/random/entropy_avail

# With the modification we made to the kernel earlier, a full pool would be
# "8192". In the next command GnuPG is going to need a lot of entropy. The
# kernel gets most of its entropy from the mouse. If it looks like GnuPG is
# stalled then move the mouse around, and maybe bang on the keyboard.

# Then make the key:
export OLDUMASK=$(umask) &&
umask 0277 &&
head -c 2925 /dev/random | uuencode -m - | head -n 66 | tail -n 65 \
	| /root/loop-AES-utils/bin/gpg --symmetric --cipher-algo AES256 \
	--digest-algo SHA512 -a > /root/keys/$(hostname)-HLFS_DISC-key.gpg

# Restore your umask:
umask $(echo $OLDUMASK) &&

# Also see: http://mail.nl.linux.org/linux-crypto/2005-04/msg00001.html

# After creating a key we can divide up the drive. I will try to have put enough
# information here so that you can do anything you like. Partitions don't exist
# with loop devices, we have to use offsets. The largest offset losetup will
# understand is 2GB, except for the last one. There's no frontend program, like
# fdisk, that will do all the calculations for us, so we have to go through some
# hoops to do this. First we run fdisk to make pretend partitions so we can get
# the sectors for each partition we want. We can treat some offsets like
# extended partitions with logical partitions inside them. By this I mean we
# would have an encryption key for one large (extended) partition, and we could
# mount the small (logical) partitions inside it, and they would all share the
# same key and password. Furthermore the swap space can have a randomly
# generated password each time it is initialized, for greater security. These
# offsets will be almost impossible to detect without the decryption keys, there
# is no data on the drive in plain text. Okay, so lets start with fdisk:
fdisk /dev/HLFS_DISC

# There should not be an existing partition table, it was wiped out by dd and
# frandom earlier. Create the partitions the way you want them but don't write
# it. I am creating a 512MB swap partition, two 1GB root partitions, two 512MB
# /var partitions, two 2GB /usr partitions, and the rest for /home. When you are
# done enter "x" to enter expert mode, and "p" to print the partition table.
# Mine looks like this:

Expert command (m for help): p

Disk /dev/hda: 16 heads, 63 sectors, 26377 cylinders

Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
 1 00   1   1    0  15  63 1023         63   26587953 05
 2 00   0   0    0   0   0    0          0          0 00
 3 00   0   0    0   0   0    0          0          0 00
 4 00   0   0    0   0   0    0          0          0 00
 5 00   2   1    0  15  63  992         63    1000818 82
 6 00   1   1  993  15  63 1023         63    2000817 83
 7 00  15  63 1023  15  63 1023         63    2000817 83
 8 00  15  63 1023  15  63 1023         63    1000881 83
 9 00  15  63 1023  15  63 1023         63    1000881 83
10 00  15  63 1023  15  63 1023         63    4000689 83
11 00  15  63 1023  15  63 1023         63    4000689 83
12 00  15  63 1023  15  63 1023         63   11581857 83

# Save your output somewhere, maybe to a file. Enter "r" to return to main
# menu, and "q" to quit without saving. In my table (above) partition 1 is an
# extended partition of the entire disc. Partitions 2, 3, and 4 and unused.
# Partition 5 is the first partition, for swap space. losetup offset and
# sizelimit must be in bytes. Each sector is 512 bytes. The shell can multiply
# for us. A random password is used:
losetup -e AES256 -H random -o @$((512*63)) -s $((512*1000818)) \
	/dev/loop10 /dev/HLFS_DISC

# loop11 is going to be my extended partition. The other seven loop devices 
# and partitions will all use the same encryption key. So, the first partition
# starts on sector 63, and is 1000818 sectors in size. 63 plus 1000818 is
# 1000881. That means the second partition starts on sector 1000881. Because
# this is the extended partition, it takes up the rest of the disc, we don't
# need to specify the size. This partition will use the GnuPG key we made
# earlier:
losetup -e AES256 -K /root/keys/$(hostname)-HLFS_DISC-key.gpg \
	-o @$((512*1000881)) /dev/loop11 /dev/HLFS_DISC

# My first root partition starts on sector 1000881, and is 2000817 sectors in
# size. The offset is the same as the "extended partition" we just made. The
# shell can do the math:
losetup -o @$((512*1000881)) -s $((512*2000817)) /dev/loop12 /dev/loop11

# The second root partition starts on sector $((1000881+2000817)):
losetup -o @$((512*(1000881+2000817))) -s $((512*2000817)) \
	/dev/loop13 /dev/loop11

# The first /var partition:
losetup -o @$((512*(1000881+2000817+2000817))) -s $((512*1000881)) \
	/dev/loop14 /dev/loop11

# The second /var partition:
losetup -o @$((512*(1000881+2000817+2000817+1000881))) -s $((512*1000881)) \
	/dev/loop15 /dev/loop11

# The first /usr partition:
losetup -o @$((512*(1000881+(2*(2000817+1000881))))) -s $((512*4000689)) \
	/dev/loop16 /dev/loop11

# The second /usr partition:
losetup -o @$((512*(1000881+(2*(2000817+1000881))+4000689))) \
	-s $((512*4000689)) /dev/loop17 /dev/loop11

# The /home partition. This is over 2GB, don't use a sizelimit:
losetup -o @$((512*(1000881+(2*(2000817+1000881+4000689))))) \
	/dev/loop18 /dev/loop11

# See the pattern? Still with me? Now we can format:
mkswap /dev/loop10 &&
mkfs.reiserfs /dev/loop12 &&
mkfs.reiserfs /dev/loop13 &&
mkfs.reiserfs /dev/loop14 &&
mkfs.reiserfs /dev/loop15 &&
mkfs.reiserfs /dev/loop16 &&
mkfs.reiserfs /dev/loop17 &&
mkfs.reiserfs /dev/loop18

# Now mount them all. If there is a problem, like overlapping partitions, you
# will see it here:
mkdir /mnt/hlfs &&
mkdir /mnt/hlfs2 &&
mount /dev/loop12 /mnt/hlfs &&
mount /dev/loop13 /mnt/hlfs2 &&
mkdir /mnt/hlfs/var &&
mkdir /mnt/hlfs2/var &&
mount /dev/loop14 /mnt/hlfs/var &&
mount /dev/loop15 /mnt/hlfs2/var &&
mkdir /mnt/hlfs/usr &&
mkdir /mnt/hlfs2/usr &&
mount /dev/loop16 /mnt/hlfs/usr &&
mount /dev/loop17 /mnt/hlfs2/usr &&
mkdir /mnt/hlfs/home &&
mount /dev/loop18 /mnt/hlfs/home

# You will need to remember all the offsets you used for later.. but luckily its
# all found from 'losetup -a', so save the output from losetup.

# Now, take an Advil, and install HLFS.

# --- Part 2 - Installing HLFS/LFS ---

# Copy all the patches and packages from this hint to the HLFS/LFS sources
# directory.

# Chapter 6 - Util-linux:

# Chapter 8 - Kernel:

More information about the hlfs-dev mailing list