]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
scsi: ufs: core: Add UFSHCD_QUIRK_KEYS_IN_PRDT
authorEric Biggers <ebiggers@google.com>
Mon, 8 Jul 2024 23:53:29 +0000 (16:53 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 11 Jul 2024 02:32:30 +0000 (22:32 -0400)
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>
Link: https://lore.kernel.org/r/20240708235330.103590-6-ebiggers@kernel.org
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/ufs/core/ufshcd-crypto.h
drivers/ufs/core/ufshcd.c
include/ufs/ufshcd.h

index 3eb8df42e1942e2b46c2578ef2f74c1d685b61d1..89bb97c14c15b6c14a5ff3a9bdeeb1ac2c81eeb7 100644 (file)
@@ -50,6 +50,20 @@ static inline int ufshcd_crypto_fill_prdt(struct ufs_hba *hba,
        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);
@@ -73,6 +87,9 @@ static inline int ufshcd_crypto_fill_prdt(struct ufs_hba *hba,
        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;
index 06619682087c3dfef7058e5748df1a1420242ed7..7c5ad68e49f20de8267f6cf526be6ddba7c8b91c 100644 (file)
@@ -5479,6 +5479,7 @@ void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
        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);
 }
index fb791d1a6d00d71953840d72b56df376e75830fc..80accfbe48aaca3551521bad6ed6e72002b68020 100644 (file)
@@ -665,6 +665,14 @@ enum ufshcd_quirks {
         * 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 {