Why does LUKS need to generate hash values

dm-cryptluks

If you create a new LUKS device, you can specify the option -hash and -iter-time.

For example like this:

 sudo cryptsetup luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --iter-time 2100 --hash sha512 /dev/loop0

From the manpage of cryptsetup:

–hash, -h

For create action specifies hash to use for password hashing.

For luksFormat action specifies hash used in LUKS key setup scheme and
volume key digest.

Because of the first sentence I naively assumed that the hash is used in a similar way as in a standard linux system, where a hash value is created by a specified algorithm (for example sha512). To make it harder for an attacker which has the hash and wants to try a dictionary attack, the has is salted and the algorithm is iterated n-times to make computation time longer. In this case the has value is stored in /etc/shadow. If a user logs in, the hash is computed and compared to the value in the /etc/shadows file. If they are equal, the user is accepted to login. In a similar way an attacker which owns the file /etc/shadow (from where he also knows the salt value) can compute hashes from words in a dictionary and compare it to the value in the /etc/shadow file until some string matches.

If the hash in LUKS were used in a similar way, I assumed it must be stored somewhere (for example in the partition header) and if the attacker had access to the partition header (or the file where it is stored) for some reasons, he could proceed in a similar way as above to find out the password. This lead me to the question about how to get the hash: How can I extract the hash value of a LUKS device?

Thinking about how the LUKS system may work, I guess that it is not used in this way. Instead I think, that the password is just used to encrypt the key (and no hash is stored anywhere), which is stored encrypted in the header. But in the LUKS man-page I didn't find any hint, which encryption algorithm is used for key encryption and how to change it. (The options --cipher aes-cbc-essiv:sha256 --key-size 256 refer to the actual algorithm which is used to encrypt the partition but not the key). This indicates for me that this understanding my be also incorrect.

So, how does this all really works and what is the role of the hash described above? Would be great if someone could clarify my misconceptions above (perhaps with some references).

Best Answer

The LUKS format has multiple key slots, each one may contain the encrypted master key that is used for data encryption. This master key is encrypted using another key which is derived from your passphrase.

Using plain hash_function(passphrase) to generate a key would be dumb as hashes such as sha1 can be calculated fast (SHA-1 is an example of a MAC algorithm, for authentication of a message, not to be used as plain for a password).

For data encryption based on a passphrase, you want the function to be slow to thwart brute-force attacks. For this purpose, PBKDF2 (password-based key derivation function) is used (see the excellent answers on this Sec.SE question for motivations and other examples).

derivedKey = PBKDF2(hash_function, passphrase, salt, iterations, derivedKeyLen)

The hash_function for my installation is sha1 as is shown in cryptsetup --help:

Default compiled-in key and passphrase parameters:
        Maximum keyfile size: 8192kB, Maximum interactive passphrase length 512 (characters)
Default PBKDF2 iteration time for LUKS: 1000 (ms)

Default compiled-in device cipher parameters:
        loop-AES: aes, Key 256 bits
        plain: aes-cbc-essiv:sha256, Key: 256 bits, Password hashing: ripemd160
        LUKS1: aes-xts-plain64, Key: 256 bits, LUKS header hashing: sha1, RNG: /dev/urandom

The derived key length depends on the cipher used for data encryption. The number of iterations depends on your processor speed.

These details can be found in the manual page of cryptsetup (pbkdf2 should ring a bell). For other security details, see the FAQ of cryptsetup.

Related Question