LUKS Integration - npmccallum/deo GitHub Wiki

Background

Before reading this page, please read the Key Acquisition Methods page to understand the problem set. Importantly, all acquisition methods require a place to store metadata. For the password method, this is the slots used to store the encrypted volume key. Other methods will need to store other metadata.

As part of a long conversation about how to store more generic metadata in LUKS, several methods for dealing with the generic metadata storage problem arose.

Integrating with LUKS

Don't Store Extra Metadata: Use UUID

One method proposed was to use the LUKS volume UUID as the secret identifier. UUIDs provide ~128 bits of entropy (slightly less due to formatting constraints). This method has the advantage that the UUID is already stored in the LUKS header.

One minor drawback of this proposal is that an attacker which is able to access the disk header can spoof itself to the third party. However, if the third party is sufficiently protected (for instance by network access restrictions or physical proximity restrictions), this risk is somewhat mitigated.

Unfortunately, the UUID also has the significant drawback that it is not actually a secret. Even if access to the on-disk header is precluded, the UUID is listed by the Linux kernel in the /dev tree and is readable by all local users. Further, the UUID field has pre-existed its use as a secret and thus the potential exists that the UUID is widely known outside the computing system itself (such as in a disk inventory or network monitoring tools). For this reason, the use of UUID for authentication is not suitable.

Store Metadata in the Post-Slot Space

There is an alignment gap in the current LUKS header after the slot space. The size of this space is dependent on the size of the slot space; which is, in turn, dependent on the size of the keys used for encryption. For example:

128bit key =>  508k free space
256bit key => 1020k free space
512bit key =>   28k free space

It appears that after LUKS provisioning, this space is not touched by any tools. However, it is theoretically possible that some tool writes to this space.

Store Metadata in a Slot

Another option is to store the metadata in a password slot itself. Slots for 128, 256 and 512 bit keys have a size of 64k, 128k, 256k (respectively). In this method, we would manually mark the slot as active and write the raw data into the slot space. LUKS tools would see this as an active password slot, but would not be able to successfully retrieve the volume key from the slot since it doesn't actually contain an encrypted volume key. One downside to this approach is that an admin might use cryptsetup to accidentally delete the metadata -- possibly rendering the disk unrecoverable.

Tasks

If we decided to use either a slot or the post-slot gap to store additional metadata, we would need to audit known LUKS utilities to make sure that no writes to this area are performed that could damage our metadata. Further, if a new version of LUKS is defined it will need to account for this storage space and properly migrate the data in this space to the new header format. Further, our key management system will need to learn to parse LUKS manually in order to calculate the offsets and write data into the void.

Additionally, systemd/dracut (and GNOME, KDE, etc.) currently detect the presence of a LUKS volume and attempt to unlock it. When using our management system on top of LUKS, this can never succeed. This represents an unknown set of problems.

Migrate from LUKS to a new Format

In this method, we would create a new-on disk format which contains space for storing the crypto parameters and the acquisition metadata. We would then write a new utility for reading this header and activating dm-crypt. Finally, we would write migration code to migrate to the new format from LUKS.

Although this sounds like a big job, it is actually much smaller considering the following factors. LUKS handles two tasks: key acquisition and passing crypto parameters to dm-crypt. The former of these two tasks is the vast majority of the LUKS code. Since we are essentially writing a parallel key acquisition stack, we are bypassing the vast majority of the LUKS code already. The only data we need from the LUKS header besides acquisition metadata is the crypto parameters; something which could easily be subsumed by the new tool. Further, we have to define a new on-disk format for everything that goes inside the metadata.

In short, we already have to craft a new on-disk format for the metadata. The only data from the LUKS header which would not be duplicated is the crypto parameters, which are exceedingly small.

There are some other advantages to this approach. First, we don't have to learn to speak LUKS directly. Only the migration code needs to understand LUKS sufficiently enough to extract the crypto parameters and the volume key: something that can be done with libcryptsetup directly. Second, LUKS can continue to operate exactly as it already does: we don't have to worry about breaking existing LUKS setups and we don't have to handle the migration of metadata stored in strange places in the LUKS header.

To summarize this proposal: make a new disk format for our new key management system. Users who want to use it can migrate from LUKS using a tool we provide which uses libcryptsetup. Users who want to continue using LUKS do so without any interaction. Higher-level integration (systemd, GNOME, KDE, etc.) with LUKS continues unabated.