Message ID | 20240708235330.103590-6-ebiggers@kernel.org (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | Basic inline encryption support for ufs-exynos | expand |
> -----Original Message----- > From: Eric Biggers <ebiggers@kernel.org> > Sent: Tuesday, July 9, 2024 5:23 AM > To: linux-scsi@vger.kernel.org > Cc: linux-samsung-soc@vger.kernel.org; linux-fscrypt@vger.kernel.org; Alim > Akhtar <alim.akhtar@samsung.com>; Avri Altman <avri.altman@wdc.com>; > Bart Van Assche <bvanassche@acm.org>; Martin K . Petersen > <martin.petersen@oracle.com>; Peter Griffin <peter.griffin@linaro.org>; > André Draszik <andre.draszik@linaro.org>; William McVicker > <willmcvicker@google.com> > Subject: [PATCH v3 5/6] scsi: ufs: core: Add UFSHCD_QUIRK_KEYS_IN_PRDT > > From: Eric Biggers <ebiggers@google.com> > > Since the nonstandard inline encryption support on Exynos SoCs requires > that raw cryptographic keys be copied into the PRDT, it is desirable to zeroize > those keys after each request to keep them from being left in memory. > Therefore, add a quirk bit that enables the zeroization. > > We could instead do the zeroization unconditionally. However, using a quirk > bit avoids adding the zeroization overhead to standard devices. > > Reviewed-by: Bart Van Assche <bvanassche@acm.org> > Reviewed-by: Peter Griffin <peter.griffin@linaro.org> > Signed-off-by: Eric Biggers <ebiggers@google.com> > --- Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
diff --git a/drivers/ufs/core/ufshcd-crypto.h b/drivers/ufs/core/ufshcd-crypto.h index 3eb8df42e194..89bb97c14c15 100644 --- a/drivers/ufs/core/ufshcd-crypto.h +++ b/drivers/ufs/core/ufshcd-crypto.h @@ -48,10 +48,24 @@ static inline int ufshcd_crypto_fill_prdt(struct ufs_hba *hba, lrbp->ucd_prdt_ptr, scsi_sg_count(cmd)); return 0; } +static inline void ufshcd_crypto_clear_prdt(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp) +{ + if (!(hba->quirks & UFSHCD_QUIRK_KEYS_IN_PRDT)) + return; + + if (!(scsi_cmd_to_rq(lrbp->cmd)->crypt_ctx)) + return; + + /* Zeroize the PRDT because it can contain cryptographic keys. */ + memzero_explicit(lrbp->ucd_prdt_ptr, + ufshcd_sg_entry_size(hba) * scsi_sg_count(lrbp->cmd)); +} + bool ufshcd_crypto_enable(struct ufs_hba *hba); int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba); void ufshcd_init_crypto(struct ufs_hba *hba); @@ -71,10 +85,13 @@ static inline int ufshcd_crypto_fill_prdt(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { return 0; } +static inline void ufshcd_crypto_clear_prdt(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp) { } + static inline bool ufshcd_crypto_enable(struct ufs_hba *hba) { return false; } diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 744af9708e51..958cc73d8e79 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -5472,10 +5472,11 @@ void ufshcd_release_scsi_cmd(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { struct scsi_cmnd *cmd = lrbp->cmd; scsi_dma_unmap(cmd); + ufshcd_crypto_clear_prdt(hba, lrbp); ufshcd_release(hba); ufshcd_clk_scaling_update_busy(hba); } /** diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 59aa6c831a41..fe0073b37224 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -661,10 +661,18 @@ enum ufshcd_quirks { * This quirk needs to be enabled if the host controller supports inline * encryption but does not support the CRYPTO_GENERAL_ENABLE bit, i.e. * host controller initialization fails if that bit is set. */ UFSHCD_QUIRK_BROKEN_CRYPTO_ENABLE = 1 << 23, + + /* + * This quirk needs to be enabled if the host controller driver copies + * cryptographic keys into the PRDT in order to send them to hardware, + * and therefore the PRDT should be zeroized after each request (as per + * the standard best practice for managing keys). + */ + UFSHCD_QUIRK_KEYS_IN_PRDT = 1 << 24, }; enum ufshcd_caps { /* Allow dynamic clk gating */ UFSHCD_CAP_CLK_GATING = 1 << 0,