ANDROID: update "fscrypt: add support for hardware-wrapped keys" to v7

The hardware-wrapped key support in this branch is based on my patch
"[RFC PATCH v3 3/3] fscrypt: add support for hardware-wrapped keys"
(https://lore.kernel.org/r/20211021181608.54127-4-ebiggers@kernel.org)
I've since made several updates to that patch and it is now at v7.

This commit brings in the updates from v3 to v7, to the extent possible
while retaining compatibility with the UAPI and on-disk format used for
this feature in Android.  This mainly includes some improved log
messages, and compatibility with the blk-crypto updates.

Bug: 160883801
Link: https://lore.kernel.org/all/20221216203636.81491-5-ebiggers@kernel.org
Change-Id: I1c43ca55ec7e95dd06f8f7944100ffd14771d3a7
Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
Eric Biggers
2022-12-16 22:52:13 +00:00
committed by Treehugger Robot
parent be794c1c9d
commit 113b9b5027
4 changed files with 38 additions and 44 deletions

View File

@@ -363,16 +363,15 @@ fscrypt_using_inline_encryption(const struct fscrypt_info *ci)
}
int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key,
unsigned int raw_key_size,
const u8 *raw_key, size_t raw_key_size,
bool is_hw_wrapped,
const struct fscrypt_info *ci);
void fscrypt_destroy_inline_crypt_key(struct super_block *sb,
struct fscrypt_prepared_key *prep_key);
int fscrypt_derive_sw_secret(struct super_block *sb, const u8 *wrapped_key,
unsigned int wrapped_key_size,
int fscrypt_derive_sw_secret(struct super_block *sb,
const u8 *wrapped_key, size_t wrapped_key_size,
u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
/*
@@ -385,7 +384,7 @@ fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
{
/*
* The two smp_load_acquire()'s here pair with the smp_store_release()'s
* in fscrypt_prepare_inline_crypt_key() and __fscrypt_prepare_key().
* in fscrypt_prepare_inline_crypt_key() and fscrypt_prepare_key().
* I.e., in some cases (namely, if this prep_key is a per-mode
* encryption key) another task can publish blk_key or tfm concurrently,
* executing a RELEASE barrier. We need to use smp_load_acquire() here
@@ -412,7 +411,7 @@ fscrypt_using_inline_encryption(const struct fscrypt_info *ci)
static inline int
fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key, unsigned int raw_key_size,
const u8 *raw_key, size_t raw_key_size,
bool is_hw_wrapped,
const struct fscrypt_info *ci)
{
@@ -427,8 +426,8 @@ fscrypt_destroy_inline_crypt_key(struct super_block *sb,
}
static inline int
fscrypt_derive_sw_secret(struct super_block *sb, const u8 *wrapped_key,
unsigned int wrapped_key_size,
fscrypt_derive_sw_secret(struct super_block *sb,
const u8 *wrapped_key, size_t wrapped_key_size,
u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
{
fscrypt_warn(NULL, "kernel doesn't support hardware-wrapped keys");

View File

@@ -155,8 +155,7 @@ out_free_devs:
}
int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key,
unsigned int raw_key_size,
const u8 *raw_key, size_t raw_key_size,
bool is_hw_wrapped,
const struct fscrypt_info *ci)
{
@@ -240,19 +239,22 @@ void fscrypt_destroy_inline_crypt_key(struct super_block *sb,
* hardware-wrapped key. Returns -EOPNOTSUPP if hardware-wrapped keys aren't
* supported on this filesystem or hardware.
*/
int fscrypt_derive_sw_secret(struct super_block *sb, const u8 *wrapped_key,
unsigned int wrapped_key_size,
int fscrypt_derive_sw_secret(struct super_block *sb,
const u8 *wrapped_key, size_t wrapped_key_size,
u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
{
struct blk_crypto_profile *profile;
struct block_device **devs;
unsigned int num_devs;
unsigned int i;
int err;
/* The filesystem must be mounted with -o inlinecrypt */
if (!(sb->s_flags & SB_INLINECRYPT))
/* The filesystem must be mounted with -o inlinecrypt. */
if (!(sb->s_flags & SB_INLINECRYPT)) {
fscrypt_warn(NULL,
"%s: filesystem not mounted with inlinecrypt\n",
sb->s_id);
return -EOPNOTSUPP;
}
/*
* Hardware-wrapped keys might be specific to a particular storage
@@ -263,17 +265,21 @@ int fscrypt_derive_sw_secret(struct super_block *sb, const u8 *wrapped_key,
devs = fscrypt_get_devices(sb, &num_devs);
if (IS_ERR(devs))
return PTR_ERR(devs);
profile = bdev_get_queue(devs[0])->crypto_profile;
for (i = 1; i < num_devs; i++) {
if (bdev_get_queue(devs[i])->crypto_profile != profile) {
if (!blk_crypto_hw_wrapped_keys_compatible(devs[0], devs[i])) {
fscrypt_warn(NULL,
"unsupported multi-device configuration for hardware-wrapped keys");
"%s: unsupported multi-device configuration for hardware-wrapped keys",
sb->s_id);
kfree(devs);
return -EOPNOTSUPP;
}
}
err = blk_crypto_derive_sw_secret(profile, wrapped_key,
err = blk_crypto_derive_sw_secret(devs[0], wrapped_key,
wrapped_key_size, sw_secret);
if (err == -EOPNOTSUPP)
fscrypt_warn(NULL,
"%s: block device doesn't support hardware-wrapped keys\n",
sb->s_id);
kfree(devs);
return err;
}

View File

@@ -782,11 +782,11 @@ fscrypt_get_test_dummy_secret(struct fscrypt_master_key_secret *secret)
{
static u8 test_key[FSCRYPT_MAX_STANDARD_KEY_SIZE];
get_random_once(test_key, FSCRYPT_MAX_STANDARD_KEY_SIZE);
get_random_once(test_key, sizeof(test_key));
memset(secret, 0, sizeof(*secret));
secret->size = FSCRYPT_MAX_STANDARD_KEY_SIZE;
memcpy(secret->raw, test_key, FSCRYPT_MAX_STANDARD_KEY_SIZE);
secret->size = sizeof(test_key);
memcpy(secret->raw, test_key, sizeof(test_key));
}
int fscrypt_get_test_dummy_key_identifier(

View File

@@ -130,23 +130,17 @@ err_free_tfm:
* Prepare the crypto transform object or blk-crypto key in @prep_key, given the
* raw key, encryption mode (@ci->ci_mode), flag indicating which encryption
* implementation (fs-layer or blk-crypto) will be used (@ci->ci_inlinecrypt),
* and IV generation method (@ci->ci_policy.flags). The raw key can be either a
* standard key or a hardware-wrapped key, as indicated by @is_hw_wrapped; it
* can only be a hardware-wrapped key if blk-crypto will be used.
* and IV generation method (@ci->ci_policy.flags).
*/
static int __fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key, unsigned int raw_key_size,
bool is_hw_wrapped,
const struct fscrypt_info *ci)
int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key, const struct fscrypt_info *ci)
{
struct crypto_skcipher *tfm;
if (fscrypt_using_inline_encryption(ci))
return fscrypt_prepare_inline_crypt_key(prep_key,
raw_key, raw_key_size, is_hw_wrapped, ci);
if (WARN_ON(is_hw_wrapped || raw_key_size != ci->ci_mode->keysize))
return -EINVAL;
return fscrypt_prepare_inline_crypt_key(prep_key, raw_key,
ci->ci_mode->keysize,
false, ci);
tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode);
if (IS_ERR(tfm))
@@ -161,13 +155,6 @@ static int __fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
return 0;
}
int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key, const struct fscrypt_info *ci)
{
return __fscrypt_prepare_key(prep_key, raw_key, ci->ci_mode->keysize,
false, ci);
}
/* Destroy a crypto transform object and/or blk-crypto key. */
void fscrypt_destroy_prepared_key(struct super_block *sb,
struct fscrypt_prepared_key *prep_key)
@@ -208,7 +195,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
if (!fscrypt_using_inline_encryption(ci)) {
if (sb->s_flags & SB_INLINECRYPT)
fscrypt_warn(ci->ci_inode,
"Hardware-wrapped key required, but no suitable inline encryption hardware is available");
"Hardware-wrapped key required, but no suitable inline encryption capabilities are available");
else
fscrypt_warn(ci->ci_inode,
"Hardware-wrapped keys require inline encryption (-o inlinecrypt)");
@@ -229,8 +216,10 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
goto done_unlock;
if (use_hw_wrapped_key) {
err = __fscrypt_prepare_key(prep_key, mk->mk_secret.raw,
mk->mk_secret.size, true, ci);
err = fscrypt_prepare_inline_crypt_key(prep_key,
mk->mk_secret.raw,
mk->mk_secret.size, true,
ci);
if (err)
goto out_unlock;
goto done_unlock;