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

Commit 49875670 authored by Blagovest Kolenichev's avatar Blagovest Kolenichev
Browse files

File and metadata encryption changes from android-4.19.96-107

Added required changes to fit properly android-4.19.79-95
crypto content into msm-4.19 branch. Modifications in
abi_gki_aarch64.xml are discarded completely. The order of
applying is bottom to top:

1f876610 ANDROID: dm: Add wrapped key support in dm-default-key
b785dbcb ANDROID: dm: add support for passing through derive_raw_secret
66b3c812 ANDROID: block: Prevent crypto fallback for wrapped keys
36500bff fscrypt: support passing a keyring key to FS_IOC_ADD_ENCRYPTION_KEY
b32863f1 ANDROID: dm: add dm-default-key target for metadata encryption
94706caf ANDROID: dm: enable may_passthrough_inline_crypto on some targets
44e1174c ANDROID: dm: add support for passing through inline crypto support
e65d08ae ANDROID: block: Introduce passthrough keyslot manager
8f48f665 ANDROID: ext4, f2fs: enable direct I/O with inline encryption
bbee7819 FROMLIST: scsi: ufs: add program_key() variant op
0f1c72a2 ANDROID: block: export symbols needed for modules to use inline crypto
35b62551 ANDROID: block: fix some inline crypto bugs
23b81578 ANDROID: fscrypt: add support for hardware-wrapped keys
a076eebe ANDROID: block: add KSM op to derive software secret from wrapped key
3e8c4180 ANDROID: block: provide key size as input to inline crypto APIs
bb7f6203 ANDROID: ufshcd-crypto: export cap find API
b01c73ea BACKPORT: FROMLIST: Update Inline Encryption from v5 to v6 of patch series

Change-Id: Ic741913aa478500da94a52eace02bb9192e581b9
Git-repo: https://android.googlesource.com/kernel/common/+/refs/heads/android-4.19


Signed-off-by: default avatarBlagovest Kolenichev <bkolenichev@codeaurora.org>
Signed-off-by: default avatarNeeraj Soni <neersoni@codeaurora.org>
parent 94699594
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ Blk-crypto ensures that:

- The bio's encryption context is programmed into a keyslot in the KSM of the
  request queue that the bio is being submitted to (or the crypto API fallback
  KSM if the request queue doesn't have a KSM), and that the ``processing_ksm``
  KSM if the request queue doesn't have a KSM), and that the ``bc_ksm``
  in the ``bi_crypt_context`` is set to this KSM

- That the bio has its own individual reference to the keyslot in this KSM.
@@ -107,7 +107,7 @@ Blk-crypto ensures that:
  ensuring that the bio has a valid reference to the keyslot when, for e.g., the
  crypto API fallback KSM in blk-crypto performs crypto on the device's behalf.
  The individual references are ensured by increasing the refcount for the
  keyslot in the ``processing_ksm`` when a bio with a programmed encryption
  keyslot in the ``bc_ksm`` when a bio with a programmed encryption
  context is cloned.


@@ -120,7 +120,7 @@ been programmed into any keyslot in any KSM (for e.g. a bio from the FS).
  request queue the bio is being submitted to (and if this KSM does not exist,
  then it will program it into blk-crypto's internal KSM for crypto API
  fallback). The KSM that this encryption context was programmed into is stored
  as the ``processing_ksm`` in the bio's ``bi_crypt_context``.
  as the ``bc_ksm`` in the bio's ``bi_crypt_context``.

**Case 2:** blk-crypto is given a bio whose encryption context has already been
programmed into a keyslot in the *crypto API fallback* KSM.
@@ -138,7 +138,7 @@ KSM).
This way, when a device driver is processing a bio, it can be sure that
the bio's encryption context has been programmed into some KSM (either the
device driver's request queue's KSM, or blk-crypto's crypto API fallback KSM).
It then simply needs to check if the bio's processing_ksm is the device's
It then simply needs to check if the bio's ``bc_ksm`` is the device's
request queue's KSM. If so, then it should proceed with IE. If not, it should
simply do nothing with respect to crypto, because some other KSM (perhaps the
blk-crypto crypto API fallback KSM) is handling the en/decryption.
+32 −3
Original line number Diff line number Diff line
@@ -638,7 +638,8 @@ follows::
    struct fscrypt_add_key_arg {
            struct fscrypt_key_specifier key_spec;
            __u32 raw_size;
            __u32 __reserved[9];
            __u32 key_id;
            __u32 __reserved[8];
            __u8 raw[];
    };

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

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

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

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

- ``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
  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
by effective user ID) added the key, and only allows the key to be
@@ -701,11 +725,16 @@ FS_IOC_ADD_ENCRYPTION_KEY can fail with the following errors:

- ``EACCES``: FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR was specified, but the
  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
  the key
- ``EINVAL``: invalid key size or key specifier type, or reserved bits
  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
- ``EOPNOTSUPP``: the kernel was not configured with encryption
  support for this filesystem, or the filesystem superblock has not
+11 −4
Original line number Diff line number Diff line
@@ -202,13 +202,20 @@ config BLK_SED_OPAL

config BLK_INLINE_ENCRYPTION
	bool "Enable inline encryption support in block layer"
	help
	  Build the blk-crypto subsystem. Enabling this lets the
	  block layer handle encryption, so users can take
	  advantage of inline encryption hardware if present.

config BLK_INLINE_ENCRYPTION_FALLBACK
	bool "Enable crypto API fallback for blk-crypto"
	depends on BLK_INLINE_ENCRYPTION
	select CRYPTO
	select CRYPTO_BLKCIPHER
	help
	  Build the blk-crypto subsystem.
	  Enabling this lets the block layer handle encryption,
	  so users can take advantage of inline encryption
	  hardware if present.
	  Enabling this lets the block layer handle inline encryption
	  by falling back to the kernel crypto API when inline
	  encryption hardware is not present.

menu "Partition Types"

+1 −0
Original line number Diff line number Diff line
@@ -39,3 +39,4 @@ obj-$(CONFIG_BLK_DEBUG_FS_ZONED)+= blk-mq-debugfs-zoned.o
obj-$(CONFIG_BLK_SED_OPAL)	+= sed-opal.o
obj-$(CONFIG_BLK_INLINE_ENCRYPTION)	+= keyslot-manager.o bio-crypt-ctx.o \
					   blk-crypto.o
obj-$(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK)	+= blk-crypto-fallback.o
 No newline at end of file
+59 −62
Original line number Diff line number Diff line
@@ -5,26 +5,43 @@

#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/slab.h>
#include <linux/keyslot-manager.h>
#include <linux/module.h>
#include <linux/slab.h>

#include "blk-crypto-internal.h"

static int num_prealloc_crypt_ctxs = 128;

module_param(num_prealloc_crypt_ctxs, int, 0444);
MODULE_PARM_DESC(num_prealloc_crypt_ctxs,
		"Number of bio crypto contexts to preallocate");

static struct kmem_cache *bio_crypt_ctx_cache;
static mempool_t *bio_crypt_ctx_pool;

