linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
@ 2023-07-19 17:04 Gaurav Kashyap
  2023-07-19 17:04 ` [PATCH v2 01/10] ice, ufs, mmc: use blk_crypto_key for program_key Gaurav Kashyap
                   ` (12 more replies)
  0 siblings, 13 replies; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

These patches add support to Qualcomm ICE (Inline Crypto Enginr) for hardware
wrapped keys using Qualcomm Hardware Key Manager (HWKM) and are made on top
of a rebased version  Eric Bigger's set of changes to support wrapped keys in
fscrypt and block below:
https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7
(The rebased patches are not uploaded here)

Ref v1 here:
https://lore.kernel.org/linux-scsi/20211206225725.77512-1-quic_gaurkash@quicinc.com/

Explanation and use of hardware-wrapped-keys can be found here:
Documentation/block/inline-encryption.rst

This patch is organized as follows:

Patch 1 - Prepares ICE and storage layers (UFS and EMMC) to pass around wrapped keys.
Patch 2 - Adds a new SCM api to support deriving software secret when wrapped keys are used
Patch 3-4 - Adds support for wrapped keys in the ICE driver. This includes adding HWKM support
Patch 5-6 - Adds support for wrapped keys in UFS
Patch 7-10 - Supports generate, prepare and import functionality in ICE and UFS

NOTE: MMC will have similar changes to UFS and will be uploaded in a different patchset
      Patch 3, 4, 8, 10 will have MMC equivalents.

Testing:
Test platform: SM8550 MTP
Engineering trustzone image is required to test this feature only
for SM8550. For SM8650 onwards, all trustzone changes to support this
will be part of the released images.
The engineering changes primarily contain hooks to generate, import and
prepare keys for HW wrapped disk encryption.

The changes were tested by mounting initramfs and running the fscryptctl
tool (Ref: https://github.com/ebiggers/fscryptctl/tree/wip-wrapped-keys) to
generate and prepare keys, as well as to set policies on folders, which
consequently invokes disk encryption flows through UFS.

Gaurav Kashyap (10):
  ice, ufs, mmc: use blk_crypto_key for program_key
  qcom_scm: scm call for deriving a software secret
  soc: qcom: ice: add hwkm support in ice
  soc: qcom: ice: support for hardware wrapped keys
  ufs: core: support wrapped keys in ufs core
  ufs: host: wrapped keys support in ufs qcom
  qcom_scm: scm call for create, prepare and import keys
  ufs: core: add support for generate, import and prepare keys
  soc: qcom: support for generate, import and prepare key
  ufs: host: support for generate, import and prepare key

 drivers/firmware/qcom_scm.c            | 292 +++++++++++++++++++++++
 drivers/firmware/qcom_scm.h            |   4 +
 drivers/mmc/host/cqhci-crypto.c        |   7 +-
 drivers/mmc/host/cqhci.h               |   2 +
 drivers/mmc/host/sdhci-msm.c           |   6 +-
 drivers/soc/qcom/ice.c                 | 309 +++++++++++++++++++++++--
 drivers/ufs/core/ufshcd-crypto.c       |  92 +++++++-
 drivers/ufs/host/ufs-qcom.c            |  63 ++++-
 include/linux/firmware/qcom/qcom_scm.h |  13 ++
 include/soc/qcom/ice.h                 |  18 +-
 include/ufs/ufshcd.h                   |  25 ++
 11 files changed, 797 insertions(+), 34 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 01/10] ice, ufs, mmc: use blk_crypto_key for program_key
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
@ 2023-07-19 17:04 ` Gaurav Kashyap
  2023-07-19 17:04 ` [PATCH v2 02/10] qcom_scm: scm call for deriving a software secret Gaurav Kashyap
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

The program key ops in the storage controller does not
pass on the blk crypto key structure to ice, this is okay
when wrapped keys are not supported and keys are standard
AES XTS sizes. However, wrapped keyblobs can be of any size
and in preparation for that, modify the ICE and storage
controller APIs to accept blk_crypto_key.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/mmc/host/cqhci-crypto.c  | 7 ++++---
 drivers/mmc/host/cqhci.h         | 2 ++
 drivers/mmc/host/sdhci-msm.c     | 6 ++++--
 drivers/soc/qcom/ice.c           | 6 +++---
 drivers/ufs/core/ufshcd-crypto.c | 7 ++++---
 drivers/ufs/host/ufs-qcom.c      | 6 ++++--
 include/soc/qcom/ice.h           | 5 +++--
 include/ufs/ufshcd.h             | 1 +
 8 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/drivers/mmc/host/cqhci-crypto.c b/drivers/mmc/host/cqhci-crypto.c
index 6652982410ec..91da6de1d650 100644
--- a/drivers/mmc/host/cqhci-crypto.c
+++ b/drivers/mmc/host/cqhci-crypto.c
@@ -32,6 +32,7 @@ cqhci_host_from_crypto_profile(struct blk_crypto_profile *profile)
 }
 
 static int cqhci_crypto_program_key(struct cqhci_host *cq_host,
+				    const struct blk_crypto_key *bkey,
 				    const union cqhci_crypto_cfg_entry *cfg,
 				    int slot)
 {
@@ -39,7 +40,7 @@ static int cqhci_crypto_program_key(struct cqhci_host *cq_host,
 	int i;
 
 	if (cq_host->ops->program_key)
-		return cq_host->ops->program_key(cq_host, cfg, slot);
+		return cq_host->ops->program_key(cq_host, bkey, cfg, slot);
 
 	/* Clear CFGE */
 	cqhci_writel(cq_host, 0, slot_offset + 16 * sizeof(cfg->reg_val[0]));
@@ -99,7 +100,7 @@ static int cqhci_crypto_keyslot_program(struct blk_crypto_profile *profile,
 		memcpy(cfg.crypto_key, key->raw, key->size);
 	}
 
-	err = cqhci_crypto_program_key(cq_host, &cfg, slot);
+	err = cqhci_crypto_program_key(cq_host, key, &cfg, slot);
 
 	memzero_explicit(&cfg, sizeof(cfg));
 	return err;
@@ -113,7 +114,7 @@ static int cqhci_crypto_clear_keyslot(struct cqhci_host *cq_host, int slot)
 	 */
 	union cqhci_crypto_cfg_entry cfg = {};
 
-	return cqhci_crypto_program_key(cq_host, &cfg, slot);
+	return cqhci_crypto_program_key(cq_host, NULL, &cfg, slot);
 }
 
 static int cqhci_crypto_keyslot_evict(struct blk_crypto_profile *profile,
diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
index 1a12e40a02e6..949ebbe05773 100644
--- a/drivers/mmc/host/cqhci.h
+++ b/drivers/mmc/host/cqhci.h
@@ -12,6 +12,7 @@
 #include <linux/completion.h>
 #include <linux/wait.h>
 #include <linux/irqreturn.h>
+#include <linux/blk-crypto.h>
 #include <asm/io.h>
 
 /* registers */
@@ -291,6 +292,7 @@ struct cqhci_host_ops {
 	void (*post_disable)(struct mmc_host *mmc);
 #ifdef CONFIG_MMC_CRYPTO
 	int (*program_key)(struct cqhci_host *cq_host,
+			   const struct blk_crypto_key *bkey,
 			   const union cqhci_crypto_cfg_entry *cfg, int slot);
 #endif
 };
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 1c935b5bafe1..487d2fdcc7a8 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1859,6 +1859,7 @@ static __maybe_unused int sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
  * vendor-specific SCM calls for this; it doesn't support the standard way.
  */
 static int sdhci_msm_program_key(struct cqhci_host *cq_host,
+				 const struct blk_crypto_key_type *bkey,
 				 const union cqhci_crypto_cfg_entry *cfg,
 				 int slot)
 {
@@ -1866,6 +1867,7 @@ static int sdhci_msm_program_key(struct cqhci_host *cq_host,
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
 	union cqhci_crypto_cap_entry cap;
+	u8 ice_key_size;
 
 	/* Only AES-256-XTS has been tested so far. */
 	cap = cq_host->crypto_cap_array[cfg->crypto_cap_idx];
@@ -1873,11 +1875,11 @@ static int sdhci_msm_program_key(struct cqhci_host *cq_host,
 		cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256)
 		return -EINVAL;
 
+	ice_key_size = QCOM_ICE_CRYPTO_KEY_SIZE_256;
 	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,
+					    ice_key_size, bkey,
 					    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 a6123ea96272..d19f674bb1b6 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -161,8 +161,8 @@ EXPORT_SYMBOL_GPL(qcom_ice_suspend);
 
 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)
+			 const struct blk_crypto_key *bkey,
+			 u8 data_unit_size, int slot)
 {
 	struct device *dev = ice->dev;
 	union {
@@ -181,7 +181,7 @@ int qcom_ice_program_key(struct qcom_ice *ice,
 		return -EINVAL;
 	}
 
-	memcpy(key.bytes, crypto_key, AES_256_XTS_KEY_SIZE);
+	memcpy(key.bytes, bkey->raw, AES_256_XTS_KEY_SIZE);
 
 	/* The SCM call requires that the key words are encoded in big endian */
 	for (i = 0; i < ARRAY_SIZE(key.words); i++)
diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c
index f4cc54d82281..34537cbac622 100644
--- a/drivers/ufs/core/ufshcd-crypto.c
+++ b/drivers/ufs/core/ufshcd-crypto.c
@@ -18,6 +18,7 @@ static const struct ufs_crypto_alg_entry {
 };
 
 static int ufshcd_program_key(struct ufs_hba *hba,
+			      const struct blk_crypto_key *bkey,
 			      const union ufs_crypto_cfg_entry *cfg, int slot)
 {
 	int i;
@@ -27,7 +28,7 @@ static int ufshcd_program_key(struct ufs_hba *hba,
 	ufshcd_hold(hba);
 
 	if (hba->vops && hba->vops->program_key) {
-		err = hba->vops->program_key(hba, cfg, slot);
+		err = hba->vops->program_key(hba, bkey, cfg, slot);
 		goto out;
 	}
 
@@ -89,7 +90,7 @@ static int ufshcd_crypto_keyslot_program(struct blk_crypto_profile *profile,
 		memcpy(cfg.crypto_key, key->raw, key->size);
 	}
 
-	err = ufshcd_program_key(hba, &cfg, slot);
+	err = ufshcd_program_key(hba, key, &cfg, slot);
 
 	memzero_explicit(&cfg, sizeof(cfg));
 	return err;
@@ -103,7 +104,7 @@ static int ufshcd_clear_keyslot(struct ufs_hba *hba, int slot)
 	 */
 	union ufs_crypto_cfg_entry cfg = {};
 
-	return ufshcd_program_key(hba, &cfg, slot);
+	return ufshcd_program_key(hba, NULL, &cfg, slot);
 }
 
 static int ufshcd_crypto_keyslot_evict(struct blk_crypto_profile *profile,
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 8d6fd4c3324f..a04aafad4f48 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -103,6 +103,7 @@ static inline int ufs_qcom_ice_suspend(struct ufs_qcom_host *host)
 }
 
 static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
+				    const struct blk_crypto_key *bkey,
 				    const union ufs_crypto_cfg_entry *cfg,
 				    int slot)
 {
@@ -110,6 +111,7 @@ static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
 	union ufs_crypto_cap_entry cap;
 	bool config_enable =
 		cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE;
+	u8 ice_key_size;
 
 	/* Only AES-256-XTS has been tested so far. */
 	cap = hba->crypto_cap_array[cfg->crypto_cap_idx];
@@ -117,11 +119,11 @@ static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
 	    cap.key_size != UFS_CRYPTO_KEY_SIZE_256)
 		return -EINVAL;
 
+	ice_key_size = QCOM_ICE_CRYPTO_KEY_SIZE_256;
 	if (config_enable)
 		return qcom_ice_program_key(host->ice,
 					    QCOM_ICE_CRYPTO_ALG_AES_XTS,
-					    QCOM_ICE_CRYPTO_KEY_SIZE_256,
-					    cfg->crypto_key,
+					    ice_key_size, bkey,
 					    cfg->data_unit_size, slot);
 	else
 		return qcom_ice_evict_key(host->ice, slot);
diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
index 5870a94599a2..9dd835dba2a7 100644
--- a/include/soc/qcom/ice.h
+++ b/include/soc/qcom/ice.h
@@ -7,6 +7,7 @@
 #define __QCOM_ICE_H__
 
 #include <linux/types.h>
+#include <linux/blk-crypto.h>
 
 struct qcom_ice;
 
@@ -30,8 +31,8 @@ int qcom_ice_resume(struct qcom_ice *ice);
 int qcom_ice_suspend(struct qcom_ice *ice);
 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);
+			 const struct blk_crypto_key *bkey,
+			 u8 data_unit_size, int slot);
 int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
 struct qcom_ice *of_qcom_ice_get(struct device *dev);
 #endif /* __QCOM_ICE_H__ */
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index 6dc11fa0ebb1..ef5995584bc3 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -341,6 +341,7 @@ struct ufs_hba_variant_ops {
 				struct devfreq_dev_profile *profile,
 				struct devfreq_simple_ondemand_data *data);
 	int	(*program_key)(struct ufs_hba *hba,
+			       const struct blk_crypto_key *bkey,
 			       const union ufs_crypto_cfg_entry *cfg, int slot);
 	void	(*event_notify)(struct ufs_hba *hba,
 				enum ufs_event_type evt, void *data);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 02/10] qcom_scm: scm call for deriving a software secret
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
  2023-07-19 17:04 ` [PATCH v2 01/10] ice, ufs, mmc: use blk_crypto_key for program_key Gaurav Kashyap
@ 2023-07-19 17:04 ` Gaurav Kashyap
  2023-07-22  3:50   ` Bjorn Andersson
  2023-07-19 17:04 ` [PATCH v2 03/10] soc: qcom: ice: add hwkm support in ice Gaurav Kashyap
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

Inline storage encryption requires deriving a sw secret from
the hardware wrapped keys. For non-wrapped keys, this can be
directly done as keys are in the clear.

However, when keys are hardware wrapped, it can be unwrapped
by HWKM (Hardware Key Manager) which is accessible only from Qualcomm
Trustzone. Hence, it also makes sense that the software secret is also
derived there and returned to the linux kernel . This can be invoked by
using the crypto profile APIs provided by the block layer.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/firmware/qcom_scm.c            | 70 ++++++++++++++++++++++++++
 drivers/firmware/qcom_scm.h            |  1 +
 include/linux/firmware/qcom/qcom_scm.h |  3 ++
 3 files changed, 74 insertions(+)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index fde33acd46b7..51062d5c7f7b 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -1140,6 +1140,76 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
 }
 EXPORT_SYMBOL(qcom_scm_ice_set_key);
 
+/**
+ * qcom_scm_derive_sw_secret() - Derive SW secret from wrapped key
+ * @wrapped_key: the wrapped key used for inline encryption
+ * @wrapped_key_size: size of the wrapped key
+ * @sw_secret: the secret to be derived which is exactly the secret size
+ * @secret_size: size of the secret
+ *
+ * Derive a SW secret from a HW Wrapped key for non HW key operations.
+ * For wrapped keys, the key needs to be unwrapped, in order to derive a
+ * SW secret, which can be done only by the secure EE.
+ *
+ * For more information on sw secret, please refer to "Hardware-wrapped keys"
+ * section of Documentation/block/inline-encryption.rst.
+ *
+ * Return: 0 on success; -errno on failure.
+ */
+int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size,
+			      u8 *sw_secret, u32 secret_size)
+{
+	struct qcom_scm_desc desc = {
+		.svc = QCOM_SCM_SVC_ES,
+		.cmd =  QCOM_SCM_ES_DERIVE_SW_SECRET,
+		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW,
+					 QCOM_SCM_VAL, QCOM_SCM_RW,
+					 QCOM_SCM_VAL),
+		.args[1] = wrapped_key_size,
+		.args[3] = secret_size,
+		.owner = ARM_SMCCC_OWNER_SIP,
+	};
+
+	void *keybuf, *secretbuf;
+	dma_addr_t key_phys, secret_phys;
+	int ret;
+
+	/*
+	 * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly
+	 * get a physical address, while guaranteeing that we can zeroize the
+	 * key material later using memzero_explicit().
+	 *
+	 */
+	keybuf = dma_alloc_coherent(__scm->dev, wrapped_key_size, &key_phys,
+				    GFP_KERNEL);
+	if (!keybuf)
+		return -ENOMEM;
+	secretbuf = dma_alloc_coherent(__scm->dev, secret_size, &secret_phys,
+				    GFP_KERNEL);
+	if (!secretbuf) {
+		ret = -ENOMEM;
+		goto bail_keybuf;
+	}
+
+	memcpy(keybuf, wrapped_key, wrapped_key_size);
+	desc.args[0] = key_phys;
+	desc.args[2] = secret_phys;
+
+	ret = qcom_scm_call(__scm->dev, &desc, NULL);
+	if (!ret)
+		memcpy(sw_secret, secretbuf, secret_size);
+
+	memzero_explicit(secretbuf, secret_size);
+	dma_free_coherent(__scm->dev, secret_size, secretbuf, secret_phys);
+
+bail_keybuf:
+	memzero_explicit(keybuf, wrapped_key_size);
+	dma_free_coherent(__scm->dev, wrapped_key_size, keybuf, key_phys);
+
+	return ret;
+}
+EXPORT_SYMBOL(qcom_scm_derive_sw_secret);
+
 /**
  * qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
  *
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index e6e512bd57d1..c145cdc71ff8 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -119,6 +119,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
 #define QCOM_SCM_SVC_ES			0x10	/* Enterprise Security */
 #define QCOM_SCM_ES_INVALIDATE_ICE_KEY	0x03
 #define QCOM_SCM_ES_CONFIG_SET_ICE_KEY	0x04
+#define QCOM_SCM_ES_DERIVE_SW_SECRET	0x07
 
 #define QCOM_SCM_SVC_HDCP		0x11
 #define QCOM_SCM_HDCP_INVOKE		0x01
diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h
index 250ea4efb7cb..20f5d0b7dfd4 100644
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -109,6 +109,9 @@ extern int qcom_scm_ice_invalidate_key(u32 index);
 extern int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
 				enum qcom_scm_ice_cipher cipher,
 				u32 data_unit_size);
+extern int qcom_scm_derive_sw_secret(const u8 *wrapped_key,
+				     u32 wrapped_key_size, u8 *sw_secret,
+				     u32 secret_size);
 
 extern bool qcom_scm_hdcp_available(void);
 extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 03/10] soc: qcom: ice: add hwkm support in ice
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
  2023-07-19 17:04 ` [PATCH v2 01/10] ice, ufs, mmc: use blk_crypto_key for program_key Gaurav Kashyap
  2023-07-19 17:04 ` [PATCH v2 02/10] qcom_scm: scm call for deriving a software secret Gaurav Kashyap
