Gentoo Wiki ArchivesGentoo Wiki

SECURITY_System_Encryption_DM-Crypt_with_LUKS

Split-arrows.gifIt has been suggested that this article be split into multiple articles accessible from a disambiguation or index page.   (Discuss)
This article is part of the HOWTO series.
Installation Kernel & Hardware Networks Portage Software System X Server Gaming Non-x86 Emulators Misc
This article is part of the Security series.
Prompt example.
Prompt example.

Contents

Introduction

The main purpose of this document is to describe the process of encrypting your system with DM-Crypt and cryptsetup-luks from the moment you start your Gentoo installation. It's worth pointing out that while this document was written for Gentoo based systems in mind, it should be generic enough to be used with other meta-distributions as well.

Why Gentoo ?

Quote: http://luks.endorphin.org/about

LUKS on Gentoo uses cryptsetup-luks to make Gentoo the first Linux distribution that can be run and installed seamlessly with LUKS, and (without disrespect of other crypto project) is believed to deliver the best user experience.

Alternatives

An alternative to dm-crypt is loop-AES by Jari Ruusu. It's up to you to investigate which one suits your needs best. Truecrypt also seems to have roughly the same functionality.

Important

Please note that this document does not use Gentoo's sys-kernel/genkernel utility to generate the initramfs. The guide uses its own custom init script (not distro specific) and has a "get your hands dirty" approach.

A simpler approach requiring fewer manual modifications is available by following the Gentoo-luks instructions. They should make your life easier.

Why?

People against the use of cryptography might argue that "if you're innocent, you have nothing to hide." In a utopian society this would be true; unfortunately the world is not black and white, there is a lot of grey in between.

Quote: Cardinal Richelieu

If one would give me six lines written by the hand of the most honest man, I would find something in them to have him hanged.

It's not the objective of this document to convince you to use cryptography. You might, however, find the following papers interesting.

by Bruce Schneier
by Philip Zimmermann

Back on topic, by encrypting your system you're not only protecting sensitive data your system might contain, you're also ensuring that the system won't get compromised by someone with physical access to it.

Now let's talk about what encrypting your system won't protect you against:

(1) - A little Judo might help here.
(2) - If you use a keyfile on a removable media(USB-stick) this doesn't quite apply to you anymore.
(3) - More about this on the next section.

Security levels

Security level Description Explanation
Most Root partition is encrypted. Boots from a USB stick. This is the safest approach. The kernel and (optionally) initramfs exist on the USB stick (which is not available to the attacker).
Medium Root partition is encrypted. Boots from /boot. The problem with this setup is that a sophisticated attacker could tamper with the kernel and/or initramfs archive and obtain passphrases for your partition(s).
Least Root partition is not encrypted. Boots from /boot. Separate partiton contains sensitive data and is encrypted. The problem with this setup is that an attacker could perform a man in the middle attack by tampering with your system.

Keyfiles on removable media

Keyfiles stored on removable media (such as a USB stick) provide protection against a rubberhose attack (torture). In this situation, the passphrase exists solely on the removal media. As you do not know the passphrase, you cannot reveal it, regardless of the amount of torture applied to you.

This depends heavily upon the total destruction of the removable media - if it is destroyed, the encrypted data it protects can never be recovered.

Warning: This would save your data only, you'd get killed either way. If the data is more important than your life it would be stupid for you to rely on the information presented in this amateur document.

GPG-protected keys

GPG-protected keys provide protection from an attacker managing to obtain removable media that contains keyfiles. Unlike regular keyfiles, an attacker would need a secondary passphrase to decrypt the keys. This comes with the drawback of having to enter a GPG passphrase upon each boot.

Plausible deniability

plausible deniability involves the possession of encrypted data which cannot be proven to exist. This is often done by using steganography. Keys hidden in this way are currently not supported by the init script.

To implement this, check out StegFS and Scubed.

Two things to remember

Minimum Requirements

You can use zgrep <CONFIG> /proc/config.gz to check whether your kernel meets the requirements. Look for the following options:

You can see the available ciphers by doing cat /proc/crypto. Some Live-CDs have ciphers available as modules instead of built-in, so you might need to load them first.


(1) It is recommended that you use a multi-purpose Live-CD such as Knoppix (or the new Gentoo Live-CD), because minimal Live-CDs aim to be … minimal, and may lack some of useful tools or ciphers for you to use.

Before you begin

Since you will be encrypting your system from the moment you start your Gentoo installation, you'll need to divert a lot from the official Gentoo Installation guide.
To make your life easier, the guide contains links to the Gentoo Installation guide sections when needed, so just fire up lynx (or links2) in its own virtual console and keep reading.

Warning: Backup your data:

Regularly backup your data. It will be encrypted and might be impossible to recover when your harddisk starts dying.


Tip! You can switch virtual consoles with Alt+F<number>


Note: Make sure you're using the correct keymap. If you chose the wrong keymap take a look at /usr/share/keymaps and execute, for example: loadkeys es-cp850


Warning: Write caching on systems without UPS could lead to data loss and filesystem corruption!

You should consider turning write caching off for your disk. The reason is that write caching stores the I/O data on its own volatile memory before writing it to the disk. So in the event of a power failure, data loss and filesystem corruption might happen (even on journaling filesystems).

You can use hdparm to turn write caching off. Kernels >=2.6.15 now use the ATA passthru from Jeff Garzik by default, so patching the kernel is no longer required.

UPS powered systems don't have this problem and it is safe to turn write caching on.

Laptop users: make sure you shutdown/suspend the system when it's low on battery (write a script or something).


Note: LiveCD environments live in system RAM so please remove any space-abusive content you might have that you don't need.


Warning: Be careful when entering commands, one small typo and your data could be gone forever!
Warning: Please obey the warnings! They are there for a reason!

Begin

Follow the Gentoo installation guide until you reach section 4 (Preparing the Disks).

Preparing the disk

Warning: The steps below will destroy all data on your disk(or partitions)!


Checking the hard disk for errors

Quote: Ref1

It's probably a good idea to check your entire disk for errors before you start.

Not only is this good practice, but modern hard disks contain a few 'spare' sectors, and if errors are detected while reading, they can silently replace the bad sector with a backup sector (this is invisible to the OS).

So writing and reading the entire disk before you start should allow this to happen.


Warning: In this step you will already initialize your partitions by using the -w option. If you don't want to erase data now just use -n
Code: badblocks output

Testing the hard drive for bad blocks

/sbin/badblocks -c 10240 -s -w -t random -v /dev/sdc
(wait several hours ... go take a long nap)
Checking for bad blocks in read-write mode
From block 0 to 295360984
done
Reading and comparing: done
Pass completed, 0 bad blocks found.

Filling the disk with random data

When you checked the disk for bad blocks it was filled with not-so-random data; now you're going to fill it again, but this time you're going to use /dev/urandom which produces "random" data.

Doing this before you actually start storing encrypted data on the disk makes it practically impossible to know how much data has been written, therefore breaking it becomes much harder.

Below is a list of possible ways to fill the disk with random data:

badblock uses 'libc' random(), but is fast (your limitation will be disk speed, not CPU speed).
Warning: Using this method to produce random data is very insecure. Badblocks works by picking a random number X at the begining of execution, and then write/reading X across the entire disk. This produces a highly predictable sequence similar to writing zeros across the disk.
/dev/urandom will fill the disk with "random" data. It won't be as random as /dev/random though, but it's the best practical solution available. It will protect you against a full cryptoanalytic attack better than badblocks.
From the man page: shred overwrites the specified FILE(s) repeatedly, in order to make it harder for even very expensive hardware probing to recover the data. Shred looks better than just dding /dev/urandom since it does many writes (default 25, changed with -n option) and still takes input from /dev/urandom by default (changed with --random-source option). There's even a -v option which shows the progress. Note that the purpose of shred is to totally obliterate any data currently on a disk. Only the final pass of shred is useful on a brand-new disk. In such a case, you may as well just dd from /dev/urandom directly, which is about 25 times faster than using shred (in the default case).
In theory, this is the best way to fill your disk with random data, since it is much more random than any of the above. It works by using the kernel entropy pool, so if you run out of entropy it will kind of freeze. You can see what this means by doing cat -A /dev/random; it will eventually stop. Now move your mouse to produce some more entropy for the kernel to use.
The frandom suite comes as a Linux kernel module for several kernels, or a kernel patch for 2.4.22. It implements a random number generator, which is 10-50 times faster than what you get from Linux' built-in /dev/urandom. And it uses very little (/dev/frandom) or none (/dev/erandom) of the kernel's entropy pool, so it is very useful for applications that require a handy source for lots of random data. More info and sources on http://www.billauer.co.il/frandom.html
Code: filling your disk with (pseudo-)random data

Using /dev/urandom to fill the disk with random data

dd if=/dev/urandom of=/dev/sda
(go and take a nap, because this takes a long time to finish)
# I'd recommend to try out to use the bs parameter of dd and to try different values, the optimum depends on the size of the system bus. This can speed up the process about more than factor two.
# if you used /dev/random come back in 100 years
Note: There is no progress indicator, but you will see the disk activity led blinking. Also, sending SIGUSR1 to dd (killall -USR1 dd) will cause it to print the current number of blocks written.

This usually takes a really long time to finish (depending on your harddisk). Just to give you an idea: on an 80GB SATA drive it took around 12 hours. The process is CPU bound as it took 23 hours to fill a 320GB drive on my AMD64 3500+ and two-and-a-half days to fill a 120GB drive on a dual Pentium II 400Mhz machine.

Code: filling repeatedly your disk with (pseudo-)random data

Using shred to fill the disk with random data

shred -v /dev/sda
shred: /dev/sda: pass 1/25 (random)...
shred: /dev/sda: passes 1/25 (random)...28MiB/7,5GiB 0%
shred: /dev/sda: passes 1/25 (random)...57MiB/7,5GiB 0%
shred: /dev/sda: passes 1/25 (random)...85MiB/7,5GiB 1%
...
shred: /dev/sda: passes 25/25 (random)...7,3GiB/7,5GiB 97%
shred: /dev/sda: passes 25/25 (random)...7,4GiB/7,5GiB 99%
shred: /dev/sda: passes 25/25 (random)...7,5GiB/7,5GiB 100%
Note: Only pass #1, #13 and #25 use pseudo-random data, the others take given patterns instead.

Partitioning Scheme

Code: Partitioning scheme

Feel free to use any partitioning scheme.

            # Guide convention
/boot       /dev/sda1 # not needed if booting from USB-stick
swap        /dev/sda2
/           /dev/sda3
Note: Suspend2 users:

You should consider suspend2 implications before allocating space for the swap partition, for example you could have two swap partitions, one for normal swap and one for suspend2.

If you're going to use one swap partition, make sure it is big enough to also hold the suspend2 image. Please refer to the suspend2 documentation.


Now follow the Gentoo Installation Guide until you reach step 4.d (Creating Filesystems).

Create mapping between logical and physical partitions

Quote: Ref1

DM-Crypt works by transparently translating (in the kernel) between a physical on-disk partition (which is encrypted) and a logical partition which you can then mount and use as normal. This step takes no time and writes no data, it just establishes the mapping for future use.

The physical (encrypted) root partition will be /dev/sda3
The logical (unencrypted) root partition will be /dev/mapper/root

This document uses the serpent and blowfish ciphers. You can use whichever you want, though. Please refer to a subsection for more information on ciphers.

Loading necessary modules

The modules you need to load depend on the ciphers you plan to use. Please see this subsection for some information about different available ciphers, and of course edit the commands accordingly.

Code: Loading modules
modprobe dm-crypt  # required
modprobe dm-mod    # required
modprobe serpent   
modprobe sha256 
modprobe blowfish
modprobe aes
Tip! Loading the modules, Bash one-liner:

for i in dm-crypt dm-mod serpent sha256 blowfish;do modprobe $i;done


Tip! cat /proc/crypto will show you the loaded modules.

cryptsetup-luks executable

For all actions described from now on, you need a working cryptsetup-luks binary for your host platform.

If your Live-CD doesn't provide one you need to get it from somewhere else. Luckily for us a static precompiled cryptsetup-luks binary exists on [1].

Code: cryptsetup(-luks) executable
bunzip2 -d cryptsetup-1.0.3-i686-pc-linux-gnu-static.bz2
chmod +x  cryptsetup-1.0.3-i686-pc-linux-gnu-static
# rename it to cryptsetup (optional)
mv cryptsetup-1.0.3-i686-pc-linux-gnu-static cryptsetup

You can check whether your Live-CD contains the LUKS version of cryptsetup with cryptsetup --help. If you don't see any options with "luks" in them your Live-CD doesn't have it.

Encrypting swap for installation

First you will encrypt swap for use during installation. This is important because you don't want the encryption keys swapped to an unencrypted disk.

Code: Encrypting swap for installation (not for suspend2 users)
cryptsetup -c blowfish -h sha256 -d /dev/urandom create swap /dev/sda2 
mkswap /dev/mapper/swap
swapon /dev/mapper/swap

Suspend2 users

The above example does not use LUKS and it reads the key from /dev/urandom. For most setups this is appropiate, but not in your case because the suspend2 image needs to be preserved between reboots.

You've to treat the swap partition just as if it were a regular partition, meaning you should encrypt it like it's explained in the "Creating the mapping(s)" section.

Randomly generated keys (optionally, encrypted with GnuPG)

If you plan to use randomly generated keys for your partition(s) and (optionally) encrypting the keys with GnuPG, then keep reading. Otherwise continue on the next section.

Randomly generated keys are better than passphrases for two reasons:

Again, this is an extract from the loop-AES README stating the importance of having the swap partition encrypted.

Quote: loop-AES.README

Many of following examples depend on gpg encrypted key file. gpg appears to prevent its own keys from being leaked to swap, but does not appear to prevent data handled by it from being leaked to swap. In gpg encrypted key file cases, the data handled by gpg are loop encryption keys, and they may leak to swap. Therefore, use of gpg encrypted key file depends on encrypted swap.

Quote: loop-AES.README

When gpg encrypts data with symmetric cipher only or when gpg encrypts secret keyring keys with secret passphrase, gpg uses seeded (salted) and iterated key setup. However, default amount of iteration is tuned for slow processors and can be increased for better resistance against dictionary attacks. Larger key iteration makes key setup much slower, but also makes dictionary attacks much slower too.

Included optional gpg patch makes gpg password iteration 128 times slower. gpg stores new iteration value along with seed bytes into symmetric cipher encrypted output file or secret keyring, so unpatched gpg versions will read and decrypt the data just fine.

Note: The Gentoo ebuild for gnupg applies the patch.

In the following examples the random keys are encrypted with gpg. If you want to use random keys as regular keyfiles do not pipe the output into gpg.


Encrypting randomly generated keys with gpg

You'll need the uuencode utility (emerge sharutils) and GnuPG (emerge gnupg). Unfortunately not many Live-CDs ship with them. If this applies, these are your options:

Instructions:

# substitute <partition> with the partition this key is intended (eg:rootkey.gpg)
head -c 45 /dev/random | uuencode -m - | head -n 2 | tail -n 1 | gpg --symmetric -a >./<partition>key.gpg

Explanation of command above:

The head command is used to output the first lines (parts) of files.
head -c 45 tells it to print the first 45 bytes generated from /dev/random, which is large enough to generate a strong key.
The uuencode utility is used for binary to text encoding. The -m argument tells it to use base64 encoding.
Next comes head -n 2, tail -n 1. head outputs the first 2 lines and tail prints the last line.
Why?
Because the output before the two commands are executed looks like this:

begin-base64 644 -
<random content>
====

To finish up, the output (random key) is piped into gpg, which encrypts it using a symmetric cipher.
Note: The default symmetric cipher used is CAST5, but another may be chosen with the --cipher-algo option. (man gpg)

