Resistance of dm-crypt to corruption

11.12.2010 23:15

Recently I've been thinking about using dm-crypt to encrypt partitions on my computers. As mulaz writes, portable devices like flash drives and laptops are getting physically smaller and logically larger. The former makes them easier to lose or get stolen while the latter increases the possibility that they contain something valuable. I've been using LUKS to format my USB flash drives for a while now. I've been pleasantly surprised that the GNOME desktop will recognize, prompt for password and mount them automatically.

Two years ago Phoronix found out that disk encryption on contemporary hardware has negligible effect on performance. On the other hand EeePC 901 didn't fare that well (also, I wonder what the impact on battery life is?). In 2010 the overhead of encryption should be even smaller.

One thing I've been wondering about is how an encrypted volume behaves when data on the storage device gets corrupted (bad block, odd cosmic particle, etc.) Is it all-or-nothing like file compression, where you loose the entire file if only a part of it gets corrupted? Encryption is done in blocks so in theory only the blocks touched by corruption on the device level should be affected after decryption.

To test that theory I made two 2 GB files with ext3 filesystem on them and mounted them via the loopback device. One was encrypted with dm-crypt (default settings) and the other was left unencrypted. Then I copied some random data to them and ran the following script. It incrementally zeros 64 kB blocks at random locations on the block device and compares file contents with the original. It stops at the first sign of trouble.

#!/bin/bash

set -e

SIZE=2147483648
BLOCK=$(($SIZE/32768))
FILE="encrypted_damaged"
#FILE="plaintext_damaged"

N=0
while true; do
	OFFSET="$RANDOM"

	echo "Writing $BLOCK bytes at $OFFSET to $FILE" >> log
	tail -n1 log

	dd if=/dev/zero of="$FILE" bs="$BLOCK" count=1 seek="$OFFSET" conv=notrunc

	losetup /dev/loop0 "$FILE"
	cryptsetup --key-file=password create test /dev/loop0 
	mount /dev/mapper/test /mnt
	#mount /dev/loop0 /mnt

	diff --brief /mnt/linux-2.6.34.7.tar.bz2 linux-2.6.34.7.tar.bz2
	diff --brief -r /mnt/linux-2.6.34.7 linux-2.6.34.7

	#umount /dev/loop0
	umount /dev/mapper/test
	cryptsetup remove test
	losetup -d /dev/loop0

	N=$(($N+1))
done

As expected, both plain and encrypted volumes behaved in the same way. In most cases corruption only caused file contents to silently change. When it touched filesystem structures a fsck was necessary, but the success rate on plain and encrypted volumes was pretty much similar. From what I've seen encrypted volumes don't seem to be any more vulnerable to corruption than otherwise.

Of course, this is only anecdotal evidence: I only did a couple of runs to convince myself that my understanding of how dm-crypt should behave is correct. Also note that plain dm-crypt volumes used here are different from LUKS formatted volumes - those have a header that holds some vital parameters for the encryption algorithm and from what I heard once that header is lost you can say goodbye to your data.

Posted by Tomaž | Categories: Code

Comments

AES is a block cipher, so every bit error 'destroys' the whole block, which consists of 128bits on aes128 and 256bits with aes256.

This is kinda bad with text files (1 bit(=1byte) error->32byte error with aes256), but with binary files, it's usually the same... 1 bit, 32 bytes, or 1meg... the file is useless anyway.

True. Although I expect block devices like hard drives and flash to have block level CRC. So a single bad bit will probably cause an unreadable block anyway. And those are usually much larger than AES blocks (512 B, 4 kB for hard drives, 128 kB for flash...)

Posted by Tomaž

Add a new comment


(No HTML tags allowed. Separate paragraphs with a blank line.)