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: 521008 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 C81F0C433F5 for ; Mon, 6 Dec 2021 22:58:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376760AbhLFXC1 (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-arm-msm@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:18 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: 521007 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 9899CC433FE for ; Mon, 6 Dec 2021 22:59:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376865AbhLFXC3 (ORCPT ); Mon, 6 Dec 2021 18:02:29 -0500 Received: from alexa-out-sd-01.qualcomm.com ([199.106.114.38]:25266 "EHLO alexa-out-sd-01.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376698AbhLFXC3 (ORCPT ); Mon, 6 Dec 2021 18:02:29 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1638831540; x=1670367540; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=ZtHeV/8nzFawIG2bxZRyAsVXm2z5YxzeubDnFvOQvm4=; b=YFxG1w9u3JRwd5X7fSBadRxnhWpcliA/nG58Dnle3GfdPdWvRxuNjz8n DS8+yoNvy/oH6k9BCXdWILO76tHZURWm/CIqZY6p/4Offd/0+Rc6ykPDT POJ+Ic+jmzmmgYos1EpzCqIQHvcXqdZP0CzSt7889h04Sle3xjzMVQuFG 4=; Received: from unknown (HELO ironmsg02-sd.qualcomm.com) ([10.53.140.142]) by alexa-out-sd-01.qualcomm.com with ESMTP; 06 Dec 2021 14:59:00 -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:58:59 -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:59 -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:58 -0800 From: Gaurav Kashyap To: , CC: , , , , , , Gaurav Kashyap Subject: [PATCH 03/10] qcom_scm: scm call for deriving a software secret Date: Mon, 6 Dec 2021 14:57:18 -0800 Message-ID: <20211206225725.77512-4-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-arm-msm@vger.kernel.org Storage encryption requires fscrypt deriving a sw secret from the keys inserted into the linux keyring. For non-wrapped keys, this can be directly done as keys are in the clear. However, when keys are hardware wrapped, it can be unwrapped by HWKM which is accessible only from Qualcomm Trustzone. Hence, it also makes sense that the software secret is also derived there and returned to the linux kernel for wrapped keys. This can be invoked by using the crypto profile APIs provided by the block layer. Signed-off-by: Gaurav Kashyap --- drivers/firmware/qcom_scm.c | 73 +++++++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.h | 1 + include/linux/qcom_scm.h | 6 +++ 3 files changed, 80 insertions(+) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 2ee97bab7440..4a7703846788 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -1062,6 +1062,79 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, } EXPORT_SYMBOL(qcom_scm_ice_set_key); +/** + * qcom_scm_derive_sw_secret() - Derive SW secret from wrapped encryption key + * @wrapped_key: the wrapped key used for inline encryption + * @wrapped_key_size: size of the wrapped key + * @sw_secret: the secret to be derived which is at most the secret size + * @secret_size: maximum size of the secret that is derived + * + * Derive a SW secret to be used for inline encryption using Qualcomm ICE. + * + * For wrapped keys, the key needs to be unwrapped, in order to derive a + * SW secret, which can be done only by the secure EE. So, it makes sense + * for the secure EE to derive the sw secret and return to the kernel when + * wrapped keys are used. + * + * For more information on sw secret, please refer to "Hardware-wrapped keys" + * section of Documentation/block/inline-encryption.rst. + * + * Return: 0 on success; -errno on failure. + */ +int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size, + u8 *sw_secret, u32 secret_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_DERIVE_SW_SECRET, + .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO, + QCOM_SCM_VAL, QCOM_SCM_RW, + QCOM_SCM_VAL), + .args[1] = wrapped_key_size, + .args[3] = secret_size, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + void *keybuf, *secretbuf; + dma_addr_t key_phys, secret_phys; + int ret; + + /* + * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly + * get a physical address, while guaranteeing that we can zeroize the + * key material later using memzero_explicit(). + * + */ + keybuf = dma_alloc_coherent(__scm->dev, wrapped_key_size, &key_phys, + GFP_KERNEL); + if (!keybuf) + return -ENOMEM; + secretbuf = dma_alloc_coherent(__scm->dev, secret_size, &secret_phys, + GFP_KERNEL); + if (!secretbuf) { + ret = -ENOMEM; + goto bail_keybuf; + } + + memcpy(keybuf, wrapped_key, wrapped_key_size); + desc.args[0] = key_phys; + desc.args[2] = secret_phys; + + ret = qcom_scm_call(__scm->dev, &desc, NULL); + if (!ret) + memcpy(sw_secret, secretbuf, secret_size); + + memzero_explicit(secretbuf, secret_size); + dma_free_coherent(__scm->dev, secret_size, secretbuf, secret_phys); + +bail_keybuf: + memzero_explicit(keybuf, wrapped_key_size); + dma_free_coherent(__scm->dev, wrapped_key_size, keybuf, key_phys); + + return ret; +} +EXPORT_SYMBOL(qcom_scm_derive_sw_secret); + /** * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. * diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index d92156ceb3ac..08bb2a4c80db 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -110,6 +110,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, #define QCOM_SCM_SVC_ES 0x10 /* Enterprise Security */ #define QCOM_SCM_ES_INVALIDATE_ICE_KEY 0x03 #define QCOM_SCM_ES_CONFIG_SET_ICE_KEY 0x04 +#define QCOM_SCM_ES_DERIVE_SW_SECRET 0x07 #define QCOM_SCM_SVC_HDCP 0x11 #define QCOM_SCM_HDCP_INVOKE 0x01 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index c0475d1c9885..ccd764bdc357 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -103,6 +103,9 @@ extern int qcom_scm_ice_invalidate_key(u32 index); extern int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, enum qcom_scm_ice_cipher cipher, u32 data_unit_size); +extern int qcom_scm_derive_sw_secret(const u8 *wrapped_key, + u32 wrapped_key_size, u8 *sw_secret, + u32 secret_size); extern bool qcom_scm_hdcp_available(void); extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, @@ -169,6 +172,9 @@ static inline int qcom_scm_ice_invalidate_key(u32 index) { return -ENODEV; } static inline 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 -ENODEV; } +static inline int qcom_scm_derive_sw_secret(const u8 *wrapped_key, + u32 wrapped_key_size, u8 *sw_secret, + u32 secret_size) { return -ENODEV; } static inline bool qcom_scm_hdcp_available(void) { return false; } static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, From patchwork Mon Dec 6 22:57:20 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: 521006 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 75670C433F5 for ; Mon, 6 Dec 2021 22:59:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376975AbhLFXCf (ORCPT ); Mon, 6 Dec 2021 18:02:35 -0500 Received: from alexa-out.qualcomm.com ([129.46.98.28]:36329 "EHLO alexa-out.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376873AbhLFXCc (ORCPT ); Mon, 6 Dec 2021 18:02:32 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1638831544; x=1670367544; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=9qedNGE1JEVmN4kcgOxpqxc9N60VuBMS8Us4NYfi29c=; b=C4zFofd3AowluFztbb18k3W36LPYpFma5cnGx6TgCP7FpTBsTyS9yVlV GvCJVSbX4+bgEIPZjbwyDYSL6NsY5vGhRKFm75G0BfEB8dKt5Iezl7NXA Qj7O1kHbAWaQu52v4zY+QqIopjCrhiAXWiAahhmZRTIW9yhm3K+/CxYP1 Q=; Received: from ironmsg-lv-alpha.qualcomm.com ([10.47.202.13]) by alexa-out.qualcomm.com with ESMTP; 06 Dec 2021 14:59:03 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg-lv-alpha.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Dec 2021 14:59:03 -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:02 -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:02 -0800 From: Gaurav Kashyap To: , CC: , , , , , , Gaurav Kashyap Subject: [PATCH 05/10] scsi: ufs: prepare to support wrapped keys Date: Mon, 6 Dec 2021 14:57:20 -0800 Message-ID: <20211206225725.77512-6-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-arm-msm@vger.kernel.org Adds support in ufshcd-core for wrapped keys. 1. Change program key vop to support wrapped key sizes by using blk_crypto_key directly instead of using ufs_crypto_cfg which is not suitable for wrapped keys. 2. Add derive_sw_secret vop and derive_sw_secret crypto_profile op. Signed-off-by: Gaurav Kashyap --- drivers/scsi/ufs/ufshcd-crypto.c | 52 +++++++++++++++++++++++++------- drivers/scsi/ufs/ufshcd.h | 9 +++++- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd-crypto.c b/drivers/scsi/ufs/ufshcd-crypto.c index 0ed82741f981..9d68621a0eb4 100644 --- a/drivers/scsi/ufs/ufshcd-crypto.c +++ b/drivers/scsi/ufs/ufshcd-crypto.c @@ -18,16 +18,23 @@ static const struct ufs_crypto_alg_entry { }; static int ufshcd_program_key(struct ufs_hba *hba, + const struct blk_crypto_key *key, const union ufs_crypto_cfg_entry *cfg, int slot) { int i; u32 slot_offset = hba->crypto_cfg_register + slot * sizeof(*cfg); int err = 0; + bool evict = false; ufshcd_hold(hba, false); if (hba->vops && hba->vops->program_key) { - err = hba->vops->program_key(hba, cfg, slot); + if (!(cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE)) + evict = true; + err = hba->vops->program_key(hba, key, slot, + cfg->data_unit_size, + cfg->crypto_cap_idx, + evict); goto out; } @@ -80,16 +87,18 @@ static int ufshcd_crypto_keyslot_program(struct blk_crypto_profile *profile, cfg.crypto_cap_idx = cap_idx; cfg.config_enable = UFS_CRYPTO_CONFIGURATION_ENABLE; - if (ccap_array[cap_idx].algorithm_id == UFS_CRYPTO_ALG_AES_XTS) { - /* In XTS mode, the blk_crypto_key's size is already doubled */ - memcpy(cfg.crypto_key, key->raw, key->size/2); - memcpy(cfg.crypto_key + UFS_CRYPTO_KEY_MAX_SIZE/2, - key->raw + key->size/2, key->size/2); - } else { - memcpy(cfg.crypto_key, key->raw, key->size); + if (key->crypto_cfg.key_type != BLK_CRYPTO_KEY_TYPE_HW_WRAPPED) { + if (ccap_array[cap_idx].algorithm_id == UFS_CRYPTO_ALG_AES_XTS) { + /* In XTS mode, the blk_crypto_key's size is already doubled */ + memcpy(cfg.crypto_key, key->raw, key->size/2); + memcpy(cfg.crypto_key + UFS_CRYPTO_KEY_MAX_SIZE/2, + key->raw + key->size/2, key->size/2); + } else { + memcpy(cfg.crypto_key, key->raw, key->size); + } } - err = ufshcd_program_key(hba, &cfg, slot); + err = ufshcd_program_key(hba, key, &cfg, slot); memzero_explicit(&cfg, sizeof(cfg)); return err; @@ -103,7 +112,7 @@ static int ufshcd_clear_keyslot(struct ufs_hba *hba, int slot) */ union ufs_crypto_cfg_entry cfg = {}; - return ufshcd_program_key(hba, &cfg, slot); + return ufshcd_program_key(hba, NULL, &cfg, slot); } static int ufshcd_crypto_keyslot_evict(struct blk_crypto_profile *profile, @@ -126,9 +135,25 @@ bool ufshcd_crypto_enable(struct ufs_hba *hba) return true; } +static int ufshcd_crypto_derive_sw_secret(struct blk_crypto_profile *profile, + const u8 *wrapped_key, + 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); + + if (hba->vops && hba->vops->derive_secret) + return hba->vops->derive_secret(hba, wrapped_key, + wrapped_key_size, sw_secret); + + return -EOPNOTSUPP; +} + static const struct blk_crypto_ll_ops ufshcd_crypto_ops = { .keyslot_program = ufshcd_crypto_keyslot_program, .keyslot_evict = ufshcd_crypto_keyslot_evict, + .derive_sw_secret = ufshcd_crypto_derive_sw_secret, }; static enum blk_crypto_mode_num @@ -190,7 +215,12 @@ int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba) hba->crypto_profile.ll_ops = ufshcd_crypto_ops; /* UFS only supports 8 bytes for any DUN */ hba->crypto_profile.max_dun_bytes_supported = 8; - hba->crypto_profile.key_types_supported = BLK_CRYPTO_KEY_TYPE_STANDARD; + if (hba->hw_wrapped_keys_supported) + hba->crypto_profile.key_types_supported = + BLK_CRYPTO_KEY_TYPE_HW_WRAPPED; + else + hba->crypto_profile.key_types_supported = + BLK_CRYPTO_KEY_TYPE_STANDARD; hba->crypto_profile.dev = hba->dev; /* diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index df5439b12208..095c2d660aa7 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -320,6 +320,7 @@ struct ufs_pwr_mode_info { * @device_reset: called to issue a reset pulse on the UFS device * @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 */ struct ufs_hba_variant_ops { const char *name; @@ -353,9 +354,14 @@ struct ufs_hba_variant_ops { struct devfreq_dev_profile *profile, void *data); int (*program_key)(struct ufs_hba *hba, - const union ufs_crypto_cfg_entry *cfg, int slot); + const struct blk_crypto_key *crypto_key, + int slot, u8 data_unit_size, int capid, + bool evict); void (*event_notify)(struct ufs_hba *hba, enum ufs_event_type evt, void *data); + int (*derive_secret)(struct ufs_hba *hba, const u8 *wrapped_key, + unsigned int wrapped_key_size, + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]); }; /* clock gating state */ @@ -906,6 +912,7 @@ struct ufs_hba { union ufs_crypto_cap_entry *crypto_cap_array; u32 crypto_cfg_register; struct blk_crypto_profile crypto_profile; + bool hw_wrapped_keys_supported; #endif #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_root; From patchwork Mon Dec 6 22:57:22 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: 521005 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 2AE28C433F5 for ; Mon, 6 Dec 2021 22:59:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353697AbhLFXCs (ORCPT ); Mon, 6 Dec 2021 18:02:48 -0500 Received: from alexa-out-sd-01.qualcomm.com ([199.106.114.38]:25283 "EHLO alexa-out-sd-01.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1377040AbhLFXCj (ORCPT ); Mon, 6 Dec 2021 18:02:39 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1638831550; x=1670367550; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=9pDqBy7b4J82ylZCzc4TAkcjhQdpn6D73KXKK36EV68=; b=EHdJQK49Bgp/TgU+5c2ZXnDJgWT6rV+TAZgk5A5cBacrv3deJZa5+yHk jtujRv2EmlFhWAKnqLYgs03Fx61Rb7k7zy6veuosoUxdwMXrNjJaWGT0b sHXOplE0atNudDKW2TzhvxyLSVlGeNo6+UotJ6VueHVJXYpx4V0fIQQYs M=; Received: from unknown (HELO ironmsg05-sd.qualcomm.com) ([10.53.140.145]) by alexa-out-sd-01.qualcomm.com with ESMTP; 06 Dec 2021 14:59:09 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg05-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Dec 2021 14:59:09 -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:09 -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:08 -0800 From: Gaurav Kashyap To: , CC: , , , , , , Gaurav Kashyap Subject: [PATCH 07/10] qcom_scm: scm call for create, prepare and import keys Date: Mon, 6 Dec 2021 14:57:22 -0800 Message-ID: <20211206225725.77512-8-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-arm-msm@vger.kernel.org Storage encryption has two IOCTLs for creating, importing and preparing keys for encryption. For wrapped keys, these IOCTLs need to interface with the secure environment, which require these SCM calls. generate_key: This is used to generate and return a longterm wrapped key. Trustzone achieves this by generating a key and then wrapping it using hwkm, returning a wrapped keyblob. import_key: The functionality is similar to generate, but here, a raw key is imported into hwkm and a longterm wrapped keyblob is returned. prepare_key: The longterm wrapped key from import or generate is made further secure by rewrapping it with a per-boot ephemeral wrapped key before installing it to the linux kernel for programming to ICE. Signed-off-by: Gaurav Kashyap --- drivers/firmware/qcom_scm.c | 213 ++++++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.h | 3 + include/linux/qcom_scm.h | 24 +++- 3 files changed, 239 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 4a7703846788..cca5c1ac5666 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -1135,6 +1135,219 @@ int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size, } EXPORT_SYMBOL(qcom_scm_derive_sw_secret); +/** + * qcom_scm_generate_ice_key() - Generate a wrapped key for encryption. + * @longterm_wrapped_key: the wrapped key returned after key generation + * @longterm_wrapped_key_size: size of the wrapped key to be returned. + * + * Qualcomm wrapped keys need to be generated in a trusted environment. + * A generate key IOCTL call is used to achieve this. These are longterm + * in nature as they need to be generated and wrapped only once per + * requirement. + * + * This SCM calls adds support for the generate key IOCTL to interface + * with the secure environment to generate and return a wrapped key.. + * + * Return: 0 on success; -errno on failure. + */ +int qcom_scm_generate_ice_key(u8 *longterm_wrapped_key, + u32 longterm_wrapped_key_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_GENERATE_ICE_KEY, + .arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, + QCOM_SCM_VAL), + .args[1] = longterm_wrapped_key_size, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + void *longterm_wrapped_keybuf; + dma_addr_t longterm_wrapped_key_phys; + int ret; + + /* + * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly + * get a physical address, while guaranteeing that we can zeroize the + * key material later using memzero_explicit(). + * + */ + longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev, + longterm_wrapped_key_size, + &longterm_wrapped_key_phys, GFP_KERNEL); + if (!longterm_wrapped_keybuf) + return -ENOMEM; + + desc.args[0] = longterm_wrapped_key_phys; + + ret = qcom_scm_call(__scm->dev, &desc, NULL); + memcpy(longterm_wrapped_key, longterm_wrapped_keybuf, + longterm_wrapped_key_size); + + memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size); + dma_free_coherent(__scm->dev, longterm_wrapped_key_size, + longterm_wrapped_keybuf, longterm_wrapped_key_phys); + + return ret; +} +EXPORT_SYMBOL(qcom_scm_generate_ice_key); + +/** + * qcom_scm_prepare_ice_key() - Get per boot ephemeral wrapped key + * @longterm_wrapped_key: the wrapped key + * @longterm_wrapped_key_size: size of the wrapped key + * @ephemeral_wrapped_key: ephemeral wrapped key to be returned + * @ephemeral_wrapped_key_size: size of the ephemeral wrapped key + * + * Qualcomm wrapped keys (longterm keys) are rewrapped with a per-boot + * ephemeral key for added protection. These are ephemeral in nature as + * they are valid only for that boot. A create key IOCTL is used to + * achieve this. These are the keys that are installed into the kernel + * to be then unwrapped and programmed into ICE. + * + * This SCM call adds support for the create key IOCTL to interface + * with the secure environment to rewrap the wrapped key with an + * ephemeral wrapping key. + * + * Return: 0 on success; -errno on failure. + */ +int qcom_scm_prepare_ice_key(const u8 *longterm_wrapped_key, + u32 longterm_wrapped_key_size, + u8 *ephemeral_wrapped_key, + u32 ephemeral_wrapped_key_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_PREPARE_ICE_KEY, + .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO, + QCOM_SCM_VAL, QCOM_SCM_RW, + QCOM_SCM_VAL), + .args[1] = longterm_wrapped_key_size, + .args[3] = ephemeral_wrapped_key_size, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + void *longterm_wrapped_keybuf, *ephemeral_wrapped_keybuf; + dma_addr_t longterm_wrapped_key_phys, ephemeral_wrapped_key_phys; + int ret; + + /* + * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly + * get a physical address, while guaranteeing that we can zeroize the + * key material later using memzero_explicit(). + * + */ + longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev, + longterm_wrapped_key_size, + &longterm_wrapped_key_phys, GFP_KERNEL); + if (!longterm_wrapped_keybuf) + return -ENOMEM; + ephemeral_wrapped_keybuf = dma_alloc_coherent(__scm->dev, + ephemeral_wrapped_key_size, + &ephemeral_wrapped_key_phys, GFP_KERNEL); + if (!ephemeral_wrapped_keybuf) { + ret = -ENOMEM; + goto bail_keybuf; + } + + memcpy(longterm_wrapped_keybuf, longterm_wrapped_key, + longterm_wrapped_key_size); + desc.args[0] = longterm_wrapped_key_phys; + desc.args[2] = ephemeral_wrapped_key_phys; + + ret = qcom_scm_call(__scm->dev, &desc, NULL); + if (!ret) + memcpy(ephemeral_wrapped_key, ephemeral_wrapped_keybuf, + ephemeral_wrapped_key_size); + + memzero_explicit(ephemeral_wrapped_keybuf, ephemeral_wrapped_key_size); + dma_free_coherent(__scm->dev, ephemeral_wrapped_key_size, + ephemeral_wrapped_keybuf, + ephemeral_wrapped_key_phys); + +bail_keybuf: + memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size); + dma_free_coherent(__scm->dev, longterm_wrapped_key_size, + longterm_wrapped_keybuf, longterm_wrapped_key_phys); + + return ret; +} +EXPORT_SYMBOL(qcom_scm_prepare_ice_key); + +/** + * qcom_scm_import_ice_key() - Import a wrapped key for encryption + * @imported_key: the raw key that is imported + * @imported_key_size: size of the key to be imported + * @longterm_wrapped_key: the wrapped key to be returned + * @longterm_wrapped_key_size: size of the wrapped key + * + * Conceptually, this is very similar to generate, the difference being, + * here we want to import a raw key and return a longterm wrapped key + * from it. THe same create key IOCTL is used to achieve this. + * + * This SCM call adds support for the create key IOCTL to interface with + * the secure environment to import a raw key and generate a longterm + * wrapped key. + * + * Return: 0 on success; -errno on failure. + */ +int qcom_scm_import_ice_key(const u8 *imported_key, u32 imported_key_size, + u8 *longterm_wrapped_key, + u32 longterm_wrapped_key_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_IMPORT_ICE_KEY, + .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RO, + QCOM_SCM_VAL, QCOM_SCM_RW, + QCOM_SCM_VAL), + .args[1] = imported_key_size, + .args[3] = longterm_wrapped_key_size, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + void *imported_keybuf, *longterm_wrapped_keybuf; + dma_addr_t imported_key_phys, longterm_wrapped_key_phys; + int ret; + /* + * Like qcom_scm_ice_set_key(), we use dma_alloc_coherent() to properly + * get a physical address, while guaranteeing that we can zeroize the + * key material later using memzero_explicit(). + * + */ + imported_keybuf = dma_alloc_coherent(__scm->dev, imported_key_size, + &imported_key_phys, GFP_KERNEL); + if (!imported_keybuf) + return -ENOMEM; + longterm_wrapped_keybuf = dma_alloc_coherent(__scm->dev, + longterm_wrapped_key_size, + &longterm_wrapped_key_phys, GFP_KERNEL); + if (!longterm_wrapped_keybuf) { + ret = -ENOMEM; + goto bail_keybuf; + } + + memcpy(imported_keybuf, imported_key, imported_key_size); + desc.args[0] = imported_key_phys; + desc.args[2] = longterm_wrapped_key_phys; + + ret = qcom_scm_call(__scm->dev, &desc, NULL); + if (!ret) + memcpy(longterm_wrapped_key, longterm_wrapped_keybuf, + longterm_wrapped_key_size); + + memzero_explicit(longterm_wrapped_keybuf, longterm_wrapped_key_size); + dma_free_coherent(__scm->dev, longterm_wrapped_key_size, + longterm_wrapped_keybuf, longterm_wrapped_key_phys); +bail_keybuf: + memzero_explicit(imported_keybuf, imported_key_size); + dma_free_coherent(__scm->dev, imported_key_size, imported_keybuf, + imported_key_phys); + + return ret; +} +EXPORT_SYMBOL(qcom_scm_import_ice_key); + /** * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. * diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 08bb2a4c80db..efd0ede1fb37 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -111,6 +111,9 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, #define QCOM_SCM_ES_INVALIDATE_ICE_KEY 0x03 #define QCOM_SCM_ES_CONFIG_SET_ICE_KEY 0x04 #define QCOM_SCM_ES_DERIVE_SW_SECRET 0x07 +#define QCOM_SCM_ES_GENERATE_ICE_KEY 0x08 +#define QCOM_SCM_ES_PREPARE_ICE_KEY 0x09 +#define QCOM_SCM_ES_IMPORT_ICE_KEY 0xA #define QCOM_SCM_SVC_HDCP 0x11 #define QCOM_SCM_HDCP_INVOKE 0x01 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index ccd764bdc357..865e4b4392a1 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -106,6 +106,16 @@ extern int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, extern int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size, u8 *sw_secret, u32 secret_size); +extern int qcom_scm_generate_ice_key(u8 *longterm_wrapped_key, + u32 longterm_wrapped_key_size); +extern int qcom_scm_prepare_ice_key(const u8 *longterm_wrapped_key, + u32 longterm_wrapped_key_size, + u8 *ephemeral_wrapped_key, + u32 ephemeral_wrapped_key_size); +extern int qcom_scm_import_ice_key(const u8 *imported_key, + u32 imported_key_size, + u8 *longterm_wrapped_key, + u32 longterm_wrapped_key_size); extern bool qcom_scm_hdcp_available(void); extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, @@ -175,7 +185,19 @@ static inline int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size, static inline int qcom_scm_derive_sw_secret(const u8 *wrapped_key, u32 wrapped_key_size, u8 *sw_secret, u32 secret_size) { return -ENODEV; } - +static inline int qcom_scm_generate_ice_key(u8 *longterm_wrapped_key, + u32 longterm_wrapped_key_size) + { return -ENODEV; } +static inline int qcom_scm_prepare_ice_key(const u8 *longterm_wrapped_key, + u32 longterm_wrapped_key_size, + u8 *ephemeral_wrapped_key, + u32 ephemeral_wrapped_key_size) + { return -ENODEV; } +static inline int qcom_scm_import_ice_key(const u8 *imported_key, + u32 imported_key_size, + u8 *longterm_wrapped_key, + u32 longterm_wrapped_key_size) + { return -ENODEV; } static inline bool qcom_scm_hdcp_available(void) { return false; } static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { return -ENODEV; } From patchwork Mon Dec 6 22:57:25 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: 521004 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 E1516C4321E for ; Mon, 6 Dec 2021 22:59:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376873AbhLFXCu (ORCPT ); Mon, 6 Dec 2021 18:02:50 -0500 Received: from alexa-out-sd-01.qualcomm.com ([199.106.114.38]:25287 "EHLO alexa-out-sd-01.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376929AbhLFXCo (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=Ue4j4uhm1swKWHsP5swU+lpTqR0o0aLaH/vHm0ED9Xc=; b=ad6rULnG6q02l8dIRnJ7OwVqPpCyFrwDlqOQvwGawN6eW1em7u2j1Enf 1RT8POt1x87ra9/twRa96J1mFqHzsXqsAF7/CyTvrTw6Ui7/ZKpW1n9xJ U1gpItjSvEdYbclYsqutrKsxEvOCu/bv7atHNO50w18W09sLzn7yfFiF9 o=; Received: from unknown (HELO ironmsg05-sd.qualcomm.com) ([10.53.140.145]) by alexa-out-sd-01.qualcomm.com with ESMTP; 06 Dec 2021 14:59:14 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg05-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Dec 2021 14:59:14 -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:13 -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:13 -0800 From: Gaurav Kashyap To: , CC: , , , , , , Gaurav Kashyap Subject: [PATCH 10/10] arm64: dts: qcom: sm8350: add ice and hwkm mappings Date: Mon, 6 Dec 2021 14:57:25 -0800 Message-ID: <20211206225725.77512-11-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-arm-msm@vger.kernel.org Add register mappings for ICE (Inline Crypto Engine) and HWKM (Hardware Key Manager) slave, which are both part of the UFS controller for sm8350. These are required for inline storage encryption using hardware wrapped key. Signed-off-by: Gaurav Kashyap --- arch/arm64/boot/dts/qcom/sm8350.dtsi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi index e91cd8a5e535..8e15524731b3 100644 --- a/arch/arm64/boot/dts/qcom/sm8350.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi @@ -1019,7 +1019,10 @@ ufs_mem_hc: ufshc@1d84000 { compatible = "qcom,sm8350-ufshc", "qcom,ufshc", "jedec,ufs-2.0"; - reg = <0 0x01d84000 0 0x3000>; + reg = <0 0x01d84000 0 0x3000>, + <0 0x01d88000 0 0x8000>, + <0 0x01d90000 0 0x9000>; + reg-names = "ufs_mem", "ice", "ice_hwkm"; interrupts = ; phys = <&ufs_mem_phy_lanes>; phy-names = "ufsphy";