Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 216d8cab authored by Eric Biggers's avatar Eric Biggers Committed by Jaegeuk Kim
Browse files

fscrypt: clarify what is meant by a per-file key

Now that there's sometimes a second type of per-file key (the dirhash
key), clarify some function names, macros, and documentation that
specifically deal with per-file *encryption* keys.

Link: https://lore.kernel.org/r/20200120223201.241390-4-ebiggers@kernel.org


Reviewed-by: default avatarDaniel Rosenberg <drosen@google.com>
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
parent 7e250323
Loading
Loading
Loading
Loading
+12 −12
Original line number Diff line number Diff line
@@ -234,8 +234,8 @@ HKDF is more flexible, is nonreversible, and evenly distributes
entropy from the master key.  HKDF is also standardized and widely
used by other software, whereas the AES-128-ECB based KDF is ad-hoc.

Per-file keys
-------------
Per-file encryption keys
------------------------

Since each master key can protect many files, it is necessary to
"tweak" the encryption of each file so that the same plaintext in two
@@ -268,9 +268,9 @@ is greater than that of an AES-256-XTS key.
Therefore, to improve performance and save memory, for Adiantum a
"direct key" configuration is supported.  When the user has enabled
this by setting FSCRYPT_POLICY_FLAG_DIRECT_KEY in the fscrypt policy,
per-file keys are not used.  Instead, whenever any data (contents or
filenames) is encrypted, the file's 16-byte nonce is included in the
IV.  Moreover:
per-file encryption keys are not used.  Instead, whenever any data
(contents or filenames) is encrypted, the file's 16-byte nonce is
included in the IV.  Moreover:

- For v1 encryption policies, the encryption is done directly with the
  master key.  Because of this, users **must not** use the same master
@@ -335,11 +335,11 @@ used.
Adiantum is a (primarily) stream cipher-based mode that is fast even
on CPUs without dedicated crypto instructions.  It's also a true
wide-block mode, unlike XTS.  It can also eliminate the need to derive
per-file keys.  However, it depends on the security of two primitives,
XChaCha12 and AES-256, rather than just one.  See the paper
"Adiantum: length-preserving encryption for entry-level processors"
(https://eprint.iacr.org/2018/720.pdf) for more details.  To use
Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled.  Also, fast
per-file encryption keys.  However, it depends on the security of two
primitives, XChaCha12 and AES-256, rather than just one.  See the
paper "Adiantum: length-preserving encryption for entry-level
processors" (https://eprint.iacr.org/2018/720.pdf) for more details.
To use Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled.  Also, fast
implementations of ChaCha and NHPoly1305 should be enabled, e.g.
CONFIG_CRYPTO_CHACHA20_NEON and CONFIG_CRYPTO_NHPOLY1305_NEON for ARM.

@@ -1149,8 +1149,8 @@ The context structs contain the same information as the corresponding
policy structs (see `Setting an encryption policy`_), except that the
context structs also contain a nonce.  The nonce is randomly generated
by the kernel and is used as KDF input or as a tweak to cause
different files to be encrypted differently; see `Per-file keys`_ and
`DIRECT_KEY policies`_.
different files to be encrypted differently; see `Per-file encryption
keys`_ and `DIRECT_KEY policies`_.

Data path changes
-----------------
+3 −3
Original line number Diff line number Diff line
@@ -269,7 +269,7 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
 * output doesn't reveal another.
 */
#define HKDF_CONTEXT_KEY_IDENTIFIER	1
#define HKDF_CONTEXT_PER_FILE_KEY	2
#define HKDF_CONTEXT_PER_FILE_ENC_KEY	2
#define HKDF_CONTEXT_DIRECT_KEY		3
#define HKDF_CONTEXT_IV_INO_LBLK_64_KEY	4
#define HKDF_CONTEXT_DIRHASH_KEY	5
@@ -441,8 +441,8 @@ extern struct crypto_skcipher *
fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
			  const struct inode *inode);

extern int fscrypt_set_derived_key(struct fscrypt_info *ci,
				   const u8 *derived_key);
extern int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci,
					const u8 *raw_key);

extern int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
				      const struct fscrypt_master_key *mk);
+20 −19
Original line number Diff line number Diff line
@@ -107,12 +107,12 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode,
	return ERR_PTR(err);
}

/* Given the per-file key, set up the file's crypto transform object */
int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key)
/* Given a per-file encryption key, set up the file's crypto transform object */
int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key)
{
	struct crypto_skcipher *tfm;

	tfm = fscrypt_allocate_skcipher(ci->ci_mode, derived_key, ci->ci_inode);
	tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode);
	if (IS_ERR(tfm))
		return PTR_ERR(tfm);

@@ -121,7 +121,7 @@ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key)
	return 0;
}

static int setup_per_mode_key(struct fscrypt_info *ci,
static int setup_per_mode_enc_key(struct fscrypt_info *ci,
				  struct fscrypt_master_key *mk,
				  struct crypto_skcipher **tfms,
				  u8 hkdf_context, bool include_fs_uuid)
@@ -196,14 +196,14 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,

	if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
		/*
		 * DIRECT_KEY: instead of deriving per-file keys, the per-file
		 * nonce will be included in all the IVs.  But unlike v1
		 * policies, for v2 policies in this case we don't encrypt with
		 * the master key directly but rather derive a per-mode key.
		 * This ensures that the master key is consistently used only
		 * for HKDF, avoiding key reuse issues.
		 * DIRECT_KEY: instead of deriving per-file encryption keys, the
		 * per-file nonce will be included in all the IVs.  But unlike
		 * v1 policies, for v2 policies in this case we don't encrypt
		 * with the master key directly but rather derive a per-mode
		 * encryption key.  This ensures that the master key is
		 * consistently used only for HKDF, avoiding key reuse issues.
		 */
		err = setup_per_mode_key(ci, mk, mk->mk_direct_tfms,
		err = setup_per_mode_enc_key(ci, mk, mk->mk_direct_tfms,
					     HKDF_CONTEXT_DIRECT_KEY, false);
	} else if (ci->ci_policy.v2.flags &
		   FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
@@ -213,20 +213,21 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
		 * the IVs.  This format is optimized for use with inline
		 * encryption hardware compliant with the UFS or eMMC standards.
		 */
		err = setup_per_mode_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms,
					 HKDF_CONTEXT_IV_INO_LBLK_64_KEY, true);
		err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms,
					     HKDF_CONTEXT_IV_INO_LBLK_64_KEY,
					     true);
	} else {
		u8 derived_key[FSCRYPT_MAX_KEY_SIZE];

		err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
					  HKDF_CONTEXT_PER_FILE_KEY,
					  HKDF_CONTEXT_PER_FILE_ENC_KEY,
					  ci->ci_nonce,
					  FS_KEY_DERIVATION_NONCE_SIZE,
					  derived_key, ci->ci_mode->keysize);
		if (err)
			return err;

		err = fscrypt_set_derived_key(ci, derived_key);
		err = fscrypt_set_per_file_enc_key(ci, derived_key);
		memzero_explicit(derived_key, ci->ci_mode->keysize);
	}
	if (err)
+2 −2
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
 * This file implements compatibility functions for the original encryption
 * policy version ("v1"), including:
 *
 * - Deriving per-file keys using the AES-128-ECB based KDF
 * - Deriving per-file encryption keys using the AES-128-ECB based KDF
 *   (rather than the new method of using HKDF-SHA512)
 *
 * - Retrieving fscrypt master keys from process-subscribed keyrings
@@ -283,7 +283,7 @@ static int setup_v1_file_key_derived(struct fscrypt_info *ci,
	if (err)
		goto out;

	err = fscrypt_set_derived_key(ci, derived_key);
	err = fscrypt_set_per_file_enc_key(ci, derived_key);
out:
	kzfree(derived_key);
	return err;