Linux Disk Encryption ============================================================ (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 Creating a New Encrypted Device ------------------------------------------------------------ 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 LUKS Passphrases ------------------------------------------------------------ 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. Back Up the LUKS Header ------------------------------------------------------------ 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 # cryptsetup luksHeaderBackup --header-backup-file /root/luks-header-backup /dev/sdX Restore: # cryptsetup luksHeaderRestore --header-backup-file # cryptsetup luksHeaderRestore --header-backup-file /root/luks-header-backup /dev/sdX Example: USB hard disk as encrypted backup target ------------------------------------------------------------ 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" Using a loop device for testing ------------------------------------------------------------ $ 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 Encrypt a swap file ------------------------------------------------------------ ``` # 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 ``` Links ------------------------------------------------------------ - https://wiki.archlinux.org/index.php/Dm-crypt - https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Encryption.html - https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions - https://wiki.archlinux.org/index.php/disk_encryption - https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup - https://askubuntu.com/questions/703443/gdisk-hex-codes - https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system - https://askubuntu.com/questions/571581/are-there-any-advantages-disadvantages-if-any-in-running-luksformat-on-raw-dr