Chapter 9. Encrypting block devices using LUKS By using the disk encryption, you can protect the data on a block device by encrypting it. To access the device's decrypted contents, enter a passphrase or key as authentication. This is important for mobile computers and removable media because it helps to protect the device's contents even if it has been physically removed from the system. The LUKS format is a default implementation of block device encryption in Red Hat Enterprise Linux. 9.1. LUKS disk encryption Linux Unified Key Setup-on-disk-format (LUKS) provides a set of tools that simplifies managing the encrypted devices. With LUKS, you can encrypt block devices and enable multiple user keys to decrypt a master key. For bulk encryption of the partition, use this master key. Red Hat Enterprise Linux uses LUKS to perform block device encryption. By default, the option to encrypt the block device is unchecked during the installation. If you select the option to encrypt your disk, the system prompts you for a passphrase every time you boot the computer. This passphrase unlocks the bulk encryption key that decrypts your partition. If you want to modify the default partition table, you can select the partitions that you want to encrypt. This is set in the partition table settings. Ciphers The default cipher used for LUKS is aes-xts-plain64 . The default key size for LUKS is 512 bits. The default key size for LUKS with Anaconda XTS mode is 512 bits. The following are the available ciphers: Advanced Encryption Standard (AES) Twofish Serpent Operations performed by LUKS LUKS encrypts entire block devices and is therefore well-suited for protecting contents of mobile devices such as removable storage media or laptop disk drives. The underlying contents of the encrypted block device are arbitrary, which makes it useful for encrypting swap devices. This can also be useful with certain databases that use specially formatted block devices for data storage. LUKS uses the existing device mapper kernel subsystem. LUKS provides passphrase strengthening, which protects against dictionary attacks. LUKS devices contain multiple key slots, which means you can add backup keys or passphrases. Important LUKS is not recommended for the following scenarios: Disk-encryption solutions such as LUKS protect the data only when your system is off. After the system is on and LUKS has decrypted the disk, the files on that disk are available to anyone who have access to them. Scenarios that require multiple users to have distinct access keys to the same device. The LUKS1 format provides eight key slots and LUKS2 provides up to 32 key slots. Applications that require file-level encryption. Additional resources LUKS Project Home Page LUKS On-Disk Format Specification FIPS 197: Advanced Encryption Standard (AES) 9.2. LUKS versions in RHEL In Red Hat Enterprise Linux, the default format for LUKS encryption is LUKS2. The old LUKS1 format remains fully supported and it is provided as a format compatible with earlier Red Hat Enterprise Linux releases. LUKS2 re-encryption is considered more robust and safe to use as compared to LUKS1 re-encryption. The LUKS2 format enables future updates of various parts without a need to modify binary structures. Internally it uses JSON text format for metadata, provides redundancy of metadata, detects metadata corruption, and automatically repairs from a metadata copy. Important Do not use LUKS2 in systems that support only LUKS1. Since Red Hat Enterprise Linux 9.2, you can use the cryptsetup reencrypt command for both the LUKS versions to encrypt the disk. Online re-encryption The LUKS2 format supports re-encrypting encrypted devices while the devices are in use. For example, you do not have to unmount the file system on the device to perform the following tasks: Changing the volume key Changing the encryption algorithm When encrypting a non-encrypted device, you must still unmount the file system. You can remount the file system after a short initialization of the encryption. The LUKS1 format does not support online re-encryption. Conversion In certain situations, you can convert LUKS1 to LUKS2. The conversion is not possible specifically in the following scenarios: A LUKS1 device is marked as being used by a Policy-Based Decryption (PBD) Clevis solution. The cryptsetup tool does not convert the device when some luksmeta metadata are detected. A device is active. The device must be in an inactive state before any conversion is possible. 9.3. Options for data protection during LUKS2 re-encryption LUKS2 provides several options that prioritize performance or data protection during the re-encryption process. It provides the following modes for the resilience option, and you can select any of these modes by using the cryptsetup reencrypt --resilience resilience-mode /dev/sdx command: checksum The default mode. It balances data protection and performance. This mode stores individual checksums of the sectors in the re-encryption area, which the recovery process can detect for the sectors that were re-encrypted by LUKS2. The mode requires that the block device sector write is atomic. journal The safest mode but also the slowest. Since this mode journals the re-encryption area in the binary area, the LUKS2 writes the data twice. none The none mode prioritizes performance and provides no data protection. It protects the data only against safe process termination, such as the SIGTERM signal or the user pressing Ctrl + C key. Any unexpected system failure or application failure might result in data corruption. If a LUKS2 re-encryption process terminates unexpectedly by force, LUKS2 can perform the recovery in one of the following ways: Automatically By performing any one of the following actions triggers the automatic recovery action during the LUKS2 device open action: Executing the cryptsetup open command. Attaching the device with the systemd-cryptsetup command. Manually By using the cryptsetup repair /dev/sdx command on the LUKS2 device. Additional resources cryptsetup-reencrypt(8) and cryptsetup-repair(8) man pages on your system 9.4. Encrypting existing data on a block device using LUKS2 You can encrypt the existing data on a not yet encrypted device by using the LUKS2 format. A new LUKS header is stored in the head of the device. Prerequisites The block device has a file system. You have backed up your data. Warning You might lose your data during the encryption process due to a hardware, kernel, or human failure. Ensure that you have a reliable backup before you start encrypting the data. Procedure Unmount all file systems on the device that you plan to encrypt, for example: Make free space for storing a LUKS header. Use one of the following options that suits your scenario: In the case of encrypting a logical volume, you can extend the logical volume without resizing the file system. For example: Extend the partition by using partition management tools, such as parted . Shrink the file system on the device. You can use the resize2fs utility for the ext2, ext3, or ext4 file systems. Note that you cannot shrink the XFS file system. Initialize the encryption: Mount the device: Add an entry for a persistent mapping to the /etc/crypttab file: Find the luksUUID : Open /etc/crypttab in a text editor of your choice and add a device in this file: Replace a52e2cc9-a5be-47b8-a95d-6bdf4f2d9325 with your device's luksUUID . Refresh initramfs with dracut : Add an entry for a persistent mounting to the /etc/fstab file: Find the file system's UUID of the active LUKS block device: Open /etc/fstab in a text editor of your choice and add a device in this file, for example: Replace 37bc2492-d8fa-4969-9d9b-bb64d3685aa9 with your file system's UUID. Resume the online encryption: Verification Verify if the existing data was encrypted: View the status of the encrypted blank block device: Additional resources cryptsetup(8) , cryptsetup-reencrypt(8) , lvextend(8) , resize2fs(8) , and parted(8) man pages on your system 9.5. Encrypting existing data on a block device using LUKS2 with a detached header You can encrypt existing data on a block device without creating free space for storing a LUKS header. The header is stored in a detached location, which also serves as an additional layer of security. The procedure uses the LUKS2 encryption format. Prerequisites The block device has a file system. You have backed up your data. Warning You might lose your data during the encryption process due to a hardware, kernel, or human failure. Ensure that you have a reliable backup before you start encrypting the data. Procedure Unmount all file systems on the device, for example: Initialize the encryption: Replace /home/header with a path to the file with a detached LUKS header. The detached LUKS header has to be accessible to unlock the encrypted device later. Mount the device: Resume the online encryption: Verification Verify if the existing data on a block device using LUKS2 with a detached header is encrypted: View the status of the encrypted blank block device: Additional resources cryptsetup(8) and cryptsetup-reencrypt(8) man pages on your system 9.6. Encrypting a blank block device using LUKS2 You can encrypt a blank block device, which you can use for an encrypted storage by using the LUKS2 format. Prerequisites A blank block device. You can use commands such as lsblk to find if there is no real data on that device, for example, a file system. Procedure Setup a partition as an encrypted LUKS partition: Open an encrypted LUKS partition: This unlocks the partition and maps it to a new device by using the device mapper. To not overwrite the encrypted data, this command alerts the kernel that the device is an encrypted device and addressed through LUKS by using the /dev/mapper/ device_mapped_name path. Create a file system to write encrypted data to the partition, which must be accessed through the device mapped name: Mount the device: Verification Verify if the blank block device is encrypted: View the status of the encrypted blank block device: Additional resources cryptsetup(8) , cryptsetup-open (8) , and cryptsetup-lusFormat(8) man pages on your system 9.7. Configuring the LUKS passphrase in the web console If you want to add encryption to an existing logical volume on your system, you can only do so through formatting the volume. Prerequisites You have installed the RHEL 9 web console. You have enabled the cockpit service. Your user account is allowed to log in to the web console. For instructions, see Installing and enabling the web console . The cockpit-storaged package is installed on your system. Available existing logical volume without encryption. Procedure Log in to the RHEL 9 web console. For details, see Logging in to the web console . In the panel, click Storage . In the Storage table, click the menu button ... for the storage device you want to encrypt and click Format . In the Encryption field , select the encryption specification, LUKS1 or LUKS2 . Set and confirm your new passphrase. Optional: Modify further encryption options. Finalize formatting settings. Click Format . 9.8. Changing the LUKS passphrase in the web console Change a LUKS passphrase on an encrypted disk or partition in the web console. Prerequisites You have installed the RHEL 9 web console. You have enabled the cockpit service. Your user account is allowed to log in to the web console. For instructions, see Installing and enabling the web console . The cockpit-storaged package is installed on your system. Procedure Log in to the RHEL 9 web console. For details, see Logging in to the web console . In the panel, click Storage . In the Storage table, select the disk with encrypted data. On the disk page, scroll to the Keys section and click the edit button. In the Change passphrase dialog window: Enter your current passphrase. Enter your new passphrase. Confirm your new passphrase. Click Save . 9.9. Creating a LUKS2 encrypted volume by using the storage RHEL system role You can use the storage role to create and configure a volume encrypted with LUKS by running an Ansible playbook. Prerequisites You have prepared the control node and the managed nodes You are logged in to the control node as a user who can run playbooks on the managed nodes. The account you use to connect to the managed nodes has sudo permissions on them. Procedure Store your sensitive variables in an encrypted file: Create the vault: After the ansible-vault create command opens an editor, enter the sensitive data in the <key> : <value> format: luks_password: <password> Save the changes, and close the editor. Ansible encrypts the data in the vault. Create a playbook file, for example ~/playbook.yml , with the following content: --- - name: Manage local storage hosts: managed-node-01.example.com vars_files: - vault.yml tasks: - name: Create and configure a volume encrypted with LUKS ansible.builtin.include_role: name: rhel-system-roles.storage vars: storage_volumes: - name: barefs type: disk disks: - sdb fs_type: xfs fs_label: <label> mount_point: /mnt/data encryption: true encryption_password: "{{ luks_password }}" For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.storage/README.md file on the control node. Validate the playbook syntax: Note that this command only validates the syntax and does not protect against a wrong but valid configuration. Run the playbook: Verification Find the luksUUID value of the LUKS encrypted volume: View the encryption status of the volume: Verify the created LUKS encrypted volume: Additional resources /usr/share/ansible/roles/rhel-system-roles.storage/README.md file /usr/share/doc/rhel-system-roles/storage/ directory Encrypting block devices by using LUKS Ansible vault

