diff mbox series

[3/4] soc: qcom: add HWKM library for storage encryption

Message ID 20211103231840.115521-4-quic_gaurkash@quicinc.com (mailing list archive)
State New, archived
Headers show
Series Adds wrapped key support for inline storage encryption | expand

Commit Message

Gaurav Kashyap (QUIC) Nov. 3, 2021, 11:18 p.m. UTC
Wrapped keys should utilize hardware to protect the keys
used for storage encryption. Qualcomm's Inline Crypto Engine
supports a hardware block called Hardware Key Manager (HWKM)
for key management.

Although most of the interactions to this hardware block happens
via a secure execution environment, some initializations for the
slave present in ICE can be done from the kernel.

This can also be a placeholder for when the hardware provides more
capabilites to be acessed from the linux kernel in the future.

Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
---
 drivers/soc/qcom/Kconfig        |   7 ++
 drivers/soc/qcom/Makefile       |   1 +
 drivers/soc/qcom/qti-ice-hwkm.c |  77 ++++++++++++++++++++++
 drivers/soc/qcom/qti-ice-regs.h | 112 ++++++++++++++++++++++++++++++++
 include/linux/qti-ice-common.h  |   6 ++
 5 files changed, 203 insertions(+)
 create mode 100644 drivers/soc/qcom/qti-ice-hwkm.c

Comments

Eric Biggers Nov. 4, 2021, 11:46 p.m. UTC | #1
On Wed, Nov 03, 2021 at 04:18:39PM -0700, Gaurav Kashyap wrote:
> Wrapped keys should utilize hardware to protect the keys
> used for storage encryption. Qualcomm's Inline Crypto Engine
> supports a hardware block called Hardware Key Manager (HWKM)
> for key management.
> 
> Although most of the interactions to this hardware block happens
> via a secure execution environment, some initializations for the
> slave present in ICE can be done from the kernel.
> 
> This can also be a placeholder for when the hardware provides more
> capabilites to be acessed from the linux kernel in the future.
> 
> Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com>
> ---
>  drivers/soc/qcom/Kconfig        |   7 ++
>  drivers/soc/qcom/Makefile       |   1 +
>  drivers/soc/qcom/qti-ice-hwkm.c |  77 ++++++++++++++++++++++
>  drivers/soc/qcom/qti-ice-regs.h | 112 ++++++++++++++++++++++++++++++++
>  include/linux/qti-ice-common.h  |   6 ++
>  5 files changed, 203 insertions(+)
>  create mode 100644 drivers/soc/qcom/qti-ice-hwkm.c
> 
> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> index 39f223ed8cdd..d441d5b81c53 100644
> --- a/drivers/soc/qcom/Kconfig
> +++ b/drivers/soc/qcom/Kconfig
> @@ -216,4 +216,11 @@ config QTI_ICE_COMMON
>  	help
>  	  Enable the common ICE library that can be used
>  	  by UFS and EMMC drivers for ICE functionality.
> +
> +config QTI_HW_WRAPPED_KEYS
> +	tristate "QTI HW Wrapped Keys"
> +	depends on QTI_ICE_COMMON
> +	help
> +	  Enable wrapped key functionality for storage
> +	  encryption.

It might be reasonable to just include the hardware-wrapped key support whenever
QTI_ICE_COMMON is enabled.  Note that I'm not planning separate kconfig options
at the block or fscrypt levels.

If we do have this kconfig option, then please make sure that the help text
properly explains it.  That should include linking to the documentation where
the reader can find out more about what this feature is, and hence why they
might want to enable it, or not enable it.

Also this code probably should be part of the qti-ice-common module (which maybe
should be called "qti-ice-lib"?) rather than its own module.  That would mean
making QTI_HW_WRAPPED_KEYS a bool option that controls whether qti-ice-hwkm.c is
built into qti-ice-common, rather than a tristate that controls whether it's
built into its own module.

- Eric
diff mbox series

Patch

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 39f223ed8cdd..d441d5b81c53 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -216,4 +216,11 @@  config QTI_ICE_COMMON
 	help
 	  Enable the common ICE library that can be used
 	  by UFS and EMMC drivers for ICE functionality.
+
+config QTI_HW_WRAPPED_KEYS
+	tristate "QTI HW Wrapped Keys"
+	depends on QTI_ICE_COMMON
+	help
+	  Enable wrapped key functionality for storage
+	  encryption.
 endmenu
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 57840b19b7ee..56d1f4b8d436 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -27,3 +27,4 @@  obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
 obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
 obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) +=	kryo-l2-accessors.o
 obj-$(CONFIG_QTI_ICE_COMMON) += qti-ice-common.o
+obj-$(CONFIG_QTI_HW_WRAPPED_KEYS) += qti-ice-hwkm.o
diff --git a/drivers/soc/qcom/qti-ice-hwkm.c b/drivers/soc/qcom/qti-ice-hwkm.c
new file mode 100644
index 000000000000..d65873745999
--- /dev/null
+++ b/drivers/soc/qcom/qti-ice-hwkm.c
@@ -0,0 +1,77 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HWKM ICE library for storage encryption.
+ *
+ * Copyright (c) 2021, Linux Foundation. All rights reserved.
+ */
+
+#include <linux/qti-ice-common.h>
+#include "qti-ice-regs.h"
+
+static int qti_ice_hwkm_bist_status(const struct ice_mmio_data *mmio, int version)
+{
+	if (!qti_ice_hwkm_testb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_STATUS,
+			(version == 1) ? BIST_DONE_V1 : BIST_DONE_V2) ||
+        !qti_ice_hwkm_testb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_STATUS,
+			(version == 1) ? CRYPTO_LIB_BIST_DONE_V1 :
+			CRYPTO_LIB_BIST_DONE_V2) ||
+        !qti_ice_hwkm_testb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_STATUS,
+			(version == 1) ? BOOT_CMD_LIST1_DONE_V1 :
+			BOOT_CMD_LIST1_DONE_V2) ||
+        !qti_ice_hwkm_testb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_STATUS,
+			(version == 1) ? BOOT_CMD_LIST0_DONE_V1 :
+			BOOT_CMD_LIST0_DONE_V2) ||
+        !qti_ice_hwkm_testb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_STATUS,
+			(version == 1) ? KT_CLEAR_DONE_V1 :
+			KT_CLEAR_DONE_V2))
+		return -EINVAL;
+	return 0;
+}
+
+static int qti_ice_hwkm_init_sequence(const struct ice_mmio_data *mmio,
+                                      int version)
+{
+	u32 val = 0;
+
+	/*
+	 * 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 (version >= 2) {
+		val = qti_ice_readl(mmio->ice_mmio, QTI_ICE_REGS_CONTROL);
+		val = val & 0xFFFFFFFE;
+		qti_ice_writel(mmio->ice_mmio, val, QTI_ICE_REGS_CONTROL);
+	} else {
+		qti_ice_hwkm_writel(mmio->ice_hwkm_mmio, 0x7,
+				    QTI_HWKM_ICE_RG_TZ_KM_CTL);
+	}
+
+	/* Check BIST status */
+	if (qti_ice_hwkm_bist_status(mmio, version))
+		return -EINVAL;
+
+	/* Disable CRC check */
+	qti_ice_hwkm_clearb(mmio->ice_hwkm_mmio, QTI_HWKM_ICE_RG_TZ_KM_CTL,
+			    CRC_CHECK_EN);
+
+	/* Set RSP_FIFO_FULL bit */
+	qti_ice_hwkm_setb(mmio->ice_hwkm_mmio,
+			QTI_HWKM_ICE_RG_BANK0_BANKN_IRQ_STATUS, RSP_FIFO_FULL);
+
+	return 0;
+}
+
+int qti_ice_hwkm_init(const struct ice_mmio_data *mmio, int version)
+{
+	if (!mmio->ice_hwkm_mmio)
+		return -EINVAL;
+
+	return qti_ice_hwkm_init_sequence(mmio, version);
+}
+EXPORT_SYMBOL(qti_ice_hwkm_init);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/qti-ice-regs.h b/drivers/soc/qcom/qti-ice-regs.h
index 47c625c9d536..4c8d9fd62e42 100644
--- a/drivers/soc/qcom/qti-ice-regs.h
+++ b/drivers/soc/qcom/qti-ice-regs.h
@@ -137,9 +137,121 @@ 
 			 QTI_ICE_QTIC_DBG_OPEN_EVENT |		\
 			 QTI_ICE_KEYS_RAM_RESET_COMPLETED)
 
+/* Read/write macros for ICE address space */
 #define qti_ice_writel(mmio, val, reg)		\
 	writel_relaxed((val), mmio + (reg))
 #define qti_ice_readl(mmio, reg)		\
 	readl_relaxed(mmio + (reg))
 
+/* Registers for ICE HWKM Slave */
+
+#define HWKM_VERSION_STEP_REV_MASK 			0xFFFF
+#define HWKM_VERSION_STEP_REV				0 /* bit 15-0 */
+#define HWKM_VERSION_MAJOR_REV_MASK			0xFF000000
+#define HWKM_VERSION_MAJOR_REV				24 /* bit 31-24 */
+#define HWKM_VERSION_MINOR_REV_MASK			0xFF0000
+#define HWKM_VERSION_MINOR_REV				16 /* bit 23-16 */
+
+/* QTI HWKM ICE slave config and status registers */
+
+#define QTI_HWKM_ICE_RG_IPCAT_VERSION			0x0000
+#define QTI_HWKM_ICE_RG_KEY_POLICY_VERSION		0x0004
+#define QTI_HWKM_ICE_RG_SHARED_STATUS			0x0008
+#define QTI_HWKM_ICE_RG_KEYTABLE_SIZE			0x000C
+
+#define QTI_HWKM_ICE_RG_TZ_KM_CTL			0x1000
+#define QTI_HWKM_ICE_RG_TZ_KM_STATUS			0x1004
+#define QTI_HWKM_ICE_RG_TZ_KM_STATUS_IRQ_MASK		0x1008
+#define QTI_HWKM_ICE_RG_TZ_KM_BOOT_STAGE_OTP		0x100C
+#define QTI_HWKM_ICE_RG_TZ_KM_DEBUG_CTL			0x1010
+#define QTI_HWKM_ICE_RG_TZ_KM_DEBUG_WRITE		0x1014
+#define QTI_HWKM_ICE_RG_TZ_KM_DEBUG_READ		0x1018
+#define QTI_HWKM_ICE_RG_TZ_TPKEY_RECEIVE_CTL		0x101C
+#define QTI_HWKM_ICE_RG_TZ_TPKEY_RECEIVE_STATUS		0x1020
+#define QTI_HWKM_ICE_RG_TZ_KM_COMMON_IRQ_ROUTING	0x1024
+
+/* HWKM_ICEMEM_SLAVE_ICE_KM_RG_TZ_KM_CTL */
+#define CRC_CHECK_EN					0
+#define KEYTABLE_HW_WR_ACCESS_EN			1
+#define KEYTABLE_HW_RD_ACCESS_EN			2
+#define BOOT_INIT0_DISABLE				3
+#define BOOT_INIT1_DISABLE				4
+#define ICE_LEGACY_MODE_EN_OTP				5
+
+/* HWKM_ICEMEM_SLAVE_ICE_KM_RG_TZ_KM_STATUS for v2 and above*/
+#define KT_CLEAR_DONE_V2				0
+#define BOOT_CMD_LIST0_DONE_V2				1
+#define BOOT_CMD_LIST1_DONE_V2				2
+#define LAST_ACTIVITY_BANK_V2				3
+#define CRYPTO_LIB_BIST_ERROR_V2			6
+#define CRYPTO_LIB_BIST_DONE_V2				7
+#define BIST_ERROR_V2					8
+#define BIST_DONE_V2					9
+#define LAST_ACTIVITY_BANK_MASK_V2			0x38
+
+/* HWKM_ICEMEM_SLAVE_ICE_KM_RG_TZ_KM_STATUS for v1*/
+#define KT_CLEAR_DONE_V1				0
+#define BOOT_CMD_LIST0_DONE_V1				1
+#define BOOT_CMD_LIST1_DONE_V1				2
+#define KEYTABLE_KEY_POLICY_V1				3
+#define KEYTABLE_INTEGRITY_ERROR_V1			4
+#define KEYTABLE_KEY_SLOT_ERROR_V1			5
+#define KEYTABLE_KEY_SLOT_NOT_EVEN_ERROR_V1		6
+#define KEYTABLE_KEY_SLOT_OUT_OF_RANGE_V1		7
+#define KEYTABLE_KEY_SIZE_ERROR_V1			8
+#define KEYTABLE_OPERATION_ERROR_V1			9
+#define LAST_ACTIVITY_BANK_V1				10
+#define CRYPTO_LIB_BIST_ERROR_V1			13
+#define CRYPTO_LIB_BIST_DONE_V1				14
+#define BIST_ERROR_V1					15
+#define BIST_DONE_V1					16
+
+/* HWKM_ICEMEM_SLAVE_ICE_KM_RG_TZ_TPKEY_RECEIVE_CTL */
+#define TPKEY_EN					8
+
+/* QTI HWKM ICE slave register bank 0 */
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_CTL			0x2000
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_STATUS		0x2004
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_IRQ_STATUS		0x2008
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_IRQ_MASK		0x200C
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_ESR			0x2010
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_ESR_IRQ_MASK	0x2014
+#define QTI_HWKM_ICE_RG_BANK0_BANKN_ESYNR		0x2018
+
+/* QTI_HWKM_ICE_RG_BANKN_IRQ_STATUS */
+#define ARB_GRAN_WINNER					0
+#define CMD_DONE_BIT					1
+#define RSP_FIFO_NOT_EMPTY				2
+#define RSP_FIFO_FULL					3
+#define RSP_FIFO_UNDERFLOW				4
+#define CMD_FIFO_UNDERFLOW				5
+
+/* Read/write macros for ICE HWKM address space */
+
+#define qti_ice_hwkm_readl(hwkm_mmio, reg)		\
+	(readl_relaxed(hwkm_mmio + (reg)))
+#define qti_ice_hwkm_writel(hwkm_mmio, val, reg)	\
+	(writel_relaxed((val), hwkm_mmio + (reg)))
+#define qti_ice_hwkm_setb(hwkm_mmio, reg, nr) {		\
+	u32 val = qti_ice_hwkm_readl(hwkm_mmio, reg);	\
+	val |= (0x1 << nr);				\
+	qti_ice_hwkm_writel(hwkm_mmio, val, reg);	\
+}
+#define qti_ice_hwkm_clearb(hwkm_mmio, reg, nr) {	\
+	u32 val = qti_ice_hwkm_readl(hwkm_mmio, reg);	\
+	val &= ~(0x1 << nr);				\
+	qti_ice_hwkm_writel(hwkm_mmio, val, reg);	\
+}
+
+static inline bool qti_ice_hwkm_testb(void __iomem *ice_hwkm_mmio,
+				      u32 reg, u8 nr)
+{
+	u32 val = qti_ice_hwkm_readl(ice_hwkm_mmio, reg);
+
+	val = (val >> nr) & 0x1;
+	if (val == 0)
+		return false;
+	return true;
+}
+
 #endif /* _QTI_INLINE_CRYPTO_ENGINE_REGS_H_ */
diff --git a/include/linux/qti-ice-common.h b/include/linux/qti-ice-common.h
index 433422b34a7d..b0a50a1c6876 100644
--- a/include/linux/qti-ice-common.h
+++ b/include/linux/qti-ice-common.h
@@ -23,4 +23,10 @@  int qti_ice_keyslot_program(const struct ice_mmio_data *mmio,
                 unsigned int slot, u8 data_unit_mask, int capid);
 int qti_ice_keyslot_evict(unsigned int slot);
 
+#if IS_ENABLED(CONFIG_QTI_HW_WRAPPED_KEYS)
+int qti_ice_hwkm_init(const struct ice_mmio_data *mmio, int version);
+#else
+static inline int qti_ice_hwkm_init(const struct ice_mmio_data *mmio,
+					int version) { return -ENODEV; }
+#endif /* CONFIG_QTI_HW_WRAPPED_KEYS */
 #endif /* _QTI_ICE_COMMON_H */