From ArchWiki
Revision as of 07:57, 1 December 2007 by Chris.Giles (talk | contribs) (Added the "Encrypted tmp partition" section)
Jump to navigation Jump to search


There are either 3 or 4 rival disk encryption standards in Linux, depending on how you count them.

The old cryptoloop is deprecated: it's old, insecure and unreliable.

A much better version, loop-AES (, was created but, due to politics, never became favorable with the kernel developers. It's far more secure than either cryptoloop or straight device-mapper encryptions (and probably faster than any of the other 3 options), but is not user-friendly. It also requires non-standard kernel support, which ARCH's kernel26 doesn't have.

The standard device-mapper encryption (dm-crypt) is what the Encrypted_Root_Filesystem HOWTO uses. If used with the ESSIV option (Encrypted Sector Salt Initial Value), it becomes immune to the two most serious vulnerabilities of cryptoloop.

LUKS essentially makes management of encrypted partitions easier. Without going into the hairy details (check out the LUKS home page if you're interested), it stores all the needed setup information on the disk itself. All you need then is the password, which can be in a separate file if you like. The Linux implementation uses dm-crypt, with ESSIV enabled by default, and so should be about as secure as loop-AES (depending on how you manage passwords and key files etc). It can have up to eight different passwords, which can be changed or revoked easily. It is also supported by mkinitcpio in ARCH linux, which is nice.

Note: if you want to have encrypted swap, read the section below about Encrypted Swap and decide how you want to set it up before you start the rest of this HOWTO.

The Steps

Getting started

If you're not starting from an unused hard drive, BACK UP YOUR DATA! I cannot stress this enough. Ideally, you should be doing this regularly anyway, and it's particularly important with an encrypted hard drive. But beware: if you have unencrypted backups, is there any point in having an encrypted hard drive? Think about where you store your backups.


Repartitioning and formatting your drive will only remove the filesystem metadata and will mostly leave the actual data intact, allowing determined attackers to recover data using tools like Foremost. If your harddisk contained sensitive data from previous use, you might want to overwrite this data with random data. This step can take a lot of time depending on your system configuration. A Pentium M 1.2 GHz can write random data at about 100 MB per minute.

# dd if=/dev/urandom of=/dev/sda


Next, set up your partitions as you want. Make sure you have a separate partition for /boot. If you think about it, this is absolutely necessary. If your /boot partition was encrypted, then your bootloader wouldn't be able to read the kernel image and you would not get far.

# cfdisk /dev/sda

The following partition layout will be used:

/dev/sda1 -> /boot
/dev/sda2 -> swap
/dev/sda3 -> /
/dev/sda4 -> /home

Setting up LUKS

Now that we have our real, physical partitions set up, we need to tell cryptsetup to create a new (encrypted) block device based on our root and home partitions, /dev/sda3 and /dev/sda4. But first we have to load the modules that cryptsetup needs.

# modprobe dm-crypt
# modprobe aes-i586

Note: x86_64 users can also try the "aes_x86_64" optimized module instead of "aes-i585".

Create your new LUKS encrypted partitions:

# cryptsetup -y luksFormat /dev/sda3
Enter passphrase: mypassword
Verify passphrase: mypassword
# cryptsetup -y luksFormat /dev/sda4
Enter passphrase: myotherpassword
Verify passphrase: myotherpassword

Then open the newly created LUKS partitions:

# cryptsetup luksOpen /dev/sda3 root
Enter any LUKS passphrase: mypassword
key slot 0 unlocked.
Command successful.
# cryptsetup luksOpen /dev/sda4 home
Enter any LUKS passphrase: myotherpassword
key slot 0 unlocked.
Command successful.

Now you should have a device called /dev/mapper/root, and another one called /dev/mapper/home. These are block devices like any other, but with a neat twist: whenever you write to them, the data is actually written to /dev/sda3 or /dev/sda4 respectively, but it is encrypted first! The only way to access the data on this encrypted partition is to re-create that /dev/mapper/root or /dev/mapper/home device with cryptsetup each time you boot. With LUKS, you can use cryptsetup luksAddKey /dev/sda3 to add a new password, or cryptsetup luksDelKey /dev/sda3 to revoke a password. Type cryptsetup -? or man cryptsetup (once you've booted your new Arch installation) for more info.

Note: With LUKS, if you enter the wrong password, it will reject it. You don't have to worry about it possibly destroying your data.

Note: If you've decided to go for option two for encrypted swap (see Encrypted Swap below), you should set up /dev/mapper/swap in the same way as you've just set up /dev/mapper/home.

Arch Installer

Now that /dev/mapper/root and /dev/mapper/home are in place, we can enter the regular Arch setup script and it will do the rest, as it normally would.

# /arch/setup

Note: Most of the installation can be carried out normally. However, there are a few areas where it is important to make certain selections these are marked below.

Prepare hard drive

Skip the Partitioning and Auto-Prepare business and go straight to "Set Filesystem Mountpoints". When asked for your / (root) partition, do NOT select /dev/sda3 as you normally would. Select /dev/mapper/root instead. Similarly, use /dev/mapper/home instead of /dev/sda4 as the partition to be mounted as /home. The same is valid for a swap partition which is set up like the home partition.

Select packages

The base package contains all required programs. If you want you can add others but it is not required.

Note: If you are installing from a release predating Voodoo (which you really shouldn't) you need to install the system/cryptsetup package.

Install packages

Let the setup install the packages.

Configure System

Attention: You need to answer the question Do you need support for booting from encrypted volumes? with yes.

Let the hwdetect program detect your hardware and answer the questions asked suiting your needs, respecting the above mentioned option.

Afterwards you can check the files presented to you by the installer, the most important one being /etc/mkinitcpio. For detailed info on mkinitcpio (and its configuration) look here.You have to make sure that your HOOKS looks something like this:

HOOKS="... encrypt ... filesystem ..."

It is important that the encrypt hook comes before the filesystem one. If you store your key on an external USB device (e.g. an USB stick), you need to add the USB hook too:

HOOKS="... usb encrypt ... filesystem ..."

For safety, add in usb before encrypt; not sure if they're run in the order they appear in mkinitcpio.conf or not.

Install Kernel

Select the kernel and follow the instructions presented to you by the installer. When asked to check over the /mnt/etc/mkinitcpio.d/kernel26-fallback.conf file make sure the HOOKS line looks the same as mentioned above.

Install Bootloader

GRUB: You have to make some small changes to the entries generated by the installer by replacing /dev/mapper/root with /dev/sda3. The corrected config looks like this:

# (0) Arch Linux
title Arch Linux
root (hd0,0)
kernel /vmlinuz26 root=/dev/sda3 ro
initrd /kernel26.img

LILO: If someone has experience in using LUKS with LILO please fill in.

Exit Install

Now that the install is finished the only thing left to do is add entries to the /etc/crypttab file so you don't have to enter the passphrase for all encrypted partitions. This works only for non-root partitions e.g. /home, swap, etc.

# vi /mnt/etc/crypttab

Add the following line for the /home partition

home    /dev/sda4    "myotherpassword"

If you want to use a key file, generate a key and add it to the LUKS partition by executing the following:

# head -n 220 /dev/urandom | tail -n 200 > /mnt/etc/home.key
# cryptsetup luksAddKey /dev/sda4 /mnt/etc/home.key
Enter any LUKS passphrase: myotherpassword
Verify passphrase: myotherpassword
key slot 0 unlocked.
Command successful.

Then add the following information to the /etc/crypttab file for automounting:

home    /dev/sda4    /etc/home.key

Now the only thing left to do is reboot. Upon booting you should be presented with the text

A password is required to access the root filesystem:

followed by a prompt for any LUKS password. Type it in (mypassword) and everything should boot. Once you've booted and logged in, type mount. You should have /dev/mapper/root mounted at / and, if you set up a separate encrypted home partition, /dev/mapper/home mounted at /home. If you set up encrypted swap, swapon -s should have /dev/mapper/swap listed as your swap partition.

Encrypted swap partition

Sensitive data stored in memory may be written to swap at any time. If you've gone to the trouble of encrypting your root and home partitions, you should encrypt your swap as well. There are two options here: random encryption on each boot (better security, but less elegant), or the same encryption each time. We won't cover the second option here, as it is pretty much identical to how you set up the /home partition above. Just replace all references to home with swap, and sda4 with sda2.

For the first option, we're not going to use LUKS. We're going to set up dm-crypt directly. If you're still in the archsetup process, just switch to a different virtual console (ALT+F2). If you've exited already, the new root will have been unmounted. Use mount /dev/mapper/root /mnt to mount it again.

Now add an entry to the cryptsetup file:

# echo swap /dev/sda2 /dev/urandom "-c aes-cbc-essiv:sha256 -h sha256 -s 256" >> /mnt/etc/crypttab

This will set up /dev/mapper/swap, with underlying block device /dev/hda2, using a random 256-bit key taken from /dev/urandom. Note the use of ESSIV, as in aes-cbc-essiv. That prevents a major cryptographic attack called watermarking.

Now, the bootscripts won't be able to automatically use the resulting partition for swap, because mkswap needs to be run first. So delete the swap entry from /mnt/etc/fstab and add lines to rc.local to set up the swap:

# sed -i /^swap/d /mnt/etc/fstab
# echo "mkswap /dev/mapper/swap" >> /mnt/etc/rc.local

# echo "swapon /dev/mapper/swap" >> /mnt/etc/rc.local

And you're done! Carry on with installation or, if you've already finished, umount /mnt.

Encrypted tmp partition

See the Using DM-Crypt article for more information about this.

Store the key externally (USB stick)

First you should set up your stick with an udev rule. There's some documentation in the Arch wiki about that already, if you want more in-depth, structural info, read this guide. Here's quickly how it goes.

Get the serial number from your USB stick:

lsusb -v | grep -A 5 Vendor

Create a udev-rule for it:

echo 'KERNEL=="sd*", ATTRS{serial}=="$SERIAL", SYMLINK+="$SYMLINK%n"' > /etc/udev/rules.d/8-usbstick.rules

Replace $SYMLINK and $SERIAL with their respective values. %n will expand to the partition (just like sda is subdivided into sda1, sda2, ...). You do not need to go with the 'serial' attribute, if you have a custom rule of your own, you can put it in as well (e.g. using the vendor name).

Rescan your sysfs:


Now check the contents of dev:

ls /dev

It should show your device with your desired name.

Generate a temporary keyfile:

dd if=/dev/urandom of=secretkey bs=512 count=4

To store the key file, you have two options. The first is less risky than the other :-). We assume you are using a FAT-formatted USB stick here, if not, change the MODULES=() line in /etc/mkinitcpio.conf accordingly to provide support for your device.

Now you have to add two extra modules in your /etc/mkinitcpio.conf, one for the stick's file system and one for the codepage: further you should tell mkinitcpio about your udev-rule:

MODULES="ata_generic ata_piix nls_cp437 vfat"

Replace those module names if you use another file system on your USB stick (e.g. ext2) or another codepage. Users running the stock Arch kernel should stick to the codepage mentioned here.

Generate a new image (maybe you should take a copy of your old kernel26.img before):

mkinitcpio -g /boot/kernel26.img

Store the key as a plain (visible) file

Be sure to choose a plain name for your key - a bit of 'security through obscurity' is always nice ;-). Avoid using dots (hidden files) and similar characters - the encrypt hook will fail to find the keyfile during the boot process.

You have to add a kernel parameter in your menu.lst (grub), it should look something like this:

kernel /vmlinuz26 root=/dev/hda3 ro vga=791 cryptkey=/dev/usbstick1:vfat:/secretkey

This assumes /dev/usbstick1 is the FAT partition of your choice.

That's all, reboot and have fun!

Store the key between the MBR and first partition

Add the temporary keyfile we created before with cryptsetup:

cryptsetup luksAddKey /dev/hda3 secretkey

That should return you output like this:

Enter any LUKS passphrase:
key slot 0 unlocked.
Command successful.

Next you'll have to write the key directly between MBR and first partition.

WARNING: you should only follow this step if you know what you are doing - it can cause data loss and damage your partitions or MBR on the stick!

If you have a bootloader installed on your drive you have to adjust the values. E.g. Grub needs the first 16 sectors, you would have to replace seek=4 with seek=16; otherwise you would overwrite parts of your Grub installation. When in doubt, take a look at the first 64 sectors of your drive and decide on your own where to place your key.


dd if=/dev/usbstick of=64sectors bs=512 count=64   # gives you copy of your first 64 sectors
hexcurse 64sectors                                 # determine free space

Write your key to the disk:

dd if=secretkey of=/dev/usbstick bs=512 seek=4

If everything went fine you can now delete your temporary secretkey:

rm secretkey

Now you have to add a kernel parameter in your menu.lst (Grub), it should look something like this:

kernel /vmlinuz26 root=/dev/hda3 ro vga=791 cryptkey=/dev/usbstick:2048:2048

Format for the cryptkey option:


OFFSET and SIZE match in this example, but this is coincidence - they can differ (and often will). An other possible example could be

kernel /vmlinuz26 root=/dev/hda3 ro vga=791 cryptkey=/dev/usbstick:8192:2048

That's all, reboot and have fun! Ad look if your partitions still work after that ;-).

Applying this to a non-root partition

You might get tempted to apply all this fancy stuff to a non-root partition. Arch does not support this out of the box, however, you can easily change the cryptdev and cryptname values in /lib/initcpio/hooks/encrypt (the first one to your /dev/sd* partition, the second to the name you want to attribute). That should be enough.
The big advantage is you can have everything automated, while setting up /etc/crypttab with an external key file (i.e. not on any internal HD partition) can be a pain - you need to make sure the USB/FireWire/... device gets mounted before the encrypted partition, which means you have to change fstab order (at least).
Of course, if the cryptsetup package gets upgraded, you will have to change this script again. However, this solution is to be preferred over hacking rc.sysinit or similar files. Unlike /etc/crypttab, only one partition is supported, but with some further hacking one should be able to have multiple partitions unlocked.

If you want to do this on a software RAID partition, there's one more thing you need to do. Just setting the /dev/mdX device in /lib/initcpio/hooks/encrypt is not enough; the encrypt hook will fail to find the key for some reason, and not prompt for a passphrase either. It looks like the RAID devices aren't brought up until after the encrypt hook is run. You can solve this by putting the RAID array in /boot/grub/menu.lst, like

kernel /boot/vmlinuz26 md=1,/dev/hda5,/dev/hdb5

If you set up your root partition as a RAID array you will notice the similarities with that setup ;-). Grub can handle multiple array definitions just fine:

kernel /boot/vmlinuz26 root=/dev/md0 ro md=0,/dev/sda1,/dev/sdb1 md=1,/dev/sda5,/dev/sdb5,/dev/sdc5