Revert "ANDROID: fscrypt: add support for hardware-wrapped keys"

This reverts ANDROID-fscrypt-add-support-for-hardware-wrapped-keys.patch
because it is part of the hardware-wrapped keys feature, which conflicts
heavily with upstream refactoring in 5.16.  I've also reworked the
hardware-wrapped key patches when proposing them upstream
(https://lore.kernel.org/linux-block/20210916174928.65529-1-ebiggers@kernel.org).

To unblock the 5.16 merge, revert the hardware-wrapped key patches for
now.  I'll apply a new version of them after the 5.16 merge.

Bug: 160883801
Change-Id: I891e1f5ba0632bf9d77199420261691d16adbc09
Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
Eric Biggers
2021-10-21 10:15:50 -07:00
parent d1a66e7942
commit 3eb33e7e86
6 changed files with 47 additions and 178 deletions
+6 -38
View File
@@ -22,8 +22,6 @@
#define FSCRYPT_MIN_KEY_SIZE 16
#define FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE 128
#define FSCRYPT_CONTEXT_V1 1
#define FSCRYPT_CONTEXT_V2 2
@@ -332,8 +330,7 @@ void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf);
/* inline_crypt.c */
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
bool is_hw_wrapped_key);
int fscrypt_select_encryption_impl(struct fscrypt_info *ci);
static inline bool
fscrypt_using_inline_encryption(const struct fscrypt_info *ci)
@@ -343,18 +340,10 @@ 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,
bool is_hw_wrapped,
const struct fscrypt_info *ci);
void fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key);
extern int fscrypt_derive_raw_secret(struct super_block *sb,
const u8 *wrapped_key,
unsigned int wrapped_key_size,
u8 *raw_secret,
unsigned int raw_secret_size);
/*
* Check whether the crypto transform or blk-crypto key has been allocated in
* @prep_key, depending on which encryption implementation the file will use.
@@ -378,8 +367,7 @@ fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
static inline int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
bool is_hw_wrapped_key)
static inline int fscrypt_select_encryption_impl(struct fscrypt_info *ci)
{
return 0;
}
@@ -392,8 +380,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,
bool is_hw_wrapped,
const u8 *raw_key,
const struct fscrypt_info *ci)
{
WARN_ON(1);
@@ -405,17 +392,6 @@ fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key)
{
}
static inline int fscrypt_derive_raw_secret(struct super_block *sb,
const u8 *wrapped_key,
unsigned int wrapped_key_size,
u8 *raw_secret,
unsigned int raw_secret_size)
{
fscrypt_warn(NULL,
"kernel built without support for hardware-wrapped keys");
return -EOPNOTSUPP;
}
static inline bool
fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
const struct fscrypt_info *ci)
@@ -440,15 +416,8 @@ struct fscrypt_master_key_secret {
/* Size of the raw key in bytes. Set even if ->raw isn't set. */
u32 size;
/* True if the key in ->raw is a hardware-wrapped key. */
bool is_hw_wrapped;
/*
* For v1 policy keys: the raw key. Wiped for v2 policy keys, unless
* ->is_hw_wrapped is true, in which case this contains the wrapped key
* rather than the key with which 'hkdf' was keyed.
*/
u8 raw[FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE];
/* For v1 policy keys: the raw key. Wiped for v2 policy keys. */
u8 raw[FSCRYPT_MAX_KEY_SIZE];
} __randomize_layout;
@@ -589,8 +558,7 @@ struct fscrypt_mode {
extern struct fscrypt_mode fscrypt_modes[];
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);
const u8 *raw_key, const struct fscrypt_info *ci);
void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key);
+5 -27
View File
@@ -15,7 +15,6 @@
#include <linux/blk-crypto.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include <linux/keyslot-manager.h>
#include <linux/sched/mm.h>
#include <linux/slab.h>
#include <linux/uio.h>
@@ -66,8 +65,7 @@ static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci)
}
/* Enable inline encryption for this file if supported. */
int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
bool is_hw_wrapped_key)
int fscrypt_select_encryption_impl(struct fscrypt_info *ci)
{
const struct inode *inode = ci->ci_inode;
struct super_block *sb = inode->i_sb;
@@ -108,7 +106,7 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
crypto_cfg.crypto_mode = ci->ci_mode->blk_crypto_mode;
crypto_cfg.data_unit_size = sb->s_blocksize;
crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci);
crypto_cfg.is_hw_wrapped = is_hw_wrapped_key;
crypto_cfg.is_hw_wrapped = false;
num_devs = fscrypt_get_num_devices(sb);
devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL);
if (!devs)
@@ -129,8 +127,6 @@ out_free_devs:
int fscrypt_prepare_inline_crypt_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)
{
const struct inode *inode = ci->ci_inode;
@@ -149,12 +145,9 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
blk_key->num_devs = num_devs;
fscrypt_get_devices(sb, num_devs, blk_key->devs);
BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE >
BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE);
err = blk_crypto_init_key(&blk_key->base, raw_key, raw_key_size,
is_hw_wrapped, crypto_mode,
fscrypt_get_dun_bytes(ci), sb->s_blocksize);
err = blk_crypto_init_key(&blk_key->base, raw_key, ci->ci_mode->keysize,
false, crypto_mode, fscrypt_get_dun_bytes(ci),
sb->s_blocksize);
if (err) {
fscrypt_err(inode, "error %d initializing blk-crypto key", err);
goto fail;
@@ -213,21 +206,6 @@ void fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key)
}
}
int fscrypt_derive_raw_secret(struct super_block *sb,
const u8 *wrapped_key,
unsigned int wrapped_key_size,
u8 *raw_secret, unsigned int raw_secret_size)
{
struct request_queue *q;
q = bdev_get_queue(sb->s_bdev);
if (!q->ksm)
return -EOPNOTSUPP;
return blk_ksm_derive_raw_secret(q->ksm, wrapped_key, wrapped_key_size,
raw_secret, raw_secret_size);
}
bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
{
return inode->i_crypt_info->ci_inlinecrypt;
+10 -40
View File
@@ -472,9 +472,6 @@ out_unlock:
return err;
}
/* Size of software "secret" derived from hardware-wrapped key */
#define RAW_SECRET_SIZE 32
static int add_master_key(struct super_block *sb,
struct fscrypt_master_key_secret *secret,
struct fscrypt_key_specifier *key_spec)
@@ -482,28 +479,17 @@ static int add_master_key(struct super_block *sb,
int err;
if (key_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
u8 _kdf_key[RAW_SECRET_SIZE];
u8 *kdf_key = secret->raw;
unsigned int kdf_key_size = secret->size;
if (secret->is_hw_wrapped) {
kdf_key = _kdf_key;
kdf_key_size = RAW_SECRET_SIZE;
err = fscrypt_derive_raw_secret(sb, secret->raw,
secret->size,
kdf_key, kdf_key_size);
if (err)
return err;
}
err = fscrypt_init_hkdf(&secret->hkdf, kdf_key, kdf_key_size);
/*
* Now that the HKDF context is initialized, the raw HKDF key is
* no longer needed.
*/
memzero_explicit(kdf_key, kdf_key_size);
err = fscrypt_init_hkdf(&secret->hkdf, secret->raw,
secret->size);
if (err)
return err;
/*
* Now that the HKDF context is initialized, the raw key is no
* longer needed.
*/
memzero_explicit(secret->raw, secret->size);
/* Calculate the key identifier */
err = fscrypt_hkdf_expand(&secret->hkdf,
HKDF_CONTEXT_KEY_IDENTIFIER, NULL, 0,
@@ -519,10 +505,8 @@ static int fscrypt_provisioning_key_preparse(struct key_preparsed_payload *prep)
{
const struct fscrypt_provisioning_key_payload *payload = prep->data;
BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE < FSCRYPT_MAX_KEY_SIZE);
if (prep->datalen < sizeof(*payload) + FSCRYPT_MIN_KEY_SIZE ||
prep->datalen > sizeof(*payload) + FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE)
prep->datalen > sizeof(*payload) + FSCRYPT_MAX_KEY_SIZE)
return -EINVAL;
if (payload->type != FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR &&
@@ -671,29 +655,15 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg)
return -EACCES;
memset(&secret, 0, sizeof(secret));
if (arg.__flags) {
if (arg.__flags & ~__FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED)
return -EINVAL;
if (arg.key_spec.type != FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER)
return -EINVAL;
secret.is_hw_wrapped = true;
}
if (arg.key_id) {
if (arg.raw_size != 0)
return -EINVAL;
err = get_keyring_key(arg.key_id, arg.key_spec.type, &secret);
if (err)
goto out_wipe_secret;
err = -EINVAL;
if (secret.size > FSCRYPT_MAX_KEY_SIZE && !secret.is_hw_wrapped)
goto out_wipe_secret;
} else {
if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE ||
arg.raw_size > (secret.is_hw_wrapped ?
FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE :
FSCRYPT_MAX_KEY_SIZE))
arg.raw_size > FSCRYPT_MAX_KEY_SIZE)
return -EINVAL;
secret.size = arg.raw_size;
err = -EFAULT;
+24 -67
View File
@@ -121,17 +121,12 @@ err_free_tfm:
* (fs-layer or blk-crypto) will be used.
*/
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)
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);
tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode);
if (IS_ERR(tfm))
@@ -157,9 +152,7 @@ void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key)
int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key)
{
ci->ci_owns_key = true;
return fscrypt_prepare_key(&ci->ci_enc_key, raw_key,
ci->ci_mode->keysize,
false /*is_hw_wrapped*/, ci);
return fscrypt_prepare_key(&ci->ci_enc_key, raw_key, ci);
}
static int setup_per_mode_enc_key(struct fscrypt_info *ci,
@@ -191,48 +184,24 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
if (fscrypt_is_key_prepared(prep_key, ci))
goto done_unlock;
if (mk->mk_secret.is_hw_wrapped && S_ISREG(inode->i_mode)) {
int i;
if (!fscrypt_using_inline_encryption(ci)) {
fscrypt_warn(ci->ci_inode,
"Hardware-wrapped keys require inline encryption (-o inlinecrypt)");
err = -EINVAL;
goto out_unlock;
}
for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
if (fscrypt_is_key_prepared(&keys[i], ci)) {
fscrypt_warn(ci->ci_inode,
"Each hardware-wrapped key can only be used with one encryption mode");
err = -EINVAL;
goto out_unlock;
}
}
err = fscrypt_prepare_key(prep_key, mk->mk_secret.raw,
mk->mk_secret.size, true, ci);
if (err)
goto out_unlock;
} else {
BUILD_BUG_ON(sizeof(mode_num) != 1);
BUILD_BUG_ON(sizeof(sb->s_uuid) != 16);
BUILD_BUG_ON(sizeof(hkdf_info) != 17);
hkdf_info[hkdf_infolen++] = mode_num;
if (include_fs_uuid) {
memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid,
sizeof(sb->s_uuid));
hkdf_infolen += sizeof(sb->s_uuid);
}
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
hkdf_context, hkdf_info, hkdf_infolen,
mode_key, mode->keysize);
if (err)
goto out_unlock;
err = fscrypt_prepare_key(prep_key, mode_key, mode->keysize,
false /*is_hw_wrapped*/, ci);
memzero_explicit(mode_key, mode->keysize);
if (err)
goto out_unlock;
BUILD_BUG_ON(sizeof(mode_num) != 1);
BUILD_BUG_ON(sizeof(sb->s_uuid) != 16);
BUILD_BUG_ON(sizeof(hkdf_info) != 17);
hkdf_info[hkdf_infolen++] = mode_num;
if (include_fs_uuid) {
memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid,
sizeof(sb->s_uuid));
hkdf_infolen += sizeof(sb->s_uuid);
}
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
hkdf_context, hkdf_info, hkdf_infolen,
mode_key, mode->keysize);
if (err)
goto out_unlock;
err = fscrypt_prepare_key(prep_key, mode_key, ci);
memzero_explicit(mode_key, mode->keysize);
if (err)
goto out_unlock;
done_unlock:
ci->ci_enc_key = *prep_key;
err = 0;
@@ -337,14 +306,6 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
{
int err;
if (mk->mk_secret.is_hw_wrapped &&
!(ci->ci_policy.v2.flags & (FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 |
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))) {
fscrypt_warn(ci->ci_inode,
"Hardware-wrapped keys are only supported with IV_INO_LBLK policies");
return -EINVAL;
}
if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
/*
* DIRECT_KEY: instead of deriving per-file encryption keys, the
@@ -415,6 +376,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
struct fscrypt_key_specifier mk_spec;
int err;
err = fscrypt_select_encryption_impl(ci);
if (err)
return err;
switch (ci->ci_policy.version) {
case FSCRYPT_POLICY_V1:
mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
@@ -439,10 +404,6 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
ci->ci_policy.version != FSCRYPT_POLICY_V1)
return PTR_ERR(key);
err = fscrypt_select_encryption_impl(ci, false);
if (err)
return err;
/*
* As a legacy fallback for v1 policies, search for the key in
* the current task's subscribed keyrings too. Don't move this
@@ -477,10 +438,6 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
goto out_release_key;
}
err = fscrypt_select_encryption_impl(ci, mk->mk_secret.is_hw_wrapped);
if (err)
goto out_release_key;
switch (ci->ci_policy.version) {
case FSCRYPT_POLICY_V1:
err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw);
+1 -2
View File
@@ -233,8 +233,7 @@ 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;
err = fscrypt_prepare_key(&dk->dk_key, raw_key, ci->ci_mode->keysize,
false /*is_hw_wrapped*/, ci);
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,
+1 -4
View File
@@ -124,10 +124,7 @@ struct fscrypt_add_key_arg {
struct fscrypt_key_specifier key_spec;
__u32 raw_size;
__u32 key_id;
__u32 __reserved[7];
/* N.B.: "temporary" flag, not reserved upstream */
#define __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED 0x00000001
__u32 __flags;
__u32 __reserved[8];
__u8 raw[];
};