Managing encrypted storage is a crucial aspect of data security. Normally, this involves manually entering passphrases during system boot, a process that can be cumbersome, especially in environments with numerous systems or in automated deployment scenarios.
This is where Network-Bound Disk Encryption (NBDE), a framework for automated decryption, provides a flexible and powerful solution.
Clevis software, which is the client in NBDE client/server architecture that can function in standalone mode, works by binding encrypted devices, such as LUKS-encrypted volumes, to various pins. These pins are essentially plug-ins that handle the decryption process based on different criteria. While commonly known pins include those for Tang (network-based decryption) and TPM2 (Trusted Platform Module), the PKCS #11 pin offers a robust alternative for leveraging hardware security.
What is the Clevis PKCS #11 pin?
The Clevis PKCS #11 pin is a recently developed plug-in that enables the automated unlocking of encrypted devices using a PKCS #11 compatible device.
PKCS #11 is a standard API defining how to interact with cryptographic tokens, such as smart cards, hardware modules, or even software-based keystores that expose a PKCS #11 interface.
Essentially, when PKCS #11 pin is used through Clevis, the decryption key for your volume is entrusted to a secure hardware device. This device is typically protected by a Personal Identity Number (PIN).
How the PKCS #11 pin works
When a LUKS volume is bound using the Clevis PKCS #11 pin, the process involves different steps:
- Key generation: Clevis generates a unique, random key specifically for this binding. This key is not the LUKS master key itself but will be used to unlock the LUKS volume via a dedicated LUKS key slot.
- Hardware-protected encryption: Clevis then encrypts this random key using a public key that corresponds to a private key securely held within the designated PKCS #11 device.
- Binding information storage: The encrypted random key, along with a PKCS #11 Uniform Resource Identifier (URI) that identifies the required hardware token and the specific key object within it, is stored in a dedicated Clevis binding within the LUKS header of the encrypted volume. The PKCS #11 URI scheme provides a standardized way for Clevis to locate and interact with the appropriate cryptographic token and its corresponding objects.
- Automated decryption at boot time: During the system boot process, Clevis scans bound LUKS volumes, including those configured with the PKCS #11 pin.
- PKCS #11 interaction: Clevis uses the stored PKCS #11 URI to locate the required hardware token and initiates a cryptographic operation with the device to decrypt the stored encrypted key.
- PIN verification: For most PKCS #11 devices configured for user-based access, this decryption operation requires authentication, typically in the form of a PIN. Clevis will usually prompt the user for this PIN during the boot process. Once the correct PIN is provided (or if the PIN is configured to be automatically used in less secure configurations), the PKCS #11 device uses its secure private key to decrypt the random key.
- LUKS unlocking: Clevis receives the decrypted random key and uses it to unlock the corresponding key slot in the LUKS volume header, thereby decrypting the entire volume.
This entire process, from identifying the binding to unlocking the LUKS volume, is automated by Clevis after the initial PIN entry (when required).
Advantages of PKCS #11 Clevis pin
Integrating PKCS #11 devices with Clevis for automated decryption provides three significant advantages:
- Robust key protection: The primary benefit is the enhanced security of housing decryption keys within hardware tokens. Unlike software-based keys that can be vulnerable to various operating system-level attacks (like memory scraping or cold boot attacks if not properly mitigated), keys within a PKCS #11 device are protected by the hardware's physical and logical security measures. The private key material never leaves the secure boundary of the device during cryptographic operations.
- Stronger authentication: Requiring a PIN or other form of authentication to access the key on the PKCS #11 device adds an additional layer of security beyond just possessing the physical token.
- Flexibility in unlocking policies: Clevis's design allows for combining multiple pins through its SSS pin. This means that, for example, system boot process could require both a PKCS #11 device and a Tang server to be available for a volume to unlock, creating a multi-factor authentication policy for disk decryption.
Binding Clevis to a PKCS #11 device
Configuring Clevis to use a PKCS #11 device involves binding a LUKS-encrypted volume to the pkcs11
pin, primarily through a PKCS #11 URI. An important aspect of this configuration is how Clevis handles the PIN required to access the key on the PKCS #11 device.
There are two primary methods for Clevis to obtain the PKCS #11 PIN:
- Providing the PIN at boot time: This is the recommended and most secure approach. Clevis will detect the bound PKCS #11 device during the boot process and interactively prompt the user to enter the PIN. Clevis will re-prompt if the PIN is incorrect. Users should be aware of the potential for the device to lock or become unusable after multiple incorrect PIN attempts, depending on the device's policy.
- Providing the PIN at Clevis configuration time: Clevis can be configured to store the PIN value directly within its binding configuration. Although this automates the unlocking process completely, it significantly weakens the security provided by the hardware token, as the PIN is stored on the system's storage. This method is generally not recommended for production environments.
The PKCS #11 standard defines a URI scheme to uniquely identify PKCS #11 modules, tokens, and objects. This URI is central to configuring the Clevis PKCS #11 pin. The URI can include parameters, including pin-value, though its use for storing the PIN is discouraged for security reasons.
Installation and basic configuration
For Clevis to work appropriately it uses the pkcs11-tool
command, which is part of the opensc package. Both will be installed as dependencies of clevis-pin-pkcs11
package. To get started with the Clevis PKCS #11 pin in the Red Hat Enterprise Linux (RHEL) operating system, follow these general steps:
Install the
clevis-pin-pkcs11
package:$ sudo dnf install clevis-pin-pkcs11
Ensure your PKCS #11 device is recognized by the system and accessible via
pkcs11-tool
:$ pkcs11-tool -L Available slots: Slot 0 (0x0): Yubico YubiKey OTP+CCID 00 00 token label : clevis token manufacturer : piv_II token model : PKCS#15 emulated token flags : login required, rng, token initialized, PIN initialized hardware version : 0.0 firmware version : 0.0 serial num : b213f7d0876fd4c4 pin min/max : 4/8 uri : pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=b213f7d0876fd4c4;token=clevis
The previous command should list your available slots and tokens, including their URIs.
Bind your LUKS-encrypted volume to the
pkcs11
pin usingclevis luks bind
, providing the appropriate URI in the JSON configuration:$ sudo clevis luks bind -d /dev/sda5 pkcs11 '{"uri":"pkcs11:"}'
Or, if a specific module is needed:
$ sudo clevis luks bind -d /dev/sda5 pkcs11 '{"uri":"pkcs11:module-path=/usr/lib64/libykcs11.so.2"}'
Enable the systemd socket unit that allows Clevis to receive the PIN securely during boot.
$ sudo systemctl enable --now clevis-luks-pkcs11-askpass.socket
Modify the
/etc/crypttab
file for your LUKS volume to use the Clevis PKCS #11 socket as the key file. This prevents the system from prompting on the console and instead directs the key request to Clevis. Set a keyfile-timeout for a fallback to manual passphrase entry if automated unlocking fails:$ sudo diff -Nuar /etc/crypttab.ori /etc/crypttab --- /etc/crypttab.ori YYYY-MM-DD HH:MM:SS.SSSSSSSSS +ZZZZ +++ /etc/crypttab YYYY-MM-DD HH:MM:SS.SSSSSSSSS +ZZZZ @@ -1 +1,2 @@ -luks-<your_UUID> UUID=<your_UUID> - - +luks-<your_UUID> UUID=<your_UUID> /run/systemd/clevis-pkcs11.sock keyfile-timeout=30s
Replace <your_UUID> with the actual UUID of your LUKS volume.
The
clevis encrypt
andclevis decrypt
commands can be used with thepkcs11
pin. For testing purposes only, you might include the pin-value in the URI. Remember, storing the PIN in the production binding is insecure:$ echo "top secret" | clevis encrypt pkcs11 '{"uri":"pkcs11:module-path=/usr/lib64/libykcs11.so.2?pin-value=<your_PKCS_#11_PIN>"}' | clevis decrypt
Replace <your_PKCS_#11_PIN> with the correct PIN for your PKCS #11 device. If configured correctly, the previous command should output the "top secret" string.
For encrypted root file systems, use the dracut tool to load required Clevis modules to initrd:
$ sudo dracut -f
- Reboot your system. Clevis should detect the bound PKCS #11 pin, prompt for the PIN (if not stored), and unlock the encrypted volume automatically upon successful authentication.
Handling multiple PKCS #11 devices
In environments with multiple PKCS #11 devices, it's crucial to bind Clevis to the correct device. Relying solely on the slot-id in the URI is generally discouraged, because slot IDs can change depending on how modules are initialized or devices are connected.
More reliable methods for distinguishing devices include the following:
Use a detailed Public Key Object URI (recommended): With recent versions of the
pkcs11-tool
(like those included with OpenSC 0.26.0 and later), detailed URIs for tokens and objects can be listed. The recommended approach is to identify the specific public key object that Clevis will use and include its full URI in the binding configuration. You can find these URIs by using thepkcs11-tool -L
andpkcs11-tool -O
commands:$ pkcs11-tool -L | grep uri $ pkcs11-tool -O --slot-index 1 --type pubkey | grep uri uri:pkcs11:model=PKCS%2315%20emulated;manufacturer=OpenPGP%20project;serial=000f06080f4f;token=OpenPGP%20card%20%28User%20PIN%29;id=%03;object=Authentication%20key;type=public
Then, use the resulting URI in the
clevis bind
command:$ sudo clevis luks bind -d /dev/sda pkcs11 '{"uri":"pkcs11:model=PKCS%2315%20emulated;manufacturer=OpenPGP%20project;serial=000f06080f4f;token=OpenPGP%20card%20%28User%20PIN%29;id=%03;object=Authentication%20key;type=public"}'
If a specific module path is needed, include it in the URI:
$ sudo clevis luks bind -d /dev/sda pkcs11 '{"uri":"pkcs11:model=YubiKey%20YK5;manufacturer=Yubico;serial=28083311;token=YubiKey%20PIV%20%2328083311;id=%03;object=Public%20key%20for%20Key%20Management;type=public;module-path=/usr/lib64/libykcs11.so"}'
Multi-device configuration with serial plus token specification: For older versions of
pkcs11-tool
that do not provide detailed object URIs, you can attempt to identify the device using a combination of its serial number and token label. Including the model can also help Clevis provide more informative prompts when asking for the PIN:$ pkcs11-tool -L | grep "token label\|serial" … serial=000f06080f4f token=OpenPGP%20card%20%28User%20PIN%29 … $ sudo clevis luks bind -d /dev/sda pkcs11 '{"uri":"pkcs11:model=PKCS%2315%20emulated;serial=000f06080f4f;token=OpenPGP%20card%20%28User%20PIN%29"}'
Additional configuration examples
Here are some additional examples of how to specify the PKCS #11 device using the URI:
Specifying a concrete PKCS #11 device and key: A detailed URI that identifies the device by attributes like model, manufacturer, serial number, token label, and the specific key object using its ID or label can be provided. This is the most precise method when multiple devices or keys are present:
$ sudo clevis luks bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=0a35ba26b062b9c5;token=clevis;id=%02;object=Encryption%20Key"}'
Note:
Special characters in the URI, like #, must be percent-encoded, e.g., %23 for # and %20 for spaces, as defined in RFC 7512.
Binding to the first found PKCS #11 device: Providing an empty URI tells Clevis to bind to the first accessible PKCS #11 device it finds. In this case, Clevis will prompt you to select from the available keys on that token to avoid binding to an unintended key:
$ sudo clevis luks bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:"}'
A shorter, equivalent command is:
$ sudo clevis luks bind -d /dev/sda1 pkcs11 '{}'
Providing a module path: If a PKCS #11 device requires a specific module library not automatically detected by the system's PKCS #11 stack, the module path can be specified within the URI using the module-path parameter. This is typically an advanced option only needed for certain hardware:
$ sudo clevis luks bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:model=PKCS%2315%20emulated;manufacturer=piv_II;serial=0a35ba26b062b9c5;token=clevis;id=%02;object=Encryption%20Key?module-path=/usr/local/lib64/libmypkcs11.so"}'
Once bound, Clevis bindings can be verified on a LUKS device using the
clevis luks list
command:$ sudo clevis luks list -d /dev/sda1 '{"uri": "pkcs11:"}'
As observed, the previous command will output details about the pins bound to the specified device, including the configuration JSON for the PKCS #11 pin.
Wrap up
The Clevis PKCS #11 pin offers a secure mechanism for automating the unlocking of LUKS-encrypted volumes by integrating with PKCS #11-compatible devices. By leveraging the PKCS #11 standard, Clevis provides a robust key protection and helps accomplish compliance requirements. While careful consideration must be given to PIN management and device identification, the Clevis PKCS #11 pin provides a valuable tool for enhancing operational efficiency of systems relying on disk encryption.
For more information, refer to these resources:
Last updated: August 1, 2025