In a Linux based operating system, the crypttab file (/etc/crypttab
), is used to store static information about encrypted block devices which are meant to be set up and unlocked at boot. In this tutorial we learn how it is structured and how to organize data in it.
In this tutorial you will learn:
- What the crypttab file is used for
- How data is organized inside the crypttab file
Software requirements and conventions used
Category | Requirements, Conventions or Software Version Used |
---|---|
System | Distribution-independent |
Software | No specific software needed |
Other | None |
Conventions | # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command$ – requires given linux-commands to be executed as a regular non-privileged user |
How data is organized in the crypttab file
As we already said, the /etc/crypttab
file on Linux distributions is used to store static information about encrypted block devices which should be unlocked and set during system boot. Each row in the file is dedicated to a block device, and data in it is organized in columns. There four columns, in order:
- The device mapper name which should be used for the volume
- The encrypted block device reference
- The encryption key which should eventually be used to unlock the device
- A comma-separated list of options for the device
Of the fields listed above, only the first two are mandatory. Let’s see them all in a more detailed way.
The first column: the device mapper name
In each row of the /etc/crypttab
file, the first, mandatory column, is used to store the device mapper name to use for an encrypted block device. What is this exactly?
On Linux, the main way to setup an encrypted block device is by using the
cryptsetup
utility. With it, we can use two encryption methods: plain and LUKS. The first method is simpler and needs no metadata to be stored on the device. The second is more feature-rich: the device is encrypted using a master key, and can be unlocked using multiple passwords. Passwords themselves are hashed with a salt which is stored on a header created (by default) on the encrypted device (it can also be stored separately). If the header is damaged all data is lost.
When we unlock a device using the cryptsetup utility we have to specify the device mapper name to be used for the unlocked volume. Device mapper is the system which Linux uses to map block devices to higher-level virtual devices. It is used, for example, for LVM logical volumes and volume groups, for RAID devices, and also to store encrypted block devices, as in this case. Device mapper volumes are represented inside the /dev/mapper
directory and can be listed simply by using the ls
command as in the example below:
$ ls /dev/mapper root_lv home_lv [...]
In the output of the command above, we can see two files representing logical volumes.
Suppose we want to unlock a LUKS encrypted block device with cryptsetup
. In the most basic situation, we would use the following syntax:
$ sudo cryptsetup luksOpen /path/to/encrypted/block/device dm-volume-name
The volume name is exactly what we need to provide in the first column of each row in the crypttab file.
The second column: the encrypted block device
The second column of the crypttab file is used to reference the encrypted block device. A reference can be made by path, for example: /dev/sda1
, but since the path of a block device is not guaranteed to remain the same at each boot, the best way to reference it is by using its UUID or Universally Unique identifier. We can do so by using the same notation we would use in the /etc/fstab
:
UUID=2ae2767d-3ec6-4d37-9639-e16f013f1e60
The third column: absolute path to the encryption key
When using LUKS as a method of device encryption, we can setup a file to be used as the device key. We saw how to do this in a previous tutorial. If we want the key to be used to unlock the device at boot (notice that this could represent a security issue), we have to specify its absolute path in the third field of the crypttab file. If we don’t want to use a key file to open the block device we can simply write “none” or “-” in this field.
What if the encryption keyfile is located on a different device, say for example an usb key? In that case we can append a
:
(colon) sign after the specified keyfile path, followed by an identifier for the filesystem the key is on. Once again the recommended way to reference the filesystem is by its UUID. Just to make an example, to specify the keyfile is in the /keyfiles
directory on the filesystem which has the 17513654-34ed-4c84-9808-3aedfc22a20e
UUID, we would write:
/keyfiles:UUID=17513654-34ed-4c84-9808-3aedfc22a20e
For this to work, of course, the system should be able to read the filesystem in which the keyfile is stored. If for some reason we are using a keyfile to unlock the root filesystem (this is a bad practice, and basically makes encryption useless, since if someone gets the device on which the key is stored, he has full access to data on it), we also would need to regenerate the system initramfs, so that it will include the changed crypttab file.
If the specified keyfile is not found, the user is prompted to manually enter a password to unlock the encrypted block device as a fallback.
The fourth column: encrypted device options
We can use the fourth column of each crypttab row to specify the encryption options which should be used to unlock the encrypted block device. We can, for example, specify the encryption type, the cipher, hash and size. This is typically needed when the block device was encrypted by using plain dm-crypt instead of LUKS. Since with this system there is no header where encryption metadata is stored, the encryption parameters must be provided each time the device is opened.
For example, to open and use /dev/sda1
as a plain-dm crypt device from the command line, and map it as sda1_crypt
, we would write:
$ sudo cryptsetup open \ --type plain \ --cipher=aes-xts-plain64 \ --hash=sha512 \ --size=512 /dev/sda1 sda1_crypt
To specify the same options and values statically in the crypttab file, in the fourth column of the dedicated row, we would write:
plain,cipher=aes-xts-plain64,hash=sha512,size=512
If we are using LUKS, those information are stored in the metadata header, so there is no need to report them this way. All we have to do is to be sure that luks mode is used. We can do it by replacing “plain” with “luks”.
Other options which can be used in this column are:
Option | function |
---|---|
discard | Needed to allow discard requests (TRIM) through the encrypted block device (this has security implications) |
header | Needed to specify the location of the LUKS header if it is separated from the encrypted block device |
noauto | If this option is used, the device is not automatically unlocked at boot |
nofail | Marks the unlocking of the block device as non-essential. The boot process is not stopped if unlocking is not successful |
readonly | Set the encrypted block device in read-only mode |
tries= | Takes the number of attempts the user is prompted to provide the right password. The default is 0, which means no limit. |
headless= | Takes a boolean as a value. If true, the user is never prompted for a password interactively |
The one above is not the complete list of the options which can be used in the crypttab file. To learn all of them, you can take a look at the crypttab manual.
Closing thoughts
In this tutorial we learned what is the role of /etc/crypttab
file in a Linux system: it is used to store static data about encrypted block devices which should be unlocked at boot. We also learned how information are organized in the file and saw some of the options which can be specified in the fourth column of each row.