|
|
Subscribe / Log in / New account

Per-extent encrypted keys for fscrypt

By Jonathan Corbet
January 5, 2023
The kernel's fscrypt subsystem enables filesystems to store files and directories in encrypted form, protecting them against offline attacks. A few filesystems support encryption with fscrypt currently, but Btrfs is an exception, despite a number of attempts to add this feature. The problem is that, as so often seems to be the case, Btrfs works differently and does not fit well with one of the key assumptions in the design of fscrypt. With this patch series, Sweet Tea Dorminy is working to enhance fscrypt to be a better fit for filesystems like Btrfs.

Fscrypt got its start in 2015 as an ext4-specific encryption feature, but it was later generalized to be able to support other filesystems as well, with the second user being F2FS. To enable encryption, an administrator must start with an empty directory (which can be the root directory ) on a filesystem and set a "master key" for that directory, after which all files and subdirectories created below the top-level directory will be encrypted. To be able to access the contents of that directory, the master key must be stored in the kernel's keyring. One master key can be used with multiple directory hierarchies, or different keys can be used with different hierarchies as needed.

Each file within a filesystem has its own encryption key separate from the master key; this is needed to prevent two identical (plain-text) files from having the same encrypted representation. That key is stored with the file's inode data and can only be decrypted using the master key associated with the directory hierarchy. The result is secure encryption of the directory tree, which will be inaccessible in the absence of the master key. That should prevent access to the data in an offline attack, but will not prevent access from a compromised system where the master key is present.

Btrfs is, of course, a copy-on-write filesystem, and many of its features depend on that functionality. A filesystem snapshot, for example, is simply a second reference to the filesystem itself, sharing all data between both "copies". If a given file is written to after the snapshot is made, the affected extents of that file will be copied before modification, leaving the snapshot unchanged. Extents can also be explicitly shared between files using the Btrfs "reflink" functionality which, despite numerous attempts to upstream a reflink() system call, is currently implemented as a pair of ioctl() calls.

This sharing is efficient in terms of storage space, but it creates an interesting problem when fscrypt enters the picture: if an extent is shared between two files, which key should be used to encrypt its data? Those two files will have different keys, after all. One might consider adding another layer so that either key would work, but that runs into another difficulty; any solution to this problem will need to avoid adding data to the extent for each file that references it, since the number of such references can grow without bound. So approaches that add multiple keys are not going to work.

The solution that was chosen was to move the encryption key from a file's inode to each extent contained within the file. As any given file is read, the necessary decryption keys are obtained from each extent; the keys can vary from one extent to the next. As a result, a single file can contain data encrypted by multiple keys, and a given encrypted extent can appear in different (encrypted) files. Even different master keys could be used, as long as all of the required keys have been loaded into the kernel keyring.

This mechanism solves the data-sharing problem, and enables some additional interesting use cases. For example, a directory's master key could be changed after a snapshot is made without re-encrypting all of the data contained underneath that directory. New data would, thereafter, be written using the new key. As a result, possession of the master key(s) needed to read the snapshot would not give access to any data created after the snapshot is made. Perhaps more usefully, a system in possession of (only) the current key would be able to write to an encrypted filesystem without being able to read any of the pre-snapshot data. According to this design document for fscrypt support in Btrfs, "this is an important use case for Meta".

A scheme like this will bring some limitations of its own, of course. While it is theoretically possible to load all of the per-extent keys for a file prior to accessing the file, that would be problematic in practice. Files can be large and contain a huge number of extents, which would require the kernel to allocate memory for an equally large number of keys. An attacker who could create a large, highly fragmented file could thus run the kernel out of memory. So keys are loaded as extents are accessed; this works — as long as the master keys needed to obtain each per-extent key are all present. Otherwise, access to a file will fail partway through, which could be a surprising result.

There are also limitations on the sharing of encrypted extents. Perhaps most obviously, it is not possible to reflink an encrypted extent into an unencrypted file. Inline encryption, where the actual encryption and decryption work is offloaded to a suitably capable storage device is also not supported. That is not a fundamental limitation of this approach; Dorminy just hasn't figured out how to implement it yet.

The current patch set does not add fscrypt features to Btrfs; it is, instead, a subset of a larger patch series (first posted in August 2022 and most recently in November) that is focused on the fscrypt changes. It makes sense to put that work out separately, since it may affect filesystems beyond Btrfs. Once this work clears the bar, though, the full Btrfs patch set seems certain to follow quickly.

Index entries for this article
KernelFilesystems/Btrfs
KernelSecurity/Filesystem encryption


to post comments

Per-extent encrypted keys for fscrypt

Posted Jan 6, 2023 1:44 UTC (Fri) by xecycle (subscriber, #140261) [Link] (1 responses)

Sounds like this could benefit XFS as well? Feeling it a bit interesting to see our good old XFS still getting modern features quickly. If we could reuse the overlay code to add some sort of point-in-time FS-level snapshot to XFS then I'd say it'll become my personal favorite choice :)

Per-extent encrypted keys for fscrypt

Posted Jan 6, 2023 6:07 UTC (Fri) by hsiangkao (guest, #123981) [Link]

+1 for XFS, I also think chunk-based EROFS later can benefit from it as well if it has more progresses.


Copyright © 2023, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds