From a445c3365f17490d25410b95ffdaa363b395dbaa Mon Sep 17 00:00:00 2001 From: Neeraj Soni Date: Thu, 27 Aug 2020 12:02:47 +0530 Subject: [PATCH] mmc: host: reprogram the key to cover the invalid config case This is a workaround to cover a corner case where the host controller crashes with invalid config error as the crypto config in crypto engine are lost between key programming call and descriptor processing. Test: fscryptctl test cases. Change-Id: I83c1f928a52747686a7341f6d80478dc3d683191 Signed-off-by: Neeraj Soni --- drivers/mmc/host/cmdq_hci-crypto-qti.c | 63 ++++++++++++++++++++++++-- drivers/mmc/host/cmdq_hci-crypto-qti.h | 6 +++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/cmdq_hci-crypto-qti.c b/drivers/mmc/host/cmdq_hci-crypto-qti.c index 957e3713dd8c..0573d5bec4b1 100644 --- a/drivers/mmc/host/cmdq_hci-crypto-qti.c +++ b/drivers/mmc/host/cmdq_hci-crypto-qti.c @@ -20,6 +20,7 @@ #include "cmdq_hci-crypto-qti.h" #include #include +#include #define RAW_SECRET_SIZE 32 #define MINIMUM_DUN_SIZE 512 @@ -31,8 +32,12 @@ static struct cmdq_host_crypto_variant_ops cmdq_crypto_qti_variant_ops = { .disable = cmdq_crypto_qti_disable, .resume = cmdq_crypto_qti_resume, .debug = cmdq_crypto_qti_debug, + .reset = cmdq_crypto_qti_reset, + .prepare_crypto_desc = cmdq_crypto_qti_prep_desc, }; +static atomic_t keycache; + static bool ice_cap_idx_valid(struct cmdq_host *host, unsigned int cap_idx) { @@ -69,10 +74,14 @@ void cmdq_crypto_qti_enable(struct cmdq_host *host) void cmdq_crypto_qti_disable(struct cmdq_host *host) { - /* cmdq_crypto_disable_spec(host) and - * crypto_qti_disable(host->crypto_vops->priv) - * are needed here? - */ + cmdq_crypto_disable_spec(host); + crypto_qti_disable(host->crypto_vops->priv); +} + +int cmdq_crypto_qti_reset(struct cmdq_host *host) +{ + atomic_set(&keycache, 0); + return 0; } static int cmdq_crypto_qti_keyslot_program(struct keyslot_manager *ksm, @@ -119,6 +128,7 @@ static int cmdq_crypto_qti_keyslot_evict(struct keyslot_manager *ksm, unsigned int slot) { int err = 0; + int val = 0; struct cmdq_host *host = keyslot_manager_private(ksm); pm_runtime_get_sync(&host->mmc->card->dev); @@ -134,6 +144,8 @@ static int cmdq_crypto_qti_keyslot_evict(struct keyslot_manager *ksm, pr_err("%s: failed with error %d\n", __func__, err); pm_runtime_put_sync(&host->mmc->card->dev); + val = atomic_read(&keycache) & ~(1 << slot); + atomic_set(&keycache, val); return err; } @@ -303,6 +315,49 @@ int cmdq_crypto_qti_init_crypto(struct cmdq_host *host, return err; } +int cmdq_crypto_qti_prep_desc(struct cmdq_host *host, struct mmc_request *mrq, + u64 *ice_ctx) +{ + struct bio_crypt_ctx *bc; + struct request *req = mrq->req; + int ret; + int val = 0; + + if (!req->bio || !bio_crypt_should_process(req)) { + *ice_ctx = 0; + return 0; + } + if (WARN_ON(!cmdq_is_crypto_enabled(host))) { + /* + * Upper layer asked us to do inline encryption + * but that isn't enabled, so we fail this request. + */ + return -EINVAL; + } + + bc = req->bio->bi_crypt_context; + + if (!cmdq_keyslot_valid(host, bc->bc_keyslot)) + return -EINVAL; + if (!(atomic_read(&keycache) & (1 << bc->bc_keyslot))) { + ret = cmdq_crypto_qti_keyslot_program(host->ksm, bc->bc_key, + bc->bc_keyslot); + if (ret) { + pr_err("%s keyslot program failed %d\n", __func__, ret); + return ret; + } + val = atomic_read(&keycache) | (1 << bc->bc_keyslot); + atomic_set(&keycache, val); + } + + if (ice_ctx) { + *ice_ctx = DATA_UNIT_NUM(bc->bc_dun[0]) | + CRYPTO_CONFIG_INDEX(bc->bc_keyslot) | + CRYPTO_ENABLE(true); + } + return 0; +} + int cmdq_crypto_qti_debug(struct cmdq_host *host) { return crypto_qti_debug(host->crypto_vops->priv); diff --git a/drivers/mmc/host/cmdq_hci-crypto-qti.h b/drivers/mmc/host/cmdq_hci-crypto-qti.h index e63465bca3e2..b186a9aa9d8a 100644 --- a/drivers/mmc/host/cmdq_hci-crypto-qti.h +++ b/drivers/mmc/host/cmdq_hci-crypto-qti.h @@ -30,4 +30,10 @@ void cmdq_crypto_qti_set_vops(struct cmdq_host *host); int cmdq_crypto_qti_resume(struct cmdq_host *host); +int cmdq_crypto_qti_prep_desc(struct cmdq_host *host, + struct mmc_request *mrq, + u64 *ice_ctx); + +int cmdq_crypto_qti_reset(struct cmdq_host *host); + #endif /* _CMDQ_HCI_CRYPTO_QTI_H */