summaryrefslogtreecommitdiffstats
path: root/fs/crypto/keyinfo.c
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-08-04 22:35:45 -0400
committerEric Biggers <ebiggers@google.com>2019-08-12 22:05:51 -0400
commit3ec4f2a62927c72607db633f55b0489e3d5b8e48 (patch)
tree3d0db9c40d623b71b43ec7a99ac9e17bd6d592d9 /fs/crypto/keyinfo.c
parenta828daabb2ae917c12f4dc617c04db1185e6221f (diff)
fscrypt: refactor key setup code in preparation for v2 policies
Do some more refactoring of the key setup code, in preparation for introducing a filesystem-level keyring and v2 encryption policies: - Now that ci_inode exists, don't pass around the inode unnecessarily. - Define a function setup_file_encryption_key() which handles the crypto key setup given an under-construction fscrypt_info. Don't pass the fscrypt_context, since everything is in the fscrypt_info. [This will be extended for v2 policies and the fs-level keyring.] - Define a function fscrypt_set_derived_key() which sets the per-file key, without depending on anything specific to v1 policies. [This will also be used for v2 policies.] - Define a function fscrypt_setup_v1_file_key() which takes the raw master key, thus separating finding the key from using it. [This will also be used if the key is found in the fs-level keyring.] Reviewed-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Eric Biggers <ebiggers@google.com>
Diffstat (limited to 'fs/crypto/keyinfo.c')
-rw-r--r--fs/crypto/keyinfo.c247
1 files changed, 138 insertions, 109 deletions
diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
index c4650071df27..c6bf44d64111 100644
--- a/fs/crypto/keyinfo.c
+++ b/fs/crypto/keyinfo.c
@@ -1,12 +1,11 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2/* 2/*
3 * key management facility for FS encryption support. 3 * Key setup facility for FS encryption support.
4 * 4 *
5 * Copyright (C) 2015, Google, Inc. 5 * Copyright (C) 2015, Google, Inc.
6 * 6 *
7 * This contains encryption key functions. 7 * Originally written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar.
8 * 8 * Heavily modified since then.
9 * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015.
10 */ 9 */
11 10
12#include <keys/user-type.h> 11#include <keys/user-type.h>
@@ -25,14 +24,19 @@ static DEFINE_HASHTABLE(fscrypt_direct_keys, 6); /* 6 bits = 64 buckets */
25static DEFINE_SPINLOCK(fscrypt_direct_keys_lock); 24static DEFINE_SPINLOCK(fscrypt_direct_keys_lock);
26 25
27/* 26/*
28 * Key derivation function. This generates the derived key by encrypting the 27 * v1 key derivation function. This generates the derived key by encrypting the
29 * master key with AES-128-ECB using the inode's nonce as the AES key. 28 * master key with AES-128-ECB using the nonce as the AES key. This provides a
29 * unique derived key with sufficient entropy for each inode. However, it's
30 * nonstandard, non-extensible, doesn't evenly distribute the entropy from the
31 * master key, and is trivially reversible: an attacker who compromises a
32 * derived key can "decrypt" it to get back to the master key, then derive any
33 * other key. For all new code, use HKDF instead.
30 * 34 *
31 * The master key must be at least as long as the derived key. If the master 35 * The master key must be at least as long as the derived key. If the master
32 * key is longer, then only the first 'derived_keysize' bytes are used. 36 * key is longer, then only the first 'derived_keysize' bytes are used.
33 */ 37 */
34static int derive_key_aes(const u8 *master_key, 38static int derive_key_aes(const u8 *master_key,
35 const struct fscrypt_context *ctx, 39 const u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE],
36 u8 *derived_key, unsigned int derived_keysize) 40 u8 *derived_key, unsigned int derived_keysize)
37{ 41{
38 int res = 0; 42 int res = 0;
@@ -55,7 +59,7 @@ static int derive_key_aes(const u8 *master_key,
55 skcipher_request_set_callback(req, 59 skcipher_request_set_callback(req,
56 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, 60 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
57 crypto_req_done, &wait); 61 crypto_req_done, &wait);
58 res = crypto_skcipher_setkey(tfm, ctx->nonce, sizeof(ctx->nonce)); 62 res = crypto_skcipher_setkey(tfm, nonce, FS_KEY_DERIVATION_NONCE_SIZE);
59 if (res < 0) 63 if (res < 0)
60 goto out; 64 goto out;
61 65
@@ -183,54 +187,10 @@ select_encryption_mode(const struct fscrypt_info *ci, const struct inode *inode)
183 return ERR_PTR(-EINVAL); 187 return ERR_PTR(-EINVAL);
184} 188}
185 189
186/* Find the master key, then derive the inode's actual encryption key */ 190/* Create a symmetric cipher object for the given encryption mode and key */
187static int find_and_derive_key(const struct inode *inode,
188 const struct fscrypt_context *ctx,
189 u8 *derived_key, const struct fscrypt_mode *mode)
190{
191 struct key *key;
192 const struct fscrypt_key *payload;
193 int err;
194
195 key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX,
196 ctx->master_key_descriptor,
197 mode->keysize, &payload);
198 if (key == ERR_PTR(-ENOKEY) && inode->i_sb->s_cop->key_prefix) {
199 key = find_and_lock_process_key(inode->i_sb->s_cop->key_prefix,
200 ctx->master_key_descriptor,
201 mode->keysize, &payload);
202 }
203 if (IS_ERR(key))
204 return PTR_ERR(key);
205
206 if (ctx->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
207 if (mode->ivsize < offsetofend(union fscrypt_iv, nonce)) {
208 fscrypt_warn(inode,
209 "Direct key mode not allowed with %s",
210 mode->friendly_name);
211 err = -EINVAL;
212 } else if (ctx->contents_encryption_mode !=
213 ctx->filenames_encryption_mode) {
214 fscrypt_warn(inode,
215 "Direct key mode not allowed with different contents and filenames modes");
216 err = -EINVAL;
217 } else {
218 memcpy(derived_key, payload->raw, mode->keysize);
219 err = 0;
220 }
221 } else {
222 err = derive_key_aes(payload->raw, ctx, derived_key,
223 mode->keysize);
224 }
225 up_read(&key->sem);
226 key_put(key);
227 return err;
228}
229
230/* Allocate and key a symmetric cipher object for the given encryption mode */
231static struct crypto_skcipher * 191static struct crypto_skcipher *
232allocate_skcipher_for_mode(struct fscrypt_mode *mode, const u8 *raw_key, 192fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
233 const struct inode *inode) 193 const struct inode *inode)
234{ 194{
235 struct crypto_skcipher *tfm; 195 struct crypto_skcipher *tfm;
236 int err; 196 int err;
@@ -308,8 +268,7 @@ static void put_direct_key(struct fscrypt_direct_key *dk)
308 */ 268 */
309static struct fscrypt_direct_key * 269static struct fscrypt_direct_key *
310find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, 270find_or_insert_direct_key(struct fscrypt_direct_key *to_insert,
311 const u8 *raw_key, const struct fscrypt_mode *mode, 271 const u8 *raw_key, const struct fscrypt_info *ci)
312 const struct fscrypt_info *ci)
313{ 272{
314 unsigned long hash_key; 273 unsigned long hash_key;
315 struct fscrypt_direct_key *dk; 274 struct fscrypt_direct_key *dk;
@@ -328,9 +287,9 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert,
328 if (memcmp(ci->ci_master_key_descriptor, dk->dk_descriptor, 287 if (memcmp(ci->ci_master_key_descriptor, dk->dk_descriptor,
329 FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) 288 FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0)
330 continue; 289 continue;
331 if (mode != dk->dk_mode) 290 if (ci->ci_mode != dk->dk_mode)
332 continue; 291 continue;
333 if (crypto_memneq(raw_key, dk->dk_raw, mode->keysize)) 292 if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize))
334 continue; 293 continue;
335 /* using existing tfm with same (descriptor, mode, raw_key) */ 294 /* using existing tfm with same (descriptor, mode, raw_key) */
336 refcount_inc(&dk->dk_refcount); 295 refcount_inc(&dk->dk_refcount);
@@ -346,14 +305,13 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert,
346 305
347/* Prepare to encrypt directly using the master key in the given mode */ 306/* Prepare to encrypt directly using the master key in the given mode */
348static struct fscrypt_direct_key * 307static struct fscrypt_direct_key *
349fscrypt_get_direct_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode, 308fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key)
350 const u8 *raw_key, const struct inode *inode)
351{ 309{
352 struct fscrypt_direct_key *dk; 310 struct fscrypt_direct_key *dk;
353 int err; 311 int err;
354 312
355 /* Is there already a tfm for this key? */ 313 /* Is there already a tfm for this key? */
356 dk = find_or_insert_direct_key(NULL, raw_key, mode, ci); 314 dk = find_or_insert_direct_key(NULL, raw_key, ci);
357 if (dk) 315 if (dk)
358 return dk; 316 return dk;
359 317
@@ -362,8 +320,9 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode,
362 if (!dk) 320 if (!dk)
363 return ERR_PTR(-ENOMEM); 321 return ERR_PTR(-ENOMEM);
364 refcount_set(&dk->dk_refcount, 1); 322 refcount_set(&dk->dk_refcount, 1);
365 dk->dk_mode = mode; 323 dk->dk_mode = ci->ci_mode;
366 dk->dk_ctfm = allocate_skcipher_for_mode(mode, raw_key, inode); 324 dk->dk_ctfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key,
325 ci->ci_inode);
367 if (IS_ERR(dk->dk_ctfm)) { 326 if (IS_ERR(dk->dk_ctfm)) {
368 err = PTR_ERR(dk->dk_ctfm); 327 err = PTR_ERR(dk->dk_ctfm);
369 dk->dk_ctfm = NULL; 328 dk->dk_ctfm = NULL;
@@ -371,9 +330,9 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, struct fscrypt_mode *mode,
371 } 330 }
372 memcpy(dk->dk_descriptor, ci->ci_master_key_descriptor, 331 memcpy(dk->dk_descriptor, ci->ci_master_key_descriptor,
373 FSCRYPT_KEY_DESCRIPTOR_SIZE); 332 FSCRYPT_KEY_DESCRIPTOR_SIZE);
374 memcpy(dk->dk_raw, raw_key, mode->keysize); 333 memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize);
375 334
376 return find_or_insert_direct_key(dk, raw_key, mode, ci); 335 return find_or_insert_direct_key(dk, raw_key, ci);
377 336
378err_free_dk: 337err_free_dk:
379 free_direct_key(dk); 338 free_direct_key(dk);
@@ -422,6 +381,9 @@ static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key,
422 struct crypto_cipher *essiv_tfm; 381 struct crypto_cipher *essiv_tfm;
423 u8 salt[SHA256_DIGEST_SIZE]; 382 u8 salt[SHA256_DIGEST_SIZE];
424 383
384 if (WARN_ON(ci->ci_mode->ivsize != AES_BLOCK_SIZE))
385 return -EINVAL;
386
425 essiv_tfm = crypto_alloc_cipher("aes", 0, 0); 387 essiv_tfm = crypto_alloc_cipher("aes", 0, 0);
426 if (IS_ERR(essiv_tfm)) 388 if (IS_ERR(essiv_tfm))
427 return PTR_ERR(essiv_tfm); 389 return PTR_ERR(essiv_tfm);
@@ -446,41 +408,24 @@ out:
446 return err; 408 return err;
447} 409}
448 410
449/* 411/* Given the per-file key, set up the file's crypto transform object(s) */
450 * Given the encryption mode and key (normally the derived key, but for 412static int fscrypt_set_derived_key(struct fscrypt_info *ci,
451 * DIRECT_KEY mode it's the master key), set up the inode's symmetric cipher 413 const u8 *derived_key)
452 * transform object(s).
453 */
454static int setup_crypto_transform(struct fscrypt_info *ci,
455 struct fscrypt_mode *mode,
456 const u8 *raw_key, const struct inode *inode)
457{ 414{
458 struct fscrypt_direct_key *dk; 415 struct fscrypt_mode *mode = ci->ci_mode;
459 struct crypto_skcipher *ctfm; 416 struct crypto_skcipher *ctfm;
460 int err; 417 int err;
461 418
462 if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { 419 ctfm = fscrypt_allocate_skcipher(mode, derived_key, ci->ci_inode);
463 dk = fscrypt_get_direct_key(ci, mode, raw_key, inode); 420 if (IS_ERR(ctfm))
464 if (IS_ERR(dk)) 421 return PTR_ERR(ctfm);
465 return PTR_ERR(dk); 422
466 ctfm = dk->dk_ctfm;
467 } else {
468 dk = NULL;
469 ctfm = allocate_skcipher_for_mode(mode, raw_key, inode);
470 if (IS_ERR(ctfm))
471 return PTR_ERR(ctfm);
472 }
473 ci->ci_direct_key = dk;
474 ci->ci_ctfm = ctfm; 423 ci->ci_ctfm = ctfm;
475 424
476 if (mode->needs_essiv) { 425 if (mode->needs_essiv) {
477 /* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */ 426 err = init_essiv_generator(ci, derived_key, mode->keysize);
478 WARN_ON(mode->ivsize != AES_BLOCK_SIZE);
479 WARN_ON(ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY);
480
481 err = init_essiv_generator(ci, raw_key, mode->keysize);
482 if (err) { 427 if (err) {
483 fscrypt_warn(inode, 428 fscrypt_warn(ci->ci_inode,
484 "Error initializing ESSIV generator: %d", 429 "Error initializing ESSIV generator: %d",
485 err); 430 err);
486 return err; 431 return err;
@@ -489,6 +434,105 @@ static int setup_crypto_transform(struct fscrypt_info *ci,
489 return 0; 434 return 0;
490} 435}
491 436
437/* v1 policy, DIRECT_KEY: use the master key directly */
438static int setup_v1_file_key_direct(struct fscrypt_info *ci,
439 const u8 *raw_master_key)
440{
441 const struct fscrypt_mode *mode = ci->ci_mode;
442 struct fscrypt_direct_key *dk;
443
444 if (!fscrypt_mode_supports_direct_key(mode)) {
445 fscrypt_warn(ci->ci_inode,
446 "Direct key mode not allowed with %s",
447 mode->friendly_name);
448 return -EINVAL;
449 }
450
451 if (ci->ci_data_mode != ci->ci_filename_mode) {
452 fscrypt_warn(ci->ci_inode,
453 "Direct key mode not allowed with different contents and filenames modes");
454 return -EINVAL;
455 }
456
457 /* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */
458 if (WARN_ON(mode->needs_essiv))
459 return -EINVAL;
460
461 dk = fscrypt_get_direct_key(ci, raw_master_key);
462 if (IS_ERR(dk))
463 return PTR_ERR(dk);
464 ci->ci_direct_key = dk;
465 ci->ci_ctfm = dk->dk_ctfm;
466 return 0;
467}
468
469/* v1 policy, !DIRECT_KEY: derive the file's encryption key */
470static int setup_v1_file_key_derived(struct fscrypt_info *ci,
471 const u8 *raw_master_key)
472{
473 u8 *derived_key;
474 int err;
475
476 /*
477 * This cannot be a stack buffer because it will be passed to the
478 * scatterlist crypto API during derive_key_aes().
479 */
480 derived_key = kmalloc(ci->ci_mode->keysize, GFP_NOFS);
481 if (!derived_key)
482 return -ENOMEM;
483
484 err = derive_key_aes(raw_master_key, ci->ci_nonce,
485 derived_key, ci->ci_mode->keysize);
486 if (err)
487 goto out;
488
489 err = fscrypt_set_derived_key(ci, derived_key);
490out:
491 kzfree(derived_key);
492 return err;
493}
494
495static int fscrypt_setup_v1_file_key(struct fscrypt_info *ci,
496 const u8 *raw_master_key)
497{
498 if (ci->ci_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY)
499 return setup_v1_file_key_direct(ci, raw_master_key);
500 else
501 return setup_v1_file_key_derived(ci, raw_master_key);
502}
503
504static int fscrypt_setup_v1_file_key_via_subscribed_keyrings(
505 struct fscrypt_info *ci)
506{
507 struct key *key;
508 const struct fscrypt_key *payload;
509 int err;
510
511 key = find_and_lock_process_key(FSCRYPT_KEY_DESC_PREFIX,
512 ci->ci_master_key_descriptor,
513 ci->ci_mode->keysize, &payload);
514 if (key == ERR_PTR(-ENOKEY) && ci->ci_inode->i_sb->s_cop->key_prefix) {
515 key = find_and_lock_process_key(ci->ci_inode->i_sb->s_cop->key_prefix,
516 ci->ci_master_key_descriptor,
517 ci->ci_mode->keysize, &payload);
518 }
519 if (IS_ERR(key))
520 return PTR_ERR(key);
521
522 err = fscrypt_setup_v1_file_key(ci, payload->raw);
523 up_read(&key->sem);
524 key_put(key);
525 return err;
526}
527
528/*
529 * Find the master key, then set up the inode's actual encryption key.
530 */
531static int setup_file_encryption_key(struct fscrypt_info *ci)
532{
533 return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci);
534}
535
492static void put_crypt_info(struct fscrypt_info *ci) 536static void put_crypt_info(struct fscrypt_info *ci)
493{ 537{
494 if (!ci) 538 if (!ci)
@@ -508,7 +552,6 @@ int fscrypt_get_encryption_info(struct inode *inode)
508 struct fscrypt_info *crypt_info; 552 struct fscrypt_info *crypt_info;
509 struct fscrypt_context ctx; 553 struct fscrypt_context ctx;
510 struct fscrypt_mode *mode; 554 struct fscrypt_mode *mode;
511 u8 *raw_key = NULL;
512 int res; 555 int res;
513 556
514 if (fscrypt_has_encryption_key(inode)) 557 if (fscrypt_has_encryption_key(inode))
@@ -573,20 +616,7 @@ int fscrypt_get_encryption_info(struct inode *inode)
573 WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE); 616 WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
574 crypt_info->ci_mode = mode; 617 crypt_info->ci_mode = mode;
575 618
576 /* 619 res = setup_file_encryption_key(crypt_info);
577 * This cannot be a stack buffer because it may be passed to the
578 * scatterlist crypto API as part of key derivation.
579 */
580 res = -ENOMEM;
581 raw_key = kmalloc(mode->keysize, GFP_NOFS);
582 if (!raw_key)
583 goto out;
584
585 res = find_and_derive_key(inode, &ctx, raw_key, mode);
586 if (res)
587 goto out;
588
589 res = setup_crypto_transform(crypt_info, mode, raw_key, inode);
590 if (res) 620 if (res)
591 goto out; 621 goto out;
592 622
@@ -596,7 +626,6 @@ out:
596 if (res == -ENOKEY) 626 if (res == -ENOKEY)
597 res = 0; 627 res = 0;
598 put_crypt_info(crypt_info); 628 put_crypt_info(crypt_info);
599 kzfree(raw_key);
600 return res; 629 return res;
601} 630}
602EXPORT_SYMBOL(fscrypt_get_encryption_info); 631EXPORT_SYMBOL(fscrypt_get_encryption_info);