282 lines
11 KiB
Plaintext
282 lines
11 KiB
Plaintext
Debian Cryptsetup Initramfs integration
|
|
=======================================
|
|
|
|
1. Introduction
|
|
---------------
|
|
|
|
Kernels more recent than 2.6.12 have dropped support for devfs, which
|
|
means that initrd-tools can no longer be used to boot into an encrypted
|
|
root partition. Instead, a similar functionality has been developed for
|
|
use with an initramfs-image.
|
|
|
|
|
|
2. A fresh installation
|
|
-----------------------
|
|
|
|
If you plan to perform a completely new installation of Debian onto a
|
|
machine and to do so using an encrypted root partition, you might want
|
|
to consider using a version of Debian Installer with partman-crypto
|
|
(see https://wiki.debian.org/DebianInstaller/PartmanCrypto).
|
|
|
|
The installation will then take care of all the details and perform the
|
|
necessary configuration for you, meaning that you should not have to
|
|
read the rest of this document to get a machine with an encrypted
|
|
root filesystem up and running.
|
|
|
|
However, if you are not planning to perform a new installation from scratch,
|
|
the following information might be useful to you.
|
|
|
|
|
|
3. Requirements
|
|
---------------
|
|
|
|
In order to boot from an encrypted root filesystem, you need an
|
|
initramfs-image which includes the necessary kernel modules and scripts to
|
|
setup the root device after the kernel has been initialized, but before the
|
|
rest of the operating system is booted.
|
|
|
|
To do so, you need two partitions:
|
|
* an unencrypted `/boot` partition
|
|
* an encrypted `/` partition
|
|
|
|
In addition, you need to have both initramfs-tools and busybox installed.
|
|
|
|
NOTE: You should make sure that your swap partition is either encrypted, or
|
|
that you are using a swap file on an encrypted partition, as crypto keys and
|
|
other sensitive information might otherwise be written out to the swap
|
|
partition in unencrypted form.
|
|
|
|
|
|
4. Setup (regular dm-crypt)
|
|
---------------------------
|
|
|
|
First of all, you must edit `/etc/crypttab` and add a line describing your
|
|
root device, for example:
|
|
|
|
cryptroot /dev/sda2 none cipher=aes-xts-plain64,size=256,hash=sha1
|
|
|
|
This will allow cryptsetup to create `/dev/mapper/cryptroot` from the
|
|
encrypted partition `/dev/sda2` during boot.
|
|
|
|
In addition, you must also make sure that the root device is listed in
|
|
`/etc/fstab`, for example:
|
|
|
|
/dev/mapper/cryptroot / ext4 defaults 0 1
|
|
|
|
This will allow the initramfs support scripts to know which of the devices
|
|
in the crypttab that is the root device.
|
|
|
|
After doing these changes, you should regenerate the initramfs by running
|
|
`update-initramfs -u`, then make sure that your boot loader is configured
|
|
to feed the initramfs to the kernel when booting. The kernel root argument
|
|
should also be changed to `/dev/mapper/cryptroot`.
|
|
|
|
Now, reboot the machine, and if everything is correctly configured, you
|
|
should be given a prompt to type in the passphrase for the encrypted
|
|
root partition before the boot can continue.
|
|
|
|
NOTE: In order to ensure that the crypto setup works in a consistent
|
|
manner, you should make sure that the hash function is specified in the
|
|
/etc/crypttab file if you are using regular dm-crypt (with LUKS the hash
|
|
function to use is stored in the LUKS header).
|
|
|
|
|
|
5. Setup (using LUKS)
|
|
---------------------
|
|
|
|
If you are using the LUKS feature of cryptsetup, the above setup recipe should
|
|
still apply, but since most options can be derived from the information stored
|
|
in the LUKS header on-disk, the line to add to `/etc/crypttab` should look
|
|
something like this:
|
|
|
|
cryptroot /dev/sda2 none luks,discard
|
|
|
|
|
|
6. Exotic key types
|
|
-------------------
|
|
|
|
The above examples assume that you use a regular passphrase as the key to the
|
|
encrypted filesystem. However, if you wish to make use of more complex setups
|
|
(such as root-key-on-usb-memory), you can create a script which does all the
|
|
steps necessary to retrieve the key and then prints it to stdout.
|
|
|
|
Then add a `keyscript=/path/to/your/script.sh` to the options (fourth column)
|
|
in the above mentioned `/etc/crypttab` line, so that it looks something like
|
|
this:
|
|
|
|
cryptroot /dev/sda2 none luks,discard,keyscript=/usr/local/sbin/cryptkey
|
|
|
|
Next, regenerate your initramfs image. This will copy the script into the
|
|
initramfs image under the `/lib/cryptsetup/keyscripts/` directory.
|
|
|
|
NOTE: there is a limited set of tools available when the script is executing
|
|
as part of the initramfs bootup, you have to make sure that you do not use
|
|
any tools which are not available or your script, and therefore boot, will
|
|
fail.
|
|
|
|
|
|
7. "cryptopts" boot argument
|
|
----------------------------
|
|
|
|
In general, you should use the above approach with a line describing your
|
|
root partition in `/etc/crypttab` and `/etc/fstab`. However, if for some
|
|
reason you wish to override the settings that are derived from these files
|
|
and stored in the initramfs image, you can use the "cryptopts" boot argument
|
|
(this *only* works for the root partition).
|
|
|
|
The format of cryptopts is:
|
|
|
|
cryptopts=<opt1>=<value1>,<opt2>=<value2>...
|
|
|
|
Beside the `hash`, `size`, `cipher` and `lvm` options that correspond to the
|
|
same options in the fourth field of /etc/crypttab, the options `target`,
|
|
`source` and `key` are also supported. They correspond to the first, second
|
|
and third field of /etc/crypttab, respectively. See the crypttab man page
|
|
for further details.
|
|
|
|
Several `cryptopts` boot arguments can also be specified in case more than
|
|
one mapping needs to be setup in the initramfs stage of the boot.
|
|
|
|
Example boot arguments:
|
|
|
|
root=/dev/mapper/crypt0 cryptopts=target=crypt0,source=/dev/sda1,cipher=aes-xts-plain64,size=256,hash=sha1
|
|
|
|
In particular, if all `cryptopts` boot arguments have an empty value
|
|
then no mapping is setup. This can be used to disable the cryptsetup
|
|
initramfs scripts for a particular boot.
|
|
|
|
8. Resume device support
|
|
------------------------
|
|
|
|
The initramfs scripts will also try to automatically determine the devices,
|
|
if any, that are used for software suspend (swsusp, suspend2 or uswsusp) and
|
|
to set them up during the initramfs stage in order to allow suspend and resume
|
|
in combination with encryption to keep the resume image safe from potential
|
|
attackers.
|
|
|
|
If your resume device and your root partition use two different cryptsetup
|
|
mappings, you might want to use the `decrypt_derived` keyscript as described
|
|
below.
|
|
|
|
9. The `decrypt_derived` keyscript
|
|
----------------------------------
|
|
|
|
Assume that you have two entries in `/etc/crypttab`:
|
|
|
|
cryptroot /dev/sda1 none luks,discard
|
|
cryptswap /dev/sda2 none luks
|
|
|
|
If cryptswap is used as your suspend/resume device, you'd normally need to
|
|
enter two different passphrases during the boot, but the `decrypt_derived`
|
|
script can generate the key for the second mapping using a hash of the key
|
|
for the first mapping.
|
|
|
|
In short, you'll need to do something like the following to take advantage
|
|
of the decrypt_derived script:
|
|
|
|
1. `swapoff -a`
|
|
2. `cryptsetup luksClose cryptswap`
|
|
3. edit `/etc/crypttab` and change the cryptswap line to e.g.:
|
|
`cryptswap /dev/sda2 cryptroot cipher=aes-xts-plain65,size=256,hash=sha1,keyscript=decrypt_derived,swap`
|
|
4. `cryptdisks_start cryptswap`
|
|
5. Make sure that `/dev/mapper/cryptswap` has been created
|
|
6. `swapon -a`
|
|
7. (optional) `update-initramfs -u`
|
|
|
|
After you've followed the above steps, your swap device should be setup
|
|
automatically after the root device has been setup during the boot stage.
|
|
|
|
WARNING: If you use the decrypt_derived keyscript for devices with persistent
|
|
data (i.e. not swap or temp devices), then you will lose access to that data
|
|
permanently if something damages the LUKS header of the LUKS device you derive
|
|
from. The same applies if you luksFormat the device, even if you use the same
|
|
passphrase(s). A LUKS header backup, or better a backup of the data on the
|
|
derived device may be a good idea. See the Cryptsetup FAQ on how to do this
|
|
right.
|
|
|
|
Note: The decrypt_derived keyscript won't work when the volume key of the
|
|
device being derived from is offloaded to the kernel keyring service (thus not
|
|
readable by userspace). That behavior is the default for LUKS2 devices (unless
|
|
opened with the `--disable-keyring` option) since Linux 4.10. For such devices,
|
|
an alternative is to use the same passphrase and unlock the source device using
|
|
the `decrypt_keyctl` keyscript.
|
|
|
|
Note: If you don't use suspend device support, it's better to use completely
|
|
random keys for your encrypted swap device. See the section '2. Encrypted
|
|
swap partition(s)' in `/usr/share/doc/cryptsetup/README.Debian.gz` for
|
|
information on how to setup this.
|
|
|
|
10. The `passdev` keyscript
|
|
----------------------------
|
|
|
|
If you have a keyfile on a removable device (e.g. a USB-key), you can use the
|
|
passdev keyscript. It will wait for the device to appear, mount it read-only,
|
|
read the key and then unmount the device.
|
|
|
|
The `key` part of `/etc/crypttab` will be interpreted as `<device>:<path>[:<timeout>]`,
|
|
it is strongly recommended that you use one of the persistent device names from
|
|
`/dev/disk/*`, e.g. `/dev/disk/by-label/myusbkey`.
|
|
|
|
This is an example of a suitable line in cryptsetup:
|
|
|
|
cryptroot /dev/sda2 /dev/disk/by-label/myusbkey:/keys/root.key discard,cipher=aes-xts-plain64,size=256,hash=sha1,keyscript=passdev
|
|
|
|
The above line would cause the boot to pause until `/dev/disk/by-label/myusbkey`
|
|
appears in the fs, then mount that device and use the file `/keys/root.key`
|
|
on the device as the key (without any hashing) as the key for the fs.
|
|
|
|
The timeout option has to be in seconds.
|
|
|
|
If any modules are required in order to mount the filesystem on the removable
|
|
device, then initramfs-tools needs to be configured to add these modules to
|
|
the initramfs. This can be done by listing the required modules in
|
|
`/etc/initramfs-tools/modules`.
|
|
|
|
11. Limitation: renaming of target name for encrypted root device
|
|
-----------------------------------------------------------------
|
|
|
|
As spotted by Adam Lee in bug report [#671037], it's not possible to simply
|
|
rename the target name for encrypted root devices. It breaks the initramfs
|
|
creation process. The bug report submitter found a solution to work around
|
|
this limitation:
|
|
|
|
0. enter another system (like livecd)
|
|
1. open luks device with the new name, change the target name to the new one
|
|
2. chroot into it (now, the current target name is the same as it in conf)
|
|
3. `update-initramfs -u`
|
|
4. reboot
|
|
|
|
[#671037]: https://bugs.debian.org/671037
|
|
|
|
12. Storing keyfiles directly in the initrd
|
|
-------------------------------------------
|
|
|
|
Normally devices using a keyfile are ignored (with a loud warning), and
|
|
the key file itself is not included in the initrd, because the initramfs
|
|
image typically lives on an unencrypted `/boot` partition. However in
|
|
some cases it is desirable to include the key file in the initrd; for
|
|
instance recent versions of GRUB support booting from encrypted block
|
|
devices, allowing an encrypted `/boot` partition.
|
|
|
|
Among the key files listed in the crypttab(5), those matching the value
|
|
of the environment variable KEYFILE_PATTERN (interpreted as a shell
|
|
pattern) will be included in the initramfs image. For instance if
|
|
`/etc/crypttab` lists two key files `/etc/keys/{root,swap}.key`, you can
|
|
add the following to `/etc/cryptsetup-initramfs/conf-hook` to add them to
|
|
the initrd.
|
|
|
|
KEYFILE_PATTERN="/etc/keys/*.key"
|
|
|
|
Furthermore if the initramfs image is to include private key material,
|
|
you'll want to create it with a restrictive umask in order to keep
|
|
non-privileged users at bay. This can be achieved by adding the
|
|
following to `/etc/initramfs-tools/initramfs.conf`.
|
|
|
|
UMASK=0077
|
|
|
|
-- David Härdeman <david@hardeman.nu>
|
|
|
|
-- Jonas Meurer <mejo@debian.org> Thu, 01 Nov 2012 13:44:31 +0100
|
|
|
|
-- Guilhem Moulin <guilhem@debian.org> Wed, 09 Dec 2015 04:53:41 +0100
|