* [PATCH 1/5] firmware: qcom: Add a generic ICE service
2026-10-21 15:43 [PATCH 0/5] Add support for a TEE agnostic Inline Crypto Engine service Harshal Dev
@ 2026-10-21 15:43 ` Harshal Dev
2026-10-22 7:45 ` Konrad Dybcio
2026-10-21 15:43 ` [PATCH 2/5] firmware: qcom_scm: Transition to the " Harshal Dev
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Harshal Dev @ 2026-10-21 15:43 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Abel Vesa, Kuldeep Singh,
Neeraj Soni, Manivannan Sadhasivam, Sumit Garg,
Selvam Sathappan Periakaruppan
Cc: Basant Kumar, linux-kernel, linux-arm-msm, linux-crypto, Harshal Dev
Qualcomm platforms such as the IQ-9075 EVK now boot with both QTEE and
OPTEE. However, the Qualcomm Inline Crypto Engine (ICE) driver
currently only makes SCM calls into QTEE. With the arrival of ICE
support on OPTEE for Qualcomm platforms, there is a need for a generic
layer which re-directs the call to the correct TEE at runtime.
Add a generic ICE service which acts as a common layer with different
TEE backends plugged in whether it's an SCM implementation or a proper
TEE bus based implementation (such as for OPTEE).
Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
MAINTAINERS | 9 +++
drivers/firmware/qcom/Kconfig | 8 +++
drivers/firmware/qcom/Makefile | 1 +
drivers/firmware/qcom/qcom_ice.c | 125 +++++++++++++++++++++++++++++++++
drivers/firmware/qcom/qcom_ice.h | 51 ++++++++++++++
include/linux/firmware/qcom/qcom_ice.h | 32 +++++++++
6 files changed, 226 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index f58a305de664..7a80b776896c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23007,6 +23007,15 @@ F: Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
F: drivers/soc/qcom/ice.c
F: include/soc/qcom/ice.h
+QUALCOMM INLINE CRYPTO ENGINE TZ SERVICE
+M: Harshal Dev <harshal.dev@oss.qualcomm.com>
+L: linux-arm-msm@vger.kernel.org
+L: linux-crypto@vger.kernel.org
+S: Maintained
+F: drivers/firmware/qcom/qcom_ice.c
+F: drivers/firmware/qcom/qcom_ice.h
+F: include/linux/firmware/qcom/qcom_ice.h
+
QUALCOMM INTERCONNECT BWMON DRIVER
M: Krzysztof Kozlowski <krzk@kernel.org>
L: linux-arm-msm@vger.kernel.org
diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig
index 3ad22f8fc3e5..e2d1c17296c2 100644
--- a/drivers/firmware/qcom/Kconfig
+++ b/drivers/firmware/qcom/Kconfig
@@ -25,6 +25,14 @@ config QCOM_PAS_TEE
Enable the generic Peripheral Authentication Service (PAS) provided
by the firmware TEE implementation as the backend.
+config QCOM_ICE_SERVICE
+ tristate
+ help
+ Enable the generic Inline Crypto Engine (ICE) service provided by
+ firmware. It acts as a common layer with different TZ backends
+ plugged in whether it's an SCM implementation or a TEE bus based
+ ICE service implementation.
+
config QCOM_SCM
tristate "Qualcomm PAS SCM interface driver" if ARCH_QCOM || COMPILE_TEST
select QCOM_PAS
diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile
index 88ce74d74c3e..6403e8a17249 100644
--- a/drivers/firmware/qcom/Makefile
+++ b/drivers/firmware/qcom/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o
obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o
obj-$(CONFIG_QCOM_PAS) += qcom_pas.o
obj-$(CONFIG_QCOM_PAS_TEE) += qcom_pas_tee.o
+obj-$(CONFIG_QCOM_ICE_SERVICE) += qcom_ice.o
diff --git a/drivers/firmware/qcom/qcom_ice.c b/drivers/firmware/qcom/qcom_ice.c
new file mode 100644
index 000000000000..2e42d70c855a
--- /dev/null
+++ b/drivers/firmware/qcom/qcom_ice.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/firmware/qcom/qcom_ice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "qcom_ice.h"
+
+static struct qcom_ice_ops *ops_ptr;
+
+bool qcom_ice_svc_ops_registered(void)
+{
+ /*
+ * The barrier for ops_ptr is intended to synchronize the data stores
+ * for the ops data structure when client drivers are in parallel
+ * checking for ICE service availability.
+ */
+ return !!smp_load_acquire(&ops_ptr);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_ops_registered);
+
+bool qcom_ice_svc_available(void)
+{
+ if (!ops_ptr)
+ return false;
+
+ return ops_ptr->is_ice_available(ops_ptr->dev);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_available);
+
+int qcom_ice_svc_invalidate_key(u32 index)
+{
+ if (!ops_ptr)
+ return -ENODEV;
+
+ return ops_ptr->ice_invalidate_key(ops_ptr->dev, index);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_invalidate_key);
+
+int qcom_ice_svc_set_key(u32 index, const u8 *key, u32 key_size,
+ enum qcom_ice_cipher cipher, u32 data_unit_size)
+{
+ if (!ops_ptr)
+ return -ENODEV;
+
+ return ops_ptr->ice_set_key(ops_ptr->dev, index, key, key_size,
+ cipher, data_unit_size);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_set_key);
+
+bool qcom_ice_svc_has_wrapped_key_support(void)
+{
+ if (!ops_ptr)
+ return false;
+
+ return ops_ptr->ice_has_wrapped_key_support(ops_ptr->dev);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_has_wrapped_key_support);
+
+int qcom_ice_svc_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
+ u8 *sw_secret, size_t sw_secret_size)
+{
+ if (!ops_ptr)
+ return -ENODEV;
+
+ return ops_ptr->ice_derive_sw_secret(ops_ptr->dev, eph_key, eph_key_size,
+ sw_secret, sw_secret_size);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_derive_sw_secret);
+
+int qcom_ice_svc_generate_key(u8 *lt_key, size_t lt_key_size)
+{
+ if (!ops_ptr)
+ return -ENODEV;
+
+ return ops_ptr->ice_generate_key(ops_ptr->dev, lt_key, lt_key_size);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_generate_key);
+
+int qcom_ice_svc_prepare_key(const u8 *lt_key, size_t lt_key_size,
+ u8 *eph_key, size_t eph_key_size)
+{
+ if (!ops_ptr)
+ return -ENODEV;
+
+ return ops_ptr->ice_prepare_key(ops_ptr->dev, lt_key, lt_key_size,
+ eph_key, eph_key_size);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_prepare_key);
+
+int qcom_ice_svc_import_key(const u8 *raw_key, size_t raw_key_size,
+ u8 *lt_key, size_t lt_key_size)
+{
+ if (!ops_ptr)
+ return -ENODEV;
+
+ return ops_ptr->ice_import_key(ops_ptr->dev, raw_key, raw_key_size,
+ lt_key, lt_key_size);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_import_key);
+
+void qcom_ice_svc_ops_register(struct qcom_ice_ops *ops)
+{
+ if (!qcom_ice_svc_ops_registered())
+ /* Paired with smp_load_acquire() in qcom_ice_svc_ops_registered() */
+ smp_store_release(&ops_ptr, ops);
+ else
+ pr_err("qcom_ice: ops already registered (%s), rejecting %s\n",
+ ops_ptr->drv_name, ops->drv_name);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_ops_register);
+
+void qcom_ice_svc_ops_unregister(struct qcom_ice_ops *ops)
+{
+ if (READ_ONCE(ops_ptr) == ops)
+ /* Paired with smp_load_acquire() in qcom_ice_svc_ops_registered() */
+ smp_store_release(&ops_ptr, NULL);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_svc_ops_unregister);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Qualcomm ICE service");
diff --git a/drivers/firmware/qcom/qcom_ice.h b/drivers/firmware/qcom/qcom_ice.h
new file mode 100644
index 000000000000..aefaf1ecc3df
--- /dev/null
+++ b/drivers/firmware/qcom/qcom_ice.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef __QCOM_ICE_INT_H
+#define __QCOM_ICE_INT_H
+
+#include <linux/firmware/qcom/qcom_ice.h>
+
+struct device;
+
+/**
+ * struct qcom_ice_ops - Qcom ICE service backend ops
+ * @drv_name: ICE backend driver name.
+ * @dev: ICE backend device pointer.
+ * @is_ice_available: ICE service available callback.
+ * @ice_invalidate_key: Invalidate keyslot callback.
+ * @ice_set_key: Program keyslot callback.
+ * @ice_has_wrapped_key_support: Wrapped-key support callback.
+ * @ice_derive_sw_secret: Derive software secret callback.
+ * @ice_generate_key: Generate wrapped key callback.
+ * @ice_prepare_key: Prepare wrapped key callback.
+ * @ice_import_key: Import wrapped key callback.
+ */
+struct qcom_ice_ops {
+ const char *drv_name;
+ struct device *dev;
+ bool (*is_ice_available)(struct device *dev);
+ int (*ice_invalidate_key)(struct device *dev, u32 index);
+ int (*ice_set_key)(struct device *dev, u32 index, const u8 *key,
+ u32 key_size, enum qcom_ice_cipher cipher,
+ u32 data_unit_size);
+ bool (*ice_has_wrapped_key_support)(struct device *dev);
+ int (*ice_derive_sw_secret)(struct device *dev, const u8 *eph_key,
+ size_t eph_key_size, u8 *sw_secret,
+ size_t sw_secret_size);
+ int (*ice_generate_key)(struct device *dev, u8 *lt_key,
+ size_t lt_key_size);
+ int (*ice_prepare_key)(struct device *dev, const u8 *lt_key,
+ size_t lt_key_size, u8 *eph_key,
+ size_t eph_key_size);
+ int (*ice_import_key)(struct device *dev, const u8 *raw_key,
+ size_t raw_key_size, u8 *lt_key,
+ size_t lt_key_size);
+};
+
+void qcom_ice_svc_ops_register(struct qcom_ice_ops *ops);
+void qcom_ice_svc_ops_unregister(struct qcom_ice_ops *ops);
+
+#endif /* __QCOM_ICE_INT_H */
diff --git a/include/linux/firmware/qcom/qcom_ice.h b/include/linux/firmware/qcom/qcom_ice.h
new file mode 100644
index 000000000000..c3d93259c72a
--- /dev/null
+++ b/include/linux/firmware/qcom/qcom_ice.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef __QCOM_TZ_ICE_H
+#define __QCOM_TZ_ICE_H
+
+#include <linux/types.h>
+
+enum qcom_ice_cipher {
+ QCOM_ICE_CIPHER_AES_128_XTS = 0,
+ QCOM_ICE_CIPHER_AES_128_CBC = 1,
+ QCOM_ICE_CIPHER_AES_256_XTS = 3,
+ QCOM_ICE_CIPHER_AES_256_CBC = 4,
+};
+
+bool qcom_ice_svc_ops_registered(void);
+bool qcom_ice_svc_available(void);
+int qcom_ice_svc_invalidate_key(u32 index);
+int qcom_ice_svc_set_key(u32 index, const u8 *key, u32 key_size,
+ enum qcom_ice_cipher cipher, u32 data_unit_size);
+bool qcom_ice_svc_has_wrapped_key_support(void);
+int qcom_ice_svc_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
+ u8 *sw_secret, size_t sw_secret_size);
+int qcom_ice_svc_generate_key(u8 *lt_key, size_t lt_key_size);
+int qcom_ice_svc_prepare_key(const u8 *lt_key, size_t lt_key_size,
+ u8 *eph_key, size_t eph_key_size);
+int qcom_ice_svc_import_key(const u8 *raw_key, size_t raw_key_size,
+ u8 *lt_key, size_t lt_key_size);
+
+#endif /* __QCOM_TZ_ICE_H */
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH 1/5] firmware: qcom: Add a generic ICE service
2026-10-21 15:43 ` [PATCH 1/5] firmware: qcom: Add a generic ICE service Harshal Dev
@ 2026-10-22 7:45 ` Konrad Dybcio
0 siblings, 0 replies; 10+ messages in thread
From: Konrad Dybcio @ 2026-10-22 7:45 UTC (permalink / raw)
To: Harshal Dev, Bjorn Andersson, Konrad Dybcio, Abel Vesa,
Kuldeep Singh, Neeraj Soni, Manivannan Sadhasivam, Sumit Garg,
Selvam Sathappan Periakaruppan
Cc: Basant Kumar, linux-kernel, linux-arm-msm, linux-crypto
On 10/21/26 5:43 PM, Harshal Dev wrote:
> Qualcomm platforms such as the IQ-9075 EVK now boot with both QTEE and
> OPTEE. However, the Qualcomm Inline Crypto Engine (ICE) driver
> currently only makes SCM calls into QTEE. With the arrival of ICE
> support on OPTEE for Qualcomm platforms, there is a need for a generic
> layer which re-directs the call to the correct TEE at runtime.
>
> Add a generic ICE service which acts as a common layer with different
> TEE backends plugged in whether it's an SCM implementation or a proper
> TEE bus based implementation (such as for OPTEE).
>
> Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
> ---
[...]
> +bool qcom_ice_svc_ops_registered(void)
> +{
> + /*
> + * The barrier for ops_ptr is intended to synchronize the data stores
> + * for the ops data structure when client drivers are in parallel
> + * checking for ICE service availability.
> + */
> + return !!smp_load_acquire(&ops_ptr);
> +}
> +EXPORT_SYMBOL_GPL(qcom_ice_svc_ops_registered);
> +
> +bool qcom_ice_svc_available(void)
> +{
> + if (!ops_ptr)
Should this also be a barrier read?
Konrad
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/5] firmware: qcom_scm: Transition to the generic ICE service
2026-10-21 15:43 [PATCH 0/5] Add support for a TEE agnostic Inline Crypto Engine service Harshal Dev
2026-10-21 15:43 ` [PATCH 1/5] firmware: qcom: Add a generic ICE service Harshal Dev
@ 2026-10-21 15:43 ` Harshal Dev
2026-10-21 15:43 ` [PATCH 3/5] firmware: qcom: Add an TEE bus based ICE back-end Harshal Dev
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Harshal Dev @ 2026-10-21 15:43 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Abel Vesa, Kuldeep Singh,
Neeraj Soni, Manivannan Sadhasivam, Sumit Garg,
Selvam Sathappan Periakaruppan
Cc: Basant Kumar, linux-kernel, linux-arm-msm, linux-crypto, Harshal Dev
Transition the ICE related SCM APIs to the generic ICE service by
registering them with the service's operations and wrapping them in
exported functions with the same signature.
This prepares the ICE driver for eventual migration to the ICE
service from the SCM driver once the TEE bus based back-end becomes
available.
Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
drivers/firmware/qcom/Kconfig | 1 +
drivers/firmware/qcom/qcom_scm.c | 123 +++++++++++++++++++++++++++++++--------
2 files changed, 100 insertions(+), 24 deletions(-)
diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig
index e2d1c17296c2..6cde1704dbc7 100644
--- a/drivers/firmware/qcom/Kconfig
+++ b/drivers/firmware/qcom/Kconfig
@@ -36,6 +36,7 @@ config QCOM_ICE_SERVICE
config QCOM_SCM
tristate "Qualcomm PAS SCM interface driver" if ARCH_QCOM || COMPILE_TEST
select QCOM_PAS
+ select QCOM_ICE_SERVICE
select QCOM_TZMEM
default y if ARCH_QCOM
diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 43e250faea75..9aeb2cefa77a 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -13,6 +13,7 @@
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/export.h>
+#include <linux/firmware/qcom/qcom_ice.h>
#include <linux/firmware/qcom/qcom_pas.h>
#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/firmware/qcom/qcom_tzmem.h>
@@ -34,6 +35,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "qcom_ice.h"
#include "qcom_pas.h"
#include "qcom_scm.h"
#include "qcom_tzmem.h"
@@ -1403,13 +1405,18 @@ EXPORT_SYMBOL_GPL(qcom_scm_ocmem_unlock);
* Return: true iff the SCM calls wrapped by qcom_scm_ice_invalidate_key() and
* qcom_scm_ice_set_key() are available.
*/
-bool qcom_scm_ice_available(void)
+static bool __qcom_scm_ice_available(struct device *dev)
{
- return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_INVALIDATE_ICE_KEY) &&
- __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_CONFIG_SET_ICE_KEY);
}
+
+bool qcom_scm_ice_available(void)
+{
+ return __qcom_scm_ice_available(__scm->dev);
+}
EXPORT_SYMBOL_GPL(qcom_scm_ice_available);
/**
@@ -1424,7 +1431,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_ice_available);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_ice_invalidate_key(u32 index)
+static int __qcom_scm_ice_invalidate_key(struct device *dev, u32 index)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1434,7 +1441,12 @@ int qcom_scm_ice_invalidate_key(u32 index)
.owner = ARM_SMCCC_OWNER_SIP,
};
- return qcom_scm_call(__scm->dev, &desc, NULL);
+ return qcom_scm_call(dev, &desc, NULL);
+}
+
+int qcom_scm_ice_invalidate_key(u32 index)
+{
+ return __qcom_scm_ice_invalidate_key(__scm->dev, index);
}
EXPORT_SYMBOL_GPL(qcom_scm_ice_invalidate_key);
@@ -1459,8 +1471,10 @@ EXPORT_SYMBOL_GPL(qcom_scm_ice_invalidate_key);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
- enum qcom_scm_ice_cipher cipher, u32 data_unit_size)
+static int __qcom_scm_ice_set_key(struct device *dev, u32 index,
+ const u8 *key, u32 key_size,
+ enum qcom_ice_cipher cipher,
+ u32 data_unit_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1485,25 +1499,38 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
memcpy(keybuf, key, key_size);
desc.args[1] = qcom_tzmem_to_phys(keybuf);
- ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ ret = qcom_scm_call(dev, &desc, NULL);
memzero_explicit(keybuf, key_size);
return ret;
}
+
+int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
+ enum qcom_scm_ice_cipher cipher, u32 data_unit_size)
+{
+ return __qcom_scm_ice_set_key(__scm->dev, index, key, key_size,
+ (enum qcom_ice_cipher)cipher,
+ data_unit_size);
+}
EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key);
-bool qcom_scm_has_wrapped_key_support(void)
+static bool __qcom_scm_has_wrapped_key_support(struct device *dev)
{
- return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_DERIVE_SW_SECRET) &&
- __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_GENERATE_ICE_KEY) &&
- __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_PREPARE_ICE_KEY) &&
- __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_IMPORT_ICE_KEY);
}
+
+bool qcom_scm_has_wrapped_key_support(void)
+{
+ return __qcom_scm_has_wrapped_key_support(__scm->dev);
+}
EXPORT_SYMBOL_GPL(qcom_scm_has_wrapped_key_support);
/**
@@ -1522,8 +1549,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_has_wrapped_key_support);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
- u8 *sw_secret, size_t sw_secret_size)
+static int __qcom_scm_derive_sw_secret(struct device *dev,
+ const u8 *eph_key, size_t eph_key_size,
+ u8 *sw_secret, size_t sw_secret_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1552,7 +1580,7 @@ int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
desc.args[2] = qcom_tzmem_to_phys(sw_secret_buf);
desc.args[3] = sw_secret_size;
- ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ ret = qcom_scm_call(dev, &desc, NULL);
if (!ret)
memcpy(sw_secret, sw_secret_buf, sw_secret_size);
@@ -1560,6 +1588,13 @@ int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
memzero_explicit(sw_secret_buf, sw_secret_size);
return ret;
}
+
+int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
+ u8 *sw_secret, size_t sw_secret_size)
+{
+ return __qcom_scm_derive_sw_secret(__scm->dev, eph_key, eph_key_size,
+ sw_secret, sw_secret_size);
+}
EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
/**
@@ -1573,7 +1608,8 @@ EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size)
+static int __qcom_scm_generate_ice_key(struct device *dev,
+ u8 *lt_key, size_t lt_key_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1592,13 +1628,18 @@ int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size)
desc.args[0] = qcom_tzmem_to_phys(lt_key_buf);
desc.args[1] = lt_key_size;
- ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ ret = qcom_scm_call(dev, &desc, NULL);
if (!ret)
memcpy(lt_key, lt_key_buf, lt_key_size);
memzero_explicit(lt_key_buf, lt_key_size);
return ret;
}
+
+int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size)
+{
+ return __qcom_scm_generate_ice_key(__scm->dev, lt_key, lt_key_size);
+}
EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key);
/**
@@ -1614,8 +1655,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key);
*
* Return: 0 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)
+static int __qcom_scm_prepare_ice_key(struct device *dev,
+ 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,
@@ -1644,7 +1686,7 @@ int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
desc.args[2] = qcom_tzmem_to_phys(eph_key_buf);
desc.args[3] = eph_key_size;
- ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ ret = qcom_scm_call(dev, &desc, NULL);
if (!ret)
memcpy(eph_key, eph_key_buf, eph_key_size);
@@ -1652,6 +1694,13 @@ int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
memzero_explicit(eph_key_buf, eph_key_size);
return ret;
}
+
+int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
+ u8 *eph_key, size_t eph_key_size)
+{
+ return __qcom_scm_prepare_ice_key(__scm->dev, lt_key, lt_key_size,
+ eph_key, eph_key_size);
+}
EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key);
/**
@@ -1667,8 +1716,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
- u8 *lt_key, size_t lt_key_size)
+static int __qcom_scm_import_ice_key(struct device *dev,
+ const u8 *raw_key, size_t raw_key_size,
+ u8 *lt_key, size_t lt_key_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1697,7 +1747,7 @@ int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
desc.args[2] = qcom_tzmem_to_phys(lt_key_buf);
desc.args[3] = lt_key_size;
- ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ ret = qcom_scm_call(dev, &desc, NULL);
if (!ret)
memcpy(lt_key, lt_key_buf, lt_key_size);
@@ -1705,8 +1755,27 @@ int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
memzero_explicit(lt_key_buf, lt_key_size);
return ret;
}
+
+int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
+ u8 *lt_key, size_t lt_key_size)
+{
+ return __qcom_scm_import_ice_key(__scm->dev, raw_key, raw_key_size,
+ lt_key, lt_key_size);
+}
EXPORT_SYMBOL_GPL(qcom_scm_import_ice_key);
+static struct qcom_ice_ops qcom_ice_ops_scm = {
+ .drv_name = "qcom_scm",
+ .is_ice_available = __qcom_scm_ice_available,
+ .ice_invalidate_key = __qcom_scm_ice_invalidate_key,
+ .ice_set_key = __qcom_scm_ice_set_key,
+ .ice_has_wrapped_key_support = __qcom_scm_has_wrapped_key_support,
+ .ice_derive_sw_secret = __qcom_scm_derive_sw_secret,
+ .ice_generate_key = __qcom_scm_generate_ice_key,
+ .ice_prepare_key = __qcom_scm_prepare_ice_key,
+ .ice_import_key = __qcom_scm_import_ice_key,
+};
+
/**
* qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
*
@@ -2836,6 +2905,11 @@ static int qcom_scm_probe(struct platform_device *pdev)
qcom_pas_ops_register(&qcom_pas_ops_scm);
}
+ if (__qcom_scm_ice_available(scm->dev)) {
+ qcom_ice_ops_scm.dev = scm->dev;
+ qcom_ice_svc_ops_register(&qcom_ice_ops_scm);
+ }
+
/*
* If "download mode" is requested, from this point on warmboot
* will cause the boot stages to enter download mode, unless
@@ -2876,6 +2950,7 @@ static void qcom_scm_shutdown(struct platform_device *pdev)
/* Clean shutdown, disable download mode to allow normal restart */
qcom_scm_set_download_mode(__scm, QCOM_DLOAD_NODUMP);
qcom_pas_ops_unregister();
+ qcom_ice_svc_ops_unregister(&qcom_ice_ops_scm);
}
static const struct of_device_id qcom_scm_dt_match[] = {
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 3/5] firmware: qcom: Add an TEE bus based ICE back-end
2026-10-21 15:43 [PATCH 0/5] Add support for a TEE agnostic Inline Crypto Engine service Harshal Dev
2026-10-21 15:43 ` [PATCH 1/5] firmware: qcom: Add a generic ICE service Harshal Dev
2026-10-21 15:43 ` [PATCH 2/5] firmware: qcom_scm: Transition to the " Harshal Dev
@ 2026-10-21 15:43 ` Harshal Dev
2026-10-22 7:47 ` Konrad Dybcio
` (2 more replies)
2026-10-21 15:43 ` [PATCH 4/5] soc: qcom: ice: Migrate to the generic ICE service Harshal Dev
2026-10-21 15:43 ` [PATCH 5/5] firmware: qcom: scm: Drop exported ICE wrapper functions Harshal Dev
4 siblings, 3 replies; 10+ messages in thread
From: Harshal Dev @ 2026-10-21 15:43 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Abel Vesa, Kuldeep Singh,
Neeraj Soni, Manivannan Sadhasivam, Sumit Garg,
Selvam Sathappan Periakaruppan
Cc: Basant Kumar, linux-kernel, linux-arm-msm, linux-crypto, Harshal Dev
Add support for a TEE client driver which forwards calls from the Inline
Crypto Engine (ICE) service (invoked by the ICE driver) to the OPTEE ICE
Psuedo-TA.
The ICE PTA supports both ICE Legacy and Standard modes. In Standard mode
Hardware Key Manager v1 is supported.
Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
MAINTAINERS | 1 +
drivers/firmware/qcom/Kconfig | 10 +
drivers/firmware/qcom/Makefile | 1 +
drivers/firmware/qcom/qcom_ice_tee.c | 384 +++++++++++++++++++++++++++++++++++
4 files changed, 396 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 7a80b776896c..d5d4f1ca85b2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23014,6 +23014,7 @@ L: linux-crypto@vger.kernel.org
S: Maintained
F: drivers/firmware/qcom/qcom_ice.c
F: drivers/firmware/qcom/qcom_ice.h
+F: drivers/firmware/qcom/qcom_ice_tee.c
F: include/linux/firmware/qcom/qcom_ice.h
QUALCOMM INTERCONNECT BWMON DRIVER
diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig
index 6cde1704dbc7..bb67bd93cc51 100644
--- a/drivers/firmware/qcom/Kconfig
+++ b/drivers/firmware/qcom/Kconfig
@@ -33,6 +33,16 @@ config QCOM_ICE_SERVICE
plugged in whether it's an SCM implementation or a TEE bus based
ICE service implementation.
+config QCOM_ICE_TEE
+ tristate
+ select QCOM_ICE_SERVICE
+ depends on TEE
+ depends on !CPU_BIG_ENDIAN
+ default m if ARCH_QCOM
+ help
+ Enable the generic Inline Crypto Engine (ICE) firmware service TEE
+ implementation as a backend.
+
config QCOM_SCM
tristate "Qualcomm PAS SCM interface driver" if ARCH_QCOM || COMPILE_TEST
select QCOM_PAS
diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile
index 6403e8a17249..db9c9823420b 100644
--- a/drivers/firmware/qcom/Makefile
+++ b/drivers/firmware/qcom/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o
obj-$(CONFIG_QCOM_PAS) += qcom_pas.o
obj-$(CONFIG_QCOM_PAS_TEE) += qcom_pas_tee.o
obj-$(CONFIG_QCOM_ICE_SERVICE) += qcom_ice.o
+obj-$(CONFIG_QCOM_ICE_TEE) += qcom_ice_tee.o
diff --git a/drivers/firmware/qcom/qcom_ice_tee.c b/drivers/firmware/qcom/qcom_ice_tee.c
new file mode 100644
index 000000000000..b7434f19e6eb
--- /dev/null
+++ b/drivers/firmware/qcom/qcom_ice_tee.c
@@ -0,0 +1,384 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/firmware/qcom/qcom_ice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include <linux/uuid.h>
+
+#include "qcom_ice.h"
+
+#define PTA_QCOM_ICE_INVALIDATE_KEY 0
+#define PTA_QCOM_ICE_SET_CONFIG_KEY 1
+#define PTA_QCOM_ICE_GENERATE_KEY 2
+#define PTA_QCOM_ICE_IMPORT_KEY 3
+#define PTA_QCOM_ICE_EXPORT_KEY 4
+#define PTA_QCOM_ICE_GET_RAW_SECRET 5
+#define PTA_QCOM_ICE_HAS_WRAPPED_KEY_SUPPORT 6
+
+#define TEE_NUM_PARAMS 4
+
+struct qcom_ice_tee_private {
+ struct device *dev;
+ struct tee_context *ctx;
+ u32 session_id;
+};
+
+static int qcom_ice_tee_invalidate_key(struct device *dev, u32 index)
+{
+ struct qcom_ice_tee_private *data = dev_get_drvdata(dev);
+ struct tee_ioctl_invoke_arg inv_arg = {
+ .func = PTA_QCOM_ICE_INVALIDATE_KEY,
+ .session = data->session_id,
+ .num_params = TEE_NUM_PARAMS,
+ };
+ struct tee_param param[TEE_NUM_PARAMS] = {
+ [0] = {
+ .attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
+ .u.value.a = index,
+ .u.value.b = 0,
+ }
+ };
+ int ret;
+
+ ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
+ if (ret < 0 || inv_arg.ret != 0)
+ ret = ret ?: -EINVAL;
+
+ return ret;
+}
+
+static int qcom_ice_tee_set_key(struct device *dev, u32 index,
+ const u8 *key, u32 key_size,
+ enum qcom_ice_cipher cipher,
+ u32 data_unit_size)
+{
+ struct qcom_ice_tee_private *data = dev_get_drvdata(dev);
+ struct tee_ioctl_invoke_arg inv_arg = {
+ .func = PTA_QCOM_ICE_SET_CONFIG_KEY,
+ .session = data->session_id,
+ .num_params = TEE_NUM_PARAMS,
+ };
+ struct tee_param param[TEE_NUM_PARAMS] = {
+ [0] = {
+ .attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
+ .u.value.a = index,
+ .u.value.b = cipher,
+ },
+ [1] = {
+ .attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
+ .u.value.a = data_unit_size,
+ },
+ [2] = {
+ .attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT,
+ }
+ };
+ struct tee_shm *key_shm;
+ u8 *key_buf;
+ int ret;
+
+ key_shm = tee_shm_alloc_kernel_buf(data->ctx, key_size);
+ if (IS_ERR(key_shm))
+ return PTR_ERR(key_shm);
+
+ key_buf = tee_shm_get_va(key_shm, 0);
+ if (IS_ERR(key_buf)) {
+ ret = PTR_ERR(key_buf);
+ goto out;
+ }
+
+ memcpy(key_buf, key, key_size);
+ param[2].u.memref.shm = key_shm;
+ param[2].u.memref.size = key_size;
+
+ ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
+ memzero_explicit(key_buf, key_size);
+ if (ret < 0 || inv_arg.ret != 0) {
+ dev_err(dev,
+ "ICE set_key failed, idx=%u, ret=%d, err=0x%x\n",
+ index, ret, inv_arg.ret);
+ ret = ret ?: -EINVAL;
+ }
+out:
+ tee_shm_free(key_shm);
+ return ret;
+}
+
+static int qcom_ice_tee_wrapped_key_call(struct device *dev, u32 cmd,
+ const u8 *in, size_t in_size,
+ u8 *out, size_t out_size)
+{
+ struct qcom_ice_tee_private *data = dev_get_drvdata(dev);
+ struct tee_ioctl_invoke_arg inv_arg = {
+ .func = cmd,
+ .session = data->session_id,
+ .num_params = TEE_NUM_PARAMS,
+ };
+ struct tee_param param[TEE_NUM_PARAMS] = { };
+ struct tee_shm *in_shm = NULL;
+ struct tee_shm *out_shm = NULL;
+ u8 *buf;
+ int ret;
+
+ if (in && in_size) {
+ in_shm = tee_shm_alloc_kernel_buf(data->ctx, in_size);
+ if (IS_ERR(in_shm))
+ return PTR_ERR(in_shm);
+
+ buf = tee_shm_get_va(in_shm, 0);
+ if (IS_ERR(buf)) {
+ ret = PTR_ERR(buf);
+ goto out;
+ }
+ memcpy(buf, in, in_size);
+
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ param[0].u.memref.shm = in_shm;
+ param[0].u.memref.size = in_size;
+ }
+
+ if (out && out_size) {
+ out_shm = tee_shm_alloc_kernel_buf(data->ctx, out_size);
+ if (IS_ERR(out_shm)) {
+ ret = PTR_ERR(out_shm);
+ goto out;
+ }
+
+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ param[1].u.memref.shm = out_shm;
+ param[1].u.memref.size = out_size;
+ }
+
+ ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
+ if (ret < 0 || inv_arg.ret != 0) {
+ dev_err(dev,
+ "ICE cmd %u failed, ret=%d, err=0x%x\n",
+ cmd, ret, inv_arg.ret);
+ ret = ret ?: -EINVAL;
+ goto out;
+ }
+
+ if (out && out_size) {
+ buf = tee_shm_get_va(out_shm, 0);
+ if (IS_ERR(buf)) {
+ ret = PTR_ERR(buf);
+ goto out;
+ }
+ memcpy(out, buf, out_size);
+ memzero_explicit(buf, out_size);
+ }
+out:
+ if (in_shm && !IS_ERR(in_shm)) {
+ buf = tee_shm_get_va(in_shm, 0);
+ if (!IS_ERR(buf))
+ memzero_explicit(buf, in_size);
+ tee_shm_free(in_shm);
+ }
+ if (out_shm && !IS_ERR(out_shm))
+ tee_shm_free(out_shm);
+
+ return ret;
+}
+
+static int qcom_ice_tee_derive_sw_secret(struct device *dev,
+ const u8 *eph_key,
+ size_t eph_key_size,
+ u8 *sw_secret,
+ size_t sw_secret_size)
+{
+ return qcom_ice_tee_wrapped_key_call(dev, PTA_QCOM_ICE_GET_RAW_SECRET,
+ eph_key, eph_key_size,
+ sw_secret, sw_secret_size);
+}
+
+static int qcom_ice_tee_generate_key(struct device *dev,
+ u8 *lt_key, size_t lt_key_size)
+{
+ struct qcom_ice_tee_private *data = dev_get_drvdata(dev);
+ struct tee_ioctl_invoke_arg inv_arg = {
+ .func = PTA_QCOM_ICE_GENERATE_KEY,
+ .session = data->session_id,
+ .num_params = TEE_NUM_PARAMS,
+ };
+ struct tee_param param[TEE_NUM_PARAMS] = { };
+ struct tee_shm *key_shm;
+ u8 *buf;
+ size_t out_size;
+ int ret;
+
+ key_shm = tee_shm_alloc_kernel_buf(data->ctx, lt_key_size);
+ if (IS_ERR(key_shm))
+ return PTR_ERR(key_shm);
+
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ param[0].u.memref.shm = key_shm;
+ param[0].u.memref.shm_offs = 0;
+ param[0].u.memref.size = lt_key_size;
+
+ ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
+ if (ret < 0 || inv_arg.ret != 0) {
+ dev_err(dev,
+ "ICE generate_key failed, ret=%d, err=0x%x\n",
+ ret, inv_arg.ret);
+ ret = ret ?: -EINVAL;
+ goto out;
+ }
+
+ buf = tee_shm_get_va(key_shm, 0);
+ out_size = param[0].u.memref.size;
+
+ memcpy(lt_key, buf, lt_key_size);
+ memzero_explicit(buf, out_size);
+out:
+ tee_shm_free(key_shm);
+ return ret;
+}
+
+static int qcom_ice_tee_prepare_key(struct device *dev,
+ const u8 *lt_key,
+ size_t lt_key_size,
+ u8 *eph_key,
+ size_t eph_key_size)
+{
+ return qcom_ice_tee_wrapped_key_call(dev, PTA_QCOM_ICE_EXPORT_KEY,
+ lt_key, lt_key_size,
+ eph_key, eph_key_size);
+}
+
+static int qcom_ice_tee_import_key(struct device *dev,
+ const u8 *raw_key,
+ size_t raw_key_size,
+ u8 *lt_key,
+ size_t lt_key_size)
+{
+ return qcom_ice_tee_wrapped_key_call(dev, PTA_QCOM_ICE_IMPORT_KEY,
+ raw_key, raw_key_size,
+ lt_key, lt_key_size);
+}
+
+static bool qcom_ice_tee_available(struct device *dev)
+{
+ return true;
+}
+
+static bool qcom_ice_tee_has_wrapped_key_support(struct device *dev)
+{
+ struct qcom_ice_tee_private *data = dev_get_drvdata(dev);
+ struct tee_ioctl_invoke_arg inv_arg = {
+ .func = PTA_QCOM_ICE_HAS_WRAPPED_KEY_SUPPORT,
+ .session = data->session_id,
+ .num_params = TEE_NUM_PARAMS,
+ };
+ struct tee_param param[TEE_NUM_PARAMS] = {
+ [0] = {
+ .attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT,
+ .u.value.a = 0,
+ }
+ };
+ int ret;
+ bool has_support = false;
+
+ ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
+ if (ret < 0 || inv_arg.ret != 0) {
+ dev_err(dev,
+ "ICE wrapped_key_support failed, ret=%d, err=0x%x\n",
+ ret, inv_arg.ret);
+ goto out;
+ }
+
+ has_support = param[0].u.value.a;
+out:
+ return has_support;
+}
+
+static struct qcom_ice_ops qcom_ice_ops_tee = {
+ .drv_name = "qcom-ice-tee",
+ .is_ice_available = qcom_ice_tee_available,
+ .ice_invalidate_key = qcom_ice_tee_invalidate_key,
+ .ice_set_key = qcom_ice_tee_set_key,
+ .ice_has_wrapped_key_support = qcom_ice_tee_has_wrapped_key_support,
+ .ice_derive_sw_secret = qcom_ice_tee_derive_sw_secret,
+ .ice_generate_key = qcom_ice_tee_generate_key,
+ .ice_prepare_key = qcom_ice_tee_prepare_key,
+ .ice_import_key = qcom_ice_tee_import_key,
+};
+
+static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
+{
+ return ver->impl_id == TEE_IMPL_ID_OPTEE;
+}
+
+static int qcom_ice_tee_probe(struct tee_client_device *ice_dev)
+{
+ struct device *dev = &ice_dev->dev;
+ struct qcom_ice_tee_private *data;
+ struct tee_ioctl_open_session_arg sess_arg = {
+ .clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL,
+ };
+ int ret, err = -ENODEV;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
+ if (IS_ERR(data->ctx))
+ return -ENODEV;
+
+ export_uuid(sess_arg.uuid, &ice_dev->id.uuid);
+ ret = tee_client_open_session(data->ctx, &sess_arg, NULL);
+ if (ret < 0 || sess_arg.ret != 0) {
+ dev_err(dev,
+ "tee_client_open_session failed, ret=%d, err=0x%x\n",
+ ret, sess_arg.ret);
+ err = ret ?: -EINVAL;
+ goto out_ctx;
+ }
+
+ data->session_id = sess_arg.session;
+ dev_set_drvdata(dev, data);
+
+ qcom_ice_ops_tee.dev = dev;
+ qcom_ice_svc_ops_register(&qcom_ice_ops_tee);
+
+ return ret;
+out_ctx:
+ tee_client_close_context(data->ctx);
+
+ return err;
+}
+
+static void qcom_ice_tee_remove(struct tee_client_device *ice_dev)
+{
+ struct device *dev = &ice_dev->dev;
+ struct qcom_ice_tee_private *data = dev_get_drvdata(dev);
+
+ qcom_ice_svc_ops_unregister(&qcom_ice_ops_tee);
+ tee_client_close_session(data->ctx, data->session_id);
+ tee_client_close_context(data->ctx);
+}
+
+static const struct tee_client_device_id qcom_ice_tee_id_table[] = {
+ {UUID_INIT(0x29e87b9e, 0x012a, 0x4878,
+ 0xa1, 0xe1, 0xa1, 0xb9, 0x0a, 0x21, 0x5b, 0x16)},
+ {}
+};
+MODULE_DEVICE_TABLE(tee, qcom_ice_tee_id_table);
+
+static struct tee_client_driver optee_ice_tee_driver = {
+ .probe = qcom_ice_tee_probe,
+ .remove = qcom_ice_tee_remove,
+ .id_table = qcom_ice_tee_id_table,
+ .driver = {
+ .name = "qcom-ice-tee",
+ },
+};
+
+module_tee_client_driver(optee_ice_tee_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Qualcomm ICE TEE driver");
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH 3/5] firmware: qcom: Add an TEE bus based ICE back-end
2026-10-21 15:43 ` [PATCH 3/5] firmware: qcom: Add an TEE bus based ICE back-end Harshal Dev
@ 2026-10-22 7:47 ` Konrad Dybcio
2026-10-22 7:51 ` Konrad Dybcio
2026-10-22 7:52 ` Konrad Dybcio
2 siblings, 0 replies; 10+ messages in thread
From: Konrad Dybcio @ 2026-10-22 7:47 UTC (permalink / raw)
To: Harshal Dev, Bjorn Andersson, Konrad Dybcio, Abel Vesa,
Kuldeep Singh, Neeraj Soni, Manivannan Sadhasivam, Sumit Garg,
Selvam Sathappan Periakaruppan
Cc: Basant Kumar, linux-kernel, linux-arm-msm, linux-crypto
On 10/21/26 5:43 PM, Harshal Dev wrote:
> Add support for a TEE client driver which forwards calls from the Inline
> Crypto Engine (ICE) service (invoked by the ICE driver) to the OPTEE ICE
> Psuedo-TA.
LLM says: typo: "Psuedo"; s/an TEE bus/a TEE bus
> The ICE PTA supports both ICE Legacy and Standard modes. In Standard mode
> Hardware Key Manager v1 is supported.
>
> Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
> ---
[...]
> +config QCOM_ICE_TEE
> + tristate
> + select QCOM_ICE_SERVICE
> + depends on TEE
> + depends on !CPU_BIG_ENDIAN
> + default m if ARCH_QCOM
> + help
> + Enable the generic Inline Crypto Engine (ICE) firmware service TEE
> + implementation as a backend.
LLM says: please use tabs here
Konrad
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/5] firmware: qcom: Add an TEE bus based ICE back-end
2026-10-21 15:43 ` [PATCH 3/5] firmware: qcom: Add an TEE bus based ICE back-end Harshal Dev
2026-10-22 7:47 ` Konrad Dybcio
@ 2026-10-22 7:51 ` Konrad Dybcio
2026-10-22 7:52 ` Konrad Dybcio
2 siblings, 0 replies; 10+ messages in thread
From: Konrad Dybcio @ 2026-10-22 7:51 UTC (permalink / raw)
To: Harshal Dev, Bjorn Andersson, Konrad Dybcio, Abel Vesa,
Kuldeep Singh, Neeraj Soni, Manivannan Sadhasivam, Sumit Garg,
Selvam Sathappan Periakaruppan
Cc: Basant Kumar, linux-kernel, linux-arm-msm, linux-crypto
On 10/21/26 5:43 PM, Harshal Dev wrote:
> Add support for a TEE client driver which forwards calls from the Inline
> Crypto Engine (ICE) service (invoked by the ICE driver) to the OPTEE ICE
> Psuedo-TA.
>
> The ICE PTA supports both ICE Legacy and Standard modes. In Standard mode
> Hardware Key Manager v1 is supported.
>
> Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
> ---
[...]
> + ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
> + if (ret < 0 || inv_arg.ret != 0) {
> + dev_err(dev,
> + "ICE generate_key failed, ret=%d, err=0x%x\n",
> + ret, inv_arg.ret);
> + ret = ret ?: -EINVAL;
> + goto out;
> + }
> +
> + buf = tee_shm_get_va(key_shm, 0);
This can return an ERR_PTR()
> + out_size = param[0].u.memref.size;
This returned size is not validated, there are a couple occurences
of that
> +
> + memcpy(lt_key, buf, lt_key_size);
> + memzero_explicit(buf, out_size);
> +out:
> + tee_shm_free(key_shm);
LLM is concerned about freeing the key without zeroing the memory
first
> +static int qcom_ice_tee_probe(struct tee_client_device *ice_dev)
> +{
> + struct device *dev = &ice_dev->dev;
> + struct qcom_ice_tee_private *data;
> + struct tee_ioctl_open_session_arg sess_arg = {
> + .clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL,
> + };
> + int ret, err = -ENODEV;
> +
> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + data->ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
> + if (IS_ERR(data->ctx))
> + return -ENODEV;
> +
> + export_uuid(sess_arg.uuid, &ice_dev->id.uuid);
> + ret = tee_client_open_session(data->ctx, &sess_arg, NULL);
> + if (ret < 0 || sess_arg.ret != 0) {
> + dev_err(dev,
> + "tee_client_open_session failed, ret=%d, err=0x%x\n",
> + ret, sess_arg.ret);
> + err = ret ?: -EINVAL;
> + goto out_ctx;
Should we care about the specific retval that comes from the TEE?
> + }
> +
> + data->session_id = sess_arg.session;
> + dev_set_drvdata(dev, data);
> +
> + qcom_ice_ops_tee.dev = dev;
> + qcom_ice_svc_ops_register(&qcom_ice_ops_tee);
This can fail (but it currently returns void)
Konrad
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH 3/5] firmware: qcom: Add an TEE bus based ICE back-end
2026-10-21 15:43 ` [PATCH 3/5] firmware: qcom: Add an TEE bus based ICE back-end Harshal Dev
2026-10-22 7:47 ` Konrad Dybcio
2026-10-22 7:51 ` Konrad Dybcio
@ 2026-10-22 7:52 ` Konrad Dybcio
2 siblings, 0 replies; 10+ messages in thread
From: Konrad Dybcio @ 2026-10-22 7:52 UTC (permalink / raw)
To: Harshal Dev, Bjorn Andersson, Konrad Dybcio, Abel Vesa,
Kuldeep Singh, Neeraj Soni, Manivannan Sadhasivam, Sumit Garg,
Selvam Sathappan Periakaruppan
Cc: Basant Kumar, linux-kernel, linux-arm-msm, linux-crypto
On 10/21/26 5:43 PM, Harshal Dev wrote:
> Add support for a TEE client driver which forwards calls from the Inline
> Crypto Engine (ICE) service (invoked by the ICE driver) to the OPTEE ICE
> Psuedo-TA.
>
> The ICE PTA supports both ICE Legacy and Standard modes. In Standard mode
> Hardware Key Manager v1 is supported.
>
> Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
> ---
[...]
> +static int qcom_ice_tee_generate_key(struct device *dev,
> + u8 *lt_key, size_t lt_key_size)
> +{
> + struct qcom_ice_tee_private *data = dev_get_drvdata(dev);
> + struct tee_ioctl_invoke_arg inv_arg = {
> + .func = PTA_QCOM_ICE_GENERATE_KEY,
> + .session = data->session_id,
> + .num_params = TEE_NUM_PARAMS,
> + };
> + struct tee_param param[TEE_NUM_PARAMS] = { };
> + struct tee_shm *key_shm;
> + u8 *buf;
> + size_t out_size;
> + int ret;
> +
> + key_shm = tee_shm_alloc_kernel_buf(data->ctx, lt_key_size);
> + if (IS_ERR(key_shm))
> + return PTR_ERR(key_shm);
> +
> + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
> + param[0].u.memref.shm = key_shm;
> + param[0].u.memref.shm_offs = 0;
> + param[0].u.memref.size = lt_key_size;
> +
> + ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
> + if (ret < 0 || inv_arg.ret != 0) {
> + dev_err(dev,
> + "ICE generate_key failed, ret=%d, err=0x%x\n",
> + ret, inv_arg.ret);
> + ret = ret ?: -EINVAL;
> + goto out;
> + }
> +
> + buf = tee_shm_get_va(key_shm, 0);
> + out_size = param[0].u.memref.size;
> +
> + memcpy(lt_key, buf, lt_key_size);
> + memzero_explicit(buf, out_size);
LLM says: s/out_size/lt_key_size here?
Or said another way, currently lt_key_size and out_size are not
cross checked
[...]
> +static int qcom_ice_tee_probe(struct tee_client_device *ice_dev)
> +{
> + struct device *dev = &ice_dev->dev;
> + struct qcom_ice_tee_private *data;
> + struct tee_ioctl_open_session_arg sess_arg = {
> + .clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL,
> + };
> + int ret, err = -ENODEV;
> +
> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + data->ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
> + if (IS_ERR(data->ctx))
> + return -ENODEV;
> +
> + export_uuid(sess_arg.uuid, &ice_dev->id.uuid);
> + ret = tee_client_open_session(data->ctx, &sess_arg, NULL);
> + if (ret < 0 || sess_arg.ret != 0) {
> + dev_err(dev,
> + "tee_client_open_session failed, ret=%d, err=0x%x\n",
> + ret, sess_arg.ret);
> + err = ret ?: -EINVAL;
> + goto out_ctx;
> + }
> +
> + data->session_id = sess_arg.session;
> + dev_set_drvdata(dev, data);
> +
> + qcom_ice_ops_tee.dev = dev;
> + qcom_ice_svc_ops_register(&qcom_ice_ops_tee);
> +
> + return ret;
This is always a 'return 0'
Konrad
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 4/5] soc: qcom: ice: Migrate to the generic ICE service
2026-10-21 15:43 [PATCH 0/5] Add support for a TEE agnostic Inline Crypto Engine service Harshal Dev
` (2 preceding siblings ...)
2026-10-21 15:43 ` [PATCH 3/5] firmware: qcom: Add an TEE bus based ICE back-end Harshal Dev
@ 2026-10-21 15:43 ` Harshal Dev
2026-10-21 15:43 ` [PATCH 5/5] firmware: qcom: scm: Drop exported ICE wrapper functions Harshal Dev
4 siblings, 0 replies; 10+ messages in thread
From: Harshal Dev @ 2026-10-21 15:43 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Abel Vesa, Kuldeep Singh,
Neeraj Soni, Manivannan Sadhasivam, Sumit Garg,
Selvam Sathappan Periakaruppan
Cc: Basant Kumar, linux-kernel, linux-arm-msm, linux-crypto, Harshal Dev
Migrate the Inline Crypto Engine (ICE) driver to the generic ICE service
which re-directs calls from the driver to either the SCM or the TEE bus
based back-end driver at runtime.
This makes the ICE driver agnostic of the TEE firmware running on the
Qualcomm platform.
Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
drivers/soc/qcom/Kconfig | 2 +-
drivers/soc/qcom/ice.c | 30 +++++++++++++++---------------
2 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 535c8619197b..f68973efcabb 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -295,7 +295,7 @@ endif
config QCOM_INLINE_CRYPTO_ENGINE
tristate
- select QCOM_SCM
+ select QCOM_ICE_SERVICE
config QCOM_KRYO_L2_ACCESSORS
bool
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index e256595b9826..c075cab6f7fd 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -18,7 +18,7 @@
#include <linux/platform_device.h>
#include <linux/xarray.h>
-#include <linux/firmware/qcom/qcom_scm.h>
+#include <linux/firmware/qcom/qcom_ice.h>
#include <soc/qcom/ice.h>
@@ -176,7 +176,7 @@ static bool qcom_ice_check_supported(struct qcom_ice *ice)
* advertise support for raw keys or wrapped keys, HWKM cannot be used
* unconditionally. A module parameter is used to opt into using it.
*/
- if (ice->hwkm_version && qcom_scm_has_wrapped_key_support()) {
+ if (ice->hwkm_version && qcom_ice_svc_has_wrapped_key_support()) {
if (qcom_ice_use_wrapped_keys) {
dev_info(dev, "Using HWKM. Supporting wrapped keys only.\n");
ice->use_hwkm = true;
@@ -352,7 +352,7 @@ static int qcom_ice_program_wrapped_key(struct qcom_ice *ice, unsigned int slot,
struct device *dev = ice->dev;
union crypto_cfg cfg = {
.dusize = bkey->crypto_cfg.data_unit_size / 512,
- .capidx = QCOM_SCM_ICE_CIPHER_AES_256_XTS,
+ .capidx = QCOM_ICE_CIPHER_AES_256_XTS,
.cfge = QCOM_ICE_HWKM_CFG_ENABLE_VAL,
};
int err;
@@ -370,11 +370,11 @@ static int qcom_ice_program_wrapped_key(struct qcom_ice *ice, unsigned int slot,
qcom_ice_writel(ice, 0x0, QCOM_ICE_REG_CRYPTOCFG(slot));
/* Call into TrustZone to program the wrapped key using HWKM. */
- err = qcom_scm_ice_set_key(translate_hwkm_slot(ice, slot), bkey->bytes,
+ err = qcom_ice_svc_set_key(translate_hwkm_slot(ice, slot), bkey->bytes,
bkey->size, cfg.capidx, cfg.dusize);
if (err) {
dev_err_ratelimited(dev,
- "qcom_scm_ice_set_key failed; err=%d, slot=%u\n",
+ "qcom_ice_svc_set_key failed; err=%d, slot=%u\n",
err, slot);
return err;
}
@@ -422,8 +422,8 @@ int qcom_ice_program_key(struct qcom_ice *ice, unsigned int slot,
for (i = 0; i < ARRAY_SIZE(key.words); i++)
__cpu_to_be32s(&key.words[i]);
- err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
- QCOM_SCM_ICE_CIPHER_AES_256_XTS,
+ err = qcom_ice_svc_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
+ QCOM_ICE_CIPHER_AES_256_XTS,
blk_key->crypto_cfg.data_unit_size / 512);
memzero_explicit(&key, sizeof(key));
@@ -436,7 +436,7 @@ int qcom_ice_evict_key(struct qcom_ice *ice, int slot)
{
if (ice->hwkm_init_complete)
slot = translate_hwkm_slot(ice, slot);
- return qcom_scm_ice_invalidate_key(slot);
+ return qcom_ice_svc_invalidate_key(slot);
}
EXPORT_SYMBOL_GPL(qcom_ice_evict_key);
@@ -473,7 +473,7 @@ int qcom_ice_derive_sw_secret(struct qcom_ice *ice,
const u8 *eph_key, size_t eph_key_size,
u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
{
- int err = qcom_scm_derive_sw_secret(eph_key, eph_key_size,
+ int err = qcom_ice_svc_derive_sw_secret(eph_key, eph_key_size,
sw_secret,
BLK_CRYPTO_SW_SECRET_SIZE);
if (err == -EIO || err == -EINVAL)
@@ -496,7 +496,7 @@ int qcom_ice_generate_key(struct qcom_ice *ice,
{
int err;
- err = qcom_scm_generate_ice_key(lt_key,
+ err = qcom_ice_svc_generate_key(lt_key,
QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version));
if (err)
return err;
@@ -523,7 +523,7 @@ int qcom_ice_prepare_key(struct qcom_ice *ice,
{
int err;
- err = qcom_scm_prepare_ice_key(lt_key, lt_key_size,
+ err = qcom_ice_svc_prepare_key(lt_key, lt_key_size,
eph_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version));
if (err == -EIO || err == -EINVAL)
err = -EBADMSG; /* probably invalid key */
@@ -551,7 +551,7 @@ int qcom_ice_import_key(struct qcom_ice *ice,
{
int err;
- err = qcom_scm_import_ice_key(raw_key, raw_key_size,
+ err = qcom_ice_svc_import_key(raw_key, raw_key_size,
lt_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version));
if (err)
return err;
@@ -565,11 +565,11 @@ static struct qcom_ice *qcom_ice_create(struct device *dev,
{
struct qcom_ice *engine;
- if (!qcom_scm_is_available())
+ if (!qcom_ice_svc_ops_registered())
return ERR_PTR(-EPROBE_DEFER);
- if (!qcom_scm_ice_available()) {
- dev_warn(dev, "ICE SCM interface not found\n");
+ if (!qcom_ice_svc_available()) {
+ dev_warn(dev, "ICE firmware service interface not found\n");
return ERR_PTR(-EOPNOTSUPP);
}
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 5/5] firmware: qcom: scm: Drop exported ICE wrapper functions
2026-10-21 15:43 [PATCH 0/5] Add support for a TEE agnostic Inline Crypto Engine service Harshal Dev
` (3 preceding siblings ...)
2026-10-21 15:43 ` [PATCH 4/5] soc: qcom: ice: Migrate to the generic ICE service Harshal Dev
@ 2026-10-21 15:43 ` Harshal Dev
4 siblings, 0 replies; 10+ messages in thread
From: Harshal Dev @ 2026-10-21 15:43 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Abel Vesa, Kuldeep Singh,
Neeraj Soni, Manivannan Sadhasivam, Sumit Garg,
Selvam Sathappan Periakaruppan
Cc: Basant Kumar, linux-kernel, linux-arm-msm, linux-crypto, Harshal Dev
Drop the exported ICE wrapper functions from the SCM driver since the ICE
driver has now migrated to generic ICE service which allows re-direction of
of ICE secure service calls to the appropriate TEE (QTEE or OPTEE) at
runtime.
Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
drivers/firmware/qcom/qcom_scm.c | 110 ++++++++-------------------------
include/linux/firmware/qcom/qcom_scm.h | 20 ------
2 files changed, 27 insertions(+), 103 deletions(-)
diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 9aeb2cefa77a..2d2a4715a0c7 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -1405,7 +1405,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_ocmem_unlock);
* Return: true iff the SCM calls wrapped by qcom_scm_ice_invalidate_key() and
* qcom_scm_ice_set_key() are available.
*/
-static bool __qcom_scm_ice_available(struct device *dev)
+static bool qcom_scm_ice_available(struct device *dev)
{
return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_INVALIDATE_ICE_KEY) &&
@@ -1413,12 +1413,6 @@ static bool __qcom_scm_ice_available(struct device *dev)
QCOM_SCM_ES_CONFIG_SET_ICE_KEY);
}
-bool qcom_scm_ice_available(void)
-{
- return __qcom_scm_ice_available(__scm->dev);
-}
-EXPORT_SYMBOL_GPL(qcom_scm_ice_available);
-
/**
* qcom_scm_ice_invalidate_key() - Invalidate an inline encryption key
* @index: the keyslot to invalidate
@@ -1431,7 +1425,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_ice_available);
*
* Return: 0 on success; -errno on failure.
*/
-static int __qcom_scm_ice_invalidate_key(struct device *dev, u32 index)
+static int qcom_scm_ice_invalidate_key(struct device *dev, u32 index)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1444,12 +1438,6 @@ static int __qcom_scm_ice_invalidate_key(struct device *dev, u32 index)
return qcom_scm_call(dev, &desc, NULL);
}
-int qcom_scm_ice_invalidate_key(u32 index)
-{
- return __qcom_scm_ice_invalidate_key(__scm->dev, index);
-}
-EXPORT_SYMBOL_GPL(qcom_scm_ice_invalidate_key);
-
/**
* qcom_scm_ice_set_key() - Set an inline encryption key
* @index: the keyslot into which to set the key
@@ -1471,10 +1459,10 @@ EXPORT_SYMBOL_GPL(qcom_scm_ice_invalidate_key);
*
* Return: 0 on success; -errno on failure.
*/
-static int __qcom_scm_ice_set_key(struct device *dev, u32 index,
- const u8 *key, u32 key_size,
- enum qcom_ice_cipher cipher,
- u32 data_unit_size)
+static int qcom_scm_ice_set_key(struct device *dev, u32 index,
+ const u8 *key, u32 key_size,
+ enum qcom_ice_cipher cipher,
+ u32 data_unit_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1506,16 +1494,7 @@ static int __qcom_scm_ice_set_key(struct device *dev, u32 index,
return ret;
}
-int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
- enum qcom_scm_ice_cipher cipher, u32 data_unit_size)
-{
- return __qcom_scm_ice_set_key(__scm->dev, index, key, key_size,
- (enum qcom_ice_cipher)cipher,
- data_unit_size);
-}
-EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key);
-
-static bool __qcom_scm_has_wrapped_key_support(struct device *dev)
+static bool qcom_scm_has_wrapped_key_support(struct device *dev)
{
return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_DERIVE_SW_SECRET) &&
@@ -1527,12 +1506,6 @@ static bool __qcom_scm_has_wrapped_key_support(struct device *dev)
QCOM_SCM_ES_IMPORT_ICE_KEY);
}
-bool qcom_scm_has_wrapped_key_support(void)
-{
- return __qcom_scm_has_wrapped_key_support(__scm->dev);
-}
-EXPORT_SYMBOL_GPL(qcom_scm_has_wrapped_key_support);
-
/**
* qcom_scm_derive_sw_secret() - Derive software secret from wrapped key
* @eph_key: an ephemerally-wrapped key
@@ -1549,9 +1522,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_has_wrapped_key_support);
*
* Return: 0 on success; -errno on failure.
*/
-static int __qcom_scm_derive_sw_secret(struct device *dev,
- const u8 *eph_key, size_t eph_key_size,
- u8 *sw_secret, size_t sw_secret_size)
+static int qcom_scm_derive_sw_secret(struct device *dev,
+ const u8 *eph_key, size_t eph_key_size,
+ u8 *sw_secret, size_t sw_secret_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1589,13 +1562,6 @@ static int __qcom_scm_derive_sw_secret(struct device *dev,
return ret;
}
-int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
- u8 *sw_secret, size_t sw_secret_size)
-{
- return __qcom_scm_derive_sw_secret(__scm->dev, eph_key, eph_key_size,
- sw_secret, sw_secret_size);
-}
-EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
/**
* qcom_scm_generate_ice_key() - Generate a wrapped key for storage encryption
@@ -1608,8 +1574,8 @@ EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
*
* Return: 0 on success; -errno on failure.
*/
-static int __qcom_scm_generate_ice_key(struct device *dev,
- u8 *lt_key, size_t lt_key_size)
+static int qcom_scm_generate_ice_key(struct device *dev,
+ u8 *lt_key, size_t lt_key_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1636,12 +1602,6 @@ static int __qcom_scm_generate_ice_key(struct device *dev,
return ret;
}
-int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size)
-{
- return __qcom_scm_generate_ice_key(__scm->dev, lt_key, lt_key_size);
-}
-EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key);
-
/**
* qcom_scm_prepare_ice_key() - Re-wrap a key with the per-boot ephemeral key
* @lt_key: a long-term wrapped key
@@ -1655,9 +1615,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key);
*
* Return: 0 on success; -errno on failure.
*/
-static int __qcom_scm_prepare_ice_key(struct device *dev,
- const u8 *lt_key, size_t lt_key_size,
- u8 *eph_key, size_t eph_key_size)
+static int qcom_scm_prepare_ice_key(struct device *dev,
+ 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,
@@ -1695,14 +1655,6 @@ static int __qcom_scm_prepare_ice_key(struct device *dev,
return ret;
}
-int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
- u8 *eph_key, size_t eph_key_size)
-{
- return __qcom_scm_prepare_ice_key(__scm->dev, lt_key, lt_key_size,
- eph_key, eph_key_size);
-}
-EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key);
-
/**
* qcom_scm_import_ice_key() - Import key for storage encryption
* @raw_key: the raw key to import
@@ -1716,9 +1668,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key);
*
* Return: 0 on success; -errno on failure.
*/
-static int __qcom_scm_import_ice_key(struct device *dev,
- const u8 *raw_key, size_t raw_key_size,
- u8 *lt_key, size_t lt_key_size)
+static int qcom_scm_import_ice_key(struct device *dev,
+ const u8 *raw_key, size_t raw_key_size,
+ u8 *lt_key, size_t lt_key_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1756,24 +1708,16 @@ static int __qcom_scm_import_ice_key(struct device *dev,
return ret;
}
-int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
- u8 *lt_key, size_t lt_key_size)
-{
- return __qcom_scm_import_ice_key(__scm->dev, raw_key, raw_key_size,
- lt_key, lt_key_size);
-}
-EXPORT_SYMBOL_GPL(qcom_scm_import_ice_key);
-
static struct qcom_ice_ops qcom_ice_ops_scm = {
.drv_name = "qcom_scm",
- .is_ice_available = __qcom_scm_ice_available,
- .ice_invalidate_key = __qcom_scm_ice_invalidate_key,
- .ice_set_key = __qcom_scm_ice_set_key,
- .ice_has_wrapped_key_support = __qcom_scm_has_wrapped_key_support,
- .ice_derive_sw_secret = __qcom_scm_derive_sw_secret,
- .ice_generate_key = __qcom_scm_generate_ice_key,
- .ice_prepare_key = __qcom_scm_prepare_ice_key,
- .ice_import_key = __qcom_scm_import_ice_key,
+ .is_ice_available = qcom_scm_ice_available,
+ .ice_invalidate_key = qcom_scm_ice_invalidate_key,
+ .ice_set_key = qcom_scm_ice_set_key,
+ .ice_has_wrapped_key_support = qcom_scm_has_wrapped_key_support,
+ .ice_derive_sw_secret = qcom_scm_derive_sw_secret,
+ .ice_generate_key = qcom_scm_generate_ice_key,
+ .ice_prepare_key = qcom_scm_prepare_ice_key,
+ .ice_import_key = qcom_scm_import_ice_key,
};
/**
@@ -2905,7 +2849,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
qcom_pas_ops_register(&qcom_pas_ops_scm);
}
- if (__qcom_scm_ice_available(scm->dev)) {
+ if (qcom_scm_ice_available(scm->dev)) {
qcom_ice_ops_scm.dev = scm->dev;
qcom_ice_svc_ops_register(&qcom_ice_ops_scm);
}
diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h
index a0a6bc0229c4..36b87be82804 100644
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -46,13 +46,6 @@ enum qcom_scm_sec_dev_id {
QCOM_SCM_ICE_DEV_ID = 20,
};
-enum qcom_scm_ice_cipher {
- QCOM_SCM_ICE_CIPHER_AES_128_XTS = 0,
- QCOM_SCM_ICE_CIPHER_AES_128_CBC = 1,
- QCOM_SCM_ICE_CIPHER_AES_256_XTS = 3,
- QCOM_SCM_ICE_CIPHER_AES_256_CBC = 4,
-};
-
#define QCOM_SCM_PERM_READ 0x4
#define QCOM_SCM_PERM_WRITE 0x2
#define QCOM_SCM_PERM_EXEC 0x1
@@ -86,19 +79,6 @@ int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset, u32 size,
u32 mode);
int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset, u32 size);
-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);
-bool qcom_scm_has_wrapped_key_support(void);
-int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_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_key_size);
-int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_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.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread