linux/fs/crypto/keyring.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Filesystem-level keyring for fscrypt
 *
 * Copyright 2019 Google LLC
 */

/*
 * This file implements management of fscrypt master keys in the
 * filesystem-level keyring, including the ioctls:
 *
 * - FS_IOC_ADD_ENCRYPTION_KEY
 * - FS_IOC_REMOVE_ENCRYPTION_KEY
 * - FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS
 * - FS_IOC_GET_ENCRYPTION_KEY_STATUS
 *
 * See the "User API" section of Documentation/filesystems/fscrypt.rst for more
 * information about these ioctls.
 */

#include <asm/unaligned.h>
#include <crypto/skcipher.h>
#include <linux/key-type.h>
#include <linux/random.h>
#include <linux/seq_file.h>

#include "fscrypt_private.h"

/* The master encryption keys for a filesystem (->s_master_keys) */
struct fscrypt_keyring {};

static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret)
{}

static void move_master_key_secret(struct fscrypt_master_key_secret *dst,
				   struct fscrypt_master_key_secret *src)
{}

static void fscrypt_free_master_key(struct rcu_head *head)
{}

void fscrypt_put_master_key(struct fscrypt_master_key *mk)
{}

void fscrypt_put_master_key_activeref(struct super_block *sb,
				      struct fscrypt_master_key *mk)
{}

/*
 * This transitions the key state from present to incompletely removed, and then
 * potentially to absent (depending on whether inodes remain).
 */
static void fscrypt_initiate_key_removal(struct super_block *sb,
					 struct fscrypt_master_key *mk)
{}

static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
{}

static int fscrypt_user_key_instantiate(struct key *key,
					struct key_preparsed_payload *prep)
{}

static void fscrypt_user_key_describe(const struct key *key, struct seq_file *m)
{}

/*
 * Type of key in ->mk_users.  Each key of this type represents a particular
 * user who has added a particular master key.
 *
 * Note that the name of this key type really should be something like
 * ".fscrypt-user" instead of simply ".fscrypt".  But the shorter name is chosen
 * mainly for simplicity of presentation in /proc/keys when read by a non-root
 * user.  And it is expected to be rare that a key is actually added by multiple
 * users, since users should keep their encryption keys confidential.
 */
static struct key_type key_type_fscrypt_user =;

#define FSCRYPT_MK_USERS_DESCRIPTION_SIZE

#define FSCRYPT_MK_USER_DESCRIPTION_SIZE

