Chapter 9. Configuring automated unlocking of encrypted volumes using policy-based decryption

The Policy-Based Decryption (PBD) is a collection of technologies that enable unlocking encrypted root and secondary volumes of hard drives on physical and virtual machines. PBD uses a variety of unlocking methods, such as user passwords, a Trusted Platform Module (TPM) device, a PKCS#11 device connected to a system, for example, a smart card, or a special network server.

PBD allows combining different unlocking methods into a policy, which makes it possible to unlock the same volume in different ways. The current implementation of the PBD in Red Hat Enterprise Linux consists of the Clevis framework and plug-ins called pins. Each pin provides a separate unlocking capability. Currently, the following pins are available:

  • tang - allows volumes to be unlocked using a network server
  • tpm2 - allows volumes to be unlocked using a TPM2 policy

The Network Bound Disc Encryption (NBDE) is a subcategory of PBD that allows binding encrypted volumes to a special network server. The current implementation of the NBDE includes a Clevis pin for Tang server and the Tang server itself.

9.1. Network-bound disk encryption

In Red Hat Enterprise Linux, NBDE is implemented through the following components and technologies:

Figure 9.1. NBDE scheme when using a LUKS1-encrypted volume. The luksmeta package is not used for LUKS2 volumes.

RHEL Security Guide 453350 0717 ECE NBDE

Tang is a server for binding data to network presence. It makes a system containing your data available when the system is bound to a certain secure network. Tang is stateless and does not require TLS or authentication. Unlike escrow-based solutions, where the server stores all encryption keys and has knowledge of every key ever used, Tang never interacts with any client keys, so it never gains any identifying information from the client.

Clevis is a pluggable framework for automated decryption. In NBDE, Clevis provides automated unlocking of LUKS volumes. The clevis package provides the client side of the feature.

A Clevis pin is a plug-in into the Clevis framework. One of such pins is a plug-in that implements interactions with the NBDE server — Tang.

Clevis and Tang are generic client and server components that provide network-bound encryption. In Red Hat Enterprise Linux, they are used in conjunction with LUKS to encrypt and decrypt root and non-root storage volumes to accomplish Network-Bound Disk Encryption.

Both client- and server-side components use the José library to perform encryption and decryption operations.

When you begin provisioning NBDE, the Clevis pin for Tang server gets a list of the Tang server’s advertised asymmetric keys. Alternatively, since the keys are asymmetric, a list of Tang’s public keys can be distributed out of band so that clients can operate without access to the Tang server. This mode is called offline provisioning.

The Clevis pin for Tang uses one of the public keys to generate a unique, cryptographically-strong encryption key. Once the data is encrypted using this key, the key is discarded. The Clevis client should store the state produced by this provisioning operation in a convenient location. This process of encrypting data is the provisioning step.

Since the LUKS version 2 (LUKS2) is the default format in Red Hat Enterprise Linux 8, the provisioning state for NBDE is stored as a token in a LUKS2 header. The leveraging of provisioning state for NBDE by the luksmeta package is used only for volumes encrypted with LUKS1. The Clevis pin for Tang supports both LUKS1 and LUKS2 without specification need.

When the client is ready to access its data, it loads the metadata produced in the provisioning step and it responds to recover the encryption key. This process is the recovery step.

In NBDE, Clevis binds a LUKS volume using a pin so that it can be automatically unlocked. After successful completion of the binding process, the disk can be unlocked using the provided Dracut unlocker.

All LUKS-encrypted devices, such as those with the /tmp, /var, and /usr/local/ directories, that contain a file system requiring to start before the network connection is established are considered to be root volumes. Additionally, all mount points that are used by services run before the network is up, such as /var/log/, var/log/audit/, or /opt, also require to be mounted early after switching to a root device. You can also identify a root volume by not having the _netdev option in the /etc/fstab file.

9.2. Installing an encryption client - Clevis

Use this procedure to deploy and start using the Clevis pluggable framework on your system.

Procedure

  1. To install Clevis and its pins on a system with an encrypted volume:

    # yum install clevis
  2. To decrypt data, use a clevis decrypt command and provide a cipher text in the JSON Web Encryption (JWE) format, for example:

    $ clevis decrypt < secret.jwe

Additional resources

  • For a quick reference, see the built-in CLI help:

    $ clevis
    Usage: clevis COMMAND [OPTIONS]
    
      clevis decrypt      Decrypts using the policy defined at encryption time
      clevis encrypt sss  Encrypts using a Shamir's Secret Sharing policy
      clevis encrypt tang Encrypts using a Tang binding server policy
      clevis encrypt tpm2 Encrypts using a TPM2.0 chip binding policy
    
    $ clevis decrypt
    Usage: clevis decrypt < JWE > PLAINTEXT
    
    Decrypts using the policy defined at encryption time
    
    $ clevis encrypt tang
    Usage: clevis encrypt tang CONFIG < PLAINTEXT > JWE
    
    Encrypts using a Tang binding server policy
    
    This command uses the following configuration properties:
    
      url: <string>   The base URL of the Tang server (REQUIRED)
    
      thp: <string>   The thumbprint of a trusted signing key
    
      adv: <string>   A filename containing a trusted advertisement
      adv: <object>   A trusted advertisement (raw JSON)
    
    Obtaining the thumbprint of a trusted signing key is easy. If you
    have access to the Tang server's database directory, simply do:
    
        $ jose jwk thp -i $DBDIR/$SIG.jwk
    
    Alternatively, if you have certainty that your network connection
    is not compromised (not likely), you can download the advertisement
    yourself using:
    
        $ curl -f $URL/adv > adv.jws
  • For more information , see the clevis(1) man page.

9.3. Deploying a Tang server with SELinux in enforcing mode

Use this procedure to deploy a Tang server running on a custom port as a confined service in SELinux enforcing mode.

Prerequisites

  • The policycoreutils-python-utils package and its dependencies are installed.

Procedure

  1. To install the tang package and its dependencies, enter the following command as root:

    # yum install tang
  2. Pick an unoccupied port, for example, 7500/tcp, and allow the tangd service to bind to that port:

    # semanage port -a -t tangd_port_t -p tcp 7500

    Note that a port can be used only by one service at a time, and thus an attempt to use an already occupied port implies the ValueError: Port already defined error message.

  3. Open the port in the firewall:

    # firewall-cmd --add-port=7500/tcp
    # firewall-cmd --runtime-to-permanent
  4. Enable the tangd service:

    # systemctl enable tangd.socket
  5. Create an override file:

    # systemctl edit tangd.socket
  6. In the following editor screen, which opens an empty override.conf file located in the /etc/systemd/system/tangd.socket.d/ directory, change the default port for the Tang server from 80 to the previously picked number by adding the following lines:

    [Socket]
    ListenStream=
    ListenStream=7500

    Save the file and exit the editor.

  7. Reload the changed configuration:

    # systemctl daemon-reload
  8. Check that your configuration is working:

    # systemctl show tangd.socket -p Listen
    Listen=[::]:7500 (Stream)
  9. Start the tangd service:

    # systemctl start tangd.socket

    Because tangd uses the systemd socket activation mechanism, the server starts as soon as the first connection comes in. A new set of cryptographic keys is automatically generated at the first start. To perform cryptographic operations such as manual key generation, use the jose utility.

Additional resources

  • semanage(8) man page
  • firewall-cmd(1) man page
  • systemd.unit(5) and systemd.socket(5) man pages
  • jose(1) man page

9.4. Rotating Tang keys

Use the following steps to rotate your Tang keys. The precise interval at which you should rotate them depends on your application, key sizes, and institutional policy.

Procedure

  1. To rotate keys, start with the generation of new keys in the key database directory, typically /var/db/tang. For example, you can create new signature and exchange keys with the following commands:

    # DB=/var/db/tang
    # jose jwk gen -i '{"alg":"ES512"}' -o $DB/new_sig.jwk
    # jose jwk gen -i '{"alg":"ECMR"}' -o $DB/new_exc.jwk
  2. Rename the old keys to have a leading . to hide them from advertisement. Note that the file names in the following example differs from real and unique file names in the key database directory.

    # mv $DB/old_sig.jwk $DB/.old_sig.jwk
    # mv $DB/old_exc.jwk $DB/.old_exc.jwk

    Tang immediately picks up all changes. No restart is required.

  3. At this point, new client bindings pick up the new keys and old clients can continue to utilize the old keys. When you are sure that all old clients use the new keys, you can remove the old keys.
Warning

Be aware that removing the old keys while clients are still using them can result in data loss.

Additional resources

9.5. Deploying an encryption client for an NBDE system with Tang

The following procedure contains steps to configure automated unlocking of an encrypted volume with a Tang network server.

Prerequisites

  • The Clevis framework is installed.
  • A Tang server is available.

Procedure

  1. To bind a Clevis encryption client to a Tang server, use the clevis encrypt tang sub-command:

    $ clevis encrypt tang '{"url":"http://tang.srv:port"}' < input-plain.txt > secret.jwe
    The advertisement contains the following signing keys:
    
    _OsIk0T-E2l6qjfdDiwVmidoZjA
    
    Do you wish to trust these keys? [ynYN] y

    Change the http://tang.srv:port URL in the previous example to match the URL of the server where tang is installed. The secret.jwe output file contains your encrypted cipher text in the JSON Web Encryption format. This cipher text is read from the input-plain.txt input file.

    Alternatively, if your configuration requires a non-interactive communication with a Tang server without SSH access, you can download an advertisement and save it to a file:

    $ curl -sfg http://tang.srv:port/adv -o adv.jws

    Use the advertisement in the adv.jws file for any following tasks, such as encryption of files or messages:

    $ echo 'hello' | clevis encrypt tang '{"url":"http://tang.srv:port","adv":"adv.jws"}'
  2. To decrypt data, use the clevis decrypt command and provide the cipher text (JWE):

    $ clevis decrypt < secret.jwe > output-plain.txt

Additional resources

  • For a quick reference, see the clevis-encrypt-tang(1) man page or use the built-in CLI help:

    $ clevis
    $ clevis decrypt
    $ clevis encrypt tang
    Usage: clevis encrypt tang CONFIG < PLAINTEXT > JWE
    ...
  • For more information, see the following man pages:

    • clevis(1)
    • clevis-luks-unlockers(7)

9.6. Deploying an encryption client with a TPM 2.0 policy

The following procedure contains steps to configure automated unlocking of an encrypted volume with a Trusted Platform Module 2.0 (TPM 2.0) policy.

Prerequisites

Procedure

  1. To deploy a client that encrypts using a TPM 2.0 chip, use the clevis encrypt tpm2 sub-command with the only argument in form of the JSON configuration object:

    $ clevis encrypt tpm2 '{}' < input-plain.txt > secret.jwe

    To choose a different hierarchy, hash, and key algorithms, specify configuration properties, for example:

    $ clevis encrypt tpm2 '{"hash":"sha1","key":"rsa"}' < input-plain.txt > secret.jwe
  2. To decrypt the data, provide the ciphertext in the JSON Web Encryption (JWE) format:

    $ clevis decrypt < secret.jwe > output-plain.txt

The pin also supports sealing data to a Platform Configuration Registers (PCR) state. That way, the data can only be unsealed if the PCRs hashes values match the policy used when sealing.

For example, to seal the data to the PCR with index 0 and 1 for the SHA-1 bank:

$ clevis encrypt tpm2 '{"pcr_bank":"sha1","pcr_ids":"0,1"}' < input-plain.txt > secret.jwe

Additional resources

  • For more information and the list of possible configuration properties, see the clevis-encrypt-tpm2(1) man page.

9.7. Configuring manual enrollment of LUKS-encrypted root volumes

Use the following steps to configure unlocking of LUKS-encrypted root volumes with NBDE.

Prerequisite

  • A Tang server is running and available.

Procedure

  1. To automatically unlock an existing LUKS-encrypted root volume, install the clevis-luks subpackage:

    # yum install clevis-luks
  2. Identify the LUKS-encrypted volume for PBD. In the following example, the block device is referred as /dev/sda2:

    # lsblk
    NAME                                          MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
    sda                                             8:0    0    12G  0 disk
    ├─sda1                                          8:1    0     1G  0 part  /boot
    └─sda2                                          8:2    0    11G  0 part
      └─luks-40e20552-2ade-4954-9d56-565aa7994fb6 253:0    0    11G  0 crypt
        ├─rhel-root                               253:0    0   9.8G  0 lvm   /
        └─rhel-swap                               253:1    0   1.2G  0 lvm   [SWAP]
  3. Bind the volume to a Tang server using the clevis luks bind command:

    # clevis luks bind -d /dev/sda2 tang '{"url":"http://tang.srv"}'
    The advertisement contains the following signing keys:
    
    _OsIk0T-E2l6qjfdDiwVmidoZjA
    
    Do you wish to trust these keys? [ynYN] y
    You are about to initialize a LUKS device for metadata storage.
    Attempting to initialize it may result in data loss if data was
    already written into the LUKS header gap in a different format.
    A backup is advised before initialization is performed.
    
    Do you wish to initialize /dev/sda2? [yn] y
    Enter existing LUKS password:

    This command performs four steps:

    1. Creates a new key with the same entropy as the LUKS master key.
    2. Encrypts the new key with Clevis.
    3. Stores the Clevis JWE object in the LUKS2 header token or uses LUKSMeta if the non-default LUKS1 header is used.
    4. Enables the new key for use with LUKS.

      Note

      The binding procedure assumes that there is at least one free LUKS password slot. The clevis luks bind command takes one of the slots.

  4. The volume can now be unlocked with your existing password as well as with the Clevis policy.
  5. To enable the early boot system to process the disk binding, enter the following commands on an already installed system:

    # yum install clevis-dracut
    # dracut -fv --regenerate-all

