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

Commit af4a70ad authored by Neeraj Soni's avatar Neeraj Soni Committed by Jiten Patel
Browse files

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.

Ported and fixed the merged conflicts in cqhci-crypto-qti.c and
cqhci-crypto-qti.h file (cherry picked from mainline kernel_msm-4.14
commit: 3315421)

Conflicts:
	drivers/mmc/host/cqhci-crypto-qti.c
	drivers/mmc/host/cqhci-crypto-qti.h

Test:
1) Flashed Q meta, create multiple files under /data.
2) Build R (include changes topic: 660_OTA_FIXES) and flash
   APPS images of R except userdata and boot the device.
3) Device booted upto UI.
4) Files created with Q build retained.
5) Created new files under /data and checked retention across
   multiple re-boots.

Change-Id: Idc8ed67281e8f2955b7d759e6821a06ced36aa0b
Signed-off-by: default avatarNeeraj Soni <neersoni@codeaurora.org>
Signed-off-by: default avatarJiten Patel <jitepate@codeaurora.org>
parent 2d6fc51f
Loading
Loading
Loading
Loading
+62 −1
Original line number Diff line number Diff line
@@ -18,8 +18,10 @@
#include "sdhci-pltfm.h"
#include "sdhci-msm.h"
#include "cqhci-crypto-qti.h"
#include "../core/queue.h"
#include <linux/crypto-qti-common.h>
#include <linux/pm_runtime.h>
#include <linux/atomic.h>

#define RAW_SECRET_SIZE 32
#define MINIMUM_DUN_SIZE 512
@@ -31,8 +33,12 @@ static struct cqhci_host_crypto_variant_ops cqhci_crypto_qti_variant_ops = {
	.disable = cqhci_crypto_qti_disable,
	.resume = cqhci_crypto_qti_resume,
	.debug = cqhci_crypto_qti_debug,
	.reset = cqhci_crypto_qti_reset,
	.prepare_crypto_desc = cqhci_crypto_qti_prep_desc,
};

static atomic_t keycache;

static bool ice_cap_idx_valid(struct cqhci_host *host,
					unsigned int cap_idx)
{
@@ -73,6 +79,12 @@ void cqhci_crypto_qti_disable(struct cqhci_host *host)
	crypto_qti_disable(host->crypto_vops->priv);
}

int cqhci_crypto_qti_reset(struct cqhci_host *host)
{
	atomic_set(&keycache, 0);
	return 0;
}

static int cqhci_crypto_qti_keyslot_program(struct keyslot_manager *ksm,
					    const struct blk_crypto_key *key,
					    unsigned int slot)
@@ -116,6 +128,7 @@ static int cqhci_crypto_qti_keyslot_evict(struct keyslot_manager *ksm,
					  unsigned int slot)
{
	int err = 0;
	int val = 0;
	struct cqhci_host *host = keyslot_manager_private(ksm);
	pm_runtime_get_sync(&host->mmc->card->dev);

@@ -130,7 +143,8 @@ static int cqhci_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;
}

@@ -291,6 +305,53 @@ int cqhci_crypto_qti_init_crypto(struct cqhci_host *host,
	return err;
}


int cqhci_crypto_qti_prep_desc(struct cqhci_host *host, struct mmc_request *mrq,
	u64 *ice_ctx)
{
	struct bio_crypt_ctx *bc;
	struct mmc_queue_req *mqrq = container_of(mrq, struct mmc_queue_req,
						  brq.mrq);
	struct request *req = mmc_queue_req_to_req(mqrq);
	int ret;
	int val = 0;

	if (!req->bio || !bio_crypt_should_process(req)) {
		*ice_ctx = 0;
		return 0;
	}
	if (WARN_ON(!cqhci_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 (!cqhci_keyslot_valid(host, bc->bc_keyslot))
		return -EINVAL;
	if (!(atomic_read(&keycache) & (1 << bc->bc_keyslot)))  {
		ret = cqhci_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 cqhci_crypto_qti_debug(struct cqhci_host *host)
{
	return crypto_qti_debug(host->crypto_vops->priv);
+5 −0
Original line number Diff line number Diff line
@@ -22,5 +22,10 @@ int cqhci_crypto_qti_debug(struct cqhci_host *host);
void cqhci_crypto_qti_set_vops(struct cqhci_host *host);

int cqhci_crypto_qti_resume(struct cqhci_host *host);
int cqhci_crypto_qti_prep_desc(struct cqhci_host *host,
				struct mmc_request *mrq,
				u64 *ice_ctx);

int cqhci_crypto_qti_reset(struct cqhci_host *host);

#endif /* _UFSHCD_ICE_QTI_H */