[PATCH 6/6] mmc: sdhci-msm: Add additional algo mode for inline encryption

From: Md Sadre Alam
Date: Tue Jul 30 2024 - 08:02:27 EST


Add support for AES-XTS-128, AES-CBC-128 and AES-CBS-256 modes for
inline encryption. Since ICE (Inline Crypto Engine) supports these
all modes

Co-developed-by: Vignesh Viswanathan <quic_viswanat@xxxxxxxxxxx>
Signed-off-by: Vignesh Viswanathan <quic_viswanat@xxxxxxxxxxx>
Signed-off-by: Md Sadre Alam <quic_mdalam@xxxxxxxxxxx>
---
drivers/mmc/host/sdhci-msm.c | 10 ++----
drivers/soc/qcom/ice.c | 65 +++++++++++++++++++++++++++++++-----
2 files changed, 58 insertions(+), 17 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index e113b99a3eab..fc1db58373ce 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1867,17 +1867,11 @@ static int sdhci_msm_program_key(struct cqhci_host *cq_host,
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
union cqhci_crypto_cap_entry cap;

- /* Only AES-256-XTS has been tested so far. */
cap = cq_host->crypto_cap_array[cfg->crypto_cap_idx];
- if (cap.algorithm_id != CQHCI_CRYPTO_ALG_AES_XTS ||
- cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256)
- return -EINVAL;

if (cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE)
- return qcom_ice_program_key(msm_host->ice,
- QCOM_ICE_CRYPTO_ALG_AES_XTS,
- QCOM_ICE_CRYPTO_KEY_SIZE_256,
- cfg->crypto_key,
+ return qcom_ice_program_key(msm_host->ice, cap.algorithm_id,
+ cap.key_size, cfg->crypto_key,
cfg->data_unit_size, slot);
else
return qcom_ice_evict_key(msm_host->ice, slot);
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index fbab7fe5c652..f387b884c516 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -19,6 +19,9 @@

#include <soc/qcom/ice.h>

+#define AES_128_CBC_KEY_SIZE 16
+#define AES_256_CBC_KEY_SIZE 32
+#define AES_128_XTS_KEY_SIZE 32
#define AES_256_XTS_KEY_SIZE 64

/* QCOM ICE registers */
@@ -161,36 +164,80 @@ int qcom_ice_suspend(struct qcom_ice *ice)
}
EXPORT_SYMBOL_GPL(qcom_ice_suspend);

+static int qcom_ice_get_algo_mode(struct qcom_ice *ice, u8 algorithm_id,
+ u8 key_size, enum qcom_scm_ice_cipher *cipher,
+ u32 *key_len)
+{
+ struct device *dev = ice->dev;
+
+ switch (key_size) {
+ case QCOM_ICE_CRYPTO_KEY_SIZE_128:
+ fallthrough;
+ case QCOM_ICE_CRYPTO_KEY_SIZE_256:
+ break;
+ default:
+ dev_err(dev, "Unhandled crypto key size %d\n", key_size);
+ return -EINVAL;
+ }
+
+ switch (algorithm_id) {
+ case QCOM_ICE_CRYPTO_ALG_AES_XTS:
+ if (key_size == QCOM_ICE_CRYPTO_KEY_SIZE_256) {
+ *cipher = QCOM_SCM_ICE_CIPHER_AES_256_XTS;
+ *key_len = AES_256_XTS_KEY_SIZE;
+ } else {
+ *cipher = QCOM_SCM_ICE_CIPHER_AES_128_XTS;
+ *key_len = AES_128_XTS_KEY_SIZE;
+ }
+ break;
+ case QCOM_ICE_CRYPTO_ALG_BITLOCKER_AES_CBC:
+ if (key_size == QCOM_ICE_CRYPTO_KEY_SIZE_256) {
+ *cipher = QCOM_SCM_ICE_CIPHER_AES_256_CBC;
+ *key_len = AES_256_CBC_KEY_SIZE;
+ } else {
+ *cipher = QCOM_SCM_ICE_CIPHER_AES_128_CBC;
+ *key_len = AES_128_CBC_KEY_SIZE;
+ }
+ break;
+ default:
+ dev_err_ratelimited(dev, "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
+ algorithm_id, key_size);
+ return -EINVAL;
+ }
+
+ dev_info(dev, "cipher: %d key_size: %d", *cipher, *key_len);
+
+ return 0;
+}
+
int qcom_ice_program_key(struct qcom_ice *ice,
u8 algorithm_id, u8 key_size,
const u8 crypto_key[], u8 data_unit_size,
int slot)
{
struct device *dev = ice->dev;
+ enum qcom_scm_ice_cipher cipher;
union {
u8 bytes[AES_256_XTS_KEY_SIZE];
u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)];
} key;
int i;
int err;
+ u32 key_len;

- /* Only AES-256-XTS has been tested so far. */
- if (algorithm_id != QCOM_ICE_CRYPTO_ALG_AES_XTS ||
- key_size != QCOM_ICE_CRYPTO_KEY_SIZE_256) {
- dev_err_ratelimited(dev,
- "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
- algorithm_id, key_size);
+ if (qcom_ice_get_algo_mode(ice, algorithm_id, key_size, &cipher, &key_len)) {
+ dev_err(dev, "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
+ algorithm_id, key_size);
return -EINVAL;
}

- memcpy(key.bytes, crypto_key, AES_256_XTS_KEY_SIZE);
+ memcpy(key.bytes, crypto_key, key_len);

/* The SCM call requires that the key words are encoded in big endian */
for (i = 0; i < ARRAY_SIZE(key.words); i++)
__cpu_to_be32s(&key.words[i]);

- err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
- QCOM_SCM_ICE_CIPHER_AES_256_XTS,
+ err = qcom_scm_ice_set_key(slot, key.bytes, key_len, cipher,
data_unit_size);

memzero_explicit(&key, sizeof(key));
--
2.34.1