162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Key setup for v1 encryption policies 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2015, 2019 Google LLC 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * This file implements compatibility functions for the original encryption 1062306a36Sopenharmony_ci * policy version ("v1"), including: 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * - Deriving per-file encryption keys using the AES-128-ECB based KDF 1362306a36Sopenharmony_ci * (rather than the new method of using HKDF-SHA512) 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * - Retrieving fscrypt master keys from process-subscribed keyrings 1662306a36Sopenharmony_ci * (rather than the new method of using a filesystem-level keyring) 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * - Handling policies with the DIRECT_KEY flag set using a master key table 1962306a36Sopenharmony_ci * (rather than the new method of implementing DIRECT_KEY with per-mode keys 2062306a36Sopenharmony_ci * managed alongside the master keys in the filesystem-level keyring) 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <crypto/algapi.h> 2462306a36Sopenharmony_ci#include <crypto/skcipher.h> 2562306a36Sopenharmony_ci#include <keys/user-type.h> 2662306a36Sopenharmony_ci#include <linux/hashtable.h> 2762306a36Sopenharmony_ci#include <linux/scatterlist.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include "fscrypt_private.h" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* Table of keys referenced by DIRECT_KEY policies */ 3262306a36Sopenharmony_cistatic DEFINE_HASHTABLE(fscrypt_direct_keys, 6); /* 6 bits = 64 buckets */ 3362306a36Sopenharmony_cistatic DEFINE_SPINLOCK(fscrypt_direct_keys_lock); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci * v1 key derivation function. This generates the derived key by encrypting the 3762306a36Sopenharmony_ci * master key with AES-128-ECB using the nonce as the AES key. This provides a 3862306a36Sopenharmony_ci * unique derived key with sufficient entropy for each inode. However, it's 3962306a36Sopenharmony_ci * nonstandard, non-extensible, doesn't evenly distribute the entropy from the 4062306a36Sopenharmony_ci * master key, and is trivially reversible: an attacker who compromises a 4162306a36Sopenharmony_ci * derived key can "decrypt" it to get back to the master key, then derive any 4262306a36Sopenharmony_ci * other key. For all new code, use HKDF instead. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * The master key must be at least as long as the derived key. If the master 4562306a36Sopenharmony_ci * key is longer, then only the first 'derived_keysize' bytes are used. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_cistatic int derive_key_aes(const u8 *master_key, 4862306a36Sopenharmony_ci const u8 nonce[FSCRYPT_FILE_NONCE_SIZE], 4962306a36Sopenharmony_ci u8 *derived_key, unsigned int derived_keysize) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci int res = 0; 5262306a36Sopenharmony_ci struct skcipher_request *req = NULL; 5362306a36Sopenharmony_ci DECLARE_CRYPTO_WAIT(wait); 5462306a36Sopenharmony_ci struct scatterlist src_sg, dst_sg; 5562306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci if (IS_ERR(tfm)) { 5862306a36Sopenharmony_ci res = PTR_ERR(tfm); 5962306a36Sopenharmony_ci tfm = NULL; 6062306a36Sopenharmony_ci goto out; 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); 6362306a36Sopenharmony_ci req = skcipher_request_alloc(tfm, GFP_KERNEL); 6462306a36Sopenharmony_ci if (!req) { 6562306a36Sopenharmony_ci res = -ENOMEM; 6662306a36Sopenharmony_ci goto out; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci skcipher_request_set_callback(req, 6962306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, 7062306a36Sopenharmony_ci crypto_req_done, &wait); 7162306a36Sopenharmony_ci res = crypto_skcipher_setkey(tfm, nonce, FSCRYPT_FILE_NONCE_SIZE); 7262306a36Sopenharmony_ci if (res < 0) 7362306a36Sopenharmony_ci goto out; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci sg_init_one(&src_sg, master_key, derived_keysize); 7662306a36Sopenharmony_ci sg_init_one(&dst_sg, derived_key, derived_keysize); 7762306a36Sopenharmony_ci skcipher_request_set_crypt(req, &src_sg, &dst_sg, derived_keysize, 7862306a36Sopenharmony_ci NULL); 7962306a36Sopenharmony_ci res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); 8062306a36Sopenharmony_ciout: 8162306a36Sopenharmony_ci skcipher_request_free(req); 8262306a36Sopenharmony_ci crypto_free_skcipher(tfm); 8362306a36Sopenharmony_ci return res; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* 8762306a36Sopenharmony_ci * Search the current task's subscribed keyrings for a "logon" key with 8862306a36Sopenharmony_ci * description prefix:descriptor, and if found acquire a read lock on it and 8962306a36Sopenharmony_ci * return a pointer to its validated payload in *payload_ret. 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_cistatic struct key * 9262306a36Sopenharmony_cifind_and_lock_process_key(const char *prefix, 9362306a36Sopenharmony_ci const u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE], 9462306a36Sopenharmony_ci unsigned int min_keysize, 9562306a36Sopenharmony_ci const struct fscrypt_key **payload_ret) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci char *description; 9862306a36Sopenharmony_ci struct key *key; 9962306a36Sopenharmony_ci const struct user_key_payload *ukp; 10062306a36Sopenharmony_ci const struct fscrypt_key *payload; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci description = kasprintf(GFP_KERNEL, "%s%*phN", prefix, 10362306a36Sopenharmony_ci FSCRYPT_KEY_DESCRIPTOR_SIZE, descriptor); 10462306a36Sopenharmony_ci if (!description) 10562306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci key = request_key(&key_type_logon, description, NULL); 10862306a36Sopenharmony_ci kfree(description); 10962306a36Sopenharmony_ci if (IS_ERR(key)) 11062306a36Sopenharmony_ci return key; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci down_read(&key->sem); 11362306a36Sopenharmony_ci ukp = user_key_payload_locked(key); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci if (!ukp) /* was the key revoked before we acquired its semaphore? */ 11662306a36Sopenharmony_ci goto invalid; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci payload = (const struct fscrypt_key *)ukp->data; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci if (ukp->datalen != sizeof(struct fscrypt_key) || 12162306a36Sopenharmony_ci payload->size < 1 || payload->size > FSCRYPT_MAX_KEY_SIZE) { 12262306a36Sopenharmony_ci fscrypt_warn(NULL, 12362306a36Sopenharmony_ci "key with description '%s' has invalid payload", 12462306a36Sopenharmony_ci key->description); 12562306a36Sopenharmony_ci goto invalid; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci if (payload->size < min_keysize) { 12962306a36Sopenharmony_ci fscrypt_warn(NULL, 13062306a36Sopenharmony_ci "key with description '%s' is too short (got %u bytes, need %u+ bytes)", 13162306a36Sopenharmony_ci key->description, payload->size, min_keysize); 13262306a36Sopenharmony_ci goto invalid; 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci *payload_ret = payload; 13662306a36Sopenharmony_ci return key; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ciinvalid: 13962306a36Sopenharmony_ci up_read(&key->sem); 14062306a36Sopenharmony_ci key_put(key); 14162306a36Sopenharmony_ci return ERR_PTR(-ENOKEY); 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci/* Master key referenced by DIRECT_KEY policy */ 14562306a36Sopenharmony_cistruct fscrypt_direct_key { 14662306a36Sopenharmony_ci struct super_block *dk_sb; 14762306a36Sopenharmony_ci struct hlist_node dk_node; 14862306a36Sopenharmony_ci refcount_t dk_refcount; 14962306a36Sopenharmony_ci const struct fscrypt_mode *dk_mode; 15062306a36Sopenharmony_ci struct fscrypt_prepared_key dk_key; 15162306a36Sopenharmony_ci u8 dk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE]; 15262306a36Sopenharmony_ci u8 dk_raw[FSCRYPT_MAX_KEY_SIZE]; 15362306a36Sopenharmony_ci}; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic void free_direct_key(struct fscrypt_direct_key *dk) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci if (dk) { 15862306a36Sopenharmony_ci fscrypt_destroy_prepared_key(dk->dk_sb, &dk->dk_key); 15962306a36Sopenharmony_ci kfree_sensitive(dk); 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_civoid fscrypt_put_direct_key(struct fscrypt_direct_key *dk) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci if (!refcount_dec_and_lock(&dk->dk_refcount, &fscrypt_direct_keys_lock)) 16662306a36Sopenharmony_ci return; 16762306a36Sopenharmony_ci hash_del(&dk->dk_node); 16862306a36Sopenharmony_ci spin_unlock(&fscrypt_direct_keys_lock); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci free_direct_key(dk); 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci/* 17462306a36Sopenharmony_ci * Find/insert the given key into the fscrypt_direct_keys table. If found, it 17562306a36Sopenharmony_ci * is returned with elevated refcount, and 'to_insert' is freed if non-NULL. If 17662306a36Sopenharmony_ci * not found, 'to_insert' is inserted and returned if it's non-NULL; otherwise 17762306a36Sopenharmony_ci * NULL is returned. 17862306a36Sopenharmony_ci */ 17962306a36Sopenharmony_cistatic struct fscrypt_direct_key * 18062306a36Sopenharmony_cifind_or_insert_direct_key(struct fscrypt_direct_key *to_insert, 18162306a36Sopenharmony_ci const u8 *raw_key, const struct fscrypt_info *ci) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci unsigned long hash_key; 18462306a36Sopenharmony_ci struct fscrypt_direct_key *dk; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci /* 18762306a36Sopenharmony_ci * Careful: to avoid potentially leaking secret key bytes via timing 18862306a36Sopenharmony_ci * information, we must key the hash table by descriptor rather than by 18962306a36Sopenharmony_ci * raw key, and use crypto_memneq() when comparing raw keys. 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(hash_key) > FSCRYPT_KEY_DESCRIPTOR_SIZE); 19362306a36Sopenharmony_ci memcpy(&hash_key, ci->ci_policy.v1.master_key_descriptor, 19462306a36Sopenharmony_ci sizeof(hash_key)); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci spin_lock(&fscrypt_direct_keys_lock); 19762306a36Sopenharmony_ci hash_for_each_possible(fscrypt_direct_keys, dk, dk_node, hash_key) { 19862306a36Sopenharmony_ci if (memcmp(ci->ci_policy.v1.master_key_descriptor, 19962306a36Sopenharmony_ci dk->dk_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) 20062306a36Sopenharmony_ci continue; 20162306a36Sopenharmony_ci if (ci->ci_mode != dk->dk_mode) 20262306a36Sopenharmony_ci continue; 20362306a36Sopenharmony_ci if (!fscrypt_is_key_prepared(&dk->dk_key, ci)) 20462306a36Sopenharmony_ci continue; 20562306a36Sopenharmony_ci if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize)) 20662306a36Sopenharmony_ci continue; 20762306a36Sopenharmony_ci /* using existing tfm with same (descriptor, mode, raw_key) */ 20862306a36Sopenharmony_ci refcount_inc(&dk->dk_refcount); 20962306a36Sopenharmony_ci spin_unlock(&fscrypt_direct_keys_lock); 21062306a36Sopenharmony_ci free_direct_key(to_insert); 21162306a36Sopenharmony_ci return dk; 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci if (to_insert) 21462306a36Sopenharmony_ci hash_add(fscrypt_direct_keys, &to_insert->dk_node, hash_key); 21562306a36Sopenharmony_ci spin_unlock(&fscrypt_direct_keys_lock); 21662306a36Sopenharmony_ci return to_insert; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/* Prepare to encrypt directly using the master key in the given mode */ 22062306a36Sopenharmony_cistatic struct fscrypt_direct_key * 22162306a36Sopenharmony_cifscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct fscrypt_direct_key *dk; 22462306a36Sopenharmony_ci int err; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* Is there already a tfm for this key? */ 22762306a36Sopenharmony_ci dk = find_or_insert_direct_key(NULL, raw_key, ci); 22862306a36Sopenharmony_ci if (dk) 22962306a36Sopenharmony_ci return dk; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* Nope, allocate one. */ 23262306a36Sopenharmony_ci dk = kzalloc(sizeof(*dk), GFP_KERNEL); 23362306a36Sopenharmony_ci if (!dk) 23462306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 23562306a36Sopenharmony_ci dk->dk_sb = ci->ci_inode->i_sb; 23662306a36Sopenharmony_ci refcount_set(&dk->dk_refcount, 1); 23762306a36Sopenharmony_ci dk->dk_mode = ci->ci_mode; 23862306a36Sopenharmony_ci err = fscrypt_prepare_key(&dk->dk_key, raw_key, ci); 23962306a36Sopenharmony_ci if (err) 24062306a36Sopenharmony_ci goto err_free_dk; 24162306a36Sopenharmony_ci memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor, 24262306a36Sopenharmony_ci FSCRYPT_KEY_DESCRIPTOR_SIZE); 24362306a36Sopenharmony_ci memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci return find_or_insert_direct_key(dk, raw_key, ci); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cierr_free_dk: 24862306a36Sopenharmony_ci free_direct_key(dk); 24962306a36Sopenharmony_ci return ERR_PTR(err); 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci/* v1 policy, DIRECT_KEY: use the master key directly */ 25362306a36Sopenharmony_cistatic int setup_v1_file_key_direct(struct fscrypt_info *ci, 25462306a36Sopenharmony_ci const u8 *raw_master_key) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci struct fscrypt_direct_key *dk; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci dk = fscrypt_get_direct_key(ci, raw_master_key); 25962306a36Sopenharmony_ci if (IS_ERR(dk)) 26062306a36Sopenharmony_ci return PTR_ERR(dk); 26162306a36Sopenharmony_ci ci->ci_direct_key = dk; 26262306a36Sopenharmony_ci ci->ci_enc_key = dk->dk_key; 26362306a36Sopenharmony_ci return 0; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci/* v1 policy, !DIRECT_KEY: derive the file's encryption key */ 26762306a36Sopenharmony_cistatic int setup_v1_file_key_derived(struct fscrypt_info *ci, 26862306a36Sopenharmony_ci const u8 *raw_master_key) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci u8 *derived_key; 27162306a36Sopenharmony_ci int err; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci /* 27462306a36Sopenharmony_ci * This cannot be a stack buffer because it will be passed to the 27562306a36Sopenharmony_ci * scatterlist crypto API during derive_key_aes(). 27662306a36Sopenharmony_ci */ 27762306a36Sopenharmony_ci derived_key = kmalloc(ci->ci_mode->keysize, GFP_KERNEL); 27862306a36Sopenharmony_ci if (!derived_key) 27962306a36Sopenharmony_ci return -ENOMEM; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci err = derive_key_aes(raw_master_key, ci->ci_nonce, 28262306a36Sopenharmony_ci derived_key, ci->ci_mode->keysize); 28362306a36Sopenharmony_ci if (err) 28462306a36Sopenharmony_ci goto out; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci err = fscrypt_set_per_file_enc_key(ci, derived_key); 28762306a36Sopenharmony_ciout: 28862306a36Sopenharmony_ci kfree_sensitive(derived_key); 28962306a36Sopenharmony_ci return err; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ciint fscrypt_setup_v1_file_key(struct fscrypt_info *ci, const u8 *raw_master_key) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci if (ci->ci_policy.v1.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) 29562306a36Sopenharmony_ci return setup_v1_file_key_direct(ci, raw_master_key); 29662306a36Sopenharmony_ci else 29762306a36Sopenharmony_ci return setup_v1_file_key_derived(ci, raw_master_key); 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ciint fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_info *ci) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci struct key *key; 30362306a36Sopenharmony_ci const struct fscrypt_key *payload; 30462306a36Sopenharmony_ci int err; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX, 30762306a36Sopenharmony_ci ci->ci_policy.v1.master_key_descriptor, 30862306a36Sopenharmony_ci ci->ci_mode->keysize, &payload); 30962306a36Sopenharmony_ci if (key == ERR_PTR(-ENOKEY) && ci->ci_inode->i_sb->s_cop->key_prefix) { 31062306a36Sopenharmony_ci key = find_and_lock_process_key(ci->ci_inode->i_sb->s_cop->key_prefix, 31162306a36Sopenharmony_ci ci->ci_policy.v1.master_key_descriptor, 31262306a36Sopenharmony_ci ci->ci_mode->keysize, &payload); 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci if (IS_ERR(key)) 31562306a36Sopenharmony_ci return PTR_ERR(key); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci err = fscrypt_setup_v1_file_key(ci, payload->raw); 31862306a36Sopenharmony_ci up_read(&key->sem); 31962306a36Sopenharmony_ci key_put(key); 32062306a36Sopenharmony_ci return err; 32162306a36Sopenharmony_ci} 322