326 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Key setup for v1 encryption policies4 *5 * Copyright 2015, 2019 Google LLC6 */7 8/*9 * This file implements compatibility functions for the original encryption10 * policy version ("v1"), including:11 *12 * - Deriving per-file encryption keys using the AES-128-ECB based KDF13 * (rather than the new method of using HKDF-SHA512)14 *15 * - Retrieving fscrypt master keys from process-subscribed keyrings16 * (rather than the new method of using a filesystem-level keyring)17 *18 * - Handling policies with the DIRECT_KEY flag set using a master key table19 * (rather than the new method of implementing DIRECT_KEY with per-mode keys20 * managed alongside the master keys in the filesystem-level keyring)21 */22 23#include <crypto/skcipher.h>24#include <crypto/utils.h>25#include <keys/user-type.h>26#include <linux/hashtable.h>27#include <linux/scatterlist.h>28 29#include "fscrypt_private.h"30 31/* Table of keys referenced by DIRECT_KEY policies */32static DEFINE_HASHTABLE(fscrypt_direct_keys, 6); /* 6 bits = 64 buckets */33static DEFINE_SPINLOCK(fscrypt_direct_keys_lock);34 35/*36 * v1 key derivation function. This generates the derived key by encrypting the37 * master key with AES-128-ECB using the nonce as the AES key. This provides a38 * unique derived key with sufficient entropy for each inode. However, it's39 * nonstandard, non-extensible, doesn't evenly distribute the entropy from the40 * master key, and is trivially reversible: an attacker who compromises a41 * derived key can "decrypt" it to get back to the master key, then derive any42 * other key. For all new code, use HKDF instead.43 *44 * The master key must be at least as long as the derived key. If the master45 * key is longer, then only the first 'derived_keysize' bytes are used.46 */47static int derive_key_aes(const u8 *master_key,48 const u8 nonce[FSCRYPT_FILE_NONCE_SIZE],49 u8 *derived_key, unsigned int derived_keysize)50{51 int res = 0;52 struct skcipher_request *req = NULL;53 DECLARE_CRYPTO_WAIT(wait);54 struct scatterlist src_sg, dst_sg;55 struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);56 57 if (IS_ERR(tfm)) {58 res = PTR_ERR(tfm);59 tfm = NULL;60 goto out;61 }62 crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);63 req = skcipher_request_alloc(tfm, GFP_KERNEL);64 if (!req) {65 res = -ENOMEM;66 goto out;67 }68 skcipher_request_set_callback(req,69 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,70 crypto_req_done, &wait);71 res = crypto_skcipher_setkey(tfm, nonce, FSCRYPT_FILE_NONCE_SIZE);72 if (res < 0)73 goto out;74 75 sg_init_one(&src_sg, master_key, derived_keysize);76 sg_init_one(&dst_sg, derived_key, derived_keysize);77 skcipher_request_set_crypt(req, &src_sg, &dst_sg, derived_keysize,78 NULL);79 res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);80out:81 skcipher_request_free(req);82 crypto_free_skcipher(tfm);83 return res;84}85 86/*87 * Search the current task's subscribed keyrings for a "logon" key with88 * description prefix:descriptor, and if found acquire a read lock on it and89 * return a pointer to its validated payload in *payload_ret.90 */91static struct key *92find_and_lock_process_key(const char *prefix,93 const u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE],94 unsigned int min_keysize,95 const struct fscrypt_key **payload_ret)96{97 char *description;98 struct key *key;99 const struct user_key_payload *ukp;100 const struct fscrypt_key *payload;101 102 description = kasprintf(GFP_KERNEL, "%s%*phN", prefix,103 FSCRYPT_KEY_DESCRIPTOR_SIZE, descriptor);104 if (!description)105 return ERR_PTR(-ENOMEM);106 107 key = request_key(&key_type_logon, description, NULL);108 kfree(description);109 if (IS_ERR(key))110 return key;111 112 down_read(&key->sem);113 ukp = user_key_payload_locked(key);114 115 if (!ukp) /* was the key revoked before we acquired its semaphore? */116 goto invalid;117 118 payload = (const struct fscrypt_key *)ukp->data;119 120 if (ukp->datalen != sizeof(struct fscrypt_key) ||121 payload->size < 1 || payload->size > FSCRYPT_MAX_KEY_SIZE) {122 fscrypt_warn(NULL,123 "key with description '%s' has invalid payload",124 key->description);125 goto invalid;126 }127 128 if (payload->size < min_keysize) {129 fscrypt_warn(NULL,130 "key with description '%s' is too short (got %u bytes, need %u+ bytes)",131 key->description, payload->size, min_keysize);132 goto invalid;133 }134 135 *payload_ret = payload;136 return key;137 138invalid:139 up_read(&key->sem);140 key_put(key);141 return ERR_PTR(-ENOKEY);142}143 144/* Master key referenced by DIRECT_KEY policy */145struct fscrypt_direct_key {146 struct super_block *dk_sb;147 struct hlist_node dk_node;148 refcount_t dk_refcount;149 const struct fscrypt_mode *dk_mode;150 struct fscrypt_prepared_key dk_key;151 u8 dk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];152 u8 dk_raw[FSCRYPT_MAX_KEY_SIZE];153};154 155static void free_direct_key(struct fscrypt_direct_key *dk)156{157 if (dk) {158 fscrypt_destroy_prepared_key(dk->dk_sb, &dk->dk_key);159 kfree_sensitive(dk);160 }161}162 163void fscrypt_put_direct_key(struct fscrypt_direct_key *dk)164{165 if (!refcount_dec_and_lock(&dk->dk_refcount, &fscrypt_direct_keys_lock))166 return;167 hash_del(&dk->dk_node);168 spin_unlock(&fscrypt_direct_keys_lock);169 170 free_direct_key(dk);171}172 173/*174 * Find/insert the given key into the fscrypt_direct_keys table. If found, it175 * is returned with elevated refcount, and 'to_insert' is freed if non-NULL. If176 * not found, 'to_insert' is inserted and returned if it's non-NULL; otherwise177 * NULL is returned.178 */179static struct fscrypt_direct_key *180find_or_insert_direct_key(struct fscrypt_direct_key *to_insert,181 const u8 *raw_key,182 const struct fscrypt_inode_info *ci)183{184 unsigned long hash_key;185 struct fscrypt_direct_key *dk;186 187 /*188 * Careful: to avoid potentially leaking secret key bytes via timing189 * information, we must key the hash table by descriptor rather than by190 * raw key, and use crypto_memneq() when comparing raw keys.191 */192 193 BUILD_BUG_ON(sizeof(hash_key) > FSCRYPT_KEY_DESCRIPTOR_SIZE);194 memcpy(&hash_key, ci->ci_policy.v1.master_key_descriptor,195 sizeof(hash_key));196 197 spin_lock(&fscrypt_direct_keys_lock);198 hash_for_each_possible(fscrypt_direct_keys, dk, dk_node, hash_key) {199 if (memcmp(ci->ci_policy.v1.master_key_descriptor,200 dk->dk_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0)201 continue;202 if (ci->ci_mode != dk->dk_mode)203 continue;204 if (!fscrypt_is_key_prepared(&dk->dk_key, ci))205 continue;206 if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize))207 continue;208 /* using existing tfm with same (descriptor, mode, raw_key) */209 refcount_inc(&dk->dk_refcount);210 spin_unlock(&fscrypt_direct_keys_lock);211 free_direct_key(to_insert);212 return dk;213 }214 if (to_insert)215 hash_add(fscrypt_direct_keys, &to_insert->dk_node, hash_key);216 spin_unlock(&fscrypt_direct_keys_lock);217 return to_insert;218}219 220/* Prepare to encrypt directly using the master key in the given mode */221static struct fscrypt_direct_key *222fscrypt_get_direct_key(const struct fscrypt_inode_info *ci, const u8 *raw_key)223{224 struct fscrypt_direct_key *dk;225 int err;226 227 /* Is there already a tfm for this key? */228 dk = find_or_insert_direct_key(NULL, raw_key, ci);229 if (dk)230 return dk;231 232 /* Nope, allocate one. */233 dk = kzalloc(sizeof(*dk), GFP_KERNEL);234 if (!dk)235 return ERR_PTR(-ENOMEM);236 dk->dk_sb = ci->ci_inode->i_sb;237 refcount_set(&dk->dk_refcount, 1);238 dk->dk_mode = ci->ci_mode;239 err = fscrypt_prepare_key(&dk->dk_key, raw_key, ci);240 if (err)241 goto err_free_dk;242 memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor,243 FSCRYPT_KEY_DESCRIPTOR_SIZE);244 memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize);245 246 return find_or_insert_direct_key(dk, raw_key, ci);247 248err_free_dk:249 free_direct_key(dk);250 return ERR_PTR(err);251}252 253/* v1 policy, DIRECT_KEY: use the master key directly */254static int setup_v1_file_key_direct(struct fscrypt_inode_info *ci,255 const u8 *raw_master_key)256{257 struct fscrypt_direct_key *dk;258 259 dk = fscrypt_get_direct_key(ci, raw_master_key);260 if (IS_ERR(dk))261 return PTR_ERR(dk);262 ci->ci_direct_key = dk;263 ci->ci_enc_key = dk->dk_key;264 return 0;265}266 267/* v1 policy, !DIRECT_KEY: derive the file's encryption key */268static int setup_v1_file_key_derived(struct fscrypt_inode_info *ci,269 const u8 *raw_master_key)270{271 u8 *derived_key;272 int err;273 274 /*275 * This cannot be a stack buffer because it will be passed to the276 * scatterlist crypto API during derive_key_aes().277 */278 derived_key = kmalloc(ci->ci_mode->keysize, GFP_KERNEL);279 if (!derived_key)280 return -ENOMEM;281 282 err = derive_key_aes(raw_master_key, ci->ci_nonce,283 derived_key, ci->ci_mode->keysize);284 if (err)285 goto out;286 287 err = fscrypt_set_per_file_enc_key(ci, derived_key);288out:289 kfree_sensitive(derived_key);290 return err;291}292 293int fscrypt_setup_v1_file_key(struct fscrypt_inode_info *ci,294 const u8 *raw_master_key)295{296 if (ci->ci_policy.v1.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY)297 return setup_v1_file_key_direct(ci, raw_master_key);298 else299 return setup_v1_file_key_derived(ci, raw_master_key);300}301 302int303fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_inode_info *ci)304{305 const struct super_block *sb = ci->ci_inode->i_sb;306 struct key *key;307 const struct fscrypt_key *payload;308 int err;309 310 key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX,311 ci->ci_policy.v1.master_key_descriptor,312 ci->ci_mode->keysize, &payload);313 if (key == ERR_PTR(-ENOKEY) && sb->s_cop->legacy_key_prefix) {314 key = find_and_lock_process_key(sb->s_cop->legacy_key_prefix,315 ci->ci_policy.v1.master_key_descriptor,316 ci->ci_mode->keysize, &payload);317 }318 if (IS_ERR(key))319 return PTR_ERR(key);320 321 err = fscrypt_setup_v1_file_key(ci, payload->raw);322 up_read(&key->sem);323 key_put(key);324 return err;325}326