AES-encrypted root partition using LVM2

From Gentoo Linux Wiki

Jump to: navigation, search
Please format this article according to the Style Guidelines and Wikification suggestions, then remove this notice {{Wikify}} from the article.

Reason(s):

  • clarify some actions ("unpack your system", "something like yaddayadda", "setup xyz")
  • don't use code templates for commands

Filesystems TOC

Filesystem.png

This howto describes installing Gentoo to achieve strong and full encryption, yet still be fast and flexible.

Contents

[edit] Introduction

Gentoo will be installed on the following layers

  1. filesystem
  2. loop-AES encryption
  3. LVM2 logical volumes
  4. disk partition.

[edit] Approach

The approach taken here is to store an encrypted gpg keyfile in a ~20M unencrypted /boot partition. The rest of the disk is either encrypted swap or encrypted storage.

An alternative is to put the keyfile on a thumb drive, or even boot from a thumb drive. There might be a theoretical advantage of this, but practically, I don't see the point. It's much better to concentrate on strong passwords.

The storage can be an ordinary device-backed loop or LVM backed loop. Either way an initrd is needed, so I think the LVM route is not that much extra effort.

Don't put swap inside a logical volume. Establish it on the first possible partition. From what I've read swap needs to be at the beginning of the disk and if it is inside LVM you can't say where on the disk it is. I can't think of why you would want the flexibility of LVM for swap anyway.

[edit] Assumptions

This howto assumes:

  1. That the installation will be on fresh hardware; and
  2. That the user is reasonably familiar with installing Gentoo and the use of logical volumes.

[edit] Work

Leave the Gentoo Live disk in its case as it doesn't include a patched losetup. I use and recommend Knoppix. I'm using 5.1.1., but for cpqarray hardware I use version 4 and get LVMv2 from somewhere else.

