dm-crypt: Linux kernel device-mapper crypto target
About dm-crypt
Device-mapper is infrastructure in the Linux kernel that provides a generic way to create virtual layers of block devices.
Device-mapper crypt target provides transparent encryption of block devices using the kernel crypto API.
The user can basically specify one of the symmetric ciphers, an encryption mode, a key (of any allowed size), an iv generation mode and then the user can create a new block device in /dev.
Writes to this device will be encrypted and reads decrypted. You can mount your filesystem on it as usual or stack dm-crypt device with another device like RAID or LVM volume.
Basic documentation of dm-crypt mapping table comes with kernel source and the latest version is available in git repository.
To enable dm-crypt support, enable CONFIG_DM_CRYPT in Device Drivers/Multi-device support (RAID and LVM) configuration option. Most of distributions have dm-crypt included by default.
To configure you need userspace components: device mapper library (part of LVM2 package) and cryptsetup. All these packages are usually included in your distro repository already.
Check /proc/crypto which contains supported ciphers and modes
(but note it contains only currently loaded crypto API modules).
There is currently no better way how to list all available variations
of cipher and modes if the crypto modules are not loaded.
Device mapper crypt table mapping line specification
Mapping table in device mapper is defined like
<start_sector> <size> <target name> <target mapping table>
- start_sector is 0 (for tables using only one mapped segment, iow table contains only one line)
- size is size of device in sectors
- target name is name of mapping target, here "crypt" for dm-crypt
Sectors unit here are always 512-bytes sectors but encryption can use different sector size (see sector_size
option).
Table fields are separated by space.
dm-crypt target version
Every device-mapper target has internal version which is increased when some new feature is added. (With exceptions caused by developer's forgetfulness. ;-)
To check which version you have installed, load the dm target module (dm-crypt.ko for dm-crypt) and use "dmsetup targets" to check version.
Note that crypt version target is not necessarily related to exact Linux kernel version, some distributions backport changes, so to check if some feature is implemented you need always check dm-crypt target version.
Mapping table for crypt target
The basic syntax is common for all 1.x.y dm-crypt target versions.
If some extension was added later, it is mentioned in the description.
<cipher> <key> <iv_offset> <device path> <offset> [<#opt_params> <opt_params>]
-
cipher: Encryption block cipher.
Cipher can be specified directly using this format:cipher[:keycount]-chainmode-ivmode[:ivopts]
.
or with kernel crypto API format (selected by capi: prefix):capi:cipher_api_spec-ivmode[:ivopts]
.
Example (direct specification): aes, twofish, serpent.
Example (crypto API specification): capi:cbc(aes)-essiv:sha256, capi:xts(aes)-plain64 .
Format with capi prefix available since: 1.16.0 (kernel 4.12) -
keycount: Multi-key compatibility mode.
You can define keycount keys and then sectors are encrypted according to their offsets
(sector 0 uses key0, sector 1 uses key1 etc). keycount must be a power of two.
This parameter is used for loop-AES compatibility mode. Keycount cannot be specified for crypto API format (capi prefix).
Available since: 1.10.0 (kernel 2.6.38) -
chainmode: Block cipher encryption mode.
Example: cbc, xts. -
ivmode: Initialization Vector (IV) used for selected block mode (if block mode requires IV).
Unless block ciphers and encryption modes, IV generators are implemented directly inside dm-crypt module.
IV generators
-
plain: the initial vector is the 32-bit little-endian version of the sector number, padded with zeros if necessary.
-
plain64: the initial vector is the 64-bit little-endian version of the sector number, padded with zeros if necessary.
Available since: 1.7.0 (no proper version set) (kernel 2.6.33) -
plain64be: the initial vector is the 64-bit big-endian version of the sector number, padded with zeros if necessary.
Available since: 1.18.0 (kernel 4.13) -
essiv: "encrypted sector|salt initial vector", the sector number is encrypted with the bulk cipher using a salt as key.
The salt is derived from the bulk cipher's key via hashing.
Note that while the cipher algorithm is always as the same as the algorithm used for data encryption, its key size depends on used hash algorithm.
In other words, while data encryption can use AES-128, the ESSIV calculation with SHA256 will use AES-256.
ESSIV takes hash algorithm as an option, so the format is essiv:hash, e.g. essiv:sha256.
Available since: 1.1.0 (kernel 2.6.10) -
benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1
Available since: 1.3.0 (no proper version set) (kernel 2.6.20) -
null: the initial vector is always zero. Provides compatibility with obsolete loop_fish2 devices.
Available since: 1.5.0 (kernel 2.6.22) -
lmk: Compatible implementation of the block chaining mode used by the Loop-AES block device encryption system.
Available since: 1.10.0 (kernel 2.6.38) -
tcw: Compatible implementation of the key seeded IV with additional whitening (to CBC mode)
used by the TrueCrypt encryption system (prior to version 4.2).
Available since: 1.13.0 (kernel 3.13) -
random: Random IV generated from kernel RNG on every sector write.
This IV requires that underlying device provides bio-integrity metadata space.
Used mainly for authenticated modes.
Available since: 1.16.0 (kernel 4.12) -
eboiv: Encrypted byte-offset IV (used in BitLocker in CBC mode).
The IV is encrypted little-endian byte-offset (with the same key and cipher as the volume).
Available since: 1.19.0 (kernel 5.3)
Examples of full cipher/mode/iv specifications:
aes-cbc-essiv:sha256
aes-xts-plain64
aes:64-cbc-lmk
twofish-ecb
serpent-cbc-plain
Examples of specification with kernel crypto API syntax (available since kernel 4.12):
capi:cbc(aes)-essiv:sha256
capi:xts(aes)-plain64
Examples of authenticated modes:
capi:gcm(aes)-random
capi:authenc(hmac(sha256),xts(aes))-random
capi:rfc7539(chacha20,poly1305)-random
Note that modes with 96-bit nonces (GCM, RFC739 with Chacha etc.) are not secure.
-
key: Key used for encryption. It is encoded as a hexadecimal number (one character represents 4 bits) or as a reference to kernel keyring (if key begins with
:
character).
You can only use key sizes that are valid for the selected cipher.
For multikey mode are all keys of the same length concatenated to one string.
If the key is located in kernel keyring, the structure is:<key_size>:<key_type>:<key_description>
.-
key_size: The encryption key size in bytes that must match keyring stored key.
-
key_type: Keyring key service type, it can be
logon
,user
orencrypted
. -
key_description: The kernel keyring key description to load.
Keys in keyring available since: 1.15.0 (kernel 4.10)
Encrypted keys in keyring available since: 1.21.0 (kernel 5.8)
-
-
iv_offset: The IV offset is a sector count that is added to the sector number before creating the IV.
It can be used to create a map that starts after the first encrypted sector.
Usually you'll set it to zero except your device is only partially available or you need to configure some mode compatible with other encryption system. -
device path: This is the device that is going to be used as backend and contains the encrypted data.
You can specify it as a path like /dev/xxx or a device number major:minor. -
offset: Starting sector within the device where the encrypted data begins.
-
#opt_params: Number of optional parameters. If there are no optional parameters, the optional parameters section can be skipped or it can be zero.
Otherwise it is the number of following arguments.
Available since: 1.11.0 (kernel 3.1)
Optional parameters
-
allow_discards: Allow block discard requests (a.k.a. TRIM) for the crypt device.
The default is to ignore discard requests.
Assess the specific security risks carefully before enabling this option.
For example, allowing discards on encrypted devices may lead to the leak of information about the ciphertext device (filesystem type, used space etc.) if the discarded blocks can be located easily on the device later.
Available since: 1.11.0 (kernel 3.1) -
same_cpu_crypt: Perform encryption using the same cpu that IO was submitted on.
The default is to use an unbound workqueue so that encryption work is automatically balanced between available CPUs.
Available since: 1.14.0 (kernel 4.0) -
submit_from_crypt_cpus: Disable offloading writes to a separate thread after encryption.
There are some situations where offloading write bios from the encryption threads to a single thread degrades performance significantly.
The default is to offload write bios to the same thread because it benefits CFQ to have writes submitted using the same context.
Available since: 1.14.0 (kernel 4.0) -
no_read_workqueue: Bypass dm-crypt internal workqueue and process read requests synchronously.
Available since: 1.22.0 (kernel 5.9) -
no_write_workqueue: Bypass dm-crypt internal workqueue and process write requests synchronously.
Available since: 1.22.0 (kernel 5.9) -
high_priority: Set dm-crypt workqueues and the writer thread to high priority.
This improves throughput and latency of dm-crypt while degrading general responsiveness of the system.
Available since: 1.26.0 (kernel 6.10) -
integrity: The device requires additional metadata space per-sector stored in per-bio kernel integrity structure.
This metadata must by provided by the underlying dm-integrity target.
The option is used to define metadata space size for authentication tags and for persistent per-sector random IV.
The integrity option takes two parameters asintegrity:<bytes>:<type>
.-
bytes: is size of persistent per-sector integrity metadata that must be provided by the underlying device.
(Underlying dm-integrity target provides bio-integrity profile named DM-DIF-EXT-TAG). -
type: can be
none
if metadata is used only for a persistent IV.
For Authenticated Encryption with Additional Data (AEAD) the type isaead
.
The type can also be a crypto API function specification that calculates integrity tags, for examplehmac(sha256)
and can be used together with common length-preserving encryption modes (like XTS).
Note that for all authenticated modes you should userandom IV
, so the per-sector metadata space is divided into two parts: sector authenticated tag and persistent (random) IV.
Available since: 1.16.0 (kernel 4.12)
-
-
integrity_key_size: Optionally set the integrity key size if it differs from the digest size.
It allows the use of wrapped key algorithms where the key size is independent of the cryptographic key size.
The integrity_key_size option takes one parameter asintegrity_key_size:<bytes>
.
Available since: 1.28.0 (kernel 6.12) -
sector_size: Specifies encryption sector size.
The default (backward compatible) sector size for dm-crypt is always 512 bytes.
This option takes one parameter in the formsector_size:<bytes>
wherebytes
means user-specified sector size used for encryption.
Size can be in range 512 - 4096 bytes and must be power of two.
Virtual device will announce this size as minimal IO size and logical sector size.
Available since: 1.17.0 (kernel 4.12) -
iv_large_sectors: IV generators will use sector number counted in
sector_size
units instead of default 512 bytes sectors.
For example, if sector size is 4096 bytes, plain64 IV for the second sector will be 8 (without flag) and 1 if iv_large_sectors is present.
If this flag is specified, theiv_offset
must be multiple ofsector_size
(in 512 bytes units).
Available since: 1.17.0 (kernel 4.12)
Examples of optional parameters section:
1 allow_discards
3 allow_discards same_cpu_crypt submit_from_crypt_cpus
Example of full mapping table
0 417792 crypt aes-xts-plain64 e8cfa3dbfe373b536be43c5637387786c01be00ba5f730aacb039e86f3eb72f3 0 8:16 0
| | | | | | | | | |
start| | | mode IV | | | offset
size | cipher | | device
target 256bit-key IV offset
0 417792 crypt serpent-cbc-essiv:sha256 a7f67ad520bd83b9725df6ebd76c3eee 0 /dev/sdb 0
| | | | | | | | | | |
start| | | mode IV IV-opts | | | offset
size | cipher | | device
target 128bit-key IV offset
Optional section example:
0 417792 crypt serpent-cbc-essiv:sha256 a7f67ad520bd83b9725df6ebd76c3eee 0 /dev/sdb 0 1 allow_discards
| |
| optional parameter
count
Configuration with dmsetup tool
Dmsetup is used to create and remove devices, get information about
devices or reload tables (that means changing the mapping while the device is in use).
Usually this tool is only used for low-level access to dm device,
example here is mentioned just to show how the low level parameters works.
Always prefer using cryptsetup if possible.
To create device and specify mapping table, use this command:
dmsetup create <name> --table " ..."
The second example above is then created using
dmsetup create x --table "0 $(blockdev --getsz /dev/sdb) crypt serpent-cbc-essiv:sha256 a7f67...ee 0 /dev/sdb 0"
You can check the full mapping table using dmsetup table
with optional --showkeys
parameter.
Note that for all device-mapper operations is required root privilege (CAP_SYSADMIN).
The newly created device then appears as /dev/mapper/name.
Example of using volume key in keyring
You can put a binary key blob into kernel keyring, here test-key
into user keyring. In a real application it is perhaps better to use the process keyring that has the same lifetime as the process.
dd if=/dev/urandom of=keyfile bs=1 count=64 status=none
keyctl padd user test-key @u <keyfile
Then we can reference this key in the dm-crypt table and optionally destroy key in keyring after it is configured:
dmsetup create test --table "0 $(blockdev --getsz /dev/sdb) crypt aes-xts-plain64 :64:user:test-key 0 /dev/sdb 0"
keyctl purge user test-key
Configuration using cryptsetup
Cryptsetup utility support several modes. Plain mode is just equivalent of direct configuration of dmcrypt target with passphrase hashing but without on-disk metadata.
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
encryption with dm-crypt using the cryptsetup utility, see cryptsetup project page
Example of using cryptsetup
If you have keyfile (in binary format) in file /key, you can setup mapping in example above as
cryptsetup -d /key -s 128 -c serpent-cbc-essiv:sha256 create <name> /dev/sdb
If you want to use LUKS on-disk metadata with default cipher, use
cryptsetup luksFormat <device>
cryptsetup luksOpen <device> <name>
The DMCrypt page is written and maintained by Milan Broz (with help of other project users and developers).
Please use New issue report if there is some bug or problem on this page, thank you.