Commands:
umount /dev/mapper/vg00-lv00
lvextend -L+ 32M /dev/mapper/vg00-lv00
cryptsetup reencrypt --encrypt --init-only --reduce-device-size 32M /dev/mapper/ vg00-lv00 lv00_encrypted /dev/mapper/ lv00_encrypted is now active and ready for online encryption.
mount /dev/mapper/ lv00_encrypted /mnt/lv00_encrypted
cryptsetup luksUUID /dev/mapper/ vg00-lv00 a52e2cc9-a5be-47b8-a95d-6bdf4f2d9325
vi /etc/crypttab lv00_encrypted UUID= a52e2cc9-a5be-47b8-a95d-6bdf4f2d9325 none
dracut -f --regenerate-all
blkid -p /dev/mapper/ lv00_encrypted /dev/mapper/ lv00-encrypted : UUID=" 37bc2492-d8fa-4969-9d9b-bb64d3685aa9 " BLOCK_SIZE="4096" TYPE="xfs" USAGE="filesystem"
vi /etc/fstab UUID= 37bc2492-d8fa-4969-9d9b-bb64d3685aa9 /home auto rw,user,auto 0
cryptsetup reencrypt --resume-only /dev/mapper/ vg00-lv00 Enter passphrase for /dev/mapper/ vg00-lv00 : Auto-detected active dm device ' lv00_encrypted ' for data device /dev/mapper/ vg00-lv00 . Finished, time 00:31.130, 10272 MiB written, speed 330.0 MiB/s
cryptsetup luksDump /dev/mapper/ vg00-lv00 LUKS header information Version: 2 Epoch: 4 Metadata area: 16384 [bytes] Keyslots area: 16744448 [bytes] UUID: a52e2cc9-a5be-47b8-a95d-6bdf4f2d9325 Label: (no label) Subsystem: (no subsystem) Flags: (no flags) Data segments: 0: crypt offset: 33554432 [bytes] length: (whole device) cipher: aes-xts-plain64 [...]
cryptsetup status lv00_encrypted /dev/mapper/ lv00_encrypted is active and is in use. type: LUKS2 cipher: aes-xts-plain64 keysize: 512 bits key location: keyring device: /dev/mapper/ vg00-lv00
umount /dev/ nvme0n1p1
cryptsetup reencrypt --encrypt --init-only --header /home/header /dev/ nvme0n1p1 nvme_encrypted WARNING! ======== Header file does not exist, do you want to create it? Are you sure? (Type 'yes' in capital letters): YES Enter passphrase for /home/header : Verify passphrase: /dev/mapper/ nvme_encrypted is now active and ready for online encryption.
mount /dev/mapper/ nvme_encrypted /mnt/nvme_encrypted
cryptsetup reencrypt --resume-only --header /home/header /dev/ nvme0n1p1 Enter passphrase for /dev/ nvme0n1p1 : Auto-detected active dm device 'nvme_encrypted' for data device /dev/ nvme0n1p1 . Finished, time 00m51s, 10 GiB written, speed 198.2 MiB/s
cryptsetup luksDump /home/header LUKS header information Version: 2 Epoch: 88 Metadata area: 16384 [bytes] Keyslots area: 16744448 [bytes] UUID: c4f5d274-f4c0-41e3-ac36-22a917ab0386 Label: (no label) Subsystem: (no subsystem) Flags: (no flags) Data segments: 0: crypt offset: 0 [bytes] length: (whole device) cipher: aes-xts-plain64 sector: 512 [bytes] [...]
cryptsetup status nvme_encrypted /dev/mapper/ nvme_encrypted is active and is in use. type: LUKS2 cipher: aes-xts-plain64 keysize: 512 bits key location: keyring device: /dev/ nvme0n1p1
cryptsetup luksFormat /dev/ nvme0n1p1 WARNING! ======== This will overwrite data on /dev/nvme0n1p1 irrevocably. Are you sure? (Type 'yes' in capital letters): YES Enter passphrase for /dev/ nvme0n1p1 : Verify passphrase:
cryptsetup open /dev/ nvme0n1p1 nvme0n1p1_encrypted Enter passphrase for /dev/ nvme0n1p1 :
mkfs -t ext4 /dev/mapper/ nvme0n1p1_encrypted
mount /dev/mapper/ nvme0n1p1_encrypted mount-point
cryptsetup luksDump /dev/ nvme0n1p1 LUKS header information Version: 2 Epoch: 3 Metadata area: 16384 [bytes] Keyslots area: 16744448 [bytes] UUID: 34ce4870-ffdf-467c-9a9e-345a53ed8a25 Label: (no label) Subsystem: (no subsystem) Flags: (no flags) Data segments: 0: crypt offset: 16777216 [bytes] length: (whole device) cipher: aes-xts-plain64 sector: 512 [bytes] [...]
cryptsetup status nvme0n1p1_encrypted /dev/mapper/ nvme0n1p1_encrypted is active and is in use. type: LUKS2 cipher: aes-xts-plain64 keysize: 512 bits key location: keyring device: /dev/ nvme0n1p1 sector size: 512 offset: 32768 sectors size: 20938752 sectors mode: read/write
ansible-vault create vault.yml New Vault password: <vault_password> Confirm New Vault password: <vault_password>
luks_password: <password>
--- - name: Manage local storage hosts: managed-node-01.example.com vars_files: - vault.yml tasks: - name: Create and configure a volume encrypted with LUKS ansible.builtin.include_role: name: rhel-system-roles.storage vars: storage_volumes: - name: barefs type: disk disks: - sdb fs_type: xfs fs_label: <label> mount_point: /mnt/data encryption: true encryption_password: "{{ luks_password }}"
ansible-playbook --ask-vault-pass --syntax-check ~/playbook.yml
ansible-playbook --ask-vault-pass ~/playbook.yml
ansible managed-node-01.example.com -m command -a 'cryptsetup luksUUID /dev/sdb' 4e4e7970-1822-470e-b55a-e91efe5d0f5c
ansible managed-node-01.example.com -m command -a 'cryptsetup status luks-4e4e7970-1822-470e-b55a-e91efe5d0f5c' /dev/mapper/luks-4e4e7970-1822-470e-b55a-e91efe5d0f5c is active and is in use. type: LUKS2 cipher: aes-xts-plain64 keysize: 512 bits key location: keyring device: /dev/sdb
ansible managed-node-01.example.com -m command -a 'cryptsetup luksDump /dev/sdb' LUKS header information Version: 2 Epoch: 3 Metadata area: 16384 [bytes] Keyslots area: 16744448 [bytes] UUID: 4e4e7970-1822-470e-b55a-e91efe5d0f5c Label: (no label) Subsystem: (no subsystem) Flags: (no flags) Data segments: 0: crypt offset: 16777216 [bytes] length: (whole device) cipher: aes-xts-plain64 sector: 512 [bytes]