18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * ESSIV skcipher and aead template for block encryption
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This template encapsulates the ESSIV IV generation algorithm used by
68c2ecf20Sopenharmony_ci * dm-crypt and fscrypt, which converts the initial vector for the skcipher
78c2ecf20Sopenharmony_ci * used for block encryption, by encrypting it using the hash of the
88c2ecf20Sopenharmony_ci * skcipher key as encryption key. Usually, the input IV is a 64-bit sector
98c2ecf20Sopenharmony_ci * number in LE representation zero-padded to the size of the IV, but this
108c2ecf20Sopenharmony_ci * is not assumed by this driver.
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * The typical use of this template is to instantiate the skcipher
138c2ecf20Sopenharmony_ci * 'essiv(cbc(aes),sha256)', which is the only instantiation used by
148c2ecf20Sopenharmony_ci * fscrypt, and the most relevant one for dm-crypt. However, dm-crypt
158c2ecf20Sopenharmony_ci * also permits ESSIV to be used in combination with the authenc template,
168c2ecf20Sopenharmony_ci * e.g., 'essiv(authenc(hmac(sha256),cbc(aes)),sha256)', in which case
178c2ecf20Sopenharmony_ci * we need to instantiate an aead that accepts the same special key format
188c2ecf20Sopenharmony_ci * as the authenc template, and deals with the way the encrypted IV is
198c2ecf20Sopenharmony_ci * embedded into the AAD area of the aead request. This means the AEAD
208c2ecf20Sopenharmony_ci * flavor produced by this template is tightly coupled to the way dm-crypt
218c2ecf20Sopenharmony_ci * happens to use it.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * Copyright (c) 2019 Linaro, Ltd. <ard.biesheuvel@linaro.org>
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * Heavily based on:
268c2ecf20Sopenharmony_ci * adiantum length-preserving encryption mode
278c2ecf20Sopenharmony_ci *
288c2ecf20Sopenharmony_ci * Copyright 2018 Google LLC
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#include <crypto/authenc.h>
328c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h>
338c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h>
348c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h>
358c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h>
368c2ecf20Sopenharmony_ci#include <linux/module.h>
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#include "internal.h"
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistruct essiv_instance_ctx {
418c2ecf20Sopenharmony_ci	union {
428c2ecf20Sopenharmony_ci		struct crypto_skcipher_spawn	skcipher_spawn;
438c2ecf20Sopenharmony_ci		struct crypto_aead_spawn	aead_spawn;
448c2ecf20Sopenharmony_ci	} u;
458c2ecf20Sopenharmony_ci	char	essiv_cipher_name[CRYPTO_MAX_ALG_NAME];
468c2ecf20Sopenharmony_ci	char	shash_driver_name[CRYPTO_MAX_ALG_NAME];
478c2ecf20Sopenharmony_ci};
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistruct essiv_tfm_ctx {
508c2ecf20Sopenharmony_ci	union {
518c2ecf20Sopenharmony_ci		struct crypto_skcipher	*skcipher;
528c2ecf20Sopenharmony_ci		struct crypto_aead	*aead;
538c2ecf20Sopenharmony_ci	} u;
548c2ecf20Sopenharmony_ci	struct crypto_cipher		*essiv_cipher;
558c2ecf20Sopenharmony_ci	struct crypto_shash		*hash;
568c2ecf20Sopenharmony_ci	int				ivoffset;
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistruct essiv_aead_request_ctx {
608c2ecf20Sopenharmony_ci	struct scatterlist		sg[4];
618c2ecf20Sopenharmony_ci	u8				*assoc;
628c2ecf20Sopenharmony_ci	struct aead_request		aead_req;
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic int essiv_skcipher_setkey(struct crypto_skcipher *tfm,
668c2ecf20Sopenharmony_ci				 const u8 *key, unsigned int keylen)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
698c2ecf20Sopenharmony_ci	u8 salt[HASH_MAX_DIGESTSIZE];
708c2ecf20Sopenharmony_ci	int err;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	crypto_skcipher_clear_flags(tctx->u.skcipher, CRYPTO_TFM_REQ_MASK);
738c2ecf20Sopenharmony_ci	crypto_skcipher_set_flags(tctx->u.skcipher,
748c2ecf20Sopenharmony_ci				  crypto_skcipher_get_flags(tfm) &
758c2ecf20Sopenharmony_ci				  CRYPTO_TFM_REQ_MASK);
768c2ecf20Sopenharmony_ci	err = crypto_skcipher_setkey(tctx->u.skcipher, key, keylen);
778c2ecf20Sopenharmony_ci	if (err)
788c2ecf20Sopenharmony_ci		return err;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	err = crypto_shash_tfm_digest(tctx->hash, key, keylen, salt);
818c2ecf20Sopenharmony_ci	if (err)
828c2ecf20Sopenharmony_ci		return err;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	crypto_cipher_clear_flags(tctx->essiv_cipher, CRYPTO_TFM_REQ_MASK);
858c2ecf20Sopenharmony_ci	crypto_cipher_set_flags(tctx->essiv_cipher,
868c2ecf20Sopenharmony_ci				crypto_skcipher_get_flags(tfm) &
878c2ecf20Sopenharmony_ci				CRYPTO_TFM_REQ_MASK);
888c2ecf20Sopenharmony_ci	return crypto_cipher_setkey(tctx->essiv_cipher, salt,
898c2ecf20Sopenharmony_ci				    crypto_shash_digestsize(tctx->hash));
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistatic int essiv_aead_setkey(struct crypto_aead *tfm, const u8 *key,
938c2ecf20Sopenharmony_ci			     unsigned int keylen)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
968c2ecf20Sopenharmony_ci	SHASH_DESC_ON_STACK(desc, tctx->hash);
978c2ecf20Sopenharmony_ci	struct crypto_authenc_keys keys;
988c2ecf20Sopenharmony_ci	u8 salt[HASH_MAX_DIGESTSIZE];
998c2ecf20Sopenharmony_ci	int err;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	crypto_aead_clear_flags(tctx->u.aead, CRYPTO_TFM_REQ_MASK);
1028c2ecf20Sopenharmony_ci	crypto_aead_set_flags(tctx->u.aead, crypto_aead_get_flags(tfm) &
1038c2ecf20Sopenharmony_ci					    CRYPTO_TFM_REQ_MASK);
1048c2ecf20Sopenharmony_ci	err = crypto_aead_setkey(tctx->u.aead, key, keylen);
1058c2ecf20Sopenharmony_ci	if (err)
1068c2ecf20Sopenharmony_ci		return err;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
1098c2ecf20Sopenharmony_ci		return -EINVAL;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	desc->tfm = tctx->hash;
1128c2ecf20Sopenharmony_ci	err = crypto_shash_init(desc) ?:
1138c2ecf20Sopenharmony_ci	      crypto_shash_update(desc, keys.enckey, keys.enckeylen) ?:
1148c2ecf20Sopenharmony_ci	      crypto_shash_finup(desc, keys.authkey, keys.authkeylen, salt);
1158c2ecf20Sopenharmony_ci	if (err)
1168c2ecf20Sopenharmony_ci		return err;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	crypto_cipher_clear_flags(tctx->essiv_cipher, CRYPTO_TFM_REQ_MASK);
1198c2ecf20Sopenharmony_ci	crypto_cipher_set_flags(tctx->essiv_cipher, crypto_aead_get_flags(tfm) &
1208c2ecf20Sopenharmony_ci						    CRYPTO_TFM_REQ_MASK);
1218c2ecf20Sopenharmony_ci	return crypto_cipher_setkey(tctx->essiv_cipher, salt,
1228c2ecf20Sopenharmony_ci				    crypto_shash_digestsize(tctx->hash));
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic int essiv_aead_setauthsize(struct crypto_aead *tfm,
1268c2ecf20Sopenharmony_ci				  unsigned int authsize)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	return crypto_aead_setauthsize(tctx->u.aead, authsize);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic void essiv_skcipher_done(struct crypto_async_request *areq, int err)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	struct skcipher_request *req = areq->data;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	skcipher_request_complete(req, err);
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic int essiv_skcipher_crypt(struct skcipher_request *req, bool enc)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
1438c2ecf20Sopenharmony_ci	const struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
1448c2ecf20Sopenharmony_ci	struct skcipher_request *subreq = skcipher_request_ctx(req);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	skcipher_request_set_tfm(subreq, tctx->u.skcipher);
1498c2ecf20Sopenharmony_ci	skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
1508c2ecf20Sopenharmony_ci				   req->iv);
1518c2ecf20Sopenharmony_ci	skcipher_request_set_callback(subreq, skcipher_request_flags(req),
1528c2ecf20Sopenharmony_ci				      essiv_skcipher_done, req);
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	return enc ? crypto_skcipher_encrypt(subreq) :
1558c2ecf20Sopenharmony_ci		     crypto_skcipher_decrypt(subreq);
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic int essiv_skcipher_encrypt(struct skcipher_request *req)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	return essiv_skcipher_crypt(req, true);
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic int essiv_skcipher_decrypt(struct skcipher_request *req)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	return essiv_skcipher_crypt(req, false);
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic void essiv_aead_done(struct crypto_async_request *areq, int err)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	struct aead_request *req = areq->data;
1718c2ecf20Sopenharmony_ci	struct essiv_aead_request_ctx *rctx = aead_request_ctx(req);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	if (err == -EINPROGRESS)
1748c2ecf20Sopenharmony_ci		goto out;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	kfree(rctx->assoc);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ciout:
1798c2ecf20Sopenharmony_ci	aead_request_complete(req, err);
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic int essiv_aead_crypt(struct aead_request *req, bool enc)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1858c2ecf20Sopenharmony_ci	const struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
1868c2ecf20Sopenharmony_ci	struct essiv_aead_request_ctx *rctx = aead_request_ctx(req);
1878c2ecf20Sopenharmony_ci	struct aead_request *subreq = &rctx->aead_req;
1888c2ecf20Sopenharmony_ci	struct scatterlist *src = req->src;
1898c2ecf20Sopenharmony_ci	int err;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	/*
1948c2ecf20Sopenharmony_ci	 * dm-crypt embeds the sector number and the IV in the AAD region, so
1958c2ecf20Sopenharmony_ci	 * we have to copy the converted IV into the right scatterlist before
1968c2ecf20Sopenharmony_ci	 * we pass it on.
1978c2ecf20Sopenharmony_ci	 */
1988c2ecf20Sopenharmony_ci	rctx->assoc = NULL;
1998c2ecf20Sopenharmony_ci	if (req->src == req->dst || !enc) {
2008c2ecf20Sopenharmony_ci		scatterwalk_map_and_copy(req->iv, req->dst,
2018c2ecf20Sopenharmony_ci					 req->assoclen - crypto_aead_ivsize(tfm),
2028c2ecf20Sopenharmony_ci					 crypto_aead_ivsize(tfm), 1);
2038c2ecf20Sopenharmony_ci	} else {
2048c2ecf20Sopenharmony_ci		u8 *iv = (u8 *)aead_request_ctx(req) + tctx->ivoffset;
2058c2ecf20Sopenharmony_ci		int ivsize = crypto_aead_ivsize(tfm);
2068c2ecf20Sopenharmony_ci		int ssize = req->assoclen - ivsize;
2078c2ecf20Sopenharmony_ci		struct scatterlist *sg;
2088c2ecf20Sopenharmony_ci		int nents;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci		if (ssize < 0)
2118c2ecf20Sopenharmony_ci			return -EINVAL;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci		nents = sg_nents_for_len(req->src, ssize);
2148c2ecf20Sopenharmony_ci		if (nents < 0)
2158c2ecf20Sopenharmony_ci			return -EINVAL;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci		memcpy(iv, req->iv, ivsize);
2188c2ecf20Sopenharmony_ci		sg_init_table(rctx->sg, 4);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci		if (unlikely(nents > 1)) {
2218c2ecf20Sopenharmony_ci			/*
2228c2ecf20Sopenharmony_ci			 * This is a case that rarely occurs in practice, but
2238c2ecf20Sopenharmony_ci			 * for correctness, we have to deal with it nonetheless.
2248c2ecf20Sopenharmony_ci			 */
2258c2ecf20Sopenharmony_ci			rctx->assoc = kmalloc(ssize, GFP_ATOMIC);
2268c2ecf20Sopenharmony_ci			if (!rctx->assoc)
2278c2ecf20Sopenharmony_ci				return -ENOMEM;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci			scatterwalk_map_and_copy(rctx->assoc, req->src, 0,
2308c2ecf20Sopenharmony_ci						 ssize, 0);
2318c2ecf20Sopenharmony_ci			sg_set_buf(rctx->sg, rctx->assoc, ssize);
2328c2ecf20Sopenharmony_ci		} else {
2338c2ecf20Sopenharmony_ci			sg_set_page(rctx->sg, sg_page(req->src), ssize,
2348c2ecf20Sopenharmony_ci				    req->src->offset);
2358c2ecf20Sopenharmony_ci		}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci		sg_set_buf(rctx->sg + 1, iv, ivsize);
2388c2ecf20Sopenharmony_ci		sg = scatterwalk_ffwd(rctx->sg + 2, req->src, req->assoclen);
2398c2ecf20Sopenharmony_ci		if (sg != rctx->sg + 2)
2408c2ecf20Sopenharmony_ci			sg_chain(rctx->sg, 3, sg);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci		src = rctx->sg;
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	aead_request_set_tfm(subreq, tctx->u.aead);
2468c2ecf20Sopenharmony_ci	aead_request_set_ad(subreq, req->assoclen);
2478c2ecf20Sopenharmony_ci	aead_request_set_callback(subreq, aead_request_flags(req),
2488c2ecf20Sopenharmony_ci				  essiv_aead_done, req);
2498c2ecf20Sopenharmony_ci	aead_request_set_crypt(subreq, src, req->dst, req->cryptlen, req->iv);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	err = enc ? crypto_aead_encrypt(subreq) :
2528c2ecf20Sopenharmony_ci		    crypto_aead_decrypt(subreq);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	if (rctx->assoc && err != -EINPROGRESS && err != -EBUSY)
2558c2ecf20Sopenharmony_ci		kfree(rctx->assoc);
2568c2ecf20Sopenharmony_ci	return err;
2578c2ecf20Sopenharmony_ci}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_cistatic int essiv_aead_encrypt(struct aead_request *req)
2608c2ecf20Sopenharmony_ci{
2618c2ecf20Sopenharmony_ci	return essiv_aead_crypt(req, true);
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_cistatic int essiv_aead_decrypt(struct aead_request *req)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	return essiv_aead_crypt(req, false);
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistatic int essiv_init_tfm(struct essiv_instance_ctx *ictx,
2708c2ecf20Sopenharmony_ci			  struct essiv_tfm_ctx *tctx)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	struct crypto_cipher *essiv_cipher;
2738c2ecf20Sopenharmony_ci	struct crypto_shash *hash;
2748c2ecf20Sopenharmony_ci	int err;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	essiv_cipher = crypto_alloc_cipher(ictx->essiv_cipher_name, 0, 0);
2778c2ecf20Sopenharmony_ci	if (IS_ERR(essiv_cipher))
2788c2ecf20Sopenharmony_ci		return PTR_ERR(essiv_cipher);
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	hash = crypto_alloc_shash(ictx->shash_driver_name, 0, 0);
2818c2ecf20Sopenharmony_ci	if (IS_ERR(hash)) {
2828c2ecf20Sopenharmony_ci		err = PTR_ERR(hash);
2838c2ecf20Sopenharmony_ci		goto err_free_essiv_cipher;
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	tctx->essiv_cipher = essiv_cipher;
2878c2ecf20Sopenharmony_ci	tctx->hash = hash;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	return 0;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cierr_free_essiv_cipher:
2928c2ecf20Sopenharmony_ci	crypto_free_cipher(essiv_cipher);
2938c2ecf20Sopenharmony_ci	return err;
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistatic int essiv_skcipher_init_tfm(struct crypto_skcipher *tfm)
2978c2ecf20Sopenharmony_ci{
2988c2ecf20Sopenharmony_ci	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
2998c2ecf20Sopenharmony_ci	struct essiv_instance_ctx *ictx = skcipher_instance_ctx(inst);
3008c2ecf20Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
3018c2ecf20Sopenharmony_ci	struct crypto_skcipher *skcipher;
3028c2ecf20Sopenharmony_ci	int err;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	skcipher = crypto_spawn_skcipher(&ictx->u.skcipher_spawn);
3058c2ecf20Sopenharmony_ci	if (IS_ERR(skcipher))
3068c2ecf20Sopenharmony_ci		return PTR_ERR(skcipher);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	crypto_skcipher_set_reqsize(tfm, sizeof(struct skcipher_request) +
3098c2ecf20Sopenharmony_ci				         crypto_skcipher_reqsize(skcipher));
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	err = essiv_init_tfm(ictx, tctx);
3128c2ecf20Sopenharmony_ci	if (err) {
3138c2ecf20Sopenharmony_ci		crypto_free_skcipher(skcipher);
3148c2ecf20Sopenharmony_ci		return err;
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	tctx->u.skcipher = skcipher;
3188c2ecf20Sopenharmony_ci	return 0;
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic int essiv_aead_init_tfm(struct crypto_aead *tfm)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	struct aead_instance *inst = aead_alg_instance(tfm);
3248c2ecf20Sopenharmony_ci	struct essiv_instance_ctx *ictx = aead_instance_ctx(inst);
3258c2ecf20Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
3268c2ecf20Sopenharmony_ci	struct crypto_aead *aead;
3278c2ecf20Sopenharmony_ci	unsigned int subreq_size;
3288c2ecf20Sopenharmony_ci	int err;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	BUILD_BUG_ON(offsetofend(struct essiv_aead_request_ctx, aead_req) !=
3318c2ecf20Sopenharmony_ci		     sizeof(struct essiv_aead_request_ctx));
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	aead = crypto_spawn_aead(&ictx->u.aead_spawn);
3348c2ecf20Sopenharmony_ci	if (IS_ERR(aead))
3358c2ecf20Sopenharmony_ci		return PTR_ERR(aead);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	subreq_size = sizeof_field(struct essiv_aead_request_ctx, aead_req) +
3388c2ecf20Sopenharmony_ci		      crypto_aead_reqsize(aead);
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	tctx->ivoffset = offsetof(struct essiv_aead_request_ctx, aead_req) +
3418c2ecf20Sopenharmony_ci			 subreq_size;
3428c2ecf20Sopenharmony_ci	crypto_aead_set_reqsize(tfm, tctx->ivoffset + crypto_aead_ivsize(aead));
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	err = essiv_init_tfm(ictx, tctx);
3458c2ecf20Sopenharmony_ci	if (err) {
3468c2ecf20Sopenharmony_ci		crypto_free_aead(aead);
3478c2ecf20Sopenharmony_ci		return err;
3488c2ecf20Sopenharmony_ci	}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	tctx->u.aead = aead;
3518c2ecf20Sopenharmony_ci	return 0;
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic void essiv_skcipher_exit_tfm(struct crypto_skcipher *tfm)
3558c2ecf20Sopenharmony_ci{
3568c2ecf20Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	crypto_free_skcipher(tctx->u.skcipher);
3598c2ecf20Sopenharmony_ci	crypto_free_cipher(tctx->essiv_cipher);
3608c2ecf20Sopenharmony_ci	crypto_free_shash(tctx->hash);
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cistatic void essiv_aead_exit_tfm(struct crypto_aead *tfm)
3648c2ecf20Sopenharmony_ci{
3658c2ecf20Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	crypto_free_aead(tctx->u.aead);
3688c2ecf20Sopenharmony_ci	crypto_free_cipher(tctx->essiv_cipher);
3698c2ecf20Sopenharmony_ci	crypto_free_shash(tctx->hash);
3708c2ecf20Sopenharmony_ci}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_cistatic void essiv_skcipher_free_instance(struct skcipher_instance *inst)
3738c2ecf20Sopenharmony_ci{
3748c2ecf20Sopenharmony_ci	struct essiv_instance_ctx *ictx = skcipher_instance_ctx(inst);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	crypto_drop_skcipher(&ictx->u.skcipher_spawn);
3778c2ecf20Sopenharmony_ci	kfree(inst);
3788c2ecf20Sopenharmony_ci}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_cistatic void essiv_aead_free_instance(struct aead_instance *inst)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	struct essiv_instance_ctx *ictx = aead_instance_ctx(inst);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	crypto_drop_aead(&ictx->u.aead_spawn);
3858c2ecf20Sopenharmony_ci	kfree(inst);
3868c2ecf20Sopenharmony_ci}
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_cistatic bool parse_cipher_name(char *essiv_cipher_name, const char *cra_name)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	const char *p, *q;
3918c2ecf20Sopenharmony_ci	int len;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	/* find the last opening parens */
3948c2ecf20Sopenharmony_ci	p = strrchr(cra_name, '(');
3958c2ecf20Sopenharmony_ci	if (!p++)
3968c2ecf20Sopenharmony_ci		return false;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	/* find the first closing parens in the tail of the string */
3998c2ecf20Sopenharmony_ci	q = strchr(p, ')');
4008c2ecf20Sopenharmony_ci	if (!q)
4018c2ecf20Sopenharmony_ci		return false;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	len = q - p;
4048c2ecf20Sopenharmony_ci	if (len >= CRYPTO_MAX_ALG_NAME)
4058c2ecf20Sopenharmony_ci		return false;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	memcpy(essiv_cipher_name, p, len);
4088c2ecf20Sopenharmony_ci	essiv_cipher_name[len] = '\0';
4098c2ecf20Sopenharmony_ci	return true;
4108c2ecf20Sopenharmony_ci}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_cistatic bool essiv_supported_algorithms(const char *essiv_cipher_name,
4138c2ecf20Sopenharmony_ci				       struct shash_alg *hash_alg,
4148c2ecf20Sopenharmony_ci				       int ivsize)
4158c2ecf20Sopenharmony_ci{
4168c2ecf20Sopenharmony_ci	struct crypto_alg *alg;
4178c2ecf20Sopenharmony_ci	bool ret = false;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	alg = crypto_alg_mod_lookup(essiv_cipher_name,
4208c2ecf20Sopenharmony_ci				    CRYPTO_ALG_TYPE_CIPHER,
4218c2ecf20Sopenharmony_ci				    CRYPTO_ALG_TYPE_MASK);
4228c2ecf20Sopenharmony_ci	if (IS_ERR(alg))
4238c2ecf20Sopenharmony_ci		return false;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	if (hash_alg->digestsize < alg->cra_cipher.cia_min_keysize ||
4268c2ecf20Sopenharmony_ci	    hash_alg->digestsize > alg->cra_cipher.cia_max_keysize)
4278c2ecf20Sopenharmony_ci		goto out;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	if (ivsize != alg->cra_blocksize)
4308c2ecf20Sopenharmony_ci		goto out;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	if (crypto_shash_alg_needs_key(hash_alg))
4338c2ecf20Sopenharmony_ci		goto out;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	ret = true;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ciout:
4388c2ecf20Sopenharmony_ci	crypto_mod_put(alg);
4398c2ecf20Sopenharmony_ci	return ret;
4408c2ecf20Sopenharmony_ci}
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_cistatic int essiv_create(struct crypto_template *tmpl, struct rtattr **tb)
4438c2ecf20Sopenharmony_ci{
4448c2ecf20Sopenharmony_ci	struct crypto_attr_type *algt;
4458c2ecf20Sopenharmony_ci	const char *inner_cipher_name;
4468c2ecf20Sopenharmony_ci	const char *shash_name;
4478c2ecf20Sopenharmony_ci	struct skcipher_instance *skcipher_inst = NULL;
4488c2ecf20Sopenharmony_ci	struct aead_instance *aead_inst = NULL;
4498c2ecf20Sopenharmony_ci	struct crypto_instance *inst;
4508c2ecf20Sopenharmony_ci	struct crypto_alg *base, *block_base;
4518c2ecf20Sopenharmony_ci	struct essiv_instance_ctx *ictx;
4528c2ecf20Sopenharmony_ci	struct skcipher_alg *skcipher_alg = NULL;
4538c2ecf20Sopenharmony_ci	struct aead_alg *aead_alg = NULL;
4548c2ecf20Sopenharmony_ci	struct crypto_alg *_hash_alg;
4558c2ecf20Sopenharmony_ci	struct shash_alg *hash_alg;
4568c2ecf20Sopenharmony_ci	int ivsize;
4578c2ecf20Sopenharmony_ci	u32 type;
4588c2ecf20Sopenharmony_ci	u32 mask;
4598c2ecf20Sopenharmony_ci	int err;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	algt = crypto_get_attr_type(tb);
4628c2ecf20Sopenharmony_ci	if (IS_ERR(algt))
4638c2ecf20Sopenharmony_ci		return PTR_ERR(algt);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	inner_cipher_name = crypto_attr_alg_name(tb[1]);
4668c2ecf20Sopenharmony_ci	if (IS_ERR(inner_cipher_name))
4678c2ecf20Sopenharmony_ci		return PTR_ERR(inner_cipher_name);
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	shash_name = crypto_attr_alg_name(tb[2]);
4708c2ecf20Sopenharmony_ci	if (IS_ERR(shash_name))
4718c2ecf20Sopenharmony_ci		return PTR_ERR(shash_name);
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	type = algt->type & algt->mask;
4748c2ecf20Sopenharmony_ci	mask = crypto_algt_inherited_mask(algt);
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	switch (type) {
4778c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
4788c2ecf20Sopenharmony_ci		skcipher_inst = kzalloc(sizeof(*skcipher_inst) +
4798c2ecf20Sopenharmony_ci					sizeof(*ictx), GFP_KERNEL);
4808c2ecf20Sopenharmony_ci		if (!skcipher_inst)
4818c2ecf20Sopenharmony_ci			return -ENOMEM;
4828c2ecf20Sopenharmony_ci		inst = skcipher_crypto_instance(skcipher_inst);
4838c2ecf20Sopenharmony_ci		base = &skcipher_inst->alg.base;
4848c2ecf20Sopenharmony_ci		ictx = crypto_instance_ctx(inst);
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci		/* Symmetric cipher, e.g., "cbc(aes)" */
4878c2ecf20Sopenharmony_ci		err = crypto_grab_skcipher(&ictx->u.skcipher_spawn, inst,
4888c2ecf20Sopenharmony_ci					   inner_cipher_name, 0, mask);
4898c2ecf20Sopenharmony_ci		if (err)
4908c2ecf20Sopenharmony_ci			goto out_free_inst;
4918c2ecf20Sopenharmony_ci		skcipher_alg = crypto_spawn_skcipher_alg(&ictx->u.skcipher_spawn);
4928c2ecf20Sopenharmony_ci		block_base = &skcipher_alg->base;
4938c2ecf20Sopenharmony_ci		ivsize = crypto_skcipher_alg_ivsize(skcipher_alg);
4948c2ecf20Sopenharmony_ci		break;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
4978c2ecf20Sopenharmony_ci		aead_inst = kzalloc(sizeof(*aead_inst) +
4988c2ecf20Sopenharmony_ci				    sizeof(*ictx), GFP_KERNEL);
4998c2ecf20Sopenharmony_ci		if (!aead_inst)
5008c2ecf20Sopenharmony_ci			return -ENOMEM;
5018c2ecf20Sopenharmony_ci		inst = aead_crypto_instance(aead_inst);
5028c2ecf20Sopenharmony_ci		base = &aead_inst->alg.base;
5038c2ecf20Sopenharmony_ci		ictx = crypto_instance_ctx(inst);
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci		/* AEAD cipher, e.g., "authenc(hmac(sha256),cbc(aes))" */
5068c2ecf20Sopenharmony_ci		err = crypto_grab_aead(&ictx->u.aead_spawn, inst,
5078c2ecf20Sopenharmony_ci				       inner_cipher_name, 0, mask);
5088c2ecf20Sopenharmony_ci		if (err)
5098c2ecf20Sopenharmony_ci			goto out_free_inst;
5108c2ecf20Sopenharmony_ci		aead_alg = crypto_spawn_aead_alg(&ictx->u.aead_spawn);
5118c2ecf20Sopenharmony_ci		block_base = &aead_alg->base;
5128c2ecf20Sopenharmony_ci		if (!strstarts(block_base->cra_name, "authenc(")) {
5138c2ecf20Sopenharmony_ci			pr_warn("Only authenc() type AEADs are supported by ESSIV\n");
5148c2ecf20Sopenharmony_ci			err = -EINVAL;
5158c2ecf20Sopenharmony_ci			goto out_drop_skcipher;
5168c2ecf20Sopenharmony_ci		}
5178c2ecf20Sopenharmony_ci		ivsize = aead_alg->ivsize;
5188c2ecf20Sopenharmony_ci		break;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	default:
5218c2ecf20Sopenharmony_ci		return -EINVAL;
5228c2ecf20Sopenharmony_ci	}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	if (!parse_cipher_name(ictx->essiv_cipher_name, block_base->cra_name)) {
5258c2ecf20Sopenharmony_ci		pr_warn("Failed to parse ESSIV cipher name from skcipher cra_name\n");
5268c2ecf20Sopenharmony_ci		err = -EINVAL;
5278c2ecf20Sopenharmony_ci		goto out_drop_skcipher;
5288c2ecf20Sopenharmony_ci	}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	/* Synchronous hash, e.g., "sha256" */
5318c2ecf20Sopenharmony_ci	_hash_alg = crypto_alg_mod_lookup(shash_name,
5328c2ecf20Sopenharmony_ci					  CRYPTO_ALG_TYPE_SHASH,
5338c2ecf20Sopenharmony_ci					  CRYPTO_ALG_TYPE_MASK | mask);
5348c2ecf20Sopenharmony_ci	if (IS_ERR(_hash_alg)) {
5358c2ecf20Sopenharmony_ci		err = PTR_ERR(_hash_alg);
5368c2ecf20Sopenharmony_ci		goto out_drop_skcipher;
5378c2ecf20Sopenharmony_ci	}
5388c2ecf20Sopenharmony_ci	hash_alg = __crypto_shash_alg(_hash_alg);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	/* Check the set of algorithms */
5418c2ecf20Sopenharmony_ci	if (!essiv_supported_algorithms(ictx->essiv_cipher_name, hash_alg,
5428c2ecf20Sopenharmony_ci					ivsize)) {
5438c2ecf20Sopenharmony_ci		pr_warn("Unsupported essiv instantiation: essiv(%s,%s)\n",
5448c2ecf20Sopenharmony_ci			block_base->cra_name, hash_alg->base.cra_name);
5458c2ecf20Sopenharmony_ci		err = -EINVAL;
5468c2ecf20Sopenharmony_ci		goto out_free_hash;
5478c2ecf20Sopenharmony_ci	}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	/* record the driver name so we can instantiate this exact algo later */
5508c2ecf20Sopenharmony_ci	strlcpy(ictx->shash_driver_name, hash_alg->base.cra_driver_name,
5518c2ecf20Sopenharmony_ci		CRYPTO_MAX_ALG_NAME);
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	/* Instance fields */
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	err = -ENAMETOOLONG;
5568c2ecf20Sopenharmony_ci	if (snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME,
5578c2ecf20Sopenharmony_ci		     "essiv(%s,%s)", block_base->cra_name,
5588c2ecf20Sopenharmony_ci		     hash_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
5598c2ecf20Sopenharmony_ci		goto out_free_hash;
5608c2ecf20Sopenharmony_ci	if (snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME,
5618c2ecf20Sopenharmony_ci		     "essiv(%s,%s)", block_base->cra_driver_name,
5628c2ecf20Sopenharmony_ci		     hash_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
5638c2ecf20Sopenharmony_ci		goto out_free_hash;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	/*
5668c2ecf20Sopenharmony_ci	 * hash_alg wasn't gotten via crypto_grab*(), so we need to inherit its
5678c2ecf20Sopenharmony_ci	 * flags manually.
5688c2ecf20Sopenharmony_ci	 */
5698c2ecf20Sopenharmony_ci	base->cra_flags        |= (hash_alg->base.cra_flags &
5708c2ecf20Sopenharmony_ci				   CRYPTO_ALG_INHERITED_FLAGS);
5718c2ecf20Sopenharmony_ci	base->cra_blocksize	= block_base->cra_blocksize;
5728c2ecf20Sopenharmony_ci	base->cra_ctxsize	= sizeof(struct essiv_tfm_ctx);
5738c2ecf20Sopenharmony_ci	base->cra_alignmask	= block_base->cra_alignmask;
5748c2ecf20Sopenharmony_ci	base->cra_priority	= block_base->cra_priority;
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	if (type == CRYPTO_ALG_TYPE_SKCIPHER) {
5778c2ecf20Sopenharmony_ci		skcipher_inst->alg.setkey	= essiv_skcipher_setkey;
5788c2ecf20Sopenharmony_ci		skcipher_inst->alg.encrypt	= essiv_skcipher_encrypt;
5798c2ecf20Sopenharmony_ci		skcipher_inst->alg.decrypt	= essiv_skcipher_decrypt;
5808c2ecf20Sopenharmony_ci		skcipher_inst->alg.init		= essiv_skcipher_init_tfm;
5818c2ecf20Sopenharmony_ci		skcipher_inst->alg.exit		= essiv_skcipher_exit_tfm;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci		skcipher_inst->alg.min_keysize	= crypto_skcipher_alg_min_keysize(skcipher_alg);
5848c2ecf20Sopenharmony_ci		skcipher_inst->alg.max_keysize	= crypto_skcipher_alg_max_keysize(skcipher_alg);
5858c2ecf20Sopenharmony_ci		skcipher_inst->alg.ivsize	= ivsize;
5868c2ecf20Sopenharmony_ci		skcipher_inst->alg.chunksize	= crypto_skcipher_alg_chunksize(skcipher_alg);
5878c2ecf20Sopenharmony_ci		skcipher_inst->alg.walksize	= crypto_skcipher_alg_walksize(skcipher_alg);
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci		skcipher_inst->free		= essiv_skcipher_free_instance;
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci		err = skcipher_register_instance(tmpl, skcipher_inst);
5928c2ecf20Sopenharmony_ci	} else {
5938c2ecf20Sopenharmony_ci		aead_inst->alg.setkey		= essiv_aead_setkey;
5948c2ecf20Sopenharmony_ci		aead_inst->alg.setauthsize	= essiv_aead_setauthsize;
5958c2ecf20Sopenharmony_ci		aead_inst->alg.encrypt		= essiv_aead_encrypt;
5968c2ecf20Sopenharmony_ci		aead_inst->alg.decrypt		= essiv_aead_decrypt;
5978c2ecf20Sopenharmony_ci		aead_inst->alg.init		= essiv_aead_init_tfm;
5988c2ecf20Sopenharmony_ci		aead_inst->alg.exit		= essiv_aead_exit_tfm;
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci		aead_inst->alg.ivsize		= ivsize;
6018c2ecf20Sopenharmony_ci		aead_inst->alg.maxauthsize	= crypto_aead_alg_maxauthsize(aead_alg);
6028c2ecf20Sopenharmony_ci		aead_inst->alg.chunksize	= crypto_aead_alg_chunksize(aead_alg);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci		aead_inst->free			= essiv_aead_free_instance;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci		err = aead_register_instance(tmpl, aead_inst);
6078c2ecf20Sopenharmony_ci	}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	if (err)
6108c2ecf20Sopenharmony_ci		goto out_free_hash;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	crypto_mod_put(_hash_alg);
6138c2ecf20Sopenharmony_ci	return 0;
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ciout_free_hash:
6168c2ecf20Sopenharmony_ci	crypto_mod_put(_hash_alg);
6178c2ecf20Sopenharmony_ciout_drop_skcipher:
6188c2ecf20Sopenharmony_ci	if (type == CRYPTO_ALG_TYPE_SKCIPHER)
6198c2ecf20Sopenharmony_ci		crypto_drop_skcipher(&ictx->u.skcipher_spawn);
6208c2ecf20Sopenharmony_ci	else
6218c2ecf20Sopenharmony_ci		crypto_drop_aead(&ictx->u.aead_spawn);
6228c2ecf20Sopenharmony_ciout_free_inst:
6238c2ecf20Sopenharmony_ci	kfree(skcipher_inst);
6248c2ecf20Sopenharmony_ci	kfree(aead_inst);
6258c2ecf20Sopenharmony_ci	return err;
6268c2ecf20Sopenharmony_ci}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci/* essiv(cipher_name, shash_name) */
6298c2ecf20Sopenharmony_cistatic struct crypto_template essiv_tmpl = {
6308c2ecf20Sopenharmony_ci	.name	= "essiv",
6318c2ecf20Sopenharmony_ci	.create	= essiv_create,
6328c2ecf20Sopenharmony_ci	.module	= THIS_MODULE,
6338c2ecf20Sopenharmony_ci};
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_cistatic int __init essiv_module_init(void)
6368c2ecf20Sopenharmony_ci{
6378c2ecf20Sopenharmony_ci	return crypto_register_template(&essiv_tmpl);
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_cistatic void __exit essiv_module_exit(void)
6418c2ecf20Sopenharmony_ci{
6428c2ecf20Sopenharmony_ci	crypto_unregister_template(&essiv_tmpl);
6438c2ecf20Sopenharmony_ci}
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_cisubsys_initcall(essiv_module_init);
6468c2ecf20Sopenharmony_cimodule_exit(essiv_module_exit);
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ESSIV skcipher/aead wrapper for block encryption");
6498c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
6508c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("essiv");
651