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 <[email protected]>
Signed-off-by: Vignesh Viswanathan <[email protected]>
Signed-off-by: Md Sadre Alam <[email protected]>
---
 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


Reply via email to