Note: If you use base64 instead of uuencode, replace uuencode -m - with base64 -w 0 (the switch makes sure encoded output is not split into multiple lines) and remove calls to head and tail (this command doesn't produce headers/footers).


Randomly generated key (another example)

Another way of generating a random key is using the dd utility.

dd if=/dev/random count=1 | gpg --symmetric -a >./<partition>_key.gpg

Warning:
If you cat a binary file, your terminal or tty might get corrupted!
If it does, type 'reset' and press enter, this should restore it.

Creating the mapping(s)

Quote: cryptsetup(LUKS) Man page

NOTES ON PASSWORD PROCESSING FOR LUKS.
Password processing is totally different for LUKS. LUKS uses PBKDF2 to protect against dictionary attacks (see RFC 2898). LUKS will always use SHA1 in HMAC mode, and no other mode is supported at the moment. Hence, -h is ignored.

LUKS will always do an exhaustive password reading. Hence, password can not be read from /dev/random, /dev/zero or any other stream, that does not terminate.

LUKS saves the processing options when a password is set to the respective key slot. Therefore, no options can be given to luksOpen. For any password creation action (luksAddKey, or luksFormat), the user specify, how much the time the password processing should consume. Increasing the time will lead to a more secure password, but also will take luksOpen longer to complete. The default setting of one second is sufficient for good security.

Quote: cryptsetup(LUKS) Man page

NOTES ON PASSWORDS

Mathematic can't be bribed. Make sure you keep your passwords safe. There are a few nice tricks for constructing a fallback, when suddely out of (or after being) blue, your brain refuses to cooperate. These fallbacks are possible with LUKS, as it's only possible with LUKS to have multiple passwords.

Warning: Users who plan to use keyfiles/gpg protected keys:

The keyfiles will be the only way to access your system, if you lose it or someone delete them(eg: someone wipes the contents of the usb-stick), you can say goodbye to all the data those keys were protecting.
You should consider adding an additional passphrase as a fallback method.

"You have been warned.."


It's time to create the mapping for the partitions, repeat the steps below for every partition you want encrypted.
Since passphrases are the weakest link in all security implementations, Diceware is suggested to create strong, yet easy to remember passphrases.

Make sure you remember your passphrase.
If you ever forget it, it's game over.

Using a 256-bit key size means that if your data was under a brute force attack, the attacker would have to search among 2256 possible passphrases.
Assuming no weaknesses in the encryption algorithm, such attack is practically impossible(for now).

Tip! Using the AES_x86_64 "AMD64 users only":

as of kernel-2.6.9 the 64bit version of the AES cipher that can be used in replacement of the 32bit AES cipher that's used by default. you must load this module before running the cryptsetup command or else the 32bit AES will be use instead. type "modprobe aes_x86_64" and continue with creation of mappings.


Code: Creating the mapping for the / partition

Note: Feel free to substitute the cipher used (see this subsection for information on ciphers).

Example 1: partition: root -- key: passphrase

cryptsetup -y --cipher serpent-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sda3 
WARNING!
========
This will overwrite data on /dev/sda3 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase: (enter your passphrase, and write it down somewhere!)
Verify passphrase: (repeat passphrase)

Example 2: partition: root -- key: keyfile

cryptsetup -v --cipher serpent-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sda3 /path/to/rootkey

Example 3: partition: root -- key: gpg protected key
Make sure you enter the correct passphrase, if you see any "gpg decryption failed" messages, luksFormat again.

gpg --quiet --decrypt rootkey.gpg | cryptsetup -v --cipher serpent-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sda3
# You can see it worked by using luksDump.
# If don't trust if it worked or not you can enter the key 
# as a passphrase when "luksOpening" the partition.


Opening the LUKS partition.
It's time to open the LUKS partition, this will create the root mapping in /dev/mapper/.

Code: Opening LUKS partition

Example 1: partition: root -- key: passphrase

cryptsetup luksOpen /dev/sda3 root 
Enter LUKS passphrase: 
key slot 0 unlocked. 

Example 2: partition: root -- key: keyfile

cryptsetup --key-file /path/to/rootkey luksOpen /dev/sda3 root

Example 3: partition: root -- key: gpg protected key

gpg --decrypt key.gpg 2>/dev/null | cryptsetup luksOpen /dev/sda3 root 

If in doubt, consult cryptsetup's manual.


From now on, every time you have to operate on your root partition (/dev/sda3) you must do so using /dev/mapper/root.

Creating the filesystem on the logical root partition

Code: Example from ref1
/sbin/mkfs.ext3 -j -m 1 -O dir_index,filetype,sparse_super /dev/mapper/root
(wait several minutes...)
mke2fs 1.35 (28-Feb-2004)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
36634624 inodes, 73258400 blocks
732584 blocks (1.00%) reserved for the super user
First data block=0
2236 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
       32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
       4096000, 7962624, 11239424, 20480000, 23887872, 71663616

Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 39 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.

Create the filesystem for the /boot partition as indicated on the Gentoo Installation Guide, but do not initialize or activate the swap partition since you already did this on a previous step.

Mounting the filesystem(s)

Code: mounting partitions

Use the mappings instead of the real devices, below is an example for the root partition.

mount -t ext3 /dev/mapper/root /mnt/gentoo

Now follow the Gentoo Installation Guide from step 5, until you reach step 7.c (Default: Kernel Manual Configuration).

Suspend2

What is it ?

Quote: suspend2 documentation

Imagine you're sitting at your computer, working away.
For some reason, you need to turn off your computer for a while - perhaps it's time to go home for the day.
When you come back to your computer next, you're going to want to carry on where you left off. Now imagine that you could push a button and have your computer store the contents of its memory to disk and power down.
Then, when you next start up your computer, it loads that image back into memory and you can carry on from where you were, just as if you'd never turned the computer off.
Far less time to start up, no reopening applications and finding what directory you put that file in yesterday.
That's what Software Suspend does.


You can use the unofficial Gentoo's sys-kernel/suspend2-sources or patch the kernel yourself.
You also need sys-apps/suspend2-userui and sys-power/hibernate-script, both get installed as dependencies if you use suspend2-sources.

You must learn how to use it, it's simple but it won't be documented here, this is what you want to read:

The support for suspend2 is implemented in the init script(which you'll see in the next section), suspend2 related information will show up later in the guide when needed, please read the warning box below, it's important.

Warning:

There're certain scenarios that can lead to data loss or corruption, you should read suspend2 documentation resources to learn how to avoid them, in particular:
Avoiding data loss

Warning -- list of things you should not do:

Use the hibernate script to control which partitions need to be unmounted before suspending.
If the new kernel has suspend2 support, you'll get a big fat warning about version mismatch, press Shift to reboot, do not continue booting.
Resuming with a different kernel will corrupt/crash the system and might cause filesystem damage.(see Suspend2.net FAQ 5.13)

Last but not least, Backup your data!

Creating initramfs image

Before you continue with configuring your kernel(Step 7.c of Gentoo Installation Guide), you need to create an initramfs.

What's an initramfs and why do I need one ?

Since the root partition is encrypted, it has to be decrypted during the boot process, this task is not done by the Linux kernel, so it has to be done in userspace.
Enter early userspace:

Quote: kernel doc: early-userspace/README

"Early userspace" is a set of libraries and programs that provide
various pieces of functionality that are important enough to be
available while a Linux kernel is coming up, but that don't need to be
run inside the kernel itself.

Fine.., but what is an initramfs ?

An initramfs image is a gzipped cpio format archive, which in our case, when extracted into rootfs by the kernel, becomes the early userspace responsible for decrypting the root partition.

You probably have more questions, so for your convenience and mine, below is a list of documents that will explain it better than I can:


Busybox

BusyBox - The Swiss Army Knife of Embedded Linux.

This document uses BusyBox for the initramfs image.
BusyBox:

"BusyBox combines tiny versions of many common UNIX utilities into a single small executable. It provides minimalist replacements for most of the utilities you usually find in GNU coreutils, util-linux, etc. The utilities in BusyBox generally have fewer options than their full-featured GNU cousins; however, the options that are included provide the expected functionality and behave very much like their GNU counterparts."
"BusyBox is a multi-call binary. A multi-call binary is an executable program that performs the same job as more than one utility program. That means there is just a single BusyBox binary, but that single binary acts like a large number of utilities. This allows BusyBox to be smaller since all the built-in utility programs (we call them applets) can share code for many common operations."


So, what does the above mean and why do I care ?
It means you will no longer have to go through the long and tedious process of finding the shared libraries dependencies for each utility(ls, cp, bash, etc..).
Instead of having separate utilities, you'll have one multi-call statically linked binary(BusyBox).
You also care because it'll save you time and it'll make the initramfs image smaller.

Choosing a C library (uClibc, glibc)

You need to decide which C library will be used to build BusyBox.

C library for developing embedded Linux systems.
This tiny C library is well suited for small embedded usage like this, plus it's what BusyBox developers recommend.
It currently doesn't support all architectures, if this is your case you'll have to use glibc.
GNU C library.
Not designed for small embedded usage, the size of the resulting binaries will much be bigger(>500k), it's not a big problem since the space occupied by the initramfs image gets deleted from memory when switching to the decrypted root.
It works, so use it if you can't use uClibc or simply don't want to create the uClibc toolchain.
The "klibc" package (http://www.kernel.org/pub/linux/libs/klibc) is designed to be a tiny C library to statically link early userspace code against, along with some related utilities.
You won't be able to build BusyBox with it.
If you want to use it, you need to read the documentation listed in this section.
klcc is a a wrapper around gcc(1) and ld(1) which compiles and links a program against the klibc tiny C library.


Building BusyBox

Note: You don't need to be root for the actions described here.


Download BusyBox, extract it and go into its directory, you will have to configure it, do make menuconfig.
You'll find that its configuration interface is much like the one you find when configuring a kernel.

It's important that you include support for all the applet init depends for working properly, most of the included applets are not required but they might come in handy whenever you go into rescue mode.
Bottom line is, stick with the configuration displayed below unless you know better.

Configuration options might change from one busybox version to another, just enable what it's shown below and don't worry about it too much.

BusyBox Configuration: v-1.2.1

Note: If an option is not displayed with an [*], it should be disabled.

Busybox Settings ---> General Configuration --->
  [ ] See lots more (probably unnecessary) configuration options.
  [*] Show terse applet usage messages
  [*] Use the devpts filesystem for Unix98 PTYs
Busybox Settings ---> Build Options --->
  [*] Build BusyBox as a static binary (no shared libs)
  [*] Build with Large File Support (for accessing files > 2 GB)
Busybox Settings ---> Debugging Options --->
  [*] Disable obsolete features removed before SUSv3?
Busybox Settings ---> Installation Options --->
  [*] Don't use /usr
      Applets links (as soft-links)  --->
  (./_install) BusyBox installation prefix
Busybox Settings ---> Busybox Library Tuning --->
  (2)  MD5: Trade Bytes for Speed

Applets

Archival Utilities  ---> 
  [*] bunzip2
  [*] cpio
  [*] gunzip
  [*] gzip
  [*] tar
  [*]   Enable archive creation
  [*]   Enable -j option to handle .tar.bz2 files
  [*]   Enable -z option
  [*]   Enable support for some GNU tar extensions
  
Coreutils --->
  [*] basename
  [*] cat
  [*] chgrp
  [*] chmod
  [*] chown
  [*] chroot
  [*] cp
  [*] cut
  --- date
  [*] dd
  [*]   Enable DD signal handling for status reporting
  [*]   Enable ibs, obs and conv options
  [*] df
  [*] diff
  [*]   Enable checks for binary files
  [*]   Enable directory support
  [*] dirname
  [*] du (default blocksize of 512 bytes)
  [*]   Use a default blocksize of 1024 bytes (1K)
  --- echo (basic SuSv3 version taking no options)
  [*]   Enable echo options (-n and -e)
  [*] env
  [*] expr
  [*] false
  [*] head
  [*]   Enable head options (-c, -q, and -v)
  [*] ln
  [*] ls
  [*]   Enable filetyping options (-p and -F)
  [*]   Enable symlinks dereferencing (-L)
  [*]   Enable recursion (-R)
  [*]   Sort the file names
  [*]   Show file timestamps   
  [*]   Show username/groupnames
  [*]   Allow use of color to identify file types
  [*] md5sum
  [*] mkdir
  [*]   Enable long options
  [*] mkfifo
  [*] mknod
  [*] mv
  [*]   Enable long options
  [*] pwd
  [*] rm
  [*] rmdir
  [*] seq
  [*] sleep (single integer arg with no suffix)
  [*] sort
  [*]   full SuSv3 compliant sort (Support -ktcsbdfiozgM)
  [*] sync
  [*] tail
  [*]   Enable extra tail options (-q, -s, and -v)
  --- test
  [*] touch
  [*] tr
  [*] true
  [*] tty
  [*] uname
  [*] uudecode
  [*] uuencode
  [*] watch
  [*] wc
  [*] yes
  --- Common options for cp and mv
  [*] Preserve hard links
  --- Common options for ls, more and telnet
  [*] Calculate terminal & column widths
  --- Common options for df, du, ls
  [*] Support for human readable output (example 13k, 23M, 235G)
  --- Common options for md5sum, sha1sum
  [*] Enable -c, -s and -w options
Console Utilities  --->
  [*] chvt
  [*] clear
  [*] deallocvt
  [*] dumpkmap
  [*] loadfont
  [*] loadkmap
  [*] reset
  [*] setkeycodes
Debian Utilities  ---> 
  [*] readlink
  [*] which
Editors  ---> 
  [*] awk
  [*]   Enable math functions (requires libm)
  [*] sed
  [*] vi
  [*]   Enable ":" colon commands (no "ex" mode)
  [*]   Enable yank/put commands and mark cmds
  [*]   Enable search and replace cmds
  [*]   Catch signals
  [*]   Remember previous cmd and "." cmd
  [*]   Enable -R option and "view" mode
  [*]   Enable set-able options, ai ic showmatch
  [*]   Support for :set
Finding Utilities  ---> 
  [*] find
  [*]   Enable -print0 option
  [*]   Enable modified time matching (-mtime) option
  [*]   Enable modified time matching (-min) option
  [*]   Enable permissions matching (-perm) option
  [*]   Enable filetype matching (-type) option
  [*]   Enable stay in filesystem (-xdev) option
  [*]   Enable -newer option for comparing file mtimes
  [*]   Enable inode number matching (-inum) option
  [*]   Enable (-exec) option allowing execution of commands
  [*] grep
  [*]   Support extended regular expressions (egrep & grep -E)
  [*]   Alias fgrep to grep -F
  [*]   Enable before and after context flags (-A, -B and -C)
  [*] xargs
Init Utilities  ---> 
  [ ] init
  [*] poweroff, halt, and reboot
Linux Ext2 FS Progs  ---> 
  [*] chattr
  [*] e2fsck
  [*] fsck
  [*] lsattr
  [*] mke2fs
  [*] tune2fs
 
Linux Module Utilities  --->
  [*] insmod
  [*] rmmod
  [*] lsmod
  [*]   lsmod pretty output for 2.6.x Linux kernels
  [*] modprobe
  [*]   Multiple options parsing
  ---   Options common to multiple modutils
  [*] Support tainted module checking with new kernels
  [*] Support version 2.6.x Linux kernels
Linux System Utilities  ---> 
  [*] dmesg
  [*] fbset
  [*] fdisk
  ---   support over 4GB disks
  [*]   Write support
  [*] mdev
  [*]   Support /etc/mdev.conf
  [*]     Support command execution at device addition/removal
  [*] mkswap
  [*] more
  [*]   Use termios to manipulate the screen
  [*] mount
  [*] swaponoff
  [*] switch_root
  [*] umount
  [*]   umount -a option
  
Miscellaneous Utilities  --->
  [*] less
  [*]   Enable bracket searching
  [*]   Enable extra flags
  [*]   Enable regular expressions
  [*] mountpoint
  [*] strings
Process Utilities  ---> 
  [*] free
  [*] kill
  [*]   killall
  [*] pidof
  [*] ps
  [*] sysctl
Shells  ---> 
      Choose your default shell (ash)  --->
  ---   Ash Shell Options
  [ ]   Job control
  [*]   'read -n N' and 'read -s' support
  [*]   alias support
  [*]   Posix math support
  [*]   Builtin version of 'echo'
  [*]   Builtin version of 'test'
  [*]   Expand prompt string
  ---   Bourne Shell Options
  [*]   Hide message on interactive shell startup
  [*]   Command line editing
  (15)    History size
  [*]     History saving
  [*]     Tab completion
  [*]     Fancy shell prompts

uClibc users, adjust the Cross Compiler prefix properly

Busybox Settings ---> Build Options --->
  [*] Do you want to build BusyBox with a Cross Compiler?
  (/usr/i386-linux-uclibc/bin/i386-uclibc-) Cross Compiler prefix


Note: busybox-1.2.0 contains a major bug in its dmesg utility making dmesg -n 1 segfault. This is fixed in the daily snapshot for July 27, 2006. The daily snapshot can be downloaded, extracted, and used in the exact same manner described above.

When you're done configuring BusyBox, enter make, it will make a statically linked busybox executable and a busybox.links file, the latter will be used to create symlinks to the BusyBox binary for all the commands compiled in.

Warning: Do not execute 'make install'. It might break your current system!

If you want to use uclibc, emerge uclibc && emerge crossdev. Next run crossdev --target i686-pc-linux-uclibc and once complete do make CROSS_COMPILE=i686-pc-linux-uclibc- (the - at the end is important)

When you follow this Wiki using a minimal-Gentoo-installation-CD (2007.0 in my case) and you work inside your new Gentoo environment, you can only emerge uclibc with USE="-nls -iconv", otherwise it will segfault during the build! You also have to create a PORTDIR_OVERLAY als mentioned here in (2) and (3). I also set up a symbolic link like

ln -s /usr/portage/sys-libs/uclibc uclibc

Then running "crossdev i686-pc-linux-uclibc" will work. But be patient. It will take some time to rebuild gcc, binutils, ...

Generating a kmap(binary keyboard translation table)

If you use a non US keyboard, you need to create a kmap(keymap) for it, otherwise you will have a hard time entering passphrases.
A kmap is a binary keyboard translation table for use with BusyBox's loadkmap utility, it's different from loadkeys, so you need to generate a kmap from the current loaded keymap.
The documentation for generating kmaps is quite scarce, it's a simple procedure so it will be explained below.


Code: Generating the kmap
# Save the current keymap
dumpkeys > default_keymap

# Next, load the kernel keymap you plan to use into the kernel
# look at /usr/share/keymaps 
loadkeys es-cp850  

## Extra step: convert keymap to unicode
#dumpkeys | loadkeys -u

# Now use BusyBox's dumpkmap applet to obtain the kmap from the
# current loaded keymap.
# Substitue <ARCH> with the correct architecture
./busybox dumpkmap > es-cp850-<ARCH>.bin

# Load the default_keymap
loadkeys default_keymap


Save the kmap you just created because it'll be included into the initramfs image later.

If you need to load a font(most people don't need to worry about this), have a look at /usr/share/consolefonts, you've to decompress the font you plan to use and don't forget to include it into the initramfs image later.

Note: kmaps won't work across architectures.

Initramfs's init

When you boot your system, the kernel will extract the initramfs cpio archive into rootfs(a special instance of ramfs) and will check if a file named "init" exist, if found it will execute it as PID 1(parent of all process).
This init process is then responsible for bringing the system the rest of the way up, in our case, its job will be to decrypt the root partition and switch to it, delegating the rest of your system boot process to the normal init.

The init script below is intedend for users following this document, please read its instructions(comments) before using it.
It's worth pointing out that it's not Gentoo specific, therefore it can be used no matter your distribution.

Tip! (Optional) for debugging purposes during init's initiation, add "-x" at the top of the script after #!/bin/sh

Example: #!/bin/sh -x. Now each command will be showing with "+" before it :)


Note: the new init script: http://wiki.suspend2.net/EncryptedSwapAndRoot
File: init -- download
#!/bin/sh
#=====================================
# | WARNING:                          |
# |______USE AT YOUR OWN RISK!________|
#
# [[SECURITY System Encryption DM-Crypt with LUKS]]
#                                 
# Arguments:
#   init script supports the following:
#     standard: 
#       * root=<device>          root device (required).
#       * ro                     mount root read only.
#
#     init specific:       
#      * ikmap=<kmap>[:<font>]      Load kmap and font(optional).
#      * is2                        Enables suspend2 support(required for suspend2 users).
#      * rescue                     Drops you into a minimal shell
#      * iswap=<device>             swap device(eg:/dev/sda2) (required for suspend2 users).
#      * ichkpt=<n>                 Interrupts init and drops to shell.
#      * ikey_root=<mode>:<device>:</path/to/file>  
#      * ikey_swap=<mode>:<device>:</path/to/file>
#      
#                      
#        == About key files ==
#        For partitions that are encrypted with a key, you must set 'ikey_root' and/or 'ikey_swap' properly,
#       otherwise you'll be asked for the passphrase.
#       This information is then used to obtain each key file from the specified removable media. 
#
#       <mode>           - defines how the init script shall treat the supplied keyfile(see below). 
#       <device>         - the device that will be assigned to the removable media.
#       </path/to/file>  - full path to file inside the removable media.
#
#       Supported modes:
#       gpg              - indicates keyfile is gpg-protected
#       none             - indicates keyfile is regular file
#
#        == Notes on keys ==
#         o gpg encrypted key file --> o It'll be decrypted and piped into cryptsetup as if it were a passphrase. 
#                                      o Works if and only if you did the same when you luksFormated the partition. 
#                                        If for example, you decrypt the gpg file and then use it as positional
#					 argument to luksFormat or luksAddKey, then it'll fail because the 
#					 new-line character('\n') will not be ignored.
#                                        If you remove the new-line char from the key 
#                                        'cat key | tr -d '\n' > cleanKey' and then use 'cleanKey'
#                                        as the --key-file argument it will work.   
#
#         o regular key file       --> o It'll be passed to cryptsetup as --key-file
#
#        == Suspend2 ==  
#         Suspend2 users should always boot with 'is2', special care must be taken to ensure that
#        the swap device always has the same major/minor numbers within the initramfs as well as your
#        running system. (see kernel doc: power/swsusp-dmcrypt.txt)
#        To achieve this, the init script will always decrypt your swap partition first whether you're resuming
#        from hibernation or not.
#         
#        IMPORTANT:
#         There are certain scenarios that can lead to data loss or corruption, you should read   
#        suspend2 documentation resources, in particular:
#                 [1] - suspend2.net -> HOWTO -> Avoiding data loss
#                 [2] - kernel doc: power/suspend2.txt
#   
#        WARNING! -- DATA LOSS -- !WARNING
#                 * Always boot with is2 argument, even if you're not resuming from hibernation.
#                 * Attempting to resume with different kernel(eg: recompiled kernel):
#                     If the second kernel has suspend2 support:
#                     You will get a BIG FAT WARNING about version mismatch, 
#                     Press 'Shift' to reboot, DO NOT CONTINUE.
#                     Then boot with noresume2.
#                     Resuming with a different kernel will corrupt/crash the system
#                     and might cause filesystem damage. (See: Suspend2.net FAQ 5.13)
#                 * Booting a kernel with noresume2(or a non suspend2 kernel) and then resuming
#                 from a previous image.
#                 * Mounting(even as ro) partitions that where mounted when you suspended(hibernated), and
#                 then trying to resume.
#                     Use the hibernate script to control unmounting partitions. 
#       
#         DANGER: Back up your data!
# 
#        == Kernel parameters example ==
#        o) Partition(s): root -- Key: regular passphrase
#           root=/dev/sda3 ikmap=es-cp850_i686.bin    
#        o) Partition(s): root -- Key: regular passphrase -- Extra: fbsplash
#           root=/dev/sda3 vga=0x318 video=vesafb:mtrr,ywrap \ 
#           splash=verbose,theme:livecd-2006.0 quiet CONSOLE=/dev/tty1
#        o) Partition(s): root -- Key: regular keyfile on usb stick
#           root=/dev/sda3 ikey_root=none:/dev/sdb1:/path/to/keyfile
#        o) Partition(s): root -- Key: gpg encrypted key on usb stick
#           root=/dev/sda3 ikey_root=gpg:/dev/sdb1:/path/to/file
#        o) Partition(s): swap root -- Suspend2 noresume2 -- Key(s): gpg, regular keyfile
#           root=/dev/sda3 is2 noresume2 iswap=/dev/sda2 ikey_root=none:/dev/sdb1:/path/to/rootkey \
#           ikey_swap=gpg:/dev/sdb1:/path/to/swapkey.gpg
#        o) Partition: swap -- Suspend2 resume2(resuming from hibernation) -- Key: regular passphrase
#           is2 iswap=/dev/sda2 resume2=swap:/dev/mapper/swap
#        o) Partition: swap -- Suspend2 resume2 -- Key: gpg protected key on usb stick
#           is2 iswap=/dev/sda2 resume2=swap:/dev/mapper/swap \
#           ikey_swap=gpg:/dev/sdb1:/path/to/swapkey.gpg 
#
#	 == Modules == 	
#       If you need to load modules, create the groups you need in /etc/modules/ (inside initramfs / ),
#       each file should be a list of the modules, and each file name denotes the step in the init where
#       they should be loaded.
#       Supported groups:
#                * boot           -  boot time modules loaded but not removed.
#                * suspend2       -  suspend2 module(not required anymore?).
#                * remdev         -  modules required to access removable device
#                * gpg            -  modules required to access gpg protected file.
#
#	o The modules should exist on /lib/modules/`uname -r`/ , like in your system.
#       o Your kernel has to support module unloading for rmmod to work.
#
# BUGS/KNOWN ISSUES:
#     (b0) fbsplash: when setting the splash mode from silent to verbose,
#                 verbose image is not painted and text is not visible.
#                 WORKAROUND: boot with verbose instead.
#
#     (b1) Redirect ugly hotplug messages about usb-stick to /dev/null, it can
#     be very annoying if they happen to appear when user is asked for passphrase.
#     WORKAROUND: sleep 5 in main() before calling do_work() 
#
#     (ki0) The length of init arguments should be reduced.
#     Users with a long kernel parameter list might find init(or the system) not working
#     as expected because some arguments where stripped. 
#     "... The length of complete kernel parameters list is limited, the limit
#     depends on the architecture, and it's defined in include/asm/setup.sh as
#     COMMAND_LINE_SIZE. ..." (kernel doc: kernel-parameters.txt) 
#
#     (ki1) If the same removable device is used for swap and root(99.9% users), it gets mounted twice.
#
#     (ki2) some suspend2 users might find annoying being asked for passphrases twice(swap, root)
#     when booting with noresume2, possible solution(beside using regular keyfiles)
#     could be having a single gpg encrypted file that contains the two keys.  
#     At boot, init asks for the passphrase to decrypt the file, stores it in a variable,
#     then when the keys are needed to decrypt the partitions, init would use the passphrase
#     to decrypt the gpg file and select the right key for the partition, like this:
#     <n> = line number of the key for partition.
#     echo "${gpg_passphrase}" | gpg --no-tty --passphrase-fd 0 --decrypt keys.gpg | head -n <n> | tail -n 1 
#     the obtained key can then be used with cryptsetup to decrypt the partition.
#     Caveats:
#           o) passphrase stored in bash variable, no idea how safe this is. 
#
# ToDo:
#     * lvm support
#     * raid support	
#     * steganography support -- retrieve hidden key(s)
#     * PKCS#11 cryptographic token support
#     * suspend2 filewriter support
#
# Contact:
#   o) Bugs, critics, feedback, improvements --> reikinio at gmail dot com
#   o) Flames                                --> /dev/null
#
# History: (y/m/d)
# ------------------
# 2006.08.24 - Federico Zagarzazu
#    Fix: call splash_setup() if fbsplash args exist   
# 2006.08.06 - Federico Zagarzazu
#    Released.
# 2006.08.06 - Federico Zagarzazu
#    Fixed: /dev/device-mapper /dev/mapper/control issue 
#           otherwise it fails on my amd64 system
# 2006.08.04 - Federico Zagarzazu
#    Bug fixes, several improvements.
#    Test phase finished.
# 2006.06.20 - Federico Zagarzazu
#    Written.
# 
# Thank you! 
# ---------------------------------------------------------------
# o Alon Bar-Lev [http://wiki.suspend2.net/EncryptedSwapAndRoot]
#         I stole ideas, general structure and entire functions from his init script.
# o nix
#
# o Andreas Steinmetz [kernel doc: power/swsusp-dmcrypt.txt]
#
#  ___________________________________
# | WARNING:			      |
# |______USE AT YOUR OWN RISK!________|   

# user defined variables
uv_init=/sbin/init           # init to execute after switching to real root
uv_root_mapping=root         # self descriptive
uv_swap_mapping=swap	     # ^^
uv_check_env=1               # test if busybox applets exist 

# default values(don't edit)          
gv_active_splashutil=0
gv_splash_silent=0
gv_root_mode=rw
gv_shell_checkpoint=0

# functions
die()
{
        local lv_msg="$1"
	umount -n /mnt 2>/dev/null
        [ "${gv_splash_silent}" -eq 1 ] && splash_verbose
        echo "${lv_msg}"
        echo 
        echo "Dropping you into a minimal shell..."
        exec /bin/sh
}

bin_exist()
{
	[ ! -e "/bin/${1}" ] && [ ! -e "/sbin/${1}" ] && die "Error: ${2} ${1} not found."
}

check_busybox_applets()
{
	if [ ! -e "/etc/applets" ]; then
		echo "Warning: Cannot check if BusyBox's applets exist(/etc/applets missing)"
	else
		for i in `cat /etc/applets`; do
			bin_exist ${i} "BusyBox applet" 
		done
	fi
}

rmmod_group() {
        local lv_group="$1"
        local lv_invert
        local lv_mod

        if [ -f "/etc/modules/${lv_group}" ]; then
                for mod in `cat "/etc/modules/${lv_group}"`; do
                        invert="${lv_mod} ${lv_invert}"
                done

                for mod in ${lv_invert}; do
                        #
                        # There are some modules that cannot
                        # be unloaded
                        #
                        if [ "${lv_mod}" != "unix" ]; then
                                rmmod "`echo "${lv_mod}" | sed 's/-/_/g'`"
                        fi
                done
        fi
}

modprobe_group() {
        local lv_group="$1"
        local lv_mod

        if [ -f "/etc/modules/${lv_group}" ]; then
                for mod in `cat "/etc/modules/${lv_group}"`; do
                        modprobe "${lv_mod}" > /dev/null 2>&1
                done
        fi
}

#killallwait() { # no use for it yet
#        local lv_p="$1"
#
#        while killall -q -3 "${lv_p}"; do
#                sleep 1
#        done
#}

splash_command() {
        local lv_cmd="$1"

        if [ ${gv_active_splashutil} != 0 ]; then
                echo "$lv_cmd" > /lib/splash/cache/.splash
        fi
}

splash_verbose() {
        splash_command "set mode verbose" 
}

splash_silent() {
        splash_command "set mode silent"
}

splash_message() {
        local lv_msg="$1"

        splash_command "set message ${lv_msg}"
        splash_command "repaint"
}

splash_setup() {
	[ "$uv_check_env" -eq 1 ] && bin_exist "splash_util.static" "--"
        if [ -n "${gv_splash_console}" ]; then
                exec < "${gv_splash_console}" > "${gv_splash_console}" 2>&1
        fi
        [ -e /lib/splash/cache ] || mkdir -p /lib/splash/cache
        [ -e /lib/splash/cache/.splash ] || mknod /lib/splash/cache/.splash p
        splash_util.static --daemon "--theme=${gv_splash_theme}"
        gv_active_splashutil=1
}

splash_daemon_stop() {
	if [ "${gv_active_splashutil}" -ne 0 ]; then
                splash_command "exit"
                gv_active_splashutil=0
        fi
}

shell_checkpoint() {
        local lv_level=$1

        if [ "${gv_shell_checkpoint}" -eq "${lv_level}" ]; then
                splash_verbose
		echo "Checkpoint ${lv_level}" 
                exec /bin/sh
        fi
}

suspend2_resume() {
        [ "${gv_splash_silent}" -eq 1 ] && splash_message "Resuming..."
        splash_daemon_stop

        modprobe_group suspend2
        if [ -z "${gv_splash_theme}" ]; then
                if which suspend2ui_text > /dev/null; then
                        echo `which suspend2ui_text` > /proc/suspend2/userui_program
                fi
        else
                ln -s "/etc/splash/${gv_splash_theme}" /etc/splash/suspend2
                echo `which suspend2ui_fbsplash` > /proc/suspend2/userui_program
        fi
	mount -n -o remount,ro /
        echo > /proc/suspend2/do_resume
	mount -n -o remount,rw /
        rmmod_group suspend2
	cryptsetup luksClose "${uv_swap_mapping}" 2>/dev/null || cryptsetup remove "${uv_swap_mapping}"
        die "Error: resume from hibernation failed."
}

get_key() {
	local lv_mode="${1}"
	local lv_dev="${2}"
        gv_filepath="${3}"
	local lv_devname="`echo "${lv_dev}" | cut -d'/' -f3 | tr -d '0-9'`" # for use with /sys/block/ 
	local lv_filename="`echo "${gv_filepath}" | sed 's/\/.*\///g'`"

	modprobe_group remdev
	# wait for device
	local lv_first_time=1
	while ! mount -n -o ro "${lv_dev}" /mnt 2>/dev/null >/dev/null 
	do
		if [ "${lv_first_time}" != 0 ]; then
			echo "Insert removable device and press Enter."
			read x
			echo "Please wait a few seconds...."
			lv_first_time=0
		else
			[ ! -e "/sys/block/${lv_devname}" ] && echo "Info: /sys/block/${lv_devname} does not exist."
			[ ! -e "${lv_dev}" ] && echo "Info: ${lv_dev} does not exist."
		fi
		sleep 5
	done
	echo "Info: Removable device mounted."
	# check if keyfile exist
	if [ ! -e "/mnt/${gv_filepath}" ]; then
	 	die "Error: ${gv_filepath} does not exist on ${lv_dev}."
	fi
	# get the key
	case "$lv_mode" in
		gpg)    # key will be piped into cryptsetup as a passphrase in exec_cryptsetup()
			[ "$uv_check_env" -eq 1 ] && bin_exist "gpg" "--"
			gv_key_gpg=1
			;;
		none)
			gv_key_file="/mnt/${gv_filepath}"
			;;
		*)
			die "Error: ${lv_mode} is not valid."
			;; 
	esac
}

exec_cryptsetup() {  # 1 is device, 2 is mapping
	local lv_arg1="create"
	local lv_arg2="${2}"
	local lv_arg3="${1}"

	cryptsetup isLuks "${1}" 2>/dev/null && { lv_arg1="luksOpen"; lv_arg2="${1}"; lv_arg3="${2}"; }

	if [ -n "${gv_key_gpg}" ]; then
		modprobe_group gpg
		# Fixup gpg tty requirement
		mv /dev/tty /dev/tty.org
		cp -a /dev/console /dev/tty
		while [ ! -e "/dev/mapper/${2}" ]
		do
			sleep 2
			gpg --quiet --homedir / --logger-file /dev/null --decrypt /mnt/${gv_filepath} | \
			cryptsetup "${lv_arg1}" "${lv_arg2}" "${lv_arg3}" 2>/dev/null
		done
		rm /dev/tty
		mv /dev/tty.org /dev/tty
		rmmod_group gpg
		umount -n /mnt
		rmmod_group remdev
		gv_key_gpg=
	else
		if [ -n "${gv_key_file}" ]; then
			cryptsetup -d "${gv_key_file}" "${lv_arg1}" "${lv_arg2}" "${lv_arg3}"
	                if [ "$?" -ne 0 ]; then
                                die "Error: e1 failed to decrypt ${1}."
               	        fi
			umount -n /mnt
			rmmod_group remdev
			gv_key_file=
		else
			cryptsetup "${lv_arg1}" "${lv_arg2}" "${lv_arg3}"
			if [ "$?" -ne 0 ]; then
                               	die "Error: e2 failed to decrypt ${1}."
                       	fi
		fi
	fi
}

do_root_work() {
	[ -n "${gv_root_device}" ] || die "Error: root missing."

	if [ -n "${gv_key_root_mode}" ]; then
		# if 'init_key_root' arg was given
		[ -n "${gv_key_root_device}" ] || die "Error: init_key_root: device field empty."
		[ -n "${gv_key_root_filepath}" ] || die "Error: init_key_root: filepath field empty."

		get_key "${gv_key_root_mode}" "${gv_key_root_device}" "${gv_key_root_filepath}"
	fi
	shell_checkpoint 4
	echo "Partition: root"
	exec_cryptsetup "${gv_root_device}" "${uv_root_mapping}" 
	mount -o "${gv_root_mode}" "/dev/mapper/${uv_root_mapping}" /new-root
        if [ "$?" -ne 0 ]; then
		cryptsetup luksClose "${uv_root_mapping}" 2>/dev/null || cryptsetup remove "${uv_root_mapping}" 	
        	die "Error: mount root failed, dm-crypt mapping closed."
        fi
	shell_checkpoint 5
}

do_swap_work() {
      	if [ -n "${gv_key_swap_mode}" ]; then
               	# if 'init_key_swap' arg was given
                [ -n "${gv_key_swap_device}" ] || die "Error: init_key_swap : device field empty."
                [ -n "${gv_key_swap_filepath}" ] || die "Error: init_key_swap: filepath field empty."

                get_key "${gv_key_swap_mode}" "${gv_key_swap_device}" "${gv_key_swap_filepath}"
	fi
	shell_checkpoint 2
	echo "Partition: swap"  
        exec_cryptsetup "${gv_swap_device}" "${uv_swap_mapping}"
	shell_checkpoint 3
}

do_work() {
	[ "${gv_splash_silent}" -eq 1 ] && splash_verbose
	# load kmap and font	
	if [ -n "${gv_kmap}" ]; then
		if [ -e "/etc/${gv_kmap}" ]; then
			loadkmap < "/etc/${gv_kmap}"
		else
			die "Error: keymap ${gv_kmap} does not exist on /etc"
		fi
		if [ -n "${gv_font}" ]; then
			if [ -e "/etc/${gv_font}" ]; then
				loadfont < "/etc/${gv_font}"
			else
				die "Error: font ${gv_font} does not exist on /etc"
			fi
		fi
	fi
	print_msg
	shell_checkpoint 1
	if [ -n "${gv_active_suspend2}" ]; then
		# suspend2 users should always boot this way to prevent data loss

		[ -n "${gv_swap_device}" ] || die "Error: suspend2 requires iswap argument."
		do_swap_work

		if [ "${gv_active_suspend2}" -eq 1 ]; then

			local lv_s2img="`cat /proc/suspend2/image_exists | head -n 1`"
			[ "${lv_s2img}" -eq 0 ] && die "Error: no image exist at location pointed by resume2="
			if [ "${lv_s2img}" -ne 1 ]; then
				echo
				echo "WARNING: there is no recognizable signature at location pointed by resume2="
				echo -n "Do you want to proceed(type:yes)? "
				read lv_answer
				[ "${lv_answer}" != "yes" ] && die "resume aborted by user"
			fi      
			suspend2_resume
		else
			# noresume2  
			# open swap, open root, destroy suspend2 image, switch root
			do_root_work
			echo "Destroying previous suspend2 image(if any).."
			echo 0 > /proc/suspend2/image_exists
			# alternative: mkswap "/dev/mapper/${uv_swap_mapping}" 2>/dev/null >/dev/null
			do_switch
		fi	

	else
                do_root_work
                do_switch
	fi
}

do_switch() {
	# Unmount everything and switch root filesystems for good:
	# exec the real init and begin the real boot process.
	echo > /proc/sys/kernel/hotplug
	[ "${gv_splash_silent}" -eq 1 ] && splash_silent && splash_message "Switching / ..."
	echo "Switching / ..."
	splash_daemon_stop
	sleep 1
	/bin/umount -l /proc
	/bin/umount -l /sys
	/bin/umount -l /dev
	shell_checkpoint 6
	exec switch_root /new-root "${uv_init}"
}

print_msg() {
#	clear
	echo
	cat /etc/msg 2>/dev/null
	echo
}

parse_cmdl_args() {
	local x
	CMDLINE=`cat /proc/cmdline`
	for param in $CMDLINE; do
    		case "${param}" in
			rescue)
				gv_shell_checkpoint=1
				;;
			root=*)
				gv_root_device="`echo "${param}" | cut -d'=' -f2`"
				;;
			ro)
				gv_root_mode="ro"
				;;
			splash=*)
				gv_splash_theme="`echo "${param}" | sed 's/.*theme://' | sed 's/,.*//'`"
				[ -n "`echo ${param} | grep silent`" ] && gv_splash_silent=1
				;;
			CONSOLE=*)
				gv_splash_console="`echo "${param}" | cut -d'=' -f2`"
				;;
			is2)
				# check if booting with noresume2
				if [ -z "`grep noresume2 /proc/cmdline`" ]; then
					gv_active_suspend2=1
				else
					gv_active_suspend2=0
				fi
				;;
			ikmap=*)
				gv_kmap="`echo "${param}" | cut -d'=' -f2 | cut -d':' -f1`"
				gv_font="`echo "${param}" | cut -d':' -s -f2`"		
				;;
			ichkpt=*)
				gv_shell_checkpoint=`echo "${param}" | cut -d'=' -f2`
				;;
			iswap=*)
				gv_swap_device="`echo "${param}" | cut -d'=' -f2 | cut -d':' -f1`"
				;;
			ikey_root=*)
				x="`echo "${param}" | cut -d'=' -f2 | tr ":" " "`"
				gv_key_root_mode="`echo ${x} | cut -d' ' -f1`"
				gv_key_root_device="`echo ${x} | cut -d' ' -s -f2`"
				gv_key_root_filepath="`echo ${x} | cut -d' ' -s -f3`"
				;;
			ikey_swap=*)
				x="`echo "${param}" | cut -d'=' -f2 | tr ":" " "`"
				gv_key_swap_mode="`echo ${x} | cut -d' ' -f1`"
				gv_key_swap_device="`echo ${x} | cut -d' ' -s -f2`"
				gv_key_swap_filepath="`echo ${x} | cut -d' ' -s -f3`"
				;;
	   	 esac
	done
}

main() {
	export PATH=/sbin:/bin
#	dmesg -n 1
        umask 0077
	[ ! -d /proc ] && mkdir /proc
	/bin/mount -t proc proc /proc
#       # install busybox applets
#       /bin/busybox --install -s
	[ "$uv_check_env" -eq 1 ] && check_busybox_applets
	[ "$uv_check_env" -eq 1 ] && bin_exist "cryptsetup" "--"
        [ ! -d /tmp ] && mkdir /tmp
	[ ! -d /mnt ] && mkdir /mnt
	[ ! -d /new-root ] && mkdir /new-root
	/bin/mount -t sysfs sysfs /sys
	parse_cmdl_args
	modprobe_group boot
	# populate /dev from /sys
	/bin/mount -t tmpfs tmpfs /dev
	/sbin/mdev -s
	# handle hotplug events
	echo /sbin/mdev > /proc/sys/kernel/hotplug
	[ -n "${gv_splash_theme}" ] && splash_setup
	# fix: /dev/device-mapper should be /dev/mapper/control
	# otherwise it fails on my amd64 system(busybox v1.2.1), weird that it works
	# on my laptop(i686, /dev/mapper/control gets created on luksOpen).
	if [ ! -e "/dev/mapper/control" ]; then
		# see: /proc/misc, /sys/class/misc/device-mapper/dev 
		mkdir /dev/mapper && mv /dev/device-mapper /dev/mapper/control
		echo "device-mapper mapper/control issue fixed.." >> /.initlog
	fi
	do_work
}
main

Please, do not edit the script in the wiki directly, send changes to me(reikinio at gmail dot com) instead, thank you.

Code: busybox 1.2.2.1 (and up?)

Newer busyboxes have a bug/difference with "cut". Change:

iswap=*)
    gv_swap_device="`echo "${param}" | cut -d'=' -f2 | cut -d':' -f1`"

to:

iswap=*)
    gv_swap_device="`echo "${param}" | cut -d'=' -f2`"

In fact, even if you're using an older version, I suspect that this is a bug in the init script due to copy-n-paste programming.

As you can see, the init script is quite big, if you find it hard to understand you might find the ABS guide helpful.
The script has its own set of arguments, look at the list below to understand what each one does.
You can see some examples in the init script comments, and later in the guide when configuring the bootloader.

Arguments
Standard
root=<device> root device, e.g: /dev/sda3 (required).
ro mount root read only.
Init specific
ikmap=<kmap>[:<font>] load keymap and font(optional).
is2 enables suspend2 support(required for suspend2 users).
rescue drops you into a minimal shell.
iswap=<device> swap device(e.g:/dev/sda2) (required for suspend2 users).
ichkpt=<n> interrupts init at checkpoint n and drops to shell.
ikey_root=<mode>:<device>:</path/to/file> key for root partition is on removable device(see table below).
ikey_swap=<mode>:<device>:</path/to/file> key for swap partition is on removable device(see table below).
Keys on removable devices
<mode> defines how the init script shall treat the supplied keyfile(see table below).
<device> the device that will be assigned to the removable media.
</path/to/file> full path to file inside the removable media.
Supported modes
gpg indicates keyfile is gpg-protected
none indicates keyfile is regular file