@ 2023-07-19 17:04 ` Gaurav Kashyap
  2023-08-31  8:39   ` Neil Armstrong
  2023-07-19 17:04 ` [PATCH v2 04/10] soc: qcom: ice: support for hardware wrapped keys Gaurav Kashyap
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

Qualcomm's ICE (Inline Crypto Engine) contains a proprietary
key management hardware called Hardware Key Manager (HWKM).
This patch integrates HWKM support in ICE when it is
available. HWKM primarily provides hardware wrapped key support
where the ICE (storage) keys are not available in software and
protected in hardware.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/soc/qcom/ice.c | 112 ++++++++++++++++++++++++++++++++++++++++-
 include/soc/qcom/ice.h |   1 +
 2 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index d19f674bb1b6..242306d13049 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -24,6 +24,18 @@
 #define QCOM_ICE_REG_FUSE_SETTING		0x0010
 #define QCOM_ICE_REG_BIST_STATUS		0x0070
 #define QCOM_ICE_REG_ADVANCED_CONTROL		0x1000
+#define QCOM_ICE_REG_CONTROL			0x0
+/* QCOM ICE HWKM registers */
+#define QCOM_ICE_REG_HWKM_TZ_KM_CTL		0x1000
+#define QCOM_ICE_REG_HWKM_TZ_KM_STATUS		0x1004
+#define QCOM_ICE_REG_HWKM_BANK0_BBAC_0		0x5000
+#define QCOM_ICE_REG_HWKM_BANK0_BBAC_1		0x5004
+#define QCOM_ICE_REG_HWKM_BANK0_BBAC_2		0x5008
+#define QCOM_ICE_REG_HWKM_BANK0_BBAC_3		0x500C
+#define QCOM_ICE_REG_HWKM_BANK0_BBAC_4		0x5010
+
+#define QCOM_ICE_HWKM_BIST_DONE_V1_VAL		0x11
+#define QCOM_ICE_HWKM_BIST_DONE_V2_VAL		0x287
 
 /* BIST ("built-in self-test") status flags */
 #define QCOM_ICE_BIST_STATUS_MASK		GENMASK(31, 28)
@@ -32,6 +44,9 @@
 #define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK	0x2
 #define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK	0x4
 
+#define QCOM_ICE_HWKM_REG_OFFSET	0x8000
+#define HWKM_OFFSET(reg)		(reg + QCOM_ICE_HWKM_REG_OFFSET)
+
 #define qcom_ice_writel(engine, val, reg)	\
 	writel((val), (engine)->base + (reg))
 
@@ -44,6 +59,7 @@ struct qcom_ice {
 	struct device_link *link;
 
 	struct clk *core_clk;
+	u8 hwkm_version;
 };
 
 static bool qcom_ice_check_supported(struct qcom_ice *ice)
@@ -61,8 +77,20 @@ static bool qcom_ice_check_supported(struct qcom_ice *ice)
 		return false;
 	}
 
+	if ((major >= 4) || ((major == 3) && (minor == 2) && (step >= 1)))
+		ice->hwkm_version = 2;
+	else if ((major == 3) && (minor == 2))
+		ice->hwkm_version = 1;
+	else
+		ice->hwkm_version = 0;
+
 	dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n",
 		 major, minor, step);
+	if (!ice->hwkm_version)
+		dev_info(dev, "QC ICE HWKM (Hardware Key Manager) not supported");
+	else
+		dev_info(dev, "QC ICE HWKM (Hardware Key Manager) version = %d",
+			 ice->hwkm_version);
 
 	/* If fuses are blown, ICE might not work in the standard way. */
 	regval = qcom_ice_readl(ice, QCOM_ICE_REG_FUSE_SETTING);
@@ -111,10 +139,14 @@ static void qcom_ice_optimization_enable(struct qcom_ice *ice)
  * fails, so we needn't do it in software too, and (c) properly testing
  * storage encryption requires testing the full storage stack anyway,
  * and not relying on hardware-level self-tests.
+ *
+ * However, we still care about if HWKM BIST failed (when supported) as
+ * important functionality would fail later, so disable hwkm on failure.
  */
 static int qcom_ice_wait_bist_status(struct qcom_ice *ice)
 {
 	u32 regval;
+	u32 bist_done_val;
 	int err;
 
 	err = readl_poll_timeout(ice->base + QCOM_ICE_REG_BIST_STATUS,
@@ -123,15 +155,87 @@ static int qcom_ice_wait_bist_status(struct qcom_ice *ice)
 	if (err)
 		dev_err(ice->dev, "Timed out waiting for ICE self-test to complete\n");
 
+	if (ice->hwkm_version) {
+		bist_done_val = (ice->hwkm_version == 1) ?
+				 QCOM_ICE_HWKM_BIST_DONE_V1_VAL :
+				 QCOM_ICE_HWKM_BIST_DONE_V2_VAL;
+		if (qcom_ice_readl(ice,
+				   HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_STATUS)) !=
+				   bist_done_val) {
+			dev_warn(ice->dev, "HWKM BIST error\n");
+			ice->hwkm_version = 0;
+		}
+	}
 	return err;
 }
 
+static void qcom_ice_enable_standard_mode(struct qcom_ice *ice)
+{
+	u32 val = 0;
+
+	if (!ice->hwkm_version)
+		return;
+
+	/*
+         * When ICE is in standard (hwkm) mode, it supports HW wrapped
+         * keys, and when it is in legacy mode, it only supports standard
+         * (non HW wrapped) keys.
+         *
+	 * Put ICE in standard mode, ICE defaults to legacy mode.
+	 * Legacy mode - ICE HWKM slave not supported.
+	 * Standard mode - ICE HWKM slave supported.
+	 *
+	 * Depending on the version of HWKM, it is controlled by different
+	 * registers in ICE.
+	 */
+	if (ice->hwkm_version >= 2) {
+		val = qcom_ice_readl(ice, QCOM_ICE_REG_CONTROL);
+		val = val & 0xFFFFFFFE;
+		qcom_ice_writel(ice, val, QCOM_ICE_REG_CONTROL);
+	} else {
+		qcom_ice_writel(ice, 0x7,
+				HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_CTL));
+	}
+}
+
+static void qcom_ice_hwkm_init(struct qcom_ice *ice)
+{
+	if (!ice->hwkm_version)
+		return;
+
+	/*
+	 * Give register bank of the HWKM slave access to read and modify
+	 * the keyslots in ICE HWKM slave. Without this, trustzone will not
+	 * be able to program keys into ICE.
+	 */
+	qcom_ice_writel(ice, 0xFFFFFFFF,
+			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_0));
+	qcom_ice_writel(ice, 0xFFFFFFFF,
+			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_1));
+	qcom_ice_writel(ice, 0xFFFFFFFF,
+			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_2));
+	qcom_ice_writel(ice, 0xFFFFFFFF,
+			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_3));
+	qcom_ice_writel(ice, 0xFFFFFFFF,
+			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_4));
+}
+
 int qcom_ice_enable(struct qcom_ice *ice)
 {
+	int err;
+
 	qcom_ice_low_power_mode_enable(ice);
 	qcom_ice_optimization_enable(ice);
 
-	return qcom_ice_wait_bist_status(ice);
+	qcom_ice_enable_standard_mode(ice);
+
+	err = qcom_ice_wait_bist_status(ice);
+	if (err)
+		return err;
+
+	qcom_ice_hwkm_init(ice);
+
+	return err;
 }
 EXPORT_SYMBOL_GPL(qcom_ice_enable);
 
@@ -203,6 +307,12 @@ int qcom_ice_evict_key(struct qcom_ice *ice, int slot)
 }
 EXPORT_SYMBOL_GPL(qcom_ice_evict_key);
 
+bool qcom_ice_hwkm_supported(struct qcom_ice *ice)
+{
+	return (ice->hwkm_version > 0);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_hwkm_supported);
+
 static struct qcom_ice *qcom_ice_create(struct device *dev,
 					void __iomem *base)
 {
diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
index 9dd835dba2a7..1f52e82e3e1c 100644
--- a/include/soc/qcom/ice.h
+++ b/include/soc/qcom/ice.h
@@ -34,5 +34,6 @@ int qcom_ice_program_key(struct qcom_ice *ice,
 			 const struct blk_crypto_key *bkey,
 			 u8 data_unit_size, int slot);
 int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
+bool qcom_ice_hwkm_supported(struct qcom_ice *ice);
 struct qcom_ice *of_qcom_ice_get(struct device *dev);
 #endif /* __QCOM_ICE_H__ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 04/10] soc: qcom: ice: support for hardware wrapped keys
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (2 preceding siblings ...)
  2023-07-19 17:04 ` [PATCH v2 03/10] soc: qcom: ice: add hwkm support in ice Gaurav Kashyap
@ 2023-07-19 17:04 ` Gaurav Kashyap
  2023-08-31  9:10   ` Neil Armstrong
  2023-07-19 17:04 ` [PATCH v2 05/10] ufs: core: support wrapped keys in ufs core Gaurav Kashyap
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

Now that HWKM support is added to ICE, extend the ICE
driver to support hardware wrapped keys programming coming
in from the storage controllers (ufs and emmc). The patches that follow
will add ufs and emmc support.

Derive software secret support is also added by forwarding the
call the corresponding scm api.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/soc/qcom/ice.c | 121 +++++++++++++++++++++++++++++++++++++----
 include/soc/qcom/ice.h |   4 ++
 2 files changed, 114 insertions(+), 11 deletions(-)

diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index 242306d13049..33f67fcfa1bc 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -25,6 +25,8 @@
 #define QCOM_ICE_REG_BIST_STATUS		0x0070
 #define QCOM_ICE_REG_ADVANCED_CONTROL		0x1000
 #define QCOM_ICE_REG_CONTROL			0x0
+#define QCOM_ICE_LUT_KEYS_CRYPTOCFG_R16		0x4040
+
 /* QCOM ICE HWKM registers */
 #define QCOM_ICE_REG_HWKM_TZ_KM_CTL		0x1000
 #define QCOM_ICE_REG_HWKM_TZ_KM_STATUS		0x1004
@@ -34,6 +36,7 @@
 #define QCOM_ICE_REG_HWKM_BANK0_BBAC_3		0x500C
 #define QCOM_ICE_REG_HWKM_BANK0_BBAC_4		0x5010
 
+/* QCOM ICE HWKM BIST vals */
 #define QCOM_ICE_HWKM_BIST_DONE_V1_VAL		0x11
 #define QCOM_ICE_HWKM_BIST_DONE_V2_VAL		0x287
 
@@ -44,6 +47,8 @@
 #define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK	0x2
 #define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK	0x4
 
+#define QCOM_ICE_LUT_KEYS_CRYPTOCFG_OFFSET	0x80
+
 #define QCOM_ICE_HWKM_REG_OFFSET	0x8000
 #define HWKM_OFFSET(reg)		(reg + QCOM_ICE_HWKM_REG_OFFSET)
 
@@ -60,6 +65,17 @@ struct qcom_ice {
 
 	struct clk *core_clk;
 	u8 hwkm_version;
+	bool hwkm_init_complete;
+};
+
+union crypto_cfg {
+	__le32 regval;
+	struct {
+		u8 dusize;
+		u8 capidx;
+		u8 reserved;
+		u8 cfge;
+	};
 };
 
 static bool qcom_ice_check_supported(struct qcom_ice *ice)
@@ -218,6 +234,8 @@ static void qcom_ice_hwkm_init(struct qcom_ice *ice)
 			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_3));
 	qcom_ice_writel(ice, 0xFFFFFFFF,
 			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_4));
+
+	ice->hwkm_init_complete = true;
 }
 
 int qcom_ice_enable(struct qcom_ice *ice)
@@ -263,6 +281,52 @@ int qcom_ice_suspend(struct qcom_ice *ice)
 }
 EXPORT_SYMBOL_GPL(qcom_ice_suspend);
 
+/*
+ * HW dictates the internal mapping between the ICE and HWKM slots,
+ * which are different for different versions, make the translation
+ * here.
+*/
+static int translate_hwkm_slot(struct qcom_ice *ice, int slot)
+{
+	return (ice->hwkm_version == 1) ?
+	       (10 + slot * 2) : (slot * 2);
+}
+
+static int qcom_ice_program_wrapped_key(struct qcom_ice *ice,
+					const struct blk_crypto_key *key,
+					u8 data_unit_size, int slot)
+{
+	int hwkm_slot;
+	int err;
+	union crypto_cfg cfg;
+
+	hwkm_slot = translate_hwkm_slot(ice, slot);
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.dusize = data_unit_size;
+	cfg.capidx = QCOM_SCM_ICE_CIPHER_AES_256_XTS;
+	cfg.cfge = 0x80;
+
+	/* Clear CFGE */
+	qcom_ice_writel(ice, 0x0, QCOM_ICE_LUT_KEYS_CRYPTOCFG_R16 +
+				  QCOM_ICE_LUT_KEYS_CRYPTOCFG_OFFSET * slot);
+
+	/* Call trustzone to program the wrapped key using hwkm */
+	err = qcom_scm_ice_set_key(hwkm_slot, key->raw, key->size,
+				   QCOM_SCM_ICE_CIPHER_AES_256_XTS, data_unit_size);
+	if (err) {
+		pr_err("%s:SCM call Error: 0x%x slot %d\n", __func__, err,
+		       slot);
+		return err;
+	}
+
+	/* Enable CFGE after programming key */
+	qcom_ice_writel(ice, cfg.regval, QCOM_ICE_LUT_KEYS_CRYPTOCFG_R16 +
+					 QCOM_ICE_LUT_KEYS_CRYPTOCFG_OFFSET * slot);
+
+	return err;
+}
+
 int qcom_ice_program_key(struct qcom_ice *ice,
 			 u8 algorithm_id, u8 key_size,
 			 const struct blk_crypto_key *bkey,
@@ -278,24 +342,36 @@ int qcom_ice_program_key(struct qcom_ice *ice,
 
 	/* 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) {
+	    key_size != QCOM_ICE_CRYPTO_KEY_SIZE_256 ||
+	    key_size != QCOM_ICE_CRYPTO_KEY_SIZE_WRAPPED) {
 		dev_err_ratelimited(dev,
 				    "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
 				    algorithm_id, key_size);
 		return -EINVAL;
 	}
 
-	memcpy(key.bytes, bkey->raw, AES_256_XTS_KEY_SIZE);
-
-	/* 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]);
+	if (bkey->crypto_cfg.key_type == BLK_CRYPTO_KEY_TYPE_HW_WRAPPED) {
+		if (!ice->hwkm_version)
+			return -EINVAL;
+		err = qcom_ice_program_wrapped_key(ice, bkey, slot,
+						   data_unit_size);
+	} else {
+		if (bkey->size != QCOM_ICE_CRYPTO_KEY_SIZE_256)
+			dev_err_ratelimited(dev,
+				    "Incorrect key size; bkey->size=%d\n",
+				    algorithm_id);
+		return -EINVAL;
+		memcpy(key.bytes, bkey->raw, AES_256_XTS_KEY_SIZE);
 
-	err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
-				   QCOM_SCM_ICE_CIPHER_AES_256_XTS,
-				   data_unit_size);
+		/* 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]);
 
-	memzero_explicit(&key, sizeof(key));
+		err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
+					   QCOM_SCM_ICE_CIPHER_AES_256_XTS,
+					   data_unit_size);
+		memzero_explicit(&key, sizeof(key));
+	}
 
 	return err;
 }
@@ -303,7 +379,21 @@ EXPORT_SYMBOL_GPL(qcom_ice_program_key);
 
 int qcom_ice_evict_key(struct qcom_ice *ice, int slot)
 {
-	return qcom_scm_ice_invalidate_key(slot);
+	int hwkm_slot = slot;
+
+	if (ice->hwkm_version) {
+		hwkm_slot = translate_hwkm_slot(ice, slot);
+	/*
+	 * Ignore calls to evict key when HWKM is supported and hwkm init
+	 * is not yet done. This is to avoid the clearing all slots call
+	 * during a storage reset when ICE is still in legacy mode. HWKM slave
+	 * in ICE takes care of zeroing out the keytable on reset.
+	 */
+		if (!ice->hwkm_init_complete)
+			return 0;
+	}
+
+	return qcom_scm_ice_invalidate_key(hwkm_slot);
 }
 EXPORT_SYMBOL_GPL(qcom_ice_evict_key);
 
@@ -313,6 +403,15 @@ bool qcom_ice_hwkm_supported(struct qcom_ice *ice)
 }
 EXPORT_SYMBOL_GPL(qcom_ice_hwkm_supported);
 
+int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wrapped_key[],
+			      unsigned int wrapped_key_size,
+			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
+{
+	return qcom_scm_derive_sw_secret(wrapped_key, wrapped_key_size,
+					 sw_secret, BLK_CRYPTO_SW_SECRET_SIZE);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret);
+
 static struct qcom_ice *qcom_ice_create(struct device *dev,
 					void __iomem *base)
 {
diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
index 1f52e82e3e1c..22ab8d1a56de 100644
--- a/include/soc/qcom/ice.h
+++ b/include/soc/qcom/ice.h
@@ -17,6 +17,7 @@ enum qcom_ice_crypto_key_size {
 	QCOM_ICE_CRYPTO_KEY_SIZE_192		= 0x2,
 	QCOM_ICE_CRYPTO_KEY_SIZE_256		= 0x3,
 	QCOM_ICE_CRYPTO_KEY_SIZE_512		= 0x4,
+	QCOM_ICE_CRYPTO_KEY_SIZE_WRAPPED	= 0x5,
 };
 
 enum qcom_ice_crypto_alg {
@@ -35,5 +36,8 @@ int qcom_ice_program_key(struct qcom_ice *ice,
 			 u8 data_unit_size, int slot);
 int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
 bool qcom_ice_hwkm_supported(struct qcom_ice *ice);
+int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wrapped_key[],
+			      unsigned int wrapped_key_size,
+			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
 struct qcom_ice *of_qcom_ice_get(struct device *dev);
 #endif /* __QCOM_ICE_H__ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 05/10] ufs: core: support wrapped keys in ufs core
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (3 preceding siblings ...)
  2023-07-19 17:04 ` [PATCH v2 04/10] soc: qcom: ice: support for hardware wrapped keys Gaurav Kashyap
@ 2023-07-19 17:04 ` Gaurav Kashyap
  2023-07-19 17:04 ` [PATCH v2 06/10] ufs: host: wrapped keys support in ufs qcom Gaurav Kashyap
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

1. Add a new quirk in UFS when wrapped keys are supported. Since
   wrapped keys are not part of the UFS spec, treat it as a
   supported quirk.
2. Add derive_sw_secret crypto profile op implementation in ufshcd
   crypto.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/ufs/core/ufshcd-crypto.c | 40 +++++++++++++++++++++++++-------
 include/ufs/ufshcd.h             | 10 ++++++++
 2 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c
index 34537cbac622..2d8f43f2df1d 100644
--- a/drivers/ufs/core/ufshcd-crypto.c
+++ b/drivers/ufs/core/ufshcd-crypto.c
@@ -81,13 +81,15 @@ static int ufshcd_crypto_keyslot_program(struct blk_crypto_profile *profile,
 	cfg.crypto_cap_idx = cap_idx;
 	cfg.config_enable = UFS_CRYPTO_CONFIGURATION_ENABLE;
 
-	if (ccap_array[cap_idx].algorithm_id == UFS_CRYPTO_ALG_AES_XTS) {
-		/* In XTS mode, the blk_crypto_key's size is already doubled */
-		memcpy(cfg.crypto_key, key->raw, key->size/2);
-		memcpy(cfg.crypto_key + UFS_CRYPTO_KEY_MAX_SIZE/2,
-		       key->raw + key->size/2, key->size/2);
-	} else {
-		memcpy(cfg.crypto_key, key->raw, key->size);
+	if (key->crypto_cfg.key_type != BLK_CRYPTO_KEY_TYPE_HW_WRAPPED) {
+		if (ccap_array[cap_idx].algorithm_id == UFS_CRYPTO_ALG_AES_XTS) {
+			/* In XTS mode, the blk_crypto_key's size is already doubled */
+			memcpy(cfg.crypto_key, key->raw, key->size/2);
+			memcpy(cfg.crypto_key + UFS_CRYPTO_KEY_MAX_SIZE/2,
+			       key->raw + key->size/2, key->size/2);
+		} else {
+			memcpy(cfg.crypto_key, key->raw, key->size);
+		}
 	}
 
 	err = ufshcd_program_key(hba, key, &cfg, slot);
@@ -127,9 +129,25 @@ bool ufshcd_crypto_enable(struct ufs_hba *hba)
 	return true;
 }
 
+
+static int ufshcd_crypto_derive_sw_secret(struct blk_crypto_profile *profile,
+				const u8 wrapped_key[], size_t wrapped_key_size,
+				u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
+{
+	struct ufs_hba *hba =
+		container_of(profile, struct ufs_hba, crypto_profile);
+
+	if (hba->vops && hba->vops->derive_sw_secret)
+		return  hba->vops->derive_sw_secret(hba, wrapped_key,
+						 wrapped_key_size, sw_secret);
+
+	return -EOPNOTSUPP;
+}
+
 static const struct blk_crypto_ll_ops ufshcd_crypto_ops = {
 	.keyslot_program	= ufshcd_crypto_keyslot_program,
 	.keyslot_evict		= ufshcd_crypto_keyslot_evict,
+	.derive_sw_secret	= ufshcd_crypto_derive_sw_secret,
 };
 
 static enum blk_crypto_mode_num
@@ -191,7 +209,13 @@ int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba)
 	hba->crypto_profile.ll_ops = ufshcd_crypto_ops;
 	/* UFS only supports 8 bytes for any DUN */
 	hba->crypto_profile.max_dun_bytes_supported = 8;
-	hba->crypto_profile.key_types_supported = BLK_CRYPTO_KEY_TYPE_STANDARD;
+	if (hba->quirks & UFSHCD_QUIRK_USES_WRAPPED_CRYPTO_KEYS)
+		hba->crypto_profile.key_types_supported =
+				BLK_CRYPTO_KEY_TYPE_HW_WRAPPED;
+	else
+		hba->crypto_profile.key_types_supported =
+				BLK_CRYPTO_KEY_TYPE_STANDARD;
+
 	hba->crypto_profile.dev = hba->dev;
 
 	/*
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index ef5995584bc3..cef8e619fe5d 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -299,6 +299,7 @@ struct ufs_pwr_mode_info {
  * @device_reset: called to issue a reset pulse on the UFS device
  * @config_scaling_param: called to configure clock scaling parameters
  * @program_key: program or evict an inline encryption key
+ * @derive_sw_secret: derive sw secret from a wrapped key
  * @event_notify: called to notify important events
  * @reinit_notify: called to notify reinit of UFSHCD during max gear switch
  * @mcq_config_resource: called to configure MCQ platform resources
@@ -343,6 +344,9 @@ struct ufs_hba_variant_ops {
 	int	(*program_key)(struct ufs_hba *hba,
 			       const struct blk_crypto_key *bkey,
 			       const union ufs_crypto_cfg_entry *cfg, int slot);
+	int	(*derive_sw_secret)(struct ufs_hba *hba, const u8 wrapped_key[],
+				    unsigned int wrapped_key_size,
+				    u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
 	void	(*event_notify)(struct ufs_hba *hba,
 				enum ufs_event_type evt, void *data);
 	void	(*reinit_notify)(struct ufs_hba *);
@@ -624,6 +628,12 @@ enum ufshcd_quirks {
 	 * thus need this quirk to skip related flow.
 	 */
 	UFSHCD_QUIRK_MCQ_BROKEN_RTC			= 1 << 21,
+
+	/*
+	 * This quirk indicates that UFS will be using HW wrapped keys
+	 * when using inline encryption.
+	 */
+	UFSHCD_QUIRK_USES_WRAPPED_CRYPTO_KEYS		= 1 << 22,
 };
 
 enum ufshcd_caps {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 06/10] ufs: host: wrapped keys support in ufs qcom
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (4 preceding siblings ...)
  2023-07-19 17:04 ` [PATCH v2 05/10] ufs: core: support wrapped keys in ufs core Gaurav Kashyap
@ 2023-07-19 17:04 ` Gaurav Kashyap
  2023-07-19 17:04 ` [PATCH v2 07/10] qcom_scm: scm call for create, prepare and import keys Gaurav Kashyap
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

1. Implement derive software secret defined in ufs core.
2. Use the wrapped keys quirk when hwkm is supported. The assumption
   here is that if Qualcomm ICE supports HWKM, then all ICE keys
   will be treated as hardware wrapped keys.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/ufs/host/ufs-qcom.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index a04aafad4f48..9a7c5d46dbf4 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -82,6 +82,8 @@ static int ufs_qcom_ice_init(struct ufs_qcom_host *host)
 
 	host->ice = ice;
 	hba->caps |= UFSHCD_CAP_CRYPTO;
+	if (qcom_ice_hwkm_supported(host->ice))
+		hba->quirks |= UFSHCD_QUIRK_USES_WRAPPED_CRYPTO_KEYS;
 
 	return 0;
 }
@@ -119,7 +121,11 @@ static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
 	    cap.key_size != UFS_CRYPTO_KEY_SIZE_256)
 		return -EINVAL;
 
-	ice_key_size = QCOM_ICE_CRYPTO_KEY_SIZE_256;
+	if (bkey->crypto_cfg.key_type == BLK_CRYPTO_KEY_TYPE_HW_WRAPPED)
+		ice_key_size = QCOM_ICE_CRYPTO_KEY_SIZE_WRAPPED;
+	else
+		ice_key_size = QCOM_ICE_CRYPTO_KEY_SIZE_256;
+
 	if (config_enable)
 		return qcom_ice_program_key(host->ice,
 					    QCOM_ICE_CRYPTO_ALG_AES_XTS,
@@ -129,9 +135,24 @@ static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
 		return qcom_ice_evict_key(host->ice, slot);
 }
 
+/*
+ * Derive a SW secret from the wrapped key. The key is unwrapped in Trustzone
+ * and a SW key is then derived from it.
+ */
+int ufs_qcom_ice_derive_sw_secret(struct ufs_hba *hba, const u8 wrapped_key[],
+				  unsigned int wrapped_key_size,
+				  u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+	return qcom_ice_derive_sw_secret(host->ice, wrapped_key,
+					wrapped_key_size, sw_secret);
+}
+
 #else
 
 #define ufs_qcom_ice_program_key NULL
+#define ufs_qcom_ice_derive_sw_secret NULL
 
 static inline void ufs_qcom_ice_enable(struct ufs_qcom_host *host)
 {
@@ -1747,6 +1768,7 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
 	.device_reset		= ufs_qcom_device_reset,
 	.config_scaling_param = ufs_qcom_config_scaling_param,
 	.program_key		= ufs_qcom_ice_program_key,
+	.derive_sw_secret	= ufs_qcom_ice_derive_sw_secret,
 	.reinit_notify		= ufs_qcom_reinit_notify,
 	.mcq_config_resource	= ufs_qcom_mcq_config_resource,
 	.get_hba_mac		= ufs_qcom_get_hba_mac,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 07/10] qcom_scm: scm call for create, prepare and import keys
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (5 preceding siblings ...)
  2023-07-19 17:04 ` [PATCH v2 06/10] ufs: host: wrapped keys support in ufs qcom Gaurav Kashyap
