ANDROID: block: Prevent crypto fallback for wrapped keys
blk-crypto-fallback does not support wrapped keys, hence prevent falling back when program_key fails. Add 'is_hw_wrapped' flag to blk-crypto-key to mention if the key is wrapped when the key is initialized. Bug: 147209885 Test: Validate FBE, simulate a failure in the underlying blk device and ensure the call fails without falling back to blk-crypto-fallback. Change-Id: I8bc301ca1ac9e55ba6ab622e8325486916b45c56 Signed-off-by: Barani Muthukumaran <bmuthuku@codeaurora.org>
This commit is contained in:

committed by
Todd Kjos

parent
b92241fa92
commit
f5ecdc54d7
@@ -572,6 +572,12 @@ int blk_crypto_fallback_submit_bio(struct bio **bio_ptr)
|
|||||||
struct bio_crypt_ctx *bc = bio->bi_crypt_context;
|
struct bio_crypt_ctx *bc = bio->bi_crypt_context;
|
||||||
struct bio_fallback_crypt_ctx *f_ctx;
|
struct bio_fallback_crypt_ctx *f_ctx;
|
||||||
|
|
||||||
|
if (bc->bc_key->is_hw_wrapped) {
|
||||||
|
pr_warn_once("HW wrapped key cannot be used with fallback.\n");
|
||||||
|
bio->bi_status = BLK_STS_NOTSUPP;
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
if (!tfms_inited[bc->bc_key->crypto_mode]) {
|
if (!tfms_inited[bc->bc_key->crypto_mode]) {
|
||||||
bio->bi_status = BLK_STS_IOERR;
|
bio->bi_status = BLK_STS_IOERR;
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@@ -175,7 +175,9 @@ bool blk_crypto_endio(struct bio *bio)
|
|||||||
* @raw_key_size: Size of raw key. Must be at least the required size for the
|
* @raw_key_size: Size of raw key. Must be at least the required size for the
|
||||||
* chosen @crypto_mode; see blk_crypto_modes[]. (It's allowed
|
* chosen @crypto_mode; see blk_crypto_modes[]. (It's allowed
|
||||||
* to be longer than the mode's actual key size, in order to
|
* to be longer than the mode's actual key size, in order to
|
||||||
* support inline encryption hardware that accepts wrapped keys.)
|
* support inline encryption hardware that accepts wrapped keys.
|
||||||
|
* @is_hw_wrapped has to be set for such keys)
|
||||||
|
* @is_hw_wrapped: Denotes @raw_key is wrapped.
|
||||||
* @crypto_mode: identifier for the encryption algorithm to use
|
* @crypto_mode: identifier for the encryption algorithm to use
|
||||||
* @data_unit_size: the data unit size to use for en/decryption
|
* @data_unit_size: the data unit size to use for en/decryption
|
||||||
*
|
*
|
||||||
@@ -184,6 +186,7 @@ bool blk_crypto_endio(struct bio *bio)
|
|||||||
*/
|
*/
|
||||||
int blk_crypto_init_key(struct blk_crypto_key *blk_key,
|
int blk_crypto_init_key(struct blk_crypto_key *blk_key,
|
||||||
const u8 *raw_key, unsigned int raw_key_size,
|
const u8 *raw_key, unsigned int raw_key_size,
|
||||||
|
bool is_hw_wrapped,
|
||||||
enum blk_crypto_mode_num crypto_mode,
|
enum blk_crypto_mode_num crypto_mode,
|
||||||
unsigned int data_unit_size)
|
unsigned int data_unit_size)
|
||||||
{
|
{
|
||||||
@@ -198,9 +201,14 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key,
|
|||||||
BUILD_BUG_ON(BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE < BLK_CRYPTO_MAX_KEY_SIZE);
|
BUILD_BUG_ON(BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE < BLK_CRYPTO_MAX_KEY_SIZE);
|
||||||
|
|
||||||
mode = &blk_crypto_modes[crypto_mode];
|
mode = &blk_crypto_modes[crypto_mode];
|
||||||
if (raw_key_size < mode->keysize ||
|
if (is_hw_wrapped) {
|
||||||
raw_key_size > BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE)
|
if (raw_key_size < mode->keysize ||
|
||||||
return -EINVAL;
|
raw_key_size > BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE)
|
||||||
|
return -EINVAL;
|
||||||
|
} else {
|
||||||
|
if (raw_key_size != mode->keysize)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_power_of_2(data_unit_size))
|
if (!is_power_of_2(data_unit_size))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -209,6 +217,7 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key,
|
|||||||
blk_key->data_unit_size = data_unit_size;
|
blk_key->data_unit_size = data_unit_size;
|
||||||
blk_key->data_unit_size_bits = ilog2(data_unit_size);
|
blk_key->data_unit_size_bits = ilog2(data_unit_size);
|
||||||
blk_key->size = raw_key_size;
|
blk_key->size = raw_key_size;
|
||||||
|
blk_key->is_hw_wrapped = is_hw_wrapped;
|
||||||
memcpy(blk_key->raw, raw_key, raw_key_size);
|
memcpy(blk_key->raw, raw_key, raw_key_size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -224,7 +224,7 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = blk_crypto_init_key(&dkc->key, raw_key, cipher->key_size,
|
err = blk_crypto_init_key(&dkc->key, raw_key, cipher->key_size,
|
||||||
cipher->mode_num, dkc->sector_size);
|
false, cipher->mode_num, dkc->sector_size);
|
||||||
if (err) {
|
if (err) {
|
||||||
ti->error = "Error initializing blk-crypto key";
|
ti->error = "Error initializing blk-crypto key";
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@@ -319,6 +319,7 @@ extern int fscrypt_prepare_inline_crypt_key(
|
|||||||
struct fscrypt_prepared_key *prep_key,
|
struct fscrypt_prepared_key *prep_key,
|
||||||
const u8 *raw_key,
|
const u8 *raw_key,
|
||||||
unsigned int raw_key_size,
|
unsigned int raw_key_size,
|
||||||
|
bool is_hw_wrapped,
|
||||||
const struct fscrypt_info *ci);
|
const struct fscrypt_info *ci);
|
||||||
|
|
||||||
extern void fscrypt_destroy_inline_crypt_key(
|
extern void fscrypt_destroy_inline_crypt_key(
|
||||||
@@ -363,6 +364,7 @@ static inline bool fscrypt_using_inline_encryption(
|
|||||||
static inline int
|
static inline int
|
||||||
fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
||||||
const u8 *raw_key, unsigned int raw_key_size,
|
const u8 *raw_key, unsigned int raw_key_size,
|
||||||
|
bool is_hw_wrapped,
|
||||||
const struct fscrypt_info *ci)
|
const struct fscrypt_info *ci)
|
||||||
{
|
{
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
@@ -557,6 +559,7 @@ extern struct fscrypt_mode fscrypt_modes[];
|
|||||||
|
|
||||||
extern int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
|
extern int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
|
||||||
const u8 *raw_key, unsigned int raw_key_size,
|
const u8 *raw_key, unsigned int raw_key_size,
|
||||||
|
bool is_hw_wrapped,
|
||||||
const struct fscrypt_info *ci);
|
const struct fscrypt_info *ci);
|
||||||
|
|
||||||
extern void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key);
|
extern void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key);
|
||||||
|
@@ -50,6 +50,7 @@ void fscrypt_select_encryption_impl(struct fscrypt_info *ci)
|
|||||||
int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
||||||
const u8 *raw_key,
|
const u8 *raw_key,
|
||||||
unsigned int raw_key_size,
|
unsigned int raw_key_size,
|
||||||
|
bool is_hw_wrapped,
|
||||||
const struct fscrypt_info *ci)
|
const struct fscrypt_info *ci)
|
||||||
{
|
{
|
||||||
const struct inode *inode = ci->ci_inode;
|
const struct inode *inode = ci->ci_inode;
|
||||||
@@ -80,7 +81,7 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
|||||||
BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE);
|
BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE);
|
||||||
|
|
||||||
err = blk_crypto_init_key(&blk_key->base, raw_key, raw_key_size,
|
err = blk_crypto_init_key(&blk_key->base, raw_key, raw_key_size,
|
||||||
crypto_mode, sb->s_blocksize);
|
is_hw_wrapped, crypto_mode, sb->s_blocksize);
|
||||||
if (err) {
|
if (err) {
|
||||||
fscrypt_err(inode, "error %d initializing blk-crypto key", err);
|
fscrypt_err(inode, "error %d initializing blk-crypto key", err);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@@ -117,15 +117,15 @@ err_free_tfm:
|
|||||||
*/
|
*/
|
||||||
int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
|
int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key,
|
||||||
const u8 *raw_key, unsigned int raw_key_size,
|
const u8 *raw_key, unsigned int raw_key_size,
|
||||||
const struct fscrypt_info *ci)
|
bool is_hw_wrapped, const struct fscrypt_info *ci)
|
||||||
{
|
{
|
||||||
struct crypto_skcipher *tfm;
|
struct crypto_skcipher *tfm;
|
||||||
|
|
||||||
if (fscrypt_using_inline_encryption(ci))
|
if (fscrypt_using_inline_encryption(ci))
|
||||||
return fscrypt_prepare_inline_crypt_key(prep_key,
|
return fscrypt_prepare_inline_crypt_key(prep_key,
|
||||||
raw_key, raw_key_size, ci);
|
raw_key, raw_key_size, is_hw_wrapped, ci);
|
||||||
|
|
||||||
if (WARN_ON(raw_key_size != ci->ci_mode->keysize))
|
if (WARN_ON(is_hw_wrapped || raw_key_size != ci->ci_mode->keysize))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode);
|
tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode);
|
||||||
@@ -150,8 +150,8 @@ 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)
|
int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key)
|
||||||
{
|
{
|
||||||
ci->ci_owns_key = true;
|
ci->ci_owns_key = true;
|
||||||
return fscrypt_prepare_key(&ci->ci_key, raw_key,
|
return fscrypt_prepare_key(&ci->ci_key, raw_key, ci->ci_mode->keysize,
|
||||||
ci->ci_mode->keysize, ci);
|
false /*is_hw_wrapped*/, ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int setup_per_mode_enc_key(struct fscrypt_info *ci,
|
static int setup_per_mode_enc_key(struct fscrypt_info *ci,
|
||||||
@@ -202,7 +202,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = fscrypt_prepare_key(prep_key, mk->mk_secret.raw,
|
err = fscrypt_prepare_key(prep_key, mk->mk_secret.raw,
|
||||||
mk->mk_secret.size, ci);
|
mk->mk_secret.size, true, ci);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
} else {
|
} else {
|
||||||
@@ -221,7 +221,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
|
|||||||
if (err)
|
if (err)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
err = fscrypt_prepare_key(prep_key, mode_key, mode->keysize,
|
err = fscrypt_prepare_key(prep_key, mode_key, mode->keysize,
|
||||||
ci);
|
false /*is_hw_wrapped*/, ci);
|
||||||
memzero_explicit(mode_key, mode->keysize);
|
memzero_explicit(mode_key, mode->keysize);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@@ -234,7 +234,7 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key)
|
|||||||
refcount_set(&dk->dk_refcount, 1);
|
refcount_set(&dk->dk_refcount, 1);
|
||||||
dk->dk_mode = ci->ci_mode;
|
dk->dk_mode = ci->ci_mode;
|
||||||
err = fscrypt_prepare_key(&dk->dk_key, raw_key, ci->ci_mode->keysize,
|
err = fscrypt_prepare_key(&dk->dk_key, raw_key, ci->ci_mode->keysize,
|
||||||
ci);
|
false /*is_hw_wrapped*/, ci);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_free_dk;
|
goto err_free_dk;
|
||||||
memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor,
|
memcpy(dk->dk_descriptor, ci->ci_policy.v1.master_key_descriptor,
|
||||||
|
@@ -31,6 +31,8 @@ enum blk_crypto_mode_num {
|
|||||||
* @data_unit_size_bits: log2 of data_unit_size
|
* @data_unit_size_bits: log2 of data_unit_size
|
||||||
* @size: size of this key in bytes (determined by @crypto_mode)
|
* @size: size of this key in bytes (determined by @crypto_mode)
|
||||||
* @hash: hash of this key, for keyslot manager use only
|
* @hash: hash of this key, for keyslot manager use only
|
||||||
|
* @is_hw_wrapped: @raw points to a wrapped key to be used by an inline
|
||||||
|
* encryption hardware that accepts wrapped keys.
|
||||||
* @raw: the raw bytes of this key. Only the first @size bytes are used.
|
* @raw: the raw bytes of this key. Only the first @size bytes are used.
|
||||||
*
|
*
|
||||||
* A blk_crypto_key is immutable once created, and many bios can reference it at
|
* A blk_crypto_key is immutable once created, and many bios can reference it at
|
||||||
@@ -42,6 +44,7 @@ struct blk_crypto_key {
|
|||||||
unsigned int data_unit_size_bits;
|
unsigned int data_unit_size_bits;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
unsigned int hash;
|
unsigned int hash;
|
||||||
|
bool is_hw_wrapped;
|
||||||
u8 raw[BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE];
|
u8 raw[BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@ bool blk_crypto_endio(struct bio *bio);
|
|||||||
|
|
||||||
int blk_crypto_init_key(struct blk_crypto_key *blk_key,
|
int blk_crypto_init_key(struct blk_crypto_key *blk_key,
|
||||||
const u8 *raw_key, unsigned int raw_key_size,
|
const u8 *raw_key, unsigned int raw_key_size,
|
||||||
|
bool is_hw_wrapped,
|
||||||
enum blk_crypto_mode_num crypto_mode,
|
enum blk_crypto_mode_num crypto_mode,
|
||||||
unsigned int data_unit_size);
|
unsigned int data_unit_size);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user