Boot Knoppix, check and maybe repair the network connection and stop the X server (you don't need it):

/etc/init.d/xsession stop

Set the password for the knoppix user (so you can log in later):

passwd knoppix
Note: You may complete the rest of the installation remotely from a separate computer if you wish. In order to do this, start the ssh server in knoppix on the machine:
/etc/init.d/ssh start
Then ssh into the machine from the comfort of your favourite chair.

[edit] Partition the disk(s)

Use fdisk, cfdisk or something to arrange the partitions that you will be installing onto. Reboot if the software requires it. For the purpose of this documentation the following configuration will be used:

fdisk -l /dev/hdb
Disk /dev/hdb: 40.0 GB, 40020664320 bytes
255 heads, 63 sectors/track, 4865 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdb1               1           2       16033+  83  Linux
/dev/hdb2               3          63      489982+  82  Linux swap / Solaris
/dev/hdb3              64        2495    19535040   8e  Linux LVM
/dev/hdb4            2496        4865    19037025    5  Extended
/dev/hdb5            2496        4865    19036993+  8e  Linux LVM
hdb3 and hdb5 could have been one partition but are two here to illustrate a point later on. /boot needs a filesystem, so make one:
mke2fs /dev/hdb1

[edit] A volume for root

Create the physical volumes:

pvcreate /dev/hdb3 /dev/hdb5
Physical volume "/dev/hdb3" successfully created
Physical volume "/dev/hdb5" successfully created

Put a volume group called "vg" on those physical volumes:

vgcreate vg /dev/hdb3 /dev/hdb5
Volume group "vg" successfully created

Put a logical volume to hold your root filesystem on the volume group:

lvcreate --name root -L1G vg
Logical volume "root" created
Note: With cpqarray computers, and hence operating under Knoppix 4, copy the lvm executable into /boot (with scp or another method of copying). The above commands then look like:
/boot/lvm vgcreate vg /dev/hdb3 /dev/hdb5

[edit] Encryption for /dev/vg/root

Make a gpg key with something like

head -c 3705 /dev/random | uuencode -m - | head -n 66 | tail -n 65 | gpg --symmetric -a >/mnt/hdb1/keyfile.gpg

Or, make one available from somewhere else. I don't care how much mouse wiggling you do, my experience is that this takes forever with /dev/random, so if experimenting, choose /dev/urandom.

Fill the partition with random looking data.

head -c 15 /dev/urandom | uuencode -m - | head -n 2 | tail -n 1 | losetup -p 0 -e AES128 /dev/loop3 /dev/vg/root dd if=/dev/zero of=/dev/loop3 bs=4k conv=notrunc 2>/dev/null # This can take a while losetup -d /dev/loop3

An encrypted loopback is established over the top of the logical volume with:

losetup -e AES128 -G / -K /tmp/keyfile.gpg /dev/loop1 /dev/vg/root

By way of a suggestion:

mkreiserfs /dev/loop1

Then

mount /dev/loop1 /mnt/hdb3

and follow the rest of the install procedure.

In addition to the tools listed in the howto, also:

emerge sys-fs/lvm2

Don't reboot yet.

[edit] A new mount, umount, losetup, swapon and swapoff

Other distro users will have to follow Section 4 of the readme. We:

echo "sys-apps/util-linux loop-aes" >> /etc/portage/package.use emerge sys-apps/util-linux loop-aes

[edit] Loop-AES readme steps

What follows are some annotations against example 5 in the loop-AES readme.

[edit] Dietlibc

emerge dev-libs/dietlibc

[edit] Aespipe

This is not required because we are doing a fresh install, not a conversion.

[edit] Static gnupg

echo "app-crypt/gnupg static" >> /etc/portage/package.use
emerge app-crypt/gnupg

[edit] Backup

Only you know what to do here.

[edit] Kernel

Linux Kernel Configuration:
General setup --->

   [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support

Device Drivers --->

   [*] Block devices  ---> 
       <*>   RAM disk support
       (4096)  Default RAM disk size (kbytes)

File systems --->

   Pseudo filesystems  --->  
       -*- /proc file system support  
   Miscellaneous filesystems  --->  
       < > Compressed ROM file system support (cramfs) 

If necessary,
make modules && make modules_install
and copy the kernel into /boot.

[edit] Loop module

Grab the latest loop-AES:

wget http://loop-aes.sourceforge.net/loop-AES-latest.tar.bz2 wget http://loop-aes.sourceforge.net/loop-AES-latest.tar.bz2.sign gpg --recv-keys 0x3A220F51 #probably needed gpg loop-AES-latest.tar.bz2.sign #no problems?

Then make the module:

tar -jxf loop-AES-latest.tar.bz2 cd loop-AES-[] make LINUX_SOURCE=/usr/src/linux
Warning: Don't change
Linux Kernel Configuration:
   Processor type and features  ---> 
      High Memory Support
after building the loop module - you might end up with ioctl: LOOP_SET_FD: Cannot allocate memory at the password prompt.

[edit] Copy loop module

Make sure /boot is mounted and copy the module in:

mkdir /boot/modules-[] cp -p /lib/modules/[]/extra/loop.ko /boot/modules-[]/

[edit] Encryption keys

Completed

[edit] build-initrd.sh

This is the most difficult part. In loop-AES-[]:

cp build-initrd.sh build-initrd.conf nano build-initrd.conf

and remove and remove everything after ### End of options. Edit build-initrd.conf along the following lines

File: build-initrd.conf
USEPIVOT=2
BOOTDEV=/dev/hdb1
CRYPTROOT=/dev/hdb3
ROOTTYPE=reiserfs
GPGKEYFILE=keyfile.gpg
USEROOTSETUP=1''

Create /boot/rootsetup:

File: /boot/rootsetup
#!/lib/sh
if [ "x$1" != "x-d" ] ; then
    /lib/mkdir -p /proc /dev/mapper
    /lib/mount -n -t proc proc /proc
    /lib/mknod /dev/hdb5 b  3  69
    /lib/lvm vgscan --ignorelockingfailure
    /lib/lvm vgchange -ay --ignorelockingfailure
    /lib/umount -n /proc
    /lib/losetup -e AES128 -K /lib/keyfile.gpg -G /lib /dev/loop5 /dev/mapper/vg-root
    x=$?
    exit ${x}   # exit with return status of losetup
else
    /lib/losetup -d /dev/loop5
    x=$?
    exit ${x}   # exit with return status of losetup
fi

Note the mknod /dev/hdb5 line. If the logical volume on which root is placed consists of more than one physical volume, you need manually mknod for each device in addition to the one create by CRYPTROOT= in rootsetup.

In this example the logical volume is composed of the physical volumes /dev/hdb3 and /dev/hdb5. The CRYPTROOT=/dev/hdb3 line in build-initrd.conf establishes /dev/hdb3, and to make /dev/hdb5 we need the mknod /dev/hdb5 line in /boot/rootsetup.

We need some more /root preparations:

chmod 755 rootsetup cp -p /bin/mkdir /boot/ cp -p /bin/mount /boot/ cp -p {/lib/libblkid.so.1,/lib/libuuid.so.1} /boot cp -p /bin/mknod /boot/ cp -p /sbin/lvm /boot/ cp -p /bin/umount /boot/ echo "app-shells/dash static" >> /etc/portage/package.use emerge app-shells/dash cp -p /bin/dash /boot/ cd /boot && ln -sf dash sh

[edit] Boot loader config

I use sys-boot/grub. My /boot/grub/grub.conf looks something like:

File: /boot/grub/grub.conf
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
title=kernel-2.6.23-gentoo-r3
root (hd0,0)
kernel /boot/kernel-2.6.23-gentoo-r3
initrd /initrd.gz

[edit] A new /boot/initrd.gz

Make sure /boot is mounted.

./build-initrd.sh build-initrd.conf
Loading config from 'build-initrd.conf'
12 blocks
-rw------- 1 root root 2446 Jun 17 19:19 /boot/initrd.gz
Copying /sbin/losetup to /boot
Copying /lib/libc.so.6 to /boot
Copying /lib/ld-linux.so.2 to /boot
Copying /sbin/insmod to /boot
Copying /lib/libz.so.1 to /boot
Copying /lib/libc.so.6 to /boot
Copying /lib/ld-linux.so.2 to /boot
Copying /usr/bin/gpg to /boot
Done.

[edit] Boot loader

Perform this as part of the howto.

Note: This is a bit off topic, but, in order to get Grub to recognise a cciss array I had to device (hd0) /dev/cciss/c0d0 at the grub prompt as the first command.

[edit] Boot

The first boot into Gentoo.

reboot

A boot into Gentoo feels like this. After the power is turned on, your computer will proceed through bios checks, the boot loader and the kernel will load. Booting will then halt with a password prompt. After the password is correctly entered booting will continue. Once booted, df lists the mounted loopback devices.

[edit] A cleartext loopback for a data logical volume

We have an encrypted / but still no where for data to go. We need to size /data create a cleartext encrypted loopback.

[edit] Size /data

It is assumed that the rest of the disk should be allocated to /data. When booted from a CD and not in a chroot, pvdisplay and add up all of the Free PE values. Then create the logical volume
lvcreate -l Free PE vg -ndata

[edit] Clear text keyfile

The keyfile for the data logical volume should not have a password. The file should be clear text. This is because it is going to be stored in an encrypted partition and you don't want to have to enter passwords unnecessarily.

head -c 3705 /dev/random | uuencode -m - | head -n 66 | tail -n 65 >/etc/fskey-data losetup -e AES128 -P /etc/fskey-data /dev/loop1 /dev/vg/data mkreiserfs /dev/loop1 mkdir /data mount /dev/loop2 /data

head -c 3705 etc might return bash: uuencode: command not found. This can be solved by emerge app-arch/sharutils, or perform the head -c 3705 etc from outside the chroot. -P for <=loop-AES-v3.2b does not work.

Inside the chroot edit /etc/init.d/checkfs

File: /etc/init.d/checkfs
#put the following lines at the top
ebegin "Setting up loops"
/etc/init.d/setup_loop

And create /etc/init.d/setup_loop.

File: /etc/init.d/setup_loop
#!/bin/sh
losetup -e AES128 -P /etc/fskey-data /dev/loop1 /dev/vg/data
chmod 750 /etc/init.d/setup_loop
Note: I would really appreciate a better solution than this kludge.

[edit] fstab

fstab might end up looking like

File: /etc/fstab
/dev/loop5   /         reiserfs  noatime                               0 1
/dev/loop1   /data     reiserfs  noatime                               0 2
/dev/hdb2    none      swap      sw,loop=/dev/loop6,encryption=AES128  0 0
/dev/hdb1    /boot     ext2      noauto,noatime                        1 2

[edit] Murphy's law

When things go wrong, like grub not working or something, a set of commands like this might be needed to re-establish a chroot.

ssh root@encrypted_delight
Welcome to Knoppix!
root@Knoppix:~# 
cd /mnt mkdir gentoo mount /dev/cciss/c0d0p1 gentoo/ vgchange -ay
  2 logical volume(s) in volume group "vg" now active

losetup -e AES128 -G / -K gentoo/gpg.key /dev/loop1 /dev/vg/root

Password: 
umount gentoo/ mount /dev/loop1 gentoo/ cd gentoo mount -t proc none proc/ mount -o bind /dev/ dev/ mount /dev/cciss/c0d0p1 boot/ chroot ./ /bin/bash env-update

[edit] References

This howto is an elaboration on the loop-AES readme and the heavily commented build-initrd.sh.

Personal tools