RE: [PATCH v3 02/12] qcom_scm: scm call for deriving a software secret

[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:
> > Inline storage encryption requires deriving a sw secret from the
> > hardware wrapped keys. 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
> > (Hardware Key Manager) 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 . This can be invoked
> > by using the crypto profile APIs provided by the block layer.
> >
> > Signed-off-by: Gaurav Kashyap <quic_gaurkash@xxxxxxxxxxx>
> > ---
> >   drivers/firmware/qcom/qcom_scm.c       | 71
> ++++++++++++++++++++++++++
> >   drivers/firmware/qcom/qcom_scm.h       |  1 +
> >   include/linux/firmware/qcom/qcom_scm.h |  2 +
> >   3 files changed, 74 insertions(+)
> >
> > diff --git a/drivers/firmware/qcom/qcom_scm.c
> > b/drivers/firmware/qcom/qcom_scm.c
> > index 520de9b5633a..6dfb913f3e33 100644
> > --- a/drivers/firmware/qcom/qcom_scm.c
> > +++ b/drivers/firmware/qcom/qcom_scm.c
> > @@ -1214,6 +1214,77 @@ int qcom_scm_ice_set_key(u32 index, const u8
> *key, u32 key_size,
> >   }
> >   EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key);
> >
> > +/**
> > + * qcom_scm_derive_sw_secret() - Derive software secret from wrapped
> > +key
> > + * @wkey: the hardware wrapped key inaccessible to software
> > + * @wkey_size: size of the wrapped key
> > + * @sw_secret: the secret to be derived which is exactly the secret
> > +size
> > + * @sw_secret_size: size of the sw_secret
> > + *
> > + * Derive a software secret from a hardware wrapped key for software
> > +crypto
> > + * operations.
> > + * For wrapped keys, the key needs to be unwrapped, in order to
> > +derive a
> > + * software secret, which can be done in the hardware from a secure
> > +execution
> > + * environment.
> > + *
> > + * 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 *wkey, size_t wkey_size,
> > +			      u8 *sw_secret, size_t sw_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_RW,
> > +					 QCOM_SCM_VAL, QCOM_SCM_RW,
> > +					 QCOM_SCM_VAL),
> > +		.args[1] = wkey_size,
> > +		.args[3] = sw_secret_size,
> > +		.owner = ARM_SMCCC_OWNER_SIP,
> > +	};
> > +
> > +	void *wkey_buf, *secret_buf;
> > +	dma_addr_t wkey_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().
> > +	 */
> > +	wkey_buf = dma_alloc_coherent(__scm->dev, wkey_size,
> &wkey_phys, GFP_KERNEL);
> > +	if (!wkey_buf)
> > +		return -ENOMEM;
> > +	secret_buf = dma_alloc_coherent(__scm->dev, sw_secret_size,
> &secret_phys, GFP_KERNEL);
> > +	if (!secret_buf) {
> > +		ret = -ENOMEM;
> > +		goto err_free_wrapped;
> > +	}
> > +
> > +	memcpy(wkey_buf, wkey, wkey_size);
> > +	desc.args[0] = wkey_phys;
> > +	desc.args[2] = secret_phys;
> > +
> > +	ret = qcom_scm_call(__scm->dev, &desc, NULL);
> > +	if (!ret)
> > +		memcpy(sw_secret, secret_buf, sw_secret_size);
> > +
> > +	memzero_explicit(secret_buf, sw_secret_size);
> > +
> > +	dma_free_coherent(__scm->dev, sw_secret_size, secret_buf,
> > +secret_phys);
> > +
> > +err_free_wrapped:
> > +	memzero_explicit(wkey_buf, wkey_size);
> In error handling case the operation is being performed on unallocated
> memory.

The flow comes here only when secret_buf allocation fails.
And at that point, wkey_buf is already allocated.
Wkey_buf failure errors out directly after allocation failure.

> > +
> > +	dma_free_coherent(__scm->dev, wkey_size, wkey_buf,
> wkey_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/qcom_scm.h
> > b/drivers/firmware/qcom/qcom_scm.h
> > index 4532907e8489..c75456aa6ac5 100644
> > --- a/drivers/firmware/qcom/qcom_scm.h
> > +++ b/drivers/firmware/qcom/qcom_scm.h
> > @@ -121,6 +121,7 @@ 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/firmware/qcom/qcom_scm.h
> > b/include/linux/firmware/qcom/qcom_scm.h
> > index ccaf28846054..c65f2d61492d 100644
> > --- a/include/linux/firmware/qcom/qcom_scm.h
> > +++ b/include/linux/firmware/qcom/qcom_scm.h
> > @@ -103,6 +103,8 @@ bool qcom_scm_ice_available(void);
> >   int qcom_scm_ice_invalidate_key(u32 index);
> >   int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
> >   			 enum qcom_scm_ice_cipher cipher, u32
> data_unit_size);
> > +int qcom_scm_derive_sw_secret(const u8 *wkey, size_t wkey_size,
> > +			      u8 *sw_secret, size_t sw_secret_size);
> >
> >   bool qcom_scm_hdcp_available(void);
> >   int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
> > u32 *resp);




[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