Re: [PATCH v6 06/17] firmware: qcom: scm: add a call for deriving the software secret
From: Konrad Dybcio <konradybcio@kernel.org>
Date: 2024-09-09 11:23:53
Also in:
dm-devel, linux-arm-msm, linux-block, linux-fscrypt, linux-fsdevel, linux-mmc, linux-scsi, lkml
On 6.09.2024 8:07 PM, Bartosz Golaszewski wrote:
quoted hunk ↗ jump to hunk
From: Gaurav Kashyap <redacted> Inline storage encryption may require deriving a software secret from storage keys added to the kernel. For raw keys, this can be directly done in the kernel as keys are not encrypted in memory. However, hardware wrapped keys can only be unwrapped by the HW wrapping entity. In case of Qualcomm's wrapped key solution, this is done by the Hardware Key Manager (HWKM) from Trustzone. Add a new SCM call which provides a hook to the software secret crypto profile API provided by the block layer. Tested-by: Neil Armstrong <neil.armstrong@linaro.org> Signed-off-by: Gaurav Kashyap <redacted> Reviewed-by: Dmitry Baryshkov <redacted> Signed-off-by: Bartosz Golaszewski <redacted> --- drivers/firmware/qcom/qcom_scm.c | 65 ++++++++++++++++++++++++++++++++++ drivers/firmware/qcom/qcom_scm.h | 1 + include/linux/firmware/qcom/qcom_scm.h | 2 ++ 3 files changed, 68 insertions(+)diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 10986cb11ec0..ad3f9e9ed35d 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c@@ -1252,6 +1252,71 @@ 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, + }; + + int ret; + + void *wkey_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, + wkey_size, + GFP_KERNEL); + if (!wkey_buf) + return -ENOMEM; + + void *secret_buf __free(qcom_tzmem) = qcom_tzmem_alloc(__scm->mempool, + sw_secret_size, + GFP_KERNEL); + if (!secret_buf) { + ret = -ENOMEM; + goto out_free_wrapped; + } + + memcpy(wkey_buf, wkey, wkey_size); + desc.args[0] = qcom_tzmem_to_phys(wkey_buf); + desc.args[2] = qcom_tzmem_to_phys(secret_buf); + + 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); + +out_free_wrapped:
Is there a reason to zero out the buffer that's being zero-allocated? Konrad
+ memzero_explicit(wkey_buf, wkey_size);