@ 2023-07-19 17:04 ` Gaurav Kashyap
  2023-07-19 17:48   ` Trilok Soni
  2023-07-22  3:40   ` Bjorn Andersson
  2023-07-19 17:04 ` [PATCH v2 08/10] ufs: core: add support for generate, import and prepare keys Gaurav Kashyap
                   ` (5 subsequent siblings)
  12 siblings, 2 replies; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

Storage encryption has two IOCTLs for creating, importing
and preparing keys for encryption. For wrapped keys, these
IOCTLs need to interface with the secure environment, which
require these SCM calls.

generate_key: This is used to generate and return a longterm
              wrapped key. Trustzone achieves this by generating
	      a key and then wrapping it using hwkm, returning
	      a wrapped keyblob.
import_key:   The functionality is similar to generate, but here,
              a raw key is imported into hwkm and a longterm wrapped
	      keyblob is returned.
prepare_key:  The longterm wrapped key from import or generate
              is made further secure by rewrapping it with a per-boot
	      ephemeral wrapped key before installing it to the linux
	      kernel for programming to ICE.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/firmware/qcom_scm.c            | 222 +++++++++++++++++++++++++
 drivers/firmware/qcom_scm.h            |   3 +
 include/linux/firmware/qcom/qcom_scm.h |  10 ++
 3 files changed, 235 insertions(+)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 51062d5c7f7b..44dd1857747b 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -1210,6 +1210,228 @@ int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size,
 }
 EXPORT_SYMBOL(qcom_scm_derive_sw_secret);
 
+/**
+ * qcom_scm_generate_ice_key() - Generate a wrapped key for encryption.
+ * @longterm_wrapped_key: the wrapped key returned after key generation
+ * @longterm_wrapped_key_size: size of the wrapped key to be returned.
+ *
+ * Qualcomm wrapped keys need to be generated in a trusted environment.
+ * A generate key  IOCTL call is used to achieve this. These are longterm
+ * in nature as they need to be generated and wrapped only once per
+ * requirement.
+ *
+ * This SCM calls adds support for the generate key IOCTL to interface
+ * with the secure environment to generate and return a wrapped key..
+ *
+ * Return: 0 on success; -errno on failure.
+ */
+int qcom_scm_generate_ice_key(u8 *longterm_wrapped_key,
+			    u32 longterm_wrapped_key_size)
+{
+	struct qcom_scm_desc desc = {
+		.svc = QCOM_SCM_SVC_ES,
+		.cmd =  QCOM_SCM_ES_GENERATE_ICE_KEY,
+		.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW,
+					 QCOM_SCM_VAL),
+		.args[1] = longterm_wrapped_key_size,
+		.owner = ARM_SMCCC_OWNER_SIP,
+	};
+
+	void *longterm_wrapped_keybuf;
+	dma_addr_t longterm_wrapped_key_phys;
+	int ret;
+
+	/*
+	 * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly
+	 * get a physical address, while guaranteeing that we can zeroize the
+	 * key material later using memzero_explicit().
+	 *
+	 */
+	longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
+				  longterm_wrapped_key_size,
+				  &longterm_wrapped_key_phys, GFP_KERNEL);
+	if (!longterm_wrapped_keybuf)
+		return -ENOMEM;
+
+	desc.args[0] = longterm_wrapped_key_phys;
+
+	ret = qcom_scm_call(__scm->dev, &desc, NULL);
+	memcpy(longterm_wrapped_key, longterm_wrapped_keybuf,
+	       longterm_wrapped_key_size);
+
+	memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size);
+	dma_free_coherent(__scm->dev, longterm_wrapped_key_size,
+			  longterm_wrapped_keybuf, longterm_wrapped_key_phys);
+
+	if (!ret)
+		return longterm_wrapped_key_size;
+
+	return ret;
+}
+EXPORT_SYMBOL(qcom_scm_generate_ice_key);
+
+/**
+ * qcom_scm_prepare_ice_key() - Get per boot ephemeral wrapped key
+ * @longterm_wrapped_key: the wrapped key
+ * @longterm_wrapped_key_size: size of the wrapped key
+ * @ephemeral_wrapped_key: ephemeral wrapped key to be returned
+ * @ephemeral_wrapped_key_size: size of the ephemeral wrapped key
+ *
+ * Qualcomm wrapped keys (longterm keys) are rewrapped with a per-boot
+ * ephemeral key for added protection. These are ephemeral in nature as
+ * they are valid only for that boot. A create key IOCTL is used to
+ * achieve this. These are the keys that are installed into the kernel
+ * to be then unwrapped and programmed into ICE.
+ *
+ * This SCM call adds support for the create key IOCTL to interface
+ * with the secure environment to rewrap the wrapped key with an
+ * ephemeral wrapping key.
+ *
+ * Return: 0 on success; -errno on failure.
+ */
+int qcom_scm_prepare_ice_key(const u8 *longterm_wrapped_key,
+			     u32 longterm_wrapped_key_size,
+			     u8 *ephemeral_wrapped_key,
+			     u32 ephemeral_wrapped_key_size)
+{
+	struct qcom_scm_desc desc = {
+		.svc = QCOM_SCM_SVC_ES,
+		.cmd =  QCOM_SCM_ES_PREPARE_ICE_KEY,
+		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO,
+					 QCOM_SCM_VAL, QCOM_SCM_RW,
+					 QCOM_SCM_VAL),
+		.args[1] = longterm_wrapped_key_size,
+		.args[3] = ephemeral_wrapped_key_size,
+		.owner = ARM_SMCCC_OWNER_SIP,
+	};
+
+	void *longterm_wrapped_keybuf, *ephemeral_wrapped_keybuf;
+	dma_addr_t longterm_wrapped_key_phys, ephemeral_wrapped_key_phys;
+	int ret;
+
+	/*
+	 * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly
+	 * get a physical address, while guaranteeing that we can zeroize the
+	 * key material later using memzero_explicit().
+	 *
+	 */
+	longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
+				  longterm_wrapped_key_size,
+				  &longterm_wrapped_key_phys, GFP_KERNEL);
+	if (!longterm_wrapped_keybuf)
+		return -ENOMEM;
+	ephemeral_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
+				   ephemeral_wrapped_key_size,
+				   &ephemeral_wrapped_key_phys, GFP_KERNEL);
+	if (!ephemeral_wrapped_keybuf) {
+		ret = -ENOMEM;
+		goto bail_keybuf;
+	}
+
+	memcpy(longterm_wrapped_keybuf, longterm_wrapped_key,
+	       longterm_wrapped_key_size);
+	desc.args[0] = longterm_wrapped_key_phys;
+	desc.args[2] = ephemeral_wrapped_key_phys;
+
+	ret = qcom_scm_call(__scm->dev, &desc, NULL);
+	if (!ret)
+		memcpy(ephemeral_wrapped_key, ephemeral_wrapped_keybuf,
+		       ephemeral_wrapped_key_size);
+
+	memzero_explicit(ephemeral_wrapped_keybuf, ephemeral_wrapped_key_size);
+	dma_free_coherent(__scm->dev, ephemeral_wrapped_key_size,
+			  ephemeral_wrapped_keybuf,
+			  ephemeral_wrapped_key_phys);
+
+bail_keybuf:
+	memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size);
+	dma_free_coherent(__scm->dev, longterm_wrapped_key_size,
+			  longterm_wrapped_keybuf, longterm_wrapped_key_phys);
+
+	if (!ret)
+		return ephemeral_wrapped_key_size;
+
+	return ret;
+}
+EXPORT_SYMBOL(qcom_scm_prepare_ice_key);
+
+/**
+ * qcom_scm_import_ice_key() - Import a wrapped key for encryption
+ * @imported_key: the raw key that is imported
+ * @imported_key_size: size of the key to be imported
+ * @longterm_wrapped_key: the wrapped key to be returned
+ * @longterm_wrapped_key_size: size of the wrapped key
+ *
+ * Conceptually, this is very similar to generate, the difference being,
+ * here we want to import a raw key and return a longterm wrapped key
+ * from it. THe same create key IOCTL is used to achieve this.
+ *
+ * This SCM call adds support for the create key IOCTL to interface with
+ * the secure environment to import a raw key and generate a longterm
+ * wrapped key.
+ *
+ * Return: 0 on success; -errno on failure.
+ */
+int qcom_scm_import_ice_key(const u8 *imported_key, u32 imported_key_size,
+			    u8 *longterm_wrapped_key,
+			    u32 longterm_wrapped_key_size)
+{
+	struct qcom_scm_desc desc = {
+		.svc = QCOM_SCM_SVC_ES,
+		.cmd =  QCOM_SCM_ES_IMPORT_ICE_KEY,
+		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO,
+					 QCOM_SCM_VAL, QCOM_SCM_RW,
+					 QCOM_SCM_VAL),
+		.args[1] = imported_key_size,
+		.args[3] = longterm_wrapped_key_size,
+		.owner = ARM_SMCCC_OWNER_SIP,
+	};
+
+	void *imported_keybuf, *longterm_wrapped_keybuf;
+	dma_addr_t imported_key_phys, longterm_wrapped_key_phys;
+	int ret;
+	/*
+	 * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly
+	 * get a physical address, while guaranteeing that we can zeroize the
+	 * key material later using memzero_explicit().
+	 *
+	 */
+	imported_keybuf = dma_alloc_coherent(__scm->dev, imported_key_size,
+			  &imported_key_phys, GFP_KERNEL);
+	if (!imported_keybuf)
+		return -ENOMEM;
+	longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
+				  longterm_wrapped_key_size,
+				  &longterm_wrapped_key_phys, GFP_KERNEL);
+	if (!longterm_wrapped_keybuf) {
+		ret = -ENOMEM;
+		goto bail_keybuf;
+	}
+
+	memcpy(imported_keybuf, imported_key, imported_key_size);
+	desc.args[0] = imported_key_phys;
+	desc.args[2] = longterm_wrapped_key_phys;
+
+	ret = qcom_scm_call(__scm->dev, &desc, NULL);
+	if (!ret)
+		memcpy(longterm_wrapped_key, longterm_wrapped_keybuf,
+		       longterm_wrapped_key_size);
+
+	memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size);
+	dma_free_coherent(__scm->dev, longterm_wrapped_key_size,
+			  longterm_wrapped_keybuf, longterm_wrapped_key_phys);
+bail_keybuf:
+	memzero_explicit(imported_keybuf, imported_key_size);
+	dma_free_coherent(__scm->dev, imported_key_size, imported_keybuf,
+			  imported_key_phys);
+
+	if (!ret)
+		return longterm_wrapped_key_size;
+
+	return ret;
+}
+EXPORT_SYMBOL(qcom_scm_import_ice_key);
+
 /**
  * qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
  *
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index c145cdc71ff8..fa6164bef54f 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -120,6 +120,9 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
 #define QCOM_SCM_ES_INVALIDATE_ICE_KEY	0x03
 #define QCOM_SCM_ES_CONFIG_SET_ICE_KEY	0x04
 #define QCOM_SCM_ES_DERIVE_SW_SECRET	0x07
+#define QCOM_SCM_ES_GENERATE_ICE_KEY	0x08
+#define QCOM_SCM_ES_PREPARE_ICE_KEY	0x09
+#define QCOM_SCM_ES_IMPORT_ICE_KEY	0xA
 
 #define QCOM_SCM_SVC_HDCP		0x11
 #define QCOM_SCM_HDCP_INVOKE		0x01
diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h
index 20f5d0b7dfd4..104666123e4d 100644
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -112,6 +112,16 @@ extern int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
 extern int qcom_scm_derive_sw_secret(const u8 *wrapped_key,
 				     u32 wrapped_key_size, u8 *sw_secret,
 				     u32 secret_size);
+extern int qcom_scm_generate_ice_key(u8 *longterm_wrapped_key,
+				     u32 longterm_wrapped_key_size);
+extern int qcom_scm_prepare_ice_key(const u8 *longterm_wrapped_key,
+				    u32 longterm_wrapped_key_size,
+				    u8 *ephemeral_wrapped_key,
+				    u32 ephemeral_wrapped_key_size);
+extern int qcom_scm_import_ice_key(const u8 *imported_key,
+				   u32 imported_key_size,
+				   u8 *longterm_wrapped_key,
+				   u32 longterm_wrapped_key_size);
 
 extern bool qcom_scm_hdcp_available(void);
 extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 08/10] ufs: core: add support for generate, import and prepare keys
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (6 preceding siblings ...)
  2023-07-19 17:04 ` [PATCH v2 07/10] qcom_scm: scm call for create, prepare and import keys Gaurav Kashyap
@ 2023-07-19 17:04 ` Gaurav Kashyap
  2023-07-19 17:04 ` [PATCH v2 09/10] soc: qcom: support for generate, import and prepare key Gaurav Kashyap
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

This patch contains two changes in UFS for wrapped keys.
1. Implements the blk_crypto_profile ops for generate, import
   and prepare key apis.
2. Defines UFS vops for generate, import and prepare keys so
   that vendors can hook into them.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/ufs/core/ufshcd-crypto.c | 45 ++++++++++++++++++++++++++++++++
 include/ufs/ufshcd.h             | 14 ++++++++++
 2 files changed, 59 insertions(+)

diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c
index 2d8f43f2df1d..33a8653a7cd6 100644
--- a/drivers/ufs/core/ufshcd-crypto.c
+++ b/drivers/ufs/core/ufshcd-crypto.c
@@ -144,10 +144,55 @@ static int ufshcd_crypto_derive_sw_secret(struct blk_crypto_profile *profile,
 	return -EOPNOTSUPP;
 }
 
+static int ufshcd_crypto_generate_key(struct blk_crypto_profile *profile,
+		u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	struct ufs_hba *hba =
+		container_of(profile, struct ufs_hba, crypto_profile);
+
+	if (hba->vops && hba->vops->generate_key)
+		return  hba->vops->generate_key(hba, longterm_wrapped_key);
+
+	return -EOPNOTSUPP;
+}
+
+static int ufshcd_crypto_prepare_key(struct blk_crypto_profile *profile,
+		const u8 *longterm_wrapped_key,
+		size_t longterm_wrapped_key_size,
+		u8 ephemerally_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	struct ufs_hba *hba =
+		container_of(profile, struct ufs_hba, crypto_profile);
+
+	if (hba->vops && hba->vops->prepare_key)
+		return  hba->vops->prepare_key(hba, longterm_wrapped_key,
+			longterm_wrapped_key_size, ephemerally_wrapped_key);
+
+	return -EOPNOTSUPP;
+}
+
+static int ufshcd_crypto_import_key(struct blk_crypto_profile *profile,
+		const u8 *imported_key,
+		size_t imported_key_size,
+		u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	struct ufs_hba *hba =
+		container_of(profile, struct ufs_hba, crypto_profile);
+
+	if (hba->vops && hba->vops->import_key)
+		return  hba->vops->import_key(hba, imported_key,
+			imported_key_size, longterm_wrapped_key);
+
+	return -EOPNOTSUPP;
+}
+
 static const struct blk_crypto_ll_ops ufshcd_crypto_ops = {
 	.keyslot_program	= ufshcd_crypto_keyslot_program,
 	.keyslot_evict		= ufshcd_crypto_keyslot_evict,
 	.derive_sw_secret	= ufshcd_crypto_derive_sw_secret,
+	.generate_key		= ufshcd_crypto_generate_key,
+	.prepare_key		= ufshcd_crypto_prepare_key,
+	.import_key		= ufshcd_crypto_import_key,
 };
 
 static enum blk_crypto_mode_num
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index cef8e619fe5d..9c4824d46a2f 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -300,6 +300,9 @@ struct ufs_pwr_mode_info {
  * @config_scaling_param: called to configure clock scaling parameters
  * @program_key: program or evict an inline encryption key
  * @derive_sw_secret: derive sw secret from a wrapped key
+ * @generate_key: generate a storage key and return longterm wrapped key
+ * @prepare_key: unwrap longterm key and return ephemeral wrapped key
+ * @import_key: import sw storage key and return longterm wrapped key
  * @event_notify: called to notify important events
  * @reinit_notify: called to notify reinit of UFSHCD during max gear switch
  * @mcq_config_resource: called to configure MCQ platform resources
@@ -347,6 +350,17 @@ struct ufs_hba_variant_ops {
 	int	(*derive_sw_secret)(struct ufs_hba *hba, const u8 wrapped_key[],
 				    unsigned int wrapped_key_size,
 				    u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
+	int	(*generate_key)(struct ufs_hba *hba, u8 longterm_wrapped_key[
+				BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
+	int	(*prepare_key)(struct ufs_hba *hba,
+			       const u8 *longterm_wrapped_key,
+			       unsigned int longterm_wrapped_key_size,
+			       u8 ephemerally_wrapped_key[
+			       BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
+	int	(*import_key)(struct ufs_hba *hba, const u8 *imported_key,
+			      unsigned int imported_key_size,
+			      u8 longterm_wrapped_key[
+			      BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
 	void	(*event_notify)(struct ufs_hba *hba,
 				enum ufs_event_type evt, void *data);
 	void	(*reinit_notify)(struct ufs_hba *);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 09/10] soc: qcom: support for generate, import and prepare key
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (7 preceding siblings ...)
  2023-07-19 17:04 ` [PATCH v2 08/10] ufs: core: add support for generate, import and prepare keys Gaurav Kashyap
@ 2023-07-19 17:04 ` Gaurav Kashyap
  2023-07-22  3:56   ` Bjorn Andersson
  2023-07-19 17:04 ` [PATCH v2 10/10] ufs: host: " Gaurav Kashyap
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

Implements the ICE apis for generate, prepare and import key
apis and hooks it up the scm calls defined for them.
Key management has to be done from Qualcomm Trustzone as only
it can interface with HWKM.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/soc/qcom/ice.c | 72 ++++++++++++++++++++++++++++++++++++++++++
 include/soc/qcom/ice.h |  8 +++++
 2 files changed, 80 insertions(+)

diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index 33f67fcfa1bc..16f7af74ddb0 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -19,6 +19,13 @@
 
 #define AES_256_XTS_KEY_SIZE			64
 
+/*
+ * Wrapped key sizes from HWKm is different for different versions of
+ * HW. It is not expected to change again in the future.
+ */
+#define QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(v)	\
+	((v) == 1 ? 68 : 100)
+
 /* QCOM ICE registers */
 #define QCOM_ICE_REG_VERSION			0x0008
 #define QCOM_ICE_REG_FUSE_SETTING		0x0010
@@ -412,6 +419,71 @@ int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wrapped_key[],
 }
 EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret);
 
+/**
+ * qcom_ice_generate_key() - Generate a wrapped key for inline encryption
+ * @longterm_wrapped_key: wrapped key that is generated, which is
+ *                        BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE in size.
+ *
+ * Make a scm call into trustzone to generate a wrapped key for storage
+ * encryption using hwkm.
+ *
+ * Return: 0 on success; err on failure.
+ */
+int qcom_ice_generate_key(struct qcom_ice *ice,
+	u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	return qcom_scm_generate_ice_key(longterm_wrapped_key,
+				QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version));
+}
+EXPORT_SYMBOL_GPL(qcom_ice_generate_key);
+
+/**
+ * qcom_ice_prepare_key() - Prepare a longterm wrapped key for inline encryption
+ * @longterm_wrapped_key: wrapped key that is generated,
+ * @longterm_wrapped_key_size: size of the longterm wrapped_key
+ * @ephemerally_wrapped_key: wrapped key returned which has been wrapped with
+ *                           a per-boot ephemeral key, size of which is
+ *                           BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE in size.
+ *
+ * Make a scm call into trustzone to prepare a wrapped key for storage
+ * encryption by rewrapping the longterm wrapped key with a per boot ephemeral
+ * key using hwkm.
+ *
+ * Return: 0 on success; err on failure.
+ */
+int qcom_ice_prepare_key(struct qcom_ice *ice,
+	const u8 *longterm_wrapped_key, unsigned int longterm_wrapped_key_size,
+	u8 ephemerally_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	return qcom_scm_prepare_ice_key(longterm_wrapped_key,
+				longterm_wrapped_key_size,
+				ephemerally_wrapped_key,
+				QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version));
+}
+EXPORT_SYMBOL_GPL(qcom_ice_prepare_key);
+
+/**
+ * qcom_ice_import_key() - Import a raw key for inline encryption
+ * @imported_key: raw key that has to be imported
+ * @imported_key_size: size of the imported key
+ * @longterm_wrapped_key: wrapped key that is imported, which is
+ *                        BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE in size.
+ *
+ * Make a scm call into trustzone to import a raw key for storage encryption
+ * and generating a longterm wrapped key using hwkm.
+ *
+ * Return: 0 on success; err on failure.
+ */
+int qcom_ice_import_key(struct qcom_ice *ice,
+	const u8 *imported_key, unsigned int imported_key_size,
+	u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	return qcom_scm_import_ice_key(imported_key, imported_key_size,
+				longterm_wrapped_key,
+				QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version));
+}
+EXPORT_SYMBOL_GPL(qcom_ice_import_key);
+
 static struct qcom_ice *qcom_ice_create(struct device *dev,
 					void __iomem *base)
 {
diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
index 22ab8d1a56de..ce41ec442657 100644
--- a/include/soc/qcom/ice.h
+++ b/include/soc/qcom/ice.h
@@ -39,5 +39,13 @@ bool qcom_ice_hwkm_supported(struct qcom_ice *ice);
 int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wrapped_key[],
 			      unsigned int wrapped_key_size,
 			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
+int qcom_ice_generate_key(struct qcom_ice *ice,
+	u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
+int qcom_ice_prepare_key(struct qcom_ice *ice,
+	const u8 *longterm_wrapped_key, unsigned int longterm_wrapped_key_size,
+	u8 ephemerally_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
+int qcom_ice_import_key(struct qcom_ice *ice,
+	const u8 *imported_key, unsigned int imported_key_size,
+	u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
 struct qcom_ice *of_qcom_ice_get(struct device *dev);
 #endif /* __QCOM_ICE_H__ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 10/10] ufs: host: support for generate, import and prepare key
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (8 preceding siblings ...)
  2023-07-19 17:04 ` [PATCH v2 09/10] soc: qcom: support for generate, import and prepare key Gaurav Kashyap
@ 2023-07-19 17:04 ` Gaurav Kashyap
  2023-07-20  2:55 ` [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Eric Biggers
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 36+ messages in thread
From: Gaurav Kashyap @ 2023-07-19 17:04 UTC (permalink / raw)
  To: linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala, Gaurav Kashyap

Implements the vops for generate, prepare and import key
apis in ufs qcom and call the respective ICE module apis
for them.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/ufs/host/ufs-qcom.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 9a7c5d46dbf4..b5be0c41cba2 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -149,10 +149,42 @@ int ufs_qcom_ice_derive_sw_secret(struct ufs_hba *hba, const u8 wrapped_key[],
 					wrapped_key_size, sw_secret);
 }
 
+int ufs_qcom_ice_generate_key(struct ufs_hba *hba,
+	u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+	return qcom_ice_generate_key(host->ice, longterm_wrapped_key);
+}
+
+int ufs_qcom_ice_prepare_key(struct ufs_hba *hba,
+	const u8 *longterm_wrapped_key, unsigned int longterm_wrapped_key_size,
+	u8 ephemerally_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+	return qcom_ice_prepare_key(host->ice, longterm_wrapped_key,
+				    longterm_wrapped_key_size,
+				    ephemerally_wrapped_key);
+}
+
+int ufs_qcom_ice_import_key(struct ufs_hba *hba,
+	const u8 *imported_key, unsigned int imported_key_size,
+	u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+	return qcom_ice_import_key(host->ice, imported_key, imported_key_size,
+				   longterm_wrapped_key);
+}
+
 #else
 
 #define ufs_qcom_ice_program_key NULL
 #define ufs_qcom_ice_derive_sw_secret NULL
+#define ufs_qcom_ice_generate_key NULL
+#define ufs_qcom_ice_prepare_key NULL
+#define ufs_qcom_ice_import_key NULL
 
 static inline void ufs_qcom_ice_enable(struct ufs_qcom_host *host)
 {
@@ -1769,6 +1801,9 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
 	.config_scaling_param = ufs_qcom_config_scaling_param,
 	.program_key		= ufs_qcom_ice_program_key,
 	.derive_sw_secret	= ufs_qcom_ice_derive_sw_secret,
+	.generate_key		= ufs_qcom_ice_generate_key,
+	.prepare_key		= ufs_qcom_ice_prepare_key,
+	.import_key		= ufs_qcom_ice_import_key,
 	.reinit_notify		= ufs_qcom_reinit_notify,
 	.mcq_config_resource	= ufs_qcom_mcq_config_resource,
 	.get_hba_mac		= ufs_qcom_get_hba_mac,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 07/10] qcom_scm: scm call for create, prepare and import keys
  2023-07-19 17:04 ` [PATCH v2 07/10] qcom_scm: scm call for create, prepare and import keys Gaurav Kashyap
@ 2023-07-19 17:48   ` Trilok Soni
  2023-07-22  3:40   ` Bjorn Andersson
  1 sibling, 0 replies; 36+ messages in thread
From: Trilok Soni @ 2023-07-19 17:48 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala

On 7/19/2023 10:04 AM, Gaurav Kashyap wrote:
> Storage encryption has two IOCTLs for creating, importing
> and preparing keys for encryption. For wrapped keys, these
> IOCTLs need to interface with the secure environment, which
> require these SCM calls.
> 
> generate_key: This is used to generate and return a longterm
>                wrapped key. Trustzone achieves this by generating
> 	      a key and then wrapping it using hwkm, returning
> 	      a wrapped keyblob.
> import_key:   The functionality is similar to generate, but here,
>                a raw key is imported into hwkm and a longterm wrapped
> 	      keyblob is returned.
> prepare_key:  The longterm wrapped key from import or generate
>                is made further secure by rewrapping it with a per-boot
> 	      ephemeral wrapped key before installing it to the linux
> 	      kernel for programming to ICE.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> ---
>   drivers/firmware/qcom_scm.c            | 222 +++++++++++++++++++++++++
>   drivers/firmware/qcom_scm.h            |   3 +
>   include/linux/firmware/qcom/qcom_scm.h |  10 ++
>   3 files changed, 235 insertions(+)
> 
> diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
> index 51062d5c7f7b..44dd1857747b 100644
> --- a/drivers/firmware/qcom_scm.c
> +++ b/drivers/firmware/qcom_scm.c
> @@ -1210,6 +1210,228 @@ int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size,
>   }
>   EXPORT_SYMBOL(qcom_scm_derive_sw_secret);
>   
> +/**
> + * qcom_scm_generate_ice_key() - Generate a wrapped key for encryption.
> + * @longterm_wrapped_key: the wrapped key returned after key generation
> + * @longterm_wrapped_key_size: size of the wrapped key to be returned.
> + *
> + * Qualcomm wrapped keys need to be generated in a trusted environment.
> + * A generate key  IOCTL call is used to achieve this. These are longterm
> + * in nature as they need to be generated and wrapped only once per
> + * requirement.
> + *
> + * This SCM calls adds support for the generate key IOCTL to interface
> + * with the secure environment to generate and return a wrapped key..
> + *
> + * Return: 0 on success; -errno on failure.
> + */
> +int qcom_scm_generate_ice_key(u8 *longterm_wrapped_key,
> +			    u32 longterm_wrapped_key_size)
> +{
> +	struct qcom_scm_desc desc = {
> +		.svc = QCOM_SCM_SVC_ES,
> +		.cmd =  QCOM_SCM_ES_GENERATE_ICE_KEY,
> +		.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW,
> +					 QCOM_SCM_VAL),
> +		.args[1] = longterm_wrapped_key_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *longterm_wrapped_keybuf;
> +	dma_addr_t longterm_wrapped_key_phys;
> +	int ret;
> +
> +	/*
> +	 * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly
> +	 * get a physical address, while guaranteeing that we can zeroize the
> +	 * key material later using memzero_explicit().
> +	 *
> +	 */
> +	longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
> +				  longterm_wrapped_key_size,
> +				  &longterm_wrapped_key_phys, GFP_KERNEL);
> +	if (!longterm_wrapped_keybuf)
> +		return -ENOMEM;
> +
> +	desc.args[0] = longterm_wrapped_key_phys;
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	memcpy(longterm_wrapped_key, longterm_wrapped_keybuf,
> +	       longterm_wrapped_key_size);
> +
> +	memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size);
> +	dma_free_coherent(__scm->dev, longterm_wrapped_key_size,
> +			  longterm_wrapped_keybuf, longterm_wrapped_key_phys);
> +
> +	if (!ret)
> +		return longterm_wrapped_key_size;
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(qcom_scm_generate_ice_key);
> +
> +/**
> + * qcom_scm_prepare_ice_key() - Get per boot ephemeral wrapped key
> + * @longterm_wrapped_key: the wrapped key
> + * @longterm_wrapped_key_size: size of the wrapped key
> + * @ephemeral_wrapped_key: ephemeral wrapped key to be returned
> + * @ephemeral_wrapped_key_size: size of the ephemeral wrapped key
> + *
> + * Qualcomm wrapped keys (longterm keys) are rewrapped with a per-boot
> + * ephemeral key for added protection. These are ephemeral in nature as
> + * they are valid only for that boot. A create key IOCTL is used to
> + * achieve this. These are the keys that are installed into the kernel
> + * to be then unwrapped and programmed into ICE.
> + *
> + * This SCM call adds support for the create key IOCTL to interface
> + * with the secure environment to rewrap the wrapped key with an
> + * ephemeral wrapping key.
> + *
> + * Return: 0 on success; -errno on failure.
> + */
> +int qcom_scm_prepare_ice_key(const u8 *longterm_wrapped_key,
> +			     u32 longterm_wrapped_key_size,
> +			     u8 *ephemeral_wrapped_key,
> +			     u32 ephemeral_wrapped_key_size)
> +{
> +	struct qcom_scm_desc desc = {
> +		.svc = QCOM_SCM_SVC_ES,
> +		.cmd =  QCOM_SCM_ES_PREPARE_ICE_KEY,
> +		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO,
> +					 QCOM_SCM_VAL, QCOM_SCM_RW,
> +					 QCOM_SCM_VAL),
> +		.args[1] = longterm_wrapped_key_size,
> +		.args[3] = ephemeral_wrapped_key_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *longterm_wrapped_keybuf, *ephemeral_wrapped_keybuf;
> +	dma_addr_t longterm_wrapped_key_phys, ephemeral_wrapped_key_phys;
> +	int ret;
> +
> +	/*
> +	 * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly
> +	 * get a physical address, while guaranteeing that we can zeroize the
> +	 * key material later using memzero_explicit().
> +	 *
> +	 */
> +	longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
> +				  longterm_wrapped_key_size,
> +				  &longterm_wrapped_key_phys, GFP_KERNEL);
> +	if (!longterm_wrapped_keybuf)
> +		return -ENOMEM;
> +	ephemeral_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
> +				   ephemeral_wrapped_key_size,
> +				   &ephemeral_wrapped_key_phys, GFP_KERNEL);
> +	if (!ephemeral_wrapped_keybuf) {
> +		ret = -ENOMEM;
> +		goto bail_keybuf;
> +	}
> +
> +	memcpy(longterm_wrapped_keybuf, longterm_wrapped_key,
> +	       longterm_wrapped_key_size);
> +	desc.args[0] = longterm_wrapped_key_phys;
> +	desc.args[2] = ephemeral_wrapped_key_phys;
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	if (!ret)
> +		memcpy(ephemeral_wrapped_key, ephemeral_wrapped_keybuf,
> +		       ephemeral_wrapped_key_size);
> +
> +	memzero_explicit(ephemeral_wrapped_keybuf, ephemeral_wrapped_key_size);
> +	dma_free_coherent(__scm->dev, ephemeral_wrapped_key_size,
> +			  ephemeral_wrapped_keybuf,
> +			  ephemeral_wrapped_key_phys);
> +
> +bail_keybuf:
> +	memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size);
> +	dma_free_coherent(__scm->dev, longterm_wrapped_key_size,
> +			  longterm_wrapped_keybuf, longterm_wrapped_key_phys);
> +
> +	if (!ret)
> +		return ephemeral_wrapped_key_size;
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(qcom_scm_prepare_ice_key);

EXPORT_SYMBOL_GPL everywhere please. I understand that other places in 
this file uses EXPORT_SYMBOL but new additions can be _GPL. I will see 
if someone from my team can covert other symbols to _GPL as well in this 
file.

---Trilok Soni

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (9 preceding siblings ...)
  2023-07-19 17:04 ` [PATCH v2 10/10] ufs: host: " Gaurav Kashyap
@ 2023-07-20  2:55 ` Eric Biggers
  2023-08-01 17:31   ` Gaurav Kashyap (QUIC)
  2023-08-25 10:19 ` Srinivas Kandagatla
  2023-08-29 21:06 ` Konrad Dybcio
  12 siblings, 1 reply; 36+ messages in thread
From: Eric Biggers @ 2023-07-20  2:55 UTC (permalink / raw)
  To: Gaurav Kashyap
  Cc: linux-scsi, linux-arm-msm, linux-mmc, linux-block, linux-fscrypt,
	omprsing, quic_psodagud, avmenon, abel.vesa, quic_spuppala

Hi Gaurav,

On Wed, Jul 19, 2023 at 10:04:14AM -0700, Gaurav Kashyap wrote:
> These patches add support to Qualcomm ICE (Inline Crypto Enginr) for hardware
> wrapped keys using Qualcomm Hardware Key Manager (HWKM) and are made on top
> of a rebased version  Eric Bigger's set of changes to support wrapped keys in
> fscrypt and block below:
> https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7
> (The rebased patches are not uploaded here)
> 
> Ref v1 here:
> https://lore.kernel.org/linux-scsi/20211206225725.77512-1-quic_gaurkash@quicinc.com/
> 
> Explanation and use of hardware-wrapped-keys can be found here:
> Documentation/block/inline-encryption.rst
> 
> This patch is organized as follows:
> 
> Patch 1 - Prepares ICE and storage layers (UFS and EMMC) to pass around wrapped keys.
> Patch 2 - Adds a new SCM api to support deriving software secret when wrapped keys are used
> Patch 3-4 - Adds support for wrapped keys in the ICE driver. This includes adding HWKM support
> Patch 5-6 - Adds support for wrapped keys in UFS
> Patch 7-10 - Supports generate, prepare and import functionality in ICE and UFS
> 
> NOTE: MMC will have similar changes to UFS and will be uploaded in a different patchset
>       Patch 3, 4, 8, 10 will have MMC equivalents.
> 
> Testing:
> Test platform: SM8550 MTP
> Engineering trustzone image is required to test this feature only
> for SM8550. For SM8650 onwards, all trustzone changes to support this
> will be part of the released images.
> The engineering changes primarily contain hooks to generate, import and
> prepare keys for HW wrapped disk encryption.
> 
> The changes were tested by mounting initramfs and running the fscryptctl
> tool (Ref: https://github.com/ebiggers/fscryptctl/tree/wip-wrapped-keys) to
> generate and prepare keys, as well as to set policies on folders, which
> consequently invokes disk encryption flows through UFS.
> 
> Gaurav Kashyap (10):
>   ice, ufs, mmc: use blk_crypto_key for program_key
>   qcom_scm: scm call for deriving a software secret
>   soc: qcom: ice: add hwkm support in ice
>   soc: qcom: ice: support for hardware wrapped keys
>   ufs: core: support wrapped keys in ufs core
>   ufs: host: wrapped keys support in ufs qcom
>   qcom_scm: scm call for create, prepare and import keys
>   ufs: core: add support for generate, import and prepare keys
>   soc: qcom: support for generate, import and prepare key
>   ufs: host: support for generate, import and prepare key
> 
>  drivers/firmware/qcom_scm.c            | 292 +++++++++++++++++++++++
>  drivers/firmware/qcom_scm.h            |   4 +
>  drivers/mmc/host/cqhci-crypto.c        |   7 +-
>  drivers/mmc/host/cqhci.h               |   2 +
>  drivers/mmc/host/sdhci-msm.c           |   6 +-
>  drivers/soc/qcom/ice.c                 | 309 +++++++++++++++++++++++--
>  drivers/ufs/core/ufshcd-crypto.c       |  92 +++++++-
>  drivers/ufs/host/ufs-qcom.c            |  63 ++++-
>  include/linux/firmware/qcom/qcom_scm.h |  13 ++
>  include/soc/qcom/ice.h                 |  18 +-
>  include/ufs/ufshcd.h                   |  25 ++
>  11 files changed, 797 insertions(+), 34 deletions(-)


Thank you for continuing to work on this!

According to your cover letter, this feature requires a custom TrustZone image
to work on SM8550.  Will that image be made available outside Qualcomm?

Also according to your cover letter, this feature will work on SM8650 out of the
box.  That's great to hear.  However, SM8650 does not appear to be publicly
available yet or have any upstream kernel support.  Do you know approximately
when a SM8650 development board will become available to the general public?

Also, can you please make available a git branch somewhere that contains your
patchset?  It sounds like this depends on
https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7, but
actually a version of it that you've rebased, which I don't have access to.
Without being able to apply your patchset, I can't properly review it.

Thanks!

- Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 07/10] qcom_scm: scm call for create, prepare and import keys
  2023-07-19 17:04 ` [PATCH v2 07/10] qcom_scm: scm call for create, prepare and import keys Gaurav Kashyap
  2023-07-19 17:48   ` Trilok Soni
@ 2023-07-22  3:40   ` Bjorn Andersson
  2023-07-22  4:11     ` Eric Biggers
  1 sibling, 1 reply; 36+ messages in thread
From: Bjorn Andersson @ 2023-07-22  3:40 UTC (permalink / raw)
  To: Gaurav Kashyap
  Cc: linux-scsi, linux-arm-msm, ebiggers, linux-mmc, linux-block,
	linux-fscrypt, omprsing, quic_psodagud, avmenon, abel.vesa,
	quic_spuppala

On Wed, Jul 19, 2023 at 10:04:21AM -0700, Gaurav Kashyap wrote:
> Storage encryption has two IOCTLs for creating, importing
> and preparing keys for encryption. For wrapped keys, these
> IOCTLs need to interface with the secure environment, which
> require these SCM calls.
> 
> generate_key: This is used to generate and return a longterm
>               wrapped key. Trustzone achieves this by generating
> 	      a key and then wrapping it using hwkm, returning
> 	      a wrapped keyblob.
> import_key:   The functionality is similar to generate, but here,
>               a raw key is imported into hwkm and a longterm wrapped
> 	      keyblob is returned.
> prepare_key:  The longterm wrapped key from import or generate
>               is made further secure by rewrapping it with a per-boot
> 	      ephemeral wrapped key before installing it to the linux
> 	      kernel for programming to ICE.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> ---
>  drivers/firmware/qcom_scm.c            | 222 +++++++++++++++++++++++++
>  drivers/firmware/qcom_scm.h            |   3 +
>  include/linux/firmware/qcom/qcom_scm.h |  10 ++
>  3 files changed, 235 insertions(+)
> 
> diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
> index 51062d5c7f7b..44dd1857747b 100644
> --- a/drivers/firmware/qcom_scm.c
> +++ b/drivers/firmware/qcom_scm.c
> @@ -1210,6 +1210,228 @@ int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size,
>  }
>  EXPORT_SYMBOL(qcom_scm_derive_sw_secret);
>  
> +/**
> + * qcom_scm_generate_ice_key() - Generate a wrapped key for encryption.
> + * @longterm_wrapped_key: the wrapped key returned after key generation

"longterm" was long enough that you didn't feel it made sense in the
description ;)

Jokes aside, please follow the convention described in:
https://www.kernel.org/doc/html/v4.10/process/coding-style.html#naming

"key" or "wrapped_key" sounds sufficient to me.

> + * @longterm_wrapped_key_size: size of the wrapped key to be returned.
> + *
> + * Qualcomm wrapped keys need to be generated in a trusted environment.
> + * A generate key  IOCTL call is used to achieve this. These are longterm
> + * in nature as they need to be generated and wrapped only once per
> + * requirement.
> + *
> + * This SCM calls adds support for the generate key IOCTL to interface
> + * with the secure environment to generate and return a wrapped key..

I'm afraid I don't fully understand this sentence, please rework it.

> + *
> + * Return: 0 on success; -errno on failure.
> + */
> +int qcom_scm_generate_ice_key(u8 *longterm_wrapped_key,
> +			    u32 longterm_wrapped_key_size)
> +{
> +	struct qcom_scm_desc desc = {
> +		.svc = QCOM_SCM_SVC_ES,
> +		.cmd =  QCOM_SCM_ES_GENERATE_ICE_KEY,
> +		.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW,
> +					 QCOM_SCM_VAL),

Leaving this line unwrapped brings you to 71 characters, you have 80
(with stretch of 100) as the limit.

> +		.args[1] = longterm_wrapped_key_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *longterm_wrapped_keybuf;

"buf" or "tmp" sounds sufficient.

> +	dma_addr_t longterm_wrapped_key_phys;

"phys" or "addr"

> +	int ret;
> +
> +	/*
> +	 * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly
> +	 * get a physical address, while guaranteeing that we can zeroize the
> +	 * key material later using memzero_explicit().
> +	 *
> +	 */
> +	longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
> +				  longterm_wrapped_key_size,
> +				  &longterm_wrapped_key_phys, GFP_KERNEL);
> +	if (!longterm_wrapped_keybuf)
> +		return -ENOMEM;
> +
> +	desc.args[0] = longterm_wrapped_key_phys;
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	memcpy(longterm_wrapped_key, longterm_wrapped_keybuf,
> +	       longterm_wrapped_key_size);

The idiomatic way is to not touch the output buffer if the call fails,
any particular reason for you to not follow this here?

> +
> +	memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size);
> +	dma_free_coherent(__scm->dev, longterm_wrapped_key_size,
> +			  longterm_wrapped_keybuf, longterm_wrapped_key_phys);

With better choice of variable names you might be able to leave this
unwrapped (remember the guideline is 80, but you can go over that
slightly if it benefits readability)

> +
> +	if (!ret)
> +		return longterm_wrapped_key_size;

It's also idiomatic to return early on errors. So please swap this
around to make the successful exit at the end.

> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(qcom_scm_generate_ice_key);
> +
> +/**
> + * qcom_scm_prepare_ice_key() - Get per boot ephemeral wrapped key
> + * @longterm_wrapped_key: the wrapped key
> + * @longterm_wrapped_key_size: size of the wrapped key
> + * @ephemeral_wrapped_key: ephemeral wrapped key to be returned
> + * @ephemeral_wrapped_key_size: size of the ephemeral wrapped key
> + *
> + * Qualcomm wrapped keys (longterm keys) are rewrapped with a per-boot
> + * ephemeral key for added protection. These are ephemeral in nature as
> + * they are valid only for that boot. A create key IOCTL is used to
> + * achieve this. These are the keys that are installed into the kernel
> + * to be then unwrapped and programmed into ICE.
> + *
> + * This SCM call adds support for the create key IOCTL to interface
> + * with the secure environment to rewrap the wrapped key with an
> + * ephemeral wrapping key.
> + *
> + * Return: 0 on success; -errno on failure.
> + */
> +int qcom_scm_prepare_ice_key(const u8 *longterm_wrapped_key,
> +			     u32 longterm_wrapped_key_size,
> +			     u8 *ephemeral_wrapped_key,
> +			     u32 ephemeral_wrapped_key_size)

wrapped, wrapped_size, ephemeral, ephemeral_size perhaps?

> +{
> +	struct qcom_scm_desc desc = {
> +		.svc = QCOM_SCM_SVC_ES,
> +		.cmd =  QCOM_SCM_ES_PREPARE_ICE_KEY,
> +		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO,
> +					 QCOM_SCM_VAL, QCOM_SCM_RW,
> +					 QCOM_SCM_VAL),
> +		.args[1] = longterm_wrapped_key_size,
> +		.args[3] = ephemeral_wrapped_key_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *longterm_wrapped_keybuf, *ephemeral_wrapped_keybuf;
> +	dma_addr_t longterm_wrapped_key_phys, ephemeral_wrapped_key_phys;
> +	int ret;
> +
> +	/*
> +	 * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly
> +	 * get a physical address, while guaranteeing that we can zeroize the
> +	 * key material later using memzero_explicit().
> +	 *
> +	 */
> +	longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
> +				  longterm_wrapped_key_size,
> +				  &longterm_wrapped_key_phys, GFP_KERNEL);
> +	if (!longterm_wrapped_keybuf)
> +		return -ENOMEM;
> +	ephemeral_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
> +				   ephemeral_wrapped_key_size,
> +				   &ephemeral_wrapped_key_phys, GFP_KERNEL);
> +	if (!ephemeral_wrapped_keybuf) {
> +		ret = -ENOMEM;
> +		goto bail_keybuf;
> +	}
> +
> +	memcpy(longterm_wrapped_keybuf, longterm_wrapped_key,
> +	       longterm_wrapped_key_size);
> +	desc.args[0] = longterm_wrapped_key_phys;
> +	desc.args[2] = ephemeral_wrapped_key_phys;
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	if (!ret)
> +		memcpy(ephemeral_wrapped_key, ephemeral_wrapped_keybuf,
> +		       ephemeral_wrapped_key_size);
> +
> +	memzero_explicit(ephemeral_wrapped_keybuf, ephemeral_wrapped_key_size);
> +	dma_free_coherent(__scm->dev, ephemeral_wrapped_key_size,
> +			  ephemeral_wrapped_keybuf,
> +			  ephemeral_wrapped_key_phys);
> +
> +bail_keybuf:

Which "key"?

Perhaps

err_free_longterm_buf:

> +	memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size);

I don't see a reason to memzero_explicit(longterm_buf) in the
bail_keybuf. Move this up and memzero_explicit() both buffers at the
same time, then dma_free_coherent() them.

> +	dma_free_coherent(__scm->dev, longterm_wrapped_key_size,
> +			  longterm_wrapped_keybuf, longterm_wrapped_key_phys);
> +
> +	if (!ret)
> +		return ephemeral_wrapped_key_size;

As above, flip the two cases.

> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(qcom_scm_prepare_ice_key);
> +
> +/**
> + * qcom_scm_import_ice_key() - Import a wrapped key for encryption
> + * @imported_key: the raw key that is imported
> + * @imported_key_size: size of the key to be imported
> + * @longterm_wrapped_key: the wrapped key to be returned
> + * @longterm_wrapped_key_size: size of the wrapped key
> + *
> + * Conceptually, this is very similar to generate, the difference being,
> + * here we want to import a raw key and return a longterm wrapped key
> + * from it. THe same create key IOCTL is used to achieve this.
> + *
> + * This SCM call adds support for the create key IOCTL to interface with
> + * the secure environment to import a raw key and generate a longterm
> + * wrapped key.
> + *
> + * Return: 0 on success; -errno on failure.
> + */
> +int qcom_scm_import_ice_key(const u8 *imported_key, u32 imported_key_size,
> +			    u8 *longterm_wrapped_key,
> +			    u32 longterm_wrapped_key_size)

Same thing with naming here, please.

> +{
> +	struct qcom_scm_desc desc = {
> +		.svc = QCOM_SCM_SVC_ES,
> +		.cmd =  QCOM_SCM_ES_IMPORT_ICE_KEY,
> +		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO,
> +					 QCOM_SCM_VAL, QCOM_SCM_RW,
> +					 QCOM_SCM_VAL),
> +		.args[1] = imported_key_size,
> +		.args[3] = longterm_wrapped_key_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *imported_keybuf, *longterm_wrapped_keybuf;
> +	dma_addr_t imported_key_phys, longterm_wrapped_key_phys;
> +	int ret;

Declaration above and comment below are two separate "paragraphs", so a
empty line between them would be good.

> +	/*
> +	 * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly
> +	 * get a physical address, while guaranteeing that we can zeroize the
> +	 * key material later using memzero_explicit().
> +	 *
> +	 */
> +	imported_keybuf = dma_alloc_coherent(__scm->dev, imported_key_size,
> +			  &imported_key_phys, GFP_KERNEL);
> +	if (!imported_keybuf)
> +		return -ENOMEM;
> +	longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev,
> +				  longterm_wrapped_key_size,
> +				  &longterm_wrapped_key_phys, GFP_KERNEL);
> +	if (!longterm_wrapped_keybuf) {
> +		ret = -ENOMEM;
> +		goto bail_keybuf;
> +	}
> +
> +	memcpy(imported_keybuf, imported_key, imported_key_size);
> +	desc.args[0] = imported_key_phys;
> +	desc.args[2] = longterm_wrapped_key_phys;
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	if (!ret)
> +		memcpy(longterm_wrapped_key, longterm_wrapped_keybuf,
> +		       longterm_wrapped_key_size);
> +
> +	memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size);
> +	dma_free_coherent(__scm->dev, longterm_wrapped_key_size,
> +			  longterm_wrapped_keybuf, longterm_wrapped_key_phys);
> +bail_keybuf:
> +	memzero_explicit(imported_keybuf, imported_key_size);

As above, please move this together with the other memzero_explicit().

> +	dma_free_coherent(__scm->dev, imported_key_size, imported_keybuf,
> +			  imported_key_phys);
> +
> +	if (!ret)

And flip these.

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 02/10] qcom_scm: scm call for deriving a software secret
  2023-07-19 17:04 ` [PATCH v2 02/10] qcom_scm: scm call for deriving a software secret Gaurav Kashyap
@ 2023-07-22  3:50   ` Bjorn Andersson
  2023-07-22  4:18     ` Eric Biggers
  0 siblings, 1 reply; 36+ messages in thread
From: Bjorn Andersson @ 2023-07-22  3:50 UTC (permalink / raw)
  To: Gaurav Kashyap
  Cc: linux-scsi, linux-arm-msm, ebiggers, linux-mmc, linux-block,
	linux-fscrypt, omprsing, quic_psodagud, avmenon, abel.vesa,
	quic_spuppala

On Wed, Jul 19, 2023 at 10:04:16AM -0700, Gaurav Kashyap wrote:

The $subject prefix does not match other changes in the scm driver.
Please use git log --oneline drivers/fimware/qcom_scm.c and follow what
other changes uses.

> Inline storage encryption requires deriving a sw secret from
> the hardware wrapped keys. For non-wrapped keys, this can be
> directly done as keys are in the clear.
> 
> However, when keys are hardware wrapped, it can be unwrapped
> by HWKM (Hardware Key Manager) which is accessible only from Qualcomm
> Trustzone. Hence, it also makes sense that the software secret is also
> derived there and returned to the linux kernel . This can be invoked by
> using the crypto profile APIs provided by the block layer.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> ---
>  drivers/firmware/qcom_scm.c            | 70 ++++++++++++++++++++++++++
>  drivers/firmware/qcom_scm.h            |  1 +
>  include/linux/firmware/qcom/qcom_scm.h |  3 ++
>  3 files changed, 74 insertions(+)
> 
> diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
> index fde33acd46b7..51062d5c7f7b 100644
> --- a/drivers/firmware/qcom_scm.c
> +++ b/drivers/firmware/qcom_scm.c
> @@ -1140,6 +1140,76 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
>  }
>  EXPORT_SYMBOL(qcom_scm_ice_set_key);
>  
> +/**
> + * qcom_scm_derive_sw_secret() - Derive SW secret from wrapped key
> + * @wrapped_key: the wrapped key used for inline encryption
> + * @wrapped_key_size: size of the wrapped key

Following my reply on patch 7, how about dropping the "_key" suffix on
these.

> + * @sw_secret: the secret to be derived which is exactly the secret size

Similarly the "sw_" prefix doesn't see to add value, please omit it.

> + * @secret_size: size of the secret
> + *
> + * Derive a SW secret from a HW Wrapped key for non HW key operations.
> + * For wrapped keys, the key needs to be unwrapped, in order to derive a
> + * SW secret, which can be done only by the secure EE.

Please spell out SW, HW, and EE in this sentence.

> + *
> + * For more information on sw secret, please refer to "Hardware-wrapped keys"
> + * section of Documentation/block/inline-encryption.rst.
> + *
> + * Return: 0 on success; -errno on failure.
> + */
> +int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size,
> +			      u8 *sw_secret, u32 secret_size)

size_t is a better data type for "a size". (Think I forgot to mention
this in the other patch as well).

> +{
> +	struct qcom_scm_desc desc = {
> +		.svc = QCOM_SCM_SVC_ES,
> +		.cmd =  QCOM_SCM_ES_DERIVE_SW_SECRET,
> +		.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW,
> +					 QCOM_SCM_VAL, QCOM_SCM_RW,
> +					 QCOM_SCM_VAL),
> +		.args[1] = wrapped_key_size,
> +		.args[3] = secret_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *keybuf, *secretbuf;
> +	dma_addr_t key_phys, secret_phys;
> +	int ret;
> +
> +	/*
> +	 * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly
> +	 * get a physical address, while guaranteeing that we can zeroize the
> +	 * key material later using memzero_explicit().
> +	 *

Unnecessary empty line.

> +	 */
> +	keybuf = dma_alloc_coherent(__scm->dev, wrapped_key_size, &key_phys,
> +				    GFP_KERNEL);

Unwrapping this line takes you to 89 characters, which is less than 100
and easier to read. So please bend the 80-char recommendation for this.

> +	if (!keybuf)
> +		return -ENOMEM;
> +	secretbuf = dma_alloc_coherent(__scm->dev, secret_size, &secret_phys,
> +				    GFP_KERNEL);

Same here

> +	if (!secretbuf) {
> +		ret = -ENOMEM;
> +		goto bail_keybuf;
> +	}
> +
> +	memcpy(keybuf, wrapped_key, wrapped_key_size);
> +	desc.args[0] = key_phys;
> +	desc.args[2] = secret_phys;
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	if (!ret)
> +		memcpy(sw_secret, secretbuf, secret_size);
> +
> +	memzero_explicit(secretbuf, secret_size);

Empty line here would provide a nice separation between the zeroing and
the freeing.

> +	dma_free_coherent(__scm->dev, secret_size, secretbuf, secret_phys);
> +
> +bail_keybuf:

Both buffers are keys

err_free_wrapped:

> +	memzero_explicit(keybuf, wrapped_key_size);

And it seems sufficient to move this up together with the other
memzero_explicit() as well.

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 09/10] soc: qcom: support for generate, import and prepare key
  2023-07-19 17:04 ` [PATCH v2 09/10] soc: qcom: support for generate, import and prepare key Gaurav Kashyap
@ 2023-07-22  3:56   ` Bjorn Andersson
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Andersson @ 2023-07-22  3:56 UTC (permalink / raw)
  To: Gaurav Kashyap
  Cc: linux-scsi, linux-arm-msm, ebiggers, linux-mmc, linux-block,
	linux-fscrypt, omprsing, quic_psodagud, avmenon, abel.vesa,
	quic_spuppala

On Wed, Jul 19, 2023 at 10:04:23AM -0700, Gaurav Kashyap wrote:
> Implements the ICE apis for generate, prepare and import key
> apis and hooks it up the scm calls defined for them.
> Key management has to be done from Qualcomm Trustzone as only
> it can interface with HWKM.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> ---
>  drivers/soc/qcom/ice.c | 72 ++++++++++++++++++++++++++++++++++++++++++
>  include/soc/qcom/ice.h |  8 +++++
>  2 files changed, 80 insertions(+)
> 
> diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
> index 33f67fcfa1bc..16f7af74ddb0 100644
> --- a/drivers/soc/qcom/ice.c
> +++ b/drivers/soc/qcom/ice.c
> @@ -19,6 +19,13 @@
>  
>  #define AES_256_XTS_KEY_SIZE			64
>  
> +/*
> + * Wrapped key sizes from HWKm is different for different versions of
> + * HW. It is not expected to change again in the future.
> + */
> +#define QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(v)	\
> +	((v) == 1 ? 68 : 100)
> +
>  /* QCOM ICE registers */
>  #define QCOM_ICE_REG_VERSION			0x0008
>  #define QCOM_ICE_REG_FUSE_SETTING		0x0010
> @@ -412,6 +419,71 @@ int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wrapped_key[],
>  }
>  EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret);
>  
> +/**
> + * qcom_ice_generate_key() - Generate a wrapped key for inline encryption
> + * @longterm_wrapped_key: wrapped key that is generated, which is
> + *                        BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE in size.
> + *
> + * Make a scm call into trustzone to generate a wrapped key for storage
> + * encryption using hwkm.
> + *
> + * Return: 0 on success; err on failure.
> + */
> +int qcom_ice_generate_key(struct qcom_ice *ice,
> +	u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])

Please run "./scripts/checkpatch.pl --strict *" on your patches, and fix
all relevant warnings and errors.

Please consider revisiting the naming in this patch as well.

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 07/10] qcom_scm: scm call for create, prepare and import keys
  2023-07-22  3:40   ` Bjorn Andersson
@ 2023-07-22  4:11     ` Eric Biggers
  2023-07-22 17:32       ` Bjorn Andersson
  0 siblings, 1 reply; 36+ messages in thread
From: Eric Biggers @ 2023-07-22  4:11 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala

On Fri, Jul 21, 2023 at 08:40:32PM -0700, Bjorn Andersson wrote:
> On Wed, Jul 19, 2023 at 10:04:21AM -0700, Gaurav Kashyap wrote:
> > Storage encryption has two IOCTLs for creating, importing
> > and preparing keys for encryption. For wrapped keys, these
> > IOCTLs need to interface with the secure environment, which
> > require these SCM calls.
> > 
> > generate_key: This is used to generate and return a longterm
> >               wrapped key. Trustzone achieves this by generating
> > 	      a key and then wrapping it using hwkm, returning
> > 	      a wrapped keyblob.
> > import_key:   The functionality is similar to generate, but here,
> >               a raw key is imported into hwkm and a longterm wrapped
> > 	      keyblob is returned.
> > prepare_key:  The longterm wrapped key from import or generate
> >               is made further secure by rewrapping it with a per-boot
> > 	      ephemeral wrapped key before installing it to the linux
> > 	      kernel for programming to ICE.
> > 
> > Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> > ---
> >  drivers/firmware/qcom_scm.c            | 222 +++++++++++++++++++++++++
> >  drivers/firmware/qcom_scm.h            |   3 +
> >  include/linux/firmware/qcom/qcom_scm.h |  10 ++
> >  3 files changed, 235 insertions(+)
> > 
> > diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
> > index 51062d5c7f7b..44dd1857747b 100644
> > --- a/drivers/firmware/qcom_scm.c
> > +++ b/drivers/firmware/qcom_scm.c
> > @@ -1210,6 +1210,228 @@ int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size,
> >  }
> >  EXPORT_SYMBOL(qcom_scm_derive_sw_secret);
> >  
> > +/**
> > + * qcom_scm_generate_ice_key() - Generate a wrapped key for encryption.
> > + * @longterm_wrapped_key: the wrapped key returned after key generation
> 
> "longterm" was long enough that you didn't feel it made sense in the
> description ;)
> 
> Jokes aside, please follow the convention described in:
> https://www.kernel.org/doc/html/v4.10/process/coding-style.html#naming
> 
> "key" or "wrapped_key" sounds sufficient to me.

The naming I use in my most recent patchset that adds support for
hardware-wrapped inline encryption keys to the block layer and fscrypt
(https://lore.kernel.org/linux-block/20221216203636.81491-1-ebiggers@kernel.org/),
which this patchset is based on, is 'lt_key' for a longterm wrapped key and
'eph_key' for an ephemerally-wrapped key.

> > +int qcom_scm_prepare_ice_key(const u8 *longterm_wrapped_key,
> > +			     u32 longterm_wrapped_key_size,
> > +			     u8 *ephemeral_wrapped_key,
> > +			     u32 ephemeral_wrapped_key_size)
> 
> wrapped, wrapped_size, ephemeral, ephemeral_size perhaps?

lt_key, lt_key_size, eph_key, eph_key_size.

- Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 02/10] qcom_scm: scm call for deriving a software secret
  2023-07-22  3:50   ` Bjorn Andersson
@ 2023-07-22  4:18     ` Eric Biggers
  2023-07-22 17:31       ` Bjorn Andersson
  0 siblings, 1 reply; 36+ messages in thread
From: Eric Biggers @ 2023-07-22  4:18 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala

On Fri, Jul 21, 2023 at 08:50:56PM -0700, Bjorn Andersson wrote:
> > +/**
> > + * qcom_scm_derive_sw_secret() - Derive SW secret from wrapped key
> > + * @wrapped_key: the wrapped key used for inline encryption
> > + * @wrapped_key_size: size of the wrapped key
> 
> Following my reply on patch 7, how about dropping the "_key" suffix on
> these.
> 
> > + * @sw_secret: the secret to be derived which is exactly the secret size
> 
> Similarly the "sw_" prefix doesn't see to add value, please omit it.

The name 'sw_secret' comes from the block layer support
(https://lore.kernel.org/linux-block/20221216203636.81491-2-ebiggers@kernel.org/).
It is helpful to call it 'sw_secret' instead of 'secret', as there are other
types of secrets involved that are not accessible to software (Linux).

- Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 02/10] qcom_scm: scm call for deriving a software secret
  2023-07-22  4:18     ` Eric Biggers
@ 2023-07-22 17:31       ` Bjorn Andersson
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Andersson @ 2023-07-22 17:31 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala

On Fri, Jul 21, 2023 at 09:18:24PM -0700, Eric Biggers wrote:
> On Fri, Jul 21, 2023 at 08:50:56PM -0700, Bjorn Andersson wrote:
> > > +/**
> > > + * qcom_scm_derive_sw_secret() - Derive SW secret from wrapped key
> > > + * @wrapped_key: the wrapped key used for inline encryption
> > > + * @wrapped_key_size: size of the wrapped key
> > 
> > Following my reply on patch 7, how about dropping the "_key" suffix on
> > these.
> > 
> > > + * @sw_secret: the secret to be derived which is exactly the secret size
> > 
> > Similarly the "sw_" prefix doesn't see to add value, please omit it.
> 
> The name 'sw_secret' comes from the block layer support
> (https://lore.kernel.org/linux-block/20221216203636.81491-2-ebiggers@kernel.org/).
> It is helpful to call it 'sw_secret' instead of 'secret', as there are other
> types of secrets involved that are not accessible to software (Linux).
> 

I'm happy with that motivation.

My OCD would like for the length of that to be sw_secret_size (or
perhaps _len instead...), and not "secret_size", then.

Thanks Eric,
Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 07/10] qcom_scm: scm call for create, prepare and import keys
  2023-07-22  4:11     ` Eric Biggers
@ 2023-07-22 17:32       ` Bjorn Andersson
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Andersson @ 2023-07-22 17:32 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala

On Fri, Jul 21, 2023 at 09:11:13PM -0700, Eric Biggers wrote:
> On Fri, Jul 21, 2023 at 08:40:32PM -0700, Bjorn Andersson wrote:
> > On Wed, Jul 19, 2023 at 10:04:21AM -0700, Gaurav Kashyap wrote:
> > > Storage encryption has two IOCTLs for creating, importing
> > > and preparing keys for encryption. For wrapped keys, these
> > > IOCTLs need to interface with the secure environment, which
> > > require these SCM calls.
> > > 
> > > generate_key: This is used to generate and return a longterm
> > >               wrapped key. Trustzone achieves this by generating
> > > 	      a key and then wrapping it using hwkm, returning
> > > 	      a wrapped keyblob.
> > > import_key:   The functionality is similar to generate, but here,
> > >               a raw key is imported into hwkm and a longterm wrapped
> > > 	      keyblob is returned.
> > > prepare_key:  The longterm wrapped key from import or generate
> > >               is made further secure by rewrapping it with a per-boot
> > > 	      ephemeral wrapped key before installing it to the linux
> > > 	      kernel for programming to ICE.
> > > 
> > > Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> > > ---
> > >  drivers/firmware/qcom_scm.c            | 222 +++++++++++++++++++++++++
> > >  drivers/firmware/qcom_scm.h            |   3 +
> > >  include/linux/firmware/qcom/qcom_scm.h |  10 ++
> > >  3 files changed, 235 insertions(+)
> > > 
> > > diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
> > > index 51062d5c7f7b..44dd1857747b 100644
> > > --- a/drivers/firmware/qcom_scm.c
> > > +++ b/drivers/firmware/qcom_scm.c
> > > @@ -1210,6 +1210,228 @@ int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size,
> > >  }
> > >  EXPORT_SYMBOL(qcom_scm_derive_sw_secret);
> > >  
> > > +/**
> > > + * qcom_scm_generate_ice_key() - Generate a wrapped key for encryption.
> > > + * @longterm_wrapped_key: the wrapped key returned after key generation
> > 
> > "longterm" was long enough that you didn't feel it made sense in the
> > description ;)
> > 
> > Jokes aside, please follow the convention described in:
> > https://www.kernel.org/doc/html/v4.10/process/coding-style.html#naming
> > 
> > "key" or "wrapped_key" sounds sufficient to me.
> 
> The naming I use in my most recent patchset that adds support for
> hardware-wrapped inline encryption keys to the block layer and fscrypt
> (https://lore.kernel.org/linux-block/20221216203636.81491-1-ebiggers@kernel.org/),
> which this patchset is based on, is 'lt_key' for a longterm wrapped key and
> 'eph_key' for an ephemerally-wrapped key.
> 

Excellent, using familiar names is good!

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

* RE: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-07-20  2:55 ` [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Eric Biggers
@ 2023-08-01 17:31   ` Gaurav Kashyap (QUIC)
  2023-08-10  5:36     ` Eric Biggers
  0 siblings, 1 reply; 36+ messages in thread
From: Gaurav Kashyap (QUIC) @ 2023-08-01 17:31 UTC (permalink / raw)
  To: Eric Biggers
  Cc: linux-scsi, linux-arm-msm, linux-mmc, linux-block, linux-fscrypt,
	Om Prakash Singh, Prasad Sodagudi (QUIC), Arun Menon (SSG),
	abel.vesa, Seshu Madhavi Puppala (QUIC)

Hey Eric, thanks for your reply. Pleasure working with you again.

Please find answers inline

-----Original Message-----
From: Eric Biggers <ebiggers@kernel.org> 
Sent: Wednesday, July 19, 2023 7:56 PM
To: Gaurav Kashyap (QUIC) <quic_gaurkash@quicinc.com>
Cc: linux-scsi@vger.kernel.org; linux-arm-msm@vger.kernel.org; linux-mmc@vger.kernel.org; linux-block@vger.kernel.org; linux-fscrypt@vger.kernel.org; Om Prakash Singh <omprsing@qti.qualcomm.com>; Prasad Sodagudi (QUIC) <quic_psodagud@quicinc.com>; Arun Menon (SSG) <avmenon@quicinc.com>; abel.vesa@linaro.org; Seshu Madhavi Puppala (QUIC) <quic_spuppala@quicinc.com>
Subject: Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs

Hi Gaurav,

On Wed, Jul 19, 2023 at 10:04:14AM -0700, Gaurav Kashyap wrote:
> These patches add support to Qualcomm ICE (Inline Crypto Enginr) for 
> hardware wrapped keys using Qualcomm Hardware Key Manager (HWKM) and 
> are made on top of a rebased version  Eric Bigger's set of changes to 
> support wrapped keys in fscrypt and block below:
> https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-key
> s-v7 (The rebased patches are not uploaded here)
> 
> Ref v1 here:
> https://lore.kernel.org/linux-scsi/20211206225725.77512-1-quic_gaurkas
> h@quicinc.com/
> 
> Explanation and use of hardware-wrapped-keys can be found here:
> Documentation/block/inline-encryption.rst
> 
> This patch is organized as follows:
> 
> Patch 1 - Prepares ICE and storage layers (UFS and EMMC) to pass around wrapped keys.
> Patch 2 - Adds a new SCM api to support deriving software secret when 
> wrapped keys are used Patch 3-4 - Adds support for wrapped keys in the 
> ICE driver. This includes adding HWKM support Patch 5-6 - Adds support 
> for wrapped keys in UFS Patch 7-10 - Supports generate, prepare and 
> import functionality in ICE and UFS
> 
> NOTE: MMC will have similar changes to UFS and will be uploaded in a different patchset
>       Patch 3, 4, 8, 10 will have MMC equivalents.
> 
> Testing:
> Test platform: SM8550 MTP
> Engineering trustzone image is required to test this feature only for 
> SM8550. For SM8650 onwards, all trustzone changes to support this will 
> be part of the released images.
> The engineering changes primarily contain hooks to generate, import 
> and prepare keys for HW wrapped disk encryption.
> 
> The changes were tested by mounting initramfs and running the 
> fscryptctl tool (Ref: 
> https://github.com/ebiggers/fscryptctl/tree/wip-wrapped-keys) to 
> generate and prepare keys, as well as to set policies on folders, which consequently invokes disk encryption flows through UFS.
> 
> Gaurav Kashyap (10):
>   ice, ufs, mmc: use blk_crypto_key for program_key
>   qcom_scm: scm call for deriving a software secret
>   soc: qcom: ice: add hwkm support in ice
>   soc: qcom: ice: support for hardware wrapped keys
>   ufs: core: support wrapped keys in ufs core
>   ufs: host: wrapped keys support in ufs qcom
>   qcom_scm: scm call for create, prepare and import keys
>   ufs: core: add support for generate, import and prepare keys
>   soc: qcom: support for generate, import and prepare key
>   ufs: host: support for generate, import and prepare key
> 
>  drivers/firmware/qcom_scm.c            | 292 +++++++++++++++++++++++
>  drivers/firmware/qcom_scm.h            |   4 +
>  drivers/mmc/host/cqhci-crypto.c        |   7 +-
>  drivers/mmc/host/cqhci.h               |   2 +
>  drivers/mmc/host/sdhci-msm.c           |   6 +-
>  drivers/soc/qcom/ice.c                 | 309 +++++++++++++++++++++++--
>  drivers/ufs/core/ufshcd-crypto.c       |  92 +++++++-
>  drivers/ufs/host/ufs-qcom.c            |  63 ++++-
>  include/linux/firmware/qcom/qcom_scm.h |  13 ++
>  include/soc/qcom/ice.h                 |  18 +-
>  include/ufs/ufshcd.h                   |  25 ++
>  11 files changed, 797 insertions(+), 34 deletions(-)


Thank you for continuing to work on this!

According to your cover letter, this feature requires a custom TrustZone image to work on SM8550.  Will that image be made available outside Qualcomm?
--> Unfortunately, I don't think there is a way to do that. You can still request for one through our customer engineering team like before.

Also according to your cover letter, this feature will work on SM8650 out of the box.  That's great to hear.  However, SM8650 does not appear to be publicly available yet or have any upstream kernel support.  Do you know approximately when a SM8650 development board will become available to the general public?
--> I meant it will be available in the future releases. As of today, I don't have any information on the timelines

Also, can you please make available a git branch somewhere that contains your patchset?  It sounds like this depends on https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7, but actually a version of it that you've rebased, which I don't have access to.
Without being able to apply your patchset, I can't properly review it.
--> As for the fscrypt patches,
      I have not changed much functionally from the v7 patch, just merge conflicts.
      I will update this thread once I figure out a git location.

Thanks!

- Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-08-01 17:31   ` Gaurav Kashyap (QUIC)
@ 2023-08-10  5:36     ` Eric Biggers
  2023-08-11  0:27       ` Gaurav Kashyap (QUIC)
  0 siblings, 1 reply; 36+ messages in thread
From: Eric Biggers @ 2023-08-10  5:36 UTC (permalink / raw)
  To: Gaurav Kashyap (QUIC)
  Cc: linux-scsi, linux-arm-msm, linux-mmc, linux-block, linux-fscrypt,
	Om Prakash Singh, Prasad Sodagudi (QUIC), Arun Menon (SSG),
	abel.vesa, Seshu Madhavi Puppala (QUIC)

On Tue, Aug 01, 2023 at 05:31:59PM +0000, Gaurav Kashyap (QUIC) wrote:
> 
> According to your cover letter, this feature requires a custom TrustZone image to work on SM8550.  Will that image be made available outside Qualcomm?
> --> Unfortunately, I don't think there is a way to do that. You can still request for one through our customer engineering team like before.

I think it's already been shown that that is not a workable approach.

> Also, can you please make available a git branch somewhere that contains your patchset?  It sounds like this depends on https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7, but actually a version of it that you've rebased, which I don't have access to.
> Without being able to apply your patchset, I can't properly review it.
> --> As for the fscrypt patches,
>       I have not changed much functionally from the v7 patch, just merge conflicts.
>       I will update this thread once I figure out a git location.
> 

Any update on this?  Most kernel developers just create a GitHub repo if they
don't have kernel.org access.

- Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* RE: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-08-10  5:36     ` Eric Biggers
@ 2023-08-11  0:27       ` Gaurav Kashyap (QUIC)
  2023-08-11  2:19         ` Bjorn Andersson
  0 siblings, 1 reply; 36+ messages in thread
From: Gaurav Kashyap (QUIC) @ 2023-08-11  0:27 UTC (permalink / raw)
  To: Eric Biggers
  Cc: linux-scsi, linux-arm-msm, linux-mmc, linux-block, linux-fscrypt,
	Om Prakash Singh, Prasad Sodagudi (QUIC), Arun Menon (SSG),
	abel.vesa, Seshu Madhavi Puppala (QUIC)



-----Original Message-----
From: Eric Biggers <ebiggers@kernel.org> 
Sent: Wednesday, August 9, 2023 10:37 PM
To: Gaurav Kashyap (QUIC) <quic_gaurkash@quicinc.com>
Cc: linux-scsi@vger.kernel.org; linux-arm-msm@vger.kernel.org; linux-mmc@vger.kernel.org; linux-block@vger.kernel.org; linux-fscrypt@vger.kernel.org; Om Prakash Singh <omprsing@qti.qualcomm.com>; Prasad Sodagudi (QUIC) <quic_psodagud@quicinc.com>; Arun Menon (SSG) <avmenon@quicinc.com>; abel.vesa@linaro.org; Seshu Madhavi Puppala (QUIC) <quic_spuppala@quicinc.com>
Subject: Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs

On Tue, Aug 01, 2023 at 05:31:59PM +0000, Gaurav Kashyap (QUIC) wrote:
> 
> According to your cover letter, this feature requires a custom TrustZone image to work on SM8550.  Will that image be made available outside Qualcomm?
> --> Unfortunately, I don't think there is a way to do that. You can still request for one through our customer engineering team like before.

I think it's already been shown that that is not a workable approach.

> Also, can you please make available a git branch somewhere that contains your patchset?  It sounds like this depends on https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7, but actually a version of it that you've rebased, which I don't have access to.
> Without being able to apply your patchset, I can't properly review it.
> --> As for the fscrypt patches,
>       I have not changed much functionally from the v7 patch, just merge conflicts.
>       I will update this thread once I figure out a git location.
> 

Any update on this?  Most kernel developers just create a GitHub repo if they don't have kernel.org access.

>> Here are the git links
>> https://github.com/quic-gaurkash/linux/tree/fscrypt
>> https://github.com/quic-gaurkash/linux/tree/wrapped_keys_ice_ufs

- Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-08-11  0:27       ` Gaurav Kashyap (QUIC)
@ 2023-08-11  2:19         ` Bjorn Andersson
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Andersson @ 2023-08-11  2:19 UTC (permalink / raw)
  To: Gaurav Kashyap (QUIC)
  Cc: Eric Biggers, linux-scsi, linux-arm-msm, linux-mmc, linux-block,
	linux-fscrypt, Om Prakash Singh, Prasad Sodagudi (QUIC),
	Arun Menon (SSG), abel.vesa, Seshu Madhavi Puppala (QUIC)

On Fri, Aug 11, 2023 at 12:27:18AM +0000, Gaurav Kashyap (QUIC) wrote:
> 

Gaurav, it is impossible to decode what part of this message is from
Eric and what is from you. You must use a proper email client, and
follow proper etiquette on these mailing lists.

> 
> -----Original Message-----
> From: Eric Biggers <ebiggers@kernel.org> 
> Sent: Wednesday, August 9, 2023 10:37 PM
> To: Gaurav Kashyap (QUIC) <quic_gaurkash@quicinc.com>
> Cc: linux-scsi@vger.kernel.org; linux-arm-msm@vger.kernel.org; linux-mmc@vger.kernel.org; linux-block@vger.kernel.org; linux-fscrypt@vger.kernel.org; Om Prakash Singh <omprsing@qti.qualcomm.com>; Prasad Sodagudi (QUIC) <quic_psodagud@quicinc.com>; Arun Menon (SSG) <avmenon@quicinc.com>; abel.vesa@linaro.org; Seshu Madhavi Puppala (QUIC) <quic_spuppala@quicinc.com>
> Subject: Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
> 
> On Tue, Aug 01, 2023 at 05:31:59PM +0000, Gaurav Kashyap (QUIC) wrote:
> > 
> > According to your cover letter, this feature requires a custom TrustZone image to work on SM8550.  Will that image be made available outside Qualcomm?
> > --> Unfortunately, I don't think there is a way to do that. You can still request for one through our customer engineering team like before.
> 
> I think it's already been shown that that is not a workable approach.
> 

I agree.

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (10 preceding siblings ...)
  2023-07-20  2:55 ` [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Eric Biggers
@ 2023-08-25 10:19 ` Srinivas Kandagatla
  2023-08-25 21:07   ` Eric Biggers
  2023-08-29 21:06 ` Konrad Dybcio
  12 siblings, 1 reply; 36+ messages in thread
From: Srinivas Kandagatla @ 2023-08-25 10:19 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala


On 19/07/2023 18:04, Gaurav Kashyap wrote:
> These patches add support to Qualcomm ICE (Inline Crypto Enginr) for hardware
> wrapped keys using Qualcomm Hardware Key Manager (HWKM) and are made on top
> of a rebased version  Eric Bigger's set of changes to support wrapped keys in
> fscrypt and block below:
> https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7
> (The rebased patches are not uploaded here)
> 
> Ref v1 here:
> https://lore.kernel.org/linux-scsi/20211206225725.77512-1-quic_gaurkash@quicinc.com/
> 
> Explanation and use of hardware-wrapped-keys can be found here:
> Documentation/block/inline-encryption.rst
> 
> This patch is organized as follows:
> 
> Patch 1 - Prepares ICE and storage layers (UFS and EMMC) to pass around wrapped keys.
> Patch 2 - Adds a new SCM api to support deriving software secret when wrapped keys are used
> Patch 3-4 - Adds support for wrapped keys in the ICE driver. This includes adding HWKM support
> Patch 5-6 - Adds support for wrapped keys in UFS
> Patch 7-10 - Supports generate, prepare and import functionality in ICE and UFS
> 
> NOTE: MMC will have similar changes to UFS and will be uploaded in a different patchset
>        Patch 3, 4, 8, 10 will have MMC equivalents.
> 
> Testing:
> Test platform: SM8550 MTP
> Engineering trustzone image is required to test this feature only
> for SM8550. For SM8650 onwards, all trustzone changes to support this
> will be part of the released images.

AFAIU, Prior to these proposed changes in scm, HWKM was done with help 
of TA(Trusted Application) for generate, import, unwrap ... functionality.

1. What is the reason for moving this from TA to new smc calls?

Is this because of missing smckinvoke support in upstream?

How scalable is this approach? Are we going to add new sec sys calls to 
every interface to TA?

2. How are the older SoCs going to deal with this, given that you are 
changing drivers that are common across these?

Have you tested these patches on any older platforms?

What happens if someone want to add support to wrapped keys to this 
platforms in upstream, How is that going to be handled?

As I understand with this, we will endup with two possible solutions 
over time in upstream.


thanks,
--srini

> The engineering changes primarily contain hooks to generate, import and
> prepare keys for HW wrapped disk encryption.
> 
> The changes were tested by mounting initramfs and running the fscryptctl
> tool (Ref: https://github.com/ebiggers/fscryptctl/tree/wip-wrapped-keys) to
> generate and prepare keys, as well as to set policies on folders, which
> consequently invokes disk encryption flows through UFS.
> 
> Gaurav Kashyap (10):
>    ice, ufs, mmc: use blk_crypto_key for program_key
>    qcom_scm: scm call for deriving a software secret
>    soc: qcom: ice: add hwkm support in ice
>    soc: qcom: ice: support for hardware wrapped keys
>    ufs: core: support wrapped keys in ufs core
>    ufs: host: wrapped keys support in ufs qcom
>    qcom_scm: scm call for create, prepare and import keys
>    ufs: core: add support for generate, import and prepare keys
>    soc: qcom: support for generate, import and prepare key
>    ufs: host: support for generate, import and prepare key
> 
>   drivers/firmware/qcom_scm.c            | 292 +++++++++++++++++++++++
>   drivers/firmware/qcom_scm.h            |   4 +
>   drivers/mmc/host/cqhci-crypto.c        |   7 +-
>   drivers/mmc/host/cqhci.h               |   2 +
>   drivers/mmc/host/sdhci-msm.c           |   6 +-
>   drivers/soc/qcom/ice.c                 | 309 +++++++++++++++++++++++--
>   drivers/ufs/core/ufshcd-crypto.c       |  92 +++++++-
>   drivers/ufs/host/ufs-qcom.c            |  63 ++++-
>   include/linux/firmware/qcom/qcom_scm.h |  13 ++
>   include/soc/qcom/ice.h                 |  18 +-
>   include/ufs/ufshcd.h                   |  25 ++
>   11 files changed, 797 insertions(+), 34 deletions(-)
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-08-25 10:19 ` Srinivas Kandagatla
@ 2023-08-25 21:07   ` Eric Biggers
  2023-08-29 17:11     ` Srinivas Kandagatla
  2023-09-12 10:06     ` Srinivas Kandagatla
  0 siblings, 2 replies; 36+ messages in thread
From: Eric Biggers @ 2023-08-25 21:07 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala

Hi Srinivas,

On Fri, Aug 25, 2023 at 11:19:41AM +0100, Srinivas Kandagatla wrote:
> 
> On 19/07/2023 18:04, Gaurav Kashyap wrote:
> > These patches add support to Qualcomm ICE (Inline Crypto Enginr) for hardware
> > wrapped keys using Qualcomm Hardware Key Manager (HWKM) and are made on top
> > of a rebased version  Eric Bigger's set of changes to support wrapped keys in
> > fscrypt and block below:
> > https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7
> > (The rebased patches are not uploaded here)
> > 
> > Ref v1 here:
> > https://lore.kernel.org/linux-scsi/20211206225725.77512-1-quic_gaurkash@quicinc.com/
> > 
> > Explanation and use of hardware-wrapped-keys can be found here:
> > Documentation/block/inline-encryption.rst
> > 
> > This patch is organized as follows:
> > 
> > Patch 1 - Prepares ICE and storage layers (UFS and EMMC) to pass around wrapped keys.
> > Patch 2 - Adds a new SCM api to support deriving software secret when wrapped keys are used
> > Patch 3-4 - Adds support for wrapped keys in the ICE driver. This includes adding HWKM support
> > Patch 5-6 - Adds support for wrapped keys in UFS
> > Patch 7-10 - Supports generate, prepare and import functionality in ICE and UFS
> > 
> > NOTE: MMC will have similar changes to UFS and will be uploaded in a different patchset
> >        Patch 3, 4, 8, 10 will have MMC equivalents.
> > 
> > Testing:
> > Test platform: SM8550 MTP
> > Engineering trustzone image is required to test this feature only
> > for SM8550. For SM8650 onwards, all trustzone changes to support this
> > will be part of the released images.
> 
> AFAIU, Prior to these proposed changes in scm, HWKM was done with help of
> TA(Trusted Application) for generate, import, unwrap ... functionality.
> 
> 1. What is the reason for moving this from TA to new smc calls?
> 
> Is this because of missing smckinvoke support in upstream?
> 
> How scalable is this approach? Are we going to add new sec sys calls to
> every interface to TA?
> 
> 2. How are the older SoCs going to deal with this, given that you are
> changing drivers that are common across these?
> 
> Have you tested these patches on any older platforms?
> 
> What happens if someone want to add support to wrapped keys to this
> platforms in upstream, How is that going to be handled?
> 
> As I understand with this, we will endup with two possible solutions over
> time in upstream.

It's true that Qualcomm based Android devices already use HW-wrapped keys on
SoCs earlier than SM8650.  The problem is that the key generation, import, and
conversion were added to Android's KeyMint HAL, as a quick way to get the
feature out the door when it was needed (so to speak).  Unfortunately this
coupled this feature unnecessarily to the Android KeyMint and the corresponding
(closed source) userspace HAL provided by Qualcomm, which it's not actually
related to.  I'd guess that Qualcomm's closed source userspace HAL makes SMC
calls into Qualcomm's KeyMint TA, but I have no insight into those details.

The new SMC calls eliminate the dependency on the Android-specific KeyMint.
They're also being documented by Qualcomm.  So, as this patchset does, they can
be used by Linux in the implementation of new ioctls which provide a vendor
independent interface to HW-wrapped key generation, import, and conversion.

I think the new approach is the only one that is viable outside the Android
context.  As such, I don't think anyone has any plan to upstream support for
HW-wrapped keys for older Qualcomm SoCs that lack the new interface.

- Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-08-25 21:07   ` Eric Biggers
@ 2023-08-29 17:11     ` Srinivas Kandagatla
  2023-08-29 18:12       ` Eric Biggers
  2023-09-12 10:06     ` Srinivas Kandagatla
  1 sibling, 1 reply; 36+ messages in thread
From: Srinivas Kandagatla @ 2023-08-29 17:11 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala



On 25/08/2023 22:07, Eric Biggers wrote:
> Hi Srinivas,
> 
> On Fri, Aug 25, 2023 at 11:19:41AM +0100, Srinivas Kandagatla wrote:
>>
>> On 19/07/2023 18:04, Gaurav Kashyap wrote:
>>> These patches add support to Qualcomm ICE (Inline Crypto Enginr) for hardware
>>> wrapped keys using Qualcomm Hardware Key Manager (HWKM) and are made on top
>>> of a rebased version  Eric Bigger's set of changes to support wrapped keys in
>>> fscrypt and block below:
>>> https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7
>>> (The rebased patches are not uploaded here)
>>>
>>> Ref v1 here:
>>> https://lore.kernel.org/linux-scsi/20211206225725.77512-1-quic_gaurkash@quicinc.com/
>>>
>>> Explanation and use of hardware-wrapped-keys can be found here:
>>> Documentation/block/inline-encryption.rst
>>>
>>> This patch is organized as follows:
>>>
>>> Patch 1 - Prepares ICE and storage layers (UFS and EMMC) to pass around wrapped keys.
>>> Patch 2 - Adds a new SCM api to support deriving software secret when wrapped keys are used
>>> Patch 3-4 - Adds support for wrapped keys in the ICE driver. This includes adding HWKM support
>>> Patch 5-6 - Adds support for wrapped keys in UFS
>>> Patch 7-10 - Supports generate, prepare and import functionality in ICE and UFS
>>>
>>> NOTE: MMC will have similar changes to UFS and will be uploaded in a different patchset
>>>         Patch 3, 4, 8, 10 will have MMC equivalents.
>>>
>>> Testing:
>>> Test platform: SM8550 MTP
>>> Engineering trustzone image is required to test this feature only
>>> for SM8550. For SM8650 onwards, all trustzone changes to support this
>>> will be part of the released images.
>>
>> AFAIU, Prior to these proposed changes in scm, HWKM was done with help of
>> TA(Trusted Application) for generate, import, unwrap ... functionality.
>>
>> 1. What is the reason for moving this from TA to new smc calls?
>>
>> Is this because of missing smckinvoke support in upstream?
>>
>> How scalable is this approach? Are we going to add new sec sys calls to
>> every interface to TA?
>>
>> 2. How are the older SoCs going to deal with this, given that you are
>> changing drivers that are common across these?
>>
>> Have you tested these patches on any older platforms?
>>
>> What happens if someone want to add support to wrapped keys to this
>> platforms in upstream, How is that going to be handled?
>>
>> As I understand with this, we will endup with two possible solutions over
>> time in upstream.
> 
> It's true that Qualcomm based Android devices already use HW-wrapped keys on
> SoCs earlier than SM8650.  The problem is that the key generation, import, and
> conversion were added to Android's KeyMint HAL, as a quick way to get the
> feature out the door when it was needed (so to speak).  Unfortunately this

There is an attempt in 2021 todo exactly same thing I guess,

https://patchwork.kernel.org/project/linux-fscrypt/cover/20211206225725.77512-1-quic_gaurkash@quicinc.com/

If this was the right thing to do they why is the TZ firmware on SoCs 
after 2021 not having support for this ?

> coupled this feature unnecessarily to the Android KeyMint and the corresponding
> (closed source) userspace HAL provided by Qualcomm, which it's not actually

So how does Andriod kernel upgrades work after applying this patchset on 
platforms like SM8550 or SM8450 or SM8250..or any old platforms.

> related to.  I'd guess that Qualcomm's closed source userspace HAL makes SMC
> calls into Qualcomm's KeyMint TA, but I have no insight into those details.
> 
If we have an smcinvoke tee driver we can talk to to this TA.

> The new SMC calls eliminate the dependency on the Android-specific KeyMint.

I can see that.

Am not against adding this new interface, but is this new interface 
leaving a gap for older platforms?


Is there any other technical reason for moving out from TA based to a 
smc calls?

And are we doing a quick solution here to fix something


> They're also being documented by Qualcomm.  So, as this patchset does, they can
> be used by Linux in the implementation of new ioctls which provide a vendor
> independent interface to HW-wrapped key generation, import, and conversion.
> 
> I think the new approach is the only one that is viable outside the Android
> context.  As such, I don't think anyone has any plan to upstream support for
> HW-wrapped keys for older Qualcomm SoCs that lack the new interface.

AFAIU, There are other downstream Qualcomm LE platforms that use wrapped 
key support with the older interface.
What happens to them whey then upgrade the kernel?

Does TA interface still continue to work with the changes that went into 
common drivers (ufs/sd)?

--srini

> 
> - Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-08-29 17:11     ` Srinivas Kandagatla
@ 2023-08-29 18:12       ` Eric Biggers
  2023-08-30 10:00         ` Srinivas Kandagatla
  0 siblings, 1 reply; 36+ messages in thread
From: Eric Biggers @ 2023-08-29 18:12 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala

Hi Srinivas,

On Tue, Aug 29, 2023 at 06:11:55PM +0100, Srinivas Kandagatla wrote:
> > It's true that Qualcomm based Android devices already use HW-wrapped keys on
> > SoCs earlier than SM8650.  The problem is that the key generation, import, and
> > conversion were added to Android's KeyMint HAL, as a quick way to get the
> > feature out the door when it was needed (so to speak).  Unfortunately this
> 
> There is an attempt in 2021 todo exactly same thing I guess,
> 
> https://patchwork.kernel.org/project/linux-fscrypt/cover/20211206225725.77512-1-quic_gaurkash@quicinc.com/
> 
> If this was the right thing to do they why is the TZ firmware on SoCs after
> 2021 not having support for this ?

That's on Qualcomm.  But my understanding is that it's just taking them several
years to get the TZ changes out due to their branching schedule.  Garauv
submitted the TZ changes in 2021, but apparently SM8550 had already branched at
that point, so SM8650 is the first one that will have it.

Just because it takes Qualcomm a while to get the firmware support for this
feature deployed doesn't mean that it's the wrong approach.

> 
> > coupled this feature unnecessarily to the Android KeyMint and the corresponding
> > (closed source) userspace HAL provided by Qualcomm, which it's not actually
> 
> So how does Andriod kernel upgrades work after applying this patchset on
> platforms like SM8550 or SM8450 or SM8250..or any old platforms.

The same way they did before.  Older devices won't use this new code.

BTW, this is irrelevant for upstream.

> 
> > related to.  I'd guess that Qualcomm's closed source userspace HAL makes SMC
> > calls into Qualcomm's KeyMint TA, but I have no insight into those details.
> > 
> If we have an smcinvoke tee driver we can talk to to this TA.
> 
> > The new SMC calls eliminate the dependency on the Android-specific KeyMint.
> 
> I can see that.
> 
> Am not against adding this new interface, but is this new interface leaving
> a gap for older platforms?
> 
> 
> Is there any other technical reason for moving out from TA based to a smc
> calls?
> 
> And are we doing a quick solution here to fix something

I have very little insight into Qualcomm's old interface, which is tied to the
Android-specific KeyMint and is not known to be usable outside the Android
context or without the closed source userspace HAL from Qualcomm.

I understand that Linux kernel features that are only usable with closed source
userspace libraries are heavily frowned on.  As are features that are tied to
Android and cannot be used on other Linux distros.

If Qualcomm can document the old interface and show that it's usable directly by
the Linux kernel, then we could consider it.  But without that, the new
interface is our only option.

> > They're also being documented by Qualcomm.  So, as this patchset does, they can
> > be used by Linux in the implementation of new ioctls which provide a vendor
> > independent interface to HW-wrapped key generation, import, and conversion.
> > 
> > I think the new approach is the only one that is viable outside the Android
> > context.  As such, I don't think anyone has any plan to upstream support for
> > HW-wrapped keys for older Qualcomm SoCs that lack the new interface.
> 
> AFAIU, There are other downstream Qualcomm LE platforms that use wrapped key
> support with the older interface.
> What happens to them whey then upgrade the kernel?
> 
> Does TA interface still continue to work with the changes that went into
> common drivers (ufs/sd)?

This is a strange line of questioning for upstream review, as this feature does
not exist upstream.  This is the first time it will be supported by upstream
Linux, ever.  Adding support for this feature does not break anything.

Downstream users who implemented a less well designed version of this feature
can continue to use their existing code.

BTW, I am the person who has gotten stuck maintaining the framework for
HW-wrapped key support in the Android Common Kernels...  So if you're trying to
make things "easier" for me, please don't.  I want to have a properly designed
version of the feature upstream, and then I'll change Android to use that
whenever possible.  That's the only real long-term solution.

- Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (11 preceding siblings ...)
  2023-08-25 10:19 ` Srinivas Kandagatla
@ 2023-08-29 21:06 ` Konrad Dybcio
  12 siblings, 0 replies; 36+ messages in thread
From: Konrad Dybcio @ 2023-08-29 21:06 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala



On 19.07.2023 19:04, Gaurav Kashyap wrote:
> These patches add support to Qualcomm ICE (Inline Crypto Enginr) for hardware
> wrapped keys using Qualcomm Hardware Key Manager (HWKM) and are made on top
> of a rebased version  Eric Bigger's set of changes to support wrapped keys in
> fscrypt and block below:
> https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7
> (The rebased patches are not uploaded here)
Please make sure to also CC maintainers of the related subsystems.

I recommend using the b4 tool [1], which takes care of this and similar
issues.

[1] https://b4.docs.kernel.org/en/latest/index.html

Konrad

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-08-29 18:12       ` Eric Biggers
@ 2023-08-30 10:00         ` Srinivas Kandagatla
  2023-08-30 16:12           ` Eric Biggers
  0 siblings, 1 reply; 36+ messages in thread
From: Srinivas Kandagatla @ 2023-08-30 10:00 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala

Hi Eric,

On 29/08/2023 19:12, Eric Biggers wrote:
> 
>>> They're also being documented by Qualcomm.  So, as this patchset does, they can
>>> be used by Linux in the implementation of new ioctls which provide a vendor
>>> independent interface to HW-wrapped key generation, import, and conversion.
>>>
>>> I think the new approach is the only one that is viable outside the Android
>>> context.  As such, I don't think anyone has any plan to upstream support for
>>> HW-wrapped keys for older Qualcomm SoCs that lack the new interface.
>> AFAIU, There are other downstream Qualcomm LE platforms that use wrapped key
>> support with the older interface.
>> What happens to them whey then upgrade the kernel?
>>
>> Does TA interface still continue to work with the changes that went into
>> common drivers (ufs/sd)?
> This is a strange line of questioning for upstream review, as this feature does
> not exist upstream.  This is the first time it will be supported by upstream
> Linux, ever.  Adding support for this feature does not break anything.
These are not unusual questions, what am trying to understand here is 
below questions for better context, big picture and review/test. At the 
end of the day we all want to get these features available in upstream.

1. How backward compatibility of this wrapped key support. I guess the 
answer is NO.

2. secondly reasons behind this change. Am still not really convinced 
with the current technical reasoning to shift from TA based approach to 
this. But I guess this is all done to dump the closed source userspace 
thingy. Am hoping that this can be made available to other older SoCs at 
some point in time.

3. We are adding these apis/callbacks in common code without doing any 
compatible or SoC checks. Is this going to be a issue if someone tries 
fscrypt?

--srini

> 
> Downstream users who implemented a less well designed version of this feature
> can continue to use their existing code.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-08-30 10:00         ` Srinivas Kandagatla
@ 2023-08-30 16:12           ` Eric Biggers
  2023-08-30 16:44             ` Srinivas Kandagatla
  0 siblings, 1 reply; 36+ messages in thread
From: Eric Biggers @ 2023-08-30 16:12 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala

On Wed, Aug 30, 2023 at 11:00:07AM +0100, Srinivas Kandagatla wrote:
> 
> 3. We are adding these apis/callbacks in common code without doing any
> compatible or SoC checks. Is this going to be a issue if someone tries
> fscrypt?

ufs-qcom only declares support for wrapped keys if it's supported.  See patch 5
of this series:

+	if (qcom_ice_hwkm_supported(host->ice))
+		hba->quirks |= UFSHCD_QUIRK_USES_WRAPPED_CRYPTO_KEYS;

That in turn uses:

+bool qcom_ice_hwkm_supported(struct qcom_ice *ice)
+{
+	return (ice->hwkm_version > 0);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_hwkm_supported);

Which in turn comes from the ICE version being >= 3.2.  It does seem a bit
suspicious; it probably should check for both the ICE version and the
availability of QCOM_SCM_ES_GENERATE_ICE_KEY, QCOM_SCM_ES_PREPARE_ICE_KEY, and
QCOM_SCM_ES_IMPORT_ICE_KEY.  Regardless, it sounds like you want it to be
determined by something set in the device tree instead?  I don't think it's been
demonstrated that that's necessary.  If we can detect the hardware capabilities
dynamically, we should do that, right?

- Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-08-30 16:12           ` Eric Biggers
@ 2023-08-30 16:44             ` Srinivas Kandagatla
  0 siblings, 0 replies; 36+ messages in thread
From: Srinivas Kandagatla @ 2023-08-30 16:44 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala



On 30/08/2023 17:12, Eric Biggers wrote:
> On Wed, Aug 30, 2023 at 11:00:07AM +0100, Srinivas Kandagatla wrote:
>>
>> 3. We are adding these apis/callbacks in common code without doing any
>> compatible or SoC checks. Is this going to be a issue if someone tries
>> fscrypt?
> 
> ufs-qcom only declares support for wrapped keys if it's supported.  See patch 5
> of this series:
> 
> +	if (qcom_ice_hwkm_supported(host->ice))
> +		hba->quirks |= UFSHCD_QUIRK_USES_WRAPPED_CRYPTO_KEYS;
> 
> That in turn uses:
> 
> +bool qcom_ice_hwkm_supported(struct qcom_ice *ice)
> +{
> +	return (ice->hwkm_version > 0);
> +}
> +EXPORT_SYMBOL_GPL(qcom_ice_hwkm_supported);
> 
> Which in turn comes from the ICE version being >= 3.2.  It does seem a bit
> suspicious; it probably should check for both the ICE version and the
> availability of QCOM_SCM_ES_GENERATE_ICE_KEY, QCOM_SCM_ES_PREPARE_ICE_KEY, and
> QCOM_SCM_ES_IMPORT_ICE_KEY.  Regardless, it sounds like you want it to be
> determined by something set in the device tree instead?  I don't think it's been
> demonstrated that that's necessary.  If we can detect the hardware capabilities
> dynamically, we should do that, right?

I don't mind either way.

It would be perfect if we can dynamically query the TZ version to 
determine these capabilities.


If not we are left with some way to derive that information either via 
DT or other means.

--srini
> 
> - Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 03/10] soc: qcom: ice: add hwkm support in ice
  2023-07-19 17:04 ` [PATCH v2 03/10] soc: qcom: ice: add hwkm support in ice Gaurav Kashyap
@ 2023-08-31  8:39   ` Neil Armstrong
  0 siblings, 0 replies; 36+ messages in thread
From: Neil Armstrong @ 2023-08-31  8:39 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala

Hi,

On 19/07/2023 19:04, Gaurav Kashyap wrote:
> Qualcomm's ICE (Inline Crypto Engine) contains a proprietary
> key management hardware called Hardware Key Manager (HWKM).
> This patch integrates HWKM support in ICE when it is
> available. HWKM primarily provides hardware wrapped key support
> where the ICE (storage) keys are not available in software and
> protected in hardware.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> ---
>   drivers/soc/qcom/ice.c | 112 ++++++++++++++++++++++++++++++++++++++++-
>   include/soc/qcom/ice.h |   1 +
>   2 files changed, 112 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
> index d19f674bb1b6..242306d13049 100644
> --- a/drivers/soc/qcom/ice.c
> +++ b/drivers/soc/qcom/ice.c
> @@ -24,6 +24,18 @@
>   #define QCOM_ICE_REG_FUSE_SETTING		0x0010
>   #define QCOM_ICE_REG_BIST_STATUS		0x0070
>   #define QCOM_ICE_REG_ADVANCED_CONTROL		0x1000
> +#define QCOM_ICE_REG_CONTROL			0x0
> +/* QCOM ICE HWKM registers */
> +#define QCOM_ICE_REG_HWKM_TZ_KM_CTL		0x1000
> +#define QCOM_ICE_REG_HWKM_TZ_KM_STATUS		0x1004
> +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_0		0x5000
> +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_1		0x5004
> +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_2		0x5008
> +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_3		0x500C
> +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_4		0x5010
> +
> +#define QCOM_ICE_HWKM_BIST_DONE_V1_VAL		0x11
> +#define QCOM_ICE_HWKM_BIST_DONE_V2_VAL		0x287
>   
>   /* BIST ("built-in self-test") status flags */
>   #define QCOM_ICE_BIST_STATUS_MASK		GENMASK(31, 28)
> @@ -32,6 +44,9 @@
>   #define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK	0x2
>   #define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK	0x4
>   
> +#define QCOM_ICE_HWKM_REG_OFFSET	0x8000
> +#define HWKM_OFFSET(reg)		(reg + QCOM_ICE_HWKM_REG_OFFSET)

The current upstream ICE memory region is only 0x8000, so you should
probably check the memory region size before enabling HWKM otherwise
you'll access unmapped memory for non-updated DT.

Neil

> +
>   #define qcom_ice_writel(engine, val, reg)	\
>   	writel((val), (engine)->base + (reg))
>   
> @@ -44,6 +59,7 @@ struct qcom_ice {
>   	struct device_link *link;
>   
>   	struct clk *core_clk;
> +	u8 hwkm_version;
>   };
>   
>   static bool qcom_ice_check_supported(struct qcom_ice *ice)
> @@ -61,8 +77,20 @@ static bool qcom_ice_check_supported(struct qcom_ice *ice)
>   		return false;
>   	}
>   
> +	if ((major >= 4) || ((major == 3) && (minor == 2) && (step >= 1)))
> +		ice->hwkm_version = 2;
> +	else if ((major == 3) && (minor == 2))
> +		ice->hwkm_version = 1;
> +	else
> +		ice->hwkm_version = 0;
> +
>   	dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n",
>   		 major, minor, step);
> +	if (!ice->hwkm_version)
> +		dev_info(dev, "QC ICE HWKM (Hardware Key Manager) not supported");
> +	else
> +		dev_info(dev, "QC ICE HWKM (Hardware Key Manager) version = %d",
> +			 ice->hwkm_version);
>   
>   	/* If fuses are blown, ICE might not work in the standard way. */
>   	regval = qcom_ice_readl(ice, QCOM_ICE_REG_FUSE_SETTING);
> @@ -111,10 +139,14 @@ static void qcom_ice_optimization_enable(struct qcom_ice *ice)
>    * fails, so we needn't do it in software too, and (c) properly testing
>    * storage encryption requires testing the full storage stack anyway,
>    * and not relying on hardware-level self-tests.
> + *
> + * However, we still care about if HWKM BIST failed (when supported) as
> + * important functionality would fail later, so disable hwkm on failure.
>    */
>   static int qcom_ice_wait_bist_status(struct qcom_ice *ice)
>   {
>   	u32 regval;
> +	u32 bist_done_val;
>   	int err;
>   
>   	err = readl_poll_timeout(ice->base + QCOM_ICE_REG_BIST_STATUS,
> @@ -123,15 +155,87 @@ static int qcom_ice_wait_bist_status(struct qcom_ice *ice)
>   	if (err)
>   		dev_err(ice->dev, "Timed out waiting for ICE self-test to complete\n");
>   
> +	if (ice->hwkm_version) {
> +		bist_done_val = (ice->hwkm_version == 1) ?
> +				 QCOM_ICE_HWKM_BIST_DONE_V1_VAL :
> +				 QCOM_ICE_HWKM_BIST_DONE_V2_VAL;
> +		if (qcom_ice_readl(ice,
> +				   HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_STATUS)) !=
> +				   bist_done_val) {
> +			dev_warn(ice->dev, "HWKM BIST error\n");
> +			ice->hwkm_version = 0;
> +		}
> +	}
>   	return err;
>   }
>   
> +static void qcom_ice_enable_standard_mode(struct qcom_ice *ice)
> +{
> +	u32 val = 0;
> +
> +	if (!ice->hwkm_version)
> +		return;
> +
> +	/*
> +         * When ICE is in standard (hwkm) mode, it supports HW wrapped
> +         * keys, and when it is in legacy mode, it only supports standard
> +         * (non HW wrapped) keys.
> +         *
> +	 * Put ICE in standard mode, ICE defaults to legacy mode.
> +	 * Legacy mode - ICE HWKM slave not supported.
> +	 * Standard mode - ICE HWKM slave supported.
> +	 *
> +	 * Depending on the version of HWKM, it is controlled by different
> +	 * registers in ICE.
> +	 */
> +	if (ice->hwkm_version >= 2) {
> +		val = qcom_ice_readl(ice, QCOM_ICE_REG_CONTROL);
> +		val = val & 0xFFFFFFFE;
> +		qcom_ice_writel(ice, val, QCOM_ICE_REG_CONTROL);
> +	} else {
> +		qcom_ice_writel(ice, 0x7,
> +				HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_CTL));
> +	}
> +}
> +
> +static void qcom_ice_hwkm_init(struct qcom_ice *ice)
> +{
> +	if (!ice->hwkm_version)
> +		return;
> +
> +	/*
> +	 * Give register bank of the HWKM slave access to read and modify
> +	 * the keyslots in ICE HWKM slave. Without this, trustzone will not
> +	 * be able to program keys into ICE.
> +	 */
> +	qcom_ice_writel(ice, 0xFFFFFFFF,
> +			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_0));
> +	qcom_ice_writel(ice, 0xFFFFFFFF,
> +			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_1));
> +	qcom_ice_writel(ice, 0xFFFFFFFF,
> +			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_2));
> +	qcom_ice_writel(ice, 0xFFFFFFFF,
> +			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_3));
> +	qcom_ice_writel(ice, 0xFFFFFFFF,
> +			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_4));
> +}
> +
>   int qcom_ice_enable(struct qcom_ice *ice)
>   {
> +	int err;
> +
>   	qcom_ice_low_power_mode_enable(ice);
>   	qcom_ice_optimization_enable(ice);
>   
> -	return qcom_ice_wait_bist_status(ice);
> +	qcom_ice_enable_standard_mode(ice);
> +
> +	err = qcom_ice_wait_bist_status(ice);
> +	if (err)
> +		return err;
> +
> +	qcom_ice_hwkm_init(ice);
> +
> +	return err;
>   }
>   EXPORT_SYMBOL_GPL(qcom_ice_enable);
>   
> @@ -203,6 +307,12 @@ int qcom_ice_evict_key(struct qcom_ice *ice, int slot)
>   }
>   EXPORT_SYMBOL_GPL(qcom_ice_evict_key);
>   
> +bool qcom_ice_hwkm_supported(struct qcom_ice *ice)
> +{
> +	return (ice->hwkm_version > 0);
> +}
> +EXPORT_SYMBOL_GPL(qcom_ice_hwkm_supported);
> +
>   static struct qcom_ice *qcom_ice_create(struct device *dev,
>   					void __iomem *base)
>   {
> diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
> index 9dd835dba2a7..1f52e82e3e1c 100644
> --- a/include/soc/qcom/ice.h
> +++ b/include/soc/qcom/ice.h
> @@ -34,5 +34,6 @@ int qcom_ice_program_key(struct qcom_ice *ice,
>   			 const struct blk_crypto_key *bkey,
>   			 u8 data_unit_size, int slot);
>   int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
> +bool qcom_ice_hwkm_supported(struct qcom_ice *ice);
>   struct qcom_ice *of_qcom_ice_get(struct device *dev);
>   #endif /* __QCOM_ICE_H__ */


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 04/10] soc: qcom: ice: support for hardware wrapped keys
  2023-07-19 17:04 ` [PATCH v2 04/10] soc: qcom: ice: support for hardware wrapped keys Gaurav Kashyap
@ 2023-08-31  9:10   ` Neil Armstrong
  0 siblings, 0 replies; 36+ messages in thread
From: Neil Armstrong @ 2023-08-31  9:10 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-scsi, linux-arm-msm, ebiggers
  Cc: linux-mmc, linux-block, linux-fscrypt, omprsing, quic_psodagud,
	avmenon, abel.vesa, quic_spuppala

Hi,

On 19/07/2023 19:04, Gaurav Kashyap wrote:
> Now that HWKM support is added to ICE, extend the ICE
> driver to support hardware wrapped keys programming coming
> in from the storage controllers (ufs and emmc). The patches that follow
> will add ufs and emmc support.
> 
> Derive software secret support is also added by forwarding the
> call the corresponding scm api.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> ---
>   drivers/soc/qcom/ice.c | 121 +++++++++++++++++++++++++++++++++++++----
>   include/soc/qcom/ice.h |   4 ++
>   2 files changed, 114 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
> index 242306d13049..33f67fcfa1bc 100644
> --- a/drivers/soc/qcom/ice.c
> +++ b/drivers/soc/qcom/ice.c
> @@ -25,6 +25,8 @@
>   #define QCOM_ICE_REG_BIST_STATUS		0x0070
>   #define QCOM_ICE_REG_ADVANCED_CONTROL		0x1000
>   #define QCOM_ICE_REG_CONTROL			0x0
> +#define QCOM_ICE_LUT_KEYS_CRYPTOCFG_R16		0x4040
> +
>   /* QCOM ICE HWKM registers */
>   #define QCOM_ICE_REG_HWKM_TZ_KM_CTL		0x1000
>   #define QCOM_ICE_REG_HWKM_TZ_KM_STATUS		0x1004
> @@ -34,6 +36,7 @@
>   #define QCOM_ICE_REG_HWKM_BANK0_BBAC_3		0x500C
>   #define QCOM_ICE_REG_HWKM_BANK0_BBAC_4		0x5010
>   
> +/* QCOM ICE HWKM BIST vals */
>   #define QCOM_ICE_HWKM_BIST_DONE_V1_VAL		0x11
>   #define QCOM_ICE_HWKM_BIST_DONE_V2_VAL		0x287
>   
> @@ -44,6 +47,8 @@
>   #define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK	0x2
>   #define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK	0x4
>   
> +#define QCOM_ICE_LUT_KEYS_CRYPTOCFG_OFFSET	0x80
> +
>   #define QCOM_ICE_HWKM_REG_OFFSET	0x8000
>   #define HWKM_OFFSET(reg)		(reg + QCOM_ICE_HWKM_REG_OFFSET)
>   
> @@ -60,6 +65,17 @@ struct qcom_ice {
>   
>   	struct clk *core_clk;
>   	u8 hwkm_version;
> +	bool hwkm_init_complete;
> +};
> +
> +union crypto_cfg {
> +	__le32 regval;
> +	struct {
> +		u8 dusize;
> +		u8 capidx;
> +		u8 reserved;
> +		u8 cfge;
> +	};
>   };
>   
>   static bool qcom_ice_check_supported(struct qcom_ice *ice)
> @@ -218,6 +234,8 @@ static void qcom_ice_hwkm_init(struct qcom_ice *ice)
>   			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_3));
>   	qcom_ice_writel(ice, 0xFFFFFFFF,
>   			HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_4));
> +
> +	ice->hwkm_init_complete = true;
>   }
>   
>   int qcom_ice_enable(struct qcom_ice *ice)
> @@ -263,6 +281,52 @@ int qcom_ice_suspend(struct qcom_ice *ice)
>   }
>   EXPORT_SYMBOL_GPL(qcom_ice_suspend);
>   
> +/*
> + * HW dictates the internal mapping between the ICE and HWKM slots,
> + * which are different for different versions, make the translation
> + * here.
> +*/
> +static int translate_hwkm_slot(struct qcom_ice *ice, int slot)
> +{
> +	return (ice->hwkm_version == 1) ?
> +	       (10 + slot * 2) : (slot * 2);
> +}
> +
> +static int qcom_ice_program_wrapped_key(struct qcom_ice *ice,
> +					const struct blk_crypto_key *key,
> +					u8 data_unit_size, int slot)
> +{
> +	int hwkm_slot;
> +	int err;
> +	union crypto_cfg cfg;
> +
> +	hwkm_slot = translate_hwkm_slot(ice, slot);
> +
> +	memset(&cfg, 0, sizeof(cfg));
> +	cfg.dusize = data_unit_size;
> +	cfg.capidx = QCOM_SCM_ICE_CIPHER_AES_256_XTS;
> +	cfg.cfge = 0x80;
> +
> +	/* Clear CFGE */
> +	qcom_ice_writel(ice, 0x0, QCOM_ICE_LUT_KEYS_CRYPTOCFG_R16 +
> +				  QCOM_ICE_LUT_KEYS_CRYPTOCFG_OFFSET * slot);
> +
> +	/* Call trustzone to program the wrapped key using hwkm */
> +	err = qcom_scm_ice_set_key(hwkm_slot, key->raw, key->size,
> +				   QCOM_SCM_ICE_CIPHER_AES_256_XTS, data_unit_size);
> +	if (err) {
> +		pr_err("%s:SCM call Error: 0x%x slot %d\n", __func__, err,
> +		       slot);
> +		return err;
> +	}
> +
> +	/* Enable CFGE after programming key */
> +	qcom_ice_writel(ice, cfg.regval, QCOM_ICE_LUT_KEYS_CRYPTOCFG_R16 +
> +					 QCOM_ICE_LUT_KEYS_CRYPTOCFG_OFFSET * slot);
> +
> +	return err;
> +}
> +
>   int qcom_ice_program_key(struct qcom_ice *ice,
>   			 u8 algorithm_id, u8 key_size,
>   			 const struct blk_crypto_key *bkey,
> @@ -278,24 +342,36 @@ int qcom_ice_program_key(struct qcom_ice *ice,
>   
>   	/* 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) {
> +	    key_size != QCOM_ICE_CRYPTO_KEY_SIZE_256 ||
> +	    key_size != QCOM_ICE_CRYPTO_KEY_SIZE_WRAPPED) {

This should be:
	if (algorithm_id != QCOM_ICE_CRYPTO_ALG_AES_XTS ||
	    (key_size != QCOM_ICE_CRYPTO_KEY_SIZE_256 &&
	     key_size != QCOM_ICE_CRYPTO_KEY_SIZE_WRAPPED)) {

Otherwise it would fail on any key_size value.

Neil

>   		dev_err_ratelimited(dev,
>   				    "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
>   				    algorithm_id, key_size);
>   		return -EINVAL;
>   	}
>   
> -	memcpy(key.bytes, bkey->raw, AES_256_XTS_KEY_SIZE);
> -
> -	/* 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]);
> +	if (bkey->crypto_cfg.key_type == BLK_CRYPTO_KEY_TYPE_HW_WRAPPED) {
> +		if (!ice->hwkm_version)
> +			return -EINVAL;
> +		err = qcom_ice_program_wrapped_key(ice, bkey, slot,
> +						   data_unit_size);
> +	} else {
> +		if (bkey->size != QCOM_ICE_CRYPTO_KEY_SIZE_256)
> +			dev_err_ratelimited(dev,
> +				    "Incorrect key size; bkey->size=%d\n",
> +				    algorithm_id);
> +		return -EINVAL;
> +		memcpy(key.bytes, bkey->raw, AES_256_XTS_KEY_SIZE);
>   
> -	err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
> -				   QCOM_SCM_ICE_CIPHER_AES_256_XTS,
> -				   data_unit_size);
> +		/* 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]);
>   
> -	memzero_explicit(&key, sizeof(key));
> +		err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
> +					   QCOM_SCM_ICE_CIPHER_AES_256_XTS,
> +					   data_unit_size);
> +		memzero_explicit(&key, sizeof(key));
> +	}
>   
>   	return err;
>   }
> @@ -303,7 +379,21 @@ EXPORT_SYMBOL_GPL(qcom_ice_program_key);
>   
>   int qcom_ice_evict_key(struct qcom_ice *ice, int slot)
>   {
> -	return qcom_scm_ice_invalidate_key(slot);
> +	int hwkm_slot = slot;
> +
> +	if (ice->hwkm_version) {
> +		hwkm_slot = translate_hwkm_slot(ice, slot);
> +	/*
> +	 * Ignore calls to evict key when HWKM is supported and hwkm init
> +	 * is not yet done. This is to avoid the clearing all slots call
> +	 * during a storage reset when ICE is still in legacy mode. HWKM slave
> +	 * in ICE takes care of zeroing out the keytable on reset.
> +	 */
> +		if (!ice->hwkm_init_complete)
> +			return 0;
> +	}
> +
> +	return qcom_scm_ice_invalidate_key(hwkm_slot);
>   }
>   EXPORT_SYMBOL_GPL(qcom_ice_evict_key);
>   
> @@ -313,6 +403,15 @@ bool qcom_ice_hwkm_supported(struct qcom_ice *ice)
>   }
>   EXPORT_SYMBOL_GPL(qcom_ice_hwkm_supported);
>   
> +int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wrapped_key[],
> +			      unsigned int wrapped_key_size,
> +			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
> +{
> +	return qcom_scm_derive_sw_secret(wrapped_key, wrapped_key_size,
> +					 sw_secret, BLK_CRYPTO_SW_SECRET_SIZE);
> +}
> +EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret);
> +
>   static struct qcom_ice *qcom_ice_create(struct device *dev,
>   					void __iomem *base)
>   {
> diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
> index 1f52e82e3e1c..22ab8d1a56de 100644
> --- a/include/soc/qcom/ice.h
> +++ b/include/soc/qcom/ice.h
> @@ -17,6 +17,7 @@ enum qcom_ice_crypto_key_size {
>   	QCOM_ICE_CRYPTO_KEY_SIZE_192		= 0x2,
>   	QCOM_ICE_CRYPTO_KEY_SIZE_256		= 0x3,
>   	QCOM_ICE_CRYPTO_KEY_SIZE_512		= 0x4,
> +	QCOM_ICE_CRYPTO_KEY_SIZE_WRAPPED	= 0x5,
>   };
>   
>   enum qcom_ice_crypto_alg {
> @@ -35,5 +36,8 @@ int qcom_ice_program_key(struct qcom_ice *ice,
>   			 u8 data_unit_size, int slot);
>   int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
>   bool qcom_ice_hwkm_supported(struct qcom_ice *ice);
> +int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wrapped_key[],
> +			      unsigned int wrapped_key_size,
> +			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
>   struct qcom_ice *of_qcom_ice_get(struct device *dev);
>   #endif /* __QCOM_ICE_H__ */


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-08-25 21:07   ` Eric Biggers
  2023-08-29 17:11     ` Srinivas Kandagatla
@ 2023-09-12 10:06     ` Srinivas Kandagatla
  2023-09-19 23:18       ` Gaurav Kashyap
  1 sibling, 1 reply; 36+ messages in thread
From: Srinivas Kandagatla @ 2023-09-12 10:06 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Gaurav Kashyap, linux-scsi, linux-arm-msm, linux-mmc,
	linux-block, linux-fscrypt, omprsing, quic_psodagud, avmenon,
	abel.vesa, quic_spuppala

Hi Eric/Gaurav,

Adding more information and some questions to this discussion,

On 25/08/2023 14:07, Eric Biggers wrote:
> Hi Srinivas,
> 
> On Fri, Aug 25, 2023 at 11:19:41AM +0100, Srinivas Kandagatla wrote:
>>
>> On 19/07/2023 18:04, Gaurav Kashyap wrote:
>>> These patches add support to Qualcomm ICE (Inline Crypto Enginr) for hardware
>>> wrapped keys using Qualcomm Hardware Key Manager (HWKM) and are made on top
>>> of a rebased version  Eric Bigger's set of changes to support wrapped keys in
>>> fscrypt and block below:
>>> https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-keys-v7
>>> (The rebased patches are not uploaded here)
>>>
>>> Ref v1 here:
>>> https://lore.kernel.org/linux-scsi/20211206225725.77512-1-quic_gaurkash@quicinc.com/
>>>
>>> Explanation and use of hardware-wrapped-keys can be found here:
>>> Documentation/block/inline-encryption.rst
>>>
>>> This patch is organized as follows:
>>>
>>> Patch 1 - Prepares ICE and storage layers (UFS and EMMC) to pass around wrapped keys.
>>> Patch 2 - Adds a new SCM api to support deriving software secret when wrapped keys are used
>>> Patch 3-4 - Adds support for wrapped keys in the ICE driver. This includes adding HWKM support
>>> Patch 5-6 - Adds support for wrapped keys in UFS
>>> Patch 7-10 - Supports generate, prepare and import functionality in ICE and UFS
>>>
>>> NOTE: MMC will have similar changes to UFS and will be uploaded in a different patchset
>>>         Patch 3, 4, 8, 10 will have MMC equivalents.
>>>
>>> Testing:
>>> Test platform: SM8550 MTP
>>> Engineering trustzone image is required to test this feature only
>>> for SM8550. For SM8650 onwards, all trustzone changes to support this
>>> will be part of the released images.
>>
>> AFAIU, Prior to these proposed changes in scm, HWKM was done with help of
>> TA(Trusted Application) for generate, import, unwrap ... functionality.
>>
>> 1. What is the reason for moving this from TA to new smc calls?
>>
>> Is this because of missing smckinvoke support in upstream?
>>
>> How scalable is this approach? Are we going to add new sec sys calls to
>> every interface to TA?
>>
>> 2. How are the older SoCs going to deal with this, given that you are
>> changing drivers that are common across these?
>>
>> Have you tested these patches on any older platforms?
>>
>> What happens if someone want to add support to wrapped keys to this
>> platforms in upstream, How is that going to be handled?
>>
>> As I understand with this, we will endup with two possible solutions over
>> time in upstream.
> 
> It's true that Qualcomm based Android devices already use HW-wrapped keys on
> SoCs earlier than SM8650.  The problem is that the key generation, import, and
> conversion were added to Android's KeyMint HAL, as a quick way to get the
> feature out the door when it was needed (so to speak).  Unfortunately this
> coupled this feature unnecessarily to the Android KeyMint and the corresponding
> (closed source) userspace HAL provided by Qualcomm, which it's not actually
> related to.  I'd guess that Qualcomm's closed source userspace HAL makes SMC
> calls into Qualcomm's KeyMint TA, but I have no insight into those details.
> 
> The new SMC calls eliminate the dependency on the Android-specific KeyMint.
> They're also being documented by Qualcomm.  So, as this patchset does, they can
> be used by Linux in the implementation of new ioctls which provide a vendor
> independent interface to HW-wrapped key generation, import, and conversion.
> 
> I think the new approach is the only one that is viable outside the Android
> context.  As such, I don't think anyone has any plan to upstream support for

Just bit of history afaiu.

on Qcom SoCs there are 3 ways to talk to Trusted service/Trusted 
application.

1> Adding SCM calls. This is not scalable solution, imagine we keep 
adding new scm calls and static services to the TZ as required and this 
is going to bloat up the tz image size. Not only that, new SoCs would 
need to maintain backward compatibility, which is not going to happen. 
AFAIU this is discouraged in general and Qcom at some point in time will 
move away from this..

2> using QSEECOM: This has some scalable issues, which is now replaced 
with smcinvoke.

3> smcinvoke: This is preferred way to talk to any QTEE service or 
application. The issue is that this is based on some downstream UAPI 
which is not upstream ready yet.

IMO, adding a solution that is just going to live for few years is 
questionable for upstream.

Fixing [3] seems to be much scalable solution along with it we will also 
get support for this feature in all the Qualcomm platforms.

Am interested to hear what Gaurav has to say on this.


--srini


> HW-wrapped keys for older Qualcomm SoCs that lack the new interface.
> 
> - Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

* RE: [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs
  2023-09-12 10:06     ` Srinivas Kandagatla
@ 2023-09-19 23:18       ` Gaurav Kashyap
  0 siblings, 0 replies; 36+ messages in thread
From: Gaurav Kashyap @ 2023-09-19 23:18 UTC (permalink / raw)
  To: Srinivas Kandagatla, Eric Biggers
  Cc: Gaurav Kashyap (QUIC),
	linux-scsi, linux-arm-msm, linux-mmc, linux-block, linux-fscrypt,
	Om Prakash Singh, Prasad Sodagudi (QUIC), Arun Menon (SSG),
	abel.vesa, Seshu Madhavi Puppala (QUIC)

Hello Srinivas,

On Tue, Sep 12, 2023 at 3:07 AM, Srinivas Kandagatla wrote:
> Hi Eric/Gaurav,
> 
> Adding more information and some questions to this discussion,
> 
> On 25/08/2023 14:07, Eric Biggers wrote:
> > Hi Srinivas,
> >
> > On Fri, Aug 25, 2023 at 11:19:41AM +0100, Srinivas Kandagatla wrote:
> >>
> >> On 19/07/2023 18:04, Gaurav Kashyap wrote:
> >>> These patches add support to Qualcomm ICE (Inline Crypto Enginr) for
> >>> hardware wrapped keys using Qualcomm Hardware Key Manager
> (HWKM) and
> >>> are made on top of a rebased version  Eric Bigger's set of changes
> >>> to support wrapped keys in fscrypt and block below:
> >>> https://git.kernel.org/pub/scm/fs/fscrypt/linux.git/log/?h=wrapped-k
> >>> eys-v7 (The rebased patches are not uploaded here)
> >>>
> >>> Ref v1 here:
> >>> https://lore.kernel.org/linux-scsi/20211206225725.77512-1-quic_gaurk
> >>> ash@quicinc.com/
> >>>
> >>> Explanation and use of hardware-wrapped-keys can be found here:
> >>> Documentation/block/inline-encryption.rst
> >>>
> >>> This patch is organized as follows:
> >>>
> >>> Patch 1 - Prepares ICE and storage layers (UFS and EMMC) to pass around
> wrapped keys.
> >>> Patch 2 - Adds a new SCM api to support deriving software secret
> >>> when wrapped keys are used Patch 3-4 - Adds support for wrapped keys
> >>> in the ICE driver. This includes adding HWKM support Patch 5-6 -
> >>> Adds support for wrapped keys in UFS Patch 7-10 - Supports generate,
> >>> prepare and import functionality in ICE and UFS
> >>>
> >>> NOTE: MMC will have similar changes to UFS and will be uploaded in a
> different patchset
> >>>         Patch 3, 4, 8, 10 will have MMC equivalents.
> >>>
> >>> Testing:
> >>> Test platform: SM8550 MTP
> >>> Engineering trustzone image is required to test this feature only
> >>> for SM8550. For SM8650 onwards, all trustzone changes to support
> >>> this will be part of the released images.
> >>
> >> AFAIU, Prior to these proposed changes in scm, HWKM was done with
> >> help of TA(Trusted Application) for generate, import, unwrap ...
> functionality.
> >>
> >> 1. What is the reason for moving this from TA to new smc calls?
> >>
> >> Is this because of missing smckinvoke support in upstream?
> >>
> >> How scalable is this approach? Are we going to add new sec sys calls
> >> to every interface to TA?
> >>
> >> 2. How are the older SoCs going to deal with this, given that you are
> >> changing drivers that are common across these?
> >>
> >> Have you tested these patches on any older platforms?
> >>
> >> What happens if someone want to add support to wrapped keys to this
> >> platforms in upstream, How is that going to be handled?
> >>
> >> As I understand with this, we will endup with two possible solutions
> >> over time in upstream.
> >
> > It's true that Qualcomm based Android devices already use HW-wrapped
> > keys on SoCs earlier than SM8650.  The problem is that the key
> > generation, import, and conversion were added to Android's KeyMint
> > HAL, as a quick way to get the feature out the door when it was needed
> > (so to speak).  Unfortunately this coupled this feature unnecessarily
> > to the Android KeyMint and the corresponding (closed source) userspace
> > HAL provided by Qualcomm, which it's not actually related to.  I'd
> > guess that Qualcomm's closed source userspace HAL makes SMC calls into
> Qualcomm's KeyMint TA, but I have no insight into those details.
> >
> > The new SMC calls eliminate the dependency on the Android-specific
> KeyMint.
> > They're also being documented by Qualcomm.  So, as this patchset does,
> > they can be used by Linux in the implementation of new ioctls which
> > provide a vendor independent interface to HW-wrapped key generation,
> import, and conversion.
> >
> > I think the new approach is the only one that is viable outside the
> > Android context.  As such, I don't think anyone has any plan to
> > upstream support for
> 
> Just bit of history afaiu.
> 
> on Qcom SoCs there are 3 ways to talk to Trusted service/Trusted application.
> 
> 1> Adding SCM calls. This is not scalable solution, imagine we keep
> adding new scm calls and static services to the TZ as required and this is going
> to bloat up the tz image size. Not only that, new SoCs would need to maintain
> backward compatibility, which is not going to happen.
> AFAIU this is discouraged in general and Qcom at some point in time will move
> away from this..
> 
> 2> using QSEECOM: This has some scalable issues, which is now replaced
> with smcinvoke.
> 
> 3> smcinvoke: This is preferred way to talk to any QTEE service or
> application. The issue is that this is based on some downstream UAPI which is
> not upstream ready yet.
> 
> IMO, adding a solution that is just going to live for few years is questionable
> for upstream.
> 
> Fixing [3] seems to be much scalable solution along with it we will also get
> support for this feature in all the Qualcomm platforms.
> 
> Am interested to hear what Gaurav has to say on this.
> 
> 
> --srini
> 
> 

What you are referring to is wrapped keys being generated in a Trusted Application (in case of android and some other solutions, keymaster), and eventually being programmed via SCM calls in TZ.
And, you are suggesting instead of ioctl->scm call, we should be doing ioctl->smcinvoke->TA

What Eric and I are adding here should not be just considered a stopgap, but a path for potential clients to generate and manage wrapped keys without requiring any TA.
The TA way will continue to work, and those wrapped keys can be programmed to ICE using fscrypt.

Unless, is the suggestion that wrapped keys should always be generated and managed in a trusted application?
And then programmed though kernel->SCM call interface?

> > HW-wrapped keys for older Qualcomm SoCs that lack the new interface.
> >
> > - Eric

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2023-09-19 23:19 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-19 17:04 [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
2023-07-19 17:04 ` [PATCH v2 01/10] ice, ufs, mmc: use blk_crypto_key for program_key Gaurav Kashyap
2023-07-19 17:04 ` [PATCH v2 02/10] qcom_scm: scm call for deriving a software secret Gaurav Kashyap
2023-07-22  3:50   ` Bjorn Andersson
2023-07-22  4:18     ` Eric Biggers
2023-07-22 17:31       ` Bjorn Andersson
2023-07-19 17:04 ` [PATCH v2 03/10] soc: qcom: ice: add hwkm support in ice Gaurav Kashyap
2023-08-31  8:39   ` Neil Armstrong
2023-07-19 17:04 ` [PATCH v2 04/10] soc: qcom: ice: support for hardware wrapped keys Gaurav Kashyap
2023-08-31  9:10   ` Neil Armstrong
2023-07-19 17:04 ` [PATCH v2 05/10] ufs: core: support wrapped keys in ufs core Gaurav Kashyap
2023-07-19 17:04 ` [PATCH v2 06/10] ufs: host: wrapped keys support in ufs qcom Gaurav Kashyap
2023-07-19 17:04 ` [PATCH v2 07/10] qcom_scm: scm call for create, prepare and import keys Gaurav Kashyap
2023-07-19 17:48   ` Trilok Soni
2023-07-22  3:40   ` Bjorn Andersson
2023-07-22  4:11     ` Eric Biggers
2023-07-22 17:32       ` Bjorn Andersson
2023-07-19 17:04 ` [PATCH v2 08/10] ufs: core: add support for generate, import and prepare keys Gaurav Kashyap
2023-07-19 17:04 ` [PATCH v2 09/10] soc: qcom: support for generate, import and prepare key Gaurav Kashyap
2023-07-22  3:56   ` Bjorn Andersson
2023-07-19 17:04 ` [PATCH v2 10/10] ufs: host: " Gaurav Kashyap
2023-07-20  2:55 ` [PATCH v2 00/10] Hardware wrapped key support for qcom ice and ufs Eric Biggers
2023-08-01 17:31   ` Gaurav Kashyap (QUIC)
2023-08-10  5:36     ` Eric Biggers
2023-08-11  0:27       ` Gaurav Kashyap (QUIC)
2023-08-11  2:19         ` Bjorn Andersson
2023-08-25 10:19 ` Srinivas Kandagatla
2023-08-25 21:07   ` Eric Biggers
2023-08-29 17:11     ` Srinivas Kandagatla
2023-08-29 18:12       ` Eric Biggers
2023-08-30 10:00         ` Srinivas Kandagatla
2023-08-30 16:12           ` Eric Biggers
2023-08-30 16:44             ` Srinivas Kandagatla
2023-09-12 10:06     ` Srinivas Kandagatla
2023-09-19 23:18       ` Gaurav Kashyap
2023-08-29 21:06 ` Konrad Dybcio

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).