fscrypt: add inline encryption support
Add support for inline encryption to fs/crypto/. With "inline encryption", the block layer handles the decryption/encryption as part of the bio, instead of the filesystem doing the crypto itself via Linux's crypto API. This model is needed in order to take advantage of the inline encryption hardware present on most modern mobile SoCs. To use inline encryption, the filesystem needs to be mounted with '-o inlinecrypt'. Blk-crypto will then be used instead of the traditional filesystem-layer crypto whenever possible to encrypt the contents of any encrypted files in that filesystem. Fscrypt still provides the key and IV to use, and the actual ciphertext on-disk is still the same; therefore it's testable using the existing fscrypt ciphertext verification tests. Note that since blk-crypto has a fallback to Linux's crypto API, and also supports all the encryption modes currently supported by fscrypt, this feature is usable and testable even without actual inline encryption hardware. Per-filesystem changes will be needed to set encryption contexts when submitting bios and to implement the 'inlinecrypt' mount option. This patch just adds the common code. Signed-off-by: Satya Tangirala <satyat@google.com> Reviewed-by: Jaegeuk Kim <jaegeuk@kernel.org> Reviewed-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Theodore Ts'o <tytso@mit.edu> Link: https://lore.kernel.org/r/20200702015607.1215430-3-satyat@google.com Co-developed-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:

committed by
Eric Biggers

parent
457e7a135c
commit
5fee36095c
@@ -146,7 +146,7 @@ struct fscrypt_direct_key {
|
||||
struct hlist_node dk_node;
|
||||
refcount_t dk_refcount;
|
||||
const struct fscrypt_mode *dk_mode;
|
||||
struct crypto_skcipher *dk_ctfm;
|
||||
struct fscrypt_prepared_key dk_key;
|
||||
u8 dk_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
|
||||
u8 dk_raw[FSCRYPT_MAX_KEY_SIZE];
|
||||
};
|
||||
@@ -154,7 +154,7 @@ struct fscrypt_direct_key {
|
||||
static void free_direct_key(struct fscrypt_direct_key *dk)
|
||||
{
|
||||
if (dk) {
|
||||
crypto_free_skcipher(dk->dk_ctfm);
|
||||
fscrypt_destroy_prepared_key(&dk->dk_key);
|
||||
kzfree(dk);
|
||||
}
|
||||
}
|
||||
@@ -199,6 +199,8 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert,
|
||||
continue;
|
||||
if (ci->ci_mode != dk->dk_mode)
|
||||
continue;
|
||||
if (!fscrypt_is_key_prepared(&dk->dk_key, ci))
|
||||
continue;
|
||||
if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize))
|
||||
continue;
|
||||
/* using existing tfm with same (descriptor, mode, raw_key) */
|
||||
@@ -231,13 +233,9 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
refcount_set(&dk->dk_refcount, 1);
|
||||
dk->dk_mode = ci->ci_mode;
|
||||
dk->dk_ctfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key,
|
||||
ci->ci_inode);
|
||||
if (IS_ERR(dk->dk_ctfm)) {
|
||||
err = PTR_ERR(dk->dk_ctfm);
|
||||
dk->dk_ctfm = NULL;
|
||||
err = fscrypt_prepare_key(&dk->dk_key, raw_key, ci);
|
||||
if (err)
|
||||
goto err_free_dk;
|
||||
}
|
||||
memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor,
|
||||
FSCRYPT_KEY_DESCRIPTOR_SIZE);
|
||||
memcpy(dk->dk_raw, raw_key, ci->ci_mode->keysize);
|
||||
@@ -259,7 +257,7 @@ static int setup_v1_file_key_direct(struct fscrypt_info *ci,
|
||||
if (IS_ERR(dk))
|
||||
return PTR_ERR(dk);
|
||||
ci->ci_direct_key = dk;
|
||||
ci->ci_ctfm = dk->dk_ctfm;
|
||||
ci->ci_enc_key = dk->dk_key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user