Commit f592efe7 authored by Eric Biggers's avatar Eric Biggers

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.orgReviewed-by: default avatarDaniel Rosenberg <drosen@google.com>
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
parent aa408f83
...@@ -234,8 +234,8 @@ HKDF is more flexible, is nonreversible, and evenly distributes ...@@ -234,8 +234,8 @@ HKDF is more flexible, is nonreversible, and evenly distributes
entropy from the master key. HKDF is also standardized and widely 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. 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 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 "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. ...@@ -268,9 +268,9 @@ is greater than that of an AES-256-XTS key.
Therefore, to improve performance and save memory, for Adiantum a Therefore, to improve performance and save memory, for Adiantum a
"direct key" configuration is supported. When the user has enabled "direct key" configuration is supported. When the user has enabled
this by setting FSCRYPT_POLICY_FLAG_DIRECT_KEY in the fscrypt policy, this by setting FSCRYPT_POLICY_FLAG_DIRECT_KEY in the fscrypt policy,
per-file keys are not used. Instead, whenever any data (contents or per-file encryption keys are not used. Instead, whenever any data
filenames) is encrypted, the file's 16-byte nonce is included in the (contents or filenames) is encrypted, the file's 16-byte nonce is
IV. Moreover: included in the IV. Moreover:
- For v1 encryption policies, the encryption is done directly with the - For v1 encryption policies, the encryption is done directly with the
master key. Because of this, users **must not** use the same master master key. Because of this, users **must not** use the same master
...@@ -335,11 +335,11 @@ used. ...@@ -335,11 +335,11 @@ used.
Adiantum is a (primarily) stream cipher-based mode that is fast even Adiantum is a (primarily) stream cipher-based mode that is fast even
on CPUs without dedicated crypto instructions. It's also a true on CPUs without dedicated crypto instructions. It's also a true
wide-block mode, unlike XTS. It can also eliminate the need to derive 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, per-file encryption keys. However, it depends on the security of two
XChaCha12 and AES-256, rather than just one. See the paper primitives, XChaCha12 and AES-256, rather than just one. See the
"Adiantum: length-preserving encryption for entry-level processors" paper "Adiantum: length-preserving encryption for entry-level
(https://eprint.iacr.org/2018/720.pdf) for more details. To use processors" (https://eprint.iacr.org/2018/720.pdf) for more details.
Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled. Also, fast To use Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled. Also, fast
implementations of ChaCha and NHPoly1305 should be enabled, e.g. implementations of ChaCha and NHPoly1305 should be enabled, e.g.
CONFIG_CRYPTO_CHACHA20_NEON and CONFIG_CRYPTO_NHPOLY1305_NEON for ARM. 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 ...@@ -1149,8 +1149,8 @@ The context structs contain the same information as the corresponding
policy structs (see `Setting an encryption policy`_), except that the policy structs (see `Setting an encryption policy`_), except that the
context structs also contain a nonce. The nonce is randomly generated 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 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 different files to be encrypted differently; see `Per-file encryption
`DIRECT_KEY policies`_. keys`_ and `DIRECT_KEY policies`_.
Data path changes Data path changes
----------------- -----------------
......
...@@ -269,7 +269,7 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, ...@@ -269,7 +269,7 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
* output doesn't reveal another. * output doesn't reveal another.
*/ */
#define HKDF_CONTEXT_KEY_IDENTIFIER 1 #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_DIRECT_KEY 3
#define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4 #define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4
#define HKDF_CONTEXT_DIRHASH_KEY 5 #define HKDF_CONTEXT_DIRHASH_KEY 5
...@@ -441,8 +441,8 @@ extern struct crypto_skcipher * ...@@ -441,8 +441,8 @@ extern struct crypto_skcipher *
fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
const struct inode *inode); const struct inode *inode);
extern int fscrypt_set_derived_key(struct fscrypt_info *ci, extern int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci,
const u8 *derived_key); const u8 *raw_key);
extern int fscrypt_derive_dirhash_key(struct fscrypt_info *ci, extern int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
const struct fscrypt_master_key *mk); const struct fscrypt_master_key *mk);
......
...@@ -107,12 +107,12 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, ...@@ -107,12 +107,12 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode,
return ERR_PTR(err); return ERR_PTR(err);
} }
/* Given the per-file key, set up the file's crypto transform object */ /* Given a per-file encryption key, set up the file's crypto transform object */
int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key)
{ {
struct crypto_skcipher *tfm; 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)) if (IS_ERR(tfm))
return PTR_ERR(tfm); return PTR_ERR(tfm);
...@@ -121,10 +121,10 @@ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) ...@@ -121,10 +121,10 @@ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key)
return 0; 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 fscrypt_master_key *mk,
struct crypto_skcipher **tfms, struct crypto_skcipher **tfms,
u8 hkdf_context, bool include_fs_uuid) u8 hkdf_context, bool include_fs_uuid)
{ {
const struct inode *inode = ci->ci_inode; const struct inode *inode = ci->ci_inode;
const struct super_block *sb = inode->i_sb; const struct super_block *sb = inode->i_sb;
...@@ -196,15 +196,15 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, ...@@ -196,15 +196,15 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
/* /*
* DIRECT_KEY: instead of deriving per-file keys, the per-file * DIRECT_KEY: instead of deriving per-file encryption keys, the
* nonce will be included in all the IVs. But unlike v1 * per-file nonce will be included in all the IVs. But unlike
* policies, for v2 policies in this case we don't encrypt with * v1 policies, for v2 policies in this case we don't encrypt
* the master key directly but rather derive a per-mode key. * with the master key directly but rather derive a per-mode
* This ensures that the master key is consistently used only * encryption key. This ensures that the master key is
* for HKDF, avoiding key reuse issues. * 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); HKDF_CONTEXT_DIRECT_KEY, false);
} else if (ci->ci_policy.v2.flags & } else if (ci->ci_policy.v2.flags &
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
/* /*
...@@ -213,20 +213,21 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, ...@@ -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 * the IVs. This format is optimized for use with inline
* encryption hardware compliant with the UFS or eMMC standards. * encryption hardware compliant with the UFS or eMMC standards.
*/ */
err = setup_per_mode_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms, err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms,
HKDF_CONTEXT_IV_INO_LBLK_64_KEY, true); HKDF_CONTEXT_IV_INO_LBLK_64_KEY,
true);
} else { } else {
u8 derived_key[FSCRYPT_MAX_KEY_SIZE]; u8 derived_key[FSCRYPT_MAX_KEY_SIZE];
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
HKDF_CONTEXT_PER_FILE_KEY, HKDF_CONTEXT_PER_FILE_ENC_KEY,
ci->ci_nonce, ci->ci_nonce,
FS_KEY_DERIVATION_NONCE_SIZE, FS_KEY_DERIVATION_NONCE_SIZE,
derived_key, ci->ci_mode->keysize); derived_key, ci->ci_mode->keysize);
if (err) if (err)
return 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); memzero_explicit(derived_key, ci->ci_mode->keysize);
} }
if (err) if (err)
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* This file implements compatibility functions for the original encryption * This file implements compatibility functions for the original encryption
* policy version ("v1"), including: * 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) * (rather than the new method of using HKDF-SHA512)
* *
* - Retrieving fscrypt master keys from process-subscribed keyrings * - Retrieving fscrypt master keys from process-subscribed keyrings
...@@ -283,7 +283,7 @@ static int setup_v1_file_key_derived(struct fscrypt_info *ci, ...@@ -283,7 +283,7 @@ static int setup_v1_file_key_derived(struct fscrypt_info *ci,
if (err) if (err)
goto out; goto out;
err = fscrypt_set_derived_key(ci, derived_key); err = fscrypt_set_per_file_enc_key(ci, derived_key);
out: out:
kzfree(derived_key); kzfree(derived_key);
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment