Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8722ec5 authored by Neeraj Soni's avatar Neeraj Soni Committed by Gerrit - the friendly Code Review server
Browse files

Revert "Reverting crypto patches"



This reverts commit b73e822d.

This is reverted to integrate new file encryption framework support changes
to ensure all fixes are present to use new encryption policies.

Change-Id: I455ec66664064069ac34e6fe410bd28dc3a53d07
Signed-off-by: default avatarNeeraj Soni <neersoni@codeaurora.org>
parent 88205c5d
Loading
Loading
Loading
Loading
+69 −17
Original line number Original line Diff line number Diff line
@@ -234,8 +234,8 @@ HKDF is more flexible, is nonreversible, and evenly distributes
entropy from the master key.  HKDF is also standardized and widely
entropy from the master key.  HKDF is also standardized and widely
used by other software, whereas the AES-128-ECB based KDF is ad-hoc.
used by other software, whereas the AES-128-ECB based KDF is ad-hoc.


Per-file keys
Per-file encryption keys
-------------
------------------------


Since each master key can protect many files, it is necessary to
Since each master key can protect many files, it is necessary to
"tweak" the encryption of each file so that the same plaintext in two
"tweak" the encryption of each file so that the same plaintext in two
@@ -268,9 +268,9 @@ is greater than that of an AES-256-XTS key.
Therefore, to improve performance and save memory, for Adiantum a
Therefore, to improve performance and save memory, for Adiantum a
"direct key" configuration is supported.  When the user has enabled
"direct key" configuration is supported.  When the user has enabled
this by setting FSCRYPT_POLICY_FLAG_DIRECT_KEY in the fscrypt policy,
this by setting FSCRYPT_POLICY_FLAG_DIRECT_KEY in the fscrypt policy,
per-file keys are not used.  Instead, whenever any data (contents or
per-file encryption keys are not used.  Instead, whenever any data
filenames) is encrypted, the file's 16-byte nonce is included in the
(contents or filenames) is encrypted, the file's 16-byte nonce is
IV.  Moreover:
included in the IV.  Moreover:


- For v1 encryption policies, the encryption is done directly with the
- For v1 encryption policies, the encryption is done directly with the
  master key.  Because of this, users **must not** use the same master
  master key.  Because of this, users **must not** use the same master
@@ -302,6 +302,16 @@ For master keys used for v2 encryption policies, a unique 16-byte "key
identifier" is also derived using the KDF.  This value is stored in
identifier" is also derived using the KDF.  This value is stored in
the clear, since it is needed to reliably identify the key itself.
the clear, since it is needed to reliably identify the key itself.


Dirhash keys
------------

For directories that are indexed using a secret-keyed dirhash over the
plaintext filenames, the KDF is also used to derive a 128-bit
SipHash-2-4 key per directory in order to hash filenames.  This works
just like deriving a per-file encryption key, except that a different
KDF context is used.  Currently, only casefolded ("case-insensitive")
encrypted directories use this style of hashing.

Encryption modes and usage
Encryption modes and usage
==========================
==========================


@@ -325,11 +335,11 @@ used.
Adiantum is a (primarily) stream cipher-based mode that is fast even
Adiantum is a (primarily) stream cipher-based mode that is fast even
on CPUs without dedicated crypto instructions.  It's also a true
on CPUs without dedicated crypto instructions.  It's also a true
wide-block mode, unlike XTS.  It can also eliminate the need to derive
wide-block mode, unlike XTS.  It can also eliminate the need to derive
per-file keys.  However, it depends on the security of two primitives,
per-file encryption keys.  However, it depends on the security of two
XChaCha12 and AES-256, rather than just one.  See the paper
primitives, XChaCha12 and AES-256, rather than just one.  See the
"Adiantum: length-preserving encryption for entry-level processors"
paper "Adiantum: length-preserving encryption for entry-level
(https://eprint.iacr.org/2018/720.pdf) for more details.  To use
processors" (https://eprint.iacr.org/2018/720.pdf) for more details.
Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled.  Also, fast
To use Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled.  Also, fast
implementations of ChaCha and NHPoly1305 should be enabled, e.g.
implementations of ChaCha and NHPoly1305 should be enabled, e.g.
CONFIG_CRYPTO_CHACHA20_NEON and CONFIG_CRYPTO_NHPOLY1305_NEON for ARM.
CONFIG_CRYPTO_CHACHA20_NEON and CONFIG_CRYPTO_NHPOLY1305_NEON for ARM.


@@ -513,7 +523,9 @@ FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors:
- ``EEXIST``: the file is already encrypted with an encryption policy
- ``EEXIST``: the file is already encrypted with an encryption policy
  different from the one specified
  different from the one specified
- ``EINVAL``: an invalid encryption policy was specified (invalid
- ``EINVAL``: an invalid encryption policy was specified (invalid
  version, mode(s), or flags; or reserved bits were set)
  version, mode(s), or flags; or reserved bits were set); or a v1
  encryption policy was specified but the directory has the casefold
  flag enabled (casefolding is incompatible with v1 policies).
- ``ENOKEY``: a v2 encryption policy was specified, but the key with
- ``ENOKEY``: a v2 encryption policy was specified, but the key with
  the specified ``master_key_identifier`` has not been added, nor does
  the specified ``master_key_identifier`` has not been added, nor does
  the process have the CAP_FOWNER capability in the initial user
  the process have the CAP_FOWNER capability in the initial user
@@ -621,6 +633,17 @@ from a passphrase or other low-entropy user credential.
FS_IOC_GET_ENCRYPTION_PWSALT is deprecated.  Instead, prefer to
FS_IOC_GET_ENCRYPTION_PWSALT is deprecated.  Instead, prefer to
generate and manage any needed salt(s) in userspace.
generate and manage any needed salt(s) in userspace.


Getting a file's encryption nonce
---------------------------------

Since Linux v5.7, the ioctl FS_IOC_GET_ENCRYPTION_NONCE is supported.
On encrypted files and directories it gets the inode's 16-byte nonce.
On unencrypted files and directories, it fails with ENODATA.

This ioctl can be useful for automated tests which verify that the
encryption is being done correctly.  It is not needed for normal use
of fscrypt.

Adding keys
Adding keys
-----------
-----------


@@ -638,7 +661,8 @@ follows::
    struct fscrypt_add_key_arg {
    struct fscrypt_add_key_arg {
            struct fscrypt_key_specifier key_spec;
            struct fscrypt_key_specifier key_spec;
            __u32 raw_size;
            __u32 raw_size;
            __u32 __reserved[9];
            __u32 key_id;
            __u32 __reserved[8];
            __u8 raw[];
            __u8 raw[];
    };
    };


@@ -655,6 +679,12 @@ follows::
            } u;
            } u;
    };
    };


    struct fscrypt_provisioning_key_payload {
            __u32 type;
            __u32 __reserved;
            __u8 raw[];
    };

:c:type:`struct fscrypt_add_key_arg` must be zeroed, then initialized
:c:type:`struct fscrypt_add_key_arg` must be zeroed, then initialized
as follows:
as follows:


@@ -677,9 +707,26 @@ as follows:
  ``Documentation/security/keys/core.rst``).
  ``Documentation/security/keys/core.rst``).


- ``raw_size`` must be the size of the ``raw`` key provided, in bytes.
- ``raw_size`` must be the size of the ``raw`` key provided, in bytes.
  Alternatively, if ``key_id`` is nonzero, this field must be 0, since
  in that case the size is implied by the specified Linux keyring key.

- ``key_id`` is 0 if the raw key is given directly in the ``raw``
  field.  Otherwise ``key_id`` is the ID of a Linux keyring key of
  type "fscrypt-provisioning" whose payload is a :c:type:`struct
  fscrypt_provisioning_key_payload` whose ``raw`` field contains the
  raw key and whose ``type`` field matches ``key_spec.type``.  Since
  ``raw`` is variable-length, the total size of this key's payload
  must be ``sizeof(struct fscrypt_provisioning_key_payload)`` plus the
  raw key size.  The process must have Search permission on this key.

  Most users should leave this 0 and specify the raw key directly.
  The support for specifying a Linux keyring key is intended mainly to
  allow re-adding keys after a filesystem is unmounted and re-mounted,
  without having to store the raw keys in userspace memory.


- ``raw`` is a variable-length field which must contain the actual
- ``raw`` is a variable-length field which must contain the actual
  key, ``raw_size`` bytes long.
  key, ``raw_size`` bytes long.  Alternatively, if ``key_id`` is
  nonzero, then this field is unused.


For v2 policy keys, the kernel keeps track of which user (identified
For v2 policy keys, the kernel keeps track of which user (identified
by effective user ID) added the key, and only allows the key to be
by effective user ID) added the key, and only allows the key to be
@@ -701,11 +748,16 @@ FS_IOC_ADD_ENCRYPTION_KEY can fail with the following errors:


- ``EACCES``: FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR was specified, but the
- ``EACCES``: FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR was specified, but the
  caller does not have the CAP_SYS_ADMIN capability in the initial
  caller does not have the CAP_SYS_ADMIN capability in the initial
  user namespace
  user namespace; or the raw key was specified by Linux key ID but the
  process lacks Search permission on the key.
- ``EDQUOT``: the key quota for this user would be exceeded by adding
- ``EDQUOT``: the key quota for this user would be exceeded by adding
  the key
  the key
- ``EINVAL``: invalid key size or key specifier type, or reserved bits
- ``EINVAL``: invalid key size or key specifier type, or reserved bits
  were set
  were set
- ``EKEYREJECTED``: the raw key was specified by Linux key ID, but the
  key has the wrong type
- ``ENOKEY``: the raw key was specified by Linux key ID, but no key
  exists with that ID
- ``ENOTTY``: this type of filesystem does not implement encryption
- ``ENOTTY``: this type of filesystem does not implement encryption
- ``EOPNOTSUPP``: the kernel was not configured with encryption
- ``EOPNOTSUPP``: the kernel was not configured with encryption
  support for this filesystem, or the filesystem superblock has not
  support for this filesystem, or the filesystem superblock has not
@@ -1108,8 +1160,8 @@ The context structs contain the same information as the corresponding
policy structs (see `Setting an encryption policy`_), except that the
policy structs (see `Setting an encryption policy`_), except that the
context structs also contain a nonce.  The nonce is randomly generated
context structs also contain a nonce.  The nonce is randomly generated
by the kernel and is used as KDF input or as a tweak to cause
by the kernel and is used as KDF input or as a tweak to cause
different files to be encrypted differently; see `Per-file keys`_ and
different files to be encrypted differently; see `Per-file encryption
`DIRECT_KEY policies`_.
keys`_ and `DIRECT_KEY policies`_.


Data path changes
Data path changes
-----------------
-----------------
@@ -1161,7 +1213,7 @@ filesystem-specific hash(es) needed for directory lookups. This
allows the filesystem to still, with a high degree of confidence, map
allows the filesystem to still, with a high degree of confidence, map
the filename given in ->lookup() back to a particular directory entry
the filename given in ->lookup() back to a particular directory entry
that was previously listed by readdir().  See :c:type:`struct
that was previously listed by readdir().  See :c:type:`struct
fscrypt_digested_name` in the source for more details.
fscrypt_nokey_name` in the source for more details.


Note that the precise way that filenames are presented to userspace
Note that the precise way that filenames are presented to userspace
without the key is subject to change in the future.  It is only meant
without the key is subject to change in the future.  It is only meant
+22 −28
Original line number Original line Diff line number Diff line
@@ -487,21 +487,13 @@ bool blk_crypto_queue_decrypt_bio(struct bio *bio)
	return false;
	return false;
}
}


/**
/*
 * blk_crypto_start_using_mode() - Start using a crypto algorithm on a device
 * Prepare blk-crypto-fallback for the specified crypto mode.
 * @mode_num: the blk_crypto_mode we want to allocate ciphers for.
 * Returns -ENOPKG if the needed crypto API support is missing.
 * @data_unit_size: the data unit size that will be used
 * @q: the request queue for the device
 *
 * Upper layers must call this function to ensure that a the crypto API fallback
 * has transforms for this algorithm, if they become necessary.
 *
 * Return: 0 on success and -err on error.
 */
 */
int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num,
int blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num)
				unsigned int data_unit_size,
				struct request_queue *q)
{
{
	const char *cipher_str = blk_crypto_modes[mode_num].cipher_str;
	struct blk_crypto_keyslot *slotp;
	struct blk_crypto_keyslot *slotp;
	unsigned int i;
	unsigned int i;
	int err = 0;
	int err = 0;
@@ -514,25 +506,20 @@ int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num,
	if (likely(smp_load_acquire(&tfms_inited[mode_num])))
	if (likely(smp_load_acquire(&tfms_inited[mode_num])))
		return 0;
		return 0;


	/*
	 * If the keyslot manager of the request queue supports this
	 * crypto mode, then we don't need to allocate this mode.
	 */
	if (keyslot_manager_crypto_mode_supported(q->ksm, mode_num,
						  data_unit_size))
		return 0;

	mutex_lock(&tfms_init_lock);
	mutex_lock(&tfms_init_lock);
	if (likely(tfms_inited[mode_num]))
	if (likely(tfms_inited[mode_num]))
		goto out;
		goto out;


	for (i = 0; i < blk_crypto_num_keyslots; i++) {
	for (i = 0; i < blk_crypto_num_keyslots; i++) {
		slotp = &blk_crypto_keyslots[i];
		slotp = &blk_crypto_keyslots[i];
		slotp->tfms[mode_num] = crypto_alloc_skcipher(
		slotp->tfms[mode_num] = crypto_alloc_skcipher(cipher_str, 0, 0);
					blk_crypto_modes[mode_num].cipher_str,
					0, 0);
		if (IS_ERR(slotp->tfms[mode_num])) {
		if (IS_ERR(slotp->tfms[mode_num])) {
			err = PTR_ERR(slotp->tfms[mode_num]);
			err = PTR_ERR(slotp->tfms[mode_num]);
			if (err == -ENOENT) {
				pr_warn_once("Missing crypto API support for \"%s\"\n",
					     cipher_str);
				err = -ENOPKG;
			}
			slotp->tfms[mode_num] = NULL;
			slotp->tfms[mode_num] = NULL;
			goto out_free_tfms;
			goto out_free_tfms;
		}
		}
@@ -558,7 +545,6 @@ int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num,
	mutex_unlock(&tfms_init_lock);
	mutex_unlock(&tfms_init_lock);
	return err;
	return err;
}
}
EXPORT_SYMBOL_GPL(blk_crypto_start_using_mode);


int blk_crypto_fallback_evict_key(const struct blk_crypto_key *key)
int blk_crypto_fallback_evict_key(const struct blk_crypto_key *key)
{
{
@@ -571,6 +557,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;
@@ -608,8 +600,10 @@ int __init blk_crypto_fallback_init(void)
		crypto_mode_supported[i] = 0xFFFFFFFF;
		crypto_mode_supported[i] = 0xFFFFFFFF;
	crypto_mode_supported[BLK_ENCRYPTION_MODE_INVALID] = 0;
	crypto_mode_supported[BLK_ENCRYPTION_MODE_INVALID] = 0;


	blk_crypto_ksm = keyslot_manager_create(blk_crypto_num_keyslots,
	blk_crypto_ksm = keyslot_manager_create(
				NULL, blk_crypto_num_keyslots,
				&blk_crypto_ksm_ll_ops,
				&blk_crypto_ksm_ll_ops,
				BLK_CRYPTO_FEATURE_STANDARD_KEYS,
				crypto_mode_supported, NULL);
				crypto_mode_supported, NULL);
	if (!blk_crypto_ksm)
	if (!blk_crypto_ksm)
		return -ENOMEM;
		return -ENOMEM;
+9 −0
Original line number Original line Diff line number Diff line
@@ -19,6 +19,8 @@ extern const struct blk_crypto_mode blk_crypto_modes[];


#ifdef CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK
#ifdef CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK


int blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num);

int blk_crypto_fallback_submit_bio(struct bio **bio_ptr);
int blk_crypto_fallback_submit_bio(struct bio **bio_ptr);


bool blk_crypto_queue_decrypt_bio(struct bio *bio);
bool blk_crypto_queue_decrypt_bio(struct bio *bio);
@@ -29,6 +31,13 @@ bool bio_crypt_fallback_crypted(const struct bio_crypt_ctx *bc);


#else /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */
#else /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */


static inline int
blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num)
{
	pr_warn_once("crypto API fallback is disabled\n");
	return -ENOPKG;
}

static inline bool bio_crypt_fallback_crypted(const struct bio_crypt_ctx *bc)
static inline bool bio_crypt_fallback_crypted(const struct bio_crypt_ctx *bc)
{
{
	return false;
	return false;
+49 −6
Original line number Original line Diff line number Diff line
@@ -109,7 +109,8 @@ int blk_crypto_submit_bio(struct bio **bio_ptr)
	/* Get device keyslot if supported */
	/* Get device keyslot if supported */
	if (keyslot_manager_crypto_mode_supported(q->ksm,
	if (keyslot_manager_crypto_mode_supported(q->ksm,
						  bc->bc_key->crypto_mode,
						  bc->bc_key->crypto_mode,
						  bc->bc_key->data_unit_size)) {
						  bc->bc_key->data_unit_size,
						  bc->bc_key->is_hw_wrapped)) {
		err = bio_crypt_ctx_acquire_keyslot(bc, q->ksm);
		err = bio_crypt_ctx_acquire_keyslot(bc, q->ksm);
		if (!err)
		if (!err)
			return 0;
			return 0;
@@ -175,7 +176,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 +187,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 +202,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 (is_hw_wrapped) {
		if (raw_key_size < mode->keysize ||
		if (raw_key_size < mode->keysize ||
		    raw_key_size > BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE)
		    raw_key_size > BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE)
			return -EINVAL;
			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 +218,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);


	/*
	/*
@@ -223,6 +233,38 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key,
}
}
EXPORT_SYMBOL_GPL(blk_crypto_init_key);
EXPORT_SYMBOL_GPL(blk_crypto_init_key);


/**
 * blk_crypto_start_using_mode() - Start using blk-crypto on a device
 * @crypto_mode: the crypto mode that will be used
 * @data_unit_size: the data unit size that will be used
 * @is_hw_wrapped_key: whether the key will be hardware-wrapped
 * @q: the request queue for the device
 *
 * Upper layers must call this function to ensure that either the hardware
 * supports the needed crypto settings, or the crypto API fallback has
 * transforms for the needed mode allocated and ready to go.
 *
 * Return: 0 on success; -ENOPKG if the hardware doesn't support the crypto
 *	   settings and blk-crypto-fallback is either disabled or the needed
 *	   algorithm is disabled in the crypto API; or another -errno code.
 */
int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode,
				unsigned int data_unit_size,
				bool is_hw_wrapped_key,
				struct request_queue *q)
{
	if (keyslot_manager_crypto_mode_supported(q->ksm, crypto_mode,
						  data_unit_size,
						  is_hw_wrapped_key))
		return 0;
	if (is_hw_wrapped_key) {
		pr_warn_once("hardware doesn't support wrapped keys\n");
		return -EOPNOTSUPP;
	}
	return blk_crypto_fallback_start_using_mode(crypto_mode);
}
EXPORT_SYMBOL_GPL(blk_crypto_start_using_mode);

/**
/**
 * blk_crypto_evict_key() - Evict a key from any inline encryption hardware
 * blk_crypto_evict_key() - Evict a key from any inline encryption hardware
 *			    it may have been programmed into
 *			    it may have been programmed into
@@ -243,7 +285,8 @@ int blk_crypto_evict_key(struct request_queue *q,
{
{
	if (q->ksm &&
	if (q->ksm &&
	    keyslot_manager_crypto_mode_supported(q->ksm, key->crypto_mode,
	    keyslot_manager_crypto_mode_supported(q->ksm, key->crypto_mode,
						  key->data_unit_size))
						  key->data_unit_size,
						  key->is_hw_wrapped))
		return keyslot_manager_evict_key(q->ksm, key);
		return keyslot_manager_evict_key(q->ksm, key);


	return blk_crypto_fallback_evict_key(key);
	return blk_crypto_fallback_evict_key(key);
+24 −6
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ struct keyslot {
struct keyslot_manager {
struct keyslot_manager {
	unsigned int num_slots;
	unsigned int num_slots;
	struct keyslot_mgmt_ll_ops ksm_ll_ops;
	struct keyslot_mgmt_ll_ops ksm_ll_ops;
	unsigned int features;
	unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX];
	unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX];
	void *ll_priv_data;
	void *ll_priv_data;


@@ -78,6 +79,8 @@ static inline bool keyslot_manager_is_passthrough(struct keyslot_manager *ksm)
 * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops for the device that this keyslot
 * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops for the device that this keyslot
 *		manager will use to perform operations like programming and
 *		manager will use to perform operations like programming and
 *		evicting keys.
 *		evicting keys.
 * @features: The supported features as a bitmask of BLK_CRYPTO_FEATURE_* flags.
 *	      Most drivers should set BLK_CRYPTO_FEATURE_STANDARD_KEYS here.
 * @crypto_mode_supported:	Array of size BLK_ENCRYPTION_MODE_MAX of
 * @crypto_mode_supported:	Array of size BLK_ENCRYPTION_MODE_MAX of
 *				bitmasks that represents whether a crypto mode
 *				bitmasks that represents whether a crypto mode
 *				and data unit size are supported. The i'th bit
 *				and data unit size are supported. The i'th bit
@@ -95,6 +98,7 @@ static inline bool keyslot_manager_is_passthrough(struct keyslot_manager *ksm)
 */
 */
struct keyslot_manager *keyslot_manager_create(unsigned int num_slots,
struct keyslot_manager *keyslot_manager_create(unsigned int num_slots,
	const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
	const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
	unsigned int features,
	const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
	const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
	void *ll_priv_data)
	void *ll_priv_data)
{
{
@@ -116,6 +120,7 @@ struct keyslot_manager *keyslot_manager_create(unsigned int num_slots,


	ksm->num_slots = num_slots;
	ksm->num_slots = num_slots;
	ksm->ksm_ll_ops = *ksm_ll_ops;
	ksm->ksm_ll_ops = *ksm_ll_ops;
	ksm->features = features;
	memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
	memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
	       sizeof(ksm->crypto_mode_supported));
	       sizeof(ksm->crypto_mode_supported));
	ksm->ll_priv_data = ll_priv_data;
	ksm->ll_priv_data = ll_priv_data;
@@ -321,23 +326,24 @@ void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot)
}
}


/**
/**
 * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode/data
 * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode /
 *					     unit size combination is supported
 *					     data unit size / is_hw_wrapped_key
 *					     by a ksm.
 *					     combination is supported by a ksm.
 * @ksm: The keyslot manager to check
 * @ksm: The keyslot manager to check
 * @crypto_mode: The crypto mode to check for.
 * @crypto_mode: The crypto mode to check for.
 * @data_unit_size: The data_unit_size for the mode.
 * @data_unit_size: The data_unit_size for the mode.
 * @is_hw_wrapped_key: Whether a hardware-wrapped key will be used.
 *
 *
 * Calls and returns the result of the crypto_mode_supported function specified
 * Calls and returns the result of the crypto_mode_supported function specified
 * by the ksm.
 * by the ksm.
 *
 *
 * Context: Process context.
 * Context: Process context.
 * Return: Whether or not this ksm supports the specified crypto_mode/
 * Return: Whether or not this ksm supports the specified crypto settings.
 *	   data_unit_size combo.
 */
 */
bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
					   enum blk_crypto_mode_num crypto_mode,
					   enum blk_crypto_mode_num crypto_mode,
					   unsigned int data_unit_size)
					   unsigned int data_unit_size,
					   bool is_hw_wrapped_key)
{
{
	if (!ksm)
	if (!ksm)
		return false;
		return false;
@@ -345,6 +351,13 @@ bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
		return false;
		return false;
	if (WARN_ON(!is_power_of_2(data_unit_size)))
	if (WARN_ON(!is_power_of_2(data_unit_size)))
		return false;
		return false;
	if (is_hw_wrapped_key) {
		if (!(ksm->features & BLK_CRYPTO_FEATURE_WRAPPED_KEYS))
			return false;
	} else {
		if (!(ksm->features & BLK_CRYPTO_FEATURE_STANDARD_KEYS))
			return false;
	}
	return ksm->crypto_mode_supported[crypto_mode] & data_unit_size;
	return ksm->crypto_mode_supported[crypto_mode] & data_unit_size;
}
}


@@ -457,6 +470,7 @@ EXPORT_SYMBOL_GPL(keyslot_manager_destroy);
/**
/**
 * keyslot_manager_create_passthrough() - Create a passthrough keyslot manager
 * keyslot_manager_create_passthrough() - Create a passthrough keyslot manager
 * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops
 * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops
 * @features: Bitmask of BLK_CRYPTO_FEATURE_* flags
 * @crypto_mode_supported: Bitmasks for supported encryption modes
 * @crypto_mode_supported: Bitmasks for supported encryption modes
 * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops.
 * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops.
 *
 *
@@ -473,6 +487,7 @@ EXPORT_SYMBOL_GPL(keyslot_manager_destroy);
 */
 */
struct keyslot_manager *keyslot_manager_create_passthrough(
struct keyslot_manager *keyslot_manager_create_passthrough(
	const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
	const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
	unsigned int features,
	const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
	const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
	void *ll_priv_data)
	void *ll_priv_data)
{
{
@@ -483,6 +498,7 @@ struct keyslot_manager *keyslot_manager_create_passthrough(
		return NULL;
		return NULL;


	ksm->ksm_ll_ops = *ksm_ll_ops;
	ksm->ksm_ll_ops = *ksm_ll_ops;
	ksm->features = features;
	memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
	memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
	       sizeof(ksm->crypto_mode_supported));
	       sizeof(ksm->crypto_mode_supported));
	ksm->ll_priv_data = ll_priv_data;
	ksm->ll_priv_data = ll_priv_data;
@@ -510,11 +526,13 @@ void keyslot_manager_intersect_modes(struct keyslot_manager *parent,
	if (child) {
	if (child) {
		unsigned int i;
		unsigned int i;


		parent->features &= child->features;
		for (i = 0; i < ARRAY_SIZE(child->crypto_mode_supported); i++) {
		for (i = 0; i < ARRAY_SIZE(child->crypto_mode_supported); i++) {
			parent->crypto_mode_supported[i] &=
			parent->crypto_mode_supported[i] &=
				child->crypto_mode_supported[i];
				child->crypto_mode_supported[i];
		}
		}
	} else {
	} else {
		parent->features = 0;
		memset(parent->crypto_mode_supported, 0,
		memset(parent->crypto_mode_supported, 0,
		       sizeof(parent->crypto_mode_supported));
		       sizeof(parent->crypto_mode_supported));
	}
	}
Loading