RE: [PATCH v3 04/12] soc: qcom: ice: support for hardware wrapped keys

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Om

On 12/07/2023, Om Prakash Singh wrote:
> On 11/22/2023 11:08 AM, Gaurav Kashyap wrote:
> > Now that HWKM support is added to ICE, extend the ICE driver to
> > support hardware wrapped keys programming coming in from the storage
> > controllers (ufs and emmc). The patches that follow will add ufs and
> > emmc support.
> >
> > Derive software secret support is also added by forwarding the call
> > the corresponding scm api.
> >
> > Signed-off-by: Gaurav Kashyap <quic_gaurkash@xxxxxxxxxxx>
> > ---
> >   drivers/soc/qcom/ice.c | 114
> +++++++++++++++++++++++++++++++++++++----
> >   include/soc/qcom/ice.h |   4 ++
> >   2 files changed, 107 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c index
> > adf9cab848fa..ee7c0beef3d2 100644
> > --- a/drivers/soc/qcom/ice.c
> > +++ b/drivers/soc/qcom/ice.c
> > @@ -27,6 +27,8 @@
> >   #define QCOM_ICE_REG_BIST_STATUS		0x0070
> >   #define QCOM_ICE_REG_ADVANCED_CONTROL		0x1000
> >   #define QCOM_ICE_REG_CONTROL			0x0
> > +#define QCOM_ICE_LUT_KEYS_CRYPTOCFG_R16		0x4040
> > +
> >   /* QCOM ICE HWKM registers */
> >   #define QCOM_ICE_REG_HWKM_TZ_KM_CTL
> 	0x1000
> >   #define QCOM_ICE_REG_HWKM_TZ_KM_STATUS
> 	0x1004
> > @@ -37,6 +39,7 @@
> >   #define QCOM_ICE_REG_HWKM_BANK0_BBAC_3
> 	0x500C
> >   #define QCOM_ICE_REG_HWKM_BANK0_BBAC_4
> 	0x5010
> >
> > +/* QCOM ICE HWKM BIST vals */
> >   #define QCOM_ICE_HWKM_BIST_DONE_V1_VAL		0x11
> >   #define QCOM_ICE_HWKM_BIST_DONE_V2_VAL		0x287
> >
> > @@ -47,6 +50,8 @@
> >   #define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK	0x2
> >   #define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK	0x4
> >
> > +#define QCOM_ICE_LUT_KEYS_CRYPTOCFG_OFFSET	0x80
> > +
> >   #define QCOM_ICE_HWKM_REG_OFFSET	0x8000
> >   #define HWKM_OFFSET(reg)		((reg) +
> QCOM_ICE_HWKM_REG_OFFSET)
> >
> > @@ -67,6 +72,16 @@ struct qcom_ice {
> >   	bool hwkm_init_complete;
> >   };
> >
> > +union crypto_cfg {
> > +	__le32 regval;
> > +	struct {
> > +		u8 dusize;
> > +		u8 capidx;
> > +		u8 reserved;
> > +		u8 cfge;
> > +	};
> > +};
> > +
> >   static bool qcom_ice_check_supported(struct qcom_ice *ice)
> >   {
> >   	u32 regval = qcom_ice_readl(ice, QCOM_ICE_REG_VERSION); @@ -
> 237,6
> > +252,8 @@ static void qcom_ice_hwkm_init(struct qcom_ice *ice)
> >   	/* Clear HWKM response FIFO before doing anything */
> >   	qcom_ice_writel(ice, 0x8,
> >
> 	HWKM_OFFSET(QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STA
> TUS));
> > +
> > +	ice->hwkm_init_complete = true;
> This this change should go with previous patch 3/12.

Okay, makes sense.

> >   }
> >
> >   int qcom_ice_enable(struct qcom_ice *ice) @@ -284,6 +301,51 @@ int
> > qcom_ice_suspend(struct qcom_ice *ice)
> >   }
> >   EXPORT_SYMBOL_GPL(qcom_ice_suspend);
> >
> > +/*
> > + * HW dictates the internal mapping between the ICE and HWKM slots,
> > + * which are different for different versions, make the translation
> > + * here. For v1 however, the translation is done in trustzone.
> > + */
> > +static int translate_hwkm_slot(struct qcom_ice *ice, int slot) {
> > +	return (ice->hwkm_version == 1) ? slot : (slot * 2); }
> > +
> > +static int qcom_ice_program_wrapped_key(struct qcom_ice *ice,
> > +					const struct blk_crypto_key *key,
> > +					u8 data_unit_size, int slot)
> > +{
> > +	int hwkm_slot;
> > +	int err;
> > +	union crypto_cfg cfg;
> > +
> > +	hwkm_slot = translate_hwkm_slot(ice, slot);
> > +
> > +	memset(&cfg, 0, sizeof(cfg));
> > +	cfg.dusize = data_unit_size;
> > +	cfg.capidx = QCOM_SCM_ICE_CIPHER_AES_256_XTS;
> > +	cfg.cfge = 0x80;
> use macro for constant value "0x80"
> > +
> > +	/* Clear CFGE */
> > +	qcom_ice_writel(ice, 0x0, QCOM_ICE_LUT_KEYS_CRYPTOCFG_R16 +
> > +				  QCOM_ICE_LUT_KEYS_CRYPTOCFG_OFFSET
> * slot);
> > +
> > +	/* Call trustzone to program the wrapped key using hwkm */
> > +	err = qcom_scm_ice_set_key(hwkm_slot, key->raw, key->size,
> > +				   QCOM_SCM_ICE_CIPHER_AES_256_XTS,
> data_unit_size);
> > +	if (err) {
> > +		pr_err("%s:SCM call Error: 0x%x slot %d\n", __func__, err,
> > +		       slot);
> > +		return err;
> > +	}
> > +
> > +	/* Enable CFGE after programming key */
> > +	qcom_ice_writel(ice, cfg.regval,
> QCOM_ICE_LUT_KEYS_CRYPTOCFG_R16 +
> > +
> QCOM_ICE_LUT_KEYS_CRYPTOCFG_OFFSET * slot);
> > +
> > +	return err;
> > +}
> > +
> >   int qcom_ice_program_key(struct qcom_ice *ice,
> >   			 u8 algorithm_id, u8 key_size,
> >   			 const struct blk_crypto_key *bkey, @@ -299,24
> +361,31 @@ int
> > qcom_ice_program_key(struct qcom_ice *ice,
> >
> >   	/* Only AES-256-XTS has been tested so far. */
> >   	if (algorithm_id != QCOM_ICE_CRYPTO_ALG_AES_XTS ||
> > -	    key_size != QCOM_ICE_CRYPTO_KEY_SIZE_256) {
> > +	    (key_size != QCOM_ICE_CRYPTO_KEY_SIZE_256 &&
> > +	    key_size != QCOM_ICE_CRYPTO_KEY_SIZE_WRAPPED)) {
> Can you please check the logic with && operation. the condition will always
> be false.

No, the condition won't always be false, my v2 patches were wrong which was pointed out by Neil
https://lore.kernel.org/all/fcbf6dee-aa6a-4af8-9ff1-495adbcb5a57@xxxxxxxxxx/

The condition would check if the size passed is either 256 or wrapped.

> >   		dev_err_ratelimited(dev,
> >   				    "Unhandled crypto capability;
> algorithm_id=%d, key_size=%d\n",
> >   				    algorithm_id, key_size);
> >   		return -EINVAL;
> >   	}
> >
> > -	memcpy(key.bytes, bkey->raw, AES_256_XTS_KEY_SIZE);
> > -
> > -	/* The SCM call requires that the key words are encoded in big
> endian */
> > -	for (i = 0; i < ARRAY_SIZE(key.words); i++)
> > -		__cpu_to_be32s(&key.words[i]);
> > +	if (bkey->crypto_cfg.key_type ==
> BLK_CRYPTO_KEY_TYPE_HW_WRAPPED) {
> > +		if (!ice->use_hwkm)
> > +			return -EINVAL;
> having error log in failure case would help in debugging.
> > +		err = qcom_ice_program_wrapped_key(ice, bkey,
> data_unit_size,
> > +						   slot);
> > +	} else {
> > +		memcpy(key.bytes, bkey->raw, AES_256_XTS_KEY_SIZE);
> >
> > -	err = qcom_scm_ice_set_key(slot, key.bytes,
> AES_256_XTS_KEY_SIZE,
> > -				   QCOM_SCM_ICE_CIPHER_AES_256_XTS,
> > -				   data_unit_size);
> > +		/* The SCM call requires that the key words are encoded in
> big endian */
> > +		for (i = 0; i < ARRAY_SIZE(key.words); i++)
> > +			__cpu_to_be32s(&key.words[i]);
> >
> > -	memzero_explicit(&key, sizeof(key));
> > +		err = qcom_scm_ice_set_key(slot, key.bytes,
> AES_256_XTS_KEY_SIZE,
> > +
> QCOM_SCM_ICE_CIPHER_AES_256_XTS,
> > +					   data_unit_size);
> > +		memzero_explicit(&key, sizeof(key));
> > +	}
> >
> >   	return err;
> >   }
> > @@ -324,7 +393,21 @@ EXPORT_SYMBOL_GPL(qcom_ice_program_key);
> >
> >   int qcom_ice_evict_key(struct qcom_ice *ice, int slot)
> >   {
> > -	return qcom_scm_ice_invalidate_key(slot);
> > +	int hwkm_slot = slot;
> > +
> > +	if (ice->use_hwkm) {
> > +		hwkm_slot = translate_hwkm_slot(ice, slot);
> > +	/*
> > +	 * Ignore calls to evict key when HWKM is supported and hwkm init
> > +	 * is not yet done. This is to avoid the clearing all slots call
> > +	 * during a storage reset when ICE is still in legacy mode. HWKM slave
> > +	 * in ICE takes care of zeroing out the keytable on reset.
> > +	 */
> > +		if (!ice->hwkm_init_complete)
> > +			return 0;
> > +	}
> > +
> > +	return qcom_scm_ice_invalidate_key(hwkm_slot);
> >   }
> >   EXPORT_SYMBOL_GPL(qcom_ice_evict_key);
> >
> > @@ -334,6 +417,15 @@ bool qcom_ice_hwkm_supported(struct qcom_ice
> *ice)
> >   }
> >   EXPORT_SYMBOL_GPL(qcom_ice_hwkm_supported);
> >
> > +int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wkey[],
> > +			      unsigned int wkey_size,
> > +			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
> > +{
> > +	return qcom_scm_derive_sw_secret(wkey, wkey_size,
> > +					 sw_secret,
> BLK_CRYPTO_SW_SECRET_SIZE); }
> > +EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret);
> > +
> >   static struct qcom_ice *qcom_ice_create(struct device *dev,
> >   					void __iomem *base)
> >   {
> > diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h index
> > 1f52e82e3e1c..dabe0d3a1fd0 100644
> > --- a/include/soc/qcom/ice.h
> > +++ b/include/soc/qcom/ice.h
> > @@ -17,6 +17,7 @@ enum qcom_ice_crypto_key_size {
> >   	QCOM_ICE_CRYPTO_KEY_SIZE_192		= 0x2,
> >   	QCOM_ICE_CRYPTO_KEY_SIZE_256		= 0x3,
> >   	QCOM_ICE_CRYPTO_KEY_SIZE_512		= 0x4,
> > +	QCOM_ICE_CRYPTO_KEY_SIZE_WRAPPED	= 0x5,
> >   };
> >
> >   enum qcom_ice_crypto_alg {
> > @@ -35,5 +36,8 @@ int qcom_ice_program_key(struct qcom_ice *ice,
> >   			 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);
> > +int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wkey[],
> > +			      unsigned int wkey_size,
> > +			      u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
> >   struct qcom_ice *of_qcom_ice_get(struct device *dev);
> >   #endif /* __QCOM_ICE_H__ */




[Index of Archives]     [Linux Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux