From patchwork Mon Dec 6 22:57:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gaurav Kashyap \(QUIC\)" X-Patchwork-Id: 521131 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E342BC4332F for ; Mon, 6 Dec 2021 22:58:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376705AbhLFXC1 (ORCPT ); Mon, 6 Dec 2021 18:02:27 -0500 Received: from alexa-out-sd-02.qualcomm.com ([199.106.114.39]:37432 "EHLO alexa-out-sd-02.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376698AbhLFXC0 (ORCPT ); Mon, 6 Dec 2021 18:02:26 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1638831537; x=1670367537; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=WGylPRUG0UYIpdxPi0FmgRwNxnArJ+vsqepiE4sU9QM=; b=aNeTaqqhsF4lInvqRQRcYuhe7m3IydKU2amQpwDBynwtep3GxH5V+e2B iVD4kgzgCno8jPhXIiP6G7R8AbgwsNUACDbGpXHflk4Tv3maYybXsRDDi JdDye8PftkHj/4XE42G7ZVkV22fPvfLA/ptBztB4Rni6VtEUy6RSRldRg o=; Received: from unknown (HELO ironmsg04-sd.qualcomm.com) ([10.53.140.144]) by alexa-out-sd-02.qualcomm.com with ESMTP; 06 Dec 2021 14:58:57 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg04-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Dec 2021 14:58:57 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Mon, 6 Dec 2021 14:58:56 -0800 Received: from gabriel.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Mon, 6 Dec 2021 14:58:56 -0800 From: Gaurav Kashyap To: , CC: , , , , , , Gaurav Kashyap Subject: [PATCH 02/10] scsi: ufs: qcom: move ICE functionality to common library Date: Mon, 6 Dec 2021 14:57:17 -0800 Message-ID: <20211206225725.77512-3-quic_gaurkash@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211206225725.77512-1-quic_gaurkash@quicinc.com> References: <20211206225725.77512-1-quic_gaurkash@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Remove the ICE support in UFS and use the shared library for crypto functionality. Signed-off-by: Gaurav Kashyap --- drivers/scsi/ufs/Kconfig | 1 + drivers/scsi/ufs/ufs-qcom-ice.c | 169 +++----------------------------- drivers/scsi/ufs/ufs-qcom.h | 3 +- 3 files changed, 15 insertions(+), 158 deletions(-) diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index 432df76e6318..622a4c3fbf70 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -101,6 +101,7 @@ config SCSI_UFS_QCOM tristate "QCOM specific hooks to UFS controller platform driver" depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM select QCOM_SCM if SCSI_UFS_CRYPTO + select QTI_ICE_COMMON if SCSI_UFS_CRYPTO select RESET_CONTROLLER help This selects the QCOM specific additions to UFSHCD platform driver. diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c index bbb0ad7590ec..3826643bf537 100644 --- a/drivers/scsi/ufs/ufs-qcom-ice.c +++ b/drivers/scsi/ufs/ufs-qcom-ice.c @@ -8,90 +8,11 @@ #include #include +#include #include "ufshcd-crypto.h" #include "ufs-qcom.h" -#define AES_256_XTS_KEY_SIZE 64 - -/* QCOM ICE registers */ - -#define QCOM_ICE_REG_CONTROL 0x0000 -#define QCOM_ICE_REG_RESET 0x0004 -#define QCOM_ICE_REG_VERSION 0x0008 -#define QCOM_ICE_REG_FUSE_SETTING 0x0010 -#define QCOM_ICE_REG_PARAMETERS_1 0x0014 -#define QCOM_ICE_REG_PARAMETERS_2 0x0018 -#define QCOM_ICE_REG_PARAMETERS_3 0x001C -#define QCOM_ICE_REG_PARAMETERS_4 0x0020 -#define QCOM_ICE_REG_PARAMETERS_5 0x0024 - -/* QCOM ICE v3.X only */ -#define QCOM_ICE_GENERAL_ERR_STTS 0x0040 -#define QCOM_ICE_INVALID_CCFG_ERR_STTS 0x0030 -#define QCOM_ICE_GENERAL_ERR_MASK 0x0044 - -/* QCOM ICE v2.X only */ -#define QCOM_ICE_REG_NON_SEC_IRQ_STTS 0x0040 -#define QCOM_ICE_REG_NON_SEC_IRQ_MASK 0x0044 - -#define QCOM_ICE_REG_NON_SEC_IRQ_CLR 0x0048 -#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME1 0x0050 -#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME2 0x0054 -#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME1 0x0058 -#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME2 0x005C -#define QCOM_ICE_REG_STREAM1_BIST_ERROR_VEC 0x0060 -#define QCOM_ICE_REG_STREAM2_BIST_ERROR_VEC 0x0064 -#define QCOM_ICE_REG_STREAM1_BIST_FINISH_VEC 0x0068 -#define QCOM_ICE_REG_STREAM2_BIST_FINISH_VEC 0x006C -#define QCOM_ICE_REG_BIST_STATUS 0x0070 -#define QCOM_ICE_REG_BYPASS_STATUS 0x0074 -#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000 -#define QCOM_ICE_REG_ENDIAN_SWAP 0x1004 -#define QCOM_ICE_REG_TEST_BUS_CONTROL 0x1010 -#define QCOM_ICE_REG_TEST_BUS_REG 0x1014 - -/* BIST ("built-in self-test"?) status flags */ -#define QCOM_ICE_BIST_STATUS_MASK 0xF0000000 - -#define QCOM_ICE_FUSE_SETTING_MASK 0x1 -#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2 -#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4 - -#define qcom_ice_writel(host, val, reg) \ - writel((val), (host)->ice_mmio + (reg)) -#define qcom_ice_readl(host, reg) \ - readl((host)->ice_mmio + (reg)) - -static bool qcom_ice_supported(struct ufs_qcom_host *host) -{ - struct device *dev = host->hba->dev; - u32 regval = qcom_ice_readl(host, QCOM_ICE_REG_VERSION); - int major = regval >> 24; - int minor = (regval >> 16) & 0xFF; - int step = regval & 0xFFFF; - - /* For now this driver only supports ICE version 3. */ - if (major != 3) { - dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n", - major, minor, step); - return false; - } - - dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", - major, minor, step); - - /* If fuses are blown, ICE might not work in the standard way. */ - regval = qcom_ice_readl(host, QCOM_ICE_REG_FUSE_SETTING); - if (regval & (QCOM_ICE_FUSE_SETTING_MASK | - QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK | - QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) { - dev_warn(dev, "Fuses are blown; ICE is unusable!\n"); - return false; - } - return true; -} - int ufs_qcom_ice_init(struct ufs_qcom_host *host) { struct ufs_hba *hba = host->hba; @@ -115,14 +36,14 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *host) goto disable; } - host->ice_mmio = devm_ioremap_resource(dev, res); - if (IS_ERR(host->ice_mmio)) { - err = PTR_ERR(host->ice_mmio); + host->ice_data.ice_mmio = devm_ioremap_resource(dev, res); + if (IS_ERR(host->ice_data.ice_mmio)) { + err = PTR_ERR(host->ice_data.ice_mmio); dev_err(dev, "Failed to map ICE registers; err=%d\n", err); return err; } - if (!qcom_ice_supported(host)) + if (qti_ice_init(&host->ice_data)) goto disable; return 0; @@ -133,71 +54,21 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *host) return 0; } -static void qcom_ice_low_power_mode_enable(struct ufs_qcom_host *host) -{ - u32 regval; - - regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL); - /* - * Enable low power mode sequence - * [0]-0, [1]-0, [2]-0, [3]-E, [4]-0, [5]-0, [6]-0, [7]-0 - */ - regval |= 0x7000; - qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); -} - -static void qcom_ice_optimization_enable(struct ufs_qcom_host *host) -{ - u32 regval; - - /* ICE Optimizations Enable Sequence */ - regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL); - regval |= 0xD807100; - /* ICE HPG requires delay before writing */ - udelay(5); - qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL); - udelay(5); -} int ufs_qcom_ice_enable(struct ufs_qcom_host *host) { if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) return 0; - qcom_ice_low_power_mode_enable(host); - qcom_ice_optimization_enable(host); - return ufs_qcom_ice_resume(host); -} -/* Poll until all BIST bits are reset */ -static int qcom_ice_wait_bist_status(struct ufs_qcom_host *host) -{ - int count; - u32 reg; - - for (count = 0; count < 100; count++) { - reg = qcom_ice_readl(host, QCOM_ICE_REG_BIST_STATUS); - if (!(reg & QCOM_ICE_BIST_STATUS_MASK)) - break; - udelay(50); - } - if (reg) - return -ETIMEDOUT; - return 0; + return qti_ice_enable(&host->ice_data); } int ufs_qcom_ice_resume(struct ufs_qcom_host *host) { - int err; - if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) return 0; - err = qcom_ice_wait_bist_status(host); - if (err) { - dev_err(host->hba->dev, "BIST status error (%d)\n", err); - return err; - } - return 0; + return qti_ice_resume(&host->ice_data); } /* @@ -208,15 +79,10 @@ int ufs_qcom_ice_program_key(struct ufs_hba *hba, const union ufs_crypto_cfg_entry *cfg, int slot) { union ufs_crypto_cap_entry cap; - union { - u8 bytes[AES_256_XTS_KEY_SIZE]; - u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)]; - } key; - int i; - int err; + struct ufs_qcom_host *host = ufshcd_get_variant(hba); if (!(cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE)) - return qcom_scm_ice_invalidate_key(slot); + return qti_ice_keyslot_evict(slot); /* Only AES-256-XTS has been tested so far. */ cap = hba->crypto_cap_array[cfg->crypto_cap_idx]; @@ -228,18 +94,7 @@ int ufs_qcom_ice_program_key(struct ufs_hba *hba, return -EINVAL; } - memcpy(key.bytes, cfg->crypto_key, AES_256_XTS_KEY_SIZE); - - /* - * The SCM call byte-swaps the 32-bit words of the key. So we have to - * do the same, in order for the final key be correct. - */ - 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, - cfg->data_unit_size); - memzero_explicit(&key, sizeof(key)); - return err; + return qti_ice_keyslot_program(&host->ice_data, cfg->crypto_key, + UFS_CRYPTO_KEY_SIZE_256, slot, + cfg->data_unit_size, cfg->crypto_cap_idx); } diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index 8208e3a3ef59..8efacc0d7888 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -7,6 +7,7 @@ #include #include +#include #define MAX_UFS_QCOM_HOSTS 1 #define MAX_U32 (~(u32)0) @@ -206,7 +207,7 @@ struct ufs_qcom_host { bool is_dev_ref_clk_enabled; struct ufs_hw_version hw_ver; #ifdef CONFIG_SCSI_UFS_CRYPTO - void __iomem *ice_mmio; + struct ice_mmio_data ice_data; #endif u32 dev_ref_clk_en_mask; From patchwork Mon Dec 6 22:57:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gaurav Kashyap \(QUIC\)" X-Patchwork-Id: 521130 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6546DC4332F for ; Mon, 6 Dec 2021 22:59:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376902AbhLFXCb (ORCPT ); Mon, 6 Dec 2021 18:02:31 -0500 Received: from alexa-out-sd-02.qualcomm.com ([199.106.114.39]:37432 "EHLO alexa-out-sd-02.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376698AbhLFXCa (ORCPT ); Mon, 6 Dec 2021 18:02:30 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1638831541; x=1670367541; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=ALRFuY7so6mPcA8kT5aKmUe7cZ+s4fYanplfvm5bsRs=; b=u/CmK6ZkkbWxxzKaLpHnv0TsbvgNyXumUhbuOwPnE97Y8aef/yPzO1Pk kgA9Mi3DU63zWwevsdlYRMWBzoGF0iSrmHVe5DdrDTxhp8nh/NDWExeko rIDoSK7NxyO4Mj18b9VLqs/YLvPd+4jCjoRkx5m/qAT7OLO+V4SZ5yf/F g=; Received: from unknown (HELO ironmsg01-sd.qualcomm.com) ([10.53.140.141]) by alexa-out-sd-02.qualcomm.com with ESMTP; 06 Dec 2021 14:59:01 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg01-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Dec 2021 14:59:01 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Mon, 6 Dec 2021 14:59:01 -0800 Received: from gabriel.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Mon, 6 Dec 2021 14:59:00 -0800 From: Gaurav Kashyap To: , CC: , , , , , , Gaurav Kashyap Subject: [PATCH 04/10] soc: qcom: add HWKM library for storage encryption Date: Mon, 6 Dec 2021 14:57:19 -0800 Message-ID: <20211206225725.77512-5-quic_gaurkash@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211206225725.77512-1-quic_gaurkash@quicinc.com> References: <20211206225725.77512-1-quic_gaurkash@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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 capabilities to be accessed from the linux kernel in the future. Signed-off-by: Gaurav Kashyap --- drivers/soc/qcom/Makefile | 2 +- drivers/soc/qcom/qti-ice-hwkm.c | 111 +++++++++++++++++++++++++++++ drivers/soc/qcom/qti-ice-regs.h | 119 ++++++++++++++++++++++++++++++++ include/linux/qti-ice-common.h | 1 + 4 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/qcom/qti-ice-hwkm.c diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 57840b19b7ee..e73fefb4f533 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -26,4 +26,4 @@ obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o 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_ICE_COMMON) += qti-ice-common.o 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..3be6b350cd88 --- /dev/null +++ b/drivers/soc/qcom/qti-ice-hwkm.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * HWKM ICE library for storage encryption. + * + * Copyright (c) 2021, Qualcomm Innovation Center. All rights reserved. + */ + +#include +#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 void qti_ice_hwkm_configure_ice_registers( + const struct ice_mmio_data *mmio) +{ + qti_ice_hwkm_writel(mmio->ice_hwkm_mmio, 0xffffffff, + QTI_HWKM_ICE_RG_BANK0_AC_BANKN_BBAC_0); + qti_ice_hwkm_writel(mmio->ice_hwkm_mmio, 0xffffffff, + QTI_HWKM_ICE_RG_BANK0_AC_BANKN_BBAC_1); + qti_ice_hwkm_writel(mmio->ice_hwkm_mmio, 0xffffffff, + QTI_HWKM_ICE_RG_BANK0_AC_BANKN_BBAC_2); + qti_ice_hwkm_writel(mmio->ice_hwkm_mmio, 0xffffffff, + QTI_HWKM_ICE_RG_BANK0_AC_BANKN_BBAC_3); + qti_ice_hwkm_writel(mmio->ice_hwkm_mmio, 0xffffffff, + QTI_HWKM_ICE_RG_BANK0_AC_BANKN_BBAC_4); +} + +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; + + /* + * 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. + */ + qti_ice_hwkm_configure_ice_registers(mmio); + + /* 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; +} + +/** + * qti_ice_hwkm_init() - Initialize ICE HWKM hardware + * @ice_mmio_data: contains ICE register mapping for i/o + * @version: version of hwkm hardware + * + * Perform HWKM initialization in the ICE slave by going + * through the slave initialization routine.The registers + * can vary slightly based on the version. + * + * Return: 0 on success; err on failure. + */ + +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_GPL(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 582b73fd60fc..256c6feb9072 100644 --- a/drivers/soc/qcom/qti-ice-regs.h +++ b/drivers/soc/qcom/qti-ice-regs.h @@ -137,9 +137,128 @@ 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 access control registers for Bank 0 */ +#define QTI_HWKM_ICE_RG_BANK0_AC_BANKN_BBAC_0 0x5000 +#define QTI_HWKM_ICE_RG_BANK0_AC_BANKN_BBAC_1 0x5004 +#define QTI_HWKM_ICE_RG_BANK0_AC_BANKN_BBAC_2 0x5008 +#define QTI_HWKM_ICE_RG_BANK0_AC_BANKN_BBAC_3 0x500C +#define QTI_HWKM_ICE_RG_BANK0_AC_BANKN_BBAC_4 0x5010 + +/* 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 5a7c6fa99dc1..51dfe3c12092 100644 --- a/include/linux/qti-ice-common.h +++ b/include/linux/qti-ice-common.h @@ -20,5 +20,6 @@ int qti_ice_keyslot_program(const struct ice_mmio_data *mmio, const u8 *key, unsigned int key_size, unsigned int slot, u8 data_unit_mask, int capid); int qti_ice_keyslot_evict(unsigned int slot); +int qti_ice_hwkm_init(const struct ice_mmio_data *mmio, int version); #endif /* _QTI_ICE_COMMON_H */ From patchwork Mon Dec 6 22:57:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gaurav Kashyap \(QUIC\)" X-Patchwork-Id: 521129 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A093CC43219 for ; Mon, 6 Dec 2021 22:59:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376998AbhLFXCq (ORCPT ); Mon, 6 Dec 2021 18:02:46 -0500 Received: from alexa-out-sd-02.qualcomm.com ([199.106.114.39]:34326 "EHLO alexa-out-sd-02.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1377028AbhLFXCg (ORCPT ); Mon, 6 Dec 2021 18:02:36 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1638831547; x=1670367547; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=3DbJocESiVT640e7qeul3nWqq5xIH+alIHva07yq8SU=; b=dzU9EX4+OuctoSqrvwEeRnlK0ARu/6R/VuuikmCNy500gZp6qFa9+vtW LmVOAGj86lQ8zs1PtziYXd+G7JguQBd9RZLayUx6C2eXqnjk5HlyComi5 0Cw0y3FF65Ie16tWxdBQRMMwwL+30EX8dTCQLijFYtCDmQZjXn380JiLL Y=; Received: from unknown (HELO ironmsg02-sd.qualcomm.com) ([10.53.140.142]) by alexa-out-sd-02.qualcomm.com with ESMTP; 06 Dec 2021 14:59:07 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg02-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Dec 2021 14:59:07 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Mon, 6 Dec 2021 14:59:07 -0800 Received: from gabriel.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Mon, 6 Dec 2021 14:59:06 -0800 From: Gaurav Kashyap To: , CC: , , , , , , Gaurav Kashyap Subject: [PATCH 06/10] soc: qcom: add wrapped key support for ICE Date: Mon, 6 Dec 2021 14:57:21 -0800 Message-ID: <20211206225725.77512-7-quic_gaurkash@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211206225725.77512-1-quic_gaurkash@quicinc.com> References: <20211206225725.77512-1-quic_gaurkash@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Add support for wrapped keys in ufs and common ICE library. Qualcomm's ICE solution uses a hardware block called Hardware Key Manager (HWKM) to handle wrapped keys. This patch adds the following changes to support this. 1. Link to HWKM library for initialization. 2. Most of the key management is done from Trustzone via scm calls. Added calls to this from the ICE library. 3. Added support for this framework in ufs qcom. 4. Added support for deriving SW secret as it cannot be done in linux kernel for wrapped keys. Signed-off-by: Gaurav Kashyap --- drivers/scsi/ufs/ufs-qcom-ice.c | 48 +++++++-- drivers/scsi/ufs/ufs-qcom.c | 1 + drivers/scsi/ufs/ufs-qcom.h | 7 +- drivers/soc/qcom/qti-ice-common.c | 158 +++++++++++++++++++++++++++--- include/linux/qti-ice-common.h | 11 ++- 5 files changed, 198 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c index 3826643bf537..c8305aab6714 100644 --- a/drivers/scsi/ufs/ufs-qcom-ice.c +++ b/drivers/scsi/ufs/ufs-qcom-ice.c @@ -43,6 +43,24 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *host) return err; } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice_hwkm"); + if (!res) { + dev_warn(dev, "ICE HWKM registers not found\n"); + host->ice_data.hw_wrapped_keys_supported = false; + goto init; + } + + host->ice_data.ice_hwkm_mmio = devm_ioremap_resource(dev, res); + if (IS_ERR(host->ice_data.ice_hwkm_mmio)) { + err = PTR_ERR(host->ice_data.ice_hwkm_mmio); + dev_err(dev, "Failed to map HWKM registers; err=%d\n", err); + return err; + } + host->ice_data.hw_wrapped_keys_supported = true; + +init: + hba->hw_wrapped_keys_supported = + host->ice_data.hw_wrapped_keys_supported; if (qti_ice_init(&host->ice_data)) goto disable; @@ -54,7 +72,6 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *host) return 0; } - int ufs_qcom_ice_enable(struct ufs_qcom_host *host) { if (!(host->hba->caps & UFSHCD_CAP_CRYPTO)) @@ -76,16 +93,17 @@ int ufs_qcom_ice_resume(struct ufs_qcom_host *host) * vendor-specific SCM calls for this; it doesn't support the standard way. */ int ufs_qcom_ice_program_key(struct ufs_hba *hba, - const union ufs_crypto_cfg_entry *cfg, int slot) + const struct blk_crypto_key *key, int slot, + u8 data_unit_size, int capid, bool evict) { union ufs_crypto_cap_entry cap; struct ufs_qcom_host *host = ufshcd_get_variant(hba); - if (!(cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE)) - return qti_ice_keyslot_evict(slot); + if (evict) + return qti_ice_keyslot_evict(&host->ice_data, slot); /* Only AES-256-XTS has been tested so far. */ - cap = hba->crypto_cap_array[cfg->crypto_cap_idx]; + cap = hba->crypto_cap_array[capid]; if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS || cap.key_size != UFS_CRYPTO_KEY_SIZE_256) { dev_err_ratelimited(hba->dev, @@ -94,7 +112,21 @@ int ufs_qcom_ice_program_key(struct ufs_hba *hba, return -EINVAL; } - return qti_ice_keyslot_program(&host->ice_data, cfg->crypto_key, - UFS_CRYPTO_KEY_SIZE_256, slot, - cfg->data_unit_size, cfg->crypto_cap_idx); + return qti_ice_keyslot_program(&host->ice_data, key, slot, + data_unit_size, capid); +} + +/* + * Derive a SW secret from the wrapped key to be used in fscrypt. The key + * is unwrapped in QTI and a SW key is then derived. + */ +int ufs_qcom_ice_derive_sw_secret(struct ufs_hba *hba, const u8 *wrapped_key, + unsigned int wrapped_key_size, + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]) +{ + struct ufs_qcom_host *host = ufshcd_get_variant(hba); + + return qti_ice_derive_sw_secret(&host->ice_data, + wrapped_key, wrapped_key_size, + sw_secret); } diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 9d9770f1db4f..9f85332fbe64 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1495,6 +1495,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_secret = ufs_qcom_ice_derive_sw_secret, }; /** diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index 8efacc0d7888..e7da3d1dc3c7 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -253,7 +253,12 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *host); int ufs_qcom_ice_enable(struct ufs_qcom_host *host); int ufs_qcom_ice_resume(struct ufs_qcom_host *host); int ufs_qcom_ice_program_key(struct ufs_hba *hba, - const union ufs_crypto_cfg_entry *cfg, int slot); + const struct blk_crypto_key *key, + int slot, u8 data_unit_size, int capid, + bool evict); +int ufs_qcom_ice_derive_sw_secret(struct ufs_hba *hba, const u8 *wrapped_key, + unsigned int wrapped_key_size, + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]); #else static inline int ufs_qcom_ice_init(struct ufs_qcom_host *host) { diff --git a/drivers/soc/qcom/qti-ice-common.c b/drivers/soc/qcom/qti-ice-common.c index 0c5b529201c5..76703afa4834 100644 --- a/drivers/soc/qcom/qti-ice-common.c +++ b/drivers/soc/qcom/qti-ice-common.c @@ -14,6 +14,23 @@ #define QTI_ICE_MAX_BIST_CHECK_COUNT 100 #define QTI_AES_256_XTS_KEY_RAW_SIZE 64 +/* + * ICE resets during power collapse and HWKM has to be + * reconfigured which can be kept track with this flag. + */ +static bool qti_hwkm_init_done; +static int hwkm_version; + +union crypto_cfg { + __le32 regval; + struct { + u8 dusize; + u8 capidx; + u8 reserved; + u8 cfge; + }; +}; + static bool qti_ice_supported(const struct ice_mmio_data *mmio) { u32 regval = qti_ice_readl(mmio->ice_mmio, QTI_ICE_REGS_VERSION); @@ -28,6 +45,11 @@ static bool qti_ice_supported(const struct ice_mmio_data *mmio) return false; } + if ((major >= 4) || ((major == 3) && (minor == 2) && (step >= 1))) + hwkm_version = 2; + else + hwkm_version = 1; + pr_info("Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", major, minor, step); @@ -131,6 +153,58 @@ int qti_ice_resume(const struct ice_mmio_data *mmio) } EXPORT_SYMBOL_GPL(qti_ice_resume); +static int qti_ice_program_wrapped_key(const struct ice_mmio_data *mmio, + const struct blk_crypto_key *crypto_key, + unsigned int slot, u8 data_unit_mask, + int capid) +{ + int err = 0; + union crypto_cfg cfg; + + /* + * HWKM slave in ICE should be initialized before the first + * time we perform ICE HWKM related operations. This is because + * ICE by default comes up in legacy mode where HWKM operations + * won't work. + */ + if (!qti_hwkm_init_done) { + err = qti_ice_hwkm_init(mmio, hwkm_version); + if (err) { + pr_err("%s: Error initializing hwkm, err = %d", + __func__, err); + return -EINVAL; + } + qti_hwkm_init_done = true; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.dusize = data_unit_mask; + cfg.capidx = capid; + cfg.cfge = 0x80; + + /* Make sure CFGE is cleared */ + qti_ice_writel(mmio->ice_mmio, 0x0, (QTI_ICE_LUT_KEYS_CRYPTOCFG_R_16 + + QTI_ICE_LUT_KEYS_CRYPTOCFG_OFFSET*slot)); + /* Memory barrier - to ensure write completion before next transaction */ + wmb(); + + /* Call trustzone to program the wrapped key using hwkm */ + err = qcom_scm_ice_set_key(slot, crypto_key->raw, crypto_key->size, + capid, data_unit_mask); + if (err) + pr_err("%s:SCM call Error: 0x%x slot %d\n", + __func__, err, slot); + + /* Make sure CFGE is enabled after programming the key */ + qti_ice_writel(mmio->ice_mmio, cfg.regval, + (QTI_ICE_LUT_KEYS_CRYPTOCFG_R_16 + + QTI_ICE_LUT_KEYS_CRYPTOCFG_OFFSET*slot)); + /* Memory barrier - to ensure write completion before next transaction */ + wmb(); + + return err; +} + /** * qti_ice_keyslot_program() - Program a key to an ICE slot * @ice_mmio_data: contains ICE register mapping for i/o @@ -151,7 +225,7 @@ EXPORT_SYMBOL_GPL(qti_ice_resume); * Return: 0 on success; err on failure. */ int qti_ice_keyslot_program(const struct ice_mmio_data *mmio, - const u8 *crypto_key, unsigned int crypto_key_size, + const struct blk_crypto_key *crypto_key, unsigned int slot, u8 data_unit_mask, int capid) { int err = 0; @@ -161,22 +235,28 @@ int qti_ice_keyslot_program(const struct ice_mmio_data *mmio, u32 words[QTI_AES_256_XTS_KEY_RAW_SIZE / sizeof(u32)]; } key; - memcpy(key.bytes, crypto_key, crypto_key_size); - /* - * The SCM call byte-swaps the 32-bit words of the key. So we have to - * do the same, in order for the final key be correct. - */ - for (i = 0; i < ARRAY_SIZE(key.words); i++) - __cpu_to_be32s(&key.words[i]); + if (crypto_key->crypto_cfg.key_type == BLK_CRYPTO_KEY_TYPE_HW_WRAPPED) { + if (!mmio->hw_wrapped_keys_supported) + return -EINVAL; + err = qti_ice_program_wrapped_key(mmio, crypto_key, slot, + data_unit_mask, capid); + } else { + memcpy(key.bytes, crypto_key->raw, crypto_key->size); + /* + * The SCM call byte-swaps the 32-bit words of the key. So we have to + * do the same, in order for the final key be correct. + */ + for (i = 0; i < ARRAY_SIZE(key.words); i++) + __cpu_to_be32s(&key.words[i]); - err = qcom_scm_ice_set_key(slot, key.bytes, - QTI_AES_256_XTS_KEY_RAW_SIZE, - capid, data_unit_mask); - if (err) - pr_err("%s:SCM call Error: 0x%x slot %d\n", - __func__, err, slot); + err = qcom_scm_ice_set_key(slot, key.bytes, + QTI_AES_256_XTS_KEY_RAW_SIZE, capid, data_unit_mask); + if (err) + pr_err("%s:SCM call Error: 0x%x slot %d\n", + __func__, err, slot); + memzero_explicit(&key, sizeof(key)); + } - memzero_explicit(&key, sizeof(key)); return err; } EXPORT_SYMBOL_GPL(qti_ice_keyslot_program); @@ -190,10 +270,56 @@ EXPORT_SYMBOL_GPL(qti_ice_keyslot_program); * * Return: 0 on success; err on failure. */ -int qti_ice_keyslot_evict(unsigned int slot) +int qti_ice_keyslot_evict(const struct ice_mmio_data *mmio, unsigned int slot) { + /* + * Ignore calls to evict key when wrapped keys are supported and + * hwkm init is not yet done. This is to avoid the clearing all slots + * call that comes from ufs during ufs reset. HWKM slave in ICE takes + * care of zeroing out the keytable on reset. + */ + if (mmio->hw_wrapped_keys_supported && !qti_hwkm_init_done) + return 0; return qcom_scm_ice_invalidate_key(slot); } EXPORT_SYMBOL_GPL(qti_ice_keyslot_evict); +/** + * qti_ice_derive_sw_secret() - Derive SW secret from wrapped key + * @wrapped_key: wrapped key from which secret should be derived + * @wrapped_key_size: size of the wrapped key + * @sw_secret: secret to be returned, which is atmost BLK_CRYPTO_SW_SECRET_SIZE + * + * Make a scm call into trustzone to derive a sw secret from the + * given wrapped key. + * + * Return: 0 on success; err on failure. + */ +int qti_ice_derive_sw_secret(const struct ice_mmio_data *mmio, + const u8 *wrapped_key, + unsigned int wrapped_key_size, + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]) +{ + int err = 0; + + /* + * HWKM slave in ICE should be initialized before the first + * time we perform ICE HWKM related operations. This is because + * ICE by default comes up in legacy mode where HWKM operations + * won't work. + */ + if (!qti_hwkm_init_done) { + err = qti_ice_hwkm_init(mmio, qti_hwkm_version); + if (err) { + pr_err("%s: Error initializing hwkm, err = %d", + __func__, err); + return -EINVAL; + } + qti_hwkm_init_done = true; + } + return qcom_scm_derive_sw_secret(wrapped_key, wrapped_key_size, + sw_secret, BLK_CRYPTO_SW_SECRET_SIZE); +} +EXPORT_SYMBOL_GPL(qti_ice_derive_sw_secret); + MODULE_LICENSE("GPL v2"); diff --git a/include/linux/qti-ice-common.h b/include/linux/qti-ice-common.h index 51dfe3c12092..e329afeba113 100644 --- a/include/linux/qti-ice-common.h +++ b/include/linux/qti-ice-common.h @@ -8,18 +8,25 @@ #include #include +#include struct ice_mmio_data { void __iomem *ice_mmio; + void __iomem *ice_hwkm_mmio; + bool hw_wrapped_keys_supported; }; int qti_ice_init(const struct ice_mmio_data *mmio); int qti_ice_enable(const struct ice_mmio_data *mmio); int qti_ice_resume(const struct ice_mmio_data *mmio); int qti_ice_keyslot_program(const struct ice_mmio_data *mmio, - const u8 *key, unsigned int key_size, + const struct blk_crypto_key *crypto_key, unsigned int slot, u8 data_unit_mask, int capid); -int qti_ice_keyslot_evict(unsigned int slot); +int qti_ice_keyslot_evict(const struct ice_mmio_data *mmio, unsigned int slot); int qti_ice_hwkm_init(const struct ice_mmio_data *mmio, int version); +int qti_ice_derive_sw_secret(const struct ice_mmio_data *mmio, + const u8 *wrapped_key, + unsigned int wrapped_key_size, + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]); #endif /* _QTI_ICE_COMMON_H */ From patchwork Mon Dec 6 22:57:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gaurav Kashyap \(QUIC\)" X-Patchwork-Id: 521128 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C11B0C41535 for ; Mon, 6 Dec 2021 22:59:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1359202AbhLFXCt (ORCPT ); Mon, 6 Dec 2021 18:02:49 -0500 Received: from alexa-out.qualcomm.com ([129.46.98.28]:16498 "EHLO alexa-out.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1377123AbhLFXCl (ORCPT ); Mon, 6 Dec 2021 18:02:41 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1638831552; x=1670367552; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=ECagi/BaTQQeNMjMZWtRvSI3lnAfi1QCeUU8K69Xtrc=; b=QVoeE1ap3nytNDbvoJ7JPdryF15qrlIBxmU/X64RlD1FTNKkusLCtPOj iDv49cQAzXwA52JjjmpYCTtZ4HZy4JYMpkkqE6qKswXV9Yk6fHQUMjkhT Dmsxj4t+EZXGvdkQ5EQlGMoYxu1P0z3JcltsuUXLNnR/erLPFwk5v9NaL s=; Received: from ironmsg08-lv.qualcomm.com ([10.47.202.152]) by alexa-out.qualcomm.com with ESMTP; 06 Dec 2021 14:59:11 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg08-lv.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Dec 2021 14:59:11 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Mon, 6 Dec 2021 14:59:10 -0800 Received: from gabriel.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Mon, 6 Dec 2021 14:59:10 -0800 From: Gaurav Kashyap To: , CC: , , , , , , Gaurav Kashyap Subject: [PATCH 08/10] scsi: ufs: add support for generate, import and prepare keys Date: Mon, 6 Dec 2021 14:57:23 -0800 Message-ID: <20211206225725.77512-9-quic_gaurkash@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211206225725.77512-1-quic_gaurkash@quicinc.com> References: <20211206225725.77512-1-quic_gaurkash@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This patch contains two changes in UFS for wrapped keys. 1. Implements the blk_crypto_profile ops for generate, import and prepare key apis. 2. Adds UFS vops for generate, import and prepare keys so that vendors can hooks to them. Signed-off-by: Gaurav Kashyap --- drivers/scsi/ufs/ufshcd-crypto.c | 50 ++++++++++++++++++++++++++++++-- drivers/scsi/ufs/ufshcd.h | 11 +++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd-crypto.c b/drivers/scsi/ufs/ufshcd-crypto.c index 9d68621a0eb4..2bea9b924f77 100644 --- a/drivers/scsi/ufs/ufshcd-crypto.c +++ b/drivers/scsi/ufs/ufshcd-crypto.c @@ -136,9 +136,9 @@ bool ufshcd_crypto_enable(struct ufs_hba *hba) } static int ufshcd_crypto_derive_sw_secret(struct blk_crypto_profile *profile, - const u8 *wrapped_key, - unsigned int wrapped_key_size, - u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]) + const u8 *wrapped_key, + unsigned int wrapped_key_size, + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]) { struct ufs_hba *hba = container_of(profile, struct ufs_hba, crypto_profile); @@ -146,6 +146,47 @@ static int ufshcd_crypto_derive_sw_secret(struct blk_crypto_profile *profile, if (hba->vops && hba->vops->derive_secret) return hba->vops->derive_secret(hba, wrapped_key, wrapped_key_size, sw_secret); + return 0; +} + +static int ufshcd_crypto_generate_key(struct blk_crypto_profile *profile, + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + struct ufs_hba *hba = + container_of(profile, struct ufs_hba, crypto_profile); + + if (hba->vops && hba->vops->generate_key) + return hba->vops->generate_key(longterm_wrapped_key); + + return -EOPNOTSUPP; +} + +static int ufshcd_crypto_prepare_key(struct blk_crypto_profile *profile, + const u8 *longterm_wrapped_key, + size_t longterm_wrapped_key_size, + u8 ephemerally_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + struct ufs_hba *hba = + container_of(profile, struct ufs_hba, crypto_profile); + + if (hba->vops && hba->vops->prepare_key) + return hba->vops->prepare_key(longterm_wrapped_key, + longterm_wrapped_key_size, ephemerally_wrapped_key); + + return -EOPNOTSUPP; +} + +static int ufshcd_crypto_import_key(struct blk_crypto_profile *profile, + const u8 *imported_key, + size_t imported_key_size, + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + struct ufs_hba *hba = + container_of(profile, struct ufs_hba, crypto_profile); + + if (hba->vops && hba->vops->import_key) + return hba->vops->import_key(imported_key, + imported_key_size, longterm_wrapped_key); return -EOPNOTSUPP; } @@ -154,6 +195,9 @@ 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/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 095c2d660aa7..88cd21dec0d9 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -321,6 +321,10 @@ struct ufs_pwr_mode_info { * @program_key: program or evict an inline encryption key * @event_notify: called to notify important events * @derive_secret: derive sw secret from wrapped inline encryption key + * @generate_key: generate a longterm wrapped key for inline encryption + * @prepare_key: prepare the longterm wrapped key for inline encryption + * by rewrapping with a ephemeral wrapping key. + * @import_key: import a raw key and return a longterm wrapped key. */ struct ufs_hba_variant_ops { const char *name; @@ -362,6 +366,13 @@ struct ufs_hba_variant_ops { int (*derive_secret)(struct ufs_hba *hba, const u8 *wrapped_key, unsigned int wrapped_key_size, u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]); + int (*generate_key)(u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); + int (*prepare_key)(const u8 *longterm_wrapped_key, + unsigned int longterm_wrapped_key_size, + u8 ephemerally_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); + int (*import_key)(const u8 *imported_key, + unsigned int imported_key_size, + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); }; /* clock gating state */ From patchwork Mon Dec 6 22:57:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gaurav Kashyap \(QUIC\)" X-Patchwork-Id: 521127 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AA999C4167E for ; Mon, 6 Dec 2021 22:59:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376290AbhLFXCw (ORCPT ); Mon, 6 Dec 2021 18:02:52 -0500 Received: from alexa-out-sd-02.qualcomm.com ([199.106.114.39]:15870 "EHLO alexa-out-sd-02.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1377162AbhLFXCo (ORCPT ); Mon, 6 Dec 2021 18:02:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1638831555; x=1670367555; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=NmElV7T+xzPa6AFGYUpxLexgr3R7EJAkax7bo6Hf2K0=; b=HSMzcP5U8wku5t0X37e2TEqc7X5MsGdXZQE/93HYImdzDH6SChTucqTx xi7ohUrsDDQO54NUNyxJllUgwtaRzSxUalCW5Sfy//Q7KZhX36cE2JUqW c/rOx7vhmE9biAKTl8ZPgvTKNpTIKG5Z83SGH+pPXPepDvPkwUVMlH8AM Q=; Received: from unknown (HELO ironmsg03-sd.qualcomm.com) ([10.53.140.143]) by alexa-out-sd-02.qualcomm.com with ESMTP; 06 Dec 2021 14:59:12 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg03-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Dec 2021 14:59:12 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Mon, 6 Dec 2021 14:59:12 -0800 Received: from gabriel.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Mon, 6 Dec 2021 14:59:11 -0800 From: Gaurav Kashyap To: , CC: , , , , , , Gaurav Kashyap Subject: [PATCH 09/10] soc: qcom: support for generate, import and prepare key Date: Mon, 6 Dec 2021 14:57:24 -0800 Message-ID: <20211206225725.77512-10-quic_gaurkash@quicinc.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211206225725.77512-1-quic_gaurkash@quicinc.com> References: <20211206225725.77512-1-quic_gaurkash@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Implements the vops for generate, prepare and import key apis and hooks it up the scm calls defined for them. Key management has to be done from Qualcomm Trustzone as only it can interface with HWKM. Signed-off-by: Gaurav Kashyap --- drivers/scsi/ufs/ufs-qcom-ice.c | 22 ++++++++ drivers/scsi/ufs/ufs-qcom.c | 3 ++ drivers/scsi/ufs/ufs-qcom.h | 12 +++++ drivers/soc/qcom/qti-ice-common.c | 89 ++++++++++++++++++++++++++++--- include/linux/qti-ice-common.h | 8 +++ 5 files changed, 128 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c index c8305aab6714..7f0485553d75 100644 --- a/drivers/scsi/ufs/ufs-qcom-ice.c +++ b/drivers/scsi/ufs/ufs-qcom-ice.c @@ -130,3 +130,25 @@ int ufs_qcom_ice_derive_sw_secret(struct ufs_hba *hba, const u8 *wrapped_key, wrapped_key, wrapped_key_size, sw_secret); } + +int ufs_qcom_ice_generate_key( + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + return qti_ice_generate_key(longterm_wrapped_key); +} + +int ufs_qcom_ice_prepare_key(const u8 *longterm_wrapped_key, + unsigned int longterm_wrapped_key_size, + u8 ephemerally_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + return qti_ice_prepare_key(longterm_wrapped_key, longterm_wrapped_key_size, + ephemerally_wrapped_key); +} + +int ufs_qcom_ice_import_key(const u8 *imported_key, + unsigned int imported_key_size, + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + return qti_ice_import_key(imported_key, imported_key_size, + longterm_wrapped_key); +} diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 9f85332fbe64..cbd472844065 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1496,6 +1496,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_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, }; /** diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index e7da3d1dc3c7..1f8ed9adb28f 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -259,6 +259,14 @@ int ufs_qcom_ice_program_key(struct ufs_hba *hba, int ufs_qcom_ice_derive_sw_secret(struct ufs_hba *hba, const u8 *wrapped_key, unsigned int wrapped_key_size, u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]); +int ufs_qcom_ice_generate_key( + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); +int ufs_qcom_ice_prepare_key(const u8 *longterm_wrapped_key, + unsigned int longterm_wrapped_key_size, + u8 ephemerally_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); +int ufs_qcom_ice_import_key(const u8 *imported_key, + unsigned int imported_key_size, + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); #else static inline int ufs_qcom_ice_init(struct ufs_qcom_host *host) { @@ -273,6 +281,10 @@ static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host) return 0; } #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 #endif /* !CONFIG_SCSI_UFS_CRYPTO */ #endif /* UFS_QCOM_H_ */ diff --git a/drivers/soc/qcom/qti-ice-common.c b/drivers/soc/qcom/qti-ice-common.c index 76703afa4834..cc035f1a1d42 100644 --- a/drivers/soc/qcom/qti-ice-common.c +++ b/drivers/soc/qcom/qti-ice-common.c @@ -13,13 +13,21 @@ #define QTI_ICE_MAX_BIST_CHECK_COUNT 100 #define QTI_AES_256_XTS_KEY_RAW_SIZE 64 +#define QTI_HWKM_WRAPPED_KEY_SIZE_V1 68 +#define QTI_HWKM_WRAPPED_KEY_SIZE_V2 100 /* * ICE resets during power collapse and HWKM has to be * reconfigured which can be kept track with this flag. */ static bool qti_hwkm_init_done; -static int hwkm_version; +static int qti_hwkm_version; + +/* + * Size of the wrapped key returned by HWKM, which varies with + * hwkm version + */ +static unsigned int qti_hwkm_wrapped_key_size; union crypto_cfg { __le32 regval; @@ -45,10 +53,13 @@ static bool qti_ice_supported(const struct ice_mmio_data *mmio) return false; } - if ((major >= 4) || ((major == 3) && (minor == 2) && (step >= 1))) - hwkm_version = 2; - else - hwkm_version = 1; + if ((major >= 4) || ((major == 3) && (minor == 2) && (step >= 1))) { + qti_hwkm_wrapped_key_size = QTI_HWKM_WRAPPED_KEY_SIZE_V2; + qti_hwkm_version = 2; + } else { + qti_hwkm_wrapped_key_size = QTI_HWKM_WRAPPED_KEY_SIZE_V1; + qti_hwkm_version = 1; + } pr_info("Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", major, minor, step); @@ -168,7 +179,7 @@ static int qti_ice_program_wrapped_key(const struct ice_mmio_data *mmio, * won't work. */ if (!qti_hwkm_init_done) { - err = qti_ice_hwkm_init(mmio, hwkm_version); + err = qti_ice_hwkm_init(mmio, qti_hwkm_version); if (err) { pr_err("%s: Error initializing hwkm, err = %d", __func__, err); @@ -322,4 +333,70 @@ int qti_ice_derive_sw_secret(const struct ice_mmio_data *mmio, } EXPORT_SYMBOL_GPL(qti_ice_derive_sw_secret); +/** + * qti_ice_generate_key() - Generate a wrapped key for inline encryption + * @longterm_wrapped_key: wrapped key that is generated, which is at most + * BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE in size. + * + * Make a scm call into trustzone to generate a wrapped key for storage + * encryption using hwkm. + * + * Return: 0 on success; err on failure. + */ +int qti_ice_generate_key( + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + return qcom_scm_generate_ice_key(longterm_wrapped_key, + qti_hwkm_wrapped_key_size); +} +EXPORT_SYMBOL_GPL(qti_ice_generate_key); + +/** + * qti_ice_prepare_key() - Prepare a longterm wrapped key for inline encryption + * @longterm_wrapped_key: wrapped key that is generated, + * @longterm_wrapped_key_size: size of the longterm wrapped_key + * @ephemerally_wrapped_key: wrapped key returned which has been wrapped with + * a per-boot ephemeral key, size of which is at most + * BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE + * + * Make a scm call into trustzone to prepare a wrapped key for storage + * encryption by rewrapping the longterm wrapped key with a per boot ephemeral + * key using hwkm. + * + * Return: 0 on success; err on failure. + */ +int qti_ice_prepare_key(const u8 *longterm_wrapped_key, + unsigned int longterm_wrapped_key_size, + u8 ephemerally_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + return qcom_scm_prepare_ice_key(longterm_wrapped_key, + longterm_wrapped_key_size, + ephemerally_wrapped_key, + qti_hwkm_wrapped_key_size); +} +EXPORT_SYMBOL_GPL(qti_ice_prepare_key); + +/** + * qti_ice_import_key() - Importa raw key for inline encryption + * @imported_key: raw key that has to be imported + * @imported_key_size: size of the imported key + * @longterm_wrapped_key: longterm wrapped key returned which has been wrapped + * after imporint the raw key using hwkm. + * + * Make a scm call into trustzone to import a raw key for storage encryption + * and generating a longterm wrapped key using hwkm. + * + * Return: 0 on success; err on failure. + */ +int qti_ice_import_key(const u8 *imported_key, + unsigned int imported_key_size, + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + return qcom_scm_import_ice_key(imported_key, + imported_key_size, + longterm_wrapped_key, + qti_hwkm_wrapped_key_size); +} +EXPORT_SYMBOL_GPL(qti_ice_import_key); + MODULE_LICENSE("GPL v2"); diff --git a/include/linux/qti-ice-common.h b/include/linux/qti-ice-common.h index e329afeba113..cae5275ee1d9 100644 --- a/include/linux/qti-ice-common.h +++ b/include/linux/qti-ice-common.h @@ -28,5 +28,13 @@ int qti_ice_derive_sw_secret(const struct ice_mmio_data *mmio, const u8 *wrapped_key, unsigned int wrapped_key_size, u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]); +int qti_ice_generate_key( + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); +int qti_ice_prepare_key(const u8 *longterm_wrapped_key, + unsigned int longterm_wrapped_key_size, + u8 ephemerally_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); +int qti_ice_import_key(const u8 *imported_key, + unsigned int imported__key_size, + u8 longterm_wrapped_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); #endif /* _QTI_ICE_COMMON_H */