skip to main content.

posts about luks.

recently, there was a pratical attack against linux encrypted hard disks (with linux unified key setup (luks)) which use some form of cipher block chaining (cbc) mode. since this mode was the default some time ago, and i did use it in the past, and also had some other not-so-great setups especially on older backup disks (like using sha1 instead of sha2), i thought about re-encrypting some of my backup disks.
the usual re-encrypt step with luks goes as follows: get another harddisk with enough space, copy the data over there, re-create the luks encrypted disk, and copy the data back. takes a lot of time and space. in theory, it should be no problem of re-encrypting a disk on the fly (in theory, even while using it), but i didn’t like the idea of investing quite some time to implement that. fortunately, after searching around the web a bit, i found out that someone already did it. (offline only, though, but that’s completely fine for backup disks.) in fact, it is part of the official cryptsetup distribution form version 1.5.0 on. unfortunately, the cryptsetup coming with my installed linux mints is 1.4.3, but then, since re-encryption does not require kernel support, i could just compile the new cryptsetup and use the compiled version’s cryptsetup-reencrypt command line tool. well, and so i did.
since the process can be a bit more complicated, i wanted to document it, and since i didn’t find too much on cryptsetup-reencrypt on the net, i thought writing a blog post about it is a good idea :-)

simple resizing.

warning: if you experience power loss or your machine crashes during re-encryption, the whole encrypted harddisk might be unusable! so only do this for data you already have backuped. in case you want to re-encrypt your only backup disk, take this as an opportunity to buy a second backup disk, encrypt it with the correct settings, copy the data there as well, and only then re-encrypt your old backup harddisk.

well, you have been warned. so now let’s get it done.

so let us assume we want to re-encrypt partition /dev/sdx1. namely, we want to use aes in xex-based tweaked-codebook mode with ciphertext stealing (xts) with a key size of 512 bits (that is, we use aes-256) with hash function sha-2 with 256 bits. moreover, the hash function should be iterated often enough to obtain a time of around 2 seconds. for this, we can simply run
cryptsetup-reencrypt -c aes-xts-plain64 -s 512 -h sha256 -i=2000 /dev/sdx1
to improve performance, we can set a higher buffer size (like 32 megabytes with -B 32) or use direct i/o (with –use-directio). the command line will then be:
cryptsetup-reencrypt -c aes-xts-plain64 -s 512 -h sha256 -i=2000 -B 32 --use-directio /dev/sdx1
for some setups, this will start running, take ages, and eventually finish with a happily re-encrypted harddisk. (note that you need to enter all keys, not just one – if you don’t know one, remove it before calling!) to check out the result, run:
cryptsetup luksDump /dev/sdx1
everything is fine when you see the following in the output:

1 ...
2 Cipher name:      aes
3 Cipher mode:      xts-plain64
4 Hash spec:        sha256
5 ...
6 MK bits:          512
7 ...

finally, note that cryptsetup-reencrypt does support suspension and continuing – but only if it knows where exactly it stopped. so this won’t work with crashes or power losses, but if you press control+c, it should be no problem to continue later. (i haven’t tested it, though, i’m just repeating from its manual. note that you shouldn’t get rid of the temporary files if you want to be able to continue. if you delete them, you’ve screwed up and your data is very probably gone.)

resizing necessary.

warning: if you screw this up, you can destroy your filesystem.

the whole task gets slightly more complicated when cryptsetup-reencrypt tells you something along the lines of
Data offset for detached LUKS header must be either 0 or higher than header size (4036 sectors).
that simply means that there isn’t enough space for the (larger) luks header; so you need to make some space.
assuming you encrypted an ext2/3/4 filesystem, you can work around this as follows, assuming that you still have enough free space left on that device: first unlock the luks partition, then resize the ext2/3/4 filesystem, and finally re-encrypt with moving the data backwards (cryptsetup-reencrypt has an option specifically for this). first, run e2fsck on the filesystem (we assume it is unlocked to /dev/mapper/yourfilesystem)
e2fsck -D -p -v -t /dev/mapper/yourfilesystem
(add -f to force a complete check, and remove -p if you don’t want automatic repair in case of errors.)
if that ran through, observe the output:
disklabel: clean, 12345/123456789 files, 98765/987654321 blocks
since blocks have size 4 kilobytes (verify this by running dumpe2fs -h /dev/mapper/yourfilesystem and look for “block size”!), we can shrink the disk size by 512 blocks to obtain 2 megabytes of free space at the end of the encrypted partition – that should be enough space for the larger luks headers. to compute the new size, we take the maximal block number (987654321) and subtract 512 from it: in this case, we obtain 987653809. so now we can resize the ext2/3/4 partition to these many blocks:
resize2fs -p /dev/mapper/yourfilesystem 987653809
this also takes some time (though much less than cryptsetup-reencrypt). when it is done, we can run e2fsck another time if we want, and then lock the container:
cryptsetup luksClose yourfilesystem
then we can start re-encryption with data movement. for this, we add –reduce-device-size 2M, which moves the partition data by 2 megabytes to the back (note that cryptsetup-reencrypt uses base 1024, so 2 megabytes equals 2097152 bytes and not 2000000 bytes as in si units) – throwing away the last 2 megabytes of the encrypted filesystem. (since we resized our file system, we don’t use these anymore, so everything should be fine.) so we run:
cryptsetup-reencrypt -c aes-xts-plain64 -s 512 -h sha256 -i=2000 --reduce-device-size 2M -B 32 --use-directio /dev/sdx1
this runs for ages, and after it’s done, you can check the parameters with cryptsetup luksDump /dev/sdx1. afterwards, it isn’t a too bad idea to unlock the filesystem and run e2fsck again.

more complex settings.

everything get’s more complicated if you didn’t just encrypt a single filesystem, but say for example a whole set of partitions (using lvm, linux’ logical volume manager). in that case, you have to shrink its “physical volume”. fortunately, lvm has some support for shrinking and extending logical and physical volumes (see pvresize, lvresize and friends). if/when i’m actually trying this out, i might add some more details here (or in a new post) on how to do it.

posted in: computer
tags:
places:

since i’m always forgetting what to do to encrypt a harddisk, and have to rely on other sites (which might go offline once), i decided to sum everything up in a post. parts can already be found here in this blog.
note that the disk device name can differ from computer to computer, so i used /dev/sdx in this description which you have to change to the right name.

creation.

first, connect the disk and unmount it. then, delete all existing partitions and create a linux primary partition (or do whatever else you want):

$ sudo fdisk /dev/sdx

then it is recommended to clear the partition with random data:

$ sudo dd if=/dev/urandom of=/dev/sdx1

note that this step takes a lot of time.
then, make luks aware of the drive, open it with luks and format it:

$ sudo cryptsetup –verbose –cipher aes-xts-plain64 –key-size 512 –verify-passphrase luksFormat /dev/sdx1
$ sudo cryptsetup luksOpen /dev/sdx1 encrdisk
$ sudo mke2fs -v /dev/mapper/encrdisk
$ sudo cryptsetup luksClose encrdisk

this creates an ext2 file system. now you should be able to unplug the drive and reconnect it, and ubuntu should ask you for a passphrase to unlock the disk. feel free to add -L “label” (at most 16 characters; see the man page for more details); ubuntu will try to mount the disk as /media/label then.

(edit: since there is now a successful attack on the aes-cbc-essiv encryption mentioned here earlier, i changed it to aes-xts-plain64, using a different approach.)

mounting and unmounting.

to mount:

$ sudo cryptsetup luksOpen /dev/sdx1 encrdisk
$ sudo mount /dev/mapper/encrdisk /mnt

to unmount:

$ sudo unmount /mnt
$ sudo cryptsetup luksClose encrdisk

note that for example newer ubuntu versions automatically ask for a passphrase and performs luksOpen / mount / unmount / luksClose for you.

checking.

basically, you just have to open the partition, run the usual file system check, and close it:

$ sudo cryptsetup luksOpen /dev/sdx1 encrdisk
$ sudo fsck -v -C -n /dev/mapper/encrdisk
$ sudo cryptsetup luksClose encrdisk

passphrase management.

note that luks has a storage of several passphrases, which can all be used to open the partition. one can add and remove phrases to/from this list.
to add a passphrase:

$ cryptsetup luksAddKey /dev/sdx1

to remove a passphrase (you have to enter the passphrase to be removed):

$ cryptsetup luksRemoveKey /dev/sdx1

to remove the passphrase from a slot (useful if you forgot one of the passphrases and want to remove it):

$ cryptsetup luksKillSlot /dev/sdx1 0