int bio_crypt_ctx_init(void)
int __init bio_crypt_ctx_init(void)
{
	size_t i;

	bio_crypt_ctx_cache = KMEM_CACHE(bio_crypt_ctx, 0);
	if (!bio_crypt_ctx_cache)
		return -ENOMEM;

	bio_crypt_ctx_pool = mempool_create_slab_pool(
					num_prealloc_crypt_ctxs,
	bio_crypt_ctx_pool = mempool_create_slab_pool(num_prealloc_crypt_ctxs,
						      bio_crypt_ctx_cache);

	if (!bio_crypt_ctx_pool)
		return -ENOMEM;

	/* This is assumed in various places. */
	BUILD_BUG_ON(BLK_ENCRYPTION_MODE_INVALID != 0);

	/* Sanity check that no algorithm exceeds the defined limits. */
	for (i = 0; i < BLK_ENCRYPTION_MODE_MAX; i++) {
		BUG_ON(blk_crypto_modes[i].keysize > BLK_CRYPTO_MAX_KEY_SIZE);
		BUG_ON(blk_crypto_modes[i].ivsize > BLK_CRYPTO_MAX_IV_SIZE);
	}

	return 0;
}

@@ -32,51 +49,46 @@ struct bio_crypt_ctx *bio_crypt_alloc_ctx(gfp_t gfp_mask)
{
	return mempool_alloc(bio_crypt_ctx_pool, gfp_mask);
}
EXPORT_SYMBOL(bio_crypt_alloc_ctx);
EXPORT_SYMBOL_GPL(bio_crypt_alloc_ctx);

void bio_crypt_free_ctx(struct bio *bio)
{
	mempool_free(bio->bi_crypt_context, bio_crypt_ctx_pool);
	bio->bi_crypt_context = NULL;
}
EXPORT_SYMBOL(bio_crypt_free_ctx);

int bio_crypt_clone(struct bio *dst, struct bio *src, gfp_t gfp_mask)
void bio_crypt_clone(struct bio *dst, struct bio *src, gfp_t gfp_mask)
{
	const struct bio_crypt_ctx *src_bc = src->bi_crypt_context;

	bio_clone_skip_dm_default_key(dst, src);

	/*
	 * If a bio is swhandled, then it will be decrypted when bio_endio
	 * is called. As we only want the data to be decrypted once, copies
	 * of the bio must not have have a crypt context.
	 * If a bio is fallback_crypted, then it will be decrypted when
	 * bio_endio is called. As we only want the data to be decrypted once,
	 * copies of the bio must not have have a crypt context.
	 */
	if (!bio_has_crypt_ctx(src) || bio_crypt_swhandled(src))
		return 0;
	if (!src_bc || bio_crypt_fallback_crypted(src_bc))
		return;

	dst->bi_crypt_context = bio_crypt_alloc_ctx(gfp_mask);
	if (!dst->bi_crypt_context)
		return -ENOMEM;

	*dst->bi_crypt_context = *src->bi_crypt_context;
	*dst->bi_crypt_context = *src_bc;

	if (bio_crypt_has_keyslot(src))
		keyslot_manager_get_slot(src->bi_crypt_context->processing_ksm,
					 src->bi_crypt_context->keyslot);

	return 0;
	if (src_bc->bc_keyslot >= 0)
		keyslot_manager_get_slot(src_bc->bc_ksm, src_bc->bc_keyslot);
}
EXPORT_SYMBOL(bio_crypt_clone);
EXPORT_SYMBOL_GPL(bio_crypt_clone);

bool bio_crypt_should_process(struct bio *bio, struct request_queue *q)
bool bio_crypt_should_process(struct request *rq)
{
	if (!bio_has_crypt_ctx(bio))
		return false;
	struct bio *bio = rq->bio;

	if (q->ksm != bio->bi_crypt_context->processing_ksm)
	if (!bio || !bio->bi_crypt_context)
		return false;

	WARN_ON(!bio_crypt_has_keyslot(bio));
	return true;
	return rq->q->ksm == bio->bi_crypt_context->bc_ksm;
}
EXPORT_SYMBOL(bio_crypt_should_process);
EXPORT_SYMBOL_GPL(bio_crypt_should_process);

/*
 * Checks that two bio crypt contexts are compatible - i.e. that
@@ -87,22 +99,17 @@ bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2)
	struct bio_crypt_ctx *bc1 = b_1->bi_crypt_context;
	struct bio_crypt_ctx *bc2 = b_2->bi_crypt_context;

	if (bio_has_crypt_ctx(b_1) != bio_has_crypt_ctx(b_2))
		return false;

	if (!bio_has_crypt_ctx(b_1))
		return true;

	return bc1->keyslot == bc2->keyslot &&
	       bc1->data_unit_size_bits == bc2->data_unit_size_bits;
	if (!bc1)
		return !bc2;
	return bc2 && bc1->bc_key == bc2->bc_key;
}

/*
 * Checks that two bio crypt contexts are compatible, and also
 * that their data_unit_nums are continuous (and can hence be merged)
 * in the order b_1 followed by b_2.
 */
bool bio_crypt_ctx_back_mergeable(struct bio *b_1,
				  unsigned int b1_sectors,
bool bio_crypt_ctx_mergeable(struct bio *b_1, unsigned int b1_bytes,
			     struct bio *b_2)
{
	struct bio_crypt_ctx *bc1 = b_1->bi_crypt_context;
@@ -111,35 +118,25 @@ bool bio_crypt_ctx_back_mergeable(struct bio *b_1,
	if (!bio_crypt_ctx_compatible(b_1, b_2))
		return false;

	return !bio_has_crypt_ctx(b_1) ||
		(bc1->data_unit_num +
		(b1_sectors >> (bc1->data_unit_size_bits - 9)) ==
		bc2->data_unit_num);
	return !bc1 || bio_crypt_dun_is_contiguous(bc1, b1_bytes, bc2->bc_dun);
}

void bio_crypt_ctx_release_keyslot(struct bio *bio)
void bio_crypt_ctx_release_keyslot(struct bio_crypt_ctx *bc)
{
	struct bio_crypt_ctx *crypt_ctx = bio->bi_crypt_context;

	keyslot_manager_put_slot(crypt_ctx->processing_ksm, crypt_ctx->keyslot);
	bio->bi_crypt_context->processing_ksm = NULL;
	bio->bi_crypt_context->keyslot = -1;
	keyslot_manager_put_slot(bc->bc_ksm, bc->bc_keyslot);
	bc->bc_ksm = NULL;
	bc->bc_keyslot = -1;
}

int bio_crypt_ctx_acquire_keyslot(struct bio *bio, struct keyslot_manager *ksm)
int bio_crypt_ctx_acquire_keyslot(struct bio_crypt_ctx *bc,
				  struct keyslot_manager *ksm)
{
	int slot;
	enum blk_crypto_mode_num crypto_mode = bio_crypto_mode(bio);

	if (!ksm)
		return -ENOMEM;
	int slot = keyslot_manager_get_slot_for_key(ksm, bc->bc_key);

	slot = keyslot_manager_get_slot_for_key(ksm,
			bio_crypt_raw_key(bio), crypto_mode,
			1 << bio->bi_crypt_context->data_unit_size_bits);
	if (slot < 0)
		return slot;

	bio_crypt_set_keyslot(bio, slot, ksm);
	bc->bc_keyslot = slot;
	bc->bc_ksm = ksm;
	return 0;
}
Loading