1feed8258SEric Biggers // SPDX-License-Identifier: GPL-2.0 2feed8258SEric Biggers /* 3feed8258SEric Biggers * Key setup facility for FS encryption support. 4feed8258SEric Biggers * 5feed8258SEric Biggers * Copyright (C) 2015, Google, Inc. 6feed8258SEric Biggers * 7feed8258SEric Biggers * Originally written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar. 8feed8258SEric Biggers * Heavily modified since then. 9feed8258SEric Biggers */ 10feed8258SEric Biggers 11feed8258SEric Biggers #include <crypto/aes.h> 12feed8258SEric Biggers #include <crypto/sha.h> 13feed8258SEric Biggers #include <crypto/skcipher.h> 14feed8258SEric Biggers #include <linux/key.h> 15feed8258SEric Biggers 16feed8258SEric Biggers #include "fscrypt_private.h" 17feed8258SEric Biggers 18feed8258SEric Biggers static struct crypto_shash *essiv_hash_tfm; 19feed8258SEric Biggers 20feed8258SEric Biggers static struct fscrypt_mode available_modes[] = { 21feed8258SEric Biggers [FSCRYPT_MODE_AES_256_XTS] = { 22feed8258SEric Biggers .friendly_name = "AES-256-XTS", 23feed8258SEric Biggers .cipher_str = "xts(aes)", 24feed8258SEric Biggers .keysize = 64, 25feed8258SEric Biggers .ivsize = 16, 26feed8258SEric Biggers }, 27feed8258SEric Biggers [FSCRYPT_MODE_AES_256_CTS] = { 28feed8258SEric Biggers .friendly_name = "AES-256-CTS-CBC", 29feed8258SEric Biggers .cipher_str = "cts(cbc(aes))", 30feed8258SEric Biggers .keysize = 32, 31feed8258SEric Biggers .ivsize = 16, 32feed8258SEric Biggers }, 33feed8258SEric Biggers [FSCRYPT_MODE_AES_128_CBC] = { 34feed8258SEric Biggers .friendly_name = "AES-128-CBC", 35feed8258SEric Biggers .cipher_str = "cbc(aes)", 36feed8258SEric Biggers .keysize = 16, 37feed8258SEric Biggers .ivsize = 16, 38feed8258SEric Biggers .needs_essiv = true, 39feed8258SEric Biggers }, 40feed8258SEric Biggers [FSCRYPT_MODE_AES_128_CTS] = { 41feed8258SEric Biggers .friendly_name = "AES-128-CTS-CBC", 42feed8258SEric Biggers .cipher_str = "cts(cbc(aes))", 43feed8258SEric Biggers .keysize = 16, 44feed8258SEric Biggers .ivsize = 16, 45feed8258SEric Biggers }, 46feed8258SEric Biggers [FSCRYPT_MODE_ADIANTUM] = { 47feed8258SEric Biggers .friendly_name = "Adiantum", 48feed8258SEric Biggers .cipher_str = "adiantum(xchacha12,aes)", 49feed8258SEric Biggers .keysize = 32, 50feed8258SEric Biggers .ivsize = 32, 51feed8258SEric Biggers }, 52feed8258SEric Biggers }; 53feed8258SEric Biggers 54feed8258SEric Biggers static struct fscrypt_mode * 55feed8258SEric Biggers select_encryption_mode(const struct fscrypt_info *ci, const struct inode *inode) 56feed8258SEric Biggers { 57feed8258SEric Biggers if (!fscrypt_valid_enc_modes(ci->ci_data_mode, ci->ci_filename_mode)) { 58feed8258SEric Biggers fscrypt_warn(inode, 59feed8258SEric Biggers "Unsupported encryption modes (contents mode %d, filenames mode %d)", 60feed8258SEric Biggers ci->ci_data_mode, ci->ci_filename_mode); 61feed8258SEric Biggers return ERR_PTR(-EINVAL); 62feed8258SEric Biggers } 63feed8258SEric Biggers 64feed8258SEric Biggers if (S_ISREG(inode->i_mode)) 65feed8258SEric Biggers return &available_modes[ci->ci_data_mode]; 66feed8258SEric Biggers 67feed8258SEric Biggers if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) 68feed8258SEric Biggers return &available_modes[ci->ci_filename_mode]; 69feed8258SEric Biggers 70feed8258SEric Biggers WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n", 71feed8258SEric Biggers inode->i_ino, (inode->i_mode & S_IFMT)); 72feed8258SEric Biggers return ERR_PTR(-EINVAL); 73feed8258SEric Biggers } 74feed8258SEric Biggers 75feed8258SEric Biggers /* Create a symmetric cipher object for the given encryption mode and key */ 76feed8258SEric Biggers struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, 77feed8258SEric Biggers const u8 *raw_key, 78feed8258SEric Biggers const struct inode *inode) 79feed8258SEric Biggers { 80feed8258SEric Biggers struct crypto_skcipher *tfm; 81feed8258SEric Biggers int err; 82feed8258SEric Biggers 83feed8258SEric Biggers tfm = crypto_alloc_skcipher(mode->cipher_str, 0, 0); 84feed8258SEric Biggers if (IS_ERR(tfm)) { 85feed8258SEric Biggers if (PTR_ERR(tfm) == -ENOENT) { 86feed8258SEric Biggers fscrypt_warn(inode, 87feed8258SEric Biggers "Missing crypto API support for %s (API name: \"%s\")", 88feed8258SEric Biggers mode->friendly_name, mode->cipher_str); 89feed8258SEric Biggers return ERR_PTR(-ENOPKG); 90feed8258SEric Biggers } 91feed8258SEric Biggers fscrypt_err(inode, "Error allocating '%s' transform: %ld", 92feed8258SEric Biggers mode->cipher_str, PTR_ERR(tfm)); 93feed8258SEric Biggers return tfm; 94feed8258SEric Biggers } 95feed8258SEric Biggers if (unlikely(!mode->logged_impl_name)) { 96feed8258SEric Biggers /* 97feed8258SEric Biggers * fscrypt performance can vary greatly depending on which 98feed8258SEric Biggers * crypto algorithm implementation is used. Help people debug 99feed8258SEric Biggers * performance problems by logging the ->cra_driver_name the 100feed8258SEric Biggers * first time a mode is used. Note that multiple threads can 101feed8258SEric Biggers * race here, but it doesn't really matter. 102feed8258SEric Biggers */ 103feed8258SEric Biggers mode->logged_impl_name = true; 104feed8258SEric Biggers pr_info("fscrypt: %s using implementation \"%s\"\n", 105feed8258SEric Biggers mode->friendly_name, 106feed8258SEric Biggers crypto_skcipher_alg(tfm)->base.cra_driver_name); 107feed8258SEric Biggers } 108feed8258SEric Biggers crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); 109feed8258SEric Biggers err = crypto_skcipher_setkey(tfm, raw_key, mode->keysize); 110feed8258SEric Biggers if (err) 111feed8258SEric Biggers goto err_free_tfm; 112feed8258SEric Biggers 113feed8258SEric Biggers return tfm; 114feed8258SEric Biggers 115feed8258SEric Biggers err_free_tfm: 116feed8258SEric Biggers crypto_free_skcipher(tfm); 117feed8258SEric Biggers return ERR_PTR(err); 118feed8258SEric Biggers } 119feed8258SEric Biggers 120feed8258SEric Biggers static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) 121feed8258SEric Biggers { 122feed8258SEric Biggers struct crypto_shash *tfm = READ_ONCE(essiv_hash_tfm); 123feed8258SEric Biggers 124feed8258SEric Biggers /* init hash transform on demand */ 125feed8258SEric Biggers if (unlikely(!tfm)) { 126feed8258SEric Biggers struct crypto_shash *prev_tfm; 127feed8258SEric Biggers 128feed8258SEric Biggers tfm = crypto_alloc_shash("sha256", 0, 0); 129feed8258SEric Biggers if (IS_ERR(tfm)) { 130feed8258SEric Biggers if (PTR_ERR(tfm) == -ENOENT) { 131feed8258SEric Biggers fscrypt_warn(NULL, 132feed8258SEric Biggers "Missing crypto API support for SHA-256"); 133feed8258SEric Biggers return -ENOPKG; 134feed8258SEric Biggers } 135feed8258SEric Biggers fscrypt_err(NULL, 136feed8258SEric Biggers "Error allocating SHA-256 transform: %ld", 137feed8258SEric Biggers PTR_ERR(tfm)); 138feed8258SEric Biggers return PTR_ERR(tfm); 139feed8258SEric Biggers } 140feed8258SEric Biggers prev_tfm = cmpxchg(&essiv_hash_tfm, NULL, tfm); 141feed8258SEric Biggers if (prev_tfm) { 142feed8258SEric Biggers crypto_free_shash(tfm); 143feed8258SEric Biggers tfm = prev_tfm; 144feed8258SEric Biggers } 145feed8258SEric Biggers } 146feed8258SEric Biggers 147feed8258SEric Biggers { 148feed8258SEric Biggers SHASH_DESC_ON_STACK(desc, tfm); 149feed8258SEric Biggers desc->tfm = tfm; 150feed8258SEric Biggers 151feed8258SEric Biggers return crypto_shash_digest(desc, key, keysize, salt); 152feed8258SEric Biggers } 153feed8258SEric Biggers } 154feed8258SEric Biggers 155feed8258SEric Biggers static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key, 156feed8258SEric Biggers int keysize) 157feed8258SEric Biggers { 158feed8258SEric Biggers int err; 159feed8258SEric Biggers struct crypto_cipher *essiv_tfm; 160feed8258SEric Biggers u8 salt[SHA256_DIGEST_SIZE]; 161feed8258SEric Biggers 162feed8258SEric Biggers if (WARN_ON(ci->ci_mode->ivsize != AES_BLOCK_SIZE)) 163feed8258SEric Biggers return -EINVAL; 164feed8258SEric Biggers 165feed8258SEric Biggers essiv_tfm = crypto_alloc_cipher("aes", 0, 0); 166feed8258SEric Biggers if (IS_ERR(essiv_tfm)) 167feed8258SEric Biggers return PTR_ERR(essiv_tfm); 168feed8258SEric Biggers 169feed8258SEric Biggers ci->ci_essiv_tfm = essiv_tfm; 170feed8258SEric Biggers 171feed8258SEric Biggers err = derive_essiv_salt(raw_key, keysize, salt); 172feed8258SEric Biggers if (err) 173feed8258SEric Biggers goto out; 174feed8258SEric Biggers 175feed8258SEric Biggers /* 176feed8258SEric Biggers * Using SHA256 to derive the salt/key will result in AES-256 being 177feed8258SEric Biggers * used for IV generation. File contents encryption will still use the 178feed8258SEric Biggers * configured keysize (AES-128) nevertheless. 179feed8258SEric Biggers */ 180feed8258SEric Biggers err = crypto_cipher_setkey(essiv_tfm, salt, sizeof(salt)); 181feed8258SEric Biggers if (err) 182feed8258SEric Biggers goto out; 183feed8258SEric Biggers 184feed8258SEric Biggers out: 185feed8258SEric Biggers memzero_explicit(salt, sizeof(salt)); 186feed8258SEric Biggers return err; 187feed8258SEric Biggers } 188feed8258SEric Biggers 189feed8258SEric Biggers /* Given the per-file key, set up the file's crypto transform object(s) */ 190feed8258SEric Biggers int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) 191feed8258SEric Biggers { 192feed8258SEric Biggers struct fscrypt_mode *mode = ci->ci_mode; 193feed8258SEric Biggers struct crypto_skcipher *ctfm; 194feed8258SEric Biggers int err; 195feed8258SEric Biggers 196feed8258SEric Biggers ctfm = fscrypt_allocate_skcipher(mode, derived_key, ci->ci_inode); 197feed8258SEric Biggers if (IS_ERR(ctfm)) 198feed8258SEric Biggers return PTR_ERR(ctfm); 199feed8258SEric Biggers 200feed8258SEric Biggers ci->ci_ctfm = ctfm; 201feed8258SEric Biggers 202feed8258SEric Biggers if (mode->needs_essiv) { 203feed8258SEric Biggers err = init_essiv_generator(ci, derived_key, mode->keysize); 204feed8258SEric Biggers if (err) { 205feed8258SEric Biggers fscrypt_warn(ci->ci_inode, 206feed8258SEric Biggers "Error initializing ESSIV generator: %d", 207feed8258SEric Biggers err); 208feed8258SEric Biggers return err; 209feed8258SEric Biggers } 210feed8258SEric Biggers } 211feed8258SEric Biggers return 0; 212feed8258SEric Biggers } 213feed8258SEric Biggers 214feed8258SEric Biggers /* 215feed8258SEric Biggers * Find the master key, then set up the inode's actual encryption key. 216feed8258SEric Biggers */ 217feed8258SEric Biggers static int setup_file_encryption_key(struct fscrypt_info *ci) 218feed8258SEric Biggers { 21922d94f49SEric Biggers struct key *key; 22022d94f49SEric Biggers struct fscrypt_master_key *mk = NULL; 22122d94f49SEric Biggers struct fscrypt_key_specifier mk_spec; 22222d94f49SEric Biggers int err; 22322d94f49SEric Biggers 22422d94f49SEric Biggers mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; 22522d94f49SEric Biggers memcpy(mk_spec.u.descriptor, ci->ci_master_key_descriptor, 22622d94f49SEric Biggers FSCRYPT_KEY_DESCRIPTOR_SIZE); 22722d94f49SEric Biggers 22822d94f49SEric Biggers key = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec); 22922d94f49SEric Biggers if (IS_ERR(key)) { 23022d94f49SEric Biggers if (key != ERR_PTR(-ENOKEY)) 23122d94f49SEric Biggers return PTR_ERR(key); 23222d94f49SEric Biggers 233feed8258SEric Biggers return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci); 234feed8258SEric Biggers } 235feed8258SEric Biggers 23622d94f49SEric Biggers mk = key->payload.data[0]; 23722d94f49SEric Biggers 23822d94f49SEric Biggers if (mk->mk_secret.size < ci->ci_mode->keysize) { 23922d94f49SEric Biggers fscrypt_warn(NULL, 24022d94f49SEric Biggers "key with %s %*phN is too short (got %u bytes, need %u+ bytes)", 24122d94f49SEric Biggers master_key_spec_type(&mk_spec), 24222d94f49SEric Biggers master_key_spec_len(&mk_spec), (u8 *)&mk_spec.u, 24322d94f49SEric Biggers mk->mk_secret.size, ci->ci_mode->keysize); 24422d94f49SEric Biggers err = -ENOKEY; 24522d94f49SEric Biggers goto out_release_key; 24622d94f49SEric Biggers } 24722d94f49SEric Biggers 24822d94f49SEric Biggers err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw); 24922d94f49SEric Biggers 25022d94f49SEric Biggers out_release_key: 25122d94f49SEric Biggers key_put(key); 25222d94f49SEric Biggers return err; 25322d94f49SEric Biggers } 25422d94f49SEric Biggers 255feed8258SEric Biggers static void put_crypt_info(struct fscrypt_info *ci) 256feed8258SEric Biggers { 257feed8258SEric Biggers if (!ci) 258feed8258SEric Biggers return; 259feed8258SEric Biggers 260feed8258SEric Biggers if (ci->ci_direct_key) { 261feed8258SEric Biggers fscrypt_put_direct_key(ci->ci_direct_key); 262feed8258SEric Biggers } else { 263feed8258SEric Biggers crypto_free_skcipher(ci->ci_ctfm); 264feed8258SEric Biggers crypto_free_cipher(ci->ci_essiv_tfm); 265feed8258SEric Biggers } 266feed8258SEric Biggers kmem_cache_free(fscrypt_info_cachep, ci); 267feed8258SEric Biggers } 268feed8258SEric Biggers 269feed8258SEric Biggers int fscrypt_get_encryption_info(struct inode *inode) 270feed8258SEric Biggers { 271feed8258SEric Biggers struct fscrypt_info *crypt_info; 272feed8258SEric Biggers struct fscrypt_context ctx; 273feed8258SEric Biggers struct fscrypt_mode *mode; 274feed8258SEric Biggers int res; 275feed8258SEric Biggers 276feed8258SEric Biggers if (fscrypt_has_encryption_key(inode)) 277feed8258SEric Biggers return 0; 278feed8258SEric Biggers 279feed8258SEric Biggers res = fscrypt_initialize(inode->i_sb->s_cop->flags); 280feed8258SEric Biggers if (res) 281feed8258SEric Biggers return res; 282feed8258SEric Biggers 283feed8258SEric Biggers res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); 284feed8258SEric Biggers if (res < 0) { 285feed8258SEric Biggers if (!fscrypt_dummy_context_enabled(inode) || 286feed8258SEric Biggers IS_ENCRYPTED(inode)) { 287feed8258SEric Biggers fscrypt_warn(inode, 288feed8258SEric Biggers "Error %d getting encryption context", 289feed8258SEric Biggers res); 290feed8258SEric Biggers return res; 291feed8258SEric Biggers } 292feed8258SEric Biggers /* Fake up a context for an unencrypted directory */ 293feed8258SEric Biggers memset(&ctx, 0, sizeof(ctx)); 294feed8258SEric Biggers ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; 295feed8258SEric Biggers ctx.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; 296feed8258SEric Biggers ctx.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; 297feed8258SEric Biggers memset(ctx.master_key_descriptor, 0x42, 298feed8258SEric Biggers FSCRYPT_KEY_DESCRIPTOR_SIZE); 299feed8258SEric Biggers } else if (res != sizeof(ctx)) { 300feed8258SEric Biggers fscrypt_warn(inode, 301feed8258SEric Biggers "Unknown encryption context size (%d bytes)", res); 302feed8258SEric Biggers return -EINVAL; 303feed8258SEric Biggers } 304feed8258SEric Biggers 305feed8258SEric Biggers if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) { 306feed8258SEric Biggers fscrypt_warn(inode, "Unknown encryption context version (%d)", 307feed8258SEric Biggers ctx.format); 308feed8258SEric Biggers return -EINVAL; 309feed8258SEric Biggers } 310feed8258SEric Biggers 311feed8258SEric Biggers if (ctx.flags & ~FSCRYPT_POLICY_FLAGS_VALID) { 312feed8258SEric Biggers fscrypt_warn(inode, "Unknown encryption context flags (0x%02x)", 313feed8258SEric Biggers ctx.flags); 314feed8258SEric Biggers return -EINVAL; 315feed8258SEric Biggers } 316feed8258SEric Biggers 317feed8258SEric Biggers crypt_info = kmem_cache_zalloc(fscrypt_info_cachep, GFP_NOFS); 318feed8258SEric Biggers if (!crypt_info) 319feed8258SEric Biggers return -ENOMEM; 320feed8258SEric Biggers 321feed8258SEric Biggers crypt_info->ci_inode = inode; 322feed8258SEric Biggers 323feed8258SEric Biggers crypt_info->ci_flags = ctx.flags; 324feed8258SEric Biggers crypt_info->ci_data_mode = ctx.contents_encryption_mode; 325feed8258SEric Biggers crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; 326feed8258SEric Biggers memcpy(crypt_info->ci_master_key_descriptor, ctx.master_key_descriptor, 327feed8258SEric Biggers FSCRYPT_KEY_DESCRIPTOR_SIZE); 328feed8258SEric Biggers memcpy(crypt_info->ci_nonce, ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); 329feed8258SEric Biggers 330feed8258SEric Biggers mode = select_encryption_mode(crypt_info, inode); 331feed8258SEric Biggers if (IS_ERR(mode)) { 332feed8258SEric Biggers res = PTR_ERR(mode); 333feed8258SEric Biggers goto out; 334feed8258SEric Biggers } 335feed8258SEric Biggers WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE); 336feed8258SEric Biggers crypt_info->ci_mode = mode; 337feed8258SEric Biggers 338feed8258SEric Biggers res = setup_file_encryption_key(crypt_info); 339feed8258SEric Biggers if (res) 340feed8258SEric Biggers goto out; 341feed8258SEric Biggers 342feed8258SEric Biggers if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) 343feed8258SEric Biggers crypt_info = NULL; 344feed8258SEric Biggers out: 345feed8258SEric Biggers if (res == -ENOKEY) 346feed8258SEric Biggers res = 0; 347feed8258SEric Biggers put_crypt_info(crypt_info); 348feed8258SEric Biggers return res; 349feed8258SEric Biggers } 350feed8258SEric Biggers EXPORT_SYMBOL(fscrypt_get_encryption_info); 351feed8258SEric Biggers 352feed8258SEric Biggers /** 353feed8258SEric Biggers * fscrypt_put_encryption_info - free most of an inode's fscrypt data 354feed8258SEric Biggers * 355feed8258SEric Biggers * Free the inode's fscrypt_info. Filesystems must call this when the inode is 356feed8258SEric Biggers * being evicted. An RCU grace period need not have elapsed yet. 357feed8258SEric Biggers */ 358feed8258SEric Biggers void fscrypt_put_encryption_info(struct inode *inode) 359feed8258SEric Biggers { 360feed8258SEric Biggers put_crypt_info(inode->i_crypt_info); 361feed8258SEric Biggers inode->i_crypt_info = NULL; 362feed8258SEric Biggers } 363feed8258SEric Biggers EXPORT_SYMBOL(fscrypt_put_encryption_info); 364feed8258SEric Biggers 365feed8258SEric Biggers /** 366feed8258SEric Biggers * fscrypt_free_inode - free an inode's fscrypt data requiring RCU delay 367feed8258SEric Biggers * 368feed8258SEric Biggers * Free the inode's cached decrypted symlink target, if any. Filesystems must 369feed8258SEric Biggers * call this after an RCU grace period, just before they free the inode. 370feed8258SEric Biggers */ 371feed8258SEric Biggers void fscrypt_free_inode(struct inode *inode) 372feed8258SEric Biggers { 373feed8258SEric Biggers if (IS_ENCRYPTED(inode) && S_ISLNK(inode->i_mode)) { 374feed8258SEric Biggers kfree(inode->i_link); 375feed8258SEric Biggers inode->i_link = NULL; 376feed8258SEric Biggers } 377feed8258SEric Biggers } 378feed8258SEric Biggers EXPORT_SYMBOL(fscrypt_free_inode); 379