How do I determine what ciphers & cipher modes I can use in dm-crypt/LUKS?
There are many, many documents and man pages to read through, but one document that might particularly interest you is the LUKS On-Disk Format Specification (PDF).
Appendix B (which is, naturally, near the end) says,
Cipher and Hash specification registry
Even if the cipher-name and cipher-mode strings are not interpreted by any LUKS operation, they must have the same meaning for all implementations to achieve compatibility among different LUKS-based implementations. LUKS has to ensure that the underlaying cipher system can utilise the cipher name and cipher mode strings, and as these strings might not always be native to the cipher system, LUKS might need to map them into something appropriate.
Valid cipher names are listed in Table 1.
Valid cipher modes are listed in Table 2. By contract, cipher modes using IVs and tweaks must start from the all-zero IV / tweak. This applies for all calls to the encrypt / decrypt primitives especially when handling key material. Further, these IVs / tweaks cipher modes usually cut the cipher stream into independent blocks by reseeding tweaks / IVs at sector boundaries. The all-zero IV / tweak requirement for the first encrypted / decrypted block is equivalent to the requirement that the first block is defined to rest at sector 0.
Table 3 lists valid hash specs for hash-spec field. A compliant implementation does not have to support all cipher, cipher mode or hash specifications.
Table 1: Valid cipher names
- aes - Advanced Encryption Standard - FIPS PUB 197
- twofish - Twofish: A 128-Bit Block Cipher - http://www.schneier.com/paper-twofish-paper.html (See below)
- serpent - http://www.cl.cam.ac.uk/~rja14/serpent.html
- cast5 - RFC 2144
- cast6 - RFC 2612
Table 2: Valid cipher modes
- ecb - The cipher output is used directly
- cbc-plain - The cipher is operated in CBC mode. The CBC chaining is cut every sector, and reinitialised with the sector number as initial vector (converted to 32-bit and to little-endian). This mode is specified in [Fru05b], Chapter 4.
- cbc-essiv:hash - The cipher is operated in ESSIV mode using hash for generating the IV key for the original key. For instance, when using sha256 as hash, the cipher mode spec is “cbcessiv:sha256”. ESSIV is specified in [Fru05b], Chapter 4.
- xts-plain64 - http://grouper.ieee.org/groups/1619/email/pdf00086.pdf, plain64 is 64-bit version of plain initial vector
Table 3: Valid hash specifications
- sha1 - RFC 3174 - US Secure Hash Algorithm 1 (SHA1)
- sha256 - SHA variant according to FIPS 180-2
- sha512 - SHA variant according to FIPS 180-2
- ripemd160 - http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html (See below)
Editor’s Note: The above is copied from the specification. Subsequent to its writing, these documents’ URLs have changed:
- Twofish: A 128-Bit Block Cipher (new URL)
- The hash function RIPEMD-160 (new URL)
The 5.1 kernel, current at the time I write this, has two different formats the for cipher string, the "old" format and the "new" format. Everything in this question so far, and apparently all docs too, deals with the "old" format, so I'll describe it here. This is for just encryption. If using integrity with dm-crypt, then one must consider AEAD ciphers and it gets even more complicated.
The format parsed by the kernel is "cipher[:
keycount]-
mode-
ivmode[:
ivopts]". Examples: aes-xts-plain64
, blowfish-cbc-essiv:sha256
, aes:64-cbc-lmk
.
cipher The cipher to use, examples are
aes
,anubis
,twofish
,arc4
, etc. The kernel dm-crypt driver does not have a list of ciphers. This is passed through to the Linux Crypto API, so any suitable cipher supported by the kernel can be used.keycount Optional power of two number of keys to use with cipher. This defaults to 1 for everything except the
lmk
ivmode, where it defaults to 64. This really only applies to LMK and values other than 1 will will not work properly with other modes.mode The block chaining mode to use with the cipher. Examples are
ecb
,cbc
,xts
. Other than knowing thatecb
uses no IV, the md-crypt driver passes this through to the Linux Crypto API and can use any chaining mode supported by the kernel.-
ivmode The algorithm used to generate the initialization vector (IV) for each sector. In typical symmetric key encryption, unlike dm-crypt, the IV is another bit of data passed into the cipher along with the key when encrypting or decrypting. There is just one IV passed in for the entire operation. Since dm-crypt needs to be able to read and write each sector individually, it does not encrypt the entire disk as a single operation. Instead, there is an IV for each sector. Rather than passing in the IV as data, an algorithm for creating the IVs is specified here. This isn't part of the Linux Crypto API, since IV generation isn't done by the cipher, and the allowed ivmode values are defined the dm-crypt driver. They are:
-
plain
,plain64
,plain64be
,benbi
These simply use the sector number, in various formats, as the IV. Meant for block modes like XTS that are designed to resist attacks like watermarking when using a simple and predictable IV.plain64
appears to be the most commonly recommended. -
null
IV is always zero. For testing and backward compatibility, you shouldn't use this. -
lmk
Compatible with the Loop-AES encryption scheme. -
tcw
Compatible with TrueCrypt. -
essiv
Uses sector number encrypted with a hash of the key. Meant for modes, like CBC, that are not resistant to various attacks when using a simple IV likeplain64
.
-
ivopts The hash to be used with
essiv
ivmode, ignored for all other modes.
As a special case, "cipher-plain
" or just "cipher" are interpreted as "cipher-cbc-plain
". Another special case is that ecb
mode has no ivmode to specify.
How this relates to /proc/crypto
With respect to /proc/crypto
, only the cipher and mode are relevant. dm-crypt with construct a Crypto API specification of the form "mode(
cipher)
" and request this from the kernel. This is what one should look for in /proc/crypto
as the name
for a skcipher
. Example:
name : xts(aes)
driver : xts-aes-aesni
module : kernel
priority : 401
refcnt : 1
selftest : passed
internal : no
type : skcipher
async : yes
blocksize : 16
min keysize : 32
max keysize : 64
ivsize : 16
chunksize : 16
walksize : 16
The type
of skcipher
indicates this a symmetric key cipher, what dm-crypt uses, and the name of xts(aes)
would be written aes-xts
when specified with dm-crypt. The keysize
fields also tell us what key sizes can be used with this cipher.
If this was from a module, the module name might show up in the module
line. However, many ciphers (usually those in software that don't have any hardware specific code) are implement as a generic cipher that is combined with generic block chaining code to produce the final skcipher. For example:
name : xts(anubis)
driver : xts(ecb(anubis-generic))
module : kernel
type : skcipher
name : anubis
driver : anubis-generic
module : anubis
type : cipher
In this case the anubis cipher is combined with the kernel XTS block chaining mode code to produce the final cipher xts(anbuis)
, which has been assigned a module of kernel
. But in order to have this available we need the generic anubis cipher, which is from the anubis
module. Most ciphers have a module alias of "crypto-
cipher" that can be used to load them, e.g. modprobe crypto-anubis
would load module that provides the anubis cipher.
When using the cryptsetup benchmark
command, only the cipher and mode matter, since that is all that is benchmarked. If mode is not specified it defaults to CBC. The ivmode is totally ignored. Thus, for benchmarking, aes
, aes-cbc
, and aes-cbc-foobar
are all equivalent.
You can list the ciphers supported by your kernels with the following command,
[root@arif]# ls /lib/modules/[your kernel version]/kernel/crypto/
algif_rng.ko.xz blowfish_common.ko.xz cmac.ko.xz cts.ko.xz gf128mul.ko.xz michael_mic.ko.xz rsa_generic.ko.xz tgr192.ko.xz xts.ko.xz
ansi_cprng.ko.xz blowfish_generic.ko.xz crc32_generic.ko.xz deflate.ko.xz ghash-generic.ko.xz pcbc.ko.xz salsa20_generic.ko.xz twofish_common.ko.xz zlib.ko.xz
anubis.ko.xz camellia_generic.ko.xz crct10dif_common.ko.xz des_generic.ko.xz jitterentropy_rng.ko.xz pcrypt.ko.xz seed.ko.xz twofish_generic.ko.xz
arc4.ko.xz cast5_generic.ko.xz crct10dif_generic.ko.xz dh_generic.ko.xz khazad.ko.xz rmd128.ko.xz serpent_generic.ko.xz vmac.ko.xz
async_tx cast6_generic.ko.xz cryptd.ko.xz drbg.ko.xz lrw.ko.xz rmd160.ko.xz sha512_generic.ko.xz wp512.ko.xz
authencesn.ko.xz cast_common.ko.xz crypto_null.ko.xz fcrypt.ko.xz mcryptd.ko.xz rmd256.ko.xz tcrypt.ko.xz xcbc.ko.xz
authenc.ko.xz ccm.ko.xz crypto_user.ko.xz gcm.ko.xz md4.ko.xz rmd320.ko.xz tea.ko.xz xor.ko.xz
You can list the ciphers and hashes you can use and their I/O comparison by for luks
by the following command,
[root@arif arif]# cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1 289342 iterations per second for 256-bit key
PBKDF2-sha256 353293 iterations per second for 256-bit key
PBKDF2-sha512 227555 iterations per second for 256-bit key
PBKDF2-ripemd160 233224 iterations per second for 256-bit key
PBKDF2-whirlpool 236165 iterations per second for 256-bit key
argon2i 4 iterations, 917485 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id 4 iterations, 951672 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
# Algorithm | Key | Encryption | Decryption
aes-cbc 128b 642.2 MiB/s 2495.8 MiB/s
serpent-cbc 128b 89.3 MiB/s 542.6 MiB/s
twofish-cbc 128b 100.4 MiB/s 343.1 MiB/s
aes-cbc 256b 477.2 MiB/s 1979.2 MiB/s
serpent-cbc 256b 89.3 MiB/s 538.9 MiB/s
twofish-cbc 256b 173.3 MiB/s 343.1 MiB/s
aes-xts 256b 1668.0 MiB/s 1664.1 MiB/s
serpent-xts 256b 535.7 MiB/s 523.4 MiB/s
twofish-xts 256b 332.6 MiB/s 339.8 MiB/s
aes-xts 512b 1384.5 MiB/s 1380.7 MiB/s
serpent-xts 512b 539.3 MiB/s 524.4 MiB/s
twofish-xts 512b 335.0 MiB/s 340.1 MiB/s
You can compare specific ciphers by the following command,
[root@arif]# ciphers="aes-xts serpent-xts anubis-xts"
[root@arif]# echo "# Algorithm | Key | Encryption | Decryption";for i in $ciphers ; do cryptsetup benchmark --cipher $i|tail -n 1; done
# Algorithm | Key | Encryption | Decryption
aes-xts 256b 1613.9 MiB/s 1642.8 MiB/s
serpent-xts 256b 538.9 MiB/s 521.9 MiB/s
anubis-xts 256b 182.0 MiB/s 182.1 MiB/s