static void format_mk_users_keyring_description(
			char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
			const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
{}

static void format_mk_user_description(
			char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE],
			const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
{}

/* Create ->s_master_keys if needed.  Synchronized by fscrypt_add_key_mutex. */
static int allocate_filesystem_keyring(struct super_block *sb)
{}

/*
 * Release all encryption keys that have been added to the filesystem, along
 * with the keyring that contains them.
 *
 * This is called at unmount time, after all potentially-encrypted inodes have
 * been evicted.  The filesystem's underlying block device(s) are still
 * available at this time; this is important because after user file accesses
 * have been allowed, this function may need to evict keys from the keyslots of
 * an inline crypto engine, which requires the block device(s).
 */
void fscrypt_destroy_keyring(struct super_block *sb)
{}

static struct hlist_head *
fscrypt_mk_hash_bucket(struct fscrypt_keyring *keyring,
		       const struct fscrypt_key_specifier *mk_spec)
{}

/*
 * Find the specified master key struct in ->s_master_keys and take a structural
 * ref to it.  The structural ref guarantees that the key struct continues to
 * exist, but it does *not* guarantee that ->s_master_keys continues to contain
 * the key struct.  The structural ref needs to be dropped by
 * fscrypt_put_master_key().  Returns NULL if the key struct is not found.
 */
struct fscrypt_master_key *
fscrypt_find_master_key(struct super_block *sb,
			const struct fscrypt_key_specifier *mk_spec)
{}

static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
{}

/*
 * Find the current user's "key" in the master key's ->mk_users.
 * Returns ERR_PTR(-ENOKEY) if not found.
 */
static struct key *find_master_key_user(struct fscrypt_master_key *mk)
{}

/*
 * Give the current user a "key" in ->mk_users.  This charges the user's quota
 * and marks the master key as added by the current user, so that it cannot be
 * removed by another user with the key.  Either ->mk_sem must be held for
 * write, or the master key must be still undergoing initialization.
 */
static int add_master_key_user(struct fscrypt_master_key *mk)
{}

/*
 * Remove the current user's "key" from ->mk_users.
 * ->mk_sem must be held for write.
 *
 * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
 */
static int remove_master_key_user(struct fscrypt_master_key *mk)
{}

/*
 * Allocate a new fscrypt_master_key, transfer the given secret over to it, and
 * insert it into sb->s_master_keys.
 */
static int add_new_master_key(struct super_block *sb,
			      struct fscrypt_master_key_secret *secret,
			      const struct fscrypt_key_specifier *mk_spec)
{}

#define KEY_DEAD

static int add_existing_master_key(struct fscrypt_master_key *mk,
				   struct fscrypt_master_key_secret *secret)
{}

static int do_add_master_key(struct super_block *sb,
			     struct fscrypt_master_key_secret *secret,
			     const struct fscrypt_key_specifier *mk_spec)
{}

static int add_master_key(struct super_block *sb,
			  struct fscrypt_master_key_secret *secret,
			  struct fscrypt_key_specifier *key_spec)
{}

static int fscrypt_provisioning_key_preparse(struct key_preparsed_payload *prep)
{}

static void fscrypt_provisioning_key_free_preparse(
					struct key_preparsed_payload *prep)
{}

static void fscrypt_provisioning_key_describe(const struct key *key,
					      struct seq_file *m)
{}

static void fscrypt_provisioning_key_destroy(struct key *key)
{}

static struct key_type key_type_fscrypt_provisioning =;

/*
 * Retrieve the raw key from the Linux keyring key specified by 'key_id', and
 * store it into 'secret'.
 *
 * The key must be of type "fscrypt-provisioning" and must have the field
 * fscrypt_provisioning_key_payload::type set to 'type', indicating that it's
 * only usable with fscrypt with the particular KDF version identified by
 * 'type'.  We don't use the "logon" key type because there's no way to
 * completely restrict the use of such keys; they can be used by any kernel API
 * that accepts "logon" keys and doesn't require a specific service prefix.
 *
 * The ability to specify the key via Linux keyring key is intended for cases
 * where userspace needs to re-add keys after the filesystem is unmounted and
 * re-mounted.  Most users should just provide the raw key directly instead.
 */
static int get_keyring_key(u32 key_id, u32 type,
			   struct fscrypt_master_key_secret *secret)
{}

/*
 * Add a master encryption key to the filesystem, causing all files which were
 * encrypted with it to appear "unlocked" (decrypted) when accessed.
 *
 * When adding a key for use by v1 encryption policies, this ioctl is
 * privileged, and userspace must provide the 'key_descriptor'.
 *
 * When adding a key for use by v2+ encryption policies, this ioctl is
 * unprivileged.  This is needed, in general, to allow non-root users to use
 * encryption without encountering the visibility problems of process-subscribed
 * keyrings and the inability to properly remove keys.  This works by having
 * each key identified by its cryptographically secure hash --- the
 * 'key_identifier'.  The cryptographic hash ensures that a malicious user
 * cannot add the wrong key for a given identifier.  Furthermore, each added key
 * is charged to the appropriate user's quota for the keyrings service, which
 * prevents a malicious user from adding too many keys.  Finally, we forbid a
 * user from removing a key while other users have added it too, which prevents
 * a user who knows another user's key from causing a denial-of-service by
 * removing it at an inopportune time.  (We tolerate that a user who knows a key
 * can prevent other users from removing it.)
 *
 * For more details, see the "FS_IOC_ADD_ENCRYPTION_KEY" section of
 * Documentation/filesystems/fscrypt.rst.
 */
int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg)
{}
EXPORT_SYMBOL_GPL();

static void
fscrypt_get_test_dummy_secret(struct fscrypt_master_key_secret *secret)
{}

