Page 1 of 1

Installing on LUKS2 with AEAD or dm-integrity

Posted: 2024-10-29 01:22
by Chaser
Hello, folks!

LUKS2 has an awesome feature — AEAD encryption (Authenticated Disk Encryption), which offers the cool secondary benefit of bit rot detection.

I would like to install Debian on LUKS with AEAD to protect the system and data in /var from silent corruption. I have faced bit rot several times throughout my computing experience, and now protection on storage and ECC RAM is a must-have for me.

However, I noticed that the Debian installer lacks LUKS AEAD support. Furthermore, any attempts with reasonable effort to install Debian onto a preconfigured LUKS AEAD setup have not been successful. I also tried to configure at least LUKS with dm-integrity, but this does not work with the Debian installer, even through rescue mode.

From what I recall, the issues seem to be due to missing udebs with the integritysetup binary, along with missing kernel modules for encryption and OpenSSL libraries.

I would like to discuss this before posting bugs, and I'm hoping someone might suggest workarounds. As a temporary workaround until the Debian installer includes LUKS2 AEAD or dm-integrity support, I am considering using Btrfs.

Re: Installing on LUKS2 with AEAD or dm-integrity

Posted: 2024-11-03 09:23
by Aki
Hello,

Thanks, that’s really an interesting topic.

From LUKS2 On-Disk Format Specification version 1.1.3, 2024-02-17 [1] at page 16:
4.8 Algorithm Definition Examples
The LUKS2 specification supports all algorithms that are provided by the cryptographic backend (in the Linux case by kernel dm-crypt and userspace cryptographic library).
[..]
AEAD algorithms are experimental and require dm-integrity support.
So, according to the cryptsetup manual page [1]:
[..]
* Authenticated disk (sector) encryption (EXPERIMENTAL)

Legacy Full disk encryption (FDE), for example, LUKS1, is a length-preserving encryption (plaintext is the same size as a ciphertext). Such FDE can provide data confidentiality, but cannot provide sound data integrity protection.

Full disk authenticated encryption is a way how to provide both confidentiality and data integrity protection. Integrity protection here means not only detection of random data corruption (silent data corruption) but also prevention of an unauthorized intentional change of disk sector content.

NOTE: Integrity protection of this type cannot prevent a replay attack. An attacker can replace the device or its part of the old content, and it cannot be detected. If you need such protection, better use integrity protection on a higher layer.

For data integrity protection on the sector level, we need additional per-sector metadata space. In LUKS2 this space is provided by a new device-mapper dm-integrity target (available since kernel 4.12). Here the integrity target provides only reliable per-sector metadata store, and the whole authenticated encryption is performed inside dm-crypt stacked over the dm-integrity device.

For encryption, Authenticated Encryption with Additional Data (AEAD) is used.

Every sector is processed as a encryption request of this format:

|----- AAD -------|------ DATA -------|-- AUTH TAG --|
| (authenticated) | (auth+encryption) | |
| sector_LE | IV | sector in/out | tag in/out |

AEAD encrypts the whole sector and also authenticates sector number (to detect sector relocation) and also authenticates Initialization Vector.

AEAD encryption produces encrypted data and authentication tag. The authenticated tag is then stored in per-sector metadata space provided by dm-integrity.

Most of the current AEAD algorithms requires IV as a nonce, value that is never reused. Because sector number, as an IV, cannot be used in this environment, we use a new random IV (IV is a random value generated by system RNG on every write). This random IV is then stored in the per-ector metadata as well.

Because the authentication tag (and IV) requires additional space, the device provided for a user has less capacity. Also, the data journalling means that writes are performed twice, decreasing throughput.

This integrity protection works better with SSDs. If you want to ignore dm-integrity data journal (because journalling is performed on some higher layer or you just want to trade-off performance to safe recovery), you can switch journal off with --integrity-no-journal option. (This flag can be stored persistently as well.)

Note that (similar to integritysetup) the device read will fail if authentication tag is not initialized (no previous write). By default cryptsetup run wipe of a device (writing zeroes) to initialize authentication tags. This operation can be very time-consuming. You can skip device wipe using --integrity-no-wipe option.

To format LUKS2 device with integrity protection, use new --integrity option.

