1. Add a new quirk in UFS when wrapped keys are supported. Since
   wrapped keys are not part of the UFS spec, treat it as a
   supported quirk.
2. Add derive_sw_secret crypto profile op implementation in ufshcd
   crypto.

Signed-off-by: Gaurav Kashyap <quic_gaurk...@quicinc.com>
---
 drivers/ufs/core/ufshcd-crypto.c | 39 +++++++++++++++++++++++++-------
 include/ufs/ufshcd.h             | 10 ++++++++
 2 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/drivers/ufs/core/ufshcd-crypto.c b/drivers/ufs/core/ufshcd-crypto.c
index 34537cbac622..3edbca87c322 100644
--- a/drivers/ufs/core/ufshcd-crypto.c
+++ b/drivers/ufs/core/ufshcd-crypto.c
@@ -81,13 +81,15 @@ static int ufshcd_crypto_keyslot_program(struct 
blk_crypto_profile *profile,
        cfg.crypto_cap_idx = cap_idx;
        cfg.config_enable = UFS_CRYPTO_CONFIGURATION_ENABLE;
 
-       if (ccap_array[cap_idx].algorithm_id == UFS_CRYPTO_ALG_AES_XTS) {
-               /* In XTS mode, the blk_crypto_key's size is already doubled */
-               memcpy(cfg.crypto_key, key->raw, key->size/2);
-               memcpy(cfg.crypto_key + UFS_CRYPTO_KEY_MAX_SIZE/2,
-                      key->raw + key->size/2, key->size/2);
-       } else {
-               memcpy(cfg.crypto_key, key->raw, key->size);
+       if (key->crypto_cfg.key_type != BLK_CRYPTO_KEY_TYPE_HW_WRAPPED) {
+               if (ccap_array[cap_idx].algorithm_id == UFS_CRYPTO_ALG_AES_XTS) 
{
+                       /* In XTS mode, the blk_crypto_key's size is already 
doubled */
+                       memcpy(cfg.crypto_key, key->raw, key->size / 2);
+                       memcpy(cfg.crypto_key + UFS_CRYPTO_KEY_MAX_SIZE / 2,
+                              key->raw + key->size / 2, key->size / 2);
+               } else {
+                       memcpy(cfg.crypto_key, key->raw, key->size);
+               }
        }
 
        err = ufshcd_program_key(hba, key, &cfg, slot);
@@ -127,9 +129,24 @@ bool ufshcd_crypto_enable(struct ufs_hba *hba)
        return true;
 }
 
+static int ufshcd_crypto_derive_sw_secret(struct blk_crypto_profile *profile,
+                                         const u8 wkey[], size_t wkey_size,
+                                         u8 
sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
+{
+       struct ufs_hba *hba =
+               container_of(profile, struct ufs_hba, crypto_profile);
+
+       if (hba->vops && hba->vops->derive_sw_secret)
+               return  hba->vops->derive_sw_secret(hba, wkey, wkey_size,
+                                                   sw_secret);
+
+       return -EOPNOTSUPP;
+}
+
 static const struct blk_crypto_ll_ops ufshcd_crypto_ops = {
        .keyslot_program        = ufshcd_crypto_keyslot_program,
        .keyslot_evict          = ufshcd_crypto_keyslot_evict,
+       .derive_sw_secret       = ufshcd_crypto_derive_sw_secret,
 };
 
 static enum blk_crypto_mode_num
@@ -191,7 +208,13 @@ int ufshcd_hba_init_crypto_capabilities(struct ufs_hba 
*hba)
        hba->crypto_profile.ll_ops = ufshcd_crypto_ops;
        /* UFS only supports 8 bytes for any DUN */
        hba->crypto_profile.max_dun_bytes_supported = 8;
-       hba->crypto_profile.key_types_supported = BLK_CRYPTO_KEY_TYPE_STANDARD;
+       if (hba->quirks & UFSHCD_QUIRK_USES_WRAPPED_CRYPTO_KEYS)
+               hba->crypto_profile.key_types_supported =
+                               BLK_CRYPTO_KEY_TYPE_HW_WRAPPED;
+       else
+               hba->crypto_profile.key_types_supported =
+                               BLK_CRYPTO_KEY_TYPE_STANDARD;
+
        hba->crypto_profile.dev = hba->dev;
 
        /*
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index e1184ccc0508..86677788b5bd 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -320,6 +320,7 @@ struct ufs_pwr_mode_info {
  * @device_reset: called to issue a reset pulse on the UFS device
  * @config_scaling_param: called to configure clock scaling parameters
  * @program_key: program or evict an inline encryption key
+ * @derive_sw_secret: derive sw secret from a wrapped key
  * @event_notify: called to notify important events
  * @reinit_notify: called to notify reinit of UFSHCD during max gear switch
  * @mcq_config_resource: called to configure MCQ platform resources
@@ -364,6 +365,9 @@ struct ufs_hba_variant_ops {
        int     (*program_key)(struct ufs_hba *hba,
                               const struct blk_crypto_key *bkey,
                               const union ufs_crypto_cfg_entry *cfg, int slot);
+       int     (*derive_sw_secret)(struct ufs_hba *hba, const u8 wkey[],
+                                   unsigned int wkey_size,
+                                   u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]);
        void    (*event_notify)(struct ufs_hba *hba,
                                enum ufs_event_type evt, void *data);
        void    (*reinit_notify)(struct ufs_hba *);
@@ -643,6 +647,12 @@ enum ufshcd_quirks {
         * thus need this quirk to skip related flow.
         */
        UFSHCD_QUIRK_MCQ_BROKEN_RTC                     = 1 << 21,
+
+       /*
+        * This quirk indicates that UFS will be using HW wrapped keys
+        * when using inline encryption.
+        */
+       UFSHCD_QUIRK_USES_WRAPPED_CRYPTO_KEYS           = 1 << 22,
 };
 
 enum ufshcd_caps {
-- 
2.25.1


Reply via email to