Полное шифрование диска с помощью dm-crypt
В данной статье описывается ряд аспектов, связанных с использованием dm-crypt для (полного) шифрования диска. Здесь приведена дополнительная информация, не описанная на страницах, посвящённых dm-crypt, genkernel и initramfs.
Все дополнительные стратегии безопасности, описанные в данной статье, являются необязательными. Некоторые аспекты, представленные здесь, приведены здесь только лишь потому, что являются предметом постоянно задаваемых вопросов или сугубо личных убеждений в отношении безопасности. Целью этой статьи является по возможности объективное обсуждение данных вопросов. Настоятельно рекомендуется ознакомиться с cryptsetup FAQ для дополнительной информации.
Какую использовать комбинацию шифра и хеша?
На данный момент в LUKS алгоритмом шифрования по умолчанию является aes-xts-plain64
(AES) с XTS в качестве режима шифрования. Эта комбинация может смениться только при очень редких обстоятельствах. Значение по умолчанию является разумным выбором, учитывающим как вопросы безопасности, так и вопросы производительности, позволяя выполнять операции шифрования/дешифрования на скорости 2-3 ГиБ/с для процессора с поддержкой инструкций AES-NI.
Поддержку AES-NI можно проверить с помощью следующей команды:
user $
grep -m1 'aes' /proc/cpuinfo
XTS использует два ключа AES, поэтому возможными длинами ключей являются -s 256
и -s 512
.
Значения шифра и длины ключа по умолчанию могут быть переопределены с помощью параметров командной строки -c
и -s
, например
root #
cryptsetup luksFormat -c aes-xts-plain64 -s 512 ...
root #
cryptsetup luksFormat -c aes-cbc-essiv:sha256 -s 256 ...
Можно запустить профилирование, чтобы получить производительность конкретного набора шифра и режима шифрования:
root #
cryptsetup -c ... -s ... benchmark
Использование команды без -c
и -s
запустит профилирование для различных значений. Например, вывод (слегка укороченный) для процессора Intel Core i7 образца 2014 года будет следующим:
root #
cryptsetup benchmark
# Tests are approximate using memory only (no storage IO). # Algorithm | Key | Encryption | Decryption aes-cbc 256b 469.7 MiB/s 2093.2 MiB/s serpent-cbc 256b 85.3 MiB/s 523.3 MiB/s twofish-cbc 256b 173.4 MiB/s 340.2 MiB/s aes-xts 256b 2386.7 MiB/s 2387.4 MiB/s serpent-xts 256b 548.6 MiB/s 531.1 MiB/s twofish-xts 256b 320.0 MiB/s 342.3 MiB/s
dm-crypt поддерживают большое количество комбинаций шифров, режимов шифрования и векторов инициализации (DMCrypt wiki). Некоторые из них не так безопасны, как другие, а некоторые и вовсе являются небезопасными (например, ECB). См. Википедию о криптографических шифрах и режимах шифрования. При любых сомнениях следует использовать значения по умолчанию.
Дополнительная информация о том, как использовать cryptsetup luksFormat, доступна на вики-странице dm-crypt.
Некоторые шифры могут иметь дополнительное определение хеша в виде
cipher:hash
, например, aes-cbc-essiv:sha256
. Определенный таким образом алгоритм хеширования используется в некоторых режимах шифрования (например cbc-essiv
) при генерации вектора инициализации. Однако в режиме шифрования plain64
не используется определение хеша (для генерации вектора инициализации). В таком случае определение хеша следует опустить.What choice of hash for key derivation?
LUKS uses PBKDF2 for key derivation. In essence, the supplied passphrase by the user is combined with a salt and hashed a specified number of rounds. This key stretching makes the password more secure against brute force attacks. The hash function used in PBKDF2 can be set via -h
. The default is sha256
and can (depending on taste) be changed to another secure hash algorithm. The total number of iterations is determined by the speed of the current hardware and can be influenced by setting the number of milliseconds that shall be spent in PBKDF2 passphrase processing by --iter-time
. To increase the default from 2s to 3s and use sha512 one could for example use:
root #
cryptsetup luksFormat ... -h sha512 --iter-time 3000 ...
It is not recommended to lower the number of PBKDF2 iterations below the default value per the upstream FAQ.
On passphrases, detached LUKS headers, and (encrypted) keyfiles
Use a reasonably long passphrase (use, e.g., 8-12 common random words, see xkcd on that subject) in combination with PBKDF2 for key stretching.
Additional protection against brute force attacks can be achieved by setting up a an external USB flash drive to store essential decryption information (like a keyfile, or the LUKS header itself). The flash drive then has the equivalent function of a physical key; opening the encrypted partition is only possible if both, flash drive and passphrase, are provided. However, this comes with a significant downside in terms of complexity, for example for setting up full disk encryption, or potential to lose decryption keys (by losing the USB flash drive).
Detached LUKS header
It is possible to encrypt a partition with detached LUKS header (where all information about password derivation is stored) that is stored at (physically) different location, e.g., a USB flash drive. This leaves an attacker that is not in possession of the flash drive with no information about key derivation and encryption algorithms used. This makes brute force attacks potentially more difficult.
The following commands first create a file luks-header
with a fixed size of 5MB. Then, a detached LUKS header is written to the file. (See the dm-crypt wiki page for further information on how to use cryptsetup luksFormat, or cryptsetup open commands.)
root #
truncate -s 5M /path/to/luks-header
root #
cryptsetup luksFormat ... --header /path/to/luks-header ...
To check that the header was written successfully, run cryptsetup luksDump /path/to/luks-header.
In order to open the encrypted device, issue:
root #
cryptsetup open ... --header /path/to/luks-header
A detached LUKS header is currently not supported by genkernel.
Создание зашифрованного через GnuPG ключевого файла
The more traditional approach to use a USB flash drive is to store a GnuPG encrypted keyfile (that contains sufficient entropy) on it. Such a key file is readily supported by genkernel.
The following commands create a GnuPG encrypted keyfile of 512 bits and set up an encrypted partition with it:
root #
dd if=/dev/urandom count=64 | gpg --symmetric --cipher-algo aes --armor > /path/to/key.gpg
root #
gpg --decrypt /path/to/key.gpg | cryptsetup luksFormat ...
In order to open the encrypted device,
root #
gpg --decrypt /path/to/key.gpg | cryptsetup open ...
dm-crypt, of course, also works with clear, non-encrypted keyfiles, see the dm-crypt wiki page. The usage of clear keyfiles stored on the root partition to "chain open" encrypted partitions is discussed further down below.
Подготовка дисков
Extra precautions must be taken if the strategy outlined in this section is applied to an SSD.
It is sometimes recommended to overwrite the whole disk with random numbers prior to setting up disk encryption. The rationale behind this recommendation is that reading an encrypted disk should leak as little information as possible. But if unused blocks (by the file system) are still all zero, an adversary can recover some high level information by determining which (encryption) blocks are likely used (because they contain random looking data) and which are unused (because they are, for example, all zero). The number and location of likely used encryption blocks can reveal information such as disk usage, the file system in use, or likely average file size.
Thus, a somewhat effective (but time consuming) counter measure is to overwrite the disk with random data before using it. An efficient way to do generate large amounts of random data quickly is to use a cryptsetup mapping. For example, in order to overwrite /dev/sdXX, use
root #
cryptsetup open --type=plain --key-file=/dev/urandom /dev/sdXX delete_sdXX
root #
dd if=/dev/zero of=/dev/mapper/delete_sdXX bs=1M status=progress
root #
cryptsetup close delete_sdXX
После этого отформатируйте диск с помощью команды cryptsetup luksFormat ...
Overwriting a whole SSD with random data will mark every block as used and can, depending on manufacturer and model, severely degrade wear leveling. This might have potentially disastrous effects on disk lifetime. As mitigation, it is sometimes recommended to leave a substantial portion of the disk, around 10 - 20%, unused to have enough empty blocks for wear leveling. This can be done by creating a suitably sized, unformatted partition, and properly discarding it with
blkdiscard
. Please note that mounting a LUKS container with the --allow-discards
option will transparently forward discards to the SSD and would contradict above setup.Dm-crypt on SSDs and hybrid drives
For additional information about security aspects of using dm-crypt on SSDs and hybrid drives, have a look at the cryptsetup FAQ.
Cryptsetup can transparently forward discard operations to an SSD. This feature is activated by using the --allow-discards
option in combination with cryptsetup open. Enabling discards on an encrypted SSD can be a measure to ensure effective wear leveling and longevity, especially if the full disk is encrypted. For an in detail discussion about the security implications, have a look at the cryptsetup FAQ and the man page of cryptsetup.
Создание initramfs
After encrypting system or disk(s), one will need an initramfs so that rootfs can be mounted in there and then pass the control to real init. There are a few generic initramfs builder that can be used to accomplish the task such as dracut, mkinitcpio (there's a thread in the forums and an ebuild: sys-kernel/mkinitramfs-ll) or even genkernel (or the next variant) which has LUKS support.
Genkernel
В следующем примере используется sys-kernel/genkernel, чтобы создать только initramfs (не всё ядро) и включить в нём поддержку luks:
root #
genkernel --luks --lvm initramfs
For a more complete set of explanations refer to the comments in /etc/genkernel.conf itself or to the output of man genkernel.
The initrd will require parameters to tell it how to decrypt the drive, and they are supplied the same way as other kernel parameters. For example:
title Gentoo Linux 3.4.0-gentoo
root (hd0,0)
kernel /boot/kernel-3.4.0-gentoo crypt_root=UUID=<encrypted partition uuid> root=/dev/mapper/root
initrd /boot/initramfs-3.4.0-gentoo
Note TRIM support may be enabled if the encrypted device is capable (ie. SSD) with root_trim=yes but please read first about the security implications of this outlined in the --allow-discards section of the cryptsetup wiki.
Further information can be found in the genkernel article.
Dracut
The sys-kernel/dracut package was ported from the RedHat project and serves a similar tool for generating an initramfs. Some modules may be desired, please refer to dracut. Generally, the following command will generate a usable default initramfs.
root #
dracut -a crypt
The initrd will require parameters to tell it how to decrypt the drive, and they are supplied the same way as other kernel parameters. For example:
title Gentoo Linux 3.4.0-gentoo
root (hd0,0)
kernel /boot/kernel-3.4.0-gentoo root=UUID=<root filesystem uuid> rd.luks.uuid=<encrypted partition uuid>
initrd /boot/initramfs-3.4.0-gentoo.img
Dracut will match UUIDs that are not complete as long as they are not ambiguous, so it is possible to only enter the first stanza for brevity/clarity desired
Note TRIM support may be enabled if the encrypted device is capable (ie. SSD) with rd.luks.allow-discards but please read first about the security implications of this outlined in the --allow-discards section of the cryptsetup wiki.
For a comprehensive list of luks options within dracut please see the section in the dracut manual.
Mkinitramfs-LL
The unofficial sys-kernel/mkinitramfs-ll (found in tokiclover's bar-overlay) is a lightweight and modular variant of the previous well known initramfs generating tools which comes with udev free dependency. It depends only on busybox with mdev by default and depends on extra packages for additional functionalities. So, nor bash, coreutils nor util-linux is bundled into the initramfs. Extra flexibilities are offered as well, like the possibility to have DM-Crypt LUKS on top of LVM or vice versa, btrfs or ZFS on top of DM-Crypt LUKS, DM-Crypt LUKS on top of RAID, detached header (to a device or a file) for dm-crypt LUKS et al.
root #
mkinitramfs-ll --luks --lvm --firmware=iwlwifi-5000
Use the following GRUB2 configuration excerpt to get going for LVM/LUKS and regular key file on a removable device setup.
'"`UNIQ--pre-00000008-QINU`"'
There is an optional environment variable in the configuration file (mkinitramfs-ll.conf) to set environment variables that have the same effect as the the kernel command line arguments that let boot with a kernel cmdline free kernel. This default cmdline (as environment variables), however, can be disabled at run time if necessary by appending env=No cmdline argument.
Смотрите также
- Genkernel — утилита созданная Gentoo, которая используется для автоматизации процесса сборки ядра и initramfs.
- Dracut — an initramfs infrastructure and aims to have as little as possible hard-coded into the initramfs.
- Initramfs — is used to prepare Linux systems during boot before the init process starts.
- Initramfs (EFI stub kernel) - Configuration of the initramfs.