From patchwork Mon Dec 2 12:02:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 13890456 Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A5BA2205E07 for ; Mon, 2 Dec 2024 12:02:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733140980; cv=none; b=YXQNf72cp+GRPoxLFJZ142XVRRxOTTIa704oS6mikFiqOIiMJQ5uvcDIjiWnBVN9/Zjhozuu8IDsMkOA6VjwYD15UyEBYmJiWWS6NEqRya9UwUxlNgFx6Dqo+r35TdrZ4zKZtSLE8UbhYEdN1coZB9sFSr1XFCfdcaZlym5KEtM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733140980; c=relaxed/simple; bh=f59y2sAoxUD19VFlzXOZIuQVVcrSA8fWNTuWTCMkgVg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CkrChazQzxENVNCzdHNmzMrK2et0lIblbPC3IRtpzh1bK4aSJ4XfhwDjjxFw0GF3ozZV+nHxfUFOb4+V2XuzeP0UyuPbepn+6IJXcCxfiWo1iihTJTc7BiyWWMafFrJ81ZHMLRwqa2KKX+vRQkxKa47yzPowsRUmm5FK+/8p7mg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=bgdev.pl; spf=none smtp.mailfrom=bgdev.pl; dkim=pass (2048-bit key) header.d=bgdev-pl.20230601.gappssmtp.com header.i=@bgdev-pl.20230601.gappssmtp.com header.b=FtIBKqoM; arc=none smtp.client-ip=209.85.128.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=bgdev.pl Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bgdev.pl Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bgdev-pl.20230601.gappssmtp.com header.i=@bgdev-pl.20230601.gappssmtp.com header.b="FtIBKqoM" Received: by mail-wm1-f49.google.com with SMTP id 5b1f17b1804b1-434a1639637so38980875e9.1 for ; Mon, 02 Dec 2024 04:02:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20230601.gappssmtp.com; s=20230601; t=1733140975; x=1733745775; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=ftcUOFK9BkThfl3JBnS7+/vU5+8BtkX9fgCwRavyYYk=; b=FtIBKqoMRMVvVbcTx7L77sf5Zo90Dlt4rVDiGorjAro3WtHK3Kp0pWbtldCpkK0r/c ubEmqpZhcMe3rLhsRNBEseXdSkz3RV0dDd1dYhXMYbjhqkFf3yEVAMcfvjaIhN1NOq6a LtFSTMhjgLUJ1K+Z3y9Zzk9DTPy7oRXYSXsDi9nNmwQnSj8HEbHIxXt66nG4NWjEfvzC UIFhk5s2ji58ziIndbfoK7aR58ckoS39HFNMTDYrtwtemmKiAArB4XFiHJKg+USK02Xr peWAslAHgaBbT8aMkPbT5IhmuHJBBt3HpL5/mMdPaAJaXarFGKsS1R8gONwNhqd66Cf6 ax2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733140975; x=1733745775; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ftcUOFK9BkThfl3JBnS7+/vU5+8BtkX9fgCwRavyYYk=; b=at3ePDfR6k84LxUiy8YiBh94iVEQu4DlU4c/p6k2ZrOIimk6U4mrHquEaePUyVoBcL BonBzeVAnZQVu1XvvEjK7ZlXuogRWA5Dg7DM9MaOESclSIe9acW7iu5qKgemoGp2gYR/ fq7KLU26Vm807x1VvmI3GplI1WZn5/tN/Bqwey5dZ2asNdt4CWmPAAvpkuHrYezh3SIf gUXvQYxiI+QDFCcGh9ZAIvdGJBpH7zd/0GfMrKGTYh0NelPuzMgN+qCOmI+bzJ73VN35 ymbdMEz5hVcsT3DqE7LVHADTa6aFs85lM/wEfmtycEuArjSGtSbwJyBKf4k+L/FwNJDc gEpw== X-Forwarded-Encrypted: i=1; AJvYcCVx/PMJattXBohpClEYIx6Ll4rF1QrWLE11Ve5ih8BqFgKmV7CAKRfAtr9QmySBfroqgfnuNUY6qfVHNyLl@vger.kernel.org X-Gm-Message-State: AOJu0YyxMDYnliA5wUsjubv/cntP2eb5EiAs7Vd1D2UONDRh9nwR67xa 1iTQyfx3qIAzv4jYsJDs93GfZdKF+GdbT6NdH+B3PJlneOdc7B2VXwZlKnlWI0A= X-Gm-Gg: ASbGncuPC5R0ovCCnUdp/WxpRA0cG6c4PtUiV1vvfIM0mMSCpzN5hwfzxo/QFjdpEE4 RTchkL4Mvkad42FL1aFEzHMVVFWlHlVcpQ1VYyLcvcejaHLb/lnv2j9EpAbmfmpB5FdjN64/Hc5 15Pdw9ma1TBKfQbZY2ThboUi/eEdp3g1R+A8TNJcD9xvgNwstmJuiNJEzxBfxgeU8TzPnanfcOT lprpm1x/Q4BdQoGKuKsF7nL3y3ER8zKEPNH8+We X-Google-Smtp-Source: AGHT+IF7osq7PiK5X8TwQQbGuOfXP+0HTGbUIuO4TGAFWYSSBQCIgi6CIixopBv4gVFfOdC24T67nA== X-Received: by 2002:a05:600c:1ca7:b0:434:a202:7a0d with SMTP id 5b1f17b1804b1-434a9de44b7mr184701065e9.22.1733140974400; Mon, 02 Dec 2024 04:02:54 -0800 (PST) Received: from [127.0.1.1] ([193.57.185.11]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-434b0d9bed7sm152396095e9.8.2024.12.02.04.02.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 Dec 2024 04:02:54 -0800 (PST) From: Bartosz Golaszewski Date: Mon, 02 Dec 2024 13:02:25 +0100 Subject: [PATCH RESEND v7 09/17] soc: qcom: ice: add HWKM support to the ICE driver Precedence: bulk X-Mailing-List: linux-fscrypt@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241202-wrapped-keys-v7-9-67c3ca3f3282@linaro.org> References: <20241202-wrapped-keys-v7-0-67c3ca3f3282@linaro.org> In-Reply-To: <20241202-wrapped-keys-v7-0-67c3ca3f3282@linaro.org> To: Jens Axboe , Jonathan Corbet , Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Adrian Hunter , Asutosh Das , Ritesh Harjani , Ulf Hansson , Alim Akhtar , Avri Altman , Bart Van Assche , "James E.J. Bottomley" , Gaurav Kashyap , Neil Armstrong , Dmitry Baryshkov , "Martin K. Petersen" , Eric Biggers , "Theodore Y. Ts'o" , Jaegeuk Kim , Alexander Viro , Christian Brauner , Jan Kara , Bjorn Andersson , Konrad Dybcio , Manivannan Sadhasivam Cc: linux-block@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, dm-devel@lists.linux.dev, linux-mmc@vger.kernel.org, linux-scsi@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Bartosz Golaszewski X-Mailer: b4 0.14.1 X-Developer-Signature: v=1; a=openpgp-sha256; l=9623; i=bartosz.golaszewski@linaro.org; h=from:subject:message-id; bh=QdDciS7N9Q18RVCBLlPev9WG0N3W7Imry7+pIFcB1Sw=; b=owEBbQKS/ZANAwAKARGnLqAUcddyAcsmYgBnTaHUB2ZcB3CguIfWYlMi++x/fKzCPTWqIebCH RkX/AjSVOuJAjMEAAEKAB0WIQQWnetsC8PEYBPSx58Rpy6gFHHXcgUCZ02h1AAKCRARpy6gFHHX cv6yD/0RH5EUpQh90ceBbnf0GNGSpg9btdpxa0Ju7xN490n5XAgED9KEOEyzaG7+//+cEWa7jIB o6B5U7JGkXFPAo01bdT5XnP0pY2NREtymnbDhutCUQE4RSp00ewNTgezFcxjRcDMpMcvpT3b2WB lhis+N6NYtSrXDGsVOKgAlE7DHDjH3lT0MT2rbrpl5QJsLkildh7mXlJ2qVjzNQjLu/kfxEA3zv JzUhSO/tP3rjmCrxE7othTFUUU19FhuOP6Ombctt9F3MCucbrmdH51gmdHPYtou7q4dbGAoYrQp zz2LSm0S0qlFQMJTt6y5iX4ygJIh/2DM3IYRHeKaxy1kEwJWnfUXggs4UxkbUyAHIN+H1JMfHKZ 3XqnvliEiGTfb2RdlJjEZS+8ExcoeHonULnjVJfp9Uafl/XWZDVXeP7W2TDG2CoueuvufhQdRpR 2gzRKS0O69M20mi/UUR7SwwfC0zpF8C9G0nCG/yzjAozCJ4JPEwXAfhLjHVsadnMsoQBQIaaP+3 8n/3u0KgB9RcUT+Aw5MXhBlgq+Syoz5p8o2f/hzA2mPmk9/AlUt/v3Fi/rc8dKOeY1XVq8bt6uN b3c9joyMPMWWiGelDBN/Eh3J6MwAWhyHclSf2W6aUvqu1b0mRKsvs/P/+d6BrKWrPeKy+8WYysz Znr6RHJrsEpEwUA== X-Developer-Key: i=bartosz.golaszewski@linaro.org; a=openpgp; fpr=169DEB6C0BC3C46013D2C79F11A72EA01471D772 From: Gaurav Kashyap Qualcomm's ICE (Inline Crypto Engine) contains a proprietary key management hardware called Hardware Key Manager (HWKM). Add HWKM support to the ICE driver if it is available on the platform. HWKM primarily provides hardware wrapped key support where the ICE (storage) keys are not available in software and instead protected in hardware. When HWKM software support is not fully available (from Trustzone), there can be a scenario where the ICE hardware supports HWKM, but it cannot be used for wrapped keys. In this case, raw keys have to be used without using the HWKM. We query the TZ at run-time to find out whether wrapped keys support is available. Tested-by: Neil Armstrong Signed-off-by: Gaurav Kashyap Reviewed-by: Konrad Dybcio Signed-off-by: Bartosz Golaszewski --- drivers/soc/qcom/ice.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++-- include/soc/qcom/ice.h | 1 + 2 files changed, 149 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c index e89baaf574bc1..5f138e278554c 100644 --- a/drivers/soc/qcom/ice.c +++ b/drivers/soc/qcom/ice.c @@ -27,6 +27,40 @@ #define QCOM_ICE_REG_FUSE_SETTING 0x0010 #define QCOM_ICE_REG_BIST_STATUS 0x0070 #define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000 +#define QCOM_ICE_REG_CONTROL 0x0 +/* QCOM ICE HWKM registers */ +#define QCOM_ICE_REG_HWKM_TZ_KM_CTL 0x1000 +#define QCOM_ICE_REG_HWKM_TZ_KM_STATUS 0x1004 +#define QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STATUS 0x2008 +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_0 0x5000 +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_1 0x5004 +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_2 0x5008 +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_3 0x500C +#define QCOM_ICE_REG_HWKM_BANK0_BBAC_4 0x5010 + +/* QCOM ICE HWKM reg vals */ +#define QCOM_ICE_HWKM_BIST_DONE_V1 BIT(16) +#define QCOM_ICE_HWKM_BIST_DONE_V2 BIT(9) +#define QCOM_ICE_HWKM_BIST_DONE(ver) QCOM_ICE_HWKM_BIST_DONE_V##ver + +#define QCOM_ICE_HWKM_CRYPTO_BIST_DONE_V1 BIT(14) +#define QCOM_ICE_HWKM_CRYPTO_BIST_DONE_V2 BIT(7) +#define QCOM_ICE_HWKM_CRYPTO_BIST_DONE(v) QCOM_ICE_HWKM_CRYPTO_BIST_DONE_V##v + +#define QCOM_ICE_HWKM_BOOT_CMD_LIST1_DONE BIT(2) +#define QCOM_ICE_HWKM_BOOT_CMD_LIST0_DONE BIT(1) +#define QCOM_ICE_HWKM_KT_CLEAR_DONE BIT(0) + +#define QCOM_ICE_HWKM_BIST_VAL(v) (QCOM_ICE_HWKM_BIST_DONE(v) | \ + QCOM_ICE_HWKM_CRYPTO_BIST_DONE(v) | \ + QCOM_ICE_HWKM_BOOT_CMD_LIST1_DONE | \ + QCOM_ICE_HWKM_BOOT_CMD_LIST0_DONE | \ + QCOM_ICE_HWKM_KT_CLEAR_DONE) + +#define QCOM_ICE_HWKM_V1_STANDARD_MODE_VAL (BIT(0) | BIT(1) | BIT(2)) +#define QCOM_ICE_HWKM_V2_STANDARD_MODE_MASK GENMASK(31, 1) +#define QCOM_ICE_HWKM_DISABLE_CRC_CHECKS_VAL (BIT(1) | BIT(2)) +#define QCOM_ICE_HWKM_RSP_FIFO_CLEAR_VAL BIT(3) /* BIST ("built-in self-test") status flags */ #define QCOM_ICE_BIST_STATUS_MASK GENMASK(31, 28) @@ -35,6 +69,9 @@ #define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2 #define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4 +#define QCOM_ICE_HWKM_REG_OFFSET 0x8000 +#define HWKM_OFFSET(reg) ((reg) + QCOM_ICE_HWKM_REG_OFFSET) + #define qcom_ice_writel(engine, val, reg) \ writel((val), (engine)->base + (reg)) @@ -46,6 +83,9 @@ struct qcom_ice { void __iomem *base; struct clk *core_clk; + u8 hwkm_version; + bool use_hwkm; + bool hwkm_init_complete; }; static bool qcom_ice_check_supported(struct qcom_ice *ice) @@ -63,8 +103,21 @@ static bool qcom_ice_check_supported(struct qcom_ice *ice) return false; } - dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", - major, minor, step); + if (major >= 4 || (major == 3 && minor == 2 && step >= 1)) + ice->hwkm_version = 2; + else if (major == 3 && minor == 2) + ice->hwkm_version = 1; + else + ice->hwkm_version = 0; + + if (ice->hwkm_version == 0) + ice->use_hwkm = false; + + dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d, HWKM v%d\n", + major, minor, step, ice->hwkm_version); + + if (!ice->use_hwkm) + dev_info(dev, "QC ICE HWKM (Hardware Key Manager) not used/supported"); /* If fuses are blown, ICE might not work in the standard way. */ regval = qcom_ice_readl(ice, QCOM_ICE_REG_FUSE_SETTING); @@ -113,27 +166,106 @@ static void qcom_ice_optimization_enable(struct qcom_ice *ice) * fails, so we needn't do it in software too, and (c) properly testing * storage encryption requires testing the full storage stack anyway, * and not relying on hardware-level self-tests. + * + * However, we still care about if HWKM BIST failed (when supported) as + * important functionality would fail later, so disable hwkm on failure. */ static int qcom_ice_wait_bist_status(struct qcom_ice *ice) { u32 regval; + u32 bist_done_val; int err; err = readl_poll_timeout(ice->base + QCOM_ICE_REG_BIST_STATUS, regval, !(regval & QCOM_ICE_BIST_STATUS_MASK), 50, 5000); - if (err) + if (err) { dev_err(ice->dev, "Timed out waiting for ICE self-test to complete\n"); + return err; + } + if (ice->use_hwkm) { + bist_done_val = ice->hwkm_version == 1 ? + QCOM_ICE_HWKM_BIST_VAL(1) : + QCOM_ICE_HWKM_BIST_VAL(2); + if (qcom_ice_readl(ice, + HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_STATUS)) != + bist_done_val) { + dev_err(ice->dev, "HWKM BIST error\n"); + ice->use_hwkm = false; + err = -ENODEV; + } + } return err; } +static void qcom_ice_enable_standard_mode(struct qcom_ice *ice) +{ + u32 val = 0; + + /* + * When ICE is in standard (hwkm) mode, it supports HW wrapped + * keys, and when it is in legacy mode, it only supports standard + * (non HW wrapped) keys. + * + * Put ICE in standard mode, ICE defaults to legacy mode. + * Legacy mode - ICE HWKM slave not supported. + * Standard mode - ICE HWKM slave supported. + * + * Depending on the version of HWKM, it is controlled by different + * registers in ICE. + */ + if (ice->hwkm_version >= 2) { + val = qcom_ice_readl(ice, QCOM_ICE_REG_CONTROL); + val = val & QCOM_ICE_HWKM_V2_STANDARD_MODE_MASK; + qcom_ice_writel(ice, val, QCOM_ICE_REG_CONTROL); + } else { + qcom_ice_writel(ice, QCOM_ICE_HWKM_V1_STANDARD_MODE_VAL, + HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_CTL)); + } +} + +static void qcom_ice_hwkm_init(struct qcom_ice *ice) +{ + /* Disable CRC checks. This HWKM feature is not used. */ + qcom_ice_writel(ice, QCOM_ICE_HWKM_DISABLE_CRC_CHECKS_VAL, + HWKM_OFFSET(QCOM_ICE_REG_HWKM_TZ_KM_CTL)); + + /* + * Give register bank of the HWKM slave access to read and modify + * the keyslots in ICE HWKM slave. Without this, trustzone will not + * be able to program keys into ICE. + */ + qcom_ice_writel(ice, GENMASK(31, 0), HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_0)); + qcom_ice_writel(ice, GENMASK(31, 0), HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_1)); + qcom_ice_writel(ice, GENMASK(31, 0), HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_2)); + qcom_ice_writel(ice, GENMASK(31, 0), HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_3)); + qcom_ice_writel(ice, GENMASK(31, 0), HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BBAC_4)); + + /* Clear HWKM response FIFO before doing anything */ + qcom_ice_writel(ice, QCOM_ICE_HWKM_RSP_FIFO_CLEAR_VAL, + HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STATUS)); + ice->hwkm_init_complete = true; +} + int qcom_ice_enable(struct qcom_ice *ice) { + int err; + qcom_ice_low_power_mode_enable(ice); qcom_ice_optimization_enable(ice); - return qcom_ice_wait_bist_status(ice); + if (ice->use_hwkm) + qcom_ice_enable_standard_mode(ice); + + err = qcom_ice_wait_bist_status(ice); + if (err) + return err; + + if (ice->use_hwkm) + qcom_ice_hwkm_init(ice); + + return err; } EXPORT_SYMBOL_GPL(qcom_ice_enable); @@ -149,6 +281,10 @@ int qcom_ice_resume(struct qcom_ice *ice) return err; } + if (ice->use_hwkm) { + qcom_ice_enable_standard_mode(ice); + qcom_ice_hwkm_init(ice); + } return qcom_ice_wait_bist_status(ice); } EXPORT_SYMBOL_GPL(qcom_ice_resume); @@ -156,6 +292,7 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume); int qcom_ice_suspend(struct qcom_ice *ice) { clk_disable_unprepare(ice->core_clk); + ice->hwkm_init_complete = false; return 0; } @@ -205,6 +342,12 @@ int qcom_ice_evict_key(struct qcom_ice *ice, int slot) } EXPORT_SYMBOL_GPL(qcom_ice_evict_key); +bool qcom_ice_hwkm_supported(struct qcom_ice *ice) +{ + return ice->use_hwkm; +} +EXPORT_SYMBOL_GPL(qcom_ice_hwkm_supported); + static struct qcom_ice *qcom_ice_create(struct device *dev, void __iomem *base) { @@ -239,6 +382,7 @@ static struct qcom_ice *qcom_ice_create(struct device *dev, engine->core_clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(engine->core_clk)) return ERR_CAST(engine->core_clk); + engine->use_hwkm = qcom_scm_has_wrapped_key_support(); if (!qcom_ice_check_supported(engine)) return ERR_PTR(-EOPNOTSUPP); diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h index 9dd835dba2a78..1f52e82e3e1ca 100644 --- a/include/soc/qcom/ice.h +++ b/include/soc/qcom/ice.h @@ -34,5 +34,6 @@ int qcom_ice_program_key(struct qcom_ice *ice, const struct blk_crypto_key *bkey, u8 data_unit_size, int slot); int qcom_ice_evict_key(struct qcom_ice *ice, int slot); +bool qcom_ice_hwkm_supported(struct qcom_ice *ice); struct qcom_ice *of_qcom_ice_get(struct device *dev); #endif /* __QCOM_ICE_H__ */