(August 2017)
These notes cover full disk (block device) encryption. The complexity of disk encryption depends on whether whether we wish to encrypt the root filesystem or a non-root data partition (e.g. a removable backup drive). Disk encryption has two parts: dm-crypt and LUKS.
LUKS does key/passphrase management for dm-crypt volumes (dm-crypt is part of the kernel device mapper). LUKS can accept multiple (up to eight?) keys, giving different users (or backup keys) access to the device.
Plain dm-crypt can be used, but LUKS protects against many common mistakes.
The cryptsetup
utility manages both plain dm-crypt volumes and LUKS volumes.
See CRYPTSETUP(8).
# apt-get install cryptsetup
The cryptsetup
FAQ is information and engagingly written.
https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
Before we repartition the disk, if it formerly contained sensitive data, wipe it. Create a temporary encrypted device or partition:
# cryptsetup open --type plain /dev/sdXY testdev --key-file /dev/random
# fdisk -l
# dd if=/dev/zero of=/dev/mapper/testdev bs=1M status=progress
# cryptsetup close testdev
Or just use shred
:
# shred -v --iterations=1 /dev/sdXY
If we don’t want to overwrite the whole disk, minimally do:
# wipefs -a /dev/sdX
Initialize the partition or device:
# cryptsetup --verbose --verify-passphrase luksFormat /dev/vg0/lvdata
“Open” the LUKS container, test it, and create a new filesystem on it:
# cryptsetup open /dev/vg0/lvdata data
# ls -l /dev/mapper | grep data
# mkfs.ext4 /dev/mapper/data
Mount the new filesystem:
# mount /dev/mapper/data /data
Unmount the filesystem like:
# umount /data
# cryptsetup close data
If desired, set the filesystem to mount on boot.
The entry in /etc/crypttab
causes LUKS to prompt for a passphrase when mounting the filesystem.
See CRYPTTAB(5).
In /etc/crypttab
:
data /dev/vg0/lvdata none
In /etc/fstab
:
/dev/mapper/data /data ext4 defaults 0 2
Add a passphrase to an existing device:
# cryptsetup luksAddKey /dev/vg0/lvdata
Remove a passphrase from a device:
# cryptsetup luksRemoveKey /dev/vg0/lvdata
Just for the sake of curiosity, show which LUKS key slots are in use:
# cryptsetup luksDump /dev/sdX
Note: LUKS provides no plausible deniability about the presence of encrypted data, because the LUKS header is easily identifiable.
If the LUKS header gets damaged, data will be unrecoverable. Back up the LUKS header!
See https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions#6-backup-and-data-recovery.
Back up:
# cryptsetup luksHeaderBackup --header-backup-file <file> <device>
# cryptsetup luksHeaderBackup --header-backup-file /root/luks-header-backup /dev/sdX
Restore:
# cryptsetup luksHeaderRestore --header-backup-file <file> <device>
# cryptsetup luksHeaderRestore --header-backup-file /root/luks-header-backup /dev/sdX
A LUKS container can be created either in a partition or on a raw block device. See “2.2 LUKS on partitions or raw disks?” in the cryptsetup FAQ.
For the scenario of a removable backup disk, it makes sense to create a LUKS device on the raw block device. Having done so, do NOT partition the container (e.g. with gdisk); instead, directly format the LUKS container with a filesystem.
Prepare a new USB disk.
# apt-get install cryptsetup
# dmesg | tail | grep 'sd[[:alpha:]][[:digit:]]'
[265197.180467] sdc: sdc1
# shred -v --iterations=1 /dev/sdX
shred: /dev/sdX: pass 1/1 (random)...
# cryptsetup --verbose --verify-passphrase luksFormat /dev/sdX
# cryptsetup open /dev/sdX backup
# mkfs.ext4 /dev/mapper/backup
# mkdir -p /backup/usb
# mount /dev/mapper/backup /backup/usb/
# df -h
# umount /backup/usb
# cryptsetup close backup
# cryptsetup status backup
Normal backup operation:
# cryptsetup open /dev/sdX backup
# mount /dev/mapper/backup /backup/usb/
(Copy files to /backup/usb
.)
# umount /backup/usb
# cryptsetup close backup
# cryptsetup status backup
In some backup scenarios, backups must happen non-interactively. If we’re not worried about storing the secret locally, use a keyfile.
# dd if=/dev/urandom of=/root/luks-keyfile-for-usb-backups bs=1024 count=4
# chmod 0400 /root/luks-keyfile-for-usb-backups
# cryptsetup luksAddKey /dev/sdX /root/luks-keyfile-for-usb-backups
# cryptsetup open /dev/sdX backup --key-file /root/luks-keyfile-for-usb-backups
If we’re adding brand-new media to our rotation, and want all disks to share the same LUKS header, prep the new disk like:
# wipefs -a /dev/sdX
# cryptsetup luksHeaderRestore --header-backup-file /root/luks-header-backup /dev/sdX
# cryptsetup open /dev/sdX backup
# mkfs.ext4 /dev/mapper/backup
Here’s an example shell script for running backups:
#!/bin/sh
set -euf
# Supply the device name of an external USB drive as the sole argument:
# $ sudo ~/bin/backup-offsite /dev/sdc
d="$1"
mnt=/media/usb
h=/home/paulgorman
cryptsetup open "$d" backup --key-file /root/luks-keyfile-for-usb-backups
mkdir -p "$mnt"
mount /dev/mapper/backup "$mnt"
mkdir -p "$mnt"/Trash
rsync -aqh --delete --backup --backup-dir="$mnt"/Trash \
--exclude "$h"/.cache \
--exclude "$h"/Downloads \
--exclude "$h"/tmp \
"$h" \
/data \
/etc \
/root \
/var/spool/anacron \
/var/spool/cron \
"$mnt"
umount "$mnt"
cryptsetup close backup
cryptsetup luksHeaderBackup --header-backup-file /root/luks-header-backup "$d"
$ head -c 100M /dev/zero > luksfile
# losetup /dev/loop0 luksfile
# cryptsetup luksFormat /dev/loop0
Open/close/mount/unmount the loop device just like a real device.
To discard the loop device:
# losetup -d /dev/loop0
# apt install cryptsetup
# fallocate -l 4G /cryptswap
# vi /etc/crypttab
+ cryptswap /cryptswap /dev/urandom swap
# cryptdisks_start cryptswap
# swapoff -va
# vi /etc/fstab
- UUID=a9c3c70b-64de-40bc-a42d-335afc0bc1b6 none swap sw 0 0
+ /dev/mapper/cryptswap none swap sw 0 0
# swapon -va