dm-crypt
dm-crypt
(or Device Mapper crypt) is the Linux kernel's infrastructure for creating encrypted block devices. It works between the physical (or virtual disk) partition and the filesystem, transparently encrypting data as it's persisted to storage and decrypting it on recollection.
There are two configuration models:
- LUKS (strongly recommended) allows keys to be placed in up to 16 slots and provides convenient CLI tools for their management. This is what we deploy.
- Plain mode simply encrypts and decrypts data using the specified passphrase, without support for management of multiple keys.
The cryptsetup
command is used to manage encrypted volumes. Note that for all of the below commands that utilise key slots, the key slot will default to the first key (numbered from zero) where not specified.
Loss of the header means loss of the data
You must take care to not damage or, in the case of detached LUKS headers where the header is stored in a separate file outside of the partition, lose the header. Losing the header renders the contents of an encrypted volume unrecoverable.
Opening an encrypted container
To access the data within an encrypted container we need to open it:
$ sudo cryptsetup luksOpen test-disk.img my-test
Enter passphrase for test-disk.img:
This will expose the device in /dev
, which we can then mount as usual:
$ sudo mkdir /mnt/test
$ sudo mount /dev/mapper/my-test /mnt/test
$ sudo ls /mnt/test
lost+found
Closing an encrypted container
First ensure that any mounted volumes on it are unmounted. You can identify these with lsblk
to list the devices and mount
to list the active volumes:
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 89.1M 1 loop /snap/core/8039
loop1 7:1 0 89.1M 1 loop /snap/core/8268
loop2 7:2 0 56.4M 1 loop /snap/powershell/39
loop3 7:3 0 56.4M 1 loop /snap/powershell/77
loop4 7:4 0 100M 0 loop
└─my-test 253:3 0 84M 0 crypt /mnt/test
nvme0n1 259:0 0 931.5G 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot/efi
├─nvme0n1p2 259:2 0 732M 0 part /boot
└─nvme0n1p3 259:3 0 930.3G 0 part
└─nvme0n1p3_crypt 253:0 0 930.3G 0 crypt
├─ubuntu--vg-root 253:1 0 929.3G 0 lvm /
└─ubuntu--vg-swap_1 253:2 0 976M 0 lvm [SWAP]
$ mount | grep my-test
/dev/mapper/my-test on /mnt/test type ext4 (rw,relatime)
$ umount /dev/mapper/my-test
$ rm -rf /mnt/test
Then close it:
sudo cryptsetup luksClose my-test
Listing enabled encrypted volumes
You can find a complete list of device mapper targets known to the system using dmsetup
:
$ sudo dmsetup ls --target crypt
my-encrypted-data-disk (253, 2)
my-encrypted-os-disk (253, 1)
Note that the device names shown here will be the names of the decrypted devices -- the ones within the encrypted container. Most cryptsetup
commands operate on the container itself, so we'll need to know the names of the backing devices. The easiest way to visualise this is lsblk
-- just look at the line above the volume you're interested in:
$ sudo lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 30G 0 disk
├─sda1 8:1 0 29.7G 0 part
│ └─my-encrypted-os-disk 253:1 0 29.7G 0 crypt /
├─sda2 8:2 0 256M 0 part /boot
├─sda14 8:14 0 4M 0 part
└─sda15 8:15 0 106M 0 part /boot/efi
sdb 8:16 0 40G 0 disk
└─sdb1 8:17 0 40G 0 part /mnt
sdc 8:32 0 48M 0 disk
└─sdc1 8:49 0 30G 0 part
└─my-lvm-lv 253:0 0 60G 0 lvm
└─my-encrypted-data-disk 253:2 0 60G 0 crypt /mnt/data
sde 8:64 0 30G 0 disk
└─sde1 8:65 0 30G 0 part
└─my-lvm-lv 253:0 0 60G 0 lvm
└─my-encrypted-data-disk 253:2 0 60G 0 crypt /mnt/data
From the above we can deduce that our dm-crypt
backing devices are as follows:
/dev/sda1
formy-encrypted-os-disk
/dev/my-lvm-lv
formy-encrypted-os-disk
You can drill down into the properties of an individual volume with cryptsetup
:
Decrypting filesystems at boot
Filesystems to be decrypted during boot will be listed in /etc/crypttab
:
# <target name> <source device> <key file> <options>
my-encrypted-data-disk /dev/mapper/storage-data /mnt/azure_bek_disk/LinuxPassPhraseFileName_1_1 luks,nofail
The target names define the name of the mapped volume in /dev
, which can then be added to /etc/fstab
or similar for automatic mounting.
Using an encrypted root filesystem
Decrypting the root (/root
) filesystem requires some steps in addition to ordinary volumes. Because the root filesystem is not yet available, all tools required in the decryption chain must be available in the initrd, achieved in Ubuntu by installing cryptsetup-initramfs
.
Formatting a new container
Don't run these commands on a system you don't have complete backups for -- there's a pretty good chance you'll lose data.
sudo cryptsetup luksFormat test-disk.img
WARNING!
========
This will overwrite data on test-disk.img irrevocably.
Are you sure? (Type uppercase yes): YES
Enter passphrase for test-disk.img:
Verify passphrase:
Backing up the LUKS header
When making changes (e.g. changing keys) it's advisable to take a backup of the volume's LUKS header data. If this becomes corrupted and no backup is available any data on the disk will not be recoverable.
sudo cryptsetup luksHeaderBackup --header-backup-file test-disk-header test-disk.img
Restoring the LUKS header
Use the same arguments as with luksHeaderBackup
:
$ sudo cryptsetup luksHeaderRestore --header-backup-file test-disk-header test-disk.img
WARNING!
========
Device test-disk.img already contains LUKS2 header. Replacing header will destroy existing keyslots.
Are you sure? (Type uppercase yes): YES
Dumping configuration
To print the information contained in the header of the disk along with the status of the key slots for a given volume:
$ sudo cryptsetup luksDump test-disk.img
LUKS header information
Version: 2
Epoch: 3
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: 00000000-0000-0000-0000-000000000000
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)
Data segments:
0: crypt
offset: 16777216 [bytes]
length: (whole device)
cipher: aes-xts-plain64
sector: 512 [bytes]
Keyslots:
0: luks2
Key: 512 bits
Priority: normal
Cipher: aes-xts-plain64
Cipher key: 512 bits
PBKDF: argon2i
Time cost: 4
Memory: 1048576
Threads: 4
Salt: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
AF stripes: 4000
AF hash: sha256
Area offset:32768 [bytes]
Area length:258048 [bytes]
Digest ID: 0
Tokens:
Digests:
0: pbkdf2
Hash: sha256
Iterations: 147603
Salt: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Digest: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Adding a new key
In corporate environments it's often necessary for the organisation to be able to decrypt the contents of the disk as well as the user of the machine. LUKS allows us to do this by providing up to 16 key slots for us to fill. To add a new key:
$ sudo cryptsetup luksAddKey --key-slot 1 test-disk.img
Enter any existing passphrase:
Enter new passphrase for key slot:
Verify passphrase:
Changing an existing key
To change a key in one of the slots you need to know any one of the existing keys:
$ sudo cryptsetup luksChangeKey test-disk.img
Enter passphrase to be changed:
Enter new passphrase:
Verify passphrase:
Deleting a key
To delete a key, specify the volume path and the key slot number. Note that you don't use the --key-slot
option as the key slot number is required.
$ sudo cryptsetup luksRemoveKey test-disk.img
Enter passphrase to be deleted:
Backlinks