linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs
@ 2024-01-27 23:13 Gaurav Kashyap
  2024-01-27 23:13 ` [PATCH v4 01/15] ice, ufs, mmc: use blk_crypto_key for program_key Gaurav Kashyap
                   ` (14 more replies)
  0 siblings, 15 replies; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:13 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

The fourth iteration of patches that add support to Qualcomm ICE (Inline Crypto Engine) for hardware wrapped keys using Qualcomm Hardware Key Manager (HWKM)

These patches do the following:
- Address comments from previous versions (https://lore.kernel.org/linux-arm-msm/20231122053817.3401748-1-quic_gaurkash@quicinc.com/)
- Tested on top of Eric's latest fscrypt and block set: https://lore.kernel.org/all/20231104211259.17448-1-ebiggers@kernel.org/
- Rebased and tested on top of Linaro's SHMBridge patches: (https://lkml.org/lkml/2023/11/20/555)

Explanation and use of hardware-wrapped-keys can be found here:
Documentation/block/inline-encryption.rst (https://lore.kernel.org/all/20231104211259.17448-1-ebiggers@kernel.org/)

Testing: 
Test platform: SM8650 MTP

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.

Tested both standard and wrapped keys (Removing qcom,ice-use-hwkm from dtsi will support using standard keys)

Steps to test:

The following configs were enabled:
CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_QCOM_INLINE_CRYPTO_ENGINE=m
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
CONFIG_SCSI_UFS_CRYPTO=y

Flash boot image to shell and run the following commands

Creating and preparing keys
- mkfs.ext4 -F -O encrypt,stable_inodes /dev/disk/by-partlabel/userdata
- mount /dev/disk/by-partlabel/userdata -o inlinecrypt /mnt
- ./fscryptctl generate_hw_wrapped_key /dev/disk/by-partlabel/userdata > /mnt/key.longterm  OR
   dd if=/dev/zero bs=32 count=1 | tr '\0' 'X' \ | fscryptctl import_hw_wrapped_key /dev/disk/by-partlabel/userdata > /mnt/key.longterm
- ./fscryptctl prepare_hw_wrapped_key /dev/disk/by-partlabel/userdata < /mnt/key.longterm > /tmp/key.ephemeral
- ./fscryptctl add_key --hw-wrapped-key < /tmp/key.ephemeral /mnt

Create a folder and associate created keys with the folder
- rm -rf /mnt/dir
- mkdir /mnt/dir
- ./fscryptctl set_policy --hw-wrapped-key --iv-ino-lblk-64 "$keyid" /mnt/dir
- dmesg > /mnt/dir/test.txt
- sync

- Reboot
- mount /dev/disk/by-partlabel/userdata -o inlinecrypt /mnt
- ls /mnt/dir (You should see an encrypted file)
- ./fscryptctl prepare_hw_wrapped_key /dev/disk/by-partlabel/userdata < /mnt/key.longterm > /tmp/key.ephemeral
- ./fscryptctl add_key --hw-wrapped-key < /tmp/key.ephemeral /mnt
- cat /mnt/dir/test.txt

NOTE: Evicting a key with HWKM is not supported in the current SCM call for HWKM v2 chipsets, TZ already supports a different call for this.
Changes will be added separately for these after further internal discussions. But this should not stop merging the existing patches.

Merge Strategy:

This is an open-ended question to the community and the respective component maintainers.
The changes have the following components.

- Fscrypt and block patches (From Eric Biggers)
- SHMBridge patches (Bartosz Golaszewski)
- Qualcomm SCM (This patchset)
- Qualcomm ICE (This patchset)
- UFS Core ((This patchset))
- Qualcomm UFS Host (This patchset)

It would be ideal if one maintainer can take in all the changes together since working with many immutable branches shared with each other might get tricky.

Gaurav Kashyap (15):
  ice, ufs, mmc: use blk_crypto_key for program_key
  qcom_scm: scm call for deriving a software secret
  qcom_scm: scm call for create, prepare and import keys
  soc: qcom: ice: add hwkm support in ice
  soc: qcom: ice: support for hardware wrapped keys
  soc: qcom: ice: support for generate, import and prepare key
  ufs: core: support wrapped keys in ufs core
  ufs: core: add support to derive software secret
  ufs: core: add support for generate, import and prepare keys
  ufs: host: wrapped keys support in ufs qcom
  ufs: host: implement derive sw secret vop in ufs qcom
  ufs: host: support for generate, import and prepare key
  dt-bindings: crypto: ice: document the hwkm property
  arm64: dts: qcom: sm8650: add hwkm support to ufs ice
  arm64: dts: qcom: sm8550: add hwkm support to ufs ice

 .../crypto/qcom,inline-crypto-engine.yaml     |  10 +
 arch/arm64/boot/dts/qcom/sm8550.dtsi          |   3 +-
 arch/arm64/boot/dts/qcom/sm8650.dtsi          |   3 +-
 drivers/firmware/qcom/qcom_scm.c              | 247 ++++++++++++++
 drivers/firmware/qcom/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                        | 315 +++++++++++++++++-
 drivers/ufs/core/ufshcd-crypto.c              |  87 ++++-
 drivers/ufs/host/ufs-qcom.c                   |  61 +++-
 include/linux/firmware/qcom/qcom_scm.h        |   7 +
 include/soc/qcom/ice.h                        |  18 +-
 include/ufs/ufshcd.h                          |  22 ++
 14 files changed, 754 insertions(+), 38 deletions(-)

-- 
2.43.0


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

* [PATCH v4 01/15] ice, ufs, mmc: use blk_crypto_key for program_key
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
@ 2024-01-27 23:13 ` Gaurav Kashyap
  2024-02-06 11:46   ` Bartosz Golaszewski
  2024-02-13 12:49   ` Ulf Hansson
  2024-01-27 23:14 ` [PATCH v4 02/15] qcom_scm: scm call for deriving a software secret Gaurav Kashyap
                   ` (13 subsequent siblings)
  14 siblings, 2 replies; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:13 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	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>
Reviewed-by: Om Prakash Singh <quic_omprsing@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 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 668e0aceeeba..529ea9f4fa07 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 *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 fbab7fe5c652..6f941d32fffb 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -163,8 +163,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 {
@@ -183,7 +183,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 39eef470f8fa..acf352594362 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -144,6 +144,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)
 {
@@ -151,6 +152,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];
@@ -158,11 +160,11 @@ static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
 	    cap.key_size != UFS_CRYPTO_KEY_SIZE_256)
 		return -EOPNOTSUPP;
 
+	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 cb2afcebbdf5..582d5a747e84 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -363,6 +363,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.43.0


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

* [PATCH v4 02/15] qcom_scm: scm call for deriving a software secret
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
  2024-01-27 23:13 ` [PATCH v4 01/15] ice, ufs, mmc: use blk_crypto_key for program_key Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-01-30  4:43   ` Bjorn Andersson
  2024-02-01 16:11   ` Konrad Dybcio
  2024-01-27 23:14 ` [PATCH v4 03/15] qcom_scm: scm call for create, prepare and import keys Gaurav Kashyap
                   ` (12 subsequent siblings)
  14 siblings, 2 replies; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

Inline storage encryption may require deriving a software
secret from storage keys added to the kernel.

For non-wrapped keys, this can be directly done in the kernel as
keys are in the clear.

However, hardware wrapped keys can only be unwrapped by the wrapping
entity. In case of Qualcomm's wrapped key solution, this is done by
the Hardware Key Manager (HWKM) from Trustzone.
Hence, adding a new SCM call which in the end provides a hook
to the software secret crypto profile API provided by the block
layer.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/firmware/qcom/qcom_scm.c       | 65 ++++++++++++++++++++++++++
 drivers/firmware/qcom/qcom_scm.h       |  1 +
 include/linux/firmware/qcom/qcom_scm.h |  2 +
 3 files changed, 68 insertions(+)

diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 7e17fd662bda..4882f8a36453 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -1220,6 +1220,71 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
 }
 EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key);
 
+/**
+ * qcom_scm_derive_sw_secret() - Derive software secret from wrapped key
+ * @wkey: the hardware wrapped key inaccessible to software
+ * @wkey_size: size of the wrapped key
+ * @sw_secret: the secret to be derived which is exactly the secret size
+ * @sw_secret_size: size of the sw_secret
+ *
+ * Derive a software secret from a hardware wrapped key for software crypto
+ * operations.
+ * For wrapped keys, the key needs to be unwrapped, in order to derive a
+ * software secret, which can be done in the hardware from a secure execution
+ * environment.
+ *
+ * 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 *wkey, size_t wkey_size,
+			      u8 *sw_secret, size_t sw_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] = wkey_size,
+		.args[3] = sw_secret_size,
+		.owner = ARM_SMCCC_OWNER_SIP,
+	};
+
+	void *secret_buf;
+	void *wkey_buf;
+	int ret;
+
+	wkey_buf = qcom_tzmem_alloc(__scm->mempool, wkey_size, GFP_KERNEL);
+	if (!wkey_buf)
+		return -ENOMEM;
+
+	secret_buf = qcom_tzmem_alloc(__scm->mempool, sw_secret_size, GFP_KERNEL);
+	if (!secret_buf) {
+		ret = -ENOMEM;
+		goto err_free_wrapped;
+	}
+
+	memcpy(wkey_buf, wkey, wkey_size);
+	desc.args[0] = qcom_tzmem_to_phys(wkey_buf);
+	desc.args[2] = qcom_tzmem_to_phys(secret_buf);
+
+	ret = qcom_scm_call(__scm->dev, &desc, NULL);
+	if (!ret)
+		memcpy(sw_secret, secret_buf, sw_secret_size);
+
+	memzero_explicit(secret_buf, sw_secret_size);
+	qcom_tzmem_free(secret_buf);
+
+err_free_wrapped:
+	memzero_explicit(wkey_buf, wkey_size);
+	qcom_tzmem_free(wkey_buf);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
+
 /**
  * qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
  *
diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h
index cb7273aa0a5e..56ff0806f5d2 100644
--- a/drivers/firmware/qcom/qcom_scm.h
+++ b/drivers/firmware/qcom/qcom_scm.h
@@ -127,6 +127,7 @@ struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void);
 #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 9b6054813f59..89358478ac67 100644
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -103,6 +103,8 @@ bool qcom_scm_ice_available(void);
 int qcom_scm_ice_invalidate_key(u32 index);
 int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
 			 enum qcom_scm_ice_cipher cipher, u32 data_unit_size);
+int qcom_scm_derive_sw_secret(const u8 *wkey, size_t wkey_size,
+			      u8 *sw_secret, size_t sw_secret_size);
 
 bool qcom_scm_hdcp_available(void);
 int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
-- 
2.43.0


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

* [PATCH v4 03/15] qcom_scm: scm call for create, prepare and import keys
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
  2024-01-27 23:13 ` [PATCH v4 01/15] ice, ufs, mmc: use blk_crypto_key for program_key Gaurav Kashyap
  2024-01-27 23:14 ` [PATCH v4 02/15] qcom_scm: scm call for deriving a software secret Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-02-05 18:03   ` Om Prakash Singh
  2024-02-06 11:59   ` Bartosz Golaszewski
  2024-01-27 23:14 ` [PATCH v4 04/15] soc: qcom: ice: add hwkm support in ice Gaurav Kashyap
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

Storage encryption has two IOCTLs for creating, importing
and preparing keys for encryption. For wrapped keys, these
IOCTLs need to interface with Qualcomm's Trustzone, 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>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/firmware/qcom/qcom_scm.c       | 182 +++++++++++++++++++++++++
 drivers/firmware/qcom/qcom_scm.h       |   3 +
 include/linux/firmware/qcom/qcom_scm.h |   5 +
 3 files changed, 190 insertions(+)

diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 4882f8a36453..20dbab765c8e 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -1285,6 +1285,188 @@ int qcom_scm_derive_sw_secret(const u8 *wkey, size_t wkey_size,
 }
 EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
 
+/**
+ * qcom_scm_generate_ice_key() - Generate a wrapped key for encryption.
+ * @lt_key: the wrapped key returned after key generation
+ * @lt_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.
+ *
+ * Adds support for the create key IOCTL to interface
+ * with the secure environment to generate and return a wrapped key..
+ *
+ * Return: longterm key size on success; -errno on failure.
+ */
+int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_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] = lt_key_size,
+		.owner = ARM_SMCCC_OWNER_SIP,
+	};
+
+	void *lt_key_buf;
+	int ret;
+
+	lt_key_buf = qcom_tzmem_alloc(__scm->mempool, lt_key_size, GFP_KERNEL);
+	if (!lt_key_buf)
+		return -ENOMEM;
+
+	desc.args[0] = qcom_tzmem_to_phys(lt_key_buf);
+
+	ret = qcom_scm_call(__scm->dev, &desc, NULL);
+	if (!ret)
+		memcpy(lt_key, lt_key_buf, lt_key_size);
+
+	memzero_explicit(lt_key_buf, lt_key_size);
+	qcom_tzmem_free(lt_key_buf);
+
+	if (!ret)
+		return lt_key_size;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key);
+
+/**
+ * qcom_scm_prepare_ice_key() - Get per boot ephemeral wrapped key
+ * @lt_key: the longterm wrapped key
+ * @lt_key_size: size of the wrapped key
+ * @eph_key: ephemeral wrapped key to be returned
+ * @eph_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.
+ *
+ * Adds support for the create key IOCTL to interface
+ * with the secure environment to rewrap the wrapped key with an
+ * ephemeral wrapping key.
+ *
+ * Return: ephemeral key size on success; -errno on failure.
+ */
+int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
+			     u8 *eph_key, size_t eph_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] = lt_key_size,
+		.args[3] = eph_key_size,
+		.owner = ARM_SMCCC_OWNER_SIP,
+	};
+
+	void *eph_key_buf;
+	void *lt_key_buf;
+	int ret;
+
+	lt_key_buf = qcom_tzmem_alloc(__scm->mempool, lt_key_size, GFP_KERNEL);
+	if (!lt_key_buf)
+		return -ENOMEM;
+	eph_key_buf = qcom_tzmem_alloc(__scm->mempool, eph_key_size, GFP_KERNEL);
+	if (!eph_key_buf) {
+		ret = -ENOMEM;
+		goto err_free_longterm;
+	}
+
+	memcpy(lt_key_buf, lt_key, lt_key_size);
+	desc.args[0] = qcom_tzmem_to_phys(lt_key_buf);
+	desc.args[2] = qcom_tzmem_to_phys(eph_key_buf);
+
+	ret = qcom_scm_call(__scm->dev, &desc, NULL);
+	if (!ret)
+		memcpy(eph_key, eph_key_buf, eph_key_size);
+
+	memzero_explicit(eph_key_buf, eph_key_size);
+	qcom_tzmem_free(eph_key_buf);
+
+err_free_longterm:
+	memzero_explicit(lt_key_buf, lt_key_size);
+	qcom_tzmem_free(lt_key_buf);
+
+	if (!ret)
+		return eph_key_size;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key);
+
+/**
+ * qcom_scm_import_ice_key() - Import a wrapped key for encryption
+ * @imp_key: the raw key that is imported
+ * @imp_key_size: size of the key to be imported
+ * @lt_key: the wrapped key to be returned
+ * @lt_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.
+ *
+ * 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: longterm key size on success; -errno on failure.
+ */
+int qcom_scm_import_ice_key(const u8 *imp_key, size_t imp_key_size,
+			    u8 *lt_key, size_t lt_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] = imp_key_size,
+		.args[3] = lt_key_size,
+		.owner = ARM_SMCCC_OWNER_SIP,
+	};
+
+	void *imp_key_buf;
+	void *lt_key_buf;
+	int ret;
+
+	imp_key_buf = qcom_tzmem_alloc(__scm->mempool, imp_key_size, GFP_KERNEL);
+	if (!imp_key_buf)
+		return -ENOMEM;
+	lt_key_buf = qcom_tzmem_alloc(__scm->mempool, lt_key_size, GFP_KERNEL);
+	if (!lt_key_buf) {
+		ret = -ENOMEM;
+		goto err_free_longterm;
+	}
+
+	memcpy(imp_key_buf, imp_key, imp_key_size);
+	desc.args[0] = qcom_tzmem_to_phys(imp_key_buf);
+	desc.args[2] = qcom_tzmem_to_phys(lt_key_buf);
+
+	ret = qcom_scm_call(__scm->dev, &desc, NULL);
+	if (!ret)
+		memcpy(lt_key, lt_key_buf, lt_key_size);
+
+	memzero_explicit(lt_key_buf, lt_key_size);
+	qcom_tzmem_free(lt_key_buf);
+
+err_free_longterm:
+	memzero_explicit(imp_key_buf, imp_key_size);
+	qcom_tzmem_free(imp_key_buf);
+
+	if (!ret)
+		return lt_key_size;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(qcom_scm_import_ice_key);
+
 /**
  * qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
  *
diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h
index 56ff0806f5d2..c30d6383b6de 100644
--- a/drivers/firmware/qcom/qcom_scm.h
+++ b/drivers/firmware/qcom/qcom_scm.h
@@ -128,6 +128,9 @@ struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void);
 #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 89358478ac67..a0983a40bc09 100644
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -105,6 +105,11 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
 			 enum qcom_scm_ice_cipher cipher, u32 data_unit_size);
 int qcom_scm_derive_sw_secret(const u8 *wkey, size_t wkey_size,
 			      u8 *sw_secret, size_t sw_secret_size);
+int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size);
+int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
+			     u8 *eph_key, size_t eph_size);
+int qcom_scm_import_ice_key(const u8 *imp_key, size_t imp_size,
+			    u8 *lt_key, size_t lt_key_size);
 
 bool qcom_scm_hdcp_available(void);
 int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
-- 
2.43.0


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

* [PATCH v4 04/15] soc: qcom: ice: add hwkm support in ice
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (2 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 03/15] qcom_scm: scm call for create, prepare and import keys Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-02-04 18:32   ` [EXTERNAL] " Kamlesh Gurudasani
  2024-02-05 18:22   ` Om Prakash Singh
  2024-01-27 23:14 ` [PATCH v4 05/15] soc: qcom: ice: support for hardware wrapped keys Gaurav Kashyap
                   ` (10 subsequent siblings)
  14 siblings, 2 replies; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	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.

When HWKM software support is not fully available (from Trustzone),
there can be a scenario where the ICE hardware supports HWKM, but
it cannot be used for wrapped keys. In this case, standard keys have
to be used without using HWKM. Hence, providing a toggle controlled
by a devicetree entry to use HWKM or not.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/soc/qcom/ice.c | 126 ++++++++++++++++++++++++++++++++++++++++-
 include/soc/qcom/ice.h |   1 +
 2 files changed, 124 insertions(+), 3 deletions(-)

diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index 6f941d32fffb..c718e8153b23 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -26,6 +26,20 @@
 #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_BANKN_IRQ_STATUS	0x2008
+#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
+
+/* QCOM ICE HWKM BIST vals */
+#define QCOM_ICE_HWKM_BIST_DONE_V1_VAL		0x14007
+#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)
@@ -34,6 +48,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))
 
