From: Eric Biggers <ebiggers@xxxxxxxxxx> Hello, This patchset solves multiple interrelated problems with how filesystem encryption keys are managed (for ext4, f2fs, and ubifs), including: (1) There is a visibility mismatch between the filesystem/VFS "view" of encrypted files (which is global) and the process-subscribed keyrings (which are not global). Relying on process-subscribed keyrings to provide the encryption keys on-demand makes it quite difficult to support even simple things like running 'sudo', if encrypted files need to be accessed. (2) There is no API to securely remove an encryption key, which should wipe all secret keys from memory and revert the encrypted files to their ciphertext "view". Many users want this, even to the extent that they're already working around it using the very bad hack of 'echo 2 > /proc/sys/vm/drop_caches', or alternatively hacking in an ioctl to drop caches for a specific filesystem. (3) The key derivation function (KDF) used to derive the per-file encryption keys is nonstandard and has a number of problems, such as being trivially reversible. We've wanted to replace it for some time now. (4) There is no verification that the correct master key was supplied. This is actually a security vulnerability, as it allows malicious local users to associate the wrong key with files to which they have *read-only* access. This patchset is based loosely on my earlier patchset "fscrypt: key verification and KDF improvement". However, while the earlier patchset solved problems (3) and (4) above, it ignored (1) and (2). Consequently, it ended up with a solution which probably would have had to be reworked when we also solved (1) and (2). For example, the 'key_hash' field was hacked on to the existing on-disk format just to solve (4), but really we need it a different way to solve (1) and (2) as well, at least for non-root users. There was also a filesystem-level key cache hacked on for caching the HMAC transforms for HKDF, but really it should be a real keyring which you can add and remove keys from, as we need that anyway for (1) and (2). By considering all the problems together we end up with a solution which should be simpler in the end, notwithstanding the length of this patchset. This patchset is organized as follows: - Patches 1-6 introduce a filesystem-level crypto keyring and a new ioctl, FS_IOC_ADD_ENCRYPTION_KEY, which adds a master encryption key to it. This solves problem (1) above, though initially only for use cases where a privileged process sets up the keys. Patch 20 will make it unprivileged in some cases. - Patches 7-10 add a new ioctl, FS_IOC_REMOVE_ENCRYPTION_KEY, which removes a master encryption key from the filesystem-level crypto keyring. It also evicts the inodes which had been "unlocked" using the key. This solves problem (2) above, though initially only for use cases where a privileged process sets up the keys. Patch 20 will make it unprivileged in some cases. - Patch 11 adds an ioctl FS_IOC_GET_ENCRYPTION_KEY_STATUS which retrieves the status of a key in the filesystem-level crypto keyring. - Patches 12-14 wire up the above ioctls to ext4, f2fs, and ubifs. - Patches 15-25 introduce a new encryption policy version ("v2") where master_key_descriptor is replaced with master_key_identifier, which is a cryptographic hash of the master key. This allows opening the FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY ioctls up to non-root users. In turn, this avoids any need to rely on the process-subscribed keyrings and encounter their visibility problems, and it allows non-root users to securely remove their encryption keys. I also take the opportunity to replace the AES-ECB-based KDF with HKDF-SHA512, which is also used to compute the master_key_identifier so that we pass the master key into only a single cryptographic primitive. Note that patches 1-14 can be reviewed (and potentially even merged) on their own, without patches 15-25. At just that point, the ioctls to manage filesystem-level keys will be usable for existing encrypted files, for privileged users only. However, to understand some of the decisions made when designing the ioctls, it will be helpful to see how the later patches extend the ioctls to also be usable for v2 encryption policies and by unprivileged users. Please review all API and on-disk format changes carefully, as we will be locked into them once merged. You can also get this patchset from git at: Repository: https://github.com/ebiggers/linux.git Branch: fscrypt-v2-policy-and-api_v1 It has received light testing. I've also made proof-of-concept changes to the 'fscrypt' userspace program to make it support v2 encryption policies and the filesystem-level keyring. You can find those userspace changes in git at: Repository: https://github.com/ebiggers/fscrypt.git Branch: v2-policy-support To make the 'fscrypt' userspace program use v2 policies for new encrypted directories, add "policy_version": "2" to /etc/fscrypt.conf within the "options" section. (Again: for now please consider the userspace changes proof-of-concept quality only! So far I've been focusing on the kernel changes.) It's intended that the other major users of filesystem-level encryption, including the Android and Chromium OS key management systems, will switch to the new API and encryption policy version as well. Eric Biggers (25): fs, fscrypt: move uapi definitions to new header <linux/fscrypt.h> fscrypt: use FSCRYPT_ prefix for uapi constants fscrypt: use FSCRYPT_* definitions, not FS_* fscrypt: refactor finding and deriving key fs: add ->s_master_keys to struct super_block fscrypt: add FS_IOC_ADD_ENCRYPTION_KEY ioctl fs/inode.c: export inode_lru_list_del() fs/inode.c: rename and export dispose_list() fs/dcache.c: add shrink_dcache_inode() fscrypt: add FS_IOC_REMOVE_ENCRYPTION_KEY ioctl fscrypt: add FS_IOC_GET_ENCRYPTION_KEY_STATUS ioctl ext4 crypto: wire up new ioctls for managing encryption keys f2fs crypto: wire up new ioctls for managing encryption keys ubifs crypto: wire up new ioctls for managing encryption keys fscrypt: add UAPI definitions to get/set v2 encryption policies fscrypt: implement basic handling of v2 encryption policies fscrypt: add an HKDF-SHA512 implementation fscrypt: allow adding and removing keys for v2 encryption policies fscrypt: use HKDF-SHA512 to derive the per-file keys for v2 policies fscrypt: allow unprivileged users to add/remove keys for v2 policies fscrypt: require that key be added when setting a v2 encryption policy ext4 crypto: wire up FS_IOC_GET_ENCRYPTION_POLICY_EX f2fs crypto: wire up FS_IOC_GET_ENCRYPTION_POLICY_EX ubifs crypto: wire up FS_IOC_GET_ENCRYPTION_POLICY_EX fscrypt: document the new ioctls and policy version Documentation/filesystems/fscrypt.rst | 575 ++++++++++-- fs/crypto/Kconfig | 2 + fs/crypto/crypto.c | 19 +- fs/crypto/fname.c | 4 +- fs/crypto/fscrypt_private.h | 196 +++- fs/crypto/keyinfo.c | 1619 ++++++++++++++++++++++++++++++--- fs/crypto/policy.c | 373 +++++--- fs/dcache.c | 33 + fs/ext4/ioctl.c | 22 + fs/f2fs/file.c | 21 +- fs/inode.c | 24 +- fs/super.c | 3 + fs/ubifs/ioctl.c | 24 +- include/linux/dcache.h | 1 + include/linux/fs.h | 6 + include/linux/fscrypt.h | 12 +- include/linux/fscrypt_notsupp.h | 23 + include/linux/fscrypt_supp.h | 4 + include/uapi/linux/fs.h | 50 +- include/uapi/linux/fscrypt.h | 159 ++++ 20 files changed, 2724 insertions(+), 446 deletions(-) create mode 100644 include/uapi/linux/fscrypt.h -- 2.15.0.rc0.271.g36b669edcc-goog