Linux 6.9-rc1
[linux-2.6-microblaze.git] / block / blk-crypto.c
index a496aae..4d760b0 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/blkdev.h>
 #include <linux/blk-crypto-profile.h>
 #include <linux/module.h>
+#include <linux/ratelimit.h>
 #include <linux/slab.h>
 
 #include "blk-crypto-internal.h"
@@ -36,6 +37,12 @@ const struct blk_crypto_mode blk_crypto_modes[] = {
                .keysize = 32,
                .ivsize = 32,
        },
+       [BLK_ENCRYPTION_MODE_SM4_XTS] = {
+               .name = "SM4-XTS",
+               .cipher_str = "xts(sm4)",
+               .keysize = 32,
+               .ivsize = 16,
+       },
 };
 
 /*
@@ -218,27 +225,27 @@ static bool bio_crypt_check_alignment(struct bio *bio)
        return true;
 }
 
-blk_status_t __blk_crypto_init_request(struct request *rq)
+blk_status_t __blk_crypto_rq_get_keyslot(struct request *rq)
 {
        return blk_crypto_get_keyslot(rq->q->crypto_profile,
                                      rq->crypt_ctx->bc_key,
                                      &rq->crypt_keyslot);
 }
 
-/**
- * __blk_crypto_free_request - Uninitialize the crypto fields of a request.
- *
- * @rq: The request whose crypto fields to uninitialize.
- *
- * Completely uninitializes the crypto fields of a request. If a keyslot has
- * been programmed into some inline encryption hardware, that keyslot is
- * released. The rq->crypt_ctx is also freed.
- */
-void __blk_crypto_free_request(struct request *rq)
+void __blk_crypto_rq_put_keyslot(struct request *rq)
 {
        blk_crypto_put_keyslot(rq->crypt_keyslot);
+       rq->crypt_keyslot = NULL;
+}
+
+void __blk_crypto_free_request(struct request *rq)
+{
+       /* The keyslot, if one was needed, should have been released earlier. */
+       if (WARN_ON_ONCE(rq->crypt_keyslot))
+               __blk_crypto_rq_put_keyslot(rq);
+
        mempool_free(rq->crypt_ctx, bio_crypt_ctx_pool);
-       blk_crypto_rq_set_defaults(rq);
+       rq->crypt_ctx = NULL;
 }
 
 /**
@@ -267,7 +274,6 @@ bool __blk_crypto_bio_prep(struct bio **bio_ptr)
 {
        struct bio *bio = *bio_ptr;
        const struct blk_crypto_key *bc_key = bio->bi_crypt_context->bc_key;
-       struct blk_crypto_profile *profile;
 
        /* Error if bio has no data. */
        if (WARN_ON_ONCE(!bio_has_data(bio))) {
@@ -284,10 +290,9 @@ bool __blk_crypto_bio_prep(struct bio **bio_ptr)
         * Success if device supports the encryption context, or if we succeeded
         * in falling back to the crypto API.
         */
-       profile = bdev_get_queue(bio->bi_bdev)->crypto_profile;
-       if (__blk_crypto_cfg_supported(profile, &bc_key->crypto_cfg))
+       if (blk_crypto_config_supported_natively(bio->bi_bdev,
+                                                &bc_key->crypto_cfg))
                return true;
-
        if (blk_crypto_fallback_bio_prep(bio_ptr))
                return true;
 fail:
@@ -352,22 +357,29 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key,
        return 0;
 }
 
+bool blk_crypto_config_supported_natively(struct block_device *bdev,
+                                         const struct blk_crypto_config *cfg)
+{
+       return __blk_crypto_cfg_supported(bdev_get_queue(bdev)->crypto_profile,
+                                         cfg);
+}
+
 /*
  * Check if bios with @cfg can be en/decrypted by blk-crypto (i.e. either the
- * request queue it's submitted to supports inline crypto, or the
+ * block_device it's submitted to supports inline crypto, or the
  * blk-crypto-fallback is enabled and supports the cfg).
  */
-bool blk_crypto_config_supported(struct request_queue *q,
+bool blk_crypto_config_supported(struct block_device *bdev,
                                 const struct blk_crypto_config *cfg)
 {
        return IS_ENABLED(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) ||
-              __blk_crypto_cfg_supported(q->crypto_profile, cfg);
+              blk_crypto_config_supported_natively(bdev, cfg);
 }
 
 /**
  * blk_crypto_start_using_key() - Start using a blk_crypto_key on a device
+ * @bdev: block device to operate on
  * @key: A key to use on the device
- * @q: the request queue for the device
  *
  * Upper layers must call this function to ensure that either the hardware
  * supports the key's crypto settings, or the crypto API fallback has transforms
@@ -379,37 +391,48 @@ bool blk_crypto_config_supported(struct request_queue *q,
  *        blk-crypto-fallback is either disabled or the needed algorithm
  *        is disabled in the crypto API; or another -errno code.
  */
-int blk_crypto_start_using_key(const struct blk_crypto_key *key,
-                              struct request_queue *q)
+int blk_crypto_start_using_key(struct block_device *bdev,
+                              const struct blk_crypto_key *key)
 {
-       if (__blk_crypto_cfg_supported(q->crypto_profile, &key->crypto_cfg))
+       if (blk_crypto_config_supported_natively(bdev, &key->crypto_cfg))
                return 0;
        return blk_crypto_fallback_start_using_mode(key->crypto_cfg.crypto_mode);
 }
 
 /**
- * blk_crypto_evict_key() - Evict a key from any inline encryption hardware
- *                         it may have been programmed into
- * @q: The request queue who's associated inline encryption hardware this key
- *     might have been programmed into
- * @key: The key to evict
+ * blk_crypto_evict_key() - Evict a blk_crypto_key from a block_device
+ * @bdev: a block_device on which I/O using the key may have been done
+ * @key: the key to evict
+ *
+ * For a given block_device, this function removes the given blk_crypto_key from
+ * the keyslot management structures and evicts it from any underlying hardware
+ * keyslot(s) or blk-crypto-fallback keyslot it may have been programmed into.
  *
- * Upper layers (filesystems) must call this function to ensure that a key is
- * evicted from any hardware that it might have been programmed into.  The key
- * must not be in use by any in-flight IO when this function is called.
+ * Upper layers must call this before freeing the blk_crypto_key.  It must be
+ * called for every block_device the key may have been used on.  The key must no
+ * longer be in use by any I/O when this function is called.
  *
- * Return: 0 on success or if the key wasn't in any keyslot; -errno on error.
+ * Context: May sleep.
  */
-int blk_crypto_evict_key(struct request_queue *q,
-                        const struct blk_crypto_key *key)
+void blk_crypto_evict_key(struct block_device *bdev,
+                         const struct blk_crypto_key *key)
 {
-       if (__blk_crypto_cfg_supported(q->crypto_profile, &key->crypto_cfg))
-               return __blk_crypto_evict_key(q->crypto_profile, key);
+       struct request_queue *q = bdev_get_queue(bdev);
+       int err;
 
+       if (blk_crypto_config_supported_natively(bdev, &key->crypto_cfg))
+               err = __blk_crypto_evict_key(q->crypto_profile, key);
+       else
+               err = blk_crypto_fallback_evict_key(key);
        /*
-        * If the request_queue didn't support the key, then blk-crypto-fallback
-        * may have been used, so try to evict the key from blk-crypto-fallback.
+        * An error can only occur here if the key failed to be evicted from a
+        * keyslot (due to a hardware or driver issue) or is allegedly still in
+        * use by I/O (due to a kernel bug).  Even in these cases, the key is
+        * still unlinked from the keyslot management structures, and the caller
+        * is allowed and expected to free it right away.  There's nothing
+        * callers can do to handle errors, so just log them and return void.
         */
-       return blk_crypto_fallback_evict_key(key);
+       if (err)
+               pr_warn_ratelimited("%pg: error %d evicting key\n", bdev, err);
 }
 EXPORT_SYMBOL_GPL(blk_crypto_evict_key);