mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
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:
committed by
Treehugger Robot
parent
be794c1c9d
commit
113b9b5027
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user