For now, there are very few AEAD algorithms that can be used, and some of them are known to be problematic. In this release we support only a few of AEAD algorithms (options are for now hard coded), later this extension will be completely algorithm-agnostic.

For testing of authenticated encryption, these algorithms work for now:

1) aes-xts-plain64 with hmac-sha256 or hmac-sha512 as the authentication tag.
(Common FDE mode + independent authentication tag. Authentication key for HMAC is independently generated. This mode is very slow.)

Code: Select all

$ cryptsetup luksFormat --type luks2 <device> --cipher aes-xts-plain64 --integrity hmac-sha256
2) aes-gcm-random (native AEAD mode)
DO NOT USE in production! The GCM mode uses only 96-bit nonce, and possible collision means fatal security problem. GCM mode has very good hardware support through AES-NI, so it is useful for performance testing.

Code: Select all

$ cryptsetup luksFormat --type luks2 <device> --cipher aes-gcm-random --integrity aead
3) ChaCha20 with Poly1305 authenticator (according to RFC7539)

Code: Select all

$ cryptsetup luksFormat --type luks2 <device> --cipher chacha20-random --integrity poly1305
To specify AES128/AES256 just specify proper key size (without possible authentication key). Other symmetric ciphers, like Serpent or Twofish, should work as well. The mode 1) and 2) should be compatible with IEEE 1619.1 standard recommendation.
So, "Authenticated Encryption with Associated"(AEAD) (a type of encryption that combines both confidentiality - encryption- and authenticity - integrity - in a single process), is usable only for experimental purposes in Linux kernel. It is also confirmed by [3] and [4]. If I understand correctly (see video [4]), this is because the Linux kernel doesn't currently have an AEAD cryptographic algorithm that can compute a unique cryptographic identifier every time a disk block is updated, for the entire lifetime of a disk.

So it is currently recommended the use of luks2 without AEAD.

These are some command examples to create a LUKS2 encrypted partition with dm-integrity from [3][4]:

Code: Select all

$  cryptsetup luksFormat --type luks2 /dev/sdX $PARAMS
where $PARMS can be:
  • Code: Select all

     --cipher aes-xts-plain64 --integrity hmac-sha256
or
  • Code: Select all

     --cipher chacha20-random --integrity poly1305
This is an example with a loopback device with a local disk image (size is 50 MiB):

Code: Select all

# fallocate -l 50Mib image
# losetup /dev/loop0 $PWD/image
# cryptsetup luksFormat --type luks2 /dev/loop0 --cipher chacha20-random --integrity poly1305
# cryptsetup luksOpen /dev/loop0 encrypted_patition 
# mkfs.ext4 /dev/mapper/encrypted_patition
# lsblk /dev/loop0 
NAME                     MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS
loop0                      7:0    0   50M  0 loop  
└─encrypted_patition_dif 253:0    0 31,6M  0 crypt 
  └─encrypted_patition   253:1    0 31,6M  0 crypt 
# mount /dev/mapper/encrypted_patition /mnt
# cd mnt
# touch file
# umount /mnt
# cryptsetup luksClose encrypted_patition
# losetup -d  /dev/loop0
I did some simple and quick (probably incomplete) tests by trying to corrupt the disk image (using Debian Bookworm with kernel 6.1.0-26-amd64). I changed single bytes of the disk image (using hexedit) and waited for error messages appearing from dm-integrity (at the kernel level). The assumption was that the corrupted area needs to be read in order for dm-integrity to detect the change. The result of the tests so far is that in some cases the corruption was not detected, in other cases the luks2 disk simply did not recognize the passphrase and the disk image was simply inaccessible. No message errors detected in the kernel log (dmesg) generated by dm-integrity.

Probably, more tests are required.

So, I would suggest luks2+dm-integrity currently in a experimental environment (not in a production one).

Hope this helps.

--
[1] Cryptsetup 2.0.0 Release Notes
[2] cryptsetup > LUKS2-docs > LUKS2 On-Disk Format Specification version 1.1.3, 2024-02-17
[3] Fosdem 2018 - RedHat - Data integrity protection with cryptsetup tools with cryptsetup tools (presentation)
[4] Fosdem 2018 - RedHat - Data integrity protection with cryptsetup tools with cryptsetup tools (video)