About keys

Initramfs's structure

Code: Structure -- BusyBox's applets not printed.
# created with the 'tree' utility.
# ‘/’ for directories
# ‘*’ for executable files
.
|-- bin/
|   |-- busybox*
|   `-- gpg*                        (Optional) if key is encrypted with gpg
|-- dev/
|   |-- console
|   |-- fb/                         (Optional, fbsplash) 
|   |-- misc/
|   |-- null
|   `-- vc/                         (Optional, fbsplash) 
|-- etc/
|   |-- applets                     (Optional) list of required busybox's applets
|   |-- es-cp850_uni_x86-64.bin     (Optional) kmap
|   |-- modules/
|   |   |-- boot                    (Optional) list of modules required for boot
|   |   |-- gpg                     (Optional) list of modules required for gpg
|   |   |-- remdev                  (Optional) list of modules required for removable device 
|   |   `-- suspend2                (Optional) list of modules required for resume 
|   |-- msg                         (Optional) message to display at boot
|   `-- splash/                     (Optional) fbsplash
|       `-- livecd-2006.0/
|           |-- 1024x768.cfg
|           |-- Vera.ttf
|           `-- images/
|               |-- background-1024x768.png
|               |-- text.png
|               `-- verbose-1024x768.png
|-- init*
|-- lib/                            (Optional) only if you need to load modules 
|   `-- modules/
|       `-- `uname -r`/
|           `-- (...)
|-- new-root/
|-- proc/
|-- sbin/
|   |-- cryptsetup*
|   |-- splash_helper*              (Optional, fbsplash)
|   |-- splash_util.static*         (Optional, fbsplash)
|   |-- suspend2ui_fbsplash*        (Optional, suspend2 && fbsplash)
|   `-- suspend2ui_text*            (Optional, suspend2 && ! fbsplash ) 
`-- sys/
This file is a list of required BusyBox's applets for correct init execution, init will check if the applets listed are available and it'll abort if one is missing, it's optional and can be disabled in the init script.
This file is used to print a message, you can use it to display ascii art to spice things up(like in the screenshot).
Just search the web for "ascii art"(skull).

Building initramfs image

cryptsetup-luks
Tool to setup encrypted devices with dm-crypt
Developer: Clemens Fruhwirth
Package: sys-fs/cryptsetup-luks
Category: sys-fs
License: GPL-2
Website: http://luks.endorphin.org/

An initramfs image is a gzipped cpio archive that will be unpacked into rootfs by the kernel, there're several ways to build such an archive but only one will be documented here.
The method used here is to populate a directory with initramfs's contents, and compressing it with the cpio and gzip utilities.

If you want to learn about other methods, this is what you want to read:


Code: Building initramfs image

Create a temporary directory to populate it with initramfs contents

mkdir build_initramfs

Create applets links to busybox executable

cd /path/to/busybox-<version> 
make busybox.links
./applets/install.sh /path/to/build_initramfs --symlinks


Create required directories

cd /path/to/build_initramfs
mkdir {proc,sys,new-root,etc,dev}

Copy init script

cd /path/to/build_initramfs
cp /path/to/init .
chmod 755 init

Create required device nodes(you have to be root).

mknod --mode=0660 /path/to/build_initramfs/dev/null c 1 3
mknod --mode=0600 /path/to/build_initramfs/dev/console c 5 1

Copy cryptsetup-luks executable.
You need a statically linked cryptsetup executable, emerge it or download one from http://luks.endorphin.org/dm-crypt.

cp -p `which cryptsetup` /path/to/build_initramfs/sbin/

If you use(or plan to use) gpg encrypted keyfiles, you must include the gpg executable into initramfs.
The executable should be statically linked.
Gentoo users only need to enable the "static" use flag and emerge gnupg.

echo "app-crypt/gnupg static" >> /etc/portage/package.use
# Note: latest version of gnupg lacks the static use flag
#       execute this instead:
USE="static" emerge -av =gnupg-1.4.4

cp -p `which gpg` /path/to/build_initramfs/bin/

Copy message file(like ascii art), kmap, font. (optional)

cp /path/to/msg /path/to/build_initramfs/etc/
cp /path/to/kmap /path/to/build_initramfs/etc/
cp /path/to/font /path/to/build_initramfs/etc/

Copy applets file, this file has a list of busybox applets required for correct init operation, this is not required and can be disabled by editing the proper variable in the init script.

cp /path/to/applets /path/to/build_initramfs/etc/ 
Note: busybox-1.1.3 and possibly later versions do not create a /bin/sh applet. This will make the kernel panic with the confusing error "init not found". If this is the case for you, you'll need to replace all occurrences of /bin/sh with /bin/ash in the init script (sed -i -e 's/\/bin\/sh/\/bin\/ash/g' /path/to/build_initramfs/init). You can't just create a symlink for /bin/sh because busybox will complain that the sh applet couldn't be found.
Code: fbsplash

Please refer to its documentation:

splashutils comes with splash_geninitramfs, which is used for creating a simple initramfs for fbsplash, it also has an option to append files to an initramfs image, unfortunately it uses the --dereference option of cpio when creating the archive, which breaks all busybox symlinks.

You have two options, use splash_geninitramfs, decompress the initramfs it generates and copy its file to this initramfs build directory, or copy the files from /etc/splash directly.
There is no point on using splash_geninitramfs if you know which files need to be included, therefore this is what you need to do:

cd /path/to/build_initramfs/etc
# substitute <theme> with the fbsplash theme you want to use(look in /etc/splash)
mkdir -p splash/<theme>/images
# substitute <res>.cfg with the proper config file(look in /etc/splash/<theme>)
cp -p /etc/splash/<theme>/<res>.cfg splash/<theme>/
cp -p /etc/splash/<theme>/Vera.ttf splash/<theme>/ 
# copy the images, substitute <res> with the proper resolution.
cp -p /etc/splash/<theme>/images/background-<res>.png
cp -p /etc/splash/<theme>/images/verbose-<res>.png
cp -p /etc/splash/<theme>/images/text.png 

Now you've to copy some programs for correct fbsplash operation.

cp -p `which splash_helper`  /path/to/build_initramfs/sbin/
cp -p `which splash_util.static` /path/to/build_initramfs/sbin/ 
Code: suspend2

Suspend2 users need to include the userspace program that provides a user interface while suspending.

# If you use fbsplash 
cp -p `which suspend2ui_fbsplash` /path/to/build_initramfs/sbin/
# else
cp -p `which suspend2ui_text` /path/to/build_initramfs/sbin/
Code: Compressing directory

And finally, create the initramfs image(gzipped cpio format archive)

cd /path/to/build_initramfs
find . | cpio --quiet -o -H newc | gzip -9 >/root/initramfs-gentoo-crypt  

Remember the location of the initramfs image, you'll need it later.


Tip! You can list the contents of the initramfs image with this command:

zcat /path/to/initramfs_img.cpio.gz | cpio --list

Alternative (easy) initramfs creating

This method is *much* easier, but does not support additional kernel modules like lvm. BUT, for the default user, it is perfectly ok to use it, as it is much less complicated and will save you a lot of headaches.

Have a look at: SECURITY Encrypting Root Filesystem with DM-Crypt with LUKS#Using initramfs and busybox

Kernel Configuration

initramfs:
The initramfs image can be built into the kernel or passed from the bootloader, it's up to you to decide which method to use, if in doubt use the latter.

All 2.6.* kernels include a default initramfs if none is provided by the user, this initramfs gets created automatically when you compile the kernel.
In most systems it is ignored and the kernel falls back to legacy boot code.


initramfs built into the kernel:
The only thing you've to do is place your initramfs in /usr/src/linux/usr/.

Code: initramfs built into the kernel

If you are recompiling the kernel you first need to delete the default initramfs image that was generated by the kernel build process.
If this is not your case, the file will not exist so you can skip this step.

rm -iv /usr/src/linux/usr/initramfs_data.cpio.gz

Copy the initramfs image to the proper directory to let the kernel use it.

# important: rename it to "initramfs_data.cpio.gz" 
cp /root/initramfs-gentoo-crypt /usr/src/linux/usr/initramfs_data.cpio.gz

Prevent the kernel from overwriting the initramfs image.

touch /usr/src/linux/usr/initramfs_data.cpio.gz

Done, continue with configuring your kernel.
Leave CONFIG_INTIRAMFS_SOURCE empty!

Note: If you deviated from the guide to let the kernel build the initramfs image, you have to edit CONFIG_INTIRAMFS_SOURCE properly.


Linux Kernel Configuration: Required
Device Drivers  --->
        Multi-device support (RAID and LVM)  --->
               <*>   Device mapper support
               <*>     Crypt target support

Enable this two options below only if you're going to pass the initramfs archive via the bootloader.

Device Drivers  --->
        Block devices  --->
               <*> RAM disk support
               [*]   Initial RAM disk (initramfs/initrd) support
File systems  --->
        Pseudo filesystems  --->
          [*] /proc file system support
          [*] Virtual memory file system support (former shm fs) 
          # support for sysfs required (CONFIG_SYSFS)

Don't forget to include support for the ciphers you use.

Cryptographic options  ---> 
        <*>   SHA256 digest algorithm
        <*>   SHA384 and SHA512 digest algorithms
        <*>   Blowfish cipher algorithm
        <*>   Twofish cipher algorithm
        <*>   Serpent cipher algorithm
        <*>   AES cipher algorithms (x86_64)
Note: Do not build them as modules!


Linux Kernel Configuration: Booting from usb-stick
Device Drivers  ---> 
      USB support  --->
          <*> Support for Host-side USB
          <*> USB Mass Storage support

Depends on your hardware(enable them all if not sure)

          <*>   EHCI HCD (USB 2.0) support 
          <*>   OHCI HCD support
          <*>   UHCI HCD (most Intel and VIA) support
File systems  --->  
      <*> Second extended fs support
Note: Don't forget to include support for fbsplash and/or suspend2 if you use them.
Tip! Rule of thumb: always keep a working kernel and save your .configs

Users with /boot partition:
Copy the kernel to /boot, plus the initramfs archive if you're going to pass it via the bootloader.

Users booting with usb-stick:
Copy the kernel to /mnt/usb/ plus the initramfs archive if you're going to pass it via the bootloader, of course you have to do this after formatting the partition(next section).

Before you continue, you should install sys-fs/device-mapper.

Device mapper ioctl library for use with LVM2 utilities.
emerge device-mapper

Follow the Gentoo installation guide until you reach step 8.a

/etc/fstab

This section is only here to remind you to use mapping names and not the real devices.
Adjust it to suit your system.

File: fstab
/dev/sda1               /boot           ext2    defaults,noatime        1 2 
/dev/mapper/swap        none            swap    sw                      0 0
/dev/mapper/root        /               ext3    noatime                 0 1
none                    /proc           proc    defaults                0 0
none                    /dev/shm        tmpfs   nodev,nosuid,noexec     0 0
/dev/cdrom              /mnt/cdrom      auto    noauto,user             0 0

Follow the Gentoo installation guide from step 8.b until you reach step 10(Configuring the Bootloader)

Bootloader configuration

Note: LILO bootloader is not supported by the init script.

GRUB:

File: grub.conf
default 0
timeout 5
splashimage=(hd0,0)/grub/splash.xpm.gz

Very simple example, initramfs built into kernel, root with passphrase and no fbsplash.

title=Gentoo <kernel-version>
root (hd0,0)
kernel /boot/kernel-<version> root=/dev/sda3

Another simple example, but this time the initramfs archive is passed via the bootloader.

title=Gentoo <kernel-version>
kernel /boot/kernel-<version> root=/dev/sda3
initrd /boot/initramfs-gentoo-crypt 

An example with fbsplash, root with passphrase, and this time telling init to load a kmap.

title=Gentoo <kernel-version>
kernel /boot/kernel-<version> root=/dev/sda3 ikmap=es-cp850_uni_x86-64.bin \
vga=0x318 video=vesafb:ywrap,mtrr:3 splash=verbose,theme:livecd-2006.0 \ 
quiet CONSOLE=/dev/tty1
initrd /boot/initramfs-gentoo-crypt

An example where the key for the root partition key is gpg encrypted, the key exist on a usb-stick(the assigned device is /dev/sdb because the main system hdd is sata, yours might vary), if the usb-stick is not plugged in you'll be asked to insert the removable media by the init script.

title=Gentoo <kernel-version>
kernel /boot/kernel-<version> root=/dev/sda3 \ 
ikey_root=gpg:/dev/sdb1:/fullpath/to/rootkey.gpg 
initrd /boot/initramfs-gentoo-crypt

An example for suspend2 users with fbsplash, swap partition with passphrase.
In this example you're going to resume from hibernation.
It's recommended to have at least two entries in your bootloader configuration, one to use for resuming and one for a normal boot.

title=Gentoo s2 <kernel-version> resume
kernel /boot/kernel-<version> is2 iswap=/dev/sda2 \
resume2=swap:/dev/mapper/swap \
vga=0x318 video=vesafb:ywrap,mtrr:3 splash=verbose,theme:livecd-2006.0 \
quiet CONSOLE=/dev/tty1
initrd /boot/initramfs-gentoo-crypt

Another example for suspend2 users, this time you're not going to resume from hibernation'.
It'll decrypt your root and swap partitions, in this example, root with passphrase and swap with regular keyfile.
The suspend2 resume2 argument is required if you want to be able to suspend, so leave it there.

title=Gentoo s2 <kernel-version> noresume
kernel /boot/kernel-<version> root=/dev/sda3 iswap=/dev/sda2 \
is2 noresume2 resume2=swap:/dev/mapper/swap \
ikey_swap=none:/dev/sdb1:/path/to/swapkey \
vga=0x318 video=vesafb:ywrap,mtrr:3 splash=verbose,theme:livecd-2006.0 \
quiet CONSOLE=/dev/tty1
initrd /boot/initramfs-gentoo-crypt


Note: Don't forget to execute grub-install /dev/sda


extlinux:

Intended for people booting from usb-stick.

File: extlinux.conf

If you want more examples take a look at the GRUB configuration box above, there're more in the init script, only two examples will be listed here.
The important thing is that if you pass the initramfs via the extlinux bootloader, you must add initrd=initramfs-gentoo-crypt to the kernel parameter list.

DEFAULT menu.c32
TIMEOUT 100
PROMPT 0

An example with fbsplash and root partition with passphrase.

LABEL Gentoo
        MENU LABEL Gentoo ^Linux <version>
        MENU DEFAULT
        KERNEL vmlinuz
        APPEND root=/dev/sda3 vga=0x318 video=vesafb:ywrap,mtrr:3 \
        splash=verbose,theme:livecd-2006.0 quiet CONSOLE=/dev/tty1 \
        initrd=initramfs-gentoo-crypt

Another example for suspend2 users, swap partition with passphrase.

LABEL Gentoo
        MENU LABEL Gentoo ^Linux <version> s2 resume
        MENU DEFAULT
        KERNEL vmlinuz
        APPEND iswap=/dev/sda2 is2 resume2=swap:/dev/mapper/swap \
        vga=0x318 video=vesafb:ywrap,mtrr:3 \
        splash=verbose,theme:livecd-2006.0 quiet CONSOLE=/dev/tty1 \
        initrd=initramfs-gentoo-crypt 

Booting from usb-stick

This section explain the steps to prepare an usb-stick to boot with an encrypted root partition. The kernel, keyfiles and (optional) the initramfs archive are stored on the usb-stick.
The procedure is similar to the one found on loop-AES README(section 7.7), with the exception that extlinux will be used instead of syslinux.

Requirements

extlinux is bootloader which boots from a Linux ext2/ext3 filesystem(emerge syslinux).


Code: USB-stick - extlinux

Plug your usb-stick, unmount it(important).
The usb-stick device in this is example is /dev/sdb, the device that will be assigned to yours might be different, adjust it properly.

The first thing to do is to wipe its MBR, partition table and beginning of an existing filesystem.

dd if=/dev/zero of=/dev/sdb bs=1024k count=5 conv=notrunc

Use fdisk(or cfdisk) to create a primary partition and set the boot flag, it should be big enough to hold the kernel, initramfs archive, keyfiles, etc..(if in doubt create a single partition of the whole drive).

