Clevis
Automated Encryption Framework
Install / Use
/learn @latchset/ClevisREADME
Clevis
Welcome to Clevis!
Clevis is a pluggable framework for automated decryption. It can be used to provide automated decryption of data or even automated unlocking of LUKS volumes.
Encrypting Data
What does this look like? Well, the first step is encrypting some data. We do this with a simple command:
$ clevis encrypt PIN CONFIG < PLAINTEXT > CIPHERTEXT.jwe
This command takes plaintext on standard input and produces an encrypted JWE object on standard output. Besides the plaintext, we need to specify two additional input parameters.
First, is the pin. In clevis terminology, a pin is a plugin which implements automated decryption. We simply pass the name of a pin here.
Second, is the config. The config is a JSON object which will be passed directly to the pin. It contains all the necessary configuration to perform encryption and setup automated decryption.
To decrypt our JWE, we simply perform the following:
$ clevis decrypt < CIPHERTEXT.jwe > PLAINTEXT
Notice that no additional input or interaction is required for the decrypt command. Let's look at some more concrete examples.
PIN: Tang
Tang is a server implementation which provides cryptographic binding services without the need for an escrow. Clevis has full support for Tang. Here is an example of how to use Clevis with Tang:
$ echo hi | clevis encrypt tang '{"url": "http://tang.local"}' > hi.jwe
The advertisement is signed with the following keys:
kWwirxc5PhkFIH0yE28nc-EvjDY
Do you wish to trust the advertisement? [yN] y
In this example, we encrypt the message "hi" using the Tang pin. The only parameter needed in this case is the URL of the Tang server. During the encryption process, the Tang pin requests the key advertisement from the server and asks you to trust the keys. This works similarly to SSH.
Alternatively, you can manually load the advertisement using the adv
parameter. This parameter takes either a string referencing the file where the
advertisement is stored, or the JSON contents of the advertisement itself. When
the advertisement is specified manually like this, Clevis presumes that the
advertisement is trusted.
PIN: TPM2
Clevis provides support to encrypt a key in a Trusted Platform Module 2.0 (TPM2) chip. The cryptographically-strong, random key used for encryption is encrypted using the TPM2 chip, and is decrypted using TPM2 at the time of decryption to allow clevis to decrypt the secret stored in the JWE.
For example:
$ echo hi | clevis encrypt tpm2 '{}' > hi.jwe
Clevis store the public and private keys of the encrypted key in the JWE object, so those can be fetched on decryption to unseal the key encrypted using the TPM2.
PIN: PKCS#11
Clevis can perform the role of a PKCS#11 application, as described in the RFC 7512: The PKCS#11 URI Scheme.
PKCS#11 protocol determines that a PIN (Personal Identity Number) must be configured into the hardware device so that the unlocking process is successful. Clevis will allow users to unlock a particular encrypted disk, and will provide a way to get the PIN. There will be two possibilities:
1 - Provide the PIN at boot time: In this first case, Clevis will detect PKCS#11 device and will prompt for its PIN. In case PIN is wrong, Clevis will prompt for the PIN again. It is the user's responsibility to be aware of the possible lock / brick of the device in case PIN is unknown.
2 - Provide the PIN at Clevis configuration time: In this second case, Clevis will be configured with the PIN value.
Initially, RFC7512 defines a mechanism to specify a special kind of URI (the pkcs11 URI), that allows identifying both a device and also the information required for it to be unlocked. Special attention deserves the parameters pin-value, which allow specifying the value of the PIN or the location of the PIN respectively. Clevis will understand, initially, the 'pin-value' parameter. Below you can find and example of PKCS#11 URIs using previous parameter:
- PKCS#11 URI with
pin-valuedefined:
pkcs11:token=Software%20PKCS%2311%20softtoken;manufacturer=Snake%20Oil,%20Inc.?pin-value=the-pin
In the next section, Clevis configuration examples are provided, so that it is clarified what are the different options for a PKCS#11 device to be bound to an encrypted disk.
Clevis configuration
Clevis will provide a mechanism for the user to bind a particular PKCS#11 device to an encrypted device. The name of the new pin for Clevis will be pkcs11, and the way to configure it will be the same that is currently used:
$ clevis luks bind -h
Usage: clevis luks bind [-y] [-f] [-s SLT] [-k KEY] [-t TOKEN_ID] [-e EXISTING_TOKEN_ID] -d DEV PIN CFG
Configuration to provide a PKCS#11 URI to Clevis
As first example, a user can provide the information of the device by specifying its URI to Clevis:
$ 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"}'
Configuration to bind Clevis to the first PKCS#11 device found
An additional option is to provide Clevis a configuration so that the first PKCS#11 device found by Clevis is bound. To do so, an empty URI can be provided as shown below:
$ clevis luks bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:"}'
An even shorter configuration command, equivalent to the previous one, is shown below:
$ clevis luks bind -d /dev/sda1 pkcs11 '{}'
In this case, Clevis will be responsible for the detection of the device and, if no device is found, responsible for dumping the corresponding error.
It must be clarified that providing an empty URI will make Clevis to prompt also to select one of the available keys matched on the token to avoid accidentally encryption with unwanted keys.
Configuration to provide a module path to Clevis PKCS#11 pin:
A module path can be provided to Clevis, so that it uses that module to access a device. This is only required in case the card is not supported by underlying Clevis software (OpenSC). For this reason, the module path field is completely optional. To provide the module location the user can provide the "module-path" to the "uri" Clevis configuration:
$ 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"}'
As it happens with the rest of devices, encrypted disks that have been bound to a PKCS#11 device can be checked with clevis luks list command:
$ clevis luks list -d /dev/sda1
1: 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"}'
Configuration to provide PKCS#11 tool a different mechanism
In the first phase of development, Clevis will be used in top of OpenSC to provide PKCS#11 functionality.
OpenSC, and, in particular, pkcs11-tool, provides an option to indicate the mechanism to use for decryption.
For testing purposes, some libraries, such as SoftHSM), don't work with default pkcs11-tool mechanism,
so it is required to provide a particular mechanism to use. For this reason, Clevis can be provided with
the mechanism to use, in case the default one, RSA-PKCS-OAEP, is not valid:
$ clevis luks bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:", "mechanism":"RSA-PKCS"}'
In order to check available mechanisms for a specific token, command pkcs11-tool -M can be used:
$ pkcs11-tool -M
Using slot 0 with a present token (0x0)
Supported mechanisms:
SHA-1, digest
...
SHA512, digest
MD5, digest
...
RSA-PKCS-KEY-PAIR-GEN, keySize={2048,4096}, generate_key_pair
At this time, only RSA mechanisms are supported by Clevis. Due to a limitation of the rest of the algorithms, no other asymmetric cryptographic algorithm can do encryption easily. The ECC supports only signatures and key derivation, but not encryption. The encryption operation can be somehow constructed from the key derivation, but it is not a straightforward operation.
It must be highlighted that the RSA-PKCS mechanism (PKCS#1.5 padding for encryption) is considered to be not secure and it is mostly provided for compatibility, but it is not recommended using it in production.
Multi-device configuration
Clevis will allow specifying the slot where a PKCS#11 device is located through the parameters provided to the URI:
$ clevis luks bind -d /dev/sda1 pkcs11 '{"uri": "pkcs11:slot-id=0"}'
It must be clarified that providing just the slot information will make Clevis to guess one of the available keys matched on the token in the selected slot, which could cause accidentally encryption with unwanted keys. It is not recommended to use slot as device selector, as slot id is a number that is not guaranteed to be stable across PKCS#11 module initializations. However, there are certain libraries and modules that provide stable slot identifiers, so it can be used for these particular cases.
There are two better options to distinguish between different PKCS#11 devices:
1 - Multi-device configuration with public key object (recommended):
With recent versions of OpenSC (from OpenSC 0.26.0 release) onwards, pkcs11-tool, which is used by Clevis to handle most of the PKCS#11 commands, the PKCS#11 URI is dumped for both the tokens and the objects of a particular token:
$ pkcs11-tool -L | grep uri
uri : pkcs11:model=PKCS%2315%20emulated;manufacture
