In a personal computer scenario, encrypting the whole system is not much more complicated than just encrypting the /home partition, and I see no reason not to do so.
On Linux, I determined dm-crypt, which is part of the kernel, to be the best option. It works as an overlay. It provides a decrypted block device sitting on top of another block device, encrypted. The whole deal tries to be transparent for users of those block devices (eg: filesystems).
Dm-crypt needs a choice of cryptographic algorithms and a key to work. They can be provided by hand but there's also LUKS, which is a special block device format that embeds keys and metadata itself. However, it is designed in a way so that partitions that use it are easy to destroy and to achieve so it spreads the keys through the disk in a way that if even a part goes missing, the whole key is not recoverable. That has its uses but certainly also makes LUKS partitions much more vulnerable to data loss.
When not using LUKS, there's the problem that a method is needed for securely storing the keys. One way to do it is to have a small LUKS partition which contains the keys for the actual root. This small partition can even be stored in a file and used through a loopback device. This trivializes backing the keyring up. I'll be describing this method.
Firstly we'll prepare a LUKS loopback partition in a file, then create some keys storing them in it. For this example aes-cbc-essiv:sha256 has been used, as it's cryptsetup's default when creating plain partitions. It could have been anything else; aes-xts-plain64 is a popular choice. (update: aes-xts-plain64 is now the default for LUKS and a good choice)
Create a LUKS loopback to store keys
#16MB can fit a lot of keys.dd if=/dev/urandom of=keys.luks bs=1M count=16 losetup /dev/loop0 keys.luks cryptsetup luksFormat /dev/loop0 cryptsetup luksOpen /dev/loop0 keyring #LUKS default is decent, but let's verify just in case (aes-cbc-essiv:sha256) cryptsetup status keyring mkfs.ext3 -m0 /dev/mapper/keyring mkdir /mnt/whatever mount /dev/mapper/keyring /mnt/whatever/
Create the keys for the real partition
dd if=/dev/random of=gentoo_root.key bs=1 count=32 cryptsetup -v -c aes-cbc-essiv:sha256 -d gentoo_root.key create name device cryptsetup luksClose keyring mkfs.xfs -L gentoo_root /dev/mapper/gentoo_root mount /dev/mapper/gentoo_root /mnt/gentoo/
Next is preparing a kernel that is capable of booting such an encrypted root partition. The solution I went with is to use an initramfs to do the required setup. I'm using Gentoo genkernel's initrd feature as a base, so I'll only cover the part that sets up the encrypted root.
Kernel checklist (as builtin or modules included in the initrd)
- General setup/Initial RAM filesystem and RAM disk (initramfs/initrd) support
- harddisk bus drivers to access /
- Multiple devices driver support (RAID and LVM) -> crypt target
- cryptoapi/CBC,SHA256,SHA384,SHA512,BLOWFISH,TWOFISH,SERPENT,AES (the ones we use! SHA256, CBC, AES)
- drivers/block devices/loop
- drivers/block devices/initrd support (on by default)
- filesystems/pseudo/Virtual memory file system support (on by default)
- Support for the filesystem the root is in (as always) and the keyring's filesystem.
CPIO swiss army knife
- cpio -idv <file
- find .|cpio -ov >file
- genkernel --linuxrc=/usr/src/linuxrc --luks initramfs
- the --linuxrc param must be an absolute path.
- The default linuxrc script is: /usr/share/genkernel/defaults/linuxrc
Somewhere in the linuxrc
- Adapt this to suit your specific needs.
#Roc: fugly as hell but working setup of encrypted / good_msg 'Setting up encrypted root (Roc)...' mkdir vfat mount /dev/sda1 vfat -o ro losetup /dev/loop0 vfat/keyring.luks cryptsetup luksOpen /dev/loop0 keyring mkdir keyring mount /dev/mapper/keyring keyring -o ro cryptsetup -d keyring/gentoo_root.aes-cbc-essiv\:sha256.key -s 256 -c aes-cbc-essiv:sha256 --tries 256 create gentoo_root /dev/sda8 umount keyring rmdir keyring cryptsetup luksClose keyring losetup -d /dev/loop0 umount vfat rmdir vfat
RAM is generally trusted to temporarily store sensitive data. It's a problem when the system decides to page some memory into a swap partition, as that's permanent storage. Even worse, it could be read pretty easily by an attacker with physical access.
A way to deal with that is to have the swap block device be encrypted. As swapped information doesn't need to survive across reboots a random new key can be used for swap at each boot.
We'll be using mkswap to create a new swap at every boot, so it'd be dangerous if device order or partition order or something changed. In order to avoid that, there's many options. We'll detail some.
Option 1: LVM
- partition type 8e for LVM
We create some basic LVM setup like this
pvcreate <dev> vgcreate swapvg <dev> lvcreate -n swapdev -l 100%vg swapvg
And these scripts for setting it up at /etc/local.d
#!/bin/bash cryptsetup -d /dev/urandom create swap0 /dev/mapper/swapvg-swapdev mkswap /dev/mapper/swap0 swapon /dev/mapper/swap0
#!/bin/bash swapoff /dev/mapper/swap0 cryptsetup remove swap0
Option 2: swapfile
We create a swap file like this
dd if=/dev/urandom of=/boot/swapfile bs=1M count=<size_in_mb>
And these scripts for setting it up at /etc/local.d
#!/bin/bash losetup /dev/loop0 /boot/swapfile if [ "$?" -eq "0" ]; then cryptsetup -d /dev/urandom create swap0 /dev/loop0 if [ "$?" -eq "0" ]; then mkswap -f /dev/mapper/swap0 swapon /dev/mapper/swap0 exit 0 else echo "(encrypted swapfile) Oops. Missing kernel support for the relevant crypto stuff." exit 1 fi else echo "(encrypted swapfile) Oops. /dev/loop0 is already in use." exit 1 fi exit 1
#!/bin/bash swapoff /dev/mapper/swap0 cryptsetup remove swap0 losetup -d /d
Notes on Windows and TrueCrypt
On Windows, one of the popular options is TrueCrypt.
- Sometimes we'll need to mount a TrueCrypt system drive on Linux:
truecrypt --mount -m system <dev> <mountpoint>
- To load the TrueCrypt bootloader from Grub2: https://gitorious.org/grub2tc/grub2tc
- cryptsetup: https://code.google.com/p/cryptsetup/
- FreeOTFE: http://freeotfe.org/
- TrueCrypt: http://www.truecrypt.org/