Message ID | 20240617005825.1443206-7-quic_gaurkash@quicinc.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | Hardware wrapped key support for qcom ice and ufs | expand |
On Sun, Jun 16, 2024 at 05:51:01PM GMT, Gaurav Kashyap wrote: > Wrapped key creation and management using HWKM is currently > supported only through Qualcomm's Trustzone. > Three new SCM calls have already been added in the scm layer > for this purpose. > > This patch adds support for generate, prepare and import key > apis in ICE module and hooks it up the scm calls defined for them. > This will eventually plug into the new IOCTLS added for this > usecase in the block layer. Documentation/process/submitting-patches.rst. "This patch..." > > Tested-by: Neil Armstrong <neil.armstrong@linaro.org> > Signed-off-by: Gaurav Kashyap <quic_gaurkash@quicinc.com> > --- > drivers/soc/qcom/ice.c | 75 ++++++++++++++++++++++++++++++++++++++++++ > include/soc/qcom/ice.h | 8 +++++ > 2 files changed, 83 insertions(+) > > diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c > index f0e9e0885732..68062b27f40c 100644 > --- a/drivers/soc/qcom/ice.c > +++ b/drivers/soc/qcom/ice.c > @@ -21,6 +21,13 @@ > > #define AES_256_XTS_KEY_SIZE 64 > > +/* > + * Wrapped key sizes that HWKM expects and manages is different for different > + * versions of the hardware. > + */ > +#define QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(v) \ > + ((v) == 1 ? 68 : 100) > + > /* QCOM ICE registers */ > #define QCOM_ICE_REG_VERSION 0x0008 > #define QCOM_ICE_REG_FUSE_SETTING 0x0010 > @@ -445,6 +452,74 @@ int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wkey[], > } > EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret); > > +/** > + * qcom_ice_generate_key() - Generate a wrapped key for inline encryption > + * @lt_key: longterm wrapped key that is generated, which is > + * 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: lt wrapped key size on success; err on failure. This is incorrect. > + */ > +int qcom_ice_generate_key(struct qcom_ice *ice, > + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) > +{ > + size_t wk_size = QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version); > + > + if (!qcom_scm_generate_ice_key(lt_key, wk_size)) > + return wk_size; > + return 0; > +} > +EXPORT_SYMBOL_GPL(qcom_ice_generate_key); > + > +/** > + * qcom_ice_prepare_key() - Prepare a longterm wrapped key for inline encryption > + * @lt_key: longterm wrapped key that is generated or imported. > + * @lt_key_size: size of the longterm wrapped_key > + * @eph_key: wrapped key returned which has been wrapped with a per-boot ephemeral key, > + * size of which is BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE in 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: eph wrapped key size on success; err on failure. And this too. > + */ > +int qcom_ice_prepare_key(struct qcom_ice *ice, const u8 *lt_key, size_t lt_key_size, > + u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) > +{ > + size_t wk_size = QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version); > + > + if (!qcom_scm_prepare_ice_key(lt_key, lt_key_size, eph_key, wk_size)) > + return wk_size; > + return 0; > +} > +EXPORT_SYMBOL_GPL(qcom_ice_prepare_key); > + > +/** > + * qcom_ice_import_key() - Import a raw key for inline encryption > + * @imp_key: raw key that has to be imported > + * @imp_key_size: size of the imported key > + * @lt_key: longterm wrapped key that is imported, which is > + * BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE in size. > + * > + * Make a scm call into trustzone to import a raw key for storage encryption > + * and generate a longterm wrapped key using hwkm. > + * > + * Return: lt wrapped key size on success; err on failure. Guess, this is incorrect too. > + */ > +int qcom_ice_import_key(struct qcom_ice *ice, const u8 *imp_key, size_t imp_key_size, > + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) > +{ > + size_t wk_size = QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version); > + > + if (!qcom_scm_import_ice_key(imp_key, imp_key_size, lt_key, wk_size)) > + return wk_size; > + return 0; > +} > +EXPORT_SYMBOL_GPL(qcom_ice_import_key); > + > 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 dabe0d3a1fd0..dcf277d196ff 100644 > --- a/include/soc/qcom/ice.h > +++ b/include/soc/qcom/ice.h > @@ -39,5 +39,13 @@ 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]); > +int qcom_ice_generate_key(struct qcom_ice *ice, > + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); > +int qcom_ice_prepare_key(struct qcom_ice *ice, > + const u8 *lt_key, size_t lt_key_size, > + u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); > +int qcom_ice_import_key(struct qcom_ice *ice, > + const u8 *imp_key, size_t imp_key_size, > + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); > struct qcom_ice *of_qcom_ice_get(struct device *dev); > #endif /* __QCOM_ICE_H__ */ > -- > 2.43.0 >
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c index f0e9e0885732..68062b27f40c 100644 --- a/drivers/soc/qcom/ice.c +++ b/drivers/soc/qcom/ice.c @@ -21,6 +21,13 @@ #define AES_256_XTS_KEY_SIZE 64 +/* + * Wrapped key sizes that HWKM expects and manages is different for different + * versions of the hardware. + */ +#define QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(v) \ + ((v) == 1 ? 68 : 100) + /* QCOM ICE registers */ #define QCOM_ICE_REG_VERSION 0x0008 #define QCOM_ICE_REG_FUSE_SETTING 0x0010 @@ -445,6 +452,74 @@ int qcom_ice_derive_sw_secret(struct qcom_ice *ice, const u8 wkey[], } EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret); +/** + * qcom_ice_generate_key() - Generate a wrapped key for inline encryption + * @lt_key: longterm wrapped key that is generated, which is + * 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: lt wrapped key size on success; err on failure. + */ +int qcom_ice_generate_key(struct qcom_ice *ice, + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + size_t wk_size = QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version); + + if (!qcom_scm_generate_ice_key(lt_key, wk_size)) + return wk_size; + return 0; +} +EXPORT_SYMBOL_GPL(qcom_ice_generate_key); + +/** + * qcom_ice_prepare_key() - Prepare a longterm wrapped key for inline encryption + * @lt_key: longterm wrapped key that is generated or imported. + * @lt_key_size: size of the longterm wrapped_key + * @eph_key: wrapped key returned which has been wrapped with a per-boot ephemeral key, + * size of which is BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE in 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: eph wrapped key size on success; err on failure. + */ +int qcom_ice_prepare_key(struct qcom_ice *ice, const u8 *lt_key, size_t lt_key_size, + u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + size_t wk_size = QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version); + + if (!qcom_scm_prepare_ice_key(lt_key, lt_key_size, eph_key, wk_size)) + return wk_size; + return 0; +} +EXPORT_SYMBOL_GPL(qcom_ice_prepare_key); + +/** + * qcom_ice_import_key() - Import a raw key for inline encryption + * @imp_key: raw key that has to be imported + * @imp_key_size: size of the imported key + * @lt_key: longterm wrapped key that is imported, which is + * BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE in size. + * + * Make a scm call into trustzone to import a raw key for storage encryption + * and generate a longterm wrapped key using hwkm. + * + * Return: lt wrapped key size on success; err on failure. + */ +int qcom_ice_import_key(struct qcom_ice *ice, const u8 *imp_key, size_t imp_key_size, + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]) +{ + size_t wk_size = QCOM_ICE_HWKM_WRAPPED_KEY_SIZE(ice->hwkm_version); + + if (!qcom_scm_import_ice_key(imp_key, imp_key_size, lt_key, wk_size)) + return wk_size; + return 0; +} +EXPORT_SYMBOL_GPL(qcom_ice_import_key); + 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 dabe0d3a1fd0..dcf277d196ff 100644 --- a/include/soc/qcom/ice.h +++ b/include/soc/qcom/ice.h @@ -39,5 +39,13 @@ 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]); +int qcom_ice_generate_key(struct qcom_ice *ice, + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); +int qcom_ice_prepare_key(struct qcom_ice *ice, + const u8 *lt_key, size_t lt_key_size, + u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); +int qcom_ice_import_key(struct qcom_ice *ice, + const u8 *imp_key, size_t imp_key_size, + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]); struct qcom_ice *of_qcom_ice_get(struct device *dev); #endif /* __QCOM_ICE_H__ */