Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: qcom: ice: Add HWKM v1 support for wrapped keys

HWKM v1 and v2 differ slightly in wrapped key size and the bit fields for
certain status registers and operating mode (legacy or standard).

Add support to select HWKM version based on the major and minor revisions.
Use this HWKM version to select wrapped key size and to configure the bit
fields in registers for operating modes and hardware status.

Support for SCM calls for wrapped keys is being added in the TrustZone for
few SoCs with HWKM v1. Existing check of qcom_scm_has_wrapped_key_support()
API ensures that HWKM is used only if these SCM calls are supported in
TrustZone for that SoC.

Signed-off-by: Neeraj Soni <neeraj.soni@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20251030161012.3391239-1-neeraj.soni@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Neeraj Soni and committed by
Bjorn Andersson
d92ebadd 7a94d5f3

+58 -23
+58 -23
drivers/soc/qcom/ice.c
··· 22 22 #include <soc/qcom/ice.h> 23 23 24 24 #define AES_256_XTS_KEY_SIZE 64 /* for raw keys only */ 25 - #define QCOM_ICE_HWKM_WRAPPED_KEY_SIZE 100 /* assuming HWKM v2 */ 25 + 26 + #define QCOM_ICE_HWKM_V1 1 /* HWKM version 1 */ 27 + #define QCOM_ICE_HWKM_V2 2 /* HWKM version 2 */ 28 + 29 + #define QCOM_ICE_HWKM_MAX_WRAPPED_KEY_SIZE 100 /* Maximum HWKM wrapped key size */ 30 + 31 + /* 32 + * Wrapped key size depends upon HWKM version: 33 + * HWKM version 1 supports 68 bytes 34 + * HWKM version 2 supports 100 bytes 35 + */ 36 + #define QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(v) ((v) == QCOM_ICE_HWKM_V1 ? 68 : 100) 26 37 27 38 /* QCOM ICE registers */ 28 39 ··· 73 62 74 63 #define QCOM_ICE_REG_HWKM_TZ_KM_CTL (HWKM_OFFSET + 0x1000) 75 64 #define QCOM_ICE_HWKM_DISABLE_CRC_CHECKS_VAL (BIT(1) | BIT(2)) 65 + /* In HWKM v1 the ICE legacy mode is controlled from HWKM register space */ 66 + #define QCOM_ICE_HWKM_ICE_LEGACY_MODE_ENABLED BIT(5) 76 67 77 68 #define QCOM_ICE_REG_HWKM_TZ_KM_STATUS (HWKM_OFFSET + 0x1004) 78 69 #define QCOM_ICE_HWKM_KT_CLEAR_DONE BIT(0) 79 70 #define QCOM_ICE_HWKM_BOOT_CMD_LIST0_DONE BIT(1) 80 71 #define QCOM_ICE_HWKM_BOOT_CMD_LIST1_DONE BIT(2) 81 - #define QCOM_ICE_HWKM_CRYPTO_BIST_DONE_V2 BIT(7) 82 - #define QCOM_ICE_HWKM_BIST_DONE_V2 BIT(9) 72 + #define QCOM_ICE_HWKM_CRYPTO_BIST_DONE(v) (((v) == QCOM_ICE_HWKM_V1) ? BIT(14) : BIT(7)) 73 + #define QCOM_ICE_HWKM_BIST_DONE(v) (((v) == QCOM_ICE_HWKM_V1) ? BIT(16) : BIT(9)) 83 74 84 75 #define QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STATUS (HWKM_OFFSET + 0x2008) 85 76 #define QCOM_ICE_HWKM_RSP_FIFO_CLEAR_VAL BIT(3) ··· 110 97 struct clk *core_clk; 111 98 bool use_hwkm; 112 99 bool hwkm_init_complete; 100 + u8 hwkm_version; 113 101 }; 114 102 115 103 static bool qcom_ice_check_supported(struct qcom_ice *ice) ··· 128 114 return false; 129 115 } 130 116 117 + /* HWKM version v2 is present from ICE 3.2.1 onwards while version v1 118 + * is present only in ICE 3.2.0. Earlier ICE version don't have HWKM. 119 + */ 120 + if (major > 3 || 121 + (major == 3 && (minor >= 3 || (minor == 2 && step >= 1)))) 122 + ice->hwkm_version = QCOM_ICE_HWKM_V2; 123 + else if ((major == 3) && (minor == 2)) 124 + ice->hwkm_version = QCOM_ICE_HWKM_V1; 125 + else 126 + ice->hwkm_version = 0; 127 + 131 128 dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n", 132 129 major, minor, step); 130 + 131 + if (ice->hwkm_version) 132 + dev_info(dev, "QC Hardware Key Manager (HWKM) version v%d\n", 133 + ice->hwkm_version); 133 134 134 135 /* If fuses are blown, ICE might not work in the standard way. */ 135 136 regval = qcom_ice_readl(ice, QCOM_ICE_REG_FUSE_SETTING); ··· 160 131 * v3.2.1 and later have HWKM v2. ICE v3.2.0 has HWKM v1. Earlier ICE 161 132 * versions don't have HWKM at all. However, for HWKM to be fully 162 133 * usable by Linux, the TrustZone software also needs to support certain 163 - * SCM calls including the ones to generate and prepare keys. That 164 - * effectively makes the earliest supported SoC be SM8650, which has 165 - * HWKM v2. Therefore, this driver doesn't include support for HWKM v1, 166 - * and it checks for the SCM call support before it decides to use HWKM. 134 + * SCM calls including the ones to generate and prepare keys. Support 135 + * for these SCM calls is present for SoCs with HWKM v2 and is being 136 + * added for SoCs with HWKM v1 as well but not every SoC with HWKM v1 137 + * currently supports this. So, this driver checks for the SCM call 138 + * support before it decides to use HWKM. 167 139 * 168 140 * Also, since HWKM and legacy mode are mutually exclusive, and 169 141 * ICE-capable storage driver(s) need to know early on whether to 170 142 * advertise support for raw keys or wrapped keys, HWKM cannot be used 171 143 * unconditionally. A module parameter is used to opt into using it. 172 144 */ 173 - if ((major >= 4 || 174 - (major == 3 && (minor >= 3 || (minor == 2 && step >= 1)))) && 175 - qcom_scm_has_wrapped_key_support()) { 145 + if (ice->hwkm_version && qcom_scm_has_wrapped_key_support()) { 176 146 if (qcom_ice_use_wrapped_keys) { 177 147 dev_info(dev, "Using HWKM. Supporting wrapped keys only.\n"); 178 148 ice->use_hwkm = true; ··· 240 212 (QCOM_ICE_HWKM_KT_CLEAR_DONE | 241 213 QCOM_ICE_HWKM_BOOT_CMD_LIST0_DONE | 242 214 QCOM_ICE_HWKM_BOOT_CMD_LIST1_DONE | 243 - QCOM_ICE_HWKM_CRYPTO_BIST_DONE_V2 | 244 - QCOM_ICE_HWKM_BIST_DONE_V2)) { 215 + QCOM_ICE_HWKM_CRYPTO_BIST_DONE(ice->hwkm_version) | 216 + QCOM_ICE_HWKM_BIST_DONE(ice->hwkm_version))) { 245 217 dev_err(ice->dev, "HWKM self-test error!\n"); 246 218 /* 247 219 * Too late to revoke use_hwkm here, as it was already ··· 258 230 if (!ice->use_hwkm) 259 231 return; 260 232 261 - BUILD_BUG_ON(QCOM_ICE_HWKM_WRAPPED_KEY_SIZE > 233 + BUILD_BUG_ON(QCOM_ICE_HWKM_MAX_WRAPPED_KEY_SIZE > 262 234 BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE); 263 235 /* 264 236 * When ICE is in HWKM mode, it only supports wrapped keys. ··· 266 238 * 267 239 * Put ICE in HWKM mode. ICE defaults to legacy mode. 268 240 */ 269 - regval = qcom_ice_readl(ice, QCOM_ICE_REG_CONTROL); 270 - regval &= ~QCOM_ICE_LEGACY_MODE_ENABLED; 271 - qcom_ice_writel(ice, regval, QCOM_ICE_REG_CONTROL); 241 + if (ice->hwkm_version == QCOM_ICE_HWKM_V2) { 242 + regval = qcom_ice_readl(ice, QCOM_ICE_REG_CONTROL); 243 + regval &= ~QCOM_ICE_LEGACY_MODE_ENABLED; 244 + qcom_ice_writel(ice, regval, QCOM_ICE_REG_CONTROL); 245 + } else if (ice->hwkm_version == QCOM_ICE_HWKM_V1) { 246 + regval = qcom_ice_readl(ice, QCOM_ICE_REG_HWKM_TZ_KM_CTL); 247 + regval &= ~QCOM_ICE_HWKM_ICE_LEGACY_MODE_ENABLED; 248 + qcom_ice_writel(ice, regval, QCOM_ICE_REG_HWKM_TZ_KM_CTL); 249 + } 272 250 273 251 /* Disable CRC checks. This HWKM feature is not used. */ 274 252 qcom_ice_writel(ice, QCOM_ICE_HWKM_DISABLE_CRC_CHECKS_VAL, ··· 332 298 333 299 static unsigned int translate_hwkm_slot(struct qcom_ice *ice, unsigned int slot) 334 300 { 335 - return slot * 2; 301 + return ice->hwkm_version == QCOM_ICE_HWKM_V1 ? slot : slot * 2; 336 302 } 337 303 338 304 static int qcom_ice_program_wrapped_key(struct qcom_ice *ice, unsigned int slot, ··· 485 451 { 486 452 int err; 487 453 488 - err = qcom_scm_generate_ice_key(lt_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE); 454 + err = qcom_scm_generate_ice_key(lt_key, 455 + QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version)); 489 456 if (err) 490 457 return err; 491 458 492 - return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE; 459 + return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version); 493 460 } 494 461 EXPORT_SYMBOL_GPL(qcom_ice_generate_key); 495 462 ··· 513 478 int err; 514 479 515 480 err = qcom_scm_prepare_ice_key(lt_key, lt_key_size, 516 - eph_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE); 481 + eph_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version)); 517 482 if (err == -EIO || err == -EINVAL) 518 483 err = -EBADMSG; /* probably invalid key */ 519 484 if (err) 520 485 return err; 521 486 522 - return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE; 487 + return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version); 523 488 } 524 489 EXPORT_SYMBOL_GPL(qcom_ice_prepare_key); 525 490 ··· 541 506 int err; 542 507 543 508 err = qcom_scm_import_ice_key(raw_key, raw_key_size, 544 - lt_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE); 509 + lt_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version)); 545 510 if (err) 546 511 return err; 547 512 548 - return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE; 513 + return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version); 549 514 } 550 515 EXPORT_SYMBOL_GPL(qcom_ice_import_key); 551 516