Encrypted Harddrive (Gentoo)

So a client bugged me about encryption last week, and I dug up some stuff I wrote probably about six months ago, with all intent of publishing it, but never got round to it. The encryption described here is for Linux (I use Gentoo, most of it should apply to other distributions but I have no idea how easy/hard it would be to set it up with other distributions).

I’m going to assume that you know how to set up Gentoo as per normal, and will thus only highlight what I did different. This is by no means the only way to do this, and there are other howto’s and guides out there which can be used. There wasn’t any document that I could find at the time that described everything though.

Partitioning:

The first thing to note is that the partitioning is not my usual 50MB/512MB/512MB/remainder (/boot, /, swap and LVM) type of setup. Specifically I just create two partitions, one small (100M, but you can easily get away with 20M – even with a few old/backup kernels my /boot usage is currently at 39MB) partition as the first partition for /boot containing everything required to bootstrap Linux on an encrypted LVM container, and then everything else is created inside of LVM.

At this point you should also note that I don’t use suspend to disk (I’m not sure how I would even make that work with encryption, but if/when I do make it work, I’ll blog it), but suspend to ram should be possible (If it wasn’t for the fact that this graphics card doesn’t come back up, I might one day make it work, for now I really couldn’t care).

Setting up the crypted block device:

The crux of the whole thing is that we want everything to be encrypted when it’s written on disk. This will prevent somebody who doesn’t know the passphrase from accessing potentially sensitive data by going directly to the hard-drive, and bypassing operating system control features. Does this imply a performance hit? Yes, it does. But since I’ve got 2GB of RAM and my normal configuration only uses about 256MB in the extreme case for applications and the rest for disk cache, I don’t see this as a big hit. I’ve opted to use the luksFormat, simply because it was recommended, and based on the website the advantages are obvious. The idea is to have a “bootup” password that is required to boot into Linux, and being able to change that password is handy. luksFormat additionally allows for up to eight passwords, which is rather handy.

From a cryptographic perspective this is also good since the actual master key is 100 % random, and encrypted this reduces the possibilities of dictionary attacks. Or at least, it slows it down since for each possible password you now have to first decrypt the key, then decrypt a part of the disk with that, and then be able to verify whether the key is correct. Since we can usually take a guess as to what’s inside the cryptographic container, we can strategically pick what part of the container to perform this decryption on (the beginning should be good as there will be file system of LVM headers of sorts to look for).

In order to make things harder though, we first want to randomize the entire disk, such that the disk will appear entirely random when looking at it, instead of having large parts of the disk as zero, so we start off by running:

dd if=/dev/random of=/dev/sda2 bs=1M

Please note that THIS WILL TAKE A WHILE. You can probably get away with using /dev/urandom (unless you are uber paranoïd and have reason to wait a couple of days). Alternatively you can just make sure to fill the container with _something_ as soon as possible after having constructed it (You have lots of data lying around right? not? Well, ok, just take the windows CD that came with your computer and repeatedly copy it to different filenames until there’s no more space availabe. What? No CD with your computer? What a rip-off :p).

Now it’s time to get that encryption going, this is actually a lot simpler than you can imagine:

cryptsetup -y -s 256 luksFormat /dev/sda2
cryptsetup luksOpen /dev/sda2 root

The first of these commands sets up the luksFormat headers, and other meta data, -y asks cryptsetup to confirm the passphrase, -s informs it we want a 256 bit key, and luksFormat is the command informing cryptsetup to format the device (<tt>/dev/sda2</tt>) using the luks format. This will prompt you for the initial passphrase. Enter it, retype it, and you’re done. The second command opens this encrypted container, you will once again have to enter the passphrase. The last parameter is the name of the device-mapper device that you would like to have created. In the above case this will create <tt>/dev/mapper/root</tt>. This is in leaue of the documentation I based this off of, which can be found here, and will probably be something else when I finally boot the system.

LVM2:

What?!? Yet more layers? Yes. Indeed. The reason you absolutely want to use LVM2 isn’t always obvious. Traditionally UNIX systems always had large numbers of partitions. This was initially due to the relatively small size of disks. For example, /bin and /sbin resided on seperate disks simply because that was the space requirements. Now we have large disks and I’m still advocating severe partitioning. My reasons are not, however, space related but rather they’re security related. Each partition that is being mounted, can have mount options such as noexec, nosuid and nodev to name but a couple. This means that you can (and should) setup /home to be noexec preferably (developers can’t work with noexec), but at least nosuid. /var typcially doesn’t require exec, dev or atime, except for /var/tmp/portage where exec is required, so I sometimes symlink that to a different location. Depending on how paranoid I feel on any given day. That, and I like keeping containers relatively small, also, the added advantage of just adding disks into a system (not that handy on a notebook, but then, this part of the setup isn’t exactly notebook specific). Further advantages includes things like snapshots, which is really handy for making backups.

So, to create the LVM setup on top of the crypted device node I followed this procedure:

  1. Initialize to crypted container to be a LVM physical volume (pv):
    pvcreate /dev/mapper/root
  2. Create the volume group (vg), called lvm in this case (others use vg for obvious reasons):
    vgcreate lvm /dev/mapper/root
  3. And then create a few containers (logical volumes, aka lvs) in there for various filesystems (adjust to suit your needs):
    lvcreate -L1G -nswap lvm
    lvcreate -L512M -nroot lvm
    lvcreate -L4G -nusr lvm
    lvcreate -L4G -nvar lvm
    lvcreate -L10G -nhome lvm
    lvcreate -L1G -nopt lvm
    lvcreate -L512M -ntmp lvm

One of the really cool features of LVM is that if this doesn’t suit your needs later on – simply use the lvm tools to modify this. Much, much simpler than modifying and updating partitions.

Creating the filesystems:

We all have our own opinions regarding file systems, but the fact remains, the two most popular file systems currently is reiserfs and ext3. I use reiserfs for no particular reason (other than it turned out better in my benches). So the following is just a quick way of formatting all the containers created above quickly:

yes | for i in /dev/lvm/*; do mkfs.reiserfs $i; done
mkswap -v1 /dev/lvm/swap
mkfs.ext2 /dev/sda1

Yes. That really is ext2. /boot really does not benefit (imho) from a journal, and somebody is still to show me the contrary.

Resuming/recovering from a reboot:

In case you for some reason need to recover after rebooting and you can’t get into your system, the following commands will re-create the crypt node (this time as encrypted – just to show that the name we give here really doesn’t matter as the kernel handles the lvm stuff in-house and this name is irrelevant):

cryptsetup luksOpen /dev/sda2 encrypted

Now you probably expect to be able to do this:

vgchange -a y

But if you try it you will find that it says “No volume groups found”, which made me raise a few eyebrows the first time. The correct solution is of course to first run:

vgscan

After this a vgchange will do it’s job properly.

Setting up the initrd:

I need to start off by stating that I’m NOT a fan of initrds. Things needs to be repeatable, and whilst I’ve got some experience with embedded systems (the initrd being built here is massively oversized at nearly 6MB worth of content on my system, the scripts doesn’t do a lot of self-correction and generally is doing as little as possible).

Either way, since I like repeatable I’ve opted to just write a script that creates this initrd for me, copies the binaries from my live system (instead of compiling each and every single binary specifically with the stripped down requirements, probably statically and against uclibc instead of glibc).

This script is written in such a way as to operate from within your chroot. Thus you need to make sure that you’ve got the following packages merged into your chroot before attempting to run this script:

  • cryptsetup
  • lvm2
  • busybox (merged by default as the rescue shell)

Note that I’ve chosen busybox since it has far fewer dependencies than bash. Also be sure that you are actually chrooted when you run the script (it might run — and even work — without being in the root, but I have NOT tested this at all).

Some of the functionality can be controlled by exporting environment variables before execution, look at the first few lines, the first block of variable assignments, the default values are also shown here.

You can download the script from here. The script is mostly well commented. You should be able to modify some of the parameters by using environment variables (simplest thing to support, command-line parsing for this is just overkill imho). If you’re in need of clarifications, just post a comment and I’ll see what I can do to address the problem.

/etc/fstab:

There really is not much to this, as per usual, you can add your normal entries, just instead of actual devices you’ll use things like /dev/lvm/${partname} where ${partname} is one of the names of the containers. Use ls /dev/lvm/ to see the names, or lvdisplay. The only partition on this system not part of lvm is /boot, which I always mount with defaults,noatime,nodev,nosuid,noexec,readonly by default, everything else you can go crazy with.

Crypto Notes:

Just to make this explicit, just because your root partition is encrypted, does NOT mean that your system is secure from attackers. In fact, an encrypted hard drive only means something in the case of theft for the purpose of espeoniage, and the majority of people will think you’ve got something to hide. Which you probably do. Your motives for hiding it is your own.

It should be noted that there are many other ways of getting into a system, for example via a specially crafted trojan, hacks against your network, rogue javascript, XSS and XSURF vulnerabilities in trusted websites, a bug in the containment code of your JVM, a kernel vulnerability (such as the vmsplice exploit from Feb 2008), and many, many others. Or you could possibly leave samba open, allowing full access to all your files. If you’re paranoid enough to encrypt your hard drive (and note that this entire howto encrypts the FULL harddrive, not just a single partition, and I explicitly put swap info lvm as well, something I don’t normally do), you should be aware that there are other ways into your systems. If someone is interested I could potentially write a whole book on just that, but I reckon there are sufficient books with enough details of how this is done.

You should also be very aware of the data that you transmit over the internet, email for example is entirely plaintext, and can be sniffed by any of a number of people. In general, if data is committed to the internet you should consider it public property unless it is securely encrypted before being transmitted.

Please note that there has also been recent developments with obtaining the keys for encrypted hard drives from “hot” systems. A hot system is one that is switched on, although it may be locked, or suspended to ram. If you care this much about your data – SWITCH OFF your laptop when it’s not attended, the keys can (when properly prepped, and with a bit of luck) still be recovered for as long as 10 minutes after the laptop has been switched off. For this reason (And I really hope the Linux kernel does this) all in-ram keys that are no longer required should be overwritten in-place with random data.

Comments are closed.