mmc: core: Add basic support for inline encryption

In preparation for adding CQHCI crypto engine (inline encryption)
support, add the code required to make mmc_core and mmc_block aware of
inline encryption.  Specifically:

- Add a capability flag MMC_CAP2_CRYPTO to struct mmc_host.  Drivers
  will set this if the host and driver support inline encryption.

- Embed a blk_keyslot_manager in struct mmc_host.  Drivers will
  initialize this (as a device-managed resource) if the host and driver
  support inline encryption.  mmc_block registers this keyslot manager
  with the request_queue of any MMC card attached to the host.

- Make mmc_block copy the crypto keyslot and crypto data unit number
  from struct request to struct mmc_request, so that drivers will have
  access to them.

- If the MMC host is reset, reprogram all the keyslots to ensure that
  the software state stays in sync with the hardware state.

Co-developed-by: Satya Tangirala <satyat@google.com>
Signed-off-by: Satya Tangirala <satyat@google.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Satya Tangirala <satyat@google.com>
Reviewed-and-tested-by: Peng Zhou <peng.zhou@mediatek.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Link: https://lore.kernel.org/r/20210126001456.382989-2-ebiggers@kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
Eric Biggers 2021-01-25 16:14:48 -08:00 committed by Ulf Hansson
parent d76d9d7d10
commit 93f1c150cb
10 changed files with 124 additions and 0 deletions

View file

@ -81,3 +81,11 @@ config MMC_TEST
This driver is only of interest to those developing or
testing a host driver. Most people should say N here.
config MMC_CRYPTO
bool "MMC Crypto Engine Support"
depends on BLK_INLINE_ENCRYPTION
help
Enable Crypto Engine Support in MMC.
Enabling this makes it possible for the kernel to use the crypto
capabilities of the MMC device (if present) to perform crypto
operations on data being transferred to/from the device.

View file

@ -18,3 +18,4 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
mmc_block-objs := block.o queue.o
obj-$(CONFIG_MMC_TEST) += mmc_test.o
obj-$(CONFIG_SDIO_UART) += sdio_uart.o
mmc_core-$(CONFIG_MMC_CRYPTO) += crypto.o

View file

@ -51,6 +51,7 @@
#include "block.h"
#include "core.h"
#include "card.h"
#include "crypto.h"
#include "host.h"
#include "bus.h"
#include "mmc_ops.h"
@ -1247,6 +1248,8 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq,
memset(brq, 0, sizeof(struct mmc_blk_request));
mmc_crypto_prepare_req(mqrq);
brq->mrq.data = &brq->data;
brq->mrq.tag = req->tag;

View file

@ -37,6 +37,7 @@
#include "core.h"
#include "card.h"
#include "crypto.h"
#include "bus.h"
#include "host.h"
#include "sdio_bus.h"
@ -992,6 +993,8 @@ void mmc_set_initial_state(struct mmc_host *host)
host->ops->hs400_enhanced_strobe(host, &host->ios);
mmc_set_ios(host);
mmc_crypto_set_initial_state(host);
}
/**

48
drivers/mmc/core/crypto.c Normal file
View file

@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* MMC crypto engine (inline encryption) support
*
* Copyright 2020 Google LLC
*/
#include <linux/blk-crypto.h>
#include <linux/mmc/host.h>
#include "core.h"
#include "crypto.h"
#include "queue.h"
void mmc_crypto_set_initial_state(struct mmc_host *host)
{
/* Reset might clear all keys, so reprogram all the keys. */
if (host->caps2 & MMC_CAP2_CRYPTO)
blk_ksm_reprogram_all_keys(&host->ksm);
}
void mmc_crypto_setup_queue(struct request_queue *q, struct mmc_host *host)
{
if (host->caps2 & MMC_CAP2_CRYPTO)
blk_ksm_register(&host->ksm, q);
}
EXPORT_SYMBOL_GPL(mmc_crypto_setup_queue);
void mmc_crypto_prepare_req(struct mmc_queue_req *mqrq)
{
struct request *req = mmc_queue_req_to_req(mqrq);
struct mmc_request *mrq = &mqrq->brq.mrq;
if (!req->crypt_keyslot)
return;
mrq->crypto_enabled = true;
mrq->crypto_key_slot = blk_ksm_get_slot_idx(req->crypt_keyslot);
/*
* For now we assume that all MMC drivers set max_dun_bytes_supported=4,
* which is the limit for CQHCI crypto. So all DUNs should be 32-bit.
*/
WARN_ON_ONCE(req->crypt_ctx->bc_dun[0] > U32_MAX);
mrq->data_unit_num = req->crypt_ctx->bc_dun[0];
}
EXPORT_SYMBOL_GPL(mmc_crypto_prepare_req);

