162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2019 Google LLC
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci/*
762306a36Sopenharmony_ci * Refer to Documentation/block/inline-encryption.rst for detailed explanation.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#define pr_fmt(fmt) "blk-crypto-fallback: " fmt
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <crypto/skcipher.h>
1362306a36Sopenharmony_ci#include <linux/blk-crypto.h>
1462306a36Sopenharmony_ci#include <linux/blk-crypto-profile.h>
1562306a36Sopenharmony_ci#include <linux/blkdev.h>
1662306a36Sopenharmony_ci#include <linux/crypto.h>
1762306a36Sopenharmony_ci#include <linux/mempool.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <linux/random.h>
2062306a36Sopenharmony_ci#include <linux/scatterlist.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include "blk-cgroup.h"
2362306a36Sopenharmony_ci#include "blk-crypto-internal.h"
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic unsigned int num_prealloc_bounce_pg = 32;
2662306a36Sopenharmony_cimodule_param(num_prealloc_bounce_pg, uint, 0);
2762306a36Sopenharmony_ciMODULE_PARM_DESC(num_prealloc_bounce_pg,
2862306a36Sopenharmony_ci		 "Number of preallocated bounce pages for the blk-crypto crypto API fallback");
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic unsigned int blk_crypto_num_keyslots = 100;
3162306a36Sopenharmony_cimodule_param_named(num_keyslots, blk_crypto_num_keyslots, uint, 0);
3262306a36Sopenharmony_ciMODULE_PARM_DESC(num_keyslots,
3362306a36Sopenharmony_ci		 "Number of keyslots for the blk-crypto crypto API fallback");
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic unsigned int num_prealloc_fallback_crypt_ctxs = 128;
3662306a36Sopenharmony_cimodule_param(num_prealloc_fallback_crypt_ctxs, uint, 0);
3762306a36Sopenharmony_ciMODULE_PARM_DESC(num_prealloc_crypt_fallback_ctxs,
3862306a36Sopenharmony_ci		 "Number of preallocated bio fallback crypto contexts for blk-crypto to use during crypto API fallback");
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistruct bio_fallback_crypt_ctx {
4162306a36Sopenharmony_ci	struct bio_crypt_ctx crypt_ctx;
4262306a36Sopenharmony_ci	/*
4362306a36Sopenharmony_ci	 * Copy of the bvec_iter when this bio was submitted.
4462306a36Sopenharmony_ci	 * We only want to en/decrypt the part of the bio as described by the
4562306a36Sopenharmony_ci	 * bvec_iter upon submission because bio might be split before being
4662306a36Sopenharmony_ci	 * resubmitted
4762306a36Sopenharmony_ci	 */
4862306a36Sopenharmony_ci	struct bvec_iter crypt_iter;
4962306a36Sopenharmony_ci	union {
5062306a36Sopenharmony_ci		struct {
5162306a36Sopenharmony_ci			struct work_struct work;
5262306a36Sopenharmony_ci			struct bio *bio;
5362306a36Sopenharmony_ci		};
5462306a36Sopenharmony_ci		struct {
5562306a36Sopenharmony_ci			void *bi_private_orig;
5662306a36Sopenharmony_ci			bio_end_io_t *bi_end_io_orig;
5762306a36Sopenharmony_ci		};
5862306a36Sopenharmony_ci	};
5962306a36Sopenharmony_ci};
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic struct kmem_cache *bio_fallback_crypt_ctx_cache;
6262306a36Sopenharmony_cistatic mempool_t *bio_fallback_crypt_ctx_pool;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/*
6562306a36Sopenharmony_ci * Allocating a crypto tfm during I/O can deadlock, so we have to preallocate
6662306a36Sopenharmony_ci * all of a mode's tfms when that mode starts being used. Since each mode may
6762306a36Sopenharmony_ci * need all the keyslots at some point, each mode needs its own tfm for each
6862306a36Sopenharmony_ci * keyslot; thus, a keyslot may contain tfms for multiple modes.  However, to
6962306a36Sopenharmony_ci * match the behavior of real inline encryption hardware (which only supports a
7062306a36Sopenharmony_ci * single encryption context per keyslot), we only allow one tfm per keyslot to
7162306a36Sopenharmony_ci * be used at a time - the rest of the unused tfms have their keys cleared.
7262306a36Sopenharmony_ci */
7362306a36Sopenharmony_cistatic DEFINE_MUTEX(tfms_init_lock);
7462306a36Sopenharmony_cistatic bool tfms_inited[BLK_ENCRYPTION_MODE_MAX];
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic struct blk_crypto_fallback_keyslot {
7762306a36Sopenharmony_ci	enum blk_crypto_mode_num crypto_mode;
7862306a36Sopenharmony_ci	struct crypto_skcipher *tfms[BLK_ENCRYPTION_MODE_MAX];
7962306a36Sopenharmony_ci} *blk_crypto_keyslots;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic struct blk_crypto_profile *blk_crypto_fallback_profile;
8262306a36Sopenharmony_cistatic struct workqueue_struct *blk_crypto_wq;
8362306a36Sopenharmony_cistatic mempool_t *blk_crypto_bounce_page_pool;
8462306a36Sopenharmony_cistatic struct bio_set crypto_bio_split;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/*
8762306a36Sopenharmony_ci * This is the key we set when evicting a keyslot. This *should* be the all 0's
8862306a36Sopenharmony_ci * key, but AES-XTS rejects that key, so we use some random bytes instead.
8962306a36Sopenharmony_ci */
9062306a36Sopenharmony_cistatic u8 blank_key[BLK_CRYPTO_MAX_KEY_SIZE];
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic void blk_crypto_fallback_evict_keyslot(unsigned int slot)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	struct blk_crypto_fallback_keyslot *slotp = &blk_crypto_keyslots[slot];
9562306a36Sopenharmony_ci	enum blk_crypto_mode_num crypto_mode = slotp->crypto_mode;
9662306a36Sopenharmony_ci	int err;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	WARN_ON(slotp->crypto_mode == BLK_ENCRYPTION_MODE_INVALID);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	/* Clear the key in the skcipher */
10162306a36Sopenharmony_ci	err = crypto_skcipher_setkey(slotp->tfms[crypto_mode], blank_key,
10262306a36Sopenharmony_ci				     blk_crypto_modes[crypto_mode].keysize);
10362306a36Sopenharmony_ci	WARN_ON(err);
10462306a36Sopenharmony_ci	slotp->crypto_mode = BLK_ENCRYPTION_MODE_INVALID;
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic int
10862306a36Sopenharmony_ciblk_crypto_fallback_keyslot_program(struct blk_crypto_profile *profile,
10962306a36Sopenharmony_ci				    const struct blk_crypto_key *key,
11062306a36Sopenharmony_ci				    unsigned int slot)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	struct blk_crypto_fallback_keyslot *slotp = &blk_crypto_keyslots[slot];
11362306a36Sopenharmony_ci	const enum blk_crypto_mode_num crypto_mode =
11462306a36Sopenharmony_ci						key->crypto_cfg.crypto_mode;
11562306a36Sopenharmony_ci	int err;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	if (crypto_mode != slotp->crypto_mode &&
11862306a36Sopenharmony_ci	    slotp->crypto_mode != BLK_ENCRYPTION_MODE_INVALID)
11962306a36Sopenharmony_ci		blk_crypto_fallback_evict_keyslot(slot);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	slotp->crypto_mode = crypto_mode;
12262306a36Sopenharmony_ci	err = crypto_skcipher_setkey(slotp->tfms[crypto_mode], key->raw,
12362306a36Sopenharmony_ci				     key->size);
12462306a36Sopenharmony_ci	if (err) {
12562306a36Sopenharmony_ci		blk_crypto_fallback_evict_keyslot(slot);
12662306a36Sopenharmony_ci		return err;
12762306a36Sopenharmony_ci	}
12862306a36Sopenharmony_ci	return 0;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic int blk_crypto_fallback_keyslot_evict(struct blk_crypto_profile *profile,
13262306a36Sopenharmony_ci					     const struct blk_crypto_key *key,
13362306a36Sopenharmony_ci					     unsigned int slot)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	blk_crypto_fallback_evict_keyslot(slot);
13662306a36Sopenharmony_ci	return 0;
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic const struct blk_crypto_ll_ops blk_crypto_fallback_ll_ops = {
14062306a36Sopenharmony_ci	.keyslot_program        = blk_crypto_fallback_keyslot_program,
14162306a36Sopenharmony_ci	.keyslot_evict          = blk_crypto_fallback_keyslot_evict,
14262306a36Sopenharmony_ci};
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic void blk_crypto_fallback_encrypt_endio(struct bio *enc_bio)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	struct bio *src_bio = enc_bio->bi_private;
14762306a36Sopenharmony_ci	int i;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	for (i = 0; i < enc_bio->bi_vcnt; i++)
15062306a36Sopenharmony_ci		mempool_free(enc_bio->bi_io_vec[i].bv_page,
15162306a36Sopenharmony_ci			     blk_crypto_bounce_page_pool);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	src_bio->bi_status = enc_bio->bi_status;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	bio_uninit(enc_bio);
15662306a36Sopenharmony_ci	kfree(enc_bio);
15762306a36Sopenharmony_ci	bio_endio(src_bio);
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic struct bio *blk_crypto_fallback_clone_bio(struct bio *bio_src)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	unsigned int nr_segs = bio_segments(bio_src);
16362306a36Sopenharmony_ci	struct bvec_iter iter;
16462306a36Sopenharmony_ci	struct bio_vec bv;
16562306a36Sopenharmony_ci	struct bio *bio;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	bio = bio_kmalloc(nr_segs, GFP_NOIO);
16862306a36Sopenharmony_ci	if (!bio)
16962306a36Sopenharmony_ci		return NULL;
17062306a36Sopenharmony_ci	bio_init(bio, bio_src->bi_bdev, bio->bi_inline_vecs, nr_segs,
17162306a36Sopenharmony_ci		 bio_src->bi_opf);
17262306a36Sopenharmony_ci	if (bio_flagged(bio_src, BIO_REMAPPED))
17362306a36Sopenharmony_ci		bio_set_flag(bio, BIO_REMAPPED);
17462306a36Sopenharmony_ci	bio->bi_ioprio		= bio_src->bi_ioprio;
17562306a36Sopenharmony_ci	bio->bi_iter.bi_sector	= bio_src->bi_iter.bi_sector;
17662306a36Sopenharmony_ci	bio->bi_iter.bi_size	= bio_src->bi_iter.bi_size;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	bio_for_each_segment(bv, bio_src, iter)
17962306a36Sopenharmony_ci		bio->bi_io_vec[bio->bi_vcnt++] = bv;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	bio_clone_blkg_association(bio, bio_src);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	return bio;
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic bool
18762306a36Sopenharmony_ciblk_crypto_fallback_alloc_cipher_req(struct blk_crypto_keyslot *slot,
18862306a36Sopenharmony_ci				     struct skcipher_request **ciph_req_ret,
18962306a36Sopenharmony_ci				     struct crypto_wait *wait)
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci	struct skcipher_request *ciph_req;
19262306a36Sopenharmony_ci	const struct blk_crypto_fallback_keyslot *slotp;
19362306a36Sopenharmony_ci	int keyslot_idx = blk_crypto_keyslot_index(slot);
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	slotp = &blk_crypto_keyslots[keyslot_idx];
19662306a36Sopenharmony_ci	ciph_req = skcipher_request_alloc(slotp->tfms[slotp->crypto_mode],
19762306a36Sopenharmony_ci					  GFP_NOIO);
19862306a36Sopenharmony_ci	if (!ciph_req)
19962306a36Sopenharmony_ci		return false;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	skcipher_request_set_callback(ciph_req,
20262306a36Sopenharmony_ci				      CRYPTO_TFM_REQ_MAY_BACKLOG |
20362306a36Sopenharmony_ci				      CRYPTO_TFM_REQ_MAY_SLEEP,
20462306a36Sopenharmony_ci				      crypto_req_done, wait);
20562306a36Sopenharmony_ci	*ciph_req_ret = ciph_req;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	return true;
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_cistatic bool blk_crypto_fallback_split_bio_if_needed(struct bio **bio_ptr)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	struct bio *bio = *bio_ptr;
21362306a36Sopenharmony_ci	unsigned int i = 0;
21462306a36Sopenharmony_ci	unsigned int num_sectors = 0;
21562306a36Sopenharmony_ci	struct bio_vec bv;
21662306a36Sopenharmony_ci	struct bvec_iter iter;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	bio_for_each_segment(bv, bio, iter) {
21962306a36Sopenharmony_ci		num_sectors += bv.bv_len >> SECTOR_SHIFT;
22062306a36Sopenharmony_ci		if (++i == BIO_MAX_VECS)
22162306a36Sopenharmony_ci			break;
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci	if (num_sectors < bio_sectors(bio)) {
22462306a36Sopenharmony_ci		struct bio *split_bio;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci		split_bio = bio_split(bio, num_sectors, GFP_NOIO,
22762306a36Sopenharmony_ci				      &crypto_bio_split);
22862306a36Sopenharmony_ci		if (!split_bio) {
22962306a36Sopenharmony_ci			bio->bi_status = BLK_STS_RESOURCE;
23062306a36Sopenharmony_ci			return false;
23162306a36Sopenharmony_ci		}
23262306a36Sopenharmony_ci		bio_chain(split_bio, bio);
23362306a36Sopenharmony_ci		submit_bio_noacct(bio);
23462306a36Sopenharmony_ci		*bio_ptr = split_bio;
23562306a36Sopenharmony_ci	}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	return true;
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ciunion blk_crypto_iv {
24162306a36Sopenharmony_ci	__le64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
24262306a36Sopenharmony_ci	u8 bytes[BLK_CRYPTO_MAX_IV_SIZE];
24362306a36Sopenharmony_ci};
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_cistatic void blk_crypto_dun_to_iv(const u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE],
24662306a36Sopenharmony_ci				 union blk_crypto_iv *iv)
24762306a36Sopenharmony_ci{
24862306a36Sopenharmony_ci	int i;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	for (i = 0; i < BLK_CRYPTO_DUN_ARRAY_SIZE; i++)
25162306a36Sopenharmony_ci		iv->dun[i] = cpu_to_le64(dun[i]);
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci/*
25562306a36Sopenharmony_ci * The crypto API fallback's encryption routine.
25662306a36Sopenharmony_ci * Allocate a bounce bio for encryption, encrypt the input bio using crypto API,
25762306a36Sopenharmony_ci * and replace *bio_ptr with the bounce bio. May split input bio if it's too
25862306a36Sopenharmony_ci * large. Returns true on success. Returns false and sets bio->bi_status on
25962306a36Sopenharmony_ci * error.
26062306a36Sopenharmony_ci */
26162306a36Sopenharmony_cistatic bool blk_crypto_fallback_encrypt_bio(struct bio **bio_ptr)
26262306a36Sopenharmony_ci{
26362306a36Sopenharmony_ci	struct bio *src_bio, *enc_bio;
26462306a36Sopenharmony_ci	struct bio_crypt_ctx *bc;
26562306a36Sopenharmony_ci	struct blk_crypto_keyslot *slot;
26662306a36Sopenharmony_ci	int data_unit_size;
26762306a36Sopenharmony_ci	struct skcipher_request *ciph_req = NULL;
26862306a36Sopenharmony_ci	DECLARE_CRYPTO_WAIT(wait);
26962306a36Sopenharmony_ci	u64 curr_dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
27062306a36Sopenharmony_ci	struct scatterlist src, dst;
27162306a36Sopenharmony_ci	union blk_crypto_iv iv;
27262306a36Sopenharmony_ci	unsigned int i, j;
27362306a36Sopenharmony_ci	bool ret = false;
27462306a36Sopenharmony_ci	blk_status_t blk_st;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	/* Split the bio if it's too big for single page bvec */
27762306a36Sopenharmony_ci	if (!blk_crypto_fallback_split_bio_if_needed(bio_ptr))
27862306a36Sopenharmony_ci		return false;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	src_bio = *bio_ptr;
28162306a36Sopenharmony_ci	bc = src_bio->bi_crypt_context;
28262306a36Sopenharmony_ci	data_unit_size = bc->bc_key->crypto_cfg.data_unit_size;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* Allocate bounce bio for encryption */
28562306a36Sopenharmony_ci	enc_bio = blk_crypto_fallback_clone_bio(src_bio);
28662306a36Sopenharmony_ci	if (!enc_bio) {
28762306a36Sopenharmony_ci		src_bio->bi_status = BLK_STS_RESOURCE;
28862306a36Sopenharmony_ci		return false;
28962306a36Sopenharmony_ci	}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	/*
29262306a36Sopenharmony_ci	 * Get a blk-crypto-fallback keyslot that contains a crypto_skcipher for
29362306a36Sopenharmony_ci	 * this bio's algorithm and key.
29462306a36Sopenharmony_ci	 */
29562306a36Sopenharmony_ci	blk_st = blk_crypto_get_keyslot(blk_crypto_fallback_profile,
29662306a36Sopenharmony_ci					bc->bc_key, &slot);
29762306a36Sopenharmony_ci	if (blk_st != BLK_STS_OK) {
29862306a36Sopenharmony_ci		src_bio->bi_status = blk_st;
29962306a36Sopenharmony_ci		goto out_put_enc_bio;
30062306a36Sopenharmony_ci	}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	/* and then allocate an skcipher_request for it */
30362306a36Sopenharmony_ci	if (!blk_crypto_fallback_alloc_cipher_req(slot, &ciph_req, &wait)) {
30462306a36Sopenharmony_ci		src_bio->bi_status = BLK_STS_RESOURCE;
30562306a36Sopenharmony_ci		goto out_release_keyslot;
30662306a36Sopenharmony_ci	}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	memcpy(curr_dun, bc->bc_dun, sizeof(curr_dun));
30962306a36Sopenharmony_ci	sg_init_table(&src, 1);
31062306a36Sopenharmony_ci	sg_init_table(&dst, 1);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	skcipher_request_set_crypt(ciph_req, &src, &dst, data_unit_size,
31362306a36Sopenharmony_ci				   iv.bytes);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	/* Encrypt each page in the bounce bio */
31662306a36Sopenharmony_ci	for (i = 0; i < enc_bio->bi_vcnt; i++) {
31762306a36Sopenharmony_ci		struct bio_vec *enc_bvec = &enc_bio->bi_io_vec[i];
31862306a36Sopenharmony_ci		struct page *plaintext_page = enc_bvec->bv_page;
31962306a36Sopenharmony_ci		struct page *ciphertext_page =
32062306a36Sopenharmony_ci			mempool_alloc(blk_crypto_bounce_page_pool, GFP_NOIO);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci		enc_bvec->bv_page = ciphertext_page;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci		if (!ciphertext_page) {
32562306a36Sopenharmony_ci			src_bio->bi_status = BLK_STS_RESOURCE;
32662306a36Sopenharmony_ci			goto out_free_bounce_pages;
32762306a36Sopenharmony_ci		}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci		sg_set_page(&src, plaintext_page, data_unit_size,
33062306a36Sopenharmony_ci			    enc_bvec->bv_offset);
33162306a36Sopenharmony_ci		sg_set_page(&dst, ciphertext_page, data_unit_size,
33262306a36Sopenharmony_ci			    enc_bvec->bv_offset);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci		/* Encrypt each data unit in this page */
33562306a36Sopenharmony_ci		for (j = 0; j < enc_bvec->bv_len; j += data_unit_size) {
33662306a36Sopenharmony_ci			blk_crypto_dun_to_iv(curr_dun, &iv);
33762306a36Sopenharmony_ci			if (crypto_wait_req(crypto_skcipher_encrypt(ciph_req),
33862306a36Sopenharmony_ci					    &wait)) {
33962306a36Sopenharmony_ci				i++;
34062306a36Sopenharmony_ci				src_bio->bi_status = BLK_STS_IOERR;
34162306a36Sopenharmony_ci				goto out_free_bounce_pages;
34262306a36Sopenharmony_ci			}
34362306a36Sopenharmony_ci			bio_crypt_dun_increment(curr_dun, 1);
34462306a36Sopenharmony_ci			src.offset += data_unit_size;
34562306a36Sopenharmony_ci			dst.offset += data_unit_size;
34662306a36Sopenharmony_ci		}
34762306a36Sopenharmony_ci	}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	enc_bio->bi_private = src_bio;
35062306a36Sopenharmony_ci	enc_bio->bi_end_io = blk_crypto_fallback_encrypt_endio;
35162306a36Sopenharmony_ci	*bio_ptr = enc_bio;
35262306a36Sopenharmony_ci	ret = true;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	enc_bio = NULL;
35562306a36Sopenharmony_ci	goto out_free_ciph_req;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ciout_free_bounce_pages:
35862306a36Sopenharmony_ci	while (i > 0)
35962306a36Sopenharmony_ci		mempool_free(enc_bio->bi_io_vec[--i].bv_page,
36062306a36Sopenharmony_ci			     blk_crypto_bounce_page_pool);
36162306a36Sopenharmony_ciout_free_ciph_req:
36262306a36Sopenharmony_ci	skcipher_request_free(ciph_req);
36362306a36Sopenharmony_ciout_release_keyslot:
36462306a36Sopenharmony_ci	blk_crypto_put_keyslot(slot);
36562306a36Sopenharmony_ciout_put_enc_bio:
36662306a36Sopenharmony_ci	if (enc_bio)
36762306a36Sopenharmony_ci		bio_uninit(enc_bio);
36862306a36Sopenharmony_ci	kfree(enc_bio);
36962306a36Sopenharmony_ci	return ret;
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci/*
37362306a36Sopenharmony_ci * The crypto API fallback's main decryption routine.
37462306a36Sopenharmony_ci * Decrypts input bio in place, and calls bio_endio on the bio.
37562306a36Sopenharmony_ci */
37662306a36Sopenharmony_cistatic void blk_crypto_fallback_decrypt_bio(struct work_struct *work)
37762306a36Sopenharmony_ci{
37862306a36Sopenharmony_ci	struct bio_fallback_crypt_ctx *f_ctx =
37962306a36Sopenharmony_ci		container_of(work, struct bio_fallback_crypt_ctx, work);
38062306a36Sopenharmony_ci	struct bio *bio = f_ctx->bio;
38162306a36Sopenharmony_ci	struct bio_crypt_ctx *bc = &f_ctx->crypt_ctx;
38262306a36Sopenharmony_ci	struct blk_crypto_keyslot *slot;
38362306a36Sopenharmony_ci	struct skcipher_request *ciph_req = NULL;
38462306a36Sopenharmony_ci	DECLARE_CRYPTO_WAIT(wait);
38562306a36Sopenharmony_ci	u64 curr_dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
38662306a36Sopenharmony_ci	union blk_crypto_iv iv;
38762306a36Sopenharmony_ci	struct scatterlist sg;
38862306a36Sopenharmony_ci	struct bio_vec bv;
38962306a36Sopenharmony_ci	struct bvec_iter iter;
39062306a36Sopenharmony_ci	const int data_unit_size = bc->bc_key->crypto_cfg.data_unit_size;
39162306a36Sopenharmony_ci	unsigned int i;
39262306a36Sopenharmony_ci	blk_status_t blk_st;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/*
39562306a36Sopenharmony_ci	 * Get a blk-crypto-fallback keyslot that contains a crypto_skcipher for
39662306a36Sopenharmony_ci	 * this bio's algorithm and key.
39762306a36Sopenharmony_ci	 */
39862306a36Sopenharmony_ci	blk_st = blk_crypto_get_keyslot(blk_crypto_fallback_profile,
39962306a36Sopenharmony_ci					bc->bc_key, &slot);
40062306a36Sopenharmony_ci	if (blk_st != BLK_STS_OK) {
40162306a36Sopenharmony_ci		bio->bi_status = blk_st;
40262306a36Sopenharmony_ci		goto out_no_keyslot;
40362306a36Sopenharmony_ci	}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	/* and then allocate an skcipher_request for it */
40662306a36Sopenharmony_ci	if (!blk_crypto_fallback_alloc_cipher_req(slot, &ciph_req, &wait)) {
40762306a36Sopenharmony_ci		bio->bi_status = BLK_STS_RESOURCE;
40862306a36Sopenharmony_ci		goto out;
40962306a36Sopenharmony_ci	}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	memcpy(curr_dun, bc->bc_dun, sizeof(curr_dun));
41262306a36Sopenharmony_ci	sg_init_table(&sg, 1);
41362306a36Sopenharmony_ci	skcipher_request_set_crypt(ciph_req, &sg, &sg, data_unit_size,
41462306a36Sopenharmony_ci				   iv.bytes);
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	/* Decrypt each segment in the bio */
41762306a36Sopenharmony_ci	__bio_for_each_segment(bv, bio, iter, f_ctx->crypt_iter) {
41862306a36Sopenharmony_ci		struct page *page = bv.bv_page;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci		sg_set_page(&sg, page, data_unit_size, bv.bv_offset);
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci		/* Decrypt each data unit in the segment */
42362306a36Sopenharmony_ci		for (i = 0; i < bv.bv_len; i += data_unit_size) {
42462306a36Sopenharmony_ci			blk_crypto_dun_to_iv(curr_dun, &iv);
42562306a36Sopenharmony_ci			if (crypto_wait_req(crypto_skcipher_decrypt(ciph_req),
42662306a36Sopenharmony_ci					    &wait)) {
42762306a36Sopenharmony_ci				bio->bi_status = BLK_STS_IOERR;
42862306a36Sopenharmony_ci				goto out;
42962306a36Sopenharmony_ci			}
43062306a36Sopenharmony_ci			bio_crypt_dun_increment(curr_dun, 1);
43162306a36Sopenharmony_ci			sg.offset += data_unit_size;
43262306a36Sopenharmony_ci		}
43362306a36Sopenharmony_ci	}
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ciout:
43662306a36Sopenharmony_ci	skcipher_request_free(ciph_req);
43762306a36Sopenharmony_ci	blk_crypto_put_keyslot(slot);
43862306a36Sopenharmony_ciout_no_keyslot:
43962306a36Sopenharmony_ci	mempool_free(f_ctx, bio_fallback_crypt_ctx_pool);
44062306a36Sopenharmony_ci	bio_endio(bio);
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci/**
44462306a36Sopenharmony_ci * blk_crypto_fallback_decrypt_endio - queue bio for fallback decryption
44562306a36Sopenharmony_ci *
44662306a36Sopenharmony_ci * @bio: the bio to queue
44762306a36Sopenharmony_ci *
44862306a36Sopenharmony_ci * Restore bi_private and bi_end_io, and queue the bio for decryption into a
44962306a36Sopenharmony_ci * workqueue, since this function will be called from an atomic context.
45062306a36Sopenharmony_ci */
45162306a36Sopenharmony_cistatic void blk_crypto_fallback_decrypt_endio(struct bio *bio)
45262306a36Sopenharmony_ci{
45362306a36Sopenharmony_ci	struct bio_fallback_crypt_ctx *f_ctx = bio->bi_private;
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	bio->bi_private = f_ctx->bi_private_orig;
45662306a36Sopenharmony_ci	bio->bi_end_io = f_ctx->bi_end_io_orig;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	/* If there was an IO error, don't queue for decrypt. */
45962306a36Sopenharmony_ci	if (bio->bi_status) {
46062306a36Sopenharmony_ci		mempool_free(f_ctx, bio_fallback_crypt_ctx_pool);
46162306a36Sopenharmony_ci		bio_endio(bio);
46262306a36Sopenharmony_ci		return;
46362306a36Sopenharmony_ci	}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	INIT_WORK(&f_ctx->work, blk_crypto_fallback_decrypt_bio);
46662306a36Sopenharmony_ci	f_ctx->bio = bio;
46762306a36Sopenharmony_ci	queue_work(blk_crypto_wq, &f_ctx->work);
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci/**
47162306a36Sopenharmony_ci * blk_crypto_fallback_bio_prep - Prepare a bio to use fallback en/decryption
47262306a36Sopenharmony_ci *
47362306a36Sopenharmony_ci * @bio_ptr: pointer to the bio to prepare
47462306a36Sopenharmony_ci *
47562306a36Sopenharmony_ci * If bio is doing a WRITE operation, this splits the bio into two parts if it's
47662306a36Sopenharmony_ci * too big (see blk_crypto_fallback_split_bio_if_needed()). It then allocates a
47762306a36Sopenharmony_ci * bounce bio for the first part, encrypts it, and updates bio_ptr to point to
47862306a36Sopenharmony_ci * the bounce bio.
47962306a36Sopenharmony_ci *
48062306a36Sopenharmony_ci * For a READ operation, we mark the bio for decryption by using bi_private and
48162306a36Sopenharmony_ci * bi_end_io.
48262306a36Sopenharmony_ci *
48362306a36Sopenharmony_ci * In either case, this function will make the bio look like a regular bio (i.e.
48462306a36Sopenharmony_ci * as if no encryption context was ever specified) for the purposes of the rest
48562306a36Sopenharmony_ci * of the stack except for blk-integrity (blk-integrity and blk-crypto are not
48662306a36Sopenharmony_ci * currently supported together).
48762306a36Sopenharmony_ci *
48862306a36Sopenharmony_ci * Return: true on success. Sets bio->bi_status and returns false on error.
48962306a36Sopenharmony_ci */
49062306a36Sopenharmony_cibool blk_crypto_fallback_bio_prep(struct bio **bio_ptr)
49162306a36Sopenharmony_ci{
49262306a36Sopenharmony_ci	struct bio *bio = *bio_ptr;
49362306a36Sopenharmony_ci	struct bio_crypt_ctx *bc = bio->bi_crypt_context;
49462306a36Sopenharmony_ci	struct bio_fallback_crypt_ctx *f_ctx;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	if (WARN_ON_ONCE(!tfms_inited[bc->bc_key->crypto_cfg.crypto_mode])) {
49762306a36Sopenharmony_ci		/* User didn't call blk_crypto_start_using_key() first */
49862306a36Sopenharmony_ci		bio->bi_status = BLK_STS_IOERR;
49962306a36Sopenharmony_ci		return false;
50062306a36Sopenharmony_ci	}
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	if (!__blk_crypto_cfg_supported(blk_crypto_fallback_profile,
50362306a36Sopenharmony_ci					&bc->bc_key->crypto_cfg)) {
50462306a36Sopenharmony_ci		bio->bi_status = BLK_STS_NOTSUPP;
50562306a36Sopenharmony_ci		return false;
50662306a36Sopenharmony_ci	}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	if (bio_data_dir(bio) == WRITE)
50962306a36Sopenharmony_ci		return blk_crypto_fallback_encrypt_bio(bio_ptr);
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	/*
51262306a36Sopenharmony_ci	 * bio READ case: Set up a f_ctx in the bio's bi_private and set the
51362306a36Sopenharmony_ci	 * bi_end_io appropriately to trigger decryption when the bio is ended.
51462306a36Sopenharmony_ci	 */
51562306a36Sopenharmony_ci	f_ctx = mempool_alloc(bio_fallback_crypt_ctx_pool, GFP_NOIO);
51662306a36Sopenharmony_ci	f_ctx->crypt_ctx = *bc;
51762306a36Sopenharmony_ci	f_ctx->crypt_iter = bio->bi_iter;
51862306a36Sopenharmony_ci	f_ctx->bi_private_orig = bio->bi_private;
51962306a36Sopenharmony_ci	f_ctx->bi_end_io_orig = bio->bi_end_io;
52062306a36Sopenharmony_ci	bio->bi_private = (void *)f_ctx;
52162306a36Sopenharmony_ci	bio->bi_end_io = blk_crypto_fallback_decrypt_endio;
52262306a36Sopenharmony_ci	bio_crypt_free_ctx(bio);
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	return true;
52562306a36Sopenharmony_ci}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ciint blk_crypto_fallback_evict_key(const struct blk_crypto_key *key)
52862306a36Sopenharmony_ci{
52962306a36Sopenharmony_ci	return __blk_crypto_evict_key(blk_crypto_fallback_profile, key);
53062306a36Sopenharmony_ci}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_cistatic bool blk_crypto_fallback_inited;
53362306a36Sopenharmony_cistatic int blk_crypto_fallback_init(void)
53462306a36Sopenharmony_ci{
53562306a36Sopenharmony_ci	int i;
53662306a36Sopenharmony_ci	int err;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	if (blk_crypto_fallback_inited)
53962306a36Sopenharmony_ci		return 0;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	get_random_bytes(blank_key, BLK_CRYPTO_MAX_KEY_SIZE);
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	err = bioset_init(&crypto_bio_split, 64, 0, 0);
54462306a36Sopenharmony_ci	if (err)
54562306a36Sopenharmony_ci		goto out;
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	/* Dynamic allocation is needed because of lockdep_register_key(). */
54862306a36Sopenharmony_ci	blk_crypto_fallback_profile =
54962306a36Sopenharmony_ci		kzalloc(sizeof(*blk_crypto_fallback_profile), GFP_KERNEL);
55062306a36Sopenharmony_ci	if (!blk_crypto_fallback_profile) {
55162306a36Sopenharmony_ci		err = -ENOMEM;
55262306a36Sopenharmony_ci		goto fail_free_bioset;
55362306a36Sopenharmony_ci	}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	err = blk_crypto_profile_init(blk_crypto_fallback_profile,
55662306a36Sopenharmony_ci				      blk_crypto_num_keyslots);
55762306a36Sopenharmony_ci	if (err)
55862306a36Sopenharmony_ci		goto fail_free_profile;
55962306a36Sopenharmony_ci	err = -ENOMEM;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	blk_crypto_fallback_profile->ll_ops = blk_crypto_fallback_ll_ops;
56262306a36Sopenharmony_ci	blk_crypto_fallback_profile->max_dun_bytes_supported = BLK_CRYPTO_MAX_IV_SIZE;
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	/* All blk-crypto modes have a crypto API fallback. */
56562306a36Sopenharmony_ci	for (i = 0; i < BLK_ENCRYPTION_MODE_MAX; i++)
56662306a36Sopenharmony_ci		blk_crypto_fallback_profile->modes_supported[i] = 0xFFFFFFFF;
56762306a36Sopenharmony_ci	blk_crypto_fallback_profile->modes_supported[BLK_ENCRYPTION_MODE_INVALID] = 0;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	blk_crypto_wq = alloc_workqueue("blk_crypto_wq",
57062306a36Sopenharmony_ci					WQ_UNBOUND | WQ_HIGHPRI |
57162306a36Sopenharmony_ci					WQ_MEM_RECLAIM, num_online_cpus());
57262306a36Sopenharmony_ci	if (!blk_crypto_wq)
57362306a36Sopenharmony_ci		goto fail_destroy_profile;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	blk_crypto_keyslots = kcalloc(blk_crypto_num_keyslots,
57662306a36Sopenharmony_ci				      sizeof(blk_crypto_keyslots[0]),
57762306a36Sopenharmony_ci				      GFP_KERNEL);
57862306a36Sopenharmony_ci	if (!blk_crypto_keyslots)
57962306a36Sopenharmony_ci		goto fail_free_wq;
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	blk_crypto_bounce_page_pool =
58262306a36Sopenharmony_ci		mempool_create_page_pool(num_prealloc_bounce_pg, 0);
58362306a36Sopenharmony_ci	if (!blk_crypto_bounce_page_pool)
58462306a36Sopenharmony_ci		goto fail_free_keyslots;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	bio_fallback_crypt_ctx_cache = KMEM_CACHE(bio_fallback_crypt_ctx, 0);
58762306a36Sopenharmony_ci	if (!bio_fallback_crypt_ctx_cache)
58862306a36Sopenharmony_ci		goto fail_free_bounce_page_pool;
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	bio_fallback_crypt_ctx_pool =
59162306a36Sopenharmony_ci		mempool_create_slab_pool(num_prealloc_fallback_crypt_ctxs,
59262306a36Sopenharmony_ci					 bio_fallback_crypt_ctx_cache);
59362306a36Sopenharmony_ci	if (!bio_fallback_crypt_ctx_pool)
59462306a36Sopenharmony_ci		goto fail_free_crypt_ctx_cache;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	blk_crypto_fallback_inited = true;
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	return 0;
59962306a36Sopenharmony_cifail_free_crypt_ctx_cache:
60062306a36Sopenharmony_ci	kmem_cache_destroy(bio_fallback_crypt_ctx_cache);
60162306a36Sopenharmony_cifail_free_bounce_page_pool:
60262306a36Sopenharmony_ci	mempool_destroy(blk_crypto_bounce_page_pool);
60362306a36Sopenharmony_cifail_free_keyslots:
60462306a36Sopenharmony_ci	kfree(blk_crypto_keyslots);
60562306a36Sopenharmony_cifail_free_wq:
60662306a36Sopenharmony_ci	destroy_workqueue(blk_crypto_wq);
60762306a36Sopenharmony_cifail_destroy_profile:
60862306a36Sopenharmony_ci	blk_crypto_profile_destroy(blk_crypto_fallback_profile);
60962306a36Sopenharmony_cifail_free_profile:
61062306a36Sopenharmony_ci	kfree(blk_crypto_fallback_profile);
61162306a36Sopenharmony_cifail_free_bioset:
61262306a36Sopenharmony_ci	bioset_exit(&crypto_bio_split);
61362306a36Sopenharmony_ciout:
61462306a36Sopenharmony_ci	return err;
61562306a36Sopenharmony_ci}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci/*
61862306a36Sopenharmony_ci * Prepare blk-crypto-fallback for the specified crypto mode.
61962306a36Sopenharmony_ci * Returns -ENOPKG if the needed crypto API support is missing.
62062306a36Sopenharmony_ci */
62162306a36Sopenharmony_ciint blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num)
62262306a36Sopenharmony_ci{
62362306a36Sopenharmony_ci	const char *cipher_str = blk_crypto_modes[mode_num].cipher_str;
62462306a36Sopenharmony_ci	struct blk_crypto_fallback_keyslot *slotp;
62562306a36Sopenharmony_ci	unsigned int i;
62662306a36Sopenharmony_ci	int err = 0;
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	/*
62962306a36Sopenharmony_ci	 * Fast path
63062306a36Sopenharmony_ci	 * Ensure that updates to blk_crypto_keyslots[i].tfms[mode_num]
63162306a36Sopenharmony_ci	 * for each i are visible before we try to access them.
63262306a36Sopenharmony_ci	 */
63362306a36Sopenharmony_ci	if (likely(smp_load_acquire(&tfms_inited[mode_num])))
63462306a36Sopenharmony_ci		return 0;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	mutex_lock(&tfms_init_lock);
63762306a36Sopenharmony_ci	if (tfms_inited[mode_num])
63862306a36Sopenharmony_ci		goto out;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	err = blk_crypto_fallback_init();
64162306a36Sopenharmony_ci	if (err)
64262306a36Sopenharmony_ci		goto out;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	for (i = 0; i < blk_crypto_num_keyslots; i++) {
64562306a36Sopenharmony_ci		slotp = &blk_crypto_keyslots[i];
64662306a36Sopenharmony_ci		slotp->tfms[mode_num] = crypto_alloc_skcipher(cipher_str, 0, 0);
64762306a36Sopenharmony_ci		if (IS_ERR(slotp->tfms[mode_num])) {
64862306a36Sopenharmony_ci			err = PTR_ERR(slotp->tfms[mode_num]);
64962306a36Sopenharmony_ci			if (err == -ENOENT) {
65062306a36Sopenharmony_ci				pr_warn_once("Missing crypto API support for \"%s\"\n",
65162306a36Sopenharmony_ci					     cipher_str);
65262306a36Sopenharmony_ci				err = -ENOPKG;
65362306a36Sopenharmony_ci			}
65462306a36Sopenharmony_ci			slotp->tfms[mode_num] = NULL;
65562306a36Sopenharmony_ci			goto out_free_tfms;
65662306a36Sopenharmony_ci		}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci		crypto_skcipher_set_flags(slotp->tfms[mode_num],
65962306a36Sopenharmony_ci					  CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
66062306a36Sopenharmony_ci	}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	/*
66362306a36Sopenharmony_ci	 * Ensure that updates to blk_crypto_keyslots[i].tfms[mode_num]
66462306a36Sopenharmony_ci	 * for each i are visible before we set tfms_inited[mode_num].
66562306a36Sopenharmony_ci	 */
66662306a36Sopenharmony_ci	smp_store_release(&tfms_inited[mode_num], true);
66762306a36Sopenharmony_ci	goto out;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ciout_free_tfms:
67062306a36Sopenharmony_ci	for (i = 0; i < blk_crypto_num_keyslots; i++) {
67162306a36Sopenharmony_ci		slotp = &blk_crypto_keyslots[i];
67262306a36Sopenharmony_ci		crypto_free_skcipher(slotp->tfms[mode_num]);
67362306a36Sopenharmony_ci		slotp->tfms[mode_num] = NULL;
67462306a36Sopenharmony_ci	}
67562306a36Sopenharmony_ciout:
67662306a36Sopenharmony_ci	mutex_unlock(&tfms_init_lock);
67762306a36Sopenharmony_ci	return err;
67862306a36Sopenharmony_ci}
679