Verification steps

  1. To verify that the Clevis JWE object is successfully placed in a LUKS2 header token, use the cryptsetup luksDump command:

    # cryptsetup luksDump /dev/sda2
    Tokens:
      0: clevis
        Keyslot:  1
  2. In the case of a LUKS1 header, use the luksmeta show command:

    # luksmeta show -d /dev/sda2
    0   active empty
    1   active cb6e8904-81ff-40da-a84a-07ab9ab5715e
    2 inactive empty
    3 inactive empty
    4 inactive empty
    5 inactive empty
    6 inactive empty
    7 inactive empty
Important

To use NBDE for clients with static IP configuration (without DHCP), pass your network configuration to the dracut tool manually, for example:

# dracut -fv --regenerate-all --kernel-cmdline "ip=192.0.2.10::192.0.2.1:255.255.255.0::ens3:none:192.0.2.45"

Alternatively, create a .conf file in the /etc/dracut.conf.d/ directory with the static network information. For example:

# cat /etc/dracut.conf.d/static_ip.conf
kernel_cmdline="ip=192.0.2.10::192.0.2.1:255.255.255.0::ens3:none:192.0.2.45"

Regenerate the initial RAM disk image:

# dracut -fv --regenerate-all

Additional resources

For more information, see the following man pages:

  • clevis-luks-bind(1)
  • dracut.cmdline(7)

9.8. Configuring automated enrollment of LUKS-encrypted root volumes using Kickstart

Follow the steps in this procedure to configure an automated installation process that uses Clevis for enrollment of LUKS-encrypted root volumes.

Procedure

  1. Instruct Kickstart to partition the disk such that the root partition has enabled LUKS encryption with a temporary password. The password is temporary for the enrollment process.

    part /boot --fstype="xfs" --ondisk=vda --size=256
    part / --fstype="xfs" --ondisk=vda --grow --encrypted --passphrase=temppass
  2. Install the related Clevis packages by listing them in the %packages section:

    %packages
    clevis-dracut
    %end
  3. Call clevis luks bind to perform binding in the %post section. Afterward, remove the temporary password:

    %post
    clevis luks bind -f -k- -d /dev/vda2 \
    tang '{"url":"http://tang.srv","thp":"_OsIk0T-E2l6qjfdDiwVmidoZjA"}' \ <<< "temppass"
    cryptsetup luksRemoveKey /dev/vda2 <<< "temppass"
    %end

    In the above example, note that we specify the thumbprint that we trust on the Tang server as part of our binding configuration, enabling binding to be completely non-interactive.

    Warning

    The cryptsetup luksRemoveKey command prevents any further administration of a LUKS2 device on which you apply it. You can recover a removed master key using the dmsetup command only for LUKS1 devices.

You can use an analogous procedure when using a TPM 2.0 policy instead of a Tang server.

Additional resources

9.9. Configuring automated unlocking of a LUKS-encrypted removable storage device

Use this procedure to set up an automated unlocking process of a LUKS-encrypted USB storage device.

Procedure

  1. To automatically unlock a LUKS-encrypted removable storage device, such as a USB drive, install the clevis-udisks2 package:

    # yum install clevis-udisks2
  2. Reboot the system, and then perform the binding step using the clevis luks bind command as described in Configuring manual enrollment of LUKS-encrypted root volumes, for example:

    # clevis luks bind -d /dev/sdb1 tang '{"url":"http://tang.srv"}'
  3. The LUKS-encrypted removable device can be now unlocked automatically in your GNOME desktop session. The device bound to a Clevis policy can be also unlocked by the clevis luks unlock command:

    # clevis luks unlock -d /dev/sdb1

You can use an analogous procedure when using a TPM 2.0 policy instead of a Tang server.

Additional resources

For more information, see the following man page:

  • clevis-luks-unlockers(7)

9.10. Configuring automated unlocking of LUKS-encrypted non-root volumes at boot time

Perform the following steps to configure NBDE for unlocking LUKS-encrypted non-root volumes when the system starts.

Prerequisite

  • A Tang server is running and available.

Procedure

  1. Install the clevis-systemd and clevis-luks subpackages:

    # yum install clevis-systemd clevis-luks
  2. Enable the Clevis unlocker service:

    # systemctl enable clevis-luks-askpass.path
    Created symlink from /etc/systemd/system/remote-fs.target.wants/clevis-luks-askpass.path to /usr/lib/systemd/system/clevis-luks-askpass.path.
  3. Bind a LUKS-encrypted non-root volume to a Tang server using the clevis luks bind command. In the following example, the block device is referred as /dev/sda5:

    # clevis luks bind -d /dev/sda5 tang '{"url":"http://tang.srv"}'
    ...
    Do you wish to trust these keys? [ynYN] y
    ...
    Do you wish to initialize /dev/sda5? [yn] y
    Enter existing LUKS password:
  4. To set up the encrypted block device during system boot, add the corresponding line with the _netdev option to the /etc/crypttab configuration file.
  5. Add the volume to the list of accessible filesystems in the /etc/fstab file. Use the _netdev option in this configuration file, too.

Additional resources

For more information, see the following man pages:

  • clevis-luks-unlockers(7)
  • crypttab(5)
  • fstab(5)

9.11. Deployment of virtual machines in a NBDE network

The clevis luks bind command does not change the LUKS master key. This implies that if you create a LUKS-encrypted image for use in a virtual machine or cloud environment, all the instances that run this image will share a master key. This is extremely insecure and should be avoided at all times.

This is not a limitation of Clevis but a design principle of LUKS. If you wish to have encrypted root volumes in a cloud, you need to make sure that you perform the installation process (usually using Kickstart) for each instance of Red Hat Enterprise Linux in a cloud as well. The images cannot be shared without also sharing a LUKS master key.

If you intend to deploy automated unlocking in a virtualized environment, Red Hat strongly recommends that you use systems such as lorax or virt-install together with a Kickstart file (see Configuring automated enrollment of LUKS-encrypted root volumes using Kickstart) or another automated provisioning tool to ensure that each encrypted VM has a unique master key.

Note that automated unlocking with a TPM 2.0 policy is not supported in a virtual machine.

Additional resources

For more information, see the following man page:

  • clevis-luks-bind(1)

9.12. Building automatically-enrollable VM images for cloud environments using NBDE

Deploying automatically-enrollable encrypted images in a cloud environment can provide a unique set of challenges. Like other virtualization environments, it is recommended to reduce the number of instances started from a single image to avoid sharing the LUKS master key.

Therefore, the best practice is to create customized images that are not shared in any public repository and that provide a base for the deployment of a limited amount of instances. The exact number of instances to create should be defined by deployment’s security policies and based on the risk tolerance associated with the LUKS master key attack vector.

To build LUKS-enabled automated deployments, systems such as Lorax or virt-install together with a Kickstart file should be used to ensure master key uniqueness during the image building process.

Cloud environments enable two Tang server deployment options which we consider here. First, the Tang server can be deployed within the cloud environment itself. Second, the Tang server can be deployed outside of the cloud on independent infrastructure with a VPN link between the two infrastructures.

Deploying Tang natively in the cloud does allow for easy deployment. However, given that it shares infrastructure with the data persistence layer of ciphertext of other systems, it may be possible for both the Tang server’s private key and the Clevis metadata to be stored on the same physical disk. Access to this physical disk permits a full compromise of the ciphertext data.

Important

For this reason, Red Hat strongly recommends maintaining a physical separation between the location where the data is stored and the system where Tang is running. This separation between the cloud and the Tang server ensures that the Tang server’s private key cannot be accidentally combined with the Clevis metadata. It also provides local control of the Tang server if the cloud infrastructure is at risk.