Create filesystem(ext2).

mke2fs -m0 /dev/sdb1

Install MBR, you need the mbr.bin file that comes with syslinux.

mkdir tempdir && cd tempdir
cp /usr/portage/distfiles/syslinux-<version>.tar.bz2 .
tar -xvjf syslinux-<version>.tar.bz2 
cd syslinux-<version>
# install mbr
cat mbr.bin > /dev/sdb

Mount it.

mount -t ext2 /dev/sdb1 /mnt/usb

Copy the kernel, initramfs(if any), etc...

cp /usr/src/linux/arch/<arch>/boot/bzImage /mnt/usb/ 
cp /root/initramfs-gentoo-crypt /mnt/usb
# copy this file to get a simple menu
cp syslinux-<version>/com32/modules/menu.c32 /mnt/usb

Copy keyfiles for each partition that should be decrypted by the init script(if any).

mkdir /mnt/usb/keys
# example: gpg protected keyfile
cp /path/to/root-key.gpg /mnt/usb/keys

Install extlinux, the install is run on a mounted filesystem.

extlinux /mnt/usb

Copy extlinux.conf, the configuration file for the bootloader is expected to be found in the same directory that you installed extlinux.

cp /path/to/extlinux.conf /mnt/usb/

Unmount it.

umount /mnt/usb
sync

Done


Note: extlinux supports subdirectories, but the total path length is limited to 255 characters.

Decrypting/Encrypting partitions at startup

This is handled by Gentoo's /etc/conf.d/dmcrypt implementation scripts, you get them if you install sys-fs/cryptsetup-luks through portage.
Gentoo users can use this file to control which(and how) partitions should be decrypted.
Its documentation is available as comments inside the configuration file(/etc/conf.d/dmcrypt).
Gentoo users should use this file to decrypt all partitions(beside root) while system startup.

Non Gentoo users will have to check if their distribution has something similar, if not, they will have to write the scripts themeselves.

Note: The scripts are located at /lib/rcscripts/addons/dm-crypt*


How to use /etc/conf.d/dmcrypt(enough to get you started, but read its documentation as well):

The examples in /etc/conf.d/dmcrypt are a bit confusing since they set the source to a device-mapper file instead of the underlying device and don't indicate where to specify the mount point. Here is an example of how to mount /home at startup using /etc/conf.d/dmcrypt.


File: /etc/conf.d/dmcrypt -- /home example

First, add a cryptfs entry so that the device-mapper mappings can be setup.

mount=crypt-hda3
source='/dev/hda3'
type=luks
options=' '

The mount can be any name you prefer. The source should be the underlying device. The options is set to a single space as otherwise the default options are passed to cryptsetup luksOpen (they happen to be ignored by luksOpen but I find it undesirable to pass ignored and potentially incorrect information).
Version 1.0.3-r3 of the ebuild (released Oct 12 2006) introduced new syntax of cryptfs. In this case the example above would look like this:

target=crypt-hda3
source='/dev/hda3'

The name change (mount to target) aside, the option type has been removed in favour of an automatic check for whether the partition is a LUKS one or not; moreover, it is no longer necessary to clear the option string - it is empty by default for all non-swap partitions. Last but not least, plain-text and GnuPG-encrypted key files are now supported; check the examples in the default version of the file for more information on the subject.

File: fstab

Second, add an fstab entry so that the mount point of the encrypted filesystem can be determined.

/dev/mapper/crypt-hda3        /home           auto            noatime         0 0

The last step

Code: last steps

Finally, the moment you were waiting for, reboot the system and hope everything works correctly.

# exit the chrooted enviroment
exit
# unmount all partitions
umount /mnt/gentoo/boot
umount /mnt/gentoo/proc
umount /mnt/gentoo/dev
umount /mnt/gentoo
sync
# close all the mappings
cryptsetup luksClose swap
cryptsetup luksClose root

Good luck!

Warning: Burn the paper where you wrote down the passphrase!


The End.

Support

Before asking questions, please read the FAQ first, thank you.

Contributing

It's an open document and people are invited to contribute, only with your help it can become better, there are several ways to contribute:

Guidelines:

Since the gentoo-wiki's notifications of the discussion page sometime seems to get lost, if you see that after some time I've not responded, drop me an email.

Thank you, and if you are helping out, it would be nice if you add your name to the Author(s) section.

Author(s)

A special thank you to the developers of cryptsetup-luks and Dm-Crypt.
They're the ones who make all this possible.


-- Reikinio -- Federico Zagarzazú(no longer mantains this document)

Child Documents

References

Ciphers

Some of the available ciphers found on the cryptographic kernel menu:


Further reading

Attacks:

Misc:

More Links

FAQ

Please see LUKSFaq as well.

Code: Deleting passphrases

Note: The partition can be mounted.

cryptsetup luksDelKey <device> <slot> 

Warning:
If there is only one passphrase and you try to delete you will get a warning. If you ignore the warning and go ahead, your data is lost forever.


Code: Changing passphrase for /

First add the new passphrase

cryptsetup luksAddKey /dev/sda3
Enter any LUKS passphrase:
key slot 0 unlocked. 
Enter new passphrase for key slot:

Now delete the old passphrase, in this example the old passphrase is on key slot 0.

cryptsetup luksDelKey /dev/sda3 0

For more information, consult cryptsetup's manual.

cryptsetup-luks-1.0.3 had bug which caused this. Upgrade to >=cryptsetup-1.0.5!

It may be possible for someone to target a user in this way, if the root partition or kernel is not encrypted when the computer is shutdown. Even if you use hardware to generate random numbers, an infected machine could opt not to use those properly. Over time, new data on the drive could be decrypted more easily and the effective search space for the key would be reduced should a brute-force attack be attempted.
Solution: Do a hash of the relevant parts of your system and store it on removable media. Check intermittently to see if the hash has changed.


Keep trying if you do not find an answer below.


Code: editing an initrd, summary
losetup /dev/loop4 initrd
mkdir /mnt/initrd
mount /dev/loop4 /mnt/initrd
# edit it
umount /mnt/initrd
losetup -d /dev/loop4
# done


failed to setup dm-crypt mapping.
failed to write to key storage.
Command failed.
Make sure you're passing the right options to cryptsetup,
For example: --cipher serpent-cbc-essiv:sha256 , is right
--cipher serpent-cbc-essiv --hash sha256 is wrong!


failed to setup dm-crypt mapping
failed to read from key storage
Command failed: No key available with this passphrase
Try -v as additional parameter.
Check that you have dm-crypt and device-mapper included in the kernel.
Check you have the necessary ciphers included in the kernel.
Check the devices nodes.
The minor device number of control during boot with live cd doesn't have to be the same with later kernel. The only way to be sure to have the correct one is to check it after booting with the final kernel. Temporaly add a /bin/bash to your linuxrc and uncomment the unmounting of proc, then boot it. Being in bash with the final kernel do a cat /proc/misc and see the "real" minor device number.

See LUKSFaq.


Make sure that on your root partition, you have a /sys directory. This is important because udev requires a mounted sysfs virtual filesystem.
Code: creating /sys
# Mounting not necessary if your root partition is already mounted.
mount /
mkdir /sys
# Reboot and let udev try again.
reboot


Basically backup all the important data and follow the guide, if you're a Gentoo user, you might want to check out Stage4 on the Gentoo forums.


Yes, see here.
Crypted DVD/CD media using Luks wiki.


Perform the relevant steps from your current system, there is no need to reinstall.


You could transfer the data to an encrypted removable media first.


Failed to execute /init
Kernel panic - not syncing: No init found. Try passing init= option to kernel.
Your kernel is not unpacking the initramfs archive, please follow this steps:
Code: Troubleshooting -- Users with initramfs built into the kernel

0) Do not despair.

1) Boot with your livecd, open root partition, mount and chroot.

2) Create the initramfs archive again, make sure you are in the build_initramfs directory before creating the gzipped cpio format archive.
Make sure init has executable permissions, and double check your initramfs structure with the one provided in the guide.

cd build_initramfs
# create the contents as described in the guide.
# remove previous initramfs archive from kernel source, and
# create a new one. 
rm -iv /usr/src/linux/usr/initramfs_data.cpio.gz
find . | cpio --quiet -o -H newc | gzip -9 >/usr/src/linux/usr/initramfs_data.cpio.gz

3) Touch /usr/src/linux/usr/initramfs_data.cpio.gz to avoid the kernel from overwritting it.

touch /usr/src/linux/usr/initramfs_data.cpio.gz

4) Configure your kernel as indicated by the guide.
Make sure that you are not setting CONFIG_INITRAMFS_SOURCE(leave it empty) in your kernel configuration.

5) Compile the kernel

6) Checking if initramfs archive was built into the kernel, the kernel size will be bigger than usual, /usr/src/linux/usr/initramfs_data.cpio.gz contents should be the same of build_initramfs directory.

# kernel size should be bigger than usual
du -h /usr/src/linux/arch/<arch>/boot/bzImage
# initramfs_data.cpio.gz should be the same of build_initramfs
zcat /usr/src/linux/usr/initramfs_data.cpio.gz | cpio --list

7) Copy kernel to /boot or /mnt/usb(if booting with usb-stick)

# mount /boot first
cp /usr/src/linux/arch/<arch>/boot/bzImage /boot
# booting from usb stick: 
cp /usr/src/linux/arch/<arch>/boot/bzImage /mnt/usb/vmlinuz

8) Edit grub.conf and make sure it uses the new kernel

9) Make sure that /bin/sh exists in the initramfs. The first line of the init script (#!/bin/sh) may be failing. See the note about /bin/ash above (in the section on creating the initramfs image).

10) Reboot

Íf it keeps failing you might want to try letting the kernel handle initramfs archive creation.

Code: Troubleshooting -- Users with initramfs passed via the bootloader

Create the initramfs archive as described in the guide, double check your kernel configuration, this options are required.

 Device Drivers  --->
   Block devices  --->
    <*> RAM disk support
    [*]   Initial RAM disk (initrd) support

Reboot.

If it keeps failing you might want to try letting the kernel handle initramfs archive creation.

Code: Letting the kernel build process handle initramfs creation
  • Populate the contents of build_initramfs with initramfs contents as described in the guide, but do not create the initramfs archive.
  • Configure your kernel and edit CONFIG_INITRAMFS_SOURCE to make it point to the build_initramfs directory.
  • After this, compile the kernel, the initramfs will get built into the kernel, check its( kernel) size(it should be bigger than usual), in addition the kernel will save the initramfs archive in /usr/src/linux/usr/initramfs_data.cpio.gz, the contents of this archive should be the same of build_initramfs directory.
  • Copy kernel to /boot or /mnt/usb and reboot.


recode dos/CR-LF ./init

If it keeps failing, well.. you're on your own.
You probably made a mistake along the way, either keep trying or try using genkernel.

Retrieved from "http://www.gentoo-wiki.info/SECURITY_System_Encryption_DM-Crypt_with_LUKS"

Last modified: Fri, 26 Sep 2008 18:25:00 +1000 Hits: 105,241

Created by NickStallman.net, Luxury Homes Australia
Real estate agents should list their apartments, townhouses and units in Australia.