162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * CQHCI crypto engine (inline encryption) support
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2020 Google LLC
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/blk-crypto.h>
962306a36Sopenharmony_ci#include <linux/blk-crypto-profile.h>
1062306a36Sopenharmony_ci#include <linux/mmc/host.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "cqhci-crypto.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/* Map from blk-crypto modes to CQHCI crypto algorithm IDs and key sizes */
1562306a36Sopenharmony_cistatic const struct cqhci_crypto_alg_entry {
1662306a36Sopenharmony_ci	enum cqhci_crypto_alg alg;
1762306a36Sopenharmony_ci	enum cqhci_crypto_key_size key_size;
1862306a36Sopenharmony_ci} cqhci_crypto_algs[BLK_ENCRYPTION_MODE_MAX] = {
1962306a36Sopenharmony_ci	[BLK_ENCRYPTION_MODE_AES_256_XTS] = {
2062306a36Sopenharmony_ci		.alg = CQHCI_CRYPTO_ALG_AES_XTS,
2162306a36Sopenharmony_ci		.key_size = CQHCI_CRYPTO_KEY_SIZE_256,
2262306a36Sopenharmony_ci	},
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic inline struct cqhci_host *
2662306a36Sopenharmony_cicqhci_host_from_crypto_profile(struct blk_crypto_profile *profile)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	struct mmc_host *mmc =
2962306a36Sopenharmony_ci		container_of(profile, struct mmc_host, crypto_profile);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	return mmc->cqe_private;
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic int cqhci_crypto_program_key(struct cqhci_host *cq_host,
3562306a36Sopenharmony_ci				    const union cqhci_crypto_cfg_entry *cfg,
3662306a36Sopenharmony_ci				    int slot)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	u32 slot_offset = cq_host->crypto_cfg_register + slot * sizeof(*cfg);
3962306a36Sopenharmony_ci	int i;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (cq_host->ops->program_key)
4262306a36Sopenharmony_ci		return cq_host->ops->program_key(cq_host, cfg, slot);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	/* Clear CFGE */
4562306a36Sopenharmony_ci	cqhci_writel(cq_host, 0, slot_offset + 16 * sizeof(cfg->reg_val[0]));
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	/* Write the key */
4862306a36Sopenharmony_ci	for (i = 0; i < 16; i++) {
4962306a36Sopenharmony_ci		cqhci_writel(cq_host, le32_to_cpu(cfg->reg_val[i]),
5062306a36Sopenharmony_ci			     slot_offset + i * sizeof(cfg->reg_val[0]));
5162306a36Sopenharmony_ci	}
5262306a36Sopenharmony_ci	/* Write dword 17 */
5362306a36Sopenharmony_ci	cqhci_writel(cq_host, le32_to_cpu(cfg->reg_val[17]),
5462306a36Sopenharmony_ci		     slot_offset + 17 * sizeof(cfg->reg_val[0]));
5562306a36Sopenharmony_ci	/* Write dword 16, which includes the new value of CFGE */
5662306a36Sopenharmony_ci	cqhci_writel(cq_host, le32_to_cpu(cfg->reg_val[16]),
5762306a36Sopenharmony_ci		     slot_offset + 16 * sizeof(cfg->reg_val[0]));
5862306a36Sopenharmony_ci	return 0;
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic int cqhci_crypto_keyslot_program(struct blk_crypto_profile *profile,
6262306a36Sopenharmony_ci					const struct blk_crypto_key *key,
6362306a36Sopenharmony_ci					unsigned int slot)
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	struct cqhci_host *cq_host = cqhci_host_from_crypto_profile(profile);
6762306a36Sopenharmony_ci	const union cqhci_crypto_cap_entry *ccap_array =
6862306a36Sopenharmony_ci		cq_host->crypto_cap_array;
6962306a36Sopenharmony_ci	const struct cqhci_crypto_alg_entry *alg =
7062306a36Sopenharmony_ci			&cqhci_crypto_algs[key->crypto_cfg.crypto_mode];
7162306a36Sopenharmony_ci	u8 data_unit_mask = key->crypto_cfg.data_unit_size / 512;
7262306a36Sopenharmony_ci	int i;
7362306a36Sopenharmony_ci	int cap_idx = -1;
7462306a36Sopenharmony_ci	union cqhci_crypto_cfg_entry cfg = {};
7562306a36Sopenharmony_ci	int err;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	BUILD_BUG_ON(CQHCI_CRYPTO_KEY_SIZE_INVALID != 0);
7862306a36Sopenharmony_ci	for (i = 0; i < cq_host->crypto_capabilities.num_crypto_cap; i++) {
7962306a36Sopenharmony_ci		if (ccap_array[i].algorithm_id == alg->alg &&
8062306a36Sopenharmony_ci		    ccap_array[i].key_size == alg->key_size &&
8162306a36Sopenharmony_ci		    (ccap_array[i].sdus_mask & data_unit_mask)) {
8262306a36Sopenharmony_ci			cap_idx = i;
8362306a36Sopenharmony_ci			break;
8462306a36Sopenharmony_ci		}
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci	if (WARN_ON(cap_idx < 0))
8762306a36Sopenharmony_ci		return -EOPNOTSUPP;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	cfg.data_unit_size = data_unit_mask;
9062306a36Sopenharmony_ci	cfg.crypto_cap_idx = cap_idx;
9162306a36Sopenharmony_ci	cfg.config_enable = CQHCI_CRYPTO_CONFIGURATION_ENABLE;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	if (ccap_array[cap_idx].algorithm_id == CQHCI_CRYPTO_ALG_AES_XTS) {
9462306a36Sopenharmony_ci		/* In XTS mode, the blk_crypto_key's size is already doubled */
9562306a36Sopenharmony_ci		memcpy(cfg.crypto_key, key->raw, key->size/2);
9662306a36Sopenharmony_ci		memcpy(cfg.crypto_key + CQHCI_CRYPTO_KEY_MAX_SIZE/2,
9762306a36Sopenharmony_ci		       key->raw + key->size/2, key->size/2);
9862306a36Sopenharmony_ci	} else {
9962306a36Sopenharmony_ci		memcpy(cfg.crypto_key, key->raw, key->size);
10062306a36Sopenharmony_ci	}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	err = cqhci_crypto_program_key(cq_host, &cfg, slot);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	memzero_explicit(&cfg, sizeof(cfg));
10562306a36Sopenharmony_ci	return err;
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistatic int cqhci_crypto_clear_keyslot(struct cqhci_host *cq_host, int slot)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	/*
11162306a36Sopenharmony_ci	 * Clear the crypto cfg on the device. Clearing CFGE
11262306a36Sopenharmony_ci	 * might not be sufficient, so just clear the entire cfg.
11362306a36Sopenharmony_ci	 */
11462306a36Sopenharmony_ci	union cqhci_crypto_cfg_entry cfg = {};
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	return cqhci_crypto_program_key(cq_host, &cfg, slot);
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic int cqhci_crypto_keyslot_evict(struct blk_crypto_profile *profile,
12062306a36Sopenharmony_ci				      const struct blk_crypto_key *key,
12162306a36Sopenharmony_ci				      unsigned int slot)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	struct cqhci_host *cq_host = cqhci_host_from_crypto_profile(profile);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	return cqhci_crypto_clear_keyslot(cq_host, slot);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci/*
12962306a36Sopenharmony_ci * The keyslot management operations for CQHCI crypto.
13062306a36Sopenharmony_ci *
13162306a36Sopenharmony_ci * Note that the block layer ensures that these are never called while the host
13262306a36Sopenharmony_ci * controller is runtime-suspended.  However, the CQE won't necessarily be
13362306a36Sopenharmony_ci * "enabled" when these are called, i.e. CQHCI_ENABLE might not be set in the
13462306a36Sopenharmony_ci * CQHCI_CFG register.  But the hardware allows that.
13562306a36Sopenharmony_ci */
13662306a36Sopenharmony_cistatic const struct blk_crypto_ll_ops cqhci_crypto_ops = {
13762306a36Sopenharmony_ci	.keyslot_program	= cqhci_crypto_keyslot_program,
13862306a36Sopenharmony_ci	.keyslot_evict		= cqhci_crypto_keyslot_evict,
13962306a36Sopenharmony_ci};
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic enum blk_crypto_mode_num
14262306a36Sopenharmony_cicqhci_find_blk_crypto_mode(union cqhci_crypto_cap_entry cap)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	int i;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cqhci_crypto_algs); i++) {
14762306a36Sopenharmony_ci		BUILD_BUG_ON(CQHCI_CRYPTO_KEY_SIZE_INVALID != 0);
14862306a36Sopenharmony_ci		if (cqhci_crypto_algs[i].alg == cap.algorithm_id &&
14962306a36Sopenharmony_ci		    cqhci_crypto_algs[i].key_size == cap.key_size)
15062306a36Sopenharmony_ci			return i;
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci	return BLK_ENCRYPTION_MODE_INVALID;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci/**
15662306a36Sopenharmony_ci * cqhci_crypto_init - initialize CQHCI crypto support
15762306a36Sopenharmony_ci * @cq_host: a cqhci host
15862306a36Sopenharmony_ci *
15962306a36Sopenharmony_ci * If the driver previously set MMC_CAP2_CRYPTO and the CQE declares
16062306a36Sopenharmony_ci * CQHCI_CAP_CS, initialize the crypto support.  This involves reading the
16162306a36Sopenharmony_ci * crypto capability registers, initializing the blk_crypto_profile, clearing
16262306a36Sopenharmony_ci * all keyslots, and enabling 128-bit task descriptors.
16362306a36Sopenharmony_ci *
16462306a36Sopenharmony_ci * Return: 0 if crypto was initialized or isn't supported; whether
16562306a36Sopenharmony_ci *	   MMC_CAP2_CRYPTO remains set indicates which one of those cases it is.
16662306a36Sopenharmony_ci *	   Also can return a negative errno value on unexpected error.
16762306a36Sopenharmony_ci */
16862306a36Sopenharmony_ciint cqhci_crypto_init(struct cqhci_host *cq_host)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	struct mmc_host *mmc = cq_host->mmc;
17162306a36Sopenharmony_ci	struct device *dev = mmc_dev(mmc);
17262306a36Sopenharmony_ci	struct blk_crypto_profile *profile = &mmc->crypto_profile;
17362306a36Sopenharmony_ci	unsigned int num_keyslots;
17462306a36Sopenharmony_ci	unsigned int cap_idx;
17562306a36Sopenharmony_ci	enum blk_crypto_mode_num blk_mode_num;
17662306a36Sopenharmony_ci	unsigned int slot;
17762306a36Sopenharmony_ci	int err = 0;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	if (!(mmc->caps2 & MMC_CAP2_CRYPTO) ||
18062306a36Sopenharmony_ci	    !(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS))
18162306a36Sopenharmony_ci		goto out;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	cq_host->crypto_capabilities.reg_val =
18462306a36Sopenharmony_ci			cpu_to_le32(cqhci_readl(cq_host, CQHCI_CCAP));
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	cq_host->crypto_cfg_register =
18762306a36Sopenharmony_ci		(u32)cq_host->crypto_capabilities.config_array_ptr * 0x100;
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	cq_host->crypto_cap_array =
19062306a36Sopenharmony_ci		devm_kcalloc(dev, cq_host->crypto_capabilities.num_crypto_cap,
19162306a36Sopenharmony_ci			     sizeof(cq_host->crypto_cap_array[0]), GFP_KERNEL);
19262306a36Sopenharmony_ci	if (!cq_host->crypto_cap_array) {
19362306a36Sopenharmony_ci		err = -ENOMEM;
19462306a36Sopenharmony_ci		goto out;
19562306a36Sopenharmony_ci	}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	/*
19862306a36Sopenharmony_ci	 * CCAP.CFGC is off by one, so the actual number of crypto
19962306a36Sopenharmony_ci	 * configurations (a.k.a. keyslots) is CCAP.CFGC + 1.
20062306a36Sopenharmony_ci	 */
20162306a36Sopenharmony_ci	num_keyslots = cq_host->crypto_capabilities.config_count + 1;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	err = devm_blk_crypto_profile_init(dev, profile, num_keyslots);
20462306a36Sopenharmony_ci	if (err)
20562306a36Sopenharmony_ci		goto out;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	profile->ll_ops = cqhci_crypto_ops;
20862306a36Sopenharmony_ci	profile->dev = dev;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	/* Unfortunately, CQHCI crypto only supports 32 DUN bits. */
21162306a36Sopenharmony_ci	profile->max_dun_bytes_supported = 4;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	/*
21462306a36Sopenharmony_ci	 * Cache all the crypto capabilities and advertise the supported crypto
21562306a36Sopenharmony_ci	 * modes and data unit sizes to the block layer.
21662306a36Sopenharmony_ci	 */
21762306a36Sopenharmony_ci	for (cap_idx = 0; cap_idx < cq_host->crypto_capabilities.num_crypto_cap;
21862306a36Sopenharmony_ci	     cap_idx++) {
21962306a36Sopenharmony_ci		cq_host->crypto_cap_array[cap_idx].reg_val =
22062306a36Sopenharmony_ci			cpu_to_le32(cqhci_readl(cq_host,
22162306a36Sopenharmony_ci						CQHCI_CRYPTOCAP +
22262306a36Sopenharmony_ci						cap_idx * sizeof(__le32)));
22362306a36Sopenharmony_ci		blk_mode_num = cqhci_find_blk_crypto_mode(
22462306a36Sopenharmony_ci					cq_host->crypto_cap_array[cap_idx]);
22562306a36Sopenharmony_ci		if (blk_mode_num == BLK_ENCRYPTION_MODE_INVALID)
22662306a36Sopenharmony_ci			continue;
22762306a36Sopenharmony_ci		profile->modes_supported[blk_mode_num] |=
22862306a36Sopenharmony_ci			cq_host->crypto_cap_array[cap_idx].sdus_mask * 512;
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	/* Clear all the keyslots so that we start in a known state. */
23262306a36Sopenharmony_ci	for (slot = 0; slot < num_keyslots; slot++)
23362306a36Sopenharmony_ci		cqhci_crypto_clear_keyslot(cq_host, slot);
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	/* CQHCI crypto requires the use of 128-bit task descriptors. */
23662306a36Sopenharmony_ci	cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	return 0;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ciout:
24162306a36Sopenharmony_ci	mmc->caps2 &= ~MMC_CAP2_CRYPTO;
24262306a36Sopenharmony_ci	return err;
24362306a36Sopenharmony_ci}
244