Skip to content

Commit

Permalink
Merge patch series "Basic inline encryption support for ufs-exynos"
Browse files Browse the repository at this point in the history
Eric Biggers <ebiggers@kernel.org> says:

Add support for Flash Memory Protector (FMP), which is the inline
encryption hardware on Exynos and Exynos-based SoCs.

Specifically, add support for the "traditional FMP mode" that works on
many Exynos-based SoCs including gs101.  This is the mode that uses
"software keys" and is compatible with the upstream kernel's existing
inline encryption framework in the block and filesystem layers.  I
plan to add support for the wrapped key support on gs101 at a later
time.

Tested on gs101 (specifically Pixel 6) by running the 'encrypt' group
of xfstests on a filesystem mounted with the 'inlinecrypt' mount
option.

This patchset applies to v6.10-rc6, and it has no prerequisites that
aren't already upstream.

Link: https://lore.kernel.org/r/20240708235330.103590-1-ebiggers@kernel.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Martin K. Petersen committed Jul 11, 2024
2 parents e30618a + c96499f commit af8e69e
Show file tree
Hide file tree
Showing 5 changed files with 320 additions and 21 deletions.
34 changes: 20 additions & 14 deletions drivers/ufs/core/ufshcd-crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,12 @@ static int ufshcd_crypto_keyslot_program(struct blk_crypto_profile *profile,
return err;
}

static int ufshcd_clear_keyslot(struct ufs_hba *hba, int slot)
static int ufshcd_crypto_keyslot_evict(struct blk_crypto_profile *profile,
const struct blk_crypto_key *key,
unsigned int slot)
{
struct ufs_hba *hba =
container_of(profile, struct ufs_hba, crypto_profile);
/*
* Clear the crypto cfg on the device. Clearing CFGE
* might not be sufficient, so just clear the entire cfg.
Expand All @@ -106,23 +110,21 @@ static int ufshcd_clear_keyslot(struct ufs_hba *hba, int slot)
return ufshcd_program_key(hba, &cfg, slot);
}

static int ufshcd_crypto_keyslot_evict(struct blk_crypto_profile *profile,
const struct blk_crypto_key *key,
unsigned int slot)
{
struct ufs_hba *hba =
container_of(profile, struct ufs_hba, crypto_profile);

return ufshcd_clear_keyslot(hba, slot);
}

/*
* Reprogram the keyslots if needed, and return true if CRYPTO_GENERAL_ENABLE
* should be used in the host controller initialization sequence.
*/
bool ufshcd_crypto_enable(struct ufs_hba *hba)
{
if (!(hba->caps & UFSHCD_CAP_CRYPTO))
return false;

/* Reset might clear all keys, so reprogram all the keys. */
blk_crypto_reprogram_all_keys(&hba->crypto_profile);

if (hba->quirks & UFSHCD_QUIRK_BROKEN_CRYPTO_ENABLE)
return false;

return true;
}

Expand Down Expand Up @@ -159,6 +161,9 @@ int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba)
int err = 0;
enum blk_crypto_mode_num blk_mode_num;

if (hba->quirks & UFSHCD_QUIRK_CUSTOM_CRYPTO_PROFILE)
return 0;

/*
* Don't use crypto if either the hardware doesn't advertise the
* standard crypto capability bit *or* if the vendor specific driver
Expand Down Expand Up @@ -228,9 +233,10 @@ void ufshcd_init_crypto(struct ufs_hba *hba)
if (!(hba->caps & UFSHCD_CAP_CRYPTO))
return;

/* Clear all keyslots - the number of keyslots is (CFGC + 1) */
for (slot = 0; slot < hba->crypto_capabilities.config_count + 1; slot++)
ufshcd_clear_keyslot(hba, slot);
/* Clear all keyslots. */
for (slot = 0; slot < hba->crypto_profile.num_slots; slot++)
hba->crypto_profile.ll_ops.keyslot_evict(&hba->crypto_profile,
NULL, slot);
}

void ufshcd_crypto_register(struct ufs_hba *hba, struct request_queue *q)
Expand Down
36 changes: 36 additions & 0 deletions drivers/ufs/core/ufshcd-crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,33 @@ ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp,
h->dunu = cpu_to_le32(upper_32_bits(lrbp->data_unit_num));
}

static inline int ufshcd_crypto_fill_prdt(struct ufs_hba *hba,
struct ufshcd_lrb *lrbp)
{
struct scsi_cmnd *cmd = lrbp->cmd;
const struct bio_crypt_ctx *crypt_ctx = scsi_cmd_to_rq(cmd)->crypt_ctx;

if (crypt_ctx && hba->vops && hba->vops->fill_crypto_prdt)
return hba->vops->fill_crypto_prdt(hba, crypt_ctx,
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);
Expand All @@ -54,6 +81,15 @@ static inline void
ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp,
struct request_desc_header *h) { }

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;
Expand Down
3 changes: 2 additions & 1 deletion drivers/ufs/core/ufshcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2640,7 +2640,7 @@ static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)

ufshcd_sgl_to_prdt(hba, lrbp, sg_segments, scsi_sglist(cmd));

return 0;
return ufshcd_crypto_fill_prdt(hba, lrbp);
}

/**
Expand Down Expand Up @@ -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);
}
Expand Down
Loading

0 comments on commit af8e69e

Please sign in to comment.