40
drivers/mmc/core/crypto.h Normal file
View file

@ -0,0 +1,40 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* MMC crypto engine (inline encryption) support
*
* Copyright 2020 Google LLC
*/
#ifndef _MMC_CORE_CRYPTO_H
#define _MMC_CORE_CRYPTO_H
struct mmc_host;
struct mmc_queue_req;
struct request_queue;
#ifdef CONFIG_MMC_CRYPTO
void mmc_crypto_set_initial_state(struct mmc_host *host);
void mmc_crypto_setup_queue(struct request_queue *q, struct mmc_host *host);
void mmc_crypto_prepare_req(struct mmc_queue_req *mqrq);
#else /* CONFIG_MMC_CRYPTO */
static inline void mmc_crypto_set_initial_state(struct mmc_host *host)
{
}
static inline void mmc_crypto_setup_queue(struct request_queue *q,
struct mmc_host *host)
{
}
static inline void mmc_crypto_prepare_req(struct mmc_queue_req *mqrq)
{
}
#endif /* !CONFIG_MMC_CRYPTO */
#endif /* _MMC_CORE_CRYPTO_H */

View file

@ -25,6 +25,7 @@
#include <linux/mmc/slot-gpio.h>
#include "core.h"
#include "crypto.h"
#include "host.h"
#include "slot-gpio.h"
#include "pwrseq.h"

View file

@ -19,6 +19,7 @@
#include "block.h"
#include "core.h"
#include "card.h"
#include "crypto.h"
#include "host.h"
#define MMC_DMA_MAP_MERGE_SEGMENTS 512
@ -407,6 +408,8 @@ static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card)
mutex_init(&mq->complete_lock);
init_waitqueue_head(&mq->wait);
mmc_crypto_setup_queue(mq->queue, host);
}
static inline bool mmc_merge_capable(struct mmc_host *host)

View file

@ -162,6 +162,12 @@ struct mmc_request {
bool cap_cmd_during_tfr;
int tag;
#ifdef CONFIG_MMC_CRYPTO
bool crypto_enabled;
int crypto_key_slot;
u32 data_unit_num;
#endif
};
struct mmc_card;

View file

@ -15,6 +15,7 @@
#include <linux/mmc/card.h>
#include <linux/mmc/pm.h>
#include <linux/dma-direction.h>
#include <linux/keyslot-manager.h>
struct mmc_ios {
unsigned int clock; /* clock rate */
@ -395,6 +396,11 @@ struct mmc_host {
#define MMC_CAP2_CQE_DCMD (1 << 24) /* CQE can issue a direct command */
#define MMC_CAP2_AVOID_3_3V (1 << 25) /* Host must negotiate down from 3.3V */
#define MMC_CAP2_MERGE_CAPABLE (1 << 26) /* Host can merge a segment over the segment size */
#ifdef CONFIG_MMC_CRYPTO
#define MMC_CAP2_CRYPTO (1 << 27) /* Host supports inline encryption */
#else
#define MMC_CAP2_CRYPTO 0
#endif
int fixed_drv_type; /* fixed driver type for non-removable media */
@ -489,6 +495,11 @@ struct mmc_host {
bool cqe_enabled;
bool cqe_on;
/* Inline encryption support */
#ifdef CONFIG_MMC_CRYPTO
struct blk_keyslot_manager ksm;
#endif
/* Host Software Queue support */
bool hsq_enabled;