xref: /openbmc/linux/crypto/gcm.c (revision 255e48eb)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
228db8e3eSMikko Herranen /*
328db8e3eSMikko Herranen  * GCM: Galois/Counter Mode.
428db8e3eSMikko Herranen  *
528db8e3eSMikko Herranen  * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1@iki.fi>
628db8e3eSMikko Herranen  */
728db8e3eSMikko Herranen 
828db8e3eSMikko Herranen #include <crypto/gf128mul.h>
9dadbc53dSHerbert Xu #include <crypto/internal/aead.h>
101472e5ebSHerbert Xu #include <crypto/internal/skcipher.h>
119382d97aSHuang Ying #include <crypto/internal/hash.h>
1217db8546SHerbert Xu #include <crypto/null.h>
1342c271c6SHerbert Xu #include <crypto/scatterwalk.h>
14e0ab7e9cSCorentin LABBE #include <crypto/gcm.h>
159382d97aSHuang Ying #include <crypto/hash.h>
1628db8e3eSMikko Herranen #include <linux/err.h>
1728db8e3eSMikko Herranen #include <linux/init.h>
1828db8e3eSMikko Herranen #include <linux/kernel.h>
1928db8e3eSMikko Herranen #include <linux/module.h>
2028db8e3eSMikko Herranen #include <linux/slab.h>
2128db8e3eSMikko Herranen 
2228db8e3eSMikko Herranen struct gcm_instance_ctx {
231472e5ebSHerbert Xu 	struct crypto_skcipher_spawn ctr;
249382d97aSHuang Ying 	struct crypto_ahash_spawn ghash;
2528db8e3eSMikko Herranen };
2628db8e3eSMikko Herranen 
2728db8e3eSMikko Herranen struct crypto_gcm_ctx {
2816f37ecdSHerbert Xu 	struct crypto_skcipher *ctr;
299382d97aSHuang Ying 	struct crypto_ahash *ghash;
3028db8e3eSMikko Herranen };
3128db8e3eSMikko Herranen 
32dadbc53dSHerbert Xu struct crypto_rfc4106_ctx {
33dadbc53dSHerbert Xu 	struct crypto_aead *child;
34dadbc53dSHerbert Xu 	u8 nonce[4];
35dadbc53dSHerbert Xu };
36dadbc53dSHerbert Xu 
377b05a373SHerbert Xu struct crypto_rfc4106_req_ctx {
387b05a373SHerbert Xu 	struct scatterlist src[3];
397b05a373SHerbert Xu 	struct scatterlist dst[3];
407b05a373SHerbert Xu 	struct aead_request subreq;
417b05a373SHerbert Xu };
427b05a373SHerbert Xu 
439489667dSJussi Kivilinna struct crypto_rfc4543_instance_ctx {
449489667dSJussi Kivilinna 	struct crypto_aead_spawn aead;
459489667dSJussi Kivilinna };
469489667dSJussi Kivilinna 
4773c89c15STobias Brunner struct crypto_rfc4543_ctx {
4873c89c15STobias Brunner 	struct crypto_aead *child;
498d605398SKees Cook 	struct crypto_sync_skcipher *null;
5073c89c15STobias Brunner 	u8 nonce[4];
5173c89c15STobias Brunner };
5273c89c15STobias Brunner 
5373c89c15STobias Brunner struct crypto_rfc4543_req_ctx {
5473c89c15STobias Brunner 	struct aead_request subreq;
5573c89c15STobias Brunner };
5673c89c15STobias Brunner 
5728db8e3eSMikko Herranen struct crypto_gcm_ghash_ctx {
589382d97aSHuang Ying 	unsigned int cryptlen;
599382d97aSHuang Ying 	struct scatterlist *src;
60adcbc688SHerbert Xu 	int (*complete)(struct aead_request *req, u32 flags);
6128db8e3eSMikko Herranen };
6228db8e3eSMikko Herranen 
6328db8e3eSMikko Herranen struct crypto_gcm_req_priv_ctx {
64adcbc688SHerbert Xu 	u8 iv[16];
6528db8e3eSMikko Herranen 	u8 auth_tag[16];
666160b289SHerbert Xu 	u8 iauth_tag[16];
67adcbc688SHerbert Xu 	struct scatterlist src[3];
68adcbc688SHerbert Xu 	struct scatterlist dst[3];
69adcbc688SHerbert Xu 	struct scatterlist sg;
709382d97aSHuang Ying 	struct crypto_gcm_ghash_ctx ghash_ctx;
719382d97aSHuang Ying 	union {
729382d97aSHuang Ying 		struct ahash_request ahreq;
7316f37ecdSHerbert Xu 		struct skcipher_request skreq;
749382d97aSHuang Ying 	} u;
7528db8e3eSMikko Herranen };
7628db8e3eSMikko Herranen 
77adcbc688SHerbert Xu static struct {
78adcbc688SHerbert Xu 	u8 buf[16];
79adcbc688SHerbert Xu 	struct scatterlist sg;
80adcbc688SHerbert Xu } *gcm_zeroes;
81adcbc688SHerbert Xu 
82adcbc688SHerbert Xu static int crypto_rfc4543_copy_src_to_dst(struct aead_request *req, bool enc);
839382d97aSHuang Ying 
crypto_gcm_reqctx(struct aead_request * req)842589469dSHerbert Xu static inline struct crypto_gcm_req_priv_ctx *crypto_gcm_reqctx(
852589469dSHerbert Xu 	struct aead_request *req)
862589469dSHerbert Xu {
872589469dSHerbert Xu 	unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
882589469dSHerbert Xu 
892589469dSHerbert Xu 	return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
902589469dSHerbert Xu }
912589469dSHerbert Xu 
crypto_gcm_setkey(struct crypto_aead * aead,const u8 * key,unsigned int keylen)9228db8e3eSMikko Herranen static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key,
9328db8e3eSMikko Herranen 			     unsigned int keylen)
9428db8e3eSMikko Herranen {
9528db8e3eSMikko Herranen 	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
969382d97aSHuang Ying 	struct crypto_ahash *ghash = ctx->ghash;
9716f37ecdSHerbert Xu 	struct crypto_skcipher *ctr = ctx->ctr;
9884c91152SHerbert Xu 	struct {
9984c91152SHerbert Xu 		be128 hash;
10050d2e6dcSOndrej Mosnáček 		u8 iv[16];
10184c91152SHerbert Xu 
10276c67394SGilad Ben-Yossef 		struct crypto_wait wait;
10384c91152SHerbert Xu 
10484c91152SHerbert Xu 		struct scatterlist sg[1];
10516f37ecdSHerbert Xu 		struct skcipher_request req;
10684c91152SHerbert Xu 	} *data;
10784c91152SHerbert Xu 	int err;
10828db8e3eSMikko Herranen 
10916f37ecdSHerbert Xu 	crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
11016f37ecdSHerbert Xu 	crypto_skcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
11128db8e3eSMikko Herranen 				       CRYPTO_TFM_REQ_MASK);
11216f37ecdSHerbert Xu 	err = crypto_skcipher_setkey(ctr, key, keylen);
113adcbc688SHerbert Xu 	if (err)
114adcbc688SHerbert Xu 		return err;
11528db8e3eSMikko Herranen 
11616f37ecdSHerbert Xu 	data = kzalloc(sizeof(*data) + crypto_skcipher_reqsize(ctr),
11784c91152SHerbert Xu 		       GFP_KERNEL);
11884c91152SHerbert Xu 	if (!data)
11984c91152SHerbert Xu 		return -ENOMEM;
12084c91152SHerbert Xu 
12176c67394SGilad Ben-Yossef 	crypto_init_wait(&data->wait);
12284c91152SHerbert Xu 	sg_init_one(data->sg, &data->hash, sizeof(data->hash));
12316f37ecdSHerbert Xu 	skcipher_request_set_tfm(&data->req, ctr);
12416f37ecdSHerbert Xu 	skcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP |
12584c91152SHerbert Xu 						  CRYPTO_TFM_REQ_MAY_BACKLOG,
12676c67394SGilad Ben-Yossef 				      crypto_req_done,
12776c67394SGilad Ben-Yossef 				      &data->wait);
12816f37ecdSHerbert Xu 	skcipher_request_set_crypt(&data->req, data->sg, data->sg,
12984c91152SHerbert Xu 				   sizeof(data->hash), data->iv);
13084c91152SHerbert Xu 
13176c67394SGilad Ben-Yossef 	err = crypto_wait_req(crypto_skcipher_encrypt(&data->req),
13276c67394SGilad Ben-Yossef 							&data->wait);
13384c91152SHerbert Xu 
13428db8e3eSMikko Herranen 	if (err)
13528db8e3eSMikko Herranen 		goto out;
13628db8e3eSMikko Herranen 
1379382d97aSHuang Ying 	crypto_ahash_clear_flags(ghash, CRYPTO_TFM_REQ_MASK);
1389382d97aSHuang Ying 	crypto_ahash_set_flags(ghash, crypto_aead_get_flags(aead) &
1399382d97aSHuang Ying 			       CRYPTO_TFM_REQ_MASK);
1409382d97aSHuang Ying 	err = crypto_ahash_setkey(ghash, (u8 *)&data->hash, sizeof(be128));
14128db8e3eSMikko Herranen out:
142453431a5SWaiman Long 	kfree_sensitive(data);
14328db8e3eSMikko Herranen 	return err;
14428db8e3eSMikko Herranen }
14528db8e3eSMikko Herranen 
crypto_gcm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)146dadbc53dSHerbert Xu static int crypto_gcm_setauthsize(struct crypto_aead *tfm,
147dadbc53dSHerbert Xu 				  unsigned int authsize)
148dadbc53dSHerbert Xu {
14965526f63SIuliana Prodan 	return crypto_gcm_check_authsize(authsize);
150dadbc53dSHerbert Xu }
151dadbc53dSHerbert Xu 
crypto_gcm_init_common(struct aead_request * req)152adcbc688SHerbert Xu static void crypto_gcm_init_common(struct aead_request *req)
153adcbc688SHerbert Xu {
154adcbc688SHerbert Xu 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
155adcbc688SHerbert Xu 	__be32 counter = cpu_to_be32(1);
156adcbc688SHerbert Xu 	struct scatterlist *sg;
157adcbc688SHerbert Xu 
158adcbc688SHerbert Xu 	memset(pctx->auth_tag, 0, sizeof(pctx->auth_tag));
159e0ab7e9cSCorentin LABBE 	memcpy(pctx->iv, req->iv, GCM_AES_IV_SIZE);
160e0ab7e9cSCorentin LABBE 	memcpy(pctx->iv + GCM_AES_IV_SIZE, &counter, 4);
161adcbc688SHerbert Xu 
162adcbc688SHerbert Xu 	sg_init_table(pctx->src, 3);
163adcbc688SHerbert Xu 	sg_set_buf(pctx->src, pctx->auth_tag, sizeof(pctx->auth_tag));
164adcbc688SHerbert Xu 	sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
165adcbc688SHerbert Xu 	if (sg != pctx->src + 1)
166c56f6d12SDan Williams 		sg_chain(pctx->src, 2, sg);
167adcbc688SHerbert Xu 
168adcbc688SHerbert Xu 	if (req->src != req->dst) {
169adcbc688SHerbert Xu 		sg_init_table(pctx->dst, 3);
170adcbc688SHerbert Xu 		sg_set_buf(pctx->dst, pctx->auth_tag, sizeof(pctx->auth_tag));
171adcbc688SHerbert Xu 		sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
172adcbc688SHerbert Xu 		if (sg != pctx->dst + 1)
173c56f6d12SDan Williams 			sg_chain(pctx->dst, 2, sg);
174adcbc688SHerbert Xu 	}
175adcbc688SHerbert Xu }
176adcbc688SHerbert Xu 
crypto_gcm_init_crypt(struct aead_request * req,unsigned int cryptlen)177adcbc688SHerbert Xu static void crypto_gcm_init_crypt(struct aead_request *req,
17884c91152SHerbert Xu 				  unsigned int cryptlen)
17928db8e3eSMikko Herranen {
18028db8e3eSMikko Herranen 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
18128db8e3eSMikko Herranen 	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
1822589469dSHerbert Xu 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
18316f37ecdSHerbert Xu 	struct skcipher_request *skreq = &pctx->u.skreq;
18484c91152SHerbert Xu 	struct scatterlist *dst;
18584c91152SHerbert Xu 
186adcbc688SHerbert Xu 	dst = req->src == req->dst ? pctx->src : pctx->dst;
18728db8e3eSMikko Herranen 
18816f37ecdSHerbert Xu 	skcipher_request_set_tfm(skreq, ctx->ctr);
18916f37ecdSHerbert Xu 	skcipher_request_set_crypt(skreq, pctx->src, dst,
19084c91152SHerbert Xu 				     cryptlen + sizeof(pctx->auth_tag),
191adcbc688SHerbert Xu 				     pctx->iv);
19228db8e3eSMikko Herranen }
19328db8e3eSMikko Herranen 
gcm_remain(unsigned int len)1949382d97aSHuang Ying static inline unsigned int gcm_remain(unsigned int len)
19528db8e3eSMikko Herranen {
1969382d97aSHuang Ying 	len &= 0xfU;
1979382d97aSHuang Ying 	return len ? 16 - len : 0;
1989382d97aSHuang Ying }
1999382d97aSHuang Ying 
200*255e48ebSHerbert Xu static void gcm_hash_len_done(void *data, int err);
2019382d97aSHuang Ying 
gcm_hash_update(struct aead_request * req,crypto_completion_t compl,struct scatterlist * src,unsigned int len,u32 flags)2029382d97aSHuang Ying static int gcm_hash_update(struct aead_request *req,
2033e3dc25fSMark Rustad 			   crypto_completion_t compl,
2049382d97aSHuang Ying 			   struct scatterlist *src,
205adcbc688SHerbert Xu 			   unsigned int len, u32 flags)
2069382d97aSHuang Ying {
207adcbc688SHerbert Xu 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
2089382d97aSHuang Ying 	struct ahash_request *ahreq = &pctx->u.ahreq;
2099382d97aSHuang Ying 
210adcbc688SHerbert Xu 	ahash_request_set_callback(ahreq, flags, compl, req);
2119382d97aSHuang Ying 	ahash_request_set_crypt(ahreq, src, NULL, len);
2129382d97aSHuang Ying 
2139382d97aSHuang Ying 	return crypto_ahash_update(ahreq);
2149382d97aSHuang Ying }
2159382d97aSHuang Ying 
gcm_hash_remain(struct aead_request * req,unsigned int remain,crypto_completion_t compl,u32 flags)2169382d97aSHuang Ying static int gcm_hash_remain(struct aead_request *req,
2179382d97aSHuang Ying 			   unsigned int remain,
218adcbc688SHerbert Xu 			   crypto_completion_t compl, u32 flags)
2199382d97aSHuang Ying {
220adcbc688SHerbert Xu 	return gcm_hash_update(req, compl, &gcm_zeroes->sg, remain, flags);
2219382d97aSHuang Ying }
2229382d97aSHuang Ying 
gcm_hash_len(struct aead_request * req,u32 flags)223adcbc688SHerbert Xu static int gcm_hash_len(struct aead_request *req, u32 flags)
2249382d97aSHuang Ying {
225adcbc688SHerbert Xu 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
2269382d97aSHuang Ying 	struct ahash_request *ahreq = &pctx->u.ahreq;
2279382d97aSHuang Ying 	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
22818666550SEric Biggers 	be128 lengths;
2299382d97aSHuang Ying 
2309382d97aSHuang Ying 	lengths.a = cpu_to_be64(req->assoclen * 8);
2319382d97aSHuang Ying 	lengths.b = cpu_to_be64(gctx->cryptlen * 8);
2329382d97aSHuang Ying 	memcpy(pctx->iauth_tag, &lengths, 16);
233adcbc688SHerbert Xu 	sg_init_one(&pctx->sg, pctx->iauth_tag, 16);
234adcbc688SHerbert Xu 	ahash_request_set_callback(ahreq, flags, gcm_hash_len_done, req);
235adcbc688SHerbert Xu 	ahash_request_set_crypt(ahreq, &pctx->sg,
236adcbc688SHerbert Xu 				pctx->iauth_tag, sizeof(lengths));
2379382d97aSHuang Ying 
238adcbc688SHerbert Xu 	return crypto_ahash_finup(ahreq);
2399382d97aSHuang Ying }
2409382d97aSHuang Ying 
gcm_hash_len_continue(struct aead_request * req,u32 flags)241adcbc688SHerbert Xu static int gcm_hash_len_continue(struct aead_request *req, u32 flags)
2429382d97aSHuang Ying {
2432589469dSHerbert Xu 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
2449382d97aSHuang Ying 	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
24528db8e3eSMikko Herranen 
246adcbc688SHerbert Xu 	return gctx->complete(req, flags);
2479382d97aSHuang Ying }
2489382d97aSHuang Ying 
gcm_hash_len_done(void * data,int err)249*255e48ebSHerbert Xu static void gcm_hash_len_done(void *data, int err)
2509382d97aSHuang Ying {
251*255e48ebSHerbert Xu 	struct aead_request *req = data;
25262c5593aSHuang Ying 
253adcbc688SHerbert Xu 	if (err)
254adcbc688SHerbert Xu 		goto out;
25562c5593aSHuang Ying 
256adcbc688SHerbert Xu 	err = gcm_hash_len_continue(req, 0);
257adcbc688SHerbert Xu 	if (err == -EINPROGRESS)
2589382d97aSHuang Ying 		return;
259adcbc688SHerbert Xu 
260adcbc688SHerbert Xu out:
261adcbc688SHerbert Xu 	aead_request_complete(req, err);
2629382d97aSHuang Ying }
2639382d97aSHuang Ying 
gcm_hash_crypt_remain_continue(struct aead_request * req,u32 flags)264adcbc688SHerbert Xu static int gcm_hash_crypt_remain_continue(struct aead_request *req, u32 flags)
265adcbc688SHerbert Xu {
266adcbc688SHerbert Xu 	return gcm_hash_len(req, flags) ?:
267adcbc688SHerbert Xu 	       gcm_hash_len_continue(req, flags);
2689382d97aSHuang Ying }
2699382d97aSHuang Ying 
gcm_hash_crypt_remain_done(void * data,int err)270*255e48ebSHerbert Xu static void gcm_hash_crypt_remain_done(void *data, int err)
2719382d97aSHuang Ying {
272*255e48ebSHerbert Xu 	struct aead_request *req = data;
27362c5593aSHuang Ying 
274adcbc688SHerbert Xu 	if (err)
275adcbc688SHerbert Xu 		goto out;
276adcbc688SHerbert Xu 
277adcbc688SHerbert Xu 	err = gcm_hash_crypt_remain_continue(req, 0);
278adcbc688SHerbert Xu 	if (err == -EINPROGRESS)
279adcbc688SHerbert Xu 		return;
280adcbc688SHerbert Xu 
281adcbc688SHerbert Xu out:
282adcbc688SHerbert Xu 	aead_request_complete(req, err);
28362c5593aSHuang Ying }
28462c5593aSHuang Ying 
gcm_hash_crypt_continue(struct aead_request * req,u32 flags)285adcbc688SHerbert Xu static int gcm_hash_crypt_continue(struct aead_request *req, u32 flags)
28662c5593aSHuang Ying {
2879382d97aSHuang Ying 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
2889382d97aSHuang Ying 	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
2899382d97aSHuang Ying 	unsigned int remain;
2909382d97aSHuang Ying 
2919382d97aSHuang Ying 	remain = gcm_remain(gctx->cryptlen);
292adcbc688SHerbert Xu 	if (remain)
293adcbc688SHerbert Xu 		return gcm_hash_remain(req, remain,
294adcbc688SHerbert Xu 				       gcm_hash_crypt_remain_done, flags) ?:
295adcbc688SHerbert Xu 		       gcm_hash_crypt_remain_continue(req, flags);
2969382d97aSHuang Ying 
297adcbc688SHerbert Xu 	return gcm_hash_crypt_remain_continue(req, flags);
2989382d97aSHuang Ying }
2999382d97aSHuang Ying 
gcm_hash_crypt_done(void * data,int err)300*255e48ebSHerbert Xu static void gcm_hash_crypt_done(void *data, int err)
3019382d97aSHuang Ying {
302*255e48ebSHerbert Xu 	struct aead_request *req = data;
30362c5593aSHuang Ying 
304adcbc688SHerbert Xu 	if (err)
305adcbc688SHerbert Xu 		goto out;
306adcbc688SHerbert Xu 
307adcbc688SHerbert Xu 	err = gcm_hash_crypt_continue(req, 0);
308adcbc688SHerbert Xu 	if (err == -EINPROGRESS)
309adcbc688SHerbert Xu 		return;
310adcbc688SHerbert Xu 
311adcbc688SHerbert Xu out:
312adcbc688SHerbert Xu 	aead_request_complete(req, err);
31362c5593aSHuang Ying }
31462c5593aSHuang Ying 
gcm_hash_assoc_remain_continue(struct aead_request * req,u32 flags)315adcbc688SHerbert Xu static int gcm_hash_assoc_remain_continue(struct aead_request *req, u32 flags)
31662c5593aSHuang Ying {
3179382d97aSHuang Ying 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
3189382d97aSHuang Ying 	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
3199382d97aSHuang Ying 
320adcbc688SHerbert Xu 	if (gctx->cryptlen)
321adcbc688SHerbert Xu 		return gcm_hash_update(req, gcm_hash_crypt_done,
322adcbc688SHerbert Xu 				       gctx->src, gctx->cryptlen, flags) ?:
323adcbc688SHerbert Xu 		       gcm_hash_crypt_continue(req, flags);
3249382d97aSHuang Ying 
325adcbc688SHerbert Xu 	return gcm_hash_crypt_remain_continue(req, flags);
3269382d97aSHuang Ying }
3279382d97aSHuang Ying 
gcm_hash_assoc_remain_done(void * data,int err)328*255e48ebSHerbert Xu static void gcm_hash_assoc_remain_done(void *data, int err)
3299382d97aSHuang Ying {
330*255e48ebSHerbert Xu 	struct aead_request *req = data;
33162c5593aSHuang Ying 
332adcbc688SHerbert Xu 	if (err)
333adcbc688SHerbert Xu 		goto out;
334adcbc688SHerbert Xu 
335adcbc688SHerbert Xu 	err = gcm_hash_assoc_remain_continue(req, 0);
336adcbc688SHerbert Xu 	if (err == -EINPROGRESS)
337adcbc688SHerbert Xu 		return;
338adcbc688SHerbert Xu 
339adcbc688SHerbert Xu out:
340adcbc688SHerbert Xu 	aead_request_complete(req, err);
34162c5593aSHuang Ying }
34262c5593aSHuang Ying 
gcm_hash_assoc_continue(struct aead_request * req,u32 flags)343adcbc688SHerbert Xu static int gcm_hash_assoc_continue(struct aead_request *req, u32 flags)
34462c5593aSHuang Ying {
3459382d97aSHuang Ying 	unsigned int remain;
3469382d97aSHuang Ying 
3479382d97aSHuang Ying 	remain = gcm_remain(req->assoclen);
348adcbc688SHerbert Xu 	if (remain)
349adcbc688SHerbert Xu 		return gcm_hash_remain(req, remain,
350adcbc688SHerbert Xu 				       gcm_hash_assoc_remain_done, flags) ?:
351adcbc688SHerbert Xu 		       gcm_hash_assoc_remain_continue(req, flags);
3529382d97aSHuang Ying 
353adcbc688SHerbert Xu 	return gcm_hash_assoc_remain_continue(req, flags);
3549382d97aSHuang Ying }
3559382d97aSHuang Ying 
gcm_hash_assoc_done(void * data,int err)356*255e48ebSHerbert Xu static void gcm_hash_assoc_done(void *data, int err)
3579382d97aSHuang Ying {
358*255e48ebSHerbert Xu 	struct aead_request *req = data;
35962c5593aSHuang Ying 
360adcbc688SHerbert Xu 	if (err)
361adcbc688SHerbert Xu 		goto out;
36262c5593aSHuang Ying 
363adcbc688SHerbert Xu 	err = gcm_hash_assoc_continue(req, 0);
364adcbc688SHerbert Xu 	if (err == -EINPROGRESS)
3659382d97aSHuang Ying 		return;
366adcbc688SHerbert Xu 
367adcbc688SHerbert Xu out:
368adcbc688SHerbert Xu 	aead_request_complete(req, err);
3699382d97aSHuang Ying }
3709382d97aSHuang Ying 
gcm_hash_init_continue(struct aead_request * req,u32 flags)371adcbc688SHerbert Xu static int gcm_hash_init_continue(struct aead_request *req, u32 flags)
372adcbc688SHerbert Xu {
373adcbc688SHerbert Xu 	if (req->assoclen)
374adcbc688SHerbert Xu 		return gcm_hash_update(req, gcm_hash_assoc_done,
375adcbc688SHerbert Xu 				       req->src, req->assoclen, flags) ?:
376adcbc688SHerbert Xu 		       gcm_hash_assoc_continue(req, flags);
377adcbc688SHerbert Xu 
378adcbc688SHerbert Xu 	return gcm_hash_assoc_remain_continue(req, flags);
37962c5593aSHuang Ying }
38062c5593aSHuang Ying 
gcm_hash_init_done(void * data,int err)381*255e48ebSHerbert Xu static void gcm_hash_init_done(void *data, int err)
38262c5593aSHuang Ying {
383*255e48ebSHerbert Xu 	struct aead_request *req = data;
38462c5593aSHuang Ying 
385adcbc688SHerbert Xu 	if (err)
386adcbc688SHerbert Xu 		goto out;
387adcbc688SHerbert Xu 
388adcbc688SHerbert Xu 	err = gcm_hash_init_continue(req, 0);
389adcbc688SHerbert Xu 	if (err == -EINPROGRESS)
390adcbc688SHerbert Xu 		return;
391adcbc688SHerbert Xu 
392adcbc688SHerbert Xu out:
393adcbc688SHerbert Xu 	aead_request_complete(req, err);
3949382d97aSHuang Ying }
3959382d97aSHuang Ying 
gcm_hash(struct aead_request * req,u32 flags)396adcbc688SHerbert Xu static int gcm_hash(struct aead_request *req, u32 flags)
3979382d97aSHuang Ying {
398adcbc688SHerbert Xu 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
3999382d97aSHuang Ying 	struct ahash_request *ahreq = &pctx->u.ahreq;
400adcbc688SHerbert Xu 	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
4019382d97aSHuang Ying 
4029382d97aSHuang Ying 	ahash_request_set_tfm(ahreq, ctx->ghash);
4039382d97aSHuang Ying 
404adcbc688SHerbert Xu 	ahash_request_set_callback(ahreq, flags, gcm_hash_init_done, req);
405adcbc688SHerbert Xu 	return crypto_ahash_init(ahreq) ?:
406adcbc688SHerbert Xu 	       gcm_hash_init_continue(req, flags);
4076160b289SHerbert Xu }
4086160b289SHerbert Xu 
gcm_enc_copy_hash(struct aead_request * req,u32 flags)409adcbc688SHerbert Xu static int gcm_enc_copy_hash(struct aead_request *req, u32 flags)
4109382d97aSHuang Ying {
411adcbc688SHerbert Xu 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
4129382d97aSHuang Ying 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
4139382d97aSHuang Ying 	u8 *auth_tag = pctx->auth_tag;
4149382d97aSHuang Ying 
415adcbc688SHerbert Xu 	crypto_xor(auth_tag, pctx->iauth_tag, 16);
416adcbc688SHerbert Xu 	scatterwalk_map_and_copy(auth_tag, req->dst,
417adcbc688SHerbert Xu 				 req->assoclen + req->cryptlen,
4189382d97aSHuang Ying 				 crypto_aead_authsize(aead), 1);
419adcbc688SHerbert Xu 	return 0;
4209382d97aSHuang Ying }
4219382d97aSHuang Ying 
gcm_encrypt_continue(struct aead_request * req,u32 flags)422adcbc688SHerbert Xu static int gcm_encrypt_continue(struct aead_request *req, u32 flags)
4236160b289SHerbert Xu {
4249382d97aSHuang Ying 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
425adcbc688SHerbert Xu 	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
4266160b289SHerbert Xu 
427adcbc688SHerbert Xu 	gctx->src = sg_next(req->src == req->dst ? pctx->src : pctx->dst);
428adcbc688SHerbert Xu 	gctx->cryptlen = req->cryptlen;
429adcbc688SHerbert Xu 	gctx->complete = gcm_enc_copy_hash;
4306160b289SHerbert Xu 
431adcbc688SHerbert Xu 	return gcm_hash(req, flags);
43228db8e3eSMikko Herranen }
43328db8e3eSMikko Herranen 
gcm_encrypt_done(void * data,int err)434*255e48ebSHerbert Xu static void gcm_encrypt_done(void *data, int err)
4359382d97aSHuang Ying {
436*255e48ebSHerbert Xu 	struct aead_request *req = data;
4379382d97aSHuang Ying 
438adcbc688SHerbert Xu 	if (err)
439adcbc688SHerbert Xu 		goto out;
440adcbc688SHerbert Xu 
441adcbc688SHerbert Xu 	err = gcm_encrypt_continue(req, 0);
442adcbc688SHerbert Xu 	if (err == -EINPROGRESS)
4439382d97aSHuang Ying 		return;
4449382d97aSHuang Ying 
445adcbc688SHerbert Xu out:
44662c5593aSHuang Ying 	aead_request_complete(req, err);
4479382d97aSHuang Ying }
4489382d97aSHuang Ying 
crypto_gcm_encrypt(struct aead_request * req)44928db8e3eSMikko Herranen static int crypto_gcm_encrypt(struct aead_request *req)
45028db8e3eSMikko Herranen {
4512589469dSHerbert Xu 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
45216f37ecdSHerbert Xu 	struct skcipher_request *skreq = &pctx->u.skreq;
453adcbc688SHerbert Xu 	u32 flags = aead_request_flags(req);
45428db8e3eSMikko Herranen 
455adcbc688SHerbert Xu 	crypto_gcm_init_common(req);
456adcbc688SHerbert Xu 	crypto_gcm_init_crypt(req, req->cryptlen);
45716f37ecdSHerbert Xu 	skcipher_request_set_callback(skreq, flags, gcm_encrypt_done, req);
4589382d97aSHuang Ying 
45916f37ecdSHerbert Xu 	return crypto_skcipher_encrypt(skreq) ?:
460adcbc688SHerbert Xu 	       gcm_encrypt_continue(req, flags);
46128db8e3eSMikko Herranen }
46228db8e3eSMikko Herranen 
crypto_gcm_verify(struct aead_request * req)463adcbc688SHerbert Xu static int crypto_gcm_verify(struct aead_request *req)
46484c91152SHerbert Xu {
465adcbc688SHerbert Xu 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
46684c91152SHerbert Xu 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
46784c91152SHerbert Xu 	u8 *auth_tag = pctx->auth_tag;
46884c91152SHerbert Xu 	u8 *iauth_tag = pctx->iauth_tag;
46984c91152SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
47084c91152SHerbert Xu 	unsigned int cryptlen = req->cryptlen - authsize;
47184c91152SHerbert Xu 
4729382d97aSHuang Ying 	crypto_xor(auth_tag, iauth_tag, 16);
473adcbc688SHerbert Xu 	scatterwalk_map_and_copy(iauth_tag, req->src,
474adcbc688SHerbert Xu 				 req->assoclen + cryptlen, authsize, 0);
4756bf37e5aSJames Yonan 	return crypto_memneq(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
47684c91152SHerbert Xu }
47784c91152SHerbert Xu 
gcm_decrypt_done(void * data,int err)478*255e48ebSHerbert Xu static void gcm_decrypt_done(void *data, int err)
47928db8e3eSMikko Herranen {
480*255e48ebSHerbert Xu 	struct aead_request *req = data;
48184c91152SHerbert Xu 
48284c91152SHerbert Xu 	if (!err)
483adcbc688SHerbert Xu 		err = crypto_gcm_verify(req);
48484c91152SHerbert Xu 
48584c91152SHerbert Xu 	aead_request_complete(req, err);
48628db8e3eSMikko Herranen }
48728db8e3eSMikko Herranen 
gcm_dec_hash_continue(struct aead_request * req,u32 flags)488adcbc688SHerbert Xu static int gcm_dec_hash_continue(struct aead_request *req, u32 flags)
4899382d97aSHuang Ying {
4909382d97aSHuang Ying 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
49116f37ecdSHerbert Xu 	struct skcipher_request *skreq = &pctx->u.skreq;
4929382d97aSHuang Ying 	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
4939382d97aSHuang Ying 
494adcbc688SHerbert Xu 	crypto_gcm_init_crypt(req, gctx->cryptlen);
49516f37ecdSHerbert Xu 	skcipher_request_set_callback(skreq, flags, gcm_decrypt_done, req);
49616f37ecdSHerbert Xu 	return crypto_skcipher_decrypt(skreq) ?: crypto_gcm_verify(req);
4979382d97aSHuang Ying }
4989382d97aSHuang Ying 
crypto_gcm_decrypt(struct aead_request * req)49928db8e3eSMikko Herranen static int crypto_gcm_decrypt(struct aead_request *req)
50028db8e3eSMikko Herranen {
5016160b289SHerbert Xu 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
5022589469dSHerbert Xu 	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
5039382d97aSHuang Ying 	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
5046160b289SHerbert Xu 	unsigned int authsize = crypto_aead_authsize(aead);
5059382d97aSHuang Ying 	unsigned int cryptlen = req->cryptlen;
506adcbc688SHerbert Xu 	u32 flags = aead_request_flags(req);
50728db8e3eSMikko Herranen 
5086160b289SHerbert Xu 	cryptlen -= authsize;
50928db8e3eSMikko Herranen 
510adcbc688SHerbert Xu 	crypto_gcm_init_common(req);
511adcbc688SHerbert Xu 
512adcbc688SHerbert Xu 	gctx->src = sg_next(pctx->src);
5139382d97aSHuang Ying 	gctx->cryptlen = cryptlen;
514adcbc688SHerbert Xu 	gctx->complete = gcm_dec_hash_continue;
5159382d97aSHuang Ying 
516adcbc688SHerbert Xu 	return gcm_hash(req, flags);
51728db8e3eSMikko Herranen }
51828db8e3eSMikko Herranen 
crypto_gcm_init_tfm(struct crypto_aead * tfm)519adcbc688SHerbert Xu static int crypto_gcm_init_tfm(struct crypto_aead *tfm)
52028db8e3eSMikko Herranen {
521adcbc688SHerbert Xu 	struct aead_instance *inst = aead_alg_instance(tfm);
522adcbc688SHerbert Xu 	struct gcm_instance_ctx *ictx = aead_instance_ctx(inst);
523adcbc688SHerbert Xu 	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(tfm);
52416f37ecdSHerbert Xu 	struct crypto_skcipher *ctr;
5259382d97aSHuang Ying 	struct crypto_ahash *ghash;
52628db8e3eSMikko Herranen 	unsigned long align;
52728db8e3eSMikko Herranen 	int err;
52828db8e3eSMikko Herranen 
5299382d97aSHuang Ying 	ghash = crypto_spawn_ahash(&ictx->ghash);
5309382d97aSHuang Ying 	if (IS_ERR(ghash))
5319382d97aSHuang Ying 		return PTR_ERR(ghash);
5329382d97aSHuang Ying 
53360425a8bSEric Biggers 	ctr = crypto_spawn_skcipher(&ictx->ctr);
53428db8e3eSMikko Herranen 	err = PTR_ERR(ctr);
53528db8e3eSMikko Herranen 	if (IS_ERR(ctr))
5369382d97aSHuang Ying 		goto err_free_hash;
53728db8e3eSMikko Herranen 
53828db8e3eSMikko Herranen 	ctx->ctr = ctr;
5399382d97aSHuang Ying 	ctx->ghash = ghash;
54028db8e3eSMikko Herranen 
541adcbc688SHerbert Xu 	align = crypto_aead_alignmask(tfm);
54228db8e3eSMikko Herranen 	align &= ~(crypto_tfm_ctx_alignment() - 1);
543adcbc688SHerbert Xu 	crypto_aead_set_reqsize(tfm,
5445d72336fSHerbert Xu 		align + offsetof(struct crypto_gcm_req_priv_ctx, u) +
54516f37ecdSHerbert Xu 		max(sizeof(struct skcipher_request) +
54616f37ecdSHerbert Xu 		    crypto_skcipher_reqsize(ctr),
5479382d97aSHuang Ying 		    sizeof(struct ahash_request) +
5485d72336fSHerbert Xu 		    crypto_ahash_reqsize(ghash)));
54928db8e3eSMikko Herranen 
55028db8e3eSMikko Herranen 	return 0;
5519382d97aSHuang Ying 
5529382d97aSHuang Ying err_free_hash:
5539382d97aSHuang Ying 	crypto_free_ahash(ghash);
5549382d97aSHuang Ying 	return err;
55528db8e3eSMikko Herranen }
55628db8e3eSMikko Herranen 
crypto_gcm_exit_tfm(struct crypto_aead * tfm)557adcbc688SHerbert Xu static void crypto_gcm_exit_tfm(struct crypto_aead *tfm)
55828db8e3eSMikko Herranen {
559adcbc688SHerbert Xu 	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(tfm);
56028db8e3eSMikko Herranen 
5619382d97aSHuang Ying 	crypto_free_ahash(ctx->ghash);
56216f37ecdSHerbert Xu 	crypto_free_skcipher(ctx->ctr);
56328db8e3eSMikko Herranen }
56428db8e3eSMikko Herranen 
crypto_gcm_free(struct aead_instance * inst)5657b05a373SHerbert Xu static void crypto_gcm_free(struct aead_instance *inst)
5667b05a373SHerbert Xu {
5677b05a373SHerbert Xu 	struct gcm_instance_ctx *ctx = aead_instance_ctx(inst);
5687b05a373SHerbert Xu 
5697b05a373SHerbert Xu 	crypto_drop_skcipher(&ctx->ctr);
5707b05a373SHerbert Xu 	crypto_drop_ahash(&ctx->ghash);
5717b05a373SHerbert Xu 	kfree(inst);
5727b05a373SHerbert Xu }
5737b05a373SHerbert Xu 
crypto_gcm_create_common(struct crypto_template * tmpl,struct rtattr ** tb,const char * ctr_name,const char * ghash_name)574adcbc688SHerbert Xu static int crypto_gcm_create_common(struct crypto_template *tmpl,
575adcbc688SHerbert Xu 				    struct rtattr **tb,
5769382d97aSHuang Ying 				    const char *ctr_name,
5779382d97aSHuang Ying 				    const char *ghash_name)
57828db8e3eSMikko Herranen {
579b9f76dddSEric Biggers 	u32 mask;
580adcbc688SHerbert Xu 	struct aead_instance *inst;
58128db8e3eSMikko Herranen 	struct gcm_instance_ctx *ctx;
582ab6ffd36SEric Biggers 	struct skcipher_alg *ctr;
583ab6ffd36SEric Biggers 	struct hash_alg_common *ghash;
58428db8e3eSMikko Herranen 	int err;
58528db8e3eSMikko Herranen 
5867bcb2c99SEric Biggers 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
5877bcb2c99SEric Biggers 	if (err)
5887bcb2c99SEric Biggers 		return err;
589b9f76dddSEric Biggers 
5901472e5ebSHerbert Xu 	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
5911472e5ebSHerbert Xu 	if (!inst)
592ab6ffd36SEric Biggers 		return -ENOMEM;
593adcbc688SHerbert Xu 	ctx = aead_instance_ctx(inst);
594ab6ffd36SEric Biggers 
595ab6ffd36SEric Biggers 	err = crypto_grab_ahash(&ctx->ghash, aead_crypto_instance(inst),
596ab6ffd36SEric Biggers 				ghash_name, 0, mask);
5979382d97aSHuang Ying 	if (err)
5989382d97aSHuang Ying 		goto err_free_inst;
599ab6ffd36SEric Biggers 	ghash = crypto_spawn_ahash_alg(&ctx->ghash);
6009382d97aSHuang Ying 
601adcbc688SHerbert Xu 	err = -EINVAL;
602f699594dSEric Biggers 	if (strcmp(ghash->base.cra_name, "ghash") != 0 ||
603f699594dSEric Biggers 	    ghash->digestsize != 16)
604ab6ffd36SEric Biggers 		goto err_free_inst;
605adcbc688SHerbert Xu 
606b9f76dddSEric Biggers 	err = crypto_grab_skcipher(&ctx->ctr, aead_crypto_instance(inst),
607b9f76dddSEric Biggers 				   ctr_name, 0, mask);
6081472e5ebSHerbert Xu 	if (err)
609ab6ffd36SEric Biggers 		goto err_free_inst;
61016f37ecdSHerbert Xu 	ctr = crypto_spawn_skcipher_alg(&ctx->ctr);
61128db8e3eSMikko Herranen 
612f699594dSEric Biggers 	/* The skcipher algorithm must be CTR mode, using 16-byte blocks. */
6139b40f79cSWei Yongjun 	err = -EINVAL;
614f699594dSEric Biggers 	if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 ||
615f699594dSEric Biggers 	    crypto_skcipher_alg_ivsize(ctr) != 16 ||
616f699594dSEric Biggers 	    ctr->base.cra_blocksize != 1)
617ab6ffd36SEric Biggers 		goto err_free_inst;
61828db8e3eSMikko Herranen 
61928db8e3eSMikko Herranen 	err = -ENAMETOOLONG;
620f699594dSEric Biggers 	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
621f699594dSEric Biggers 		     "gcm(%s", ctr->base.cra_name + 4) >= CRYPTO_MAX_ALG_NAME)
622ab6ffd36SEric Biggers 		goto err_free_inst;
623f699594dSEric Biggers 
624adcbc688SHerbert Xu 	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
62516f37ecdSHerbert Xu 		     "gcm_base(%s,%s)", ctr->base.cra_driver_name,
626ab6ffd36SEric Biggers 		     ghash->base.cra_driver_name) >=
627d00aa19bSHerbert Xu 	    CRYPTO_MAX_ALG_NAME)
628ab6ffd36SEric Biggers 		goto err_free_inst;
62928db8e3eSMikko Herranen 
630adcbc688SHerbert Xu 	inst->alg.base.cra_priority = (ghash->base.cra_priority +
63116f37ecdSHerbert Xu 				       ctr->base.cra_priority) / 2;
632adcbc688SHerbert Xu 	inst->alg.base.cra_blocksize = 1;
633adcbc688SHerbert Xu 	inst->alg.base.cra_alignmask = ghash->base.cra_alignmask |
63416f37ecdSHerbert Xu 				       ctr->base.cra_alignmask;
635adcbc688SHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct crypto_gcm_ctx);
636e0ab7e9cSCorentin LABBE 	inst->alg.ivsize = GCM_AES_IV_SIZE;
63716f37ecdSHerbert Xu 	inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
638adcbc688SHerbert Xu 	inst->alg.maxauthsize = 16;
639adcbc688SHerbert Xu 	inst->alg.init = crypto_gcm_init_tfm;
640adcbc688SHerbert Xu 	inst->alg.exit = crypto_gcm_exit_tfm;
641adcbc688SHerbert Xu 	inst->alg.setkey = crypto_gcm_setkey;
642adcbc688SHerbert Xu 	inst->alg.setauthsize = crypto_gcm_setauthsize;
643adcbc688SHerbert Xu 	inst->alg.encrypt = crypto_gcm_encrypt;
644adcbc688SHerbert Xu 	inst->alg.decrypt = crypto_gcm_decrypt;
64528db8e3eSMikko Herranen 
6467b05a373SHerbert Xu 	inst->free = crypto_gcm_free;
6477b05a373SHerbert Xu 
648adcbc688SHerbert Xu 	err = aead_register_instance(tmpl, inst);
649ab6ffd36SEric Biggers 	if (err) {
65028db8e3eSMikko Herranen err_free_inst:
651ab6ffd36SEric Biggers 		crypto_gcm_free(inst);
652ab6ffd36SEric Biggers 	}
653ab6ffd36SEric Biggers 	return err;
65428db8e3eSMikko Herranen }
65528db8e3eSMikko Herranen 
crypto_gcm_create(struct crypto_template * tmpl,struct rtattr ** tb)656adcbc688SHerbert Xu static int crypto_gcm_create(struct crypto_template *tmpl, struct rtattr **tb)
657d00aa19bSHerbert Xu {
658d00aa19bSHerbert Xu 	const char *cipher_name;
659d00aa19bSHerbert Xu 	char ctr_name[CRYPTO_MAX_ALG_NAME];
660d00aa19bSHerbert Xu 
661d00aa19bSHerbert Xu 	cipher_name = crypto_attr_alg_name(tb[1]);
662d00aa19bSHerbert Xu 	if (IS_ERR(cipher_name))
663adcbc688SHerbert Xu 		return PTR_ERR(cipher_name);
664d00aa19bSHerbert Xu 
665d00aa19bSHerbert Xu 	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", cipher_name) >=
666d00aa19bSHerbert Xu 	    CRYPTO_MAX_ALG_NAME)
667adcbc688SHerbert Xu 		return -ENAMETOOLONG;
668d00aa19bSHerbert Xu 
669f699594dSEric Biggers 	return crypto_gcm_create_common(tmpl, tb, ctr_name, "ghash");
670d00aa19bSHerbert Xu }
671d00aa19bSHerbert Xu 
crypto_gcm_base_create(struct crypto_template * tmpl,struct rtattr ** tb)672adcbc688SHerbert Xu static int crypto_gcm_base_create(struct crypto_template *tmpl,
673adcbc688SHerbert Xu 				  struct rtattr **tb)
674d00aa19bSHerbert Xu {
675d00aa19bSHerbert Xu 	const char *ctr_name;
6769382d97aSHuang Ying 	const char *ghash_name;
677d00aa19bSHerbert Xu 
678d00aa19bSHerbert Xu 	ctr_name = crypto_attr_alg_name(tb[1]);
679d00aa19bSHerbert Xu 	if (IS_ERR(ctr_name))
680adcbc688SHerbert Xu 		return PTR_ERR(ctr_name);
681d00aa19bSHerbert Xu 
6829382d97aSHuang Ying 	ghash_name = crypto_attr_alg_name(tb[2]);
6839382d97aSHuang Ying 	if (IS_ERR(ghash_name))
684adcbc688SHerbert Xu 		return PTR_ERR(ghash_name);
6859382d97aSHuang Ying 
686f699594dSEric Biggers 	return crypto_gcm_create_common(tmpl, tb, ctr_name, ghash_name);
687d00aa19bSHerbert Xu }
688d00aa19bSHerbert Xu 
crypto_rfc4106_setkey(struct crypto_aead * parent,const u8 * key,unsigned int keylen)689dadbc53dSHerbert Xu static int crypto_rfc4106_setkey(struct crypto_aead *parent, const u8 *key,
690dadbc53dSHerbert Xu 				 unsigned int keylen)
691dadbc53dSHerbert Xu {
692dadbc53dSHerbert Xu 	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
693dadbc53dSHerbert Xu 	struct crypto_aead *child = ctx->child;
694dadbc53dSHerbert Xu 
695dadbc53dSHerbert Xu 	if (keylen < 4)
696dadbc53dSHerbert Xu 		return -EINVAL;
697dadbc53dSHerbert Xu 
698dadbc53dSHerbert Xu 	keylen -= 4;
699dadbc53dSHerbert Xu 	memcpy(ctx->nonce, key + keylen, 4);
700dadbc53dSHerbert Xu 
701dadbc53dSHerbert Xu 	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
702dadbc53dSHerbert Xu 	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
703dadbc53dSHerbert Xu 				     CRYPTO_TFM_REQ_MASK);
704af5034e8SEric Biggers 	return crypto_aead_setkey(child, key, keylen);
705dadbc53dSHerbert Xu }
706dadbc53dSHerbert Xu 
crypto_rfc4106_setauthsize(struct crypto_aead * parent,unsigned int authsize)707dadbc53dSHerbert Xu static int crypto_rfc4106_setauthsize(struct crypto_aead *parent,
708dadbc53dSHerbert Xu 				      unsigned int authsize)
709dadbc53dSHerbert Xu {
710dadbc53dSHerbert Xu 	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
71165526f63SIuliana Prodan 	int err;
712dadbc53dSHerbert Xu 
71365526f63SIuliana Prodan 	err = crypto_rfc4106_check_authsize(authsize);
71465526f63SIuliana Prodan 	if (err)
71565526f63SIuliana Prodan 		return err;
716dadbc53dSHerbert Xu 
717dadbc53dSHerbert Xu 	return crypto_aead_setauthsize(ctx->child, authsize);
718dadbc53dSHerbert Xu }
719dadbc53dSHerbert Xu 
crypto_rfc4106_crypt(struct aead_request * req)720dadbc53dSHerbert Xu static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req)
721dadbc53dSHerbert Xu {
7227b05a373SHerbert Xu 	struct crypto_rfc4106_req_ctx *rctx = aead_request_ctx(req);
723dadbc53dSHerbert Xu 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
724dadbc53dSHerbert Xu 	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(aead);
7257b05a373SHerbert Xu 	struct aead_request *subreq = &rctx->subreq;
726dadbc53dSHerbert Xu 	struct crypto_aead *child = ctx->child;
7277b05a373SHerbert Xu 	struct scatterlist *sg;
728dadbc53dSHerbert Xu 	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
729dadbc53dSHerbert Xu 			   crypto_aead_alignmask(child) + 1);
730dadbc53dSHerbert Xu 
731e0ab7e9cSCorentin LABBE 	scatterwalk_map_and_copy(iv + GCM_AES_IV_SIZE, req->src, 0, req->assoclen - 8, 0);
7327b05a373SHerbert Xu 
733dadbc53dSHerbert Xu 	memcpy(iv, ctx->nonce, 4);
734dadbc53dSHerbert Xu 	memcpy(iv + 4, req->iv, 8);
735dadbc53dSHerbert Xu 
7367b05a373SHerbert Xu 	sg_init_table(rctx->src, 3);
737e0ab7e9cSCorentin LABBE 	sg_set_buf(rctx->src, iv + GCM_AES_IV_SIZE, req->assoclen - 8);
7387b05a373SHerbert Xu 	sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen);
7397b05a373SHerbert Xu 	if (sg != rctx->src + 1)
7407b05a373SHerbert Xu 		sg_chain(rctx->src, 2, sg);
7417b05a373SHerbert Xu 
7427b05a373SHerbert Xu 	if (req->src != req->dst) {
7437b05a373SHerbert Xu 		sg_init_table(rctx->dst, 3);
744e0ab7e9cSCorentin LABBE 		sg_set_buf(rctx->dst, iv + GCM_AES_IV_SIZE, req->assoclen - 8);
7457b05a373SHerbert Xu 		sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen);
7467b05a373SHerbert Xu 		if (sg != rctx->dst + 1)
7477b05a373SHerbert Xu 			sg_chain(rctx->dst, 2, sg);
7487b05a373SHerbert Xu 	}
7497b05a373SHerbert Xu 
750dadbc53dSHerbert Xu 	aead_request_set_tfm(subreq, child);
751dadbc53dSHerbert Xu 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
752dadbc53dSHerbert Xu 				  req->base.data);
7537b05a373SHerbert Xu 	aead_request_set_crypt(subreq, rctx->src,
7547b05a373SHerbert Xu 			       req->src == req->dst ? rctx->src : rctx->dst,
7557b05a373SHerbert Xu 			       req->cryptlen, iv);
7567b05a373SHerbert Xu 	aead_request_set_ad(subreq, req->assoclen - 8);
757dadbc53dSHerbert Xu 
758dadbc53dSHerbert Xu 	return subreq;
759dadbc53dSHerbert Xu }
760dadbc53dSHerbert Xu 
crypto_rfc4106_encrypt(struct aead_request * req)761dadbc53dSHerbert Xu static int crypto_rfc4106_encrypt(struct aead_request *req)
762dadbc53dSHerbert Xu {
76365526f63SIuliana Prodan 	int err;
76465526f63SIuliana Prodan 
76565526f63SIuliana Prodan 	err = crypto_ipsec_check_assoclen(req->assoclen);
76665526f63SIuliana Prodan 	if (err)
76765526f63SIuliana Prodan 		return err;
7687b05a373SHerbert Xu 
769dadbc53dSHerbert Xu 	req = crypto_rfc4106_crypt(req);
770dadbc53dSHerbert Xu 
771dadbc53dSHerbert Xu 	return crypto_aead_encrypt(req);
772dadbc53dSHerbert Xu }
773dadbc53dSHerbert Xu 
crypto_rfc4106_decrypt(struct aead_request * req)774dadbc53dSHerbert Xu static int crypto_rfc4106_decrypt(struct aead_request *req)
775dadbc53dSHerbert Xu {
77665526f63SIuliana Prodan 	int err;
77765526f63SIuliana Prodan 
77865526f63SIuliana Prodan 	err = crypto_ipsec_check_assoclen(req->assoclen);
77965526f63SIuliana Prodan 	if (err)
78065526f63SIuliana Prodan 		return err;
7817b05a373SHerbert Xu 
782dadbc53dSHerbert Xu 	req = crypto_rfc4106_crypt(req);
783dadbc53dSHerbert Xu 
784dadbc53dSHerbert Xu 	return crypto_aead_decrypt(req);
785dadbc53dSHerbert Xu }
786dadbc53dSHerbert Xu 
crypto_rfc4106_init_tfm(struct crypto_aead * tfm)787adcbc688SHerbert Xu static int crypto_rfc4106_init_tfm(struct crypto_aead *tfm)
788dadbc53dSHerbert Xu {
789adcbc688SHerbert Xu 	struct aead_instance *inst = aead_alg_instance(tfm);
790adcbc688SHerbert Xu 	struct crypto_aead_spawn *spawn = aead_instance_ctx(inst);
791adcbc688SHerbert Xu 	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(tfm);
792dadbc53dSHerbert Xu 	struct crypto_aead *aead;
793dadbc53dSHerbert Xu 	unsigned long align;
794dadbc53dSHerbert Xu 
795dadbc53dSHerbert Xu 	aead = crypto_spawn_aead(spawn);
796dadbc53dSHerbert Xu 	if (IS_ERR(aead))
797dadbc53dSHerbert Xu 		return PTR_ERR(aead);
798dadbc53dSHerbert Xu 
799dadbc53dSHerbert Xu 	ctx->child = aead;
800dadbc53dSHerbert Xu 
801dadbc53dSHerbert Xu 	align = crypto_aead_alignmask(aead);
802dadbc53dSHerbert Xu 	align &= ~(crypto_tfm_ctx_alignment() - 1);
803adcbc688SHerbert Xu 	crypto_aead_set_reqsize(
804adcbc688SHerbert Xu 		tfm,
8057b05a373SHerbert Xu 		sizeof(struct crypto_rfc4106_req_ctx) +
8065d72336fSHerbert Xu 		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
8077b05a373SHerbert Xu 		align + 24);
808dadbc53dSHerbert Xu 
809dadbc53dSHerbert Xu 	return 0;
810dadbc53dSHerbert Xu }
811dadbc53dSHerbert Xu 
crypto_rfc4106_exit_tfm(struct crypto_aead * tfm)812adcbc688SHerbert Xu static void crypto_rfc4106_exit_tfm(struct crypto_aead *tfm)
813dadbc53dSHerbert Xu {
814adcbc688SHerbert Xu 	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(tfm);
815dadbc53dSHerbert Xu 
816dadbc53dSHerbert Xu 	crypto_free_aead(ctx->child);
817dadbc53dSHerbert Xu }
818dadbc53dSHerbert Xu 
crypto_rfc4106_free(struct aead_instance * inst)8197b05a373SHerbert Xu static void crypto_rfc4106_free(struct aead_instance *inst)
8207b05a373SHerbert Xu {
8217b05a373SHerbert Xu 	crypto_drop_aead(aead_instance_ctx(inst));
8227b05a373SHerbert Xu 	kfree(inst);
8237b05a373SHerbert Xu }
8247b05a373SHerbert Xu 
crypto_rfc4106_create(struct crypto_template * tmpl,struct rtattr ** tb)825adcbc688SHerbert Xu static int crypto_rfc4106_create(struct crypto_template *tmpl,
826adcbc688SHerbert Xu 				 struct rtattr **tb)
827dadbc53dSHerbert Xu {
828cd900f0cSEric Biggers 	u32 mask;
829adcbc688SHerbert Xu 	struct aead_instance *inst;
830dadbc53dSHerbert Xu 	struct crypto_aead_spawn *spawn;
831adcbc688SHerbert Xu 	struct aead_alg *alg;
832dadbc53dSHerbert Xu 	int err;
833dadbc53dSHerbert Xu 
8347bcb2c99SEric Biggers 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
8357bcb2c99SEric Biggers 	if (err)
8367bcb2c99SEric Biggers 		return err;
837cd900f0cSEric Biggers 
838dadbc53dSHerbert Xu 	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
839dadbc53dSHerbert Xu 	if (!inst)
840adcbc688SHerbert Xu 		return -ENOMEM;
841dadbc53dSHerbert Xu 
842adcbc688SHerbert Xu 	spawn = aead_instance_ctx(inst);
843cd900f0cSEric Biggers 	err = crypto_grab_aead(spawn, aead_crypto_instance(inst),
844959ac1cdSEric Biggers 			       crypto_attr_alg_name(tb[1]), 0, mask);
845dadbc53dSHerbert Xu 	if (err)
846959ac1cdSEric Biggers 		goto err_free_inst;
847dadbc53dSHerbert Xu 
848adcbc688SHerbert Xu 	alg = crypto_spawn_aead_alg(spawn);
849dadbc53dSHerbert Xu 
850dadbc53dSHerbert Xu 	err = -EINVAL;
851dadbc53dSHerbert Xu 
852adcbc688SHerbert Xu 	/* Underlying IV size must be 12. */
853e0ab7e9cSCorentin LABBE 	if (crypto_aead_alg_ivsize(alg) != GCM_AES_IV_SIZE)
854959ac1cdSEric Biggers 		goto err_free_inst;
855dadbc53dSHerbert Xu 
856dadbc53dSHerbert Xu 	/* Not a stream cipher? */
857adcbc688SHerbert Xu 	if (alg->base.cra_blocksize != 1)
858959ac1cdSEric Biggers 		goto err_free_inst;
859dadbc53dSHerbert Xu 
860dadbc53dSHerbert Xu 	err = -ENAMETOOLONG;
861adcbc688SHerbert Xu 	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
862adcbc688SHerbert Xu 		     "rfc4106(%s)", alg->base.cra_name) >=
863adcbc688SHerbert Xu 	    CRYPTO_MAX_ALG_NAME ||
864adcbc688SHerbert Xu 	    snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
865adcbc688SHerbert Xu 		     "rfc4106(%s)", alg->base.cra_driver_name) >=
866dadbc53dSHerbert Xu 	    CRYPTO_MAX_ALG_NAME)
867959ac1cdSEric Biggers 		goto err_free_inst;
868dadbc53dSHerbert Xu 
869adcbc688SHerbert Xu 	inst->alg.base.cra_priority = alg->base.cra_priority;
870adcbc688SHerbert Xu 	inst->alg.base.cra_blocksize = 1;
871adcbc688SHerbert Xu 	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
872dadbc53dSHerbert Xu 
873adcbc688SHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4106_ctx);
874dadbc53dSHerbert Xu 
875e0ab7e9cSCorentin LABBE 	inst->alg.ivsize = GCM_RFC4106_IV_SIZE;
87616f37ecdSHerbert Xu 	inst->alg.chunksize = crypto_aead_alg_chunksize(alg);
877adcbc688SHerbert Xu 	inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
878dadbc53dSHerbert Xu 
879adcbc688SHerbert Xu 	inst->alg.init = crypto_rfc4106_init_tfm;
880adcbc688SHerbert Xu 	inst->alg.exit = crypto_rfc4106_exit_tfm;
881dadbc53dSHerbert Xu 
882adcbc688SHerbert Xu 	inst->alg.setkey = crypto_rfc4106_setkey;
883adcbc688SHerbert Xu 	inst->alg.setauthsize = crypto_rfc4106_setauthsize;
884adcbc688SHerbert Xu 	inst->alg.encrypt = crypto_rfc4106_encrypt;
885adcbc688SHerbert Xu 	inst->alg.decrypt = crypto_rfc4106_decrypt;
886dadbc53dSHerbert Xu 
8877b05a373SHerbert Xu 	inst->free = crypto_rfc4106_free;
8887b05a373SHerbert Xu 
889adcbc688SHerbert Xu 	err = aead_register_instance(tmpl, inst);
890959ac1cdSEric Biggers 	if (err) {
891959ac1cdSEric Biggers err_free_inst:
892959ac1cdSEric Biggers 		crypto_rfc4106_free(inst);
893959ac1cdSEric Biggers 	}
894adcbc688SHerbert Xu 	return err;
895dadbc53dSHerbert Xu }
896dadbc53dSHerbert Xu 
crypto_rfc4543_setkey(struct crypto_aead * parent,const u8 * key,unsigned int keylen)89773c89c15STobias Brunner static int crypto_rfc4543_setkey(struct crypto_aead *parent, const u8 *key,
89873c89c15STobias Brunner 				 unsigned int keylen)
89973c89c15STobias Brunner {
90073c89c15STobias Brunner 	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(parent);
90173c89c15STobias Brunner 	struct crypto_aead *child = ctx->child;
90273c89c15STobias Brunner 
90373c89c15STobias Brunner 	if (keylen < 4)
90473c89c15STobias Brunner 		return -EINVAL;
90573c89c15STobias Brunner 
90673c89c15STobias Brunner 	keylen -= 4;
90773c89c15STobias Brunner 	memcpy(ctx->nonce, key + keylen, 4);
90873c89c15STobias Brunner 
90973c89c15STobias Brunner 	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
91073c89c15STobias Brunner 	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
91173c89c15STobias Brunner 				     CRYPTO_TFM_REQ_MASK);
912af5034e8SEric Biggers 	return crypto_aead_setkey(child, key, keylen);
91373c89c15STobias Brunner }
91473c89c15STobias Brunner 
crypto_rfc4543_setauthsize(struct crypto_aead * parent,unsigned int authsize)91573c89c15STobias Brunner static int crypto_rfc4543_setauthsize(struct crypto_aead *parent,
91673c89c15STobias Brunner 				      unsigned int authsize)
91773c89c15STobias Brunner {
91873c89c15STobias Brunner 	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(parent);
91973c89c15STobias Brunner 
92073c89c15STobias Brunner 	if (authsize != 16)
92173c89c15STobias Brunner 		return -EINVAL;
92273c89c15STobias Brunner 
92373c89c15STobias Brunner 	return crypto_aead_setauthsize(ctx->child, authsize);
92473c89c15STobias Brunner }
92573c89c15STobias Brunner 
crypto_rfc4543_crypt(struct aead_request * req,bool enc)926adcbc688SHerbert Xu static int crypto_rfc4543_crypt(struct aead_request *req, bool enc)
92773c89c15STobias Brunner {
92873c89c15STobias Brunner 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
92973c89c15STobias Brunner 	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(aead);
930adcbc688SHerbert Xu 	struct crypto_rfc4543_req_ctx *rctx = aead_request_ctx(req);
93173c89c15STobias Brunner 	struct aead_request *subreq = &rctx->subreq;
93273c89c15STobias Brunner 	unsigned int authsize = crypto_aead_authsize(aead);
93373c89c15STobias Brunner 	u8 *iv = PTR_ALIGN((u8 *)(rctx + 1) + crypto_aead_reqsize(ctx->child),
93473c89c15STobias Brunner 			   crypto_aead_alignmask(ctx->child) + 1);
935adcbc688SHerbert Xu 	int err;
936adcbc688SHerbert Xu 
937adcbc688SHerbert Xu 	if (req->src != req->dst) {
938adcbc688SHerbert Xu 		err = crypto_rfc4543_copy_src_to_dst(req, enc);
939adcbc688SHerbert Xu 		if (err)
940adcbc688SHerbert Xu 			return err;
941adcbc688SHerbert Xu 	}
94273c89c15STobias Brunner 
94373c89c15STobias Brunner 	memcpy(iv, ctx->nonce, 4);
94473c89c15STobias Brunner 	memcpy(iv + 4, req->iv, 8);
94573c89c15STobias Brunner 
94673c89c15STobias Brunner 	aead_request_set_tfm(subreq, ctx->child);
947adcbc688SHerbert Xu 	aead_request_set_callback(subreq, req->base.flags,
948adcbc688SHerbert Xu 				  req->base.complete, req->base.data);
949adcbc688SHerbert Xu 	aead_request_set_crypt(subreq, req->src, req->dst,
950adcbc688SHerbert Xu 			       enc ? 0 : authsize, iv);
951adcbc688SHerbert Xu 	aead_request_set_ad(subreq, req->assoclen + req->cryptlen -
952adcbc688SHerbert Xu 				    subreq->cryptlen);
95373c89c15STobias Brunner 
954adcbc688SHerbert Xu 	return enc ? crypto_aead_encrypt(subreq) : crypto_aead_decrypt(subreq);
95573c89c15STobias Brunner }
95673c89c15STobias Brunner 
crypto_rfc4543_copy_src_to_dst(struct aead_request * req,bool enc)9579489667dSJussi Kivilinna static int crypto_rfc4543_copy_src_to_dst(struct aead_request *req, bool enc)
9589489667dSJussi Kivilinna {
9599489667dSJussi Kivilinna 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
9609489667dSJussi Kivilinna 	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(aead);
9619489667dSJussi Kivilinna 	unsigned int authsize = crypto_aead_authsize(aead);
962adcbc688SHerbert Xu 	unsigned int nbytes = req->assoclen + req->cryptlen -
963adcbc688SHerbert Xu 			      (enc ? 0 : authsize);
9648d605398SKees Cook 	SYNC_SKCIPHER_REQUEST_ON_STACK(nreq, ctx->null);
9659489667dSJussi Kivilinna 
9668d605398SKees Cook 	skcipher_request_set_sync_tfm(nreq, ctx->null);
96716f37ecdSHerbert Xu 	skcipher_request_set_callback(nreq, req->base.flags, NULL, NULL);
96816f37ecdSHerbert Xu 	skcipher_request_set_crypt(nreq, req->src, req->dst, nbytes, NULL);
96916f37ecdSHerbert Xu 
97016f37ecdSHerbert Xu 	return crypto_skcipher_encrypt(nreq);
9719489667dSJussi Kivilinna }
9729489667dSJussi Kivilinna 
crypto_rfc4543_encrypt(struct aead_request * req)97373c89c15STobias Brunner static int crypto_rfc4543_encrypt(struct aead_request *req)
97473c89c15STobias Brunner {
97574bf81d0SIuliana Prodan 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
97674bf81d0SIuliana Prodan 	       crypto_rfc4543_crypt(req, true);
97773c89c15STobias Brunner }
97873c89c15STobias Brunner 
crypto_rfc4543_decrypt(struct aead_request * req)97973c89c15STobias Brunner static int crypto_rfc4543_decrypt(struct aead_request *req)
98073c89c15STobias Brunner {
98174bf81d0SIuliana Prodan 	return crypto_ipsec_check_assoclen(req->assoclen) ?:
98274bf81d0SIuliana Prodan 	       crypto_rfc4543_crypt(req, false);
9839489667dSJussi Kivilinna }
9849489667dSJussi Kivilinna 
crypto_rfc4543_init_tfm(struct crypto_aead * tfm)985adcbc688SHerbert Xu static int crypto_rfc4543_init_tfm(struct crypto_aead *tfm)
98673c89c15STobias Brunner {
987adcbc688SHerbert Xu 	struct aead_instance *inst = aead_alg_instance(tfm);
988adcbc688SHerbert Xu 	struct crypto_rfc4543_instance_ctx *ictx = aead_instance_ctx(inst);
9899489667dSJussi Kivilinna 	struct crypto_aead_spawn *spawn = &ictx->aead;
990adcbc688SHerbert Xu 	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(tfm);
99173c89c15STobias Brunner 	struct crypto_aead *aead;
9928d605398SKees Cook 	struct crypto_sync_skcipher *null;
99373c89c15STobias Brunner 	unsigned long align;
9949489667dSJussi Kivilinna 	int err = 0;
99573c89c15STobias Brunner 
99673c89c15STobias Brunner 	aead = crypto_spawn_aead(spawn);
99773c89c15STobias Brunner 	if (IS_ERR(aead))
99873c89c15STobias Brunner 		return PTR_ERR(aead);
99973c89c15STobias Brunner 
10003a2d4fb5SEric Biggers 	null = crypto_get_default_null_skcipher();
10019489667dSJussi Kivilinna 	err = PTR_ERR(null);
10029489667dSJussi Kivilinna 	if (IS_ERR(null))
10039489667dSJussi Kivilinna 		goto err_free_aead;
10049489667dSJussi Kivilinna 
100573c89c15STobias Brunner 	ctx->child = aead;
10069489667dSJussi Kivilinna 	ctx->null = null;
100773c89c15STobias Brunner 
100873c89c15STobias Brunner 	align = crypto_aead_alignmask(aead);
100973c89c15STobias Brunner 	align &= ~(crypto_tfm_ctx_alignment() - 1);
1010adcbc688SHerbert Xu 	crypto_aead_set_reqsize(
1011adcbc688SHerbert Xu 		tfm,
10125d72336fSHerbert Xu 		sizeof(struct crypto_rfc4543_req_ctx) +
10135d72336fSHerbert Xu 		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
1014e0ab7e9cSCorentin LABBE 		align + GCM_AES_IV_SIZE);
101573c89c15STobias Brunner 
101673c89c15STobias Brunner 	return 0;
10179489667dSJussi Kivilinna 
10189489667dSJussi Kivilinna err_free_aead:
10199489667dSJussi Kivilinna 	crypto_free_aead(aead);
10209489667dSJussi Kivilinna 	return err;
102173c89c15STobias Brunner }
102273c89c15STobias Brunner 
crypto_rfc4543_exit_tfm(struct crypto_aead * tfm)1023adcbc688SHerbert Xu static void crypto_rfc4543_exit_tfm(struct crypto_aead *tfm)
102473c89c15STobias Brunner {
1025adcbc688SHerbert Xu 	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(tfm);
102673c89c15STobias Brunner 
102773c89c15STobias Brunner 	crypto_free_aead(ctx->child);
10283a2d4fb5SEric Biggers 	crypto_put_default_null_skcipher();
102973c89c15STobias Brunner }
103073c89c15STobias Brunner 
crypto_rfc4543_free(struct aead_instance * inst)10317b05a373SHerbert Xu static void crypto_rfc4543_free(struct aead_instance *inst)
10327b05a373SHerbert Xu {
10337b05a373SHerbert Xu 	struct crypto_rfc4543_instance_ctx *ctx = aead_instance_ctx(inst);
10347b05a373SHerbert Xu 
10357b05a373SHerbert Xu 	crypto_drop_aead(&ctx->aead);
10367b05a373SHerbert Xu 
10377b05a373SHerbert Xu 	kfree(inst);
10387b05a373SHerbert Xu }
10397b05a373SHerbert Xu 
crypto_rfc4543_create(struct crypto_template * tmpl,struct rtattr ** tb)1040adcbc688SHerbert Xu static int crypto_rfc4543_create(struct crypto_template *tmpl,
1041adcbc688SHerbert Xu 				struct rtattr **tb)
104273c89c15STobias Brunner {
1043cd900f0cSEric Biggers 	u32 mask;
1044adcbc688SHerbert Xu 	struct aead_instance *inst;
1045adcbc688SHerbert Xu 	struct aead_alg *alg;
10469489667dSJussi Kivilinna 	struct crypto_rfc4543_instance_ctx *ctx;
104773c89c15STobias Brunner 	int err;
104873c89c15STobias Brunner 
10497bcb2c99SEric Biggers 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
10507bcb2c99SEric Biggers 	if (err)
10517bcb2c99SEric Biggers 		return err;
1052cd900f0cSEric Biggers 
10539489667dSJussi Kivilinna 	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
105473c89c15STobias Brunner 	if (!inst)
1055adcbc688SHerbert Xu 		return -ENOMEM;
105673c89c15STobias Brunner 
1057adcbc688SHerbert Xu 	ctx = aead_instance_ctx(inst);
1058c4caa56dSEric Biggers 	err = crypto_grab_aead(&ctx->aead, aead_crypto_instance(inst),
1059c4caa56dSEric Biggers 			       crypto_attr_alg_name(tb[1]), 0, mask);
106073c89c15STobias Brunner 	if (err)
1061c4caa56dSEric Biggers 		goto err_free_inst;
106273c89c15STobias Brunner 
1063c4caa56dSEric Biggers 	alg = crypto_spawn_aead_alg(&ctx->aead);
106473c89c15STobias Brunner 
106573c89c15STobias Brunner 	err = -EINVAL;
106673c89c15STobias Brunner 
1067adcbc688SHerbert Xu 	/* Underlying IV size must be 12. */
1068e0ab7e9cSCorentin LABBE 	if (crypto_aead_alg_ivsize(alg) != GCM_AES_IV_SIZE)
1069c4caa56dSEric Biggers 		goto err_free_inst;
107073c89c15STobias Brunner 
107173c89c15STobias Brunner 	/* Not a stream cipher? */
1072adcbc688SHerbert Xu 	if (alg->base.cra_blocksize != 1)
1073c4caa56dSEric Biggers 		goto err_free_inst;
107473c89c15STobias Brunner 
107573c89c15STobias Brunner 	err = -ENAMETOOLONG;
1076adcbc688SHerbert Xu 	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
1077adcbc688SHerbert Xu 		     "rfc4543(%s)", alg->base.cra_name) >=
1078adcbc688SHerbert Xu 	    CRYPTO_MAX_ALG_NAME ||
1079adcbc688SHerbert Xu 	    snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
1080adcbc688SHerbert Xu 		     "rfc4543(%s)", alg->base.cra_driver_name) >=
108173c89c15STobias Brunner 	    CRYPTO_MAX_ALG_NAME)
1082c4caa56dSEric Biggers 		goto err_free_inst;
108373c89c15STobias Brunner 
1084adcbc688SHerbert Xu 	inst->alg.base.cra_priority = alg->base.cra_priority;
1085adcbc688SHerbert Xu 	inst->alg.base.cra_blocksize = 1;
1086adcbc688SHerbert Xu 	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
108773c89c15STobias Brunner 
1088adcbc688SHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4543_ctx);
108973c89c15STobias Brunner 
1090e0ab7e9cSCorentin LABBE 	inst->alg.ivsize = GCM_RFC4543_IV_SIZE;
109116f37ecdSHerbert Xu 	inst->alg.chunksize = crypto_aead_alg_chunksize(alg);
1092adcbc688SHerbert Xu 	inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
109373c89c15STobias Brunner 
1094adcbc688SHerbert Xu 	inst->alg.init = crypto_rfc4543_init_tfm;
1095adcbc688SHerbert Xu 	inst->alg.exit = crypto_rfc4543_exit_tfm;
109673c89c15STobias Brunner 
1097adcbc688SHerbert Xu 	inst->alg.setkey = crypto_rfc4543_setkey;
1098adcbc688SHerbert Xu 	inst->alg.setauthsize = crypto_rfc4543_setauthsize;
1099adcbc688SHerbert Xu 	inst->alg.encrypt = crypto_rfc4543_encrypt;
1100adcbc688SHerbert Xu 	inst->alg.decrypt = crypto_rfc4543_decrypt;
110173c89c15STobias Brunner 
1102c4caa56dSEric Biggers 	inst->free = crypto_rfc4543_free;
11037b05a373SHerbert Xu 
1104adcbc688SHerbert Xu 	err = aead_register_instance(tmpl, inst);
1105c4caa56dSEric Biggers 	if (err) {
1106c4caa56dSEric Biggers err_free_inst:
1107c4caa56dSEric Biggers 		crypto_rfc4543_free(inst);
1108c4caa56dSEric Biggers 	}
1109adcbc688SHerbert Xu 	return err;
111073c89c15STobias Brunner }
111173c89c15STobias Brunner 
111256a00d9dSXiongfeng Wang static struct crypto_template crypto_gcm_tmpls[] = {
111356a00d9dSXiongfeng Wang 	{
111456a00d9dSXiongfeng Wang 		.name = "gcm_base",
111556a00d9dSXiongfeng Wang 		.create = crypto_gcm_base_create,
111656a00d9dSXiongfeng Wang 		.module = THIS_MODULE,
111756a00d9dSXiongfeng Wang 	}, {
111856a00d9dSXiongfeng Wang 		.name = "gcm",
111956a00d9dSXiongfeng Wang 		.create = crypto_gcm_create,
112056a00d9dSXiongfeng Wang 		.module = THIS_MODULE,
112156a00d9dSXiongfeng Wang 	}, {
112256a00d9dSXiongfeng Wang 		.name = "rfc4106",
112356a00d9dSXiongfeng Wang 		.create = crypto_rfc4106_create,
112456a00d9dSXiongfeng Wang 		.module = THIS_MODULE,
112556a00d9dSXiongfeng Wang 	}, {
112673c89c15STobias Brunner 		.name = "rfc4543",
1127adcbc688SHerbert Xu 		.create = crypto_rfc4543_create,
112873c89c15STobias Brunner 		.module = THIS_MODULE,
112956a00d9dSXiongfeng Wang 	},
113073c89c15STobias Brunner };
113173c89c15STobias Brunner 
crypto_gcm_module_init(void)113228db8e3eSMikko Herranen static int __init crypto_gcm_module_init(void)
113328db8e3eSMikko Herranen {
1134d00aa19bSHerbert Xu 	int err;
1135d00aa19bSHerbert Xu 
1136adcbc688SHerbert Xu 	gcm_zeroes = kzalloc(sizeof(*gcm_zeroes), GFP_KERNEL);
11379382d97aSHuang Ying 	if (!gcm_zeroes)
11389382d97aSHuang Ying 		return -ENOMEM;
11399382d97aSHuang Ying 
1140adcbc688SHerbert Xu 	sg_init_one(&gcm_zeroes->sg, gcm_zeroes->buf, sizeof(gcm_zeroes->buf));
1141adcbc688SHerbert Xu 
114256a00d9dSXiongfeng Wang 	err = crypto_register_templates(crypto_gcm_tmpls,
114356a00d9dSXiongfeng Wang 					ARRAY_SIZE(crypto_gcm_tmpls));
1144d00aa19bSHerbert Xu 	if (err)
11459382d97aSHuang Ying 		kfree(gcm_zeroes);
114656a00d9dSXiongfeng Wang 
11479382d97aSHuang Ying 	return err;
114828db8e3eSMikko Herranen }
114928db8e3eSMikko Herranen 
crypto_gcm_module_exit(void)115028db8e3eSMikko Herranen static void __exit crypto_gcm_module_exit(void)
115128db8e3eSMikko Herranen {
11529382d97aSHuang Ying 	kfree(gcm_zeroes);
115356a00d9dSXiongfeng Wang 	crypto_unregister_templates(crypto_gcm_tmpls,
115456a00d9dSXiongfeng Wang 				    ARRAY_SIZE(crypto_gcm_tmpls));
115528db8e3eSMikko Herranen }
115628db8e3eSMikko Herranen 
1157c4741b23SEric Biggers subsys_initcall(crypto_gcm_module_init);
115828db8e3eSMikko Herranen module_exit(crypto_gcm_module_exit);
115928db8e3eSMikko Herranen 
116028db8e3eSMikko Herranen MODULE_LICENSE("GPL");
116128db8e3eSMikko Herranen MODULE_DESCRIPTION("Galois/Counter Mode");
116228db8e3eSMikko Herranen MODULE_AUTHOR("Mikko Herranen <mh1@iki.fi>");
11635d26a105SKees Cook MODULE_ALIAS_CRYPTO("gcm_base");
11645d26a105SKees Cook MODULE_ALIAS_CRYPTO("rfc4106");
11655d26a105SKees Cook MODULE_ALIAS_CRYPTO("rfc4543");
11664943ba16SKees Cook MODULE_ALIAS_CRYPTO("gcm");
1167