Improve cryptsetup luksOpen performance on slow hardware - jandelgado/general GitHub Wiki

Problem

Opening (i.e. the cryptsetup luksOpen operation) an encrypted USB harddisk on an embedded device with just about 500Mhz CPU (in my case a GL.iNet-MT300N-V2 mini router running a custom OpenWRT) took minutes. After the device was opened, performance was on par with expectations.

Cause

The disk was initially encrypted (cryptsetup luksFormat) on a performant Xeon server. During storage of the key, a so called Iteration value is determined based on the hosts performance and stored alongside with the encrypted key on the disk. The faster the host used during initialization, the higher the calculated iteration count. This results in bad performance during cryptsetup luksOpen on a host with significant less CPU power.

Solution

Add another key/passphrase in a different slot and set the iterations value manually:

$ sudo cryptsetup luksAddKey -S 7 --pbkdf-force-iterations 1000 --force-password /dev/sdb1 

When opening the disk, provide the key slot to use, e.g. cryptsetup luksOpen -S 7 /dev/sdb1 crypto

Performance comparison

For demonstration we use a disk encrypted with two keys. On with a high iteration count (3536512) in slot 0 and another one with an iteration count set to 1000 in slot 7. Example output of cryptsetup luksDump with irrelevant data removed:

root@lede-mobile: ~# cryptsetup luksDump /dev/sda1
LUKS header information for /dev/sda1

Version:       	1
Cipher name:   	aes
Cipher mode:   	xts-plain64
Hash spec:     	sha256
Payload offset:	4096
MK bits:       	256
MK digest:     	...
MK salt:       	...
               	...
MK iterations: 	...
UUID:          	...

Key Slot 0: ENABLED
	Iterations:         	3536512
  	Salt:               	...
	Key material offset:	8
	AF stripes:           4000
Key Slot 1: DISABLED
...
Key Slot 7: ENABLED
	Iterations:         	1000
	Salt:               	...
	Key material offset:	1800
	AF stripes:           4000

In the example the key in Slot 7 was set with --pbkdf-force-iterations parameter set to 1000, bypassing performance based calculation of the value.

Let's compare performance of opening the disk with keyslot 0 and 7:

root@lede-mobile: ~# time cryptsetup luksOpen -S0 /dev/sda1 crypto
Enter passphrase for /dev/sda1: 
real	6m 36.46s
user	6m 27.50s
sys	0m 0.09s
root@lede-mobile: ~# cryptsetup close crypto
root@lede-mobile: ~# time cryptsetup luksOpen -S7 /dev/sda1 crypto
Enter passphrase for /dev/sda1: 
real	0m 24.83s
user	0m 21.04s
sys	0m 0.04s

Duration of cryptsetup luksOpen changes from 6m36s for opening using key slot 0 to 24s with key slot 7 - a clear improvement.

Note that of course you need the right balance between speed and iteration count to ensure security (left to the reader as excercise ;)

See also