int fscrypt_get_test_dummy_key_identifier(
				u8 key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
{}

/**
 * fscrypt_add_test_dummy_key() - add the test dummy encryption key
 * @sb: the filesystem instance to add the key to
 * @key_spec: the key specifier of the test dummy encryption key
 *
 * Add the key for the test_dummy_encryption mount option to the filesystem.  To
 * prevent misuse of this mount option, a per-boot random key is used instead of
 * a hardcoded one.  This makes it so that any encrypted files created using
 * this option won't be accessible after a reboot.
 *
 * Return: 0 on success, -errno on failure
 */
int fscrypt_add_test_dummy_key(struct super_block *sb,
			       struct fscrypt_key_specifier *key_spec)
{}

/*
 * Verify that the current user has added a master key with the given identifier
 * (returns -ENOKEY if not).  This is needed to prevent a user from encrypting
 * their files using some other user's key which they don't actually know.
 * Cryptographically this isn't much of a problem, but the semantics of this
 * would be a bit weird, so it's best to just forbid it.
 *
 * The system administrator (CAP_FOWNER) can override this, which should be
 * enough for any use cases where encryption policies are being set using keys
 * that were chosen ahead of time but aren't available at the moment.
 *
 * Note that the key may have already removed by the time this returns, but
 * that's okay; we just care whether the key was there at some point.
 *
 * Return: 0 if the key is added, -ENOKEY if it isn't, or another -errno code
 */
int fscrypt_verify_key_added(struct super_block *sb,
			     const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
{}

/*
 * Try to evict the inode's dentries from the dentry cache.  If the inode is a
 * directory, then it can have at most one dentry; however, that dentry may be
 * pinned by child dentries, so first try to evict the children too.
 */
static void shrink_dcache_inode(struct inode *inode)
{}

static void evict_dentries_for_decrypted_inodes(struct fscrypt_master_key *mk)
{}

static int check_for_busy_inodes(struct super_block *sb,
				 struct fscrypt_master_key *mk)
{}

static int try_to_lock_encrypted_files(struct super_block *sb,
				       struct fscrypt_master_key *mk)
{}

/*
 * Try to remove an fscrypt master encryption key.
 *
 * FS_IOC_REMOVE_ENCRYPTION_KEY (all_users=false) removes the current user's
 * claim to the key, then removes the key itself if no other users have claims.
 * FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS (all_users=true) always removes the
 * key itself.
 *
 * To "remove the key itself", first we transition the key to the "incompletely
 * removed" state, so that no more inodes can be unlocked with it.  Then we try
 * to evict all cached inodes that had been unlocked with the key.
 *
 * If all inodes were evicted, then we unlink the fscrypt_master_key from the
 * keyring.  Otherwise it remains in the keyring in the "incompletely removed"
 * state where it tracks the list of remaining inodes.  Userspace can execute
 * the ioctl again later to retry eviction, or alternatively can re-add the key.
 *
 * For more details, see the "Removing keys" section of
 * Documentation/filesystems/fscrypt.rst.
 */
static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
{}

int fscrypt_ioctl_remove_key(struct file *filp, void __user *uarg)
{}
EXPORT_SYMBOL_GPL();

int fscrypt_ioctl_remove_key_all_users(struct file *filp, void __user *uarg)
{}
EXPORT_SYMBOL_GPL();

/*
 * Retrieve the status of an fscrypt master encryption key.
 *
 * We set ->status to indicate whether the key is absent, present, or
 * incompletely removed.  (For an explanation of what these statuses mean and
 * how they are represented internally, see struct fscrypt_master_key.)  This
 * field allows applications to easily determine the status of an encrypted
 * directory without using a hack such as trying to open a regular file in it
 * (which can confuse the "incompletely removed" status with absent or present).
 *
 * In addition, for v2 policy keys we allow applications to determine, via
 * ->status_flags and ->user_count, whether the key has been added by the
 * current user, by other users, or by both.  Most applications should not need
 * this, since ordinarily only one user should know a given key.  However, if a
 * secret key is shared by multiple users, applications may wish to add an
 * already-present key to prevent other users from removing it.  This ioctl can
 * be used to check whether that really is the case before the work is done to
 * add the key --- which might e.g. require prompting the user for a passphrase.
 *
 * For more details, see the "FS_IOC_GET_ENCRYPTION_KEY_STATUS" section of
 * Documentation/filesystems/fscrypt.rst.
 */
int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
{}
EXPORT_SYMBOL_GPL();

int __init fscrypt_init_keyring(void)
{}