@@ -46,6 +63,9 @@ struct qcom_ice {
 	struct device_link *link;
 
 	struct clk *core_clk;
+	u8 hwkm_version;
+	bool use_hwkm;
+	bool hwkm_init_complete;
 };
 
 static bool qcom_ice_check_supported(struct qcom_ice *ice)
@@ -63,8 +83,21 @@ static bool qcom_ice_check_supported(struct qcom_ice *ice)
 		return false;
 	}
 
-	dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n",
-		 major, minor, step);
+	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;
+
+	if (ice->hwkm_version == 0)
+		ice->use_hwkm = false;
+
+	dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d, HWKM v%d\n",
+		 major, minor, step, ice->hwkm_version);
+
+	if (!ice->use_hwkm)
+		dev_info(dev, "QC ICE HWKM (Hardware Key Manager) not used/supported");
 
 	/* If fuses are blown, ICE might not work in the standard way. */
 	regval = qcom_ice_readl(ice, QCOM_ICE_REG_FUSE_SETTING);
@@ -113,10 +146,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_reg;
 	int err;
 
 	err = readl_poll_timeout(ice->base + QCOM_ICE_REG_BIST_STATUS,
@@ -125,15 +162,85 @@ 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->use_hwkm) {
+		bist_done_reg = (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_reg) {
+			dev_err(ice->dev, "HWKM BIST error\n");
+			ice->use_hwkm = false;
+		}
+	}
 	return err;
 }
 
+static void qcom_ice_enable_standard_mode(struct qcom_ice *ice)
+{
+	u32 val = 0;
+
+	/*
+	 * 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)
+{
+	/* Disable CRC checks. This HWKM feature is not used. */
+	qcom_ice_writel(ice, 0x6,
+			HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_CTL));
+
+	/*
+	 * 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));
+
+	/* Clear HWKM response FIFO before doing anything */
+	qcom_ice_writel(ice, 0x8, HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STATUS));
+	ice->hwkm_init_complete = true;
+}
+
 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);
+	if (ice->use_hwkm)
+		qcom_ice_enable_standard_mode(ice);
+
+	err = qcom_ice_wait_bist_status(ice);
+	if (err)
+		return err;
+
+	if (ice->use_hwkm)
+		qcom_ice_hwkm_init(ice);
+
+	return err;
 }
 EXPORT_SYMBOL_GPL(qcom_ice_enable);
 
@@ -149,6 +256,10 @@ int qcom_ice_resume(struct qcom_ice *ice)
 		return err;
 	}
 
+	if (ice->use_hwkm) {
+		qcom_ice_enable_standard_mode(ice);
+		qcom_ice_hwkm_init(ice);
+	}
 	return qcom_ice_wait_bist_status(ice);
 }
 EXPORT_SYMBOL_GPL(qcom_ice_resume);
@@ -156,6 +267,7 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume);
 int qcom_ice_suspend(struct qcom_ice *ice)
 {
 	clk_disable_unprepare(ice->core_clk);
+	ice->hwkm_init_complete = false;
 
 	return 0;
 }
@@ -205,6 +317,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->use_hwkm;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_hwkm_supported);
+
 static struct qcom_ice *qcom_ice_create(struct device *dev,
 					void __iomem *base)
 {
@@ -239,6 +357,8 @@ static struct qcom_ice *qcom_ice_create(struct device *dev,
 		engine->core_clk = devm_clk_get_enabled(dev, NULL);
 	if (IS_ERR(engine->core_clk))
 		return ERR_CAST(engine->core_clk);
+	engine->use_hwkm = of_property_read_bool(dev->of_node,
+						 "qcom,ice-use-hwkm");
 
 	if (!qcom_ice_check_supported(engine))
 		return ERR_PTR(-EOPNOTSUPP);
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.43.0


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

* [PATCH v4 05/15] soc: qcom: ice: support for hardware wrapped keys
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (3 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 04/15] soc: qcom: ice: add hwkm support in ice Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-02-04 19:30   ` [EXTERNAL] " Kamlesh Gurudasani
  2024-02-05 18:38   ` Om Prakash Singh
  2024-01-27 23:14 ` [PATCH v4 06/15] soc: qcom: ice: support for generate, import and prepare key Gaurav Kashyap
                   ` (9 subsequent siblings)
  14 siblings, 2 replies; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	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). This is
similar to standard keys where the call is forwarded to
Trustzone, however certain wrapped key and HWKM specific
actions has to be performed around the SCM calls.

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

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/soc/qcom/ice.c | 119 +++++++++++++++++++++++++++++++++++++----
 include/soc/qcom/ice.h |   4 ++
 2 files changed, 112 insertions(+), 11 deletions(-)

diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index c718e8153b23..c3b852269dca 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -27,6 +27,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
@@ -48,6 +50,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)
 
@@ -68,6 +72,16 @@ struct qcom_ice {
 	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)
 {
 	u32 regval = qcom_ice_readl(ice, QCOM_ICE_REG_VERSION);
@@ -273,6 +287,51 @@ 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. For v1 however, the translation is done in trustzone.
+ */
+static int translate_hwkm_slot(struct qcom_ice *ice, int slot)
+{
+	return (ice->hwkm_version == 1) ? slot : (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)
+{
+	union crypto_cfg cfg;
+	int hwkm_slot;
+	int err;
+
+	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,
@@ -288,24 +347,39 @@ 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) {
+		/* It is expected that HWKM init has completed before programming wrapped keys */
+		if (!ice->use_hwkm || !ice->hwkm_init_complete) {
+			dev_err_ratelimited(dev, "HWKM not currently used or initialized\n");
+			return -EINVAL;
+		}
+		err = qcom_ice_program_wrapped_key(ice, bkey, data_unit_size,
+						   slot);
+	} 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;
 }
@@ -313,7 +387,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->use_hwkm) {
+		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);
 
@@ -323,6 +411,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 wkey[],
+			      unsigned int wkey_size,
+			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
+{
+	return qcom_scm_derive_sw_secret(wkey, wkey_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..dabe0d3a1fd0 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 wkey[],
+			      unsigned int wkey_size,
+			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
 struct qcom_ice *of_qcom_ice_get(struct device *dev);
 #endif /* __QCOM_ICE_H__ */
-- 
2.43.0


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

* [PATCH v4 06/15] soc: qcom: ice: support for generate, import and prepare key
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (4 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 05/15] soc: qcom: ice: support for hardware wrapped keys Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-02-05 18:45   ` Om Prakash Singh
  2024-01-27 23:14 ` [PATCH v4 07/15] ufs: core: support wrapped keys in ufs core Gaurav Kashyap
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

Wrapped key creation and management using HWKM is currently
supported only through Qualcomm's Trustzone.
Three new SCM calls have already been added in the scm layer
for this purpose.

This patch adds support for generate, prepare and import key
apis in ICE module and hooks it up the scm calls defined for them.
This will eventually plug into the new IOCTLS added for this
usecase in the block layer.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/soc/qcom/ice.c | 66 ++++++++++++++++++++++++++++++++++++++++++
 include/soc/qcom/ice.h |  8 +++++
 2 files changed, 74 insertions(+)

diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index c3b852269dca..93654ae704bf 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -21,6 +21,13 @@
 
 #define AES_256_XTS_KEY_SIZE			64
 
+/*
+ * Wrapped key sizes that HWKM expects and manages is different for different
+ * versions of the hardware.
+ */
+#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
@@ -420,6 +427,65 @@ int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wkey[],
 }
 EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret);
 
+/**
+ * qcom_ice_generate_key() - Generate a wrapped key for inline encryption
+ * @lt_key: longterm 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: lt wrapped key size on success; err on failure.
+ */
+int qcom_ice_generate_key(struct qcom_ice *ice,
+			  u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	return qcom_scm_generate_ice_key(lt_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
+ * @lt_key: longterm wrapped key that is generated or imported.
+ * @lt_key_size: size of the longterm wrapped_key
+ * @eph_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: eph wrapped key size on success; err on failure.
+ */
+int qcom_ice_prepare_key(struct qcom_ice *ice, const u8 *lt_key, size_t lt_key_size,
+			 u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	return qcom_scm_prepare_ice_key(lt_key, lt_key_size, eph_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
+ * @imp_key: raw key that has to be imported
+ * @imp_key_size: size of the imported key
+ * @lt_key: longterm 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 generate a longterm wrapped key using hwkm.
+ *
+ * Return: lt wrapped key size on success; err on failure.
+ */
+int qcom_ice_import_key(struct qcom_ice *ice, const u8 *imp_key, size_t imp_key_size,
+			u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	return qcom_scm_import_ice_key(imp_key, imp_key_size, lt_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 dabe0d3a1fd0..dcf277d196ff 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 wkey[],
 			      unsigned int wkey_size,
 			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
+int qcom_ice_generate_key(struct qcom_ice *ice,
+			  u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
+int qcom_ice_prepare_key(struct qcom_ice *ice,
+			 const u8 *lt_key, size_t lt_key_size,
+			 u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
+int qcom_ice_import_key(struct qcom_ice *ice,
+			const u8 *imp_key, size_t imp_key_size,
+			u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
 struct qcom_ice *of_qcom_ice_get(struct device *dev);
 #endif /* __QCOM_ICE_H__ */
-- 
2.43.0


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

* [PATCH v4 07/15] ufs: core: support wrapped keys in ufs core
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (5 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 06/15] soc: qcom: ice: support for generate, import and prepare key Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-01-27 23:14 ` [PATCH v4 08/15] ufs: core: add support to derive software secret Gaurav Kashyap
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

Since wrapped keys are not part of the UFS specifications,
it needs to be treated as a supported quirk of the UFS
controller. This way, based on the quirk set during a host
probe, UFS crypto can choose to register either standard or
wrapped keys with block crypto profile.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/ufs/core/ufshcd-crypto.c | 24 ++++++++++++++++--------
 include/ufs/ufshcd.h             |  6 ++++++
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c
index 34537cbac622..399b55d67b3b 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);
@@ -191,7 +193,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 582d5a747e84..680c010a53d4 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -644,6 +644,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.43.0


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

* [PATCH v4 08/15] ufs: core: add support to derive software secret
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (6 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 07/15] ufs: core: support wrapped keys in ufs core Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-02-05 18:52   ` Om Prakash Singh
  2024-01-27 23:14 ` [PATCH v4 09/15] ufs: core: add support for generate, import and prepare keys Gaurav Kashyap
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

Block crypto allows storage controllers like UFS to
register an op derive a software secret from wrapped
keys added to the kernel.

Wrapped keys in most cases will have vendor specific
implementations, which means this op would need to have
a corresponding UFS variant op.
This change adds hooks in UFS core to support this variant
ops and tie them to the blk crypto op.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/ufs/core/ufshcd-crypto.c | 15 +++++++++++++++
 include/ufs/ufshcd.h             |  4 ++++
 2 files changed, 19 insertions(+)

diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c
index 399b55d67b3b..c14800eac1ff 100644
--- a/drivers/ufs/core/ufshcd-crypto.c
+++ b/drivers/ufs/core/ufshcd-crypto.c
@@ -119,6 +119,20 @@ static int ufshcd_crypto_keyslot_evict(struct blk_crypto_profile *profile,
 	return ufshcd_clear_keyslot(hba, slot);
 }
 
+static int ufshcd_crypto_derive_sw_secret(struct blk_crypto_profile *profile,
+					  const u8 wkey[], size_t wkey_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, wkey, wkey_size,
+						    sw_secret);
+
+	return -EOPNOTSUPP;
+}
+
 bool ufshcd_crypto_enable(struct ufs_hba *hba)
 {
 	if (!(hba->caps & UFSHCD_CAP_CRYPTO))
@@ -132,6 +146,7 @@ bool ufshcd_crypto_enable(struct ufs_hba *hba)
 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
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index 680c010a53d4..8a773434a329 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -321,6 +321,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
@@ -365,6 +366,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 wkey[],
+				    unsigned int wkey_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 *);
-- 
2.43.0


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

* [PATCH v4 09/15] ufs: core: add support for generate, import and prepare keys
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (7 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 08/15] ufs: core: add support to derive software secret Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-02-05 18:53   ` Om Prakash Singh
  2024-01-27 23:14 ` [PATCH v4 10/15] ufs: host: wrapped keys support in ufs qcom Gaurav Kashyap
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

Block crypto allows storage controllers like UFS to
register ops to generate, prepare and import wrapped
keys in the kernel.

Wrapped keys in most cases will have vendor specific
implementations, which means these ops would need to have
corresponding UFS variant ops.
This change adds hooks in UFS core to support these variant
ops and tie them to the blk crypto ops.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/ufs/core/ufshcd-crypto.c | 41 ++++++++++++++++++++++++++++++++
 include/ufs/ufshcd.h             | 11 +++++++++
 2 files changed, 52 insertions(+)

diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c
index c14800eac1ff..fb935a54acfa 100644
--- a/drivers/ufs/core/ufshcd-crypto.c
+++ b/drivers/ufs/core/ufshcd-crypto.c
@@ -143,10 +143,51 @@ bool ufshcd_crypto_enable(struct ufs_hba *hba)
 	return true;
 }
 
+static int ufshcd_crypto_generate_key(struct blk_crypto_profile *profile,
+				      u8 lt_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, lt_key);
+
+	return -EOPNOTSUPP;
+}
+
+static int ufshcd_crypto_prepare_key(struct blk_crypto_profile *profile,
+				     const u8 *lt_key, size_t lt_key_size,
+				     u8 eph_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, lt_key, lt_key_size, eph_key);
+
+	return -EOPNOTSUPP;
+}
+
+static int ufshcd_crypto_import_key(struct blk_crypto_profile *profile,
+				    const u8 *imp_key, size_t imp_key_size,
+				    u8 lt_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, imp_key, imp_key_size, lt_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 8a773434a329..fe66ba37e2ee 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -322,6 +322,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
@@ -369,6 +372,14 @@ struct ufs_hba_variant_ops {
 	int	(*derive_sw_secret)(struct ufs_hba *hba, const u8 wkey[],
 				    unsigned int wkey_size,
 				    u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
+	int	(*generate_key)(struct ufs_hba *hba,
+				u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
+	int	(*prepare_key)(struct ufs_hba *hba,
+			       const u8 *lt_key, size_t lt_key_size,
+			       u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
+	int	(*import_key)(struct ufs_hba *hba,
+			      const u8 *imp_key, size_t imp_key_size,
+			      u8 lt_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.43.0


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

* [PATCH v4 10/15] ufs: host: wrapped keys support in ufs qcom
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (8 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 09/15] ufs: core: add support for generate, import and prepare keys Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-02-05 18:59   ` Om Prakash Singh
  2024-01-27 23:14 ` [PATCH v4 11/15] ufs: host: implement derive sw secret vop " Gaurav Kashyap
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

Use the wrapped keys quirk when hwkm is supported/used.
Whether to use HWKM or not would be decided during an ICE
probe, and based on this information, UFS can decide to use
wrapped keys or standard keys.

Also, propagate the appropriate key size to the ICE driver
when wrapped keys are used.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/ufs/host/ufs-qcom.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index acf352594362..5c9ba06438a9 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -123,6 +123,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;
 }
@@ -160,7 +162,11 @@ static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
 	    cap.key_size != UFS_CRYPTO_KEY_SIZE_256)
 		return -EOPNOTSUPP;
 
-	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,
-- 
2.43.0


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

* [PATCH v4 11/15] ufs: host: implement derive sw secret vop in ufs qcom
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (9 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 10/15] ufs: host: wrapped keys support in ufs qcom Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-01-27 23:14 ` [PATCH v4 12/15] ufs: host: support for generate, import and prepare key Gaurav Kashyap
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

UFS core defines a variant op to tie the corresponding
derive software secret blk crypto op to the vendor specific
implementation of wrapped keys. This patch implements
this variant op.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/ufs/host/ufs-qcom.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 5c9ba06438a9..e319176accd3 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -176,9 +176,23 @@ static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
 		return qcom_ice_evict_key(host->ice, slot);
 }
 
+/*
+ * Derive a software secret from a hardware wrapped key. The key is unwrapped in
+ * hardware from trustzone and a software key/secret is then derived from it.
+ */
+static int ufs_qcom_ice_derive_sw_secret(struct ufs_hba *hba, const u8 wkey[],
+					 unsigned int wkey_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, wkey, wkey_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)
 {
@@ -1787,6 +1801,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.43.0


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

* [PATCH v4 12/15] ufs: host: support for generate, import and prepare key
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (10 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 11/15] ufs: host: implement derive sw secret vop " Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-01-27 23:14 ` [PATCH v4 13/15] dt-bindings: crypto: ice: document the hwkm property Gaurav Kashyap
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

UFS core defines a variant ops to tie the corresponding
generate, prepare and import wrapped key blk crypto ops
to the vendor specific implementation of wrapped keys.
This patch implements these variant ops.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Reviewed-by: Om Prakash Singh <quic_omprsing@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/ufs/host/ufs-qcom.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index e319176accd3..5de23ae0538c 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -189,10 +189,41 @@ static int ufs_qcom_ice_derive_sw_secret(struct ufs_hba *hba, const u8 wkey[],
 	return qcom_ice_derive_sw_secret(host->ice, wkey, wkey_size, sw_secret);
 }
 
+static int ufs_qcom_ice_generate_key(struct ufs_hba *hba,
+				     u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+	return qcom_ice_generate_key(host->ice, lt_key);
+}
+
+static int ufs_qcom_ice_prepare_key(struct ufs_hba *hba,
+				    const u8 *lt_key, size_t lt_key_size,
+				    u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+	return qcom_ice_prepare_key(host->ice, lt_key, lt_key_size,
+				    eph_key);
+}
+
+static int ufs_qcom_ice_import_key(struct ufs_hba *hba,
+				   const u8 *imp_key, size_t imp_key_size,
+				   u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+	return qcom_ice_import_key(host->ice, imp_key, imp_key_size,
+				   lt_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)
 {
@@ -1802,6 +1833,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.43.0


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

* [PATCH v4 13/15] dt-bindings: crypto: ice: document the hwkm property
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (11 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 12/15] ufs: host: support for generate, import and prepare key Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-01-29  8:18   ` Krzysztof Kozlowski
  2024-01-27 23:14 ` [PATCH v4 14/15] arm64: dts: qcom: sm8650: add hwkm support to ufs ice Gaurav Kashyap
  2024-01-27 23:14 ` [PATCH v4 15/15] arm64: dts: qcom: sm8550: " Gaurav Kashyap
  14 siblings, 1 reply; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

When Qualcomm's Inline Crypto Engine (ICE) contains Hardware
Key Manager (HWKM), and the 'HWKM' mode is enabled, it
supports wrapped keys. However, this also requires firmware
support in Trustzone to work correctly, which may not be available
on all chipsets. In the above scenario, ICE needs to support standard
keys even though HWKM is integrated from a hardware perspective.

Introducing this property so that Hardware wrapped key support
can be enabled/disabled from software based on chipset firmware,
and not just based on hardware version.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 .../bindings/crypto/qcom,inline-crypto-engine.yaml     | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
index 09e43157cc71..6415d7be9b73 100644
--- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
+++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
@@ -25,6 +25,16 @@ properties:
   clocks:
     maxItems: 1
 
+  qcom,ice-use-hwkm:
+    type: boolean
+    description:
+      Use the supported Hardware Key Manager (HWKM) in Qualcomm ICE
+      to support wrapped keys. Having this entry helps scenarios where
+      the ICE hardware supports HWKM, but the Trustzone firmware does
+      not have the full capability to use this HWKM and support wrapped
+      keys. Not having this entry enabled would make ICE function in
+      non-HWKM mode supporting standard keys.
+
 required:
   - compatible
   - reg
-- 
2.43.0


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

* [PATCH v4 14/15] arm64: dts: qcom: sm8650: add hwkm support to ufs ice
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (12 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 13/15] dt-bindings: crypto: ice: document the hwkm property Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-01-29  8:15   ` Krzysztof Kozlowski
  2024-01-27 23:14 ` [PATCH v4 15/15] arm64: dts: qcom: sm8550: " Gaurav Kashyap
  14 siblings, 1 reply; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

The Inline Crypto Engine (ICE) for UFS/EMMC supports the
Hardware Key Manager (HWKM) to securely manage storage
keys. Enable using this hardware on sm8650.

This requires two changes:
1. Register size increase: HWKM is an additional piece of hardware
   sitting alongside ICE, and extends the old ICE's register space.
2. Explicitly tell the ICE driver to use HWKM with ICE so that
   wrapped keys are used in sm8650.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
Reviewed-by: Om Prakash Singh <quic_omprsing@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 arch/arm64/boot/dts/qcom/sm8650.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
index 2df77123a8c7..c27daf576af5 100644
--- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
@@ -2524,7 +2524,8 @@ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
 		ice: crypto@1d88000 {
 			compatible = "qcom,sm8650-inline-crypto-engine",
 				     "qcom,inline-crypto-engine";
-			reg = <0 0x01d88000 0 0x8000>;
+			reg = <0 0x01d88000 0 0x10000>;
+			qcom,ice-use-hwkm;
 
 			clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
 		};
-- 
2.43.0


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

* [PATCH v4 15/15] arm64: dts: qcom: sm8550: add hwkm support to ufs ice
  2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
                   ` (13 preceding siblings ...)
  2024-01-27 23:14 ` [PATCH v4 14/15] arm64: dts: qcom: sm8650: add hwkm support to ufs ice Gaurav Kashyap
@ 2024-01-27 23:14 ` Gaurav Kashyap
  2024-01-28  1:01   ` Dmitry Baryshkov
  14 siblings, 1 reply; 37+ messages in thread
From: Gaurav Kashyap @ 2024-01-27 23:14 UTC (permalink / raw)
  To: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

The Inline Crypto Engine (ICE) for UFS/EMMC supports the
Hardware Key Manager (HWKM) to securely manage storage
keys. Enable using this hardware on sm8550.

This requires two changes:
1. Register size increase: HWKM is an additional piece of hardware
   sitting alongside ICE, and extends the old ICE's register space.
2. Explicitly tell the ICE driver to use HWKM with ICE so that
   wrapped keys are used in sm8550.

NOTE: Although wrapped keys cannot be independently generated and
tested on this platform using generate, prepare and import key calls,
there are non-kernel paths to create wrapped keys, and still use the
kernel to program them into ICE. Hence, enabling wrapped key support
on sm8550 too.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 arch/arm64/boot/dts/qcom/sm8550.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi
index ee1ba5a8c8fc..b5b41d0a544c 100644
--- a/arch/arm64/boot/dts/qcom/sm8550.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi
@@ -1977,7 +1977,8 @@ ufs_mem_hc: ufs@1d84000 {
 		ice: crypto@1d88000 {
 			compatible = "qcom,sm8550-inline-crypto-engine",
 				     "qcom,inline-crypto-engine";
-			reg = <0 0x01d88000 0 0x8000>;
+			reg = <0 0x01d88000 0 0x10000>;
+			qcom,ice-use-hwkm;
 			clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
 		};
 
-- 
2.43.0


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

* Re: [PATCH v4 15/15] arm64: dts: qcom: sm8550: add hwkm support to ufs ice
  2024-01-27 23:14 ` [PATCH v4 15/15] arm64: dts: qcom: sm8550: " Gaurav Kashyap
@ 2024-01-28  1:01   ` Dmitry Baryshkov
  2024-02-01  9:55     ` Om Prakash Singh
  0 siblings, 1 reply; 37+ messages in thread
From: Dmitry Baryshkov @ 2024-01-28  1:01 UTC (permalink / raw)
  To: Gaurav Kashyap
  Cc: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt,
	linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert

On Sun, 28 Jan 2024 at 01:28, Gaurav Kashyap <quic_gaurkash@quicinc.com> wrote:
>
> The Inline Crypto Engine (ICE) for UFS/EMMC supports the
> Hardware Key Manager (HWKM) to securely manage storage
> keys. Enable using this hardware on sm8550.
>
> This requires two changes:
> 1. Register size increase: HWKM is an additional piece of hardware
>    sitting alongside ICE, and extends the old ICE's register space.
> 2. Explicitly tell the ICE driver to use HWKM with ICE so that
>    wrapped keys are used in sm8550.
>
> NOTE: Although wrapped keys cannot be independently generated and
> tested on this platform using generate, prepare and import key calls,
> there are non-kernel paths to create wrapped keys, and still use the
> kernel to program them into ICE. Hence, enabling wrapped key support
> on sm8550 too.
>
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> ---
>  arch/arm64/boot/dts/qcom/sm8550.dtsi | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi
> index ee1ba5a8c8fc..b5b41d0a544c 100644
> --- a/arch/arm64/boot/dts/qcom/sm8550.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi
> @@ -1977,7 +1977,8 @@ ufs_mem_hc: ufs@1d84000 {
>                 ice: crypto@1d88000 {
>                         compatible = "qcom,sm8550-inline-crypto-engine",
>                                      "qcom,inline-crypto-engine";
> -                       reg = <0 0x01d88000 0 0x8000>;
> +                       reg = <0 0x01d88000 0 0x10000>;

Does the driver fail gracefully with the old DT size? At least it
should not crash.

> +                       qcom,ice-use-hwkm;
>                         clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;

-- 
With best wishes
Dmitry

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

* Re: [PATCH v4 14/15] arm64: dts: qcom: sm8650: add hwkm support to ufs ice
  2024-01-27 23:14 ` [PATCH v4 14/15] arm64: dts: qcom: sm8650: add hwkm support to ufs ice Gaurav Kashyap
@ 2024-01-29  8:15   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 37+ messages in thread
From: Krzysztof Kozlowski @ 2024-01-29  8:15 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert

On 28/01/2024 00:14, Gaurav Kashyap wrote:
> The Inline Crypto Engine (ICE) for UFS/EMMC supports the
> Hardware Key Manager (HWKM) to securely manage storage
> keys. Enable using this hardware on sm8650.
> 
> This requires two changes:
> 1. Register size increase: HWKM is an additional piece of hardware
>    sitting alongside ICE, and extends the old ICE's register space.
> 2. Explicitly tell the ICE driver to use HWKM with ICE so that
>    wrapped keys are used in sm8650.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Reviewed-by: Om Prakash Singh <quic_omprsing@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  arch/arm64/boot/dts/qcom/sm8650.dtsi | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
> index 2df77123a8c7..c27daf576af5 100644
> --- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
> @@ -2524,7 +2524,8 @@ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
>  		ice: crypto@1d88000 {
>  			compatible = "qcom,sm8650-inline-crypto-engine",
>  				     "qcom,inline-crypto-engine";
> -			reg = <0 0x01d88000 0 0x8000>;
> +			reg = <0 0x01d88000 0 0x10000>;
> +			qcom,ice-use-hwkm;

Vendor properties go to the end. Please consult DTS coding style.

Best regards,
Krzysztof


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

* Re: [PATCH v4 13/15] dt-bindings: crypto: ice: document the hwkm property
  2024-01-27 23:14 ` [PATCH v4 13/15] dt-bindings: crypto: ice: document the hwkm property Gaurav Kashyap
@ 2024-01-29  8:18   ` Krzysztof Kozlowski
  2024-02-01 19:13     ` Konrad Dybcio
  0 siblings, 1 reply; 37+ messages in thread
From: Krzysztof Kozlowski @ 2024-01-29  8:18 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert

On 28/01/2024 00:14, Gaurav Kashyap wrote:
> When Qualcomm's Inline Crypto Engine (ICE) contains Hardware
> Key Manager (HWKM), and the 'HWKM' mode is enabled, it
> supports wrapped keys. However, this also requires firmware
> support in Trustzone to work correctly, which may not be available
> on all chipsets. In the above scenario, ICE needs to support standard
> keys even though HWKM is integrated from a hardware perspective.
> 
> Introducing this property so that Hardware wrapped key support
> can be enabled/disabled from software based on chipset firmware,
> and not just based on hardware version.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  .../bindings/crypto/qcom,inline-crypto-engine.yaml     | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
> index 09e43157cc71..6415d7be9b73 100644
> --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
> +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
> @@ -25,6 +25,16 @@ properties:
>    clocks:
>      maxItems: 1
>  
> +  qcom,ice-use-hwkm:
> +    type: boolean
> +    description:
> +      Use the supported Hardware Key Manager (HWKM) in Qualcomm ICE
> +      to support wrapped keys. Having this entry helps scenarios where
> +      the ICE hardware supports HWKM, but the Trustzone firmware does
> +      not have the full capability to use this HWKM and support wrapped

How does it help in this scenario? You enable this property, Trustzone
does not support it, so what happens?

Also, which SoCs have incomplete Trustzone support? I expect this to be
a quirk, thus limited to specific SoCs with issues.

Best regards,
Krzysztof


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

* Re: [PATCH v4 02/15] qcom_scm: scm call for deriving a software secret
  2024-01-27 23:14 ` [PATCH v4 02/15] qcom_scm: scm call for deriving a software secret Gaurav Kashyap
@ 2024-01-30  4:43   ` Bjorn Andersson
  2024-02-01 16:11   ` Konrad Dybcio
  1 sibling, 0 replies; 37+ messages in thread
From: Bjorn Andersson @ 2024-01-30  4:43 UTC (permalink / raw)
  To: Gaurav Kashyap
  Cc: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt,
	linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert

On Sat, Jan 27, 2024 at 03:14:00PM -0800, Gaurav Kashyap wrote:

The subject prefix does not match other changes to this file.

> Inline storage encryption may require deriving a software
> secret from storage keys added to the kernel.
> 
> For non-wrapped keys, this can be directly done in the kernel as
> keys are in the clear.
> 
> However, hardware wrapped keys can only be unwrapped by the wrapping
> entity. In case of Qualcomm's wrapped key solution, this is done by
> the Hardware Key Manager (HWKM) from Trustzone.
> Hence, adding a new SCM call which in the end provides a hook
> to the software secret crypto profile API provided by the block
> layer.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  drivers/firmware/qcom/qcom_scm.c       | 65 ++++++++++++++++++++++++++
>  drivers/firmware/qcom/qcom_scm.h       |  1 +
>  include/linux/firmware/qcom/qcom_scm.h |  2 +
>  3 files changed, 68 insertions(+)
> 
> diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
> index 7e17fd662bda..4882f8a36453 100644
> --- a/drivers/firmware/qcom/qcom_scm.c
> +++ b/drivers/firmware/qcom/qcom_scm.c
> @@ -1220,6 +1220,71 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
>  }
>  EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key);
>  
> +/**
> + * qcom_scm_derive_sw_secret() - Derive software secret from wrapped key
> + * @wkey: the hardware wrapped key inaccessible to software
> + * @wkey_size: size of the wrapped key
> + * @sw_secret: the secret to be derived which is exactly the secret size
> + * @sw_secret_size: size of the sw_secret
> + *
> + * Derive a software secret from a hardware wrapped key for software crypto
> + * operations.
> + * For wrapped keys, the key needs to be unwrapped, in order to derive a
> + * software secret, which can be done in the hardware from a secure execution
> + * environment.
> + *
> + * 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 *wkey, size_t wkey_size,
> +			      u8 *sw_secret, size_t sw_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] = wkey_size,
> +		.args[3] = sw_secret_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *secret_buf;
> +	void *wkey_buf;
> +	int ret;
> +
> +	wkey_buf = qcom_tzmem_alloc(__scm->mempool, wkey_size, GFP_KERNEL);
> +	if (!wkey_buf)
> +		return -ENOMEM;
> +
> +	secret_buf = qcom_tzmem_alloc(__scm->mempool, sw_secret_size, GFP_KERNEL);
> +	if (!secret_buf) {
> +		ret = -ENOMEM;
> +		goto err_free_wrapped;
> +	}
> +
> +	memcpy(wkey_buf, wkey, wkey_size);
> +	desc.args[0] = qcom_tzmem_to_phys(wkey_buf);
> +	desc.args[2] = qcom_tzmem_to_phys(secret_buf);
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	if (!ret)
> +		memcpy(sw_secret, secret_buf, sw_secret_size);
> +
> +	memzero_explicit(secret_buf, sw_secret_size);
> +	qcom_tzmem_free(secret_buf);
> +
> +err_free_wrapped:

This code path is shared between error path and normal path, prefixing
it "err_" is not helpful to the reader. Please change this to
out_free_wrapped:

The rest of the patch looks good to me.

Regards,
Bjorn

> +	memzero_explicit(wkey_buf, wkey_size);
> +	qcom_tzmem_free(wkey_buf);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
> +
>  /**
>   * qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
>   *
> diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h
> index cb7273aa0a5e..56ff0806f5d2 100644
> --- a/drivers/firmware/qcom/qcom_scm.h
> +++ b/drivers/firmware/qcom/qcom_scm.h
> @@ -127,6 +127,7 @@ struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void);
>  #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 9b6054813f59..89358478ac67 100644
> --- a/include/linux/firmware/qcom/qcom_scm.h
> +++ b/include/linux/firmware/qcom/qcom_scm.h
> @@ -103,6 +103,8 @@ bool qcom_scm_ice_available(void);
>  int qcom_scm_ice_invalidate_key(u32 index);
>  int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
>  			 enum qcom_scm_ice_cipher cipher, u32 data_unit_size);
> +int qcom_scm_derive_sw_secret(const u8 *wkey, size_t wkey_size,
> +			      u8 *sw_secret, size_t sw_secret_size);
>  
>  bool qcom_scm_hdcp_available(void);
>  int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
> -- 
> 2.43.0
> 

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

* Re: [PATCH v4 15/15] arm64: dts: qcom: sm8550: add hwkm support to ufs ice
  2024-01-28  1:01   ` Dmitry Baryshkov
@ 2024-02-01  9:55     ` Om Prakash Singh
  2024-02-01 13:59       ` neil.armstrong
  0 siblings, 1 reply; 37+ messages in thread
From: Om Prakash Singh @ 2024-02-01  9:55 UTC (permalink / raw)
  To: Dmitry Baryshkov, Gaurav Kashyap
  Cc: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt,
	linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_nguyenb, bartosz.golaszewski, konrad.dybcio, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert



On 1/28/2024 6:31 AM, Dmitry Baryshkov wrote:
> On Sun, 28 Jan 2024 at 01:28, Gaurav Kashyap <quic_gaurkash@quicinc.com> wrote:
>>
>> The Inline Crypto Engine (ICE) for UFS/EMMC supports the
>> Hardware Key Manager (HWKM) to securely manage storage
>> keys. Enable using this hardware on sm8550.
>>
>> This requires two changes:
>> 1. Register size increase: HWKM is an additional piece of hardware
>>     sitting alongside ICE, and extends the old ICE's register space.
>> 2. Explicitly tell the ICE driver to use HWKM with ICE so that
>>     wrapped keys are used in sm8550.
>>
>> NOTE: Although wrapped keys cannot be independently generated and
>> tested on this platform using generate, prepare and import key calls,
>> there are non-kernel paths to create wrapped keys, and still use the
>> kernel to program them into ICE. Hence, enabling wrapped key support
>> on sm8550 too.
>>
>> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
>> ---
>>   arch/arm64/boot/dts/qcom/sm8550.dtsi | 3 ++-
>>   1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi
>> index ee1ba5a8c8fc..b5b41d0a544c 100644
>> --- a/arch/arm64/boot/dts/qcom/sm8550.dtsi
>> +++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi
>> @@ -1977,7 +1977,8 @@ ufs_mem_hc: ufs@1d84000 {
>>                  ice: crypto@1d88000 {
>>                          compatible = "qcom,sm8550-inline-crypto-engine",
>>                                       "qcom,inline-crypto-engine";
>> -                       reg = <0 0x01d88000 0 0x8000>;
>> +                       reg = <0 0x01d88000 0 0x10000>;
> 
> Does the driver fail gracefully with the old DT size? At least it
> should not crash.
When adding  qcom,ice-use-hwkm property, DT size needs to be updated.
Without any DT change, there will be know issue.

> 
>> +                       qcom,ice-use-hwkm;
>>                          clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
> 

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

* Re: [PATCH v4 15/15] arm64: dts: qcom: sm8550: add hwkm support to ufs ice
  2024-02-01  9:55     ` Om Prakash Singh
@ 2024-02-01 13:59       ` neil.armstrong
  0 siblings, 0 replies; 37+ messages in thread
From: neil.armstrong @ 2024-02-01 13:59 UTC (permalink / raw)
  To: Om Prakash Singh, Dmitry Baryshkov, Gaurav Kashyap
  Cc: linux-arm-msm, linux-scsi, andersson, ebiggers,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt,
	linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_nguyenb, bartosz.golaszewski, konrad.dybcio, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert

On 01/02/2024 10:55, Om Prakash Singh wrote:
> 
> 
> On 1/28/2024 6:31 AM, Dmitry Baryshkov wrote:
>> On Sun, 28 Jan 2024 at 01:28, Gaurav Kashyap <quic_gaurkash@quicinc.com> wrote:
>>>
>>> The Inline Crypto Engine (ICE) for UFS/EMMC supports the
>>> Hardware Key Manager (HWKM) to securely manage storage
>>> keys. Enable using this hardware on sm8550.
>>>
>>> This requires two changes:
>>> 1. Register size increase: HWKM is an additional piece of hardware
>>>     sitting alongside ICE, and extends the old ICE's register space.
>>> 2. Explicitly tell the ICE driver to use HWKM with ICE so that
>>>     wrapped keys are used in sm8550.
>>>
>>> NOTE: Although wrapped keys cannot be independently generated and
>>> tested on this platform using generate, prepare and import key calls,
>>> there are non-kernel paths to create wrapped keys, and still use the
>>> kernel to program them into ICE. Hence, enabling wrapped key support
>>> on sm8550 too.
>>>
>>> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
>>> ---
>>>   arch/arm64/boot/dts/qcom/sm8550.dtsi | 3 ++-
>>>   1 file changed, 2 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi
>>> index ee1ba5a8c8fc..b5b41d0a544c 100644
>>> --- a/arch/arm64/boot/dts/qcom/sm8550.dtsi
>>> +++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi
>>> @@ -1977,7 +1977,8 @@ ufs_mem_hc: ufs@1d84000 {
>>>                  ice: crypto@1d88000 {
>>>                          compatible = "qcom,sm8550-inline-crypto-engine",
>>>                                       "qcom,inline-crypto-engine";
>>> -                       reg = <0 0x01d88000 0 0x8000>;
>>> +                       reg = <0 0x01d88000 0 0x10000>;
>>
>> Does the driver fail gracefully with the old DT size? At least it
>> should not crash.
> When adding  qcom,ice-use-hwkm property, DT size needs to be updated.
> Without any DT change, there will be know issue.

This must be fixed in the code because new kernels could be run with older
DTs, so it should not fail with older DTs.

In this case, simply disable the HWKM if size from DT is too small.

Neil

> 
>>
>>> +                       qcom,ice-use-hwkm;
>>>                          clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
>>


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

* Re: [PATCH v4 02/15] qcom_scm: scm call for deriving a software secret
  2024-01-27 23:14 ` [PATCH v4 02/15] qcom_scm: scm call for deriving a software secret Gaurav Kashyap
  2024-01-30  4:43   ` Bjorn Andersson
@ 2024-02-01 16:11   ` Konrad Dybcio
  2024-02-06 11:56     ` Bartosz Golaszewski
  1 sibling, 1 reply; 37+ messages in thread
From: Konrad Dybcio @ 2024-02-01 16:11 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert

On 28.01.2024 00:14, Gaurav Kashyap wrote:
> Inline storage encryption may require deriving a software
> secret from storage keys added to the kernel.
> 
> For non-wrapped keys, this can be directly done in the kernel as
> keys are in the clear.
> 
> However, hardware wrapped keys can only be unwrapped by the wrapping
> entity. In case of Qualcomm's wrapped key solution, this is done by
> the Hardware Key Manager (HWKM) from Trustzone.
> Hence, adding a new SCM call which in the end provides a hook
> to the software secret crypto profile API provided by the block
> layer.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  drivers/firmware/qcom/qcom_scm.c       | 65 ++++++++++++++++++++++++++
>  drivers/firmware/qcom/qcom_scm.h       |  1 +
>  include/linux/firmware/qcom/qcom_scm.h |  2 +
>  3 files changed, 68 insertions(+)
> 
> diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
> index 7e17fd662bda..4882f8a36453 100644
> --- a/drivers/firmware/qcom/qcom_scm.c
> +++ b/drivers/firmware/qcom/qcom_scm.c
> @@ -1220,6 +1220,71 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
>  }
>  EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key);
>  
> +/**
> + * qcom_scm_derive_sw_secret() - Derive software secret from wrapped key
> + * @wkey: the hardware wrapped key inaccessible to software
> + * @wkey_size: size of the wrapped key
> + * @sw_secret: the secret to be derived which is exactly the secret size
> + * @sw_secret_size: size of the sw_secret
> + *
> + * Derive a software secret from a hardware wrapped key for software crypto
> + * operations.
> + * For wrapped keys, the key needs to be unwrapped, in order to derive a
> + * software secret, which can be done in the hardware from a secure execution
> + * environment.
> + *
> + * 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 *wkey, size_t wkey_size,
> +			      u8 *sw_secret, size_t sw_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] = wkey_size,
> +		.args[3] = sw_secret_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *secret_buf;
> +	void *wkey_buf;
> +	int ret;
> +
> +	wkey_buf = qcom_tzmem_alloc(__scm->mempool, wkey_size, GFP_KERNEL);
> +	if (!wkey_buf)
> +		return -ENOMEM;
> +
> +	secret_buf = qcom_tzmem_alloc(__scm->mempool, sw_secret_size, GFP_KERNEL);
> +	if (!secret_buf) {
> +		ret = -ENOMEM;
> +		goto err_free_wrapped;
> +	}
> +
> +	memcpy(wkey_buf, wkey, wkey_size);
> +	desc.args[0] = qcom_tzmem_to_phys(wkey_buf);
> +	desc.args[2] = qcom_tzmem_to_phys(secret_buf);
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	if (!ret)
> +		memcpy(sw_secret, secret_buf, sw_secret_size);
> +
> +	memzero_explicit(secret_buf, sw_secret_size);
> +	qcom_tzmem_free(secret_buf);
> +
> +err_free_wrapped:
> +	memzero_explicit(wkey_buf, wkey_size);
> +	qcom_tzmem_free(wkey_buf);
__free(qcom_tzmem) attribute instead?

Konrad


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

* Re: [PATCH v4 13/15] dt-bindings: crypto: ice: document the hwkm property
  2024-01-29  8:18   ` Krzysztof Kozlowski
@ 2024-02-01 19:13     ` Konrad Dybcio
  0 siblings, 0 replies; 37+ messages in thread
From: Konrad Dybcio @ 2024-02-01 19:13 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Gaurav Kashyap, linux-arm-msm, linux-scsi,
	andersson, ebiggers, neil.armstrong, srinivas.kandagatla,
	krzysztof.kozlowski+dt, conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert

On 29.01.2024 09:18, Krzysztof Kozlowski wrote:
> On 28/01/2024 00:14, Gaurav Kashyap wrote:
>> When Qualcomm's Inline Crypto Engine (ICE) contains Hardware
>> Key Manager (HWKM), and the 'HWKM' mode is enabled, it
>> supports wrapped keys. However, this also requires firmware
>> support in Trustzone to work correctly, which may not be available
>> on all chipsets. In the above scenario, ICE needs to support standard
>> keys even though HWKM is integrated from a hardware perspective.
>>
>> Introducing this property so that Hardware wrapped key support
>> can be enabled/disabled from software based on chipset firmware,
>> and not just based on hardware version.
>>
>> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
>> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
>> ---
>>  .../bindings/crypto/qcom,inline-crypto-engine.yaml     | 10 ++++++++++
>>  1 file changed, 10 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
>> index 09e43157cc71..6415d7be9b73 100644
>> --- a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
>> +++ b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
>> @@ -25,6 +25,16 @@ properties:
>>    clocks:
>>      maxItems: 1
>>  
>> +  qcom,ice-use-hwkm:
>> +    type: boolean
>> +    description:
>> +      Use the supported Hardware Key Manager (HWKM) in Qualcomm ICE
>> +      to support wrapped keys. Having this entry helps scenarios where
>> +      the ICE hardware supports HWKM, but the Trustzone firmware does
>> +      not have the full capability to use this HWKM and support wrapped
> 
> How does it help in this scenario? You enable this property, Trustzone
> does not support it, so what happens?
> 
> Also, which SoCs have incomplete Trustzone support? I expect this to be
> a quirk, thus limited to specific SoCs with issues.

Can we simply evaluate the return value of the secure calls?

Konrad

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

* Re: [EXTERNAL] [PATCH v4 04/15] soc: qcom: ice: add hwkm support in ice
  2024-01-27 23:14 ` [PATCH v4 04/15] soc: qcom: ice: add hwkm support in ice Gaurav Kashyap
@ 2024-02-04 18:32   ` Kamlesh Gurudasani
  2024-02-05 18:22   ` Om Prakash Singh
  1 sibling, 0 replies; 37+ messages in thread
From: Kamlesh Gurudasani @ 2024-02-04 18:32 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

Gaurav Kashyap <quic_gaurkash@quicinc.com> writes:

...

> +	/*
> +	 * 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;
From the code I understand that the last bit is used for setting the
mode.

Was wondering if it would make more sense to use ~BIT(0) or GENMASK
to generate this value and #define this value to express the work it
does.

In this case, something like #define xx_SET_MODE_MASK (~BIT(0)) or use GENMASK

This would make it easier for a person who is taking a look at the code
for first time. This is just my perspective.

If you do agree, you can change them at multiple places accross this
patch, wherever magic numbers are used for val and masking the value.

Regards,
Kamlesh

> +		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)
> +{
> +	/* Disable CRC checks. This HWKM feature is not used. */
> +	qcom_ice_writel(ice, 0x6,
> +			HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_CTL));
> +
> +	/*
> +	 * 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));
> +
> +	/* Clear HWKM response FIFO before doing anything */
> +	qcom_ice_writel(ice, 0x8, HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STATUS));
> +	ice->hwkm_init_complete = true;
> +}

...

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

* Re: [EXTERNAL] [PATCH v4 05/15] soc: qcom: ice: support for hardware wrapped keys
  2024-01-27 23:14 ` [PATCH v4 05/15] soc: qcom: ice: support for hardware wrapped keys Gaurav Kashyap
@ 2024-02-04 19:30   ` Kamlesh Gurudasani
  2024-02-05 18:38   ` Om Prakash Singh
  1 sibling, 0 replies; 37+ messages in thread
From: Kamlesh Gurudasani @ 2024-02-04 19:30 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	ulf.hansson, jejb, martin.petersen, mani, davem, herbert,
	Gaurav Kashyap

Gaurav Kashyap <quic_gaurkash@quicinc.com> writes:

> This message was sent from outside of Texas Instruments. 
> Do not click links or open attachments unless you recognize the source of this email and know the content is safe. 
>  
> 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). This is
> similar to standard keys where the call is forwarded to
> Trustzone, however certain wrapped key and HWKM specific
> actions has to be performed around the SCM calls.
>
> Derive software secret support is also added by forwarding the
> call to the corresponding scm api.
>
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  drivers/soc/qcom/ice.c | 119 +++++++++++++++++++++++++++++++++++++----
>  include/soc/qcom/ice.h |   4 ++
>  2 files changed, 112 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
> index c718e8153b23..c3b852269dca 100644
> --- a/drivers/soc/qcom/ice.c
> +++ b/drivers/soc/qcom/ice.c
> @@ -27,6 +27,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
> @@ -48,6 +50,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)
>  
> @@ -68,6 +72,16 @@ struct qcom_ice {
>  	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)
>  {
>  	u32 regval = qcom_ice_readl(ice, QCOM_ICE_REG_VERSION);
> @@ -273,6 +287,51 @@ 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. For v1 however, the translation is done in trustzone.
> + */
> +static int translate_hwkm_slot(struct qcom_ice *ice, int slot)
> +{
> +	return (ice->hwkm_version == 1) ? slot : (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)
> +{
> +	union crypto_cfg cfg;
> +	int hwkm_slot;
> +	int err;
> +
> +	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;
> +
This is a clever use of union, writing from one member and
reading from inactive member.

I hope this a common practice in linux(being used in some other module
already) or fits the standard of C or will give deterministic result on
other compilers as well. Thanks.

Regards,
Kamlesh

> +	/* 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,
> @@ -288,24 +347,39 @@ 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) {
> +		/* It is expected that HWKM init has completed before programming wrapped keys */
> +		if (!ice->use_hwkm || !ice->hwkm_init_complete) {
> +			dev_err_ratelimited(dev, "HWKM not currently used or initialized\n");
> +			return -EINVAL;
> +		}
> +		err = qcom_ice_program_wrapped_key(ice, bkey, data_unit_size,
> +						   slot);
> +	} 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;
>  }
> @@ -313,7 +387,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->use_hwkm) {
> +		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);
>  
> @@ -323,6 +411,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 wkey[],
> +			      unsigned int wkey_size,
> +			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
> +{
> +	return qcom_scm_derive_sw_secret(wkey, wkey_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..dabe0d3a1fd0 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 wkey[],
> +			      unsigned int wkey_size,
> +			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
>  struct qcom_ice *of_qcom_ice_get(struct device *dev);
>  #endif /* __QCOM_ICE_H__ */
> -- 
> 2.43.0

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

* Re: [PATCH v4 03/15] qcom_scm: scm call for create, prepare and import keys
  2024-01-27 23:14 ` [PATCH v4 03/15] qcom_scm: scm call for create, prepare and import keys Gaurav Kashyap
@ 2024-02-05 18:03   ` Om Prakash Singh
  2024-02-06 11:59   ` Bartosz Golaszewski
  1 sibling, 0 replies; 37+ messages in thread
From: Om Prakash Singh @ 2024-02-05 18:03 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_nguyenb, bartosz.golaszewski, konrad.dybcio, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert



On 1/28/2024 4:44 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 Qualcomm's Trustzone, 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>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>   drivers/firmware/qcom/qcom_scm.c       | 182 +++++++++++++++++++++++++
>   drivers/firmware/qcom/qcom_scm.h       |   3 +
>   include/linux/firmware/qcom/qcom_scm.h |   5 +
>   3 files changed, 190 insertions(+)
> 
> diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
> index 4882f8a36453..20dbab765c8e 100644
> --- a/drivers/firmware/qcom/qcom_scm.c
> +++ b/drivers/firmware/qcom/qcom_scm.c
> @@ -1285,6 +1285,188 @@ int qcom_scm_derive_sw_secret(const u8 *wkey, size_t wkey_size,
>   }
>   EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
>   
> +/**
> + * qcom_scm_generate_ice_key() - Generate a wrapped key for encryption.
> + * @lt_key: the wrapped key returned after key generation
> + * @lt_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.
> + *
> + * Adds support for the create key IOCTL to interface
> + * with the secure environment to generate and return a wrapped key..
> + *
> + * Return: longterm key size on success; -errno on failure.
Why to return parameter input value? already has it. returning 0 on 
success should be the standard unless the returned key size would change.
> + */
> +int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_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] = lt_key_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *lt_key_buf;
> +	int ret;
> +
> +	lt_key_buf = qcom_tzmem_alloc(__scm->mempool, lt_key_size, GFP_KERNEL);
> +	if (!lt_key_buf)
> +		return -ENOMEM;
> +
> +	desc.args[0] = qcom_tzmem_to_phys(lt_key_buf);
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	if (!ret)
> +		memcpy(lt_key, lt_key_buf, lt_key_size);
> +
> +	memzero_explicit(lt_key_buf, lt_key_size);
> +	qcom_tzmem_free(lt_key_buf);
> +
> +	if (!ret)
> +		return lt_key_size;
return 0 on success. lt_key_size is input value. Caller already has it.
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key);
> +
> +/**
> + * qcom_scm_prepare_ice_key() - Get per boot ephemeral wrapped key
> + * @lt_key: the longterm wrapped key
> + * @lt_key_size: size of the wrapped key
> + * @eph_key: ephemeral wrapped key to be returned
> + * @eph_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.
> + *
> + * Adds support for the create key IOCTL to interface
> + * with the secure environment to rewrap the wrapped key with an
> + * ephemeral wrapping key.
> + *
> + * Return: ephemeral key size on success; -errno on failure.
> + */
> +int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
> +			     u8 *eph_key, size_t eph_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] = lt_key_size,
> +		.args[3] = eph_key_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *eph_key_buf;
> +	void *lt_key_buf;
> +	int ret;
> +
> +	lt_key_buf = qcom_tzmem_alloc(__scm->mempool, lt_key_size, GFP_KERNEL);
> +	if (!lt_key_buf)
> +		return -ENOMEM;
> +	eph_key_buf = qcom_tzmem_alloc(__scm->mempool, eph_key_size, GFP_KERNEL);
> +	if (!eph_key_buf) {
> +		ret = -ENOMEM;
> +		goto err_free_longterm;
> +	}
> +
> +	memcpy(lt_key_buf, lt_key, lt_key_size);
> +	desc.args[0] = qcom_tzmem_to_phys(lt_key_buf);
> +	desc.args[2] = qcom_tzmem_to_phys(eph_key_buf);
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	if (!ret)
> +		memcpy(eph_key, eph_key_buf, eph_key_size);
> +
> +	memzero_explicit(eph_key_buf, eph_key_size);
> +	qcom_tzmem_free(eph_key_buf);
> +
> +err_free_longterm:
> +	memzero_explicit(lt_key_buf, lt_key_size);
> +	qcom_tzmem_free(lt_key_buf);
> +
> +	if (!ret)
> +		return eph_key_size;
return 0 on success. eph_key_size is input value. Caller already has it.
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key);
> +
> +/**
> + * qcom_scm_import_ice_key() - Import a wrapped key for encryption
> + * @imp_key: the raw key that is imported
> + * @imp_key_size: size of the key to be imported
> + * @lt_key: the wrapped key to be returned
> + * @lt_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.
> + *
> + * 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: longterm key size on success; -errno on failure.
> + */
> +int qcom_scm_import_ice_key(const u8 *imp_key, size_t imp_key_size,
> +			    u8 *lt_key, size_t lt_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] = imp_key_size,
> +		.args[3] = lt_key_size,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +	};
> +
> +	void *imp_key_buf;
> +	void *lt_key_buf;
> +	int ret;
> +
> +	imp_key_buf = qcom_tzmem_alloc(__scm->mempool, imp_key_size, GFP_KERNEL);
> +	if (!imp_key_buf)
> +		return -ENOMEM;
> +	lt_key_buf = qcom_tzmem_alloc(__scm->mempool, lt_key_size, GFP_KERNEL);
> +	if (!lt_key_buf) {
> +		ret = -ENOMEM;
> +		goto err_free_longterm;
> +	}
> +
> +	memcpy(imp_key_buf, imp_key, imp_key_size);
> +	desc.args[0] = qcom_tzmem_to_phys(imp_key_buf);
> +	desc.args[2] = qcom_tzmem_to_phys(lt_key_buf);
> +
> +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> +	if (!ret)
> +		memcpy(lt_key, lt_key_buf, lt_key_size);
> +
> +	memzero_explicit(lt_key_buf, lt_key_size);
> +	qcom_tzmem_free(lt_key_buf);
> +
> +err_free_longterm:
> +	memzero_explicit(imp_key_buf, imp_key_size);
> +	qcom_tzmem_free(imp_key_buf);
> +
> +	if (!ret)
> +		return lt_key_size;
return 0 on success. lt_key_size is input value. Caller already has it.
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(qcom_scm_import_ice_key);
> +
>   /**
>    * qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
>    *
> diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h
> index 56ff0806f5d2..c30d6383b6de 100644
> --- a/drivers/firmware/qcom/qcom_scm.h
> +++ b/drivers/firmware/qcom/qcom_scm.h
> @@ -128,6 +128,9 @@ struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void);
>   #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 89358478ac67..a0983a40bc09 100644
> --- a/include/linux/firmware/qcom/qcom_scm.h
> +++ b/include/linux/firmware/qcom/qcom_scm.h
> @@ -105,6 +105,11 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
>   			 enum qcom_scm_ice_cipher cipher, u32 data_unit_size);
>   int qcom_scm_derive_sw_secret(const u8 *wkey, size_t wkey_size,
>   			      u8 *sw_secret, size_t sw_secret_size);
> +int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size);
> +int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
> +			     u8 *eph_key, size_t eph_size);
> +int qcom_scm_import_ice_key(const u8 *imp_key, size_t imp_size,
> +			    u8 *lt_key, size_t lt_key_size);
>   
>   bool qcom_scm_hdcp_available(void);
>   int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);

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

* Re: [PATCH v4 04/15] soc: qcom: ice: add hwkm support in ice
  2024-01-27 23:14 ` [PATCH v4 04/15] soc: qcom: ice: add hwkm support in ice Gaurav Kashyap
  2024-02-04 18:32   ` [EXTERNAL] " Kamlesh Gurudasani
@ 2024-02-05 18:22   ` Om Prakash Singh
  1 sibling, 0 replies; 37+ messages in thread
From: Om Prakash Singh @ 2024-02-05 18:22 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_nguyenb, bartosz.golaszewski, konrad.dybcio, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert



On 1/28/2024 4:44 AM, 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.
> 
> When HWKM software support is not fully available (from Trustzone),
> there can be a scenario where the ICE hardware supports HWKM, but
> it cannot be used for wrapped keys. In this case, standard keys have
> to be used without using HWKM. Hence, providing a toggle controlled
> by a devicetree entry to use HWKM or not.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>   drivers/soc/qcom/ice.c | 126 ++++++++++++++++++++++++++++++++++++++++-
>   include/soc/qcom/ice.h |   1 +
>   2 files changed, 124 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
> index 6f941d32fffb..c718e8153b23 100644
> --- a/drivers/soc/qcom/ice.c
> +++ b/drivers/soc/qcom/ice.c
> @@ -26,6 +26,20 @@
>   #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_BANKN_IRQ_STATUS	0x2008
> +#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
> +
> +/* QCOM ICE HWKM BIST vals */
> +#define QCOM_ICE_HWKM_BIST_DONE_V1_VAL		0x14007
> +#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)
> @@ -34,6 +48,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))
>   
> @@ -46,6 +63,9 @@ struct qcom_ice {
>   	struct device_link *link;
>   
>   	struct clk *core_clk;
> +	u8 hwkm_version;
> +	bool use_hwkm;
> +	bool hwkm_init_complete;
>   };
>   
>   static bool qcom_ice_check_supported(struct qcom_ice *ice)
> @@ -63,8 +83,21 @@ static bool qcom_ice_check_supported(struct qcom_ice *ice)
>   		return false;
>   	}
>   
> -	dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n",
> -		 major, minor, step);
> +	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;
> +
> +	if (ice->hwkm_version == 0)
> +		ice->use_hwkm = false;
> +
> +	dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d, HWKM v%d\n",
> +		 major, minor, step, ice->hwkm_version);
> +
> +	if (!ice->use_hwkm)
> +		dev_info(dev, "QC ICE HWKM (Hardware Key Manager) not used/supported");
>   
>   	/* If fuses are blown, ICE might not work in the standard way. */
>   	regval = qcom_ice_readl(ice, QCOM_ICE_REG_FUSE_SETTING);
> @@ -113,10 +146,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_reg;
>   	int err;
>   
>   	err = readl_poll_timeout(ice->base + QCOM_ICE_REG_BIST_STATUS,
> @@ -125,15 +162,85 @@ 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->use_hwkm) {
> +		bist_done_reg = (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_reg) {
> +			dev_err(ice->dev, "HWKM BIST error\n");
err is not upsated to capture this failure.
> +			ice->use_hwkm = false;
> +		}
> +	}
>   	return err;
>   }
>   
> +static void qcom_ice_enable_standard_mode(struct qcom_ice *ice)
> +{
> +	u32 val = 0;
> +
> +	/*
> +	 * 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;
do not use constant "0xFFFFFFFE". Better to define bits that are being set.
> +		qcom_ice_writel(ice, val, QCOM_ICE_REG_CONTROL);
> +	} else {
> +		qcom_ice_writel(ice, 0x7, HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_CTL));
do not use constant "0x7". Better to define bits that are being set.
> +	}
> +}
> +
> +static void qcom_ice_hwkm_init(struct qcom_ice *ice)
> +{
> +	/* Disable CRC checks. This HWKM feature is not used. */
> +	qcom_ice_writel(ice, 0x6,
> +			HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_CTL));
> +
> +	/*
> +	 * 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));
> +
> +	/* Clear HWKM response FIFO before doing anything */
> +	qcom_ice_writel(ice, 0x8, HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STATUS));
Do not use constant "0x8". Please define bits that are being set.
> +	ice->hwkm_init_complete = true;
> +}
> +
>   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);
> +	if (ice->use_hwkm)
> +		qcom_ice_enable_standard_mode(ice);
> +
> +	err = qcom_ice_wait_bist_status(ice);
> +	if (err)
> +		return err;
> +
> +	if (ice->use_hwkm)
> +		qcom_ice_hwkm_init(ice);
> +
> +	return err;
>   }
>   EXPORT_SYMBOL_GPL(qcom_ice_enable);
>   
> @@ -149,6 +256,10 @@ int qcom_ice_resume(struct qcom_ice *ice)
>   		return err;
>   	}
>   
> +	if (ice->use_hwkm) {
> +		qcom_ice_enable_standard_mode(ice);
> +		qcom_ice_hwkm_init(ice);
> +	}
>   	return qcom_ice_wait_bist_status(ice);
>   }
>   EXPORT_SYMBOL_GPL(qcom_ice_resume);
> @@ -156,6 +267,7 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume);
>   int qcom_ice_suspend(struct qcom_ice *ice)
>   {
>   	clk_disable_unprepare(ice->core_clk);
> +	ice->hwkm_init_complete = false;
>   
>   	return 0;
>   }
> @@ -205,6 +317,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->use_hwkm;
> +}
> +EXPORT_SYMBOL_GPL(qcom_ice_hwkm_supported);
> +
>   static struct qcom_ice *qcom_ice_create(struct device *dev,
>   					void __iomem *base)
>   {
> @@ -239,6 +357,8 @@ static struct qcom_ice *qcom_ice_create(struct device *dev,
>   		engine->core_clk = devm_clk_get_enabled(dev, NULL);
>   	if (IS_ERR(engine->core_clk))
>   		return ERR_CAST(engine->core_clk);
> +	engine->use_hwkm = of_property_read_bool(dev->of_node,
> +						 "qcom,ice-use-hwkm");
>   
>   	if (!qcom_ice_check_supported(engine))
>   		return ERR_PTR(-EOPNOTSUPP);
> 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] 37+ messages in thread

* Re: [PATCH v4 05/15] soc: qcom: ice: support for hardware wrapped keys
  2024-01-27 23:14 ` [PATCH v4 05/15] soc: qcom: ice: support for hardware wrapped keys Gaurav Kashyap
  2024-02-04 19:30   ` [EXTERNAL] " Kamlesh Gurudasani
@ 2024-02-05 18:38   ` Om Prakash Singh
  1 sibling, 0 replies; 37+ messages in thread
From: Om Prakash Singh @ 2024-02-05 18:38 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_nguyenb, bartosz.golaszewski, konrad.dybcio, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert



On 1/28/2024 4:44 AM, 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). This is
> similar to standard keys where the call is forwarded to
> Trustzone, however certain wrapped key and HWKM specific
> actions has to be performed around the SCM calls.
> 
> Derive software secret support is also added by forwarding the
> call to the corresponding scm api.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
Reviewed-by: Om Prakash Singh <quic_omprsing@quicinc.com>

>   drivers/soc/qcom/ice.c | 119 +++++++++++++++++++++++++++++++++++++----
>   include/soc/qcom/ice.h |   4 ++
>   2 files changed, 112 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
> index c718e8153b23..c3b852269dca 100644
> --- a/drivers/soc/qcom/ice.c
> +++ b/drivers/soc/qcom/ice.c
> @@ -27,6 +27,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
> @@ -48,6 +50,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)
>   
> @@ -68,6 +72,16 @@ struct qcom_ice {
>   	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)
>   {
>   	u32 regval = qcom_ice_readl(ice, QCOM_ICE_REG_VERSION);
> @@ -273,6 +287,51 @@ 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. For v1 however, the translation is done in trustzone.
> + */
> +static int translate_hwkm_slot(struct qcom_ice *ice, int slot)
> +{
> +	return (ice->hwkm_version == 1) ? slot : (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)
> +{
> +	union crypto_cfg cfg;
> +	int hwkm_slot;
> +	int err;
> +
> +	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,
> @@ -288,24 +347,39 @@ 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) {
> +		/* It is expected that HWKM init has completed before programming wrapped keys */
> +		if (!ice->use_hwkm || !ice->hwkm_init_complete) {
> +			dev_err_ratelimited(dev, "HWKM not currently used or initialized\n");
> +			return -EINVAL;
> +		}
> +		err = qcom_ice_program_wrapped_key(ice, bkey, data_unit_size,
> +						   slot);
> +	} 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;
>   }
> @@ -313,7 +387,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->use_hwkm) {
> +		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);
>   
> @@ -323,6 +411,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 wkey[],
> +			      unsigned int wkey_size,
> +			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
> +{
> +	return qcom_scm_derive_sw_secret(wkey, wkey_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..dabe0d3a1fd0 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 wkey[],
> +			      unsigned int wkey_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] 37+ messages in thread

* Re: [PATCH v4 06/15] soc: qcom: ice: support for generate, import and prepare key
  2024-01-27 23:14 ` [PATCH v4 06/15] soc: qcom: ice: support for generate, import and prepare key Gaurav Kashyap
@ 2024-02-05 18:45   ` Om Prakash Singh
  0 siblings, 0 replies; 37+ messages in thread
From: Om Prakash Singh @ 2024-02-05 18:45 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_nguyenb, bartosz.golaszewski, konrad.dybcio, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert



On 1/28/2024 4:44 AM, Gaurav Kashyap wrote:
> Wrapped key creation and management using HWKM is currently
> supported only through Qualcomm's Trustzone.
> Three new SCM calls have already been added in the scm layer
> for this purpose.
> 
> This patch adds support for generate, prepare and import key
> apis in ICE module and hooks it up the scm calls defined for them.
> This will eventually plug into the new IOCTLS added for this
> usecase in the block layer.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>   drivers/soc/qcom/ice.c | 66 ++++++++++++++++++++++++++++++++++++++++++
>   include/soc/qcom/ice.h |  8 +++++
>   2 files changed, 74 insertions(+)
> 
> diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
> index c3b852269dca..93654ae704bf 100644
> --- a/drivers/soc/qcom/ice.c
> +++ b/drivers/soc/qcom/ice.c
> @@ -21,6 +21,13 @@
>   
>   #define AES_256_XTS_KEY_SIZE			64
>   
> +/*
> + * Wrapped key sizes that HWKM expects and manages is different for different
> + * versions of the hardware.
> + */
> +#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
> @@ -420,6 +427,65 @@ int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wkey[],
>   }
>   EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret);
>   
> +/**
> + * qcom_ice_generate_key() - Generate a wrapped key for inline encryption
> + * @lt_key: longterm 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: lt wrapped key size on success; err on failure.
> + */
you might consider to change return value based on comment on patch 3/15.
> +int qcom_ice_generate_key(struct qcom_ice *ice,
> +			  u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
> +{
> +	return qcom_scm_generate_ice_key(lt_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
> + * @lt_key: longterm wrapped key that is generated or imported.
> + * @lt_key_size: size of the longterm wrapped_key
> + * @eph_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: eph wrapped key size on success; err on failure.
> + */
> +int qcom_ice_prepare_key(struct qcom_ice *ice, const u8 *lt_key, size_t lt_key_size,
> +			 u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
> +{
> +	return qcom_scm_prepare_ice_key(lt_key, lt_key_size, eph_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
> + * @imp_key: raw key that has to be imported
> + * @imp_key_size: size of the imported key
> + * @lt_key: longterm 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 generate a longterm wrapped key using hwkm.
> + *
> + * Return: lt wrapped key size on success; err on failure.
> + */
> +int qcom_ice_import_key(struct qcom_ice *ice, const u8 *imp_key, size_t imp_key_size,
> +			u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
> +{
> +	return qcom_scm_import_ice_key(imp_key, imp_key_size, lt_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 dabe0d3a1fd0..dcf277d196ff 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 wkey[],
>   			      unsigned int wkey_size,
>   			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
> +int qcom_ice_generate_key(struct qcom_ice *ice,
> +			  u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
> +int qcom_ice_prepare_key(struct qcom_ice *ice,
> +			 const u8 *lt_key, size_t lt_key_size,
> +			 u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
> +int qcom_ice_import_key(struct qcom_ice *ice,
> +			const u8 *imp_key, size_t imp_key_size,
> +			u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
>   struct qcom_ice *of_qcom_ice_get(struct device *dev);
>   #endif /* __QCOM_ICE_H__ */

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

* Re: [PATCH v4 08/15] ufs: core: add support to derive software secret
  2024-01-27 23:14 ` [PATCH v4 08/15] ufs: core: add support to derive software secret Gaurav Kashyap
@ 2024-02-05 18:52   ` Om Prakash Singh
  0 siblings, 0 replies; 37+ messages in thread
From: Om Prakash Singh @ 2024-02-05 18:52 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_nguyenb, bartosz.golaszewski, konrad.dybcio, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert



On 1/28/2024 4:44 AM, Gaurav Kashyap wrote:
> Block crypto allows storage controllers like UFS to
> register an op derive a software secret from wrapped
> keys added to the kernel.
> 
> Wrapped keys in most cases will have vendor specific
> implementations, which means this op would need to have
> a corresponding UFS variant op.
> This change adds hooks in UFS core to support this variant
> ops and tie them to the blk crypto op.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
Reviewed-by: Om Prakash Singh <quic_omprsing@quicinc.com>

>   drivers/ufs/core/ufshcd-crypto.c | 15 +++++++++++++++
>   include/ufs/ufshcd.h             |  4 ++++
>   2 files changed, 19 insertions(+)
> 
> diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c
> index 399b55d67b3b..c14800eac1ff 100644
> --- a/drivers/ufs/core/ufshcd-crypto.c
> +++ b/drivers/ufs/core/ufshcd-crypto.c
> @@ -119,6 +119,20 @@ static int ufshcd_crypto_keyslot_evict(struct blk_crypto_profile *profile,
>   	return ufshcd_clear_keyslot(hba, slot);
>   }
>   
> +static int ufshcd_crypto_derive_sw_secret(struct blk_crypto_profile *profile,
> +					  const u8 wkey[], size_t wkey_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, wkey, wkey_size,
> +						    sw_secret);
> +
> +	return -EOPNOTSUPP;
> +}
> +
>   bool ufshcd_crypto_enable(struct ufs_hba *hba)
>   {
>   	if (!(hba->caps & UFSHCD_CAP_CRYPTO))
> @@ -132,6 +146,7 @@ bool ufshcd_crypto_enable(struct ufs_hba *hba)
>   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
> diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
> index 680c010a53d4..8a773434a329 100644
> --- a/include/ufs/ufshcd.h
> +++ b/include/ufs/ufshcd.h
> @@ -321,6 +321,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
> @@ -365,6 +366,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 wkey[],
> +				    unsigned int wkey_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 *);

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

* Re: [PATCH v4 09/15] ufs: core: add support for generate, import and prepare keys
  2024-01-27 23:14 ` [PATCH v4 09/15] ufs: core: add support for generate, import and prepare keys Gaurav Kashyap
@ 2024-02-05 18:53   ` Om Prakash Singh
  0 siblings, 0 replies; 37+ messages in thread
From: Om Prakash Singh @ 2024-02-05 18:53 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_nguyenb, bartosz.golaszewski, konrad.dybcio, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert



On 1/28/2024 4:44 AM, Gaurav Kashyap wrote:
> Block crypto allows storage controllers like UFS to
> register ops to generate, prepare and import wrapped
> keys in the kernel.
> 
> Wrapped keys in most cases will have vendor specific
> implementations, which means these ops would need to have
> corresponding UFS variant ops.
> This change adds hooks in UFS core to support these variant
> ops and tie them to the blk crypto ops.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
Reviewed-by: Om Prakash Singh <quic_omprsing@quicinc.com>

>   drivers/ufs/core/ufshcd-crypto.c | 41 ++++++++++++++++++++++++++++++++
>   include/ufs/ufshcd.h             | 11 +++++++++
>   2 files changed, 52 insertions(+)
> 
> diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c
> index c14800eac1ff..fb935a54acfa 100644
> --- a/drivers/ufs/core/ufshcd-crypto.c
> +++ b/drivers/ufs/core/ufshcd-crypto.c
> @@ -143,10 +143,51 @@ bool ufshcd_crypto_enable(struct ufs_hba *hba)
>   	return true;
>   }
>   
> +static int ufshcd_crypto_generate_key(struct blk_crypto_profile *profile,
> +				      u8 lt_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, lt_key);
> +
> +	return -EOPNOTSUPP;
> +}
> +
> +static int ufshcd_crypto_prepare_key(struct blk_crypto_profile *profile,
> +				     const u8 *lt_key, size_t lt_key_size,
> +				     u8 eph_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, lt_key, lt_key_size, eph_key);
> +
> +	return -EOPNOTSUPP;
> +}
> +
> +static int ufshcd_crypto_import_key(struct blk_crypto_profile *profile,
> +				    const u8 *imp_key, size_t imp_key_size,
> +				    u8 lt_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, imp_key, imp_key_size, lt_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 8a773434a329..fe66ba37e2ee 100644
> --- a/include/ufs/ufshcd.h
> +++ b/include/ufs/ufshcd.h
> @@ -322,6 +322,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
> @@ -369,6 +372,14 @@ struct ufs_hba_variant_ops {
>   	int	(*derive_sw_secret)(struct ufs_hba *hba, const u8 wkey[],
>   				    unsigned int wkey_size,
>   				    u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
> +	int	(*generate_key)(struct ufs_hba *hba,
> +				u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
> +	int	(*prepare_key)(struct ufs_hba *hba,
> +			       const u8 *lt_key, size_t lt_key_size,
> +			       u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
> +	int	(*import_key)(struct ufs_hba *hba,
> +			      const u8 *imp_key, size_t imp_key_size,
> +			      u8 lt_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 *);

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

* Re: [PATCH v4 10/15] ufs: host: wrapped keys support in ufs qcom
  2024-01-27 23:14 ` [PATCH v4 10/15] ufs: host: wrapped keys support in ufs qcom Gaurav Kashyap
@ 2024-02-05 18:59   ` Om Prakash Singh
  0 siblings, 0 replies; 37+ messages in thread
From: Om Prakash Singh @ 2024-02-05 18:59 UTC (permalink / raw)
  To: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt
  Cc: linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_nguyenb, bartosz.golaszewski, konrad.dybcio, ulf.hansson,
	jejb, martin.petersen, mani, davem, herbert



On 1/28/2024 4:44 AM, Gaurav Kashyap wrote:
> Use the wrapped keys quirk when hwkm is supported/used.
> Whether to use HWKM or not would be decided during an ICE
> probe, and based on this information, UFS can decide to use
> wrapped keys or standard keys.
> 
> Also, propagate the appropriate key size to the ICE driver
> when wrapped keys are used.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
Reviewed-by: Om Prakash Singh <quic_omprsing@quicinc.com>
>   drivers/ufs/host/ufs-qcom.c | 8 +++++++-
>   1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
> index acf352594362..5c9ba06438a9 100644
> --- a/drivers/ufs/host/ufs-qcom.c
> +++ b/drivers/ufs/host/ufs-qcom.c
> @@ -123,6 +123,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;
>   }
> @@ -160,7 +162,11 @@ static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
>   	    cap.key_size != UFS_CRYPTO_KEY_SIZE_256)
>   		return -EOPNOTSUPP;
>   
> -	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,

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

* Re: [PATCH v4 01/15] ice, ufs, mmc: use blk_crypto_key for program_key
  2024-01-27 23:13 ` [PATCH v4 01/15] ice, ufs, mmc: use blk_crypto_key for program_key Gaurav Kashyap
@ 2024-02-06 11:46   ` Bartosz Golaszewski
  2024-02-13 12:49   ` Ulf Hansson
  1 sibling, 0 replies; 37+ messages in thread
From: Bartosz Golaszewski @ 2024-02-06 11:46 UTC (permalink / raw)
  To: Gaurav Kashyap
  Cc: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt,
	linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, konrad.dybcio, ulf.hansson, jejb,
	martin.petersen, mani, davem, herbert

On Sun, 28 Jan 2024 at 00:26, Gaurav Kashyap <quic_gaurkash@quicinc.com> wrote:
>
> 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>
> Reviewed-by: Om Prakash Singh <quic_omprsing@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

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

* Re: [PATCH v4 02/15] qcom_scm: scm call for deriving a software secret
  2024-02-01 16:11   ` Konrad Dybcio
@ 2024-02-06 11:56     ` Bartosz Golaszewski
  0 siblings, 0 replies; 37+ messages in thread
From: Bartosz Golaszewski @ 2024-02-06 11:56 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Gaurav Kashyap, linux-arm-msm, linux-scsi, andersson, ebiggers,
	neil.armstrong, srinivas.kandagatla, krzysztof.kozlowski+dt,
	conor+dt, robh+dt, linux-kernel, linux-mmc, kernel, linux-crypto,
	devicetree, quic_omprsing, quic_nguyenb, ulf.hansson, jejb,
	martin.petersen, mani, davem, herbert

On Thu, 1 Feb 2024 at 17:11, Konrad Dybcio <konrad.dybcio@linaro.org> wrote:
>
> On 28.01.2024 00:14, Gaurav Kashyap wrote:
> > Inline storage encryption may require deriving a software
> > secret from storage keys added to the kernel.
> >
> > For non-wrapped keys, this can be directly done in the kernel as
> > keys are in the clear.
> >
> > However, hardware wrapped keys can only be unwrapped by the wrapping
> > entity. In case of Qualcomm's wrapped key solution, this is done by
> > the Hardware Key Manager (HWKM) from Trustzone.
> > Hence, adding a new SCM call which in the end provides a hook
> > to the software secret crypto profile API provided by the block
> > layer.
> >
> > Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> > Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> > ---
> >  drivers/firmware/qcom/qcom_scm.c       | 65 ++++++++++++++++++++++++++
> >  drivers/firmware/qcom/qcom_scm.h       |  1 +
> >  include/linux/firmware/qcom/qcom_scm.h |  2 +
> >  3 files changed, 68 insertions(+)
> >
> > diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
> > index 7e17fd662bda..4882f8a36453 100644
> > --- a/drivers/firmware/qcom/qcom_scm.c
> > +++ b/drivers/firmware/qcom/qcom_scm.c
> > @@ -1220,6 +1220,71 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
> >  }
> >  EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key);
> >
> > +/**
> > + * qcom_scm_derive_sw_secret() - Derive software secret from wrapped key
> > + * @wkey: the hardware wrapped key inaccessible to software
> > + * @wkey_size: size of the wrapped key
> > + * @sw_secret: the secret to be derived which is exactly the secret size
> > + * @sw_secret_size: size of the sw_secret
> > + *
> > + * Derive a software secret from a hardware wrapped key for software crypto
> > + * operations.
> > + * For wrapped keys, the key needs to be unwrapped, in order to derive a
> > + * software secret, which can be done in the hardware from a secure execution
> > + * environment.
> > + *
> > + * 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 *wkey, size_t wkey_size,
> > +                           u8 *sw_secret, size_t sw_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] = wkey_size,
> > +             .args[3] = sw_secret_size,
> > +             .owner = ARM_SMCCC_OWNER_SIP,
> > +     };
> > +
> > +     void *secret_buf;
> > +     void *wkey_buf;
> > +     int ret;
> > +
> > +     wkey_buf = qcom_tzmem_alloc(__scm->mempool, wkey_size, GFP_KERNEL);
> > +     if (!wkey_buf)
> > +             return -ENOMEM;
> > +
> > +     secret_buf = qcom_tzmem_alloc(__scm->mempool, sw_secret_size, GFP_KERNEL);
> > +     if (!secret_buf) {
> > +             ret = -ENOMEM;
> > +             goto err_free_wrapped;
> > +     }
> > +
> > +     memcpy(wkey_buf, wkey, wkey_size);
> > +     desc.args[0] = qcom_tzmem_to_phys(wkey_buf);
> > +     desc.args[2] = qcom_tzmem_to_phys(secret_buf);
> > +
> > +     ret = qcom_scm_call(__scm->dev, &desc, NULL);
> > +     if (!ret)
> > +             memcpy(sw_secret, secret_buf, sw_secret_size);
> > +
> > +     memzero_explicit(secret_buf, sw_secret_size);
> > +     qcom_tzmem_free(secret_buf);
> > +
> > +err_free_wrapped:
> > +     memzero_explicit(wkey_buf, wkey_size);
> > +     qcom_tzmem_free(wkey_buf);
> __free(qcom_tzmem) attribute instead?
>

I second this. Please look at other implementations.

Bart

> Konrad
>

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

* Re: [PATCH v4 03/15] qcom_scm: scm call for create, prepare and import keys
  2024-01-27 23:14 ` [PATCH v4 03/15] qcom_scm: scm call for create, prepare and import keys Gaurav Kashyap
  2024-02-05 18:03   ` Om Prakash Singh
@ 2024-02-06 11:59   ` Bartosz Golaszewski
  1 sibling, 0 replies; 37+ messages in thread
From: Bartosz Golaszewski @ 2024-02-06 11:59 UTC (permalink / raw)
  To: Gaurav Kashyap
  Cc: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt,
	linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, konrad.dybcio, ulf.hansson, jejb,
	martin.petersen, mani, davem, herbert

On Sun, 28 Jan 2024 at 00:26, Gaurav Kashyap <quic_gaurkash@quicinc.com> wrote:
>
> Storage encryption has two IOCTLs for creating, importing
> and preparing keys for encryption. For wrapped keys, these
> IOCTLs need to interface with Qualcomm's Trustzone, 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>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  drivers/firmware/qcom/qcom_scm.c       | 182 +++++++++++++++++++++++++
>  drivers/firmware/qcom/qcom_scm.h       |   3 +
>  include/linux/firmware/qcom/qcom_scm.h |   5 +
>  3 files changed, 190 insertions(+)
>
> diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
> index 4882f8a36453..20dbab765c8e 100644
> --- a/drivers/firmware/qcom/qcom_scm.c
> +++ b/drivers/firmware/qcom/qcom_scm.c
> @@ -1285,6 +1285,188 @@ int qcom_scm_derive_sw_secret(const u8 *wkey, size_t wkey_size,
>  }
>  EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
>
> +/**
> + * qcom_scm_generate_ice_key() - Generate a wrapped key for encryption.
> + * @lt_key: the wrapped key returned after key generation
> + * @lt_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.
> + *
> + * Adds support for the create key IOCTL to interface
> + * with the secure environment to generate and return a wrapped key..
> + *
> + * Return: longterm key size on success; -errno on failure.
> + */
> +int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_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] = lt_key_size,
> +               .owner = ARM_SMCCC_OWNER_SIP,
> +       };
> +
> +       void *lt_key_buf;
> +       int ret;
> +
> +       lt_key_buf = qcom_tzmem_alloc(__scm->mempool, lt_key_size, GFP_KERNEL);

Please use __free(qcom_tzmem) everywhere in this series. You can take
a look at the calls I converted in the series adding this allocator.
It's really useful - especially if the buffer is surely freed within
the same scope.

Bart

[snip]

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

* Re: [PATCH v4 01/15] ice, ufs, mmc: use blk_crypto_key for program_key
  2024-01-27 23:13 ` [PATCH v4 01/15] ice, ufs, mmc: use blk_crypto_key for program_key Gaurav Kashyap
  2024-02-06 11:46   ` Bartosz Golaszewski
@ 2024-02-13 12:49   ` Ulf Hansson
  1 sibling, 0 replies; 37+ messages in thread
From: Ulf Hansson @ 2024-02-13 12:49 UTC (permalink / raw)
  To: Gaurav Kashyap
  Cc: linux-arm-msm, linux-scsi, andersson, ebiggers, neil.armstrong,
	srinivas.kandagatla, krzysztof.kozlowski+dt, conor+dt, robh+dt,
	linux-kernel, linux-mmc, kernel, linux-crypto, devicetree,
	quic_omprsing, quic_nguyenb, bartosz.golaszewski, konrad.dybcio,
	jejb, martin.petersen, mani, davem, herbert

On Sun, 28 Jan 2024 at 00:26, Gaurav Kashyap <quic_gaurkash@quicinc.com> wrote:
>
> 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>
> Reviewed-by: Om Prakash Singh <quic_omprsing@quicinc.com>
> Tested-by: Neil Armstrong <neil.armstrong@linaro.org>

I assume this is better funneled via some other tree than the MMC, so:

Acked-by: Ulf Hansson <ulf.hansson@linaro.org> # For MMC

Kind regards
Uffe

> ---
>  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 668e0aceeeba..529ea9f4fa07 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 *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 fbab7fe5c652..6f941d32fffb 100644
> --- a/drivers/soc/qcom/ice.c
> +++ b/drivers/soc/qcom/ice.c
> @@ -163,8 +163,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 {
> @@ -183,7 +183,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 39eef470f8fa..acf352594362 100644
> --- a/drivers/ufs/host/ufs-qcom.c
> +++ b/drivers/ufs/host/ufs-qcom.c
> @@ -144,6 +144,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)
>  {
> @@ -151,6 +152,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];
> @@ -158,11 +160,11 @@ static int ufs_qcom_ice_program_key(struct ufs_hba *hba,
>             cap.key_size != UFS_CRYPTO_KEY_SIZE_256)
>                 return -EOPNOTSUPP;
>
> +       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 cb2afcebbdf5..582d5a747e84 100644
> --- a/include/ufs/ufshcd.h
> +++ b/include/ufs/ufshcd.h
> @@ -363,6 +363,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.43.0
>

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

end of thread, other threads:[~2024-02-13 12:49 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-27 23:13 [PATCH v4 00/15] Hardware wrapped key support for qcom ice and ufs Gaurav Kashyap
2024-01-27 23:13 ` [PATCH v4 01/15] ice, ufs, mmc: use blk_crypto_key for program_key Gaurav Kashyap
2024-02-06 11:46   ` Bartosz Golaszewski
2024-02-13 12:49   ` Ulf Hansson
2024-01-27 23:14 ` [PATCH v4 02/15] qcom_scm: scm call for deriving a software secret Gaurav Kashyap
2024-01-30  4:43   ` Bjorn Andersson
2024-02-01 16:11   ` Konrad Dybcio
2024-02-06 11:56     ` Bartosz Golaszewski
2024-01-27 23:14 ` [PATCH v4 03/15] qcom_scm: scm call for create, prepare and import keys Gaurav Kashyap
2024-02-05 18:03   ` Om Prakash Singh
2024-02-06 11:59   ` Bartosz Golaszewski
2024-01-27 23:14 ` [PATCH v4 04/15] soc: qcom: ice: add hwkm support in ice Gaurav Kashyap
2024-02-04 18:32   ` [EXTERNAL] " Kamlesh Gurudasani
2024-02-05 18:22   ` Om Prakash Singh
2024-01-27 23:14 ` [PATCH v4 05/15] soc: qcom: ice: support for hardware wrapped keys Gaurav Kashyap
2024-02-04 19:30   ` [EXTERNAL] " Kamlesh Gurudasani
2024-02-05 18:38   ` Om Prakash Singh
2024-01-27 23:14 ` [PATCH v4 06/15] soc: qcom: ice: support for generate, import and prepare key Gaurav Kashyap
2024-02-05 18:45   ` Om Prakash Singh
2024-01-27 23:14 ` [PATCH v4 07/15] ufs: core: support wrapped keys in ufs core Gaurav Kashyap
2024-01-27 23:14 ` [PATCH v4 08/15] ufs: core: add support to derive software secret Gaurav Kashyap
2024-02-05 18:52   ` Om Prakash Singh
2024-01-27 23:14 ` [PATCH v4 09/15] ufs: core: add support for generate, import and prepare keys Gaurav Kashyap
2024-02-05 18:53   ` Om Prakash Singh
2024-01-27 23:14 ` [PATCH v4 10/15] ufs: host: wrapped keys support in ufs qcom Gaurav Kashyap
2024-02-05 18:59   ` Om Prakash Singh
2024-01-27 23:14 ` [PATCH v4 11/15] ufs: host: implement derive sw secret vop " Gaurav Kashyap
2024-01-27 23:14 ` [PATCH v4 12/15] ufs: host: support for generate, import and prepare key Gaurav Kashyap
2024-01-27 23:14 ` [PATCH v4 13/15] dt-bindings: crypto: ice: document the hwkm property Gaurav Kashyap
2024-01-29  8:18   ` Krzysztof Kozlowski
2024-02-01 19:13     ` Konrad Dybcio
2024-01-27 23:14 ` [PATCH v4 14/15] arm64: dts: qcom: sm8650: add hwkm support to ufs ice Gaurav Kashyap
2024-01-29  8:15   ` Krzysztof Kozlowski
2024-01-27 23:14 ` [PATCH v4 15/15] arm64: dts: qcom: sm8550: " Gaurav Kashyap
2024-01-28  1:01   ` Dmitry Baryshkov
2024-02-01  9:55     ` Om Prakash Singh
2024-02-01 13:59       ` neil.armstrong

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).