162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * ESSIV skcipher and aead template for block encryption
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * This template encapsulates the ESSIV IV generation algorithm used by
662306a36Sopenharmony_ci * dm-crypt and fscrypt, which converts the initial vector for the skcipher
762306a36Sopenharmony_ci * used for block encryption, by encrypting it using the hash of the
862306a36Sopenharmony_ci * skcipher key as encryption key. Usually, the input IV is a 64-bit sector
962306a36Sopenharmony_ci * number in LE representation zero-padded to the size of the IV, but this
1062306a36Sopenharmony_ci * is not assumed by this driver.
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * The typical use of this template is to instantiate the skcipher
1362306a36Sopenharmony_ci * 'essiv(cbc(aes),sha256)', which is the only instantiation used by
1462306a36Sopenharmony_ci * fscrypt, and the most relevant one for dm-crypt. However, dm-crypt
1562306a36Sopenharmony_ci * also permits ESSIV to be used in combination with the authenc template,
1662306a36Sopenharmony_ci * e.g., 'essiv(authenc(hmac(sha256),cbc(aes)),sha256)', in which case
1762306a36Sopenharmony_ci * we need to instantiate an aead that accepts the same special key format
1862306a36Sopenharmony_ci * as the authenc template, and deals with the way the encrypted IV is
1962306a36Sopenharmony_ci * embedded into the AAD area of the aead request. This means the AEAD
2062306a36Sopenharmony_ci * flavor produced by this template is tightly coupled to the way dm-crypt
2162306a36Sopenharmony_ci * happens to use it.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * Copyright (c) 2019 Linaro, Ltd. <ard.biesheuvel@linaro.org>
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * Heavily based on:
2662306a36Sopenharmony_ci * adiantum length-preserving encryption mode
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci * Copyright 2018 Google LLC
2962306a36Sopenharmony_ci */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include <crypto/authenc.h>
3262306a36Sopenharmony_ci#include <crypto/internal/aead.h>
3362306a36Sopenharmony_ci#include <crypto/internal/cipher.h>
3462306a36Sopenharmony_ci#include <crypto/internal/hash.h>
3562306a36Sopenharmony_ci#include <crypto/internal/skcipher.h>
3662306a36Sopenharmony_ci#include <crypto/scatterwalk.h>
3762306a36Sopenharmony_ci#include <linux/module.h>
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#include "internal.h"
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistruct essiv_instance_ctx {
4262306a36Sopenharmony_ci	union {
4362306a36Sopenharmony_ci		struct crypto_skcipher_spawn	skcipher_spawn;
4462306a36Sopenharmony_ci		struct crypto_aead_spawn	aead_spawn;
4562306a36Sopenharmony_ci	} u;
4662306a36Sopenharmony_ci	char	essiv_cipher_name[CRYPTO_MAX_ALG_NAME];
4762306a36Sopenharmony_ci	char	shash_driver_name[CRYPTO_MAX_ALG_NAME];
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistruct essiv_tfm_ctx {
5162306a36Sopenharmony_ci	union {
5262306a36Sopenharmony_ci		struct crypto_skcipher	*skcipher;
5362306a36Sopenharmony_ci		struct crypto_aead	*aead;
5462306a36Sopenharmony_ci	} u;
5562306a36Sopenharmony_ci	struct crypto_cipher		*essiv_cipher;
5662306a36Sopenharmony_ci	struct crypto_shash		*hash;
5762306a36Sopenharmony_ci	int				ivoffset;
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistruct essiv_aead_request_ctx {
6162306a36Sopenharmony_ci	struct scatterlist		sg[4];
6262306a36Sopenharmony_ci	u8				*assoc;
6362306a36Sopenharmony_ci	struct aead_request		aead_req;
6462306a36Sopenharmony_ci};
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic int essiv_skcipher_setkey(struct crypto_skcipher *tfm,
6762306a36Sopenharmony_ci				 const u8 *key, unsigned int keylen)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
7062306a36Sopenharmony_ci	u8 salt[HASH_MAX_DIGESTSIZE];
7162306a36Sopenharmony_ci	int err;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	crypto_skcipher_clear_flags(tctx->u.skcipher, CRYPTO_TFM_REQ_MASK);
7462306a36Sopenharmony_ci	crypto_skcipher_set_flags(tctx->u.skcipher,
7562306a36Sopenharmony_ci				  crypto_skcipher_get_flags(tfm) &
7662306a36Sopenharmony_ci				  CRYPTO_TFM_REQ_MASK);
7762306a36Sopenharmony_ci	err = crypto_skcipher_setkey(tctx->u.skcipher, key, keylen);
7862306a36Sopenharmony_ci	if (err)
7962306a36Sopenharmony_ci		return err;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	err = crypto_shash_tfm_digest(tctx->hash, key, keylen, salt);
8262306a36Sopenharmony_ci	if (err)
8362306a36Sopenharmony_ci		return err;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	crypto_cipher_clear_flags(tctx->essiv_cipher, CRYPTO_TFM_REQ_MASK);
8662306a36Sopenharmony_ci	crypto_cipher_set_flags(tctx->essiv_cipher,
8762306a36Sopenharmony_ci				crypto_skcipher_get_flags(tfm) &
8862306a36Sopenharmony_ci				CRYPTO_TFM_REQ_MASK);
8962306a36Sopenharmony_ci	return crypto_cipher_setkey(tctx->essiv_cipher, salt,
9062306a36Sopenharmony_ci				    crypto_shash_digestsize(tctx->hash));
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic int essiv_aead_setkey(struct crypto_aead *tfm, const u8 *key,
9462306a36Sopenharmony_ci			     unsigned int keylen)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
9762306a36Sopenharmony_ci	SHASH_DESC_ON_STACK(desc, tctx->hash);
9862306a36Sopenharmony_ci	struct crypto_authenc_keys keys;
9962306a36Sopenharmony_ci	u8 salt[HASH_MAX_DIGESTSIZE];
10062306a36Sopenharmony_ci	int err;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	crypto_aead_clear_flags(tctx->u.aead, CRYPTO_TFM_REQ_MASK);
10362306a36Sopenharmony_ci	crypto_aead_set_flags(tctx->u.aead, crypto_aead_get_flags(tfm) &
10462306a36Sopenharmony_ci					    CRYPTO_TFM_REQ_MASK);
10562306a36Sopenharmony_ci	err = crypto_aead_setkey(tctx->u.aead, key, keylen);
10662306a36Sopenharmony_ci	if (err)
10762306a36Sopenharmony_ci		return err;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
11062306a36Sopenharmony_ci		return -EINVAL;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	desc->tfm = tctx->hash;
11362306a36Sopenharmony_ci	err = crypto_shash_init(desc) ?:
11462306a36Sopenharmony_ci	      crypto_shash_update(desc, keys.enckey, keys.enckeylen) ?:
11562306a36Sopenharmony_ci	      crypto_shash_finup(desc, keys.authkey, keys.authkeylen, salt);
11662306a36Sopenharmony_ci	if (err)
11762306a36Sopenharmony_ci		return err;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	crypto_cipher_clear_flags(tctx->essiv_cipher, CRYPTO_TFM_REQ_MASK);
12062306a36Sopenharmony_ci	crypto_cipher_set_flags(tctx->essiv_cipher, crypto_aead_get_flags(tfm) &
12162306a36Sopenharmony_ci						    CRYPTO_TFM_REQ_MASK);
12262306a36Sopenharmony_ci	return crypto_cipher_setkey(tctx->essiv_cipher, salt,
12362306a36Sopenharmony_ci				    crypto_shash_digestsize(tctx->hash));
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic int essiv_aead_setauthsize(struct crypto_aead *tfm,
12762306a36Sopenharmony_ci				  unsigned int authsize)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	return crypto_aead_setauthsize(tctx->u.aead, authsize);
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic void essiv_skcipher_done(void *data, int err)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	struct skcipher_request *req = data;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	skcipher_request_complete(req, err);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic int essiv_skcipher_crypt(struct skcipher_request *req, bool enc)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
14462306a36Sopenharmony_ci	const struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
14562306a36Sopenharmony_ci	struct skcipher_request *subreq = skcipher_request_ctx(req);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	skcipher_request_set_tfm(subreq, tctx->u.skcipher);
15062306a36Sopenharmony_ci	skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
15162306a36Sopenharmony_ci				   req->iv);
15262306a36Sopenharmony_ci	skcipher_request_set_callback(subreq, skcipher_request_flags(req),
15362306a36Sopenharmony_ci				      essiv_skcipher_done, req);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	return enc ? crypto_skcipher_encrypt(subreq) :
15662306a36Sopenharmony_ci		     crypto_skcipher_decrypt(subreq);
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cistatic int essiv_skcipher_encrypt(struct skcipher_request *req)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	return essiv_skcipher_crypt(req, true);
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic int essiv_skcipher_decrypt(struct skcipher_request *req)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	return essiv_skcipher_crypt(req, false);
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistatic void essiv_aead_done(void *data, int err)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	struct aead_request *req = data;
17262306a36Sopenharmony_ci	struct essiv_aead_request_ctx *rctx = aead_request_ctx(req);
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	if (err == -EINPROGRESS)
17562306a36Sopenharmony_ci		goto out;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	kfree(rctx->assoc);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ciout:
18062306a36Sopenharmony_ci	aead_request_complete(req, err);
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cistatic int essiv_aead_crypt(struct aead_request *req, bool enc)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
18662306a36Sopenharmony_ci	const struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
18762306a36Sopenharmony_ci	struct essiv_aead_request_ctx *rctx = aead_request_ctx(req);
18862306a36Sopenharmony_ci	struct aead_request *subreq = &rctx->aead_req;
18962306a36Sopenharmony_ci	struct scatterlist *src = req->src;
19062306a36Sopenharmony_ci	int err;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv);
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	/*
19562306a36Sopenharmony_ci	 * dm-crypt embeds the sector number and the IV in the AAD region, so
19662306a36Sopenharmony_ci	 * we have to copy the converted IV into the right scatterlist before
19762306a36Sopenharmony_ci	 * we pass it on.
19862306a36Sopenharmony_ci	 */
19962306a36Sopenharmony_ci	rctx->assoc = NULL;
20062306a36Sopenharmony_ci	if (req->src == req->dst || !enc) {
20162306a36Sopenharmony_ci		scatterwalk_map_and_copy(req->iv, req->dst,
20262306a36Sopenharmony_ci					 req->assoclen - crypto_aead_ivsize(tfm),
20362306a36Sopenharmony_ci					 crypto_aead_ivsize(tfm), 1);
20462306a36Sopenharmony_ci	} else {
20562306a36Sopenharmony_ci		u8 *iv = (u8 *)aead_request_ctx(req) + tctx->ivoffset;
20662306a36Sopenharmony_ci		int ivsize = crypto_aead_ivsize(tfm);
20762306a36Sopenharmony_ci		int ssize = req->assoclen - ivsize;
20862306a36Sopenharmony_ci		struct scatterlist *sg;
20962306a36Sopenharmony_ci		int nents;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci		if (ssize < 0)
21262306a36Sopenharmony_ci			return -EINVAL;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci		nents = sg_nents_for_len(req->src, ssize);
21562306a36Sopenharmony_ci		if (nents < 0)
21662306a36Sopenharmony_ci			return -EINVAL;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci		memcpy(iv, req->iv, ivsize);
21962306a36Sopenharmony_ci		sg_init_table(rctx->sg, 4);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci		if (unlikely(nents > 1)) {
22262306a36Sopenharmony_ci			/*
22362306a36Sopenharmony_ci			 * This is a case that rarely occurs in practice, but
22462306a36Sopenharmony_ci			 * for correctness, we have to deal with it nonetheless.
22562306a36Sopenharmony_ci			 */
22662306a36Sopenharmony_ci			rctx->assoc = kmalloc(ssize, GFP_ATOMIC);
22762306a36Sopenharmony_ci			if (!rctx->assoc)
22862306a36Sopenharmony_ci				return -ENOMEM;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci			scatterwalk_map_and_copy(rctx->assoc, req->src, 0,
23162306a36Sopenharmony_ci						 ssize, 0);
23262306a36Sopenharmony_ci			sg_set_buf(rctx->sg, rctx->assoc, ssize);
23362306a36Sopenharmony_ci		} else {
23462306a36Sopenharmony_ci			sg_set_page(rctx->sg, sg_page(req->src), ssize,
23562306a36Sopenharmony_ci				    req->src->offset);
23662306a36Sopenharmony_ci		}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci		sg_set_buf(rctx->sg + 1, iv, ivsize);
23962306a36Sopenharmony_ci		sg = scatterwalk_ffwd(rctx->sg + 2, req->src, req->assoclen);
24062306a36Sopenharmony_ci		if (sg != rctx->sg + 2)
24162306a36Sopenharmony_ci			sg_chain(rctx->sg, 3, sg);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci		src = rctx->sg;
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	aead_request_set_tfm(subreq, tctx->u.aead);
24762306a36Sopenharmony_ci	aead_request_set_ad(subreq, req->assoclen);
24862306a36Sopenharmony_ci	aead_request_set_callback(subreq, aead_request_flags(req),
24962306a36Sopenharmony_ci				  essiv_aead_done, req);
25062306a36Sopenharmony_ci	aead_request_set_crypt(subreq, src, req->dst, req->cryptlen, req->iv);
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	err = enc ? crypto_aead_encrypt(subreq) :
25362306a36Sopenharmony_ci		    crypto_aead_decrypt(subreq);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	if (rctx->assoc && err != -EINPROGRESS && err != -EBUSY)
25662306a36Sopenharmony_ci		kfree(rctx->assoc);
25762306a36Sopenharmony_ci	return err;
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic int essiv_aead_encrypt(struct aead_request *req)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	return essiv_aead_crypt(req, true);
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic int essiv_aead_decrypt(struct aead_request *req)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	return essiv_aead_crypt(req, false);
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic int essiv_init_tfm(struct essiv_instance_ctx *ictx,
27162306a36Sopenharmony_ci			  struct essiv_tfm_ctx *tctx)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	struct crypto_cipher *essiv_cipher;
27462306a36Sopenharmony_ci	struct crypto_shash *hash;
27562306a36Sopenharmony_ci	int err;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	essiv_cipher = crypto_alloc_cipher(ictx->essiv_cipher_name, 0, 0);
27862306a36Sopenharmony_ci	if (IS_ERR(essiv_cipher))
27962306a36Sopenharmony_ci		return PTR_ERR(essiv_cipher);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	hash = crypto_alloc_shash(ictx->shash_driver_name, 0, 0);
28262306a36Sopenharmony_ci	if (IS_ERR(hash)) {
28362306a36Sopenharmony_ci		err = PTR_ERR(hash);
28462306a36Sopenharmony_ci		goto err_free_essiv_cipher;
28562306a36Sopenharmony_ci	}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	tctx->essiv_cipher = essiv_cipher;
28862306a36Sopenharmony_ci	tctx->hash = hash;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	return 0;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_cierr_free_essiv_cipher:
29362306a36Sopenharmony_ci	crypto_free_cipher(essiv_cipher);
29462306a36Sopenharmony_ci	return err;
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_cistatic int essiv_skcipher_init_tfm(struct crypto_skcipher *tfm)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
30062306a36Sopenharmony_ci	struct essiv_instance_ctx *ictx = skcipher_instance_ctx(inst);
30162306a36Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
30262306a36Sopenharmony_ci	struct crypto_skcipher *skcipher;
30362306a36Sopenharmony_ci	int err;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	skcipher = crypto_spawn_skcipher(&ictx->u.skcipher_spawn);
30662306a36Sopenharmony_ci	if (IS_ERR(skcipher))
30762306a36Sopenharmony_ci		return PTR_ERR(skcipher);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	crypto_skcipher_set_reqsize(tfm, sizeof(struct skcipher_request) +
31062306a36Sopenharmony_ci				         crypto_skcipher_reqsize(skcipher));
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	err = essiv_init_tfm(ictx, tctx);
31362306a36Sopenharmony_ci	if (err) {
31462306a36Sopenharmony_ci		crypto_free_skcipher(skcipher);
31562306a36Sopenharmony_ci		return err;
31662306a36Sopenharmony_ci	}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	tctx->u.skcipher = skcipher;
31962306a36Sopenharmony_ci	return 0;
32062306a36Sopenharmony_ci}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_cistatic int essiv_aead_init_tfm(struct crypto_aead *tfm)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	struct aead_instance *inst = aead_alg_instance(tfm);
32562306a36Sopenharmony_ci	struct essiv_instance_ctx *ictx = aead_instance_ctx(inst);
32662306a36Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
32762306a36Sopenharmony_ci	struct crypto_aead *aead;
32862306a36Sopenharmony_ci	unsigned int subreq_size;
32962306a36Sopenharmony_ci	int err;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	BUILD_BUG_ON(offsetofend(struct essiv_aead_request_ctx, aead_req) !=
33262306a36Sopenharmony_ci		     sizeof(struct essiv_aead_request_ctx));
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	aead = crypto_spawn_aead(&ictx->u.aead_spawn);
33562306a36Sopenharmony_ci	if (IS_ERR(aead))
33662306a36Sopenharmony_ci		return PTR_ERR(aead);
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	subreq_size = sizeof_field(struct essiv_aead_request_ctx, aead_req) +
33962306a36Sopenharmony_ci		      crypto_aead_reqsize(aead);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	tctx->ivoffset = offsetof(struct essiv_aead_request_ctx, aead_req) +
34262306a36Sopenharmony_ci			 subreq_size;
34362306a36Sopenharmony_ci	crypto_aead_set_reqsize(tfm, tctx->ivoffset + crypto_aead_ivsize(aead));
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	err = essiv_init_tfm(ictx, tctx);
34662306a36Sopenharmony_ci	if (err) {
34762306a36Sopenharmony_ci		crypto_free_aead(aead);
34862306a36Sopenharmony_ci		return err;
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	tctx->u.aead = aead;
35262306a36Sopenharmony_ci	return 0;
35362306a36Sopenharmony_ci}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_cistatic void essiv_skcipher_exit_tfm(struct crypto_skcipher *tfm)
35662306a36Sopenharmony_ci{
35762306a36Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	crypto_free_skcipher(tctx->u.skcipher);
36062306a36Sopenharmony_ci	crypto_free_cipher(tctx->essiv_cipher);
36162306a36Sopenharmony_ci	crypto_free_shash(tctx->hash);
36262306a36Sopenharmony_ci}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_cistatic void essiv_aead_exit_tfm(struct crypto_aead *tfm)
36562306a36Sopenharmony_ci{
36662306a36Sopenharmony_ci	struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	crypto_free_aead(tctx->u.aead);
36962306a36Sopenharmony_ci	crypto_free_cipher(tctx->essiv_cipher);
37062306a36Sopenharmony_ci	crypto_free_shash(tctx->hash);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic void essiv_skcipher_free_instance(struct skcipher_instance *inst)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	struct essiv_instance_ctx *ictx = skcipher_instance_ctx(inst);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	crypto_drop_skcipher(&ictx->u.skcipher_spawn);
37862306a36Sopenharmony_ci	kfree(inst);
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_cistatic void essiv_aead_free_instance(struct aead_instance *inst)
38262306a36Sopenharmony_ci{
38362306a36Sopenharmony_ci	struct essiv_instance_ctx *ictx = aead_instance_ctx(inst);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	crypto_drop_aead(&ictx->u.aead_spawn);
38662306a36Sopenharmony_ci	kfree(inst);
38762306a36Sopenharmony_ci}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic bool parse_cipher_name(char *essiv_cipher_name, const char *cra_name)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	const char *p, *q;
39262306a36Sopenharmony_ci	int len;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/* find the last opening parens */
39562306a36Sopenharmony_ci	p = strrchr(cra_name, '(');
39662306a36Sopenharmony_ci	if (!p++)
39762306a36Sopenharmony_ci		return false;
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	/* find the first closing parens in the tail of the string */
40062306a36Sopenharmony_ci	q = strchr(p, ')');
40162306a36Sopenharmony_ci	if (!q)
40262306a36Sopenharmony_ci		return false;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	len = q - p;
40562306a36Sopenharmony_ci	if (len >= CRYPTO_MAX_ALG_NAME)
40662306a36Sopenharmony_ci		return false;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	memcpy(essiv_cipher_name, p, len);
40962306a36Sopenharmony_ci	essiv_cipher_name[len] = '\0';
41062306a36Sopenharmony_ci	return true;
41162306a36Sopenharmony_ci}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_cistatic bool essiv_supported_algorithms(const char *essiv_cipher_name,
41462306a36Sopenharmony_ci				       struct shash_alg *hash_alg,
41562306a36Sopenharmony_ci				       int ivsize)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	struct crypto_alg *alg;
41862306a36Sopenharmony_ci	bool ret = false;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	alg = crypto_alg_mod_lookup(essiv_cipher_name,
42162306a36Sopenharmony_ci				    CRYPTO_ALG_TYPE_CIPHER,
42262306a36Sopenharmony_ci				    CRYPTO_ALG_TYPE_MASK);
42362306a36Sopenharmony_ci	if (IS_ERR(alg))
42462306a36Sopenharmony_ci		return false;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	if (hash_alg->digestsize < alg->cra_cipher.cia_min_keysize ||
42762306a36Sopenharmony_ci	    hash_alg->digestsize > alg->cra_cipher.cia_max_keysize)
42862306a36Sopenharmony_ci		goto out;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	if (ivsize != alg->cra_blocksize)
43162306a36Sopenharmony_ci		goto out;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	if (crypto_shash_alg_needs_key(hash_alg))
43462306a36Sopenharmony_ci		goto out;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	ret = true;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ciout:
43962306a36Sopenharmony_ci	crypto_mod_put(alg);
44062306a36Sopenharmony_ci	return ret;
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_cistatic int essiv_create(struct crypto_template *tmpl, struct rtattr **tb)
44462306a36Sopenharmony_ci{
44562306a36Sopenharmony_ci	struct crypto_attr_type *algt;
44662306a36Sopenharmony_ci	const char *inner_cipher_name;
44762306a36Sopenharmony_ci	const char *shash_name;
44862306a36Sopenharmony_ci	struct skcipher_instance *skcipher_inst = NULL;
44962306a36Sopenharmony_ci	struct aead_instance *aead_inst = NULL;
45062306a36Sopenharmony_ci	struct crypto_instance *inst;
45162306a36Sopenharmony_ci	struct crypto_alg *base, *block_base;
45262306a36Sopenharmony_ci	struct essiv_instance_ctx *ictx;
45362306a36Sopenharmony_ci	struct skcipher_alg *skcipher_alg = NULL;
45462306a36Sopenharmony_ci	struct aead_alg *aead_alg = NULL;
45562306a36Sopenharmony_ci	struct crypto_alg *_hash_alg;
45662306a36Sopenharmony_ci	struct shash_alg *hash_alg;
45762306a36Sopenharmony_ci	int ivsize;
45862306a36Sopenharmony_ci	u32 type;
45962306a36Sopenharmony_ci	u32 mask;
46062306a36Sopenharmony_ci	int err;
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	algt = crypto_get_attr_type(tb);
46362306a36Sopenharmony_ci	if (IS_ERR(algt))
46462306a36Sopenharmony_ci		return PTR_ERR(algt);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	inner_cipher_name = crypto_attr_alg_name(tb[1]);
46762306a36Sopenharmony_ci	if (IS_ERR(inner_cipher_name))
46862306a36Sopenharmony_ci		return PTR_ERR(inner_cipher_name);
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	shash_name = crypto_attr_alg_name(tb[2]);
47162306a36Sopenharmony_ci	if (IS_ERR(shash_name))
47262306a36Sopenharmony_ci		return PTR_ERR(shash_name);
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	type = algt->type & algt->mask;
47562306a36Sopenharmony_ci	mask = crypto_algt_inherited_mask(algt);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	switch (type) {
47862306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_SKCIPHER:
47962306a36Sopenharmony_ci		skcipher_inst = kzalloc(sizeof(*skcipher_inst) +
48062306a36Sopenharmony_ci					sizeof(*ictx), GFP_KERNEL);
48162306a36Sopenharmony_ci		if (!skcipher_inst)
48262306a36Sopenharmony_ci			return -ENOMEM;
48362306a36Sopenharmony_ci		inst = skcipher_crypto_instance(skcipher_inst);
48462306a36Sopenharmony_ci		base = &skcipher_inst->alg.base;
48562306a36Sopenharmony_ci		ictx = crypto_instance_ctx(inst);
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci		/* Symmetric cipher, e.g., "cbc(aes)" */
48862306a36Sopenharmony_ci		err = crypto_grab_skcipher(&ictx->u.skcipher_spawn, inst,
48962306a36Sopenharmony_ci					   inner_cipher_name, 0, mask);
49062306a36Sopenharmony_ci		if (err)
49162306a36Sopenharmony_ci			goto out_free_inst;
49262306a36Sopenharmony_ci		skcipher_alg = crypto_spawn_skcipher_alg(&ictx->u.skcipher_spawn);
49362306a36Sopenharmony_ci		block_base = &skcipher_alg->base;
49462306a36Sopenharmony_ci		ivsize = crypto_skcipher_alg_ivsize(skcipher_alg);
49562306a36Sopenharmony_ci		break;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	case CRYPTO_ALG_TYPE_AEAD:
49862306a36Sopenharmony_ci		aead_inst = kzalloc(sizeof(*aead_inst) +
49962306a36Sopenharmony_ci				    sizeof(*ictx), GFP_KERNEL);
50062306a36Sopenharmony_ci		if (!aead_inst)
50162306a36Sopenharmony_ci			return -ENOMEM;
50262306a36Sopenharmony_ci		inst = aead_crypto_instance(aead_inst);
50362306a36Sopenharmony_ci		base = &aead_inst->alg.base;
50462306a36Sopenharmony_ci		ictx = crypto_instance_ctx(inst);
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci		/* AEAD cipher, e.g., "authenc(hmac(sha256),cbc(aes))" */
50762306a36Sopenharmony_ci		err = crypto_grab_aead(&ictx->u.aead_spawn, inst,
50862306a36Sopenharmony_ci				       inner_cipher_name, 0, mask);
50962306a36Sopenharmony_ci		if (err)
51062306a36Sopenharmony_ci			goto out_free_inst;
51162306a36Sopenharmony_ci		aead_alg = crypto_spawn_aead_alg(&ictx->u.aead_spawn);
51262306a36Sopenharmony_ci		block_base = &aead_alg->base;
51362306a36Sopenharmony_ci		if (!strstarts(block_base->cra_name, "authenc(")) {
51462306a36Sopenharmony_ci			pr_warn("Only authenc() type AEADs are supported by ESSIV\n");
51562306a36Sopenharmony_ci			err = -EINVAL;
51662306a36Sopenharmony_ci			goto out_drop_skcipher;
51762306a36Sopenharmony_ci		}
51862306a36Sopenharmony_ci		ivsize = aead_alg->ivsize;
51962306a36Sopenharmony_ci		break;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	default:
52262306a36Sopenharmony_ci		return -EINVAL;
52362306a36Sopenharmony_ci	}
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	if (!parse_cipher_name(ictx->essiv_cipher_name, block_base->cra_name)) {
52662306a36Sopenharmony_ci		pr_warn("Failed to parse ESSIV cipher name from skcipher cra_name\n");
52762306a36Sopenharmony_ci		err = -EINVAL;
52862306a36Sopenharmony_ci		goto out_drop_skcipher;
52962306a36Sopenharmony_ci	}
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	/* Synchronous hash, e.g., "sha256" */
53262306a36Sopenharmony_ci	_hash_alg = crypto_alg_mod_lookup(shash_name,
53362306a36Sopenharmony_ci					  CRYPTO_ALG_TYPE_SHASH,
53462306a36Sopenharmony_ci					  CRYPTO_ALG_TYPE_MASK | mask);
53562306a36Sopenharmony_ci	if (IS_ERR(_hash_alg)) {
53662306a36Sopenharmony_ci		err = PTR_ERR(_hash_alg);
53762306a36Sopenharmony_ci		goto out_drop_skcipher;
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci	hash_alg = __crypto_shash_alg(_hash_alg);
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	/* Check the set of algorithms */
54262306a36Sopenharmony_ci	if (!essiv_supported_algorithms(ictx->essiv_cipher_name, hash_alg,
54362306a36Sopenharmony_ci					ivsize)) {
54462306a36Sopenharmony_ci		pr_warn("Unsupported essiv instantiation: essiv(%s,%s)\n",
54562306a36Sopenharmony_ci			block_base->cra_name, hash_alg->base.cra_name);
54662306a36Sopenharmony_ci		err = -EINVAL;
54762306a36Sopenharmony_ci		goto out_free_hash;
54862306a36Sopenharmony_ci	}
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	/* record the driver name so we can instantiate this exact algo later */
55162306a36Sopenharmony_ci	strscpy(ictx->shash_driver_name, hash_alg->base.cra_driver_name,
55262306a36Sopenharmony_ci		CRYPTO_MAX_ALG_NAME);
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	/* Instance fields */
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	err = -ENAMETOOLONG;
55762306a36Sopenharmony_ci	if (snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME,
55862306a36Sopenharmony_ci		     "essiv(%s,%s)", block_base->cra_name,
55962306a36Sopenharmony_ci		     hash_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
56062306a36Sopenharmony_ci		goto out_free_hash;
56162306a36Sopenharmony_ci	if (snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME,
56262306a36Sopenharmony_ci		     "essiv(%s,%s)", block_base->cra_driver_name,
56362306a36Sopenharmony_ci		     hash_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
56462306a36Sopenharmony_ci		goto out_free_hash;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	/*
56762306a36Sopenharmony_ci	 * hash_alg wasn't gotten via crypto_grab*(), so we need to inherit its
56862306a36Sopenharmony_ci	 * flags manually.
56962306a36Sopenharmony_ci	 */
57062306a36Sopenharmony_ci	base->cra_flags        |= (hash_alg->base.cra_flags &
57162306a36Sopenharmony_ci				   CRYPTO_ALG_INHERITED_FLAGS);
57262306a36Sopenharmony_ci	base->cra_blocksize	= block_base->cra_blocksize;
57362306a36Sopenharmony_ci	base->cra_ctxsize	= sizeof(struct essiv_tfm_ctx);
57462306a36Sopenharmony_ci	base->cra_alignmask	= block_base->cra_alignmask;
57562306a36Sopenharmony_ci	base->cra_priority	= block_base->cra_priority;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	if (type == CRYPTO_ALG_TYPE_SKCIPHER) {
57862306a36Sopenharmony_ci		skcipher_inst->alg.setkey	= essiv_skcipher_setkey;
57962306a36Sopenharmony_ci		skcipher_inst->alg.encrypt	= essiv_skcipher_encrypt;
58062306a36Sopenharmony_ci		skcipher_inst->alg.decrypt	= essiv_skcipher_decrypt;
58162306a36Sopenharmony_ci		skcipher_inst->alg.init		= essiv_skcipher_init_tfm;
58262306a36Sopenharmony_ci		skcipher_inst->alg.exit		= essiv_skcipher_exit_tfm;
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci		skcipher_inst->alg.min_keysize	= crypto_skcipher_alg_min_keysize(skcipher_alg);
58562306a36Sopenharmony_ci		skcipher_inst->alg.max_keysize	= crypto_skcipher_alg_max_keysize(skcipher_alg);
58662306a36Sopenharmony_ci		skcipher_inst->alg.ivsize	= ivsize;
58762306a36Sopenharmony_ci		skcipher_inst->alg.chunksize	= crypto_skcipher_alg_chunksize(skcipher_alg);
58862306a36Sopenharmony_ci		skcipher_inst->alg.walksize	= crypto_skcipher_alg_walksize(skcipher_alg);
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci		skcipher_inst->free		= essiv_skcipher_free_instance;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci		err = skcipher_register_instance(tmpl, skcipher_inst);
59362306a36Sopenharmony_ci	} else {
59462306a36Sopenharmony_ci		aead_inst->alg.setkey		= essiv_aead_setkey;
59562306a36Sopenharmony_ci		aead_inst->alg.setauthsize	= essiv_aead_setauthsize;
59662306a36Sopenharmony_ci		aead_inst->alg.encrypt		= essiv_aead_encrypt;
59762306a36Sopenharmony_ci		aead_inst->alg.decrypt		= essiv_aead_decrypt;
59862306a36Sopenharmony_ci		aead_inst->alg.init		= essiv_aead_init_tfm;
59962306a36Sopenharmony_ci		aead_inst->alg.exit		= essiv_aead_exit_tfm;
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci		aead_inst->alg.ivsize		= ivsize;
60262306a36Sopenharmony_ci		aead_inst->alg.maxauthsize	= crypto_aead_alg_maxauthsize(aead_alg);
60362306a36Sopenharmony_ci		aead_inst->alg.chunksize	= crypto_aead_alg_chunksize(aead_alg);
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci		aead_inst->free			= essiv_aead_free_instance;
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci		err = aead_register_instance(tmpl, aead_inst);
60862306a36Sopenharmony_ci	}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	if (err)
61162306a36Sopenharmony_ci		goto out_free_hash;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	crypto_mod_put(_hash_alg);
61462306a36Sopenharmony_ci	return 0;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ciout_free_hash:
61762306a36Sopenharmony_ci	crypto_mod_put(_hash_alg);
61862306a36Sopenharmony_ciout_drop_skcipher:
61962306a36Sopenharmony_ci	if (type == CRYPTO_ALG_TYPE_SKCIPHER)
62062306a36Sopenharmony_ci		crypto_drop_skcipher(&ictx->u.skcipher_spawn);
62162306a36Sopenharmony_ci	else
62262306a36Sopenharmony_ci		crypto_drop_aead(&ictx->u.aead_spawn);
62362306a36Sopenharmony_ciout_free_inst:
62462306a36Sopenharmony_ci	kfree(skcipher_inst);
62562306a36Sopenharmony_ci	kfree(aead_inst);
62662306a36Sopenharmony_ci	return err;
62762306a36Sopenharmony_ci}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci/* essiv(cipher_name, shash_name) */
63062306a36Sopenharmony_cistatic struct crypto_template essiv_tmpl = {
63162306a36Sopenharmony_ci	.name	= "essiv",
63262306a36Sopenharmony_ci	.create	= essiv_create,
63362306a36Sopenharmony_ci	.module	= THIS_MODULE,
63462306a36Sopenharmony_ci};
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cistatic int __init essiv_module_init(void)
63762306a36Sopenharmony_ci{
63862306a36Sopenharmony_ci	return crypto_register_template(&essiv_tmpl);
63962306a36Sopenharmony_ci}
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_cistatic void __exit essiv_module_exit(void)
64262306a36Sopenharmony_ci{
64362306a36Sopenharmony_ci	crypto_unregister_template(&essiv_tmpl);
64462306a36Sopenharmony_ci}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_cisubsys_initcall(essiv_module_init);
64762306a36Sopenharmony_cimodule_exit(essiv_module_exit);
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ciMODULE_DESCRIPTION("ESSIV skcipher/aead wrapper for block encryption");
65062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
65162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("essiv");
65262306a36Sopenharmony_ciMODULE_IMPORT_NS(CRYPTO_INTERNAL);
653