xref: /openbmc/linux/crypto/ccm.c (revision 255e48eb)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
24a49b499SJoy Latten /*
34a49b499SJoy Latten  * CCM: Counter with CBC-MAC
44a49b499SJoy Latten  *
54a49b499SJoy Latten  * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
64a49b499SJoy Latten  */
74a49b499SJoy Latten 
84a49b499SJoy Latten #include <crypto/internal/aead.h>
90eb76ba2SArd Biesheuvel #include <crypto/internal/cipher.h>
10f15f05b0SArd Biesheuvel #include <crypto/internal/hash.h>
114a49b499SJoy Latten #include <crypto/internal/skcipher.h>
124a49b499SJoy Latten #include <crypto/scatterwalk.h>
134a49b499SJoy Latten #include <linux/err.h>
144a49b499SJoy Latten #include <linux/init.h>
154a49b499SJoy Latten #include <linux/kernel.h>
164a49b499SJoy Latten #include <linux/module.h>
174a49b499SJoy Latten #include <linux/slab.h>
184a49b499SJoy Latten 
194a49b499SJoy Latten struct ccm_instance_ctx {
204a49b499SJoy Latten 	struct crypto_skcipher_spawn ctr;
21f15f05b0SArd Biesheuvel 	struct crypto_ahash_spawn mac;
224a49b499SJoy Latten };
234a49b499SJoy Latten 
244a49b499SJoy Latten struct crypto_ccm_ctx {
25f15f05b0SArd Biesheuvel 	struct crypto_ahash *mac;
26464b93a3SHerbert Xu 	struct crypto_skcipher *ctr;
274a49b499SJoy Latten };
284a49b499SJoy Latten 
294a49b499SJoy Latten struct crypto_rfc4309_ctx {
304a49b499SJoy Latten 	struct crypto_aead *child;
314a49b499SJoy Latten 	u8 nonce[3];
324a49b499SJoy Latten };
334a49b499SJoy Latten 
3481c4c35eSHerbert Xu struct crypto_rfc4309_req_ctx {
3581c4c35eSHerbert Xu 	struct scatterlist src[3];
3681c4c35eSHerbert Xu 	struct scatterlist dst[3];
3781c4c35eSHerbert Xu 	struct aead_request subreq;
3881c4c35eSHerbert Xu };
3981c4c35eSHerbert Xu 
404a49b499SJoy Latten struct crypto_ccm_req_priv_ctx {
414a49b499SJoy Latten 	u8 odata[16];
423b30460cSArd Biesheuvel 	u8 idata[16];
434a49b499SJoy Latten 	u8 auth_tag[16];
444a49b499SJoy Latten 	u32 flags;
4581c4c35eSHerbert Xu 	struct scatterlist src[3];
4681c4c35eSHerbert Xu 	struct scatterlist dst[3];
47ebf533adSArd Biesheuvel 	union {
48ebf533adSArd Biesheuvel 		struct ahash_request ahreq;
49464b93a3SHerbert Xu 		struct skcipher_request skreq;
504a49b499SJoy Latten 	};
51ebf533adSArd Biesheuvel };
524a49b499SJoy Latten 
53f15f05b0SArd Biesheuvel struct cbcmac_tfm_ctx {
54f15f05b0SArd Biesheuvel 	struct crypto_cipher *child;
55f15f05b0SArd Biesheuvel };
56f15f05b0SArd Biesheuvel 
57f15f05b0SArd Biesheuvel struct cbcmac_desc_ctx {
58f15f05b0SArd Biesheuvel 	unsigned int len;
59f15f05b0SArd Biesheuvel };
60f15f05b0SArd Biesheuvel 
crypto_ccm_reqctx(struct aead_request * req)614a49b499SJoy Latten static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx(
624a49b499SJoy Latten 	struct aead_request *req)
634a49b499SJoy Latten {
644a49b499SJoy Latten 	unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
654a49b499SJoy Latten 
664a49b499SJoy Latten 	return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
674a49b499SJoy Latten }
684a49b499SJoy Latten 
set_msg_len(u8 * block,unsigned int msglen,int csize)694a49b499SJoy Latten static int set_msg_len(u8 *block, unsigned int msglen, int csize)
704a49b499SJoy Latten {
714a49b499SJoy Latten 	__be32 data;
724a49b499SJoy Latten 
734a49b499SJoy Latten 	memset(block, 0, csize);
744a49b499SJoy Latten 	block += csize;
754a49b499SJoy Latten 
764a49b499SJoy Latten 	if (csize >= 4)
774a49b499SJoy Latten 		csize = 4;
784a49b499SJoy Latten 	else if (msglen > (1 << (8 * csize)))
794a49b499SJoy Latten 		return -EOVERFLOW;
804a49b499SJoy Latten 
814a49b499SJoy Latten 	data = cpu_to_be32(msglen);
824a49b499SJoy Latten 	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
834a49b499SJoy Latten 
844a49b499SJoy Latten 	return 0;
854a49b499SJoy Latten }
864a49b499SJoy Latten 
crypto_ccm_setkey(struct crypto_aead * aead,const u8 * key,unsigned int keylen)874a49b499SJoy Latten static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key,
884a49b499SJoy Latten 			     unsigned int keylen)
894a49b499SJoy Latten {
904a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
91464b93a3SHerbert Xu 	struct crypto_skcipher *ctr = ctx->ctr;
92f15f05b0SArd Biesheuvel 	struct crypto_ahash *mac = ctx->mac;
93af5034e8SEric Biggers 	int err;
944a49b499SJoy Latten 
95464b93a3SHerbert Xu 	crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
96464b93a3SHerbert Xu 	crypto_skcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
974a49b499SJoy Latten 				       CRYPTO_TFM_REQ_MASK);
98464b93a3SHerbert Xu 	err = crypto_skcipher_setkey(ctr, key, keylen);
994a49b499SJoy Latten 	if (err)
100af5034e8SEric Biggers 		return err;
1014a49b499SJoy Latten 
102f15f05b0SArd Biesheuvel 	crypto_ahash_clear_flags(mac, CRYPTO_TFM_REQ_MASK);
103f15f05b0SArd Biesheuvel 	crypto_ahash_set_flags(mac, crypto_aead_get_flags(aead) &
1044a49b499SJoy Latten 				    CRYPTO_TFM_REQ_MASK);
105af5034e8SEric Biggers 	return crypto_ahash_setkey(mac, key, keylen);
1064a49b499SJoy Latten }
1074a49b499SJoy Latten 
crypto_ccm_setauthsize(struct crypto_aead * tfm,unsigned int authsize)1084a49b499SJoy Latten static int crypto_ccm_setauthsize(struct crypto_aead *tfm,
1094a49b499SJoy Latten 				  unsigned int authsize)
1104a49b499SJoy Latten {
1114a49b499SJoy Latten 	switch (authsize) {
1124a49b499SJoy Latten 	case 4:
1134a49b499SJoy Latten 	case 6:
1144a49b499SJoy Latten 	case 8:
1154a49b499SJoy Latten 	case 10:
1164a49b499SJoy Latten 	case 12:
1174a49b499SJoy Latten 	case 14:
1184a49b499SJoy Latten 	case 16:
1194a49b499SJoy Latten 		break;
1204a49b499SJoy Latten 	default:
1214a49b499SJoy Latten 		return -EINVAL;
1224a49b499SJoy Latten 	}
1234a49b499SJoy Latten 
1244a49b499SJoy Latten 	return 0;
1254a49b499SJoy Latten }
1264a49b499SJoy Latten 
format_input(u8 * info,struct aead_request * req,unsigned int cryptlen)1274a49b499SJoy Latten static int format_input(u8 *info, struct aead_request *req,
1284a49b499SJoy Latten 			unsigned int cryptlen)
1294a49b499SJoy Latten {
1304a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
1314a49b499SJoy Latten 	unsigned int lp = req->iv[0];
1324a49b499SJoy Latten 	unsigned int l = lp + 1;
1334a49b499SJoy Latten 	unsigned int m;
1344a49b499SJoy Latten 
1354a49b499SJoy Latten 	m = crypto_aead_authsize(aead);
1364a49b499SJoy Latten 
1374a49b499SJoy Latten 	memcpy(info, req->iv, 16);
1384a49b499SJoy Latten 
1394a49b499SJoy Latten 	/* format control info per RFC 3610 and
1404a49b499SJoy Latten 	 * NIST Special Publication 800-38C
1414a49b499SJoy Latten 	 */
1424a49b499SJoy Latten 	*info |= (8 * ((m - 2) / 2));
1434a49b499SJoy Latten 	if (req->assoclen)
1444a49b499SJoy Latten 		*info |= 64;
1454a49b499SJoy Latten 
1464a49b499SJoy Latten 	return set_msg_len(info + 16 - l, cryptlen, l);
1474a49b499SJoy Latten }
1484a49b499SJoy Latten 
format_adata(u8 * adata,unsigned int a)1494a49b499SJoy Latten static int format_adata(u8 *adata, unsigned int a)
1504a49b499SJoy Latten {
1514a49b499SJoy Latten 	int len = 0;
1524a49b499SJoy Latten 
1534a49b499SJoy Latten 	/* add control info for associated data
1544a49b499SJoy Latten 	 * RFC 3610 and NIST Special Publication 800-38C
1554a49b499SJoy Latten 	 */
1564a49b499SJoy Latten 	if (a < 65280) {
1574a49b499SJoy Latten 		*(__be16 *)adata = cpu_to_be16(a);
1584a49b499SJoy Latten 		len = 2;
1594a49b499SJoy Latten 	} else  {
1604a49b499SJoy Latten 		*(__be16 *)adata = cpu_to_be16(0xfffe);
1614a49b499SJoy Latten 		*(__be32 *)&adata[2] = cpu_to_be32(a);
1624a49b499SJoy Latten 		len = 6;
1634a49b499SJoy Latten 	}
1644a49b499SJoy Latten 
1654a49b499SJoy Latten 	return len;
1664a49b499SJoy Latten }
1674a49b499SJoy Latten 
crypto_ccm_auth(struct aead_request * req,struct scatterlist * plain,unsigned int cryptlen)1684a49b499SJoy Latten static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
1694a49b499SJoy Latten 			   unsigned int cryptlen)
1704a49b499SJoy Latten {
171f15f05b0SArd Biesheuvel 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
1724a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
1734a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
174ebf533adSArd Biesheuvel 	struct ahash_request *ahreq = &pctx->ahreq;
1754a49b499SJoy Latten 	unsigned int assoclen = req->assoclen;
176f15f05b0SArd Biesheuvel 	struct scatterlist sg[3];
1773b30460cSArd Biesheuvel 	u8 *odata = pctx->odata;
1783b30460cSArd Biesheuvel 	u8 *idata = pctx->idata;
179f15f05b0SArd Biesheuvel 	int ilen, err;
1804a49b499SJoy Latten 
1814a49b499SJoy Latten 	/* format control data for input */
1824a49b499SJoy Latten 	err = format_input(odata, req, cryptlen);
1834a49b499SJoy Latten 	if (err)
1844a49b499SJoy Latten 		goto out;
1854a49b499SJoy Latten 
186f15f05b0SArd Biesheuvel 	sg_init_table(sg, 3);
187f15f05b0SArd Biesheuvel 	sg_set_buf(&sg[0], odata, 16);
1884a49b499SJoy Latten 
1894a49b499SJoy Latten 	/* format associated data and compute into mac */
1904a49b499SJoy Latten 	if (assoclen) {
191f15f05b0SArd Biesheuvel 		ilen = format_adata(idata, assoclen);
192f15f05b0SArd Biesheuvel 		sg_set_buf(&sg[1], idata, ilen);
193f15f05b0SArd Biesheuvel 		sg_chain(sg, 3, req->src);
194516280e7SJarod Wilson 	} else {
195f15f05b0SArd Biesheuvel 		ilen = 0;
196f15f05b0SArd Biesheuvel 		sg_chain(sg, 2, req->src);
1974a49b499SJoy Latten 	}
1984a49b499SJoy Latten 
199f15f05b0SArd Biesheuvel 	ahash_request_set_tfm(ahreq, ctx->mac);
200f15f05b0SArd Biesheuvel 	ahash_request_set_callback(ahreq, pctx->flags, NULL, NULL);
201f15f05b0SArd Biesheuvel 	ahash_request_set_crypt(ahreq, sg, NULL, assoclen + ilen + 16);
202f15f05b0SArd Biesheuvel 	err = crypto_ahash_init(ahreq);
203f15f05b0SArd Biesheuvel 	if (err)
204f15f05b0SArd Biesheuvel 		goto out;
205f15f05b0SArd Biesheuvel 	err = crypto_ahash_update(ahreq);
206f15f05b0SArd Biesheuvel 	if (err)
207f15f05b0SArd Biesheuvel 		goto out;
2084a49b499SJoy Latten 
209f15f05b0SArd Biesheuvel 	/* we need to pad the MAC input to a round multiple of the block size */
210f15f05b0SArd Biesheuvel 	ilen = 16 - (assoclen + ilen) % 16;
211f15f05b0SArd Biesheuvel 	if (ilen < 16) {
212f15f05b0SArd Biesheuvel 		memset(idata, 0, ilen);
213f15f05b0SArd Biesheuvel 		sg_init_table(sg, 2);
214f15f05b0SArd Biesheuvel 		sg_set_buf(&sg[0], idata, ilen);
215f15f05b0SArd Biesheuvel 		if (plain)
216f15f05b0SArd Biesheuvel 			sg_chain(sg, 2, plain);
217f15f05b0SArd Biesheuvel 		plain = sg;
218f15f05b0SArd Biesheuvel 		cryptlen += ilen;
219f15f05b0SArd Biesheuvel 	}
220f15f05b0SArd Biesheuvel 
221ad981647STianjia Zhang 	ahash_request_set_crypt(ahreq, plain, odata, cryptlen);
222f15f05b0SArd Biesheuvel 	err = crypto_ahash_finup(ahreq);
2234a49b499SJoy Latten out:
2244a49b499SJoy Latten 	return err;
2254a49b499SJoy Latten }
2264a49b499SJoy Latten 
crypto_ccm_encrypt_done(void * data,int err)227*255e48ebSHerbert Xu static void crypto_ccm_encrypt_done(void *data, int err)
2284a49b499SJoy Latten {
229*255e48ebSHerbert Xu 	struct aead_request *req = data;
2304a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2314a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
2324a49b499SJoy Latten 	u8 *odata = pctx->odata;
2334a49b499SJoy Latten 
2344a49b499SJoy Latten 	if (!err)
23581c4c35eSHerbert Xu 		scatterwalk_map_and_copy(odata, req->dst,
23681c4c35eSHerbert Xu 					 req->assoclen + req->cryptlen,
2374a49b499SJoy Latten 					 crypto_aead_authsize(aead), 1);
2384a49b499SJoy Latten 	aead_request_complete(req, err);
2394a49b499SJoy Latten }
2404a49b499SJoy Latten 
crypto_ccm_check_iv(const u8 * iv)2414a49b499SJoy Latten static inline int crypto_ccm_check_iv(const u8 *iv)
2424a49b499SJoy Latten {
2434a49b499SJoy Latten 	/* 2 <= L <= 8, so 1 <= L' <= 7. */
2444a49b499SJoy Latten 	if (1 > iv[0] || iv[0] > 7)
2454a49b499SJoy Latten 		return -EINVAL;
2464a49b499SJoy Latten 
2474a49b499SJoy Latten 	return 0;
2484a49b499SJoy Latten }
2494a49b499SJoy Latten 
crypto_ccm_init_crypt(struct aead_request * req,u8 * tag)25081c4c35eSHerbert Xu static int crypto_ccm_init_crypt(struct aead_request *req, u8 *tag)
25181c4c35eSHerbert Xu {
25281c4c35eSHerbert Xu 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
25381c4c35eSHerbert Xu 	struct scatterlist *sg;
25481c4c35eSHerbert Xu 	u8 *iv = req->iv;
25581c4c35eSHerbert Xu 	int err;
25681c4c35eSHerbert Xu 
25781c4c35eSHerbert Xu 	err = crypto_ccm_check_iv(iv);
25881c4c35eSHerbert Xu 	if (err)
25981c4c35eSHerbert Xu 		return err;
26081c4c35eSHerbert Xu 
26181c4c35eSHerbert Xu 	pctx->flags = aead_request_flags(req);
26281c4c35eSHerbert Xu 
26381c4c35eSHerbert Xu 	 /* Note: rfc 3610 and NIST 800-38C require counter of
26481c4c35eSHerbert Xu 	 * zero to encrypt auth tag.
26581c4c35eSHerbert Xu 	 */
26681c4c35eSHerbert Xu 	memset(iv + 15 - iv[0], 0, iv[0] + 1);
26781c4c35eSHerbert Xu 
26881c4c35eSHerbert Xu 	sg_init_table(pctx->src, 3);
26981c4c35eSHerbert Xu 	sg_set_buf(pctx->src, tag, 16);
27081c4c35eSHerbert Xu 	sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
27181c4c35eSHerbert Xu 	if (sg != pctx->src + 1)
27281c4c35eSHerbert Xu 		sg_chain(pctx->src, 2, sg);
27381c4c35eSHerbert Xu 
27481c4c35eSHerbert Xu 	if (req->src != req->dst) {
27581c4c35eSHerbert Xu 		sg_init_table(pctx->dst, 3);
27681c4c35eSHerbert Xu 		sg_set_buf(pctx->dst, tag, 16);
27781c4c35eSHerbert Xu 		sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
27881c4c35eSHerbert Xu 		if (sg != pctx->dst + 1)
27981c4c35eSHerbert Xu 			sg_chain(pctx->dst, 2, sg);
28081c4c35eSHerbert Xu 	}
28181c4c35eSHerbert Xu 
28281c4c35eSHerbert Xu 	return 0;
28381c4c35eSHerbert Xu }
28481c4c35eSHerbert Xu 
crypto_ccm_encrypt(struct aead_request * req)2854a49b499SJoy Latten static int crypto_ccm_encrypt(struct aead_request *req)
2864a49b499SJoy Latten {
2874a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2884a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
2894a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
290464b93a3SHerbert Xu 	struct skcipher_request *skreq = &pctx->skreq;
2914a49b499SJoy Latten 	struct scatterlist *dst;
2924a49b499SJoy Latten 	unsigned int cryptlen = req->cryptlen;
2934a49b499SJoy Latten 	u8 *odata = pctx->odata;
2944a49b499SJoy Latten 	u8 *iv = req->iv;
2954a49b499SJoy Latten 	int err;
2964a49b499SJoy Latten 
29781c4c35eSHerbert Xu 	err = crypto_ccm_init_crypt(req, odata);
2984a49b499SJoy Latten 	if (err)
2994a49b499SJoy Latten 		return err;
3004a49b499SJoy Latten 
30181c4c35eSHerbert Xu 	err = crypto_ccm_auth(req, sg_next(pctx->src), cryptlen);
3024a49b499SJoy Latten 	if (err)
3034a49b499SJoy Latten 		return err;
3044a49b499SJoy Latten 
3054a49b499SJoy Latten 	dst = pctx->src;
30681c4c35eSHerbert Xu 	if (req->src != req->dst)
3074a49b499SJoy Latten 		dst = pctx->dst;
3084a49b499SJoy Latten 
309464b93a3SHerbert Xu 	skcipher_request_set_tfm(skreq, ctx->ctr);
310464b93a3SHerbert Xu 	skcipher_request_set_callback(skreq, pctx->flags,
3114a49b499SJoy Latten 				      crypto_ccm_encrypt_done, req);
312464b93a3SHerbert Xu 	skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv);
313464b93a3SHerbert Xu 	err = crypto_skcipher_encrypt(skreq);
3144a49b499SJoy Latten 	if (err)
3154a49b499SJoy Latten 		return err;
3164a49b499SJoy Latten 
3174a49b499SJoy Latten 	/* copy authtag to end of dst */
31881c4c35eSHerbert Xu 	scatterwalk_map_and_copy(odata, sg_next(dst), cryptlen,
3194a49b499SJoy Latten 				 crypto_aead_authsize(aead), 1);
3204a49b499SJoy Latten 	return err;
3214a49b499SJoy Latten }
3224a49b499SJoy Latten 
crypto_ccm_decrypt_done(void * data,int err)323*255e48ebSHerbert Xu static void crypto_ccm_decrypt_done(void *data, int err)
3244a49b499SJoy Latten {
325*255e48ebSHerbert Xu 	struct aead_request *req = data;
3264a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
3274a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
3284a49b499SJoy Latten 	unsigned int authsize = crypto_aead_authsize(aead);
3294a49b499SJoy Latten 	unsigned int cryptlen = req->cryptlen - authsize;
33081c4c35eSHerbert Xu 	struct scatterlist *dst;
33181c4c35eSHerbert Xu 
33281c4c35eSHerbert Xu 	pctx->flags = 0;
33381c4c35eSHerbert Xu 
33481c4c35eSHerbert Xu 	dst = sg_next(req->src == req->dst ? pctx->src : pctx->dst);
3354a49b499SJoy Latten 
3364a49b499SJoy Latten 	if (!err) {
33781c4c35eSHerbert Xu 		err = crypto_ccm_auth(req, dst, cryptlen);
3386bf37e5aSJames Yonan 		if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize))
3394a49b499SJoy Latten 			err = -EBADMSG;
3404a49b499SJoy Latten 	}
3414a49b499SJoy Latten 	aead_request_complete(req, err);
3424a49b499SJoy Latten }
3434a49b499SJoy Latten 
crypto_ccm_decrypt(struct aead_request * req)3444a49b499SJoy Latten static int crypto_ccm_decrypt(struct aead_request *req)
3454a49b499SJoy Latten {
3464a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
3474a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
3484a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
349464b93a3SHerbert Xu 	struct skcipher_request *skreq = &pctx->skreq;
3504a49b499SJoy Latten 	struct scatterlist *dst;
3514a49b499SJoy Latten 	unsigned int authsize = crypto_aead_authsize(aead);
3524a49b499SJoy Latten 	unsigned int cryptlen = req->cryptlen;
3534a49b499SJoy Latten 	u8 *authtag = pctx->auth_tag;
3544a49b499SJoy Latten 	u8 *odata = pctx->odata;
355441f99c9SRomain Izard 	u8 *iv = pctx->idata;
3564a49b499SJoy Latten 	int err;
3574a49b499SJoy Latten 
3584a49b499SJoy Latten 	cryptlen -= authsize;
3594a49b499SJoy Latten 
36081c4c35eSHerbert Xu 	err = crypto_ccm_init_crypt(req, authtag);
3614a49b499SJoy Latten 	if (err)
3624a49b499SJoy Latten 		return err;
3634a49b499SJoy Latten 
36481c4c35eSHerbert Xu 	scatterwalk_map_and_copy(authtag, sg_next(pctx->src), cryptlen,
36581c4c35eSHerbert Xu 				 authsize, 0);
3664a49b499SJoy Latten 
3674a49b499SJoy Latten 	dst = pctx->src;
36881c4c35eSHerbert Xu 	if (req->src != req->dst)
3694a49b499SJoy Latten 		dst = pctx->dst;
3704a49b499SJoy Latten 
371441f99c9SRomain Izard 	memcpy(iv, req->iv, 16);
372441f99c9SRomain Izard 
373464b93a3SHerbert Xu 	skcipher_request_set_tfm(skreq, ctx->ctr);
374464b93a3SHerbert Xu 	skcipher_request_set_callback(skreq, pctx->flags,
3754a49b499SJoy Latten 				      crypto_ccm_decrypt_done, req);
376464b93a3SHerbert Xu 	skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv);
377464b93a3SHerbert Xu 	err = crypto_skcipher_decrypt(skreq);
3784a49b499SJoy Latten 	if (err)
3794a49b499SJoy Latten 		return err;
3804a49b499SJoy Latten 
38181c4c35eSHerbert Xu 	err = crypto_ccm_auth(req, sg_next(dst), cryptlen);
3824a49b499SJoy Latten 	if (err)
3834a49b499SJoy Latten 		return err;
3844a49b499SJoy Latten 
3854a49b499SJoy Latten 	/* verify */
3866bf37e5aSJames Yonan 	if (crypto_memneq(authtag, odata, authsize))
3874a49b499SJoy Latten 		return -EBADMSG;
3884a49b499SJoy Latten 
3894a49b499SJoy Latten 	return err;
3904a49b499SJoy Latten }
3914a49b499SJoy Latten 
crypto_ccm_init_tfm(struct crypto_aead * tfm)39281c4c35eSHerbert Xu static int crypto_ccm_init_tfm(struct crypto_aead *tfm)
3934a49b499SJoy Latten {
39481c4c35eSHerbert Xu 	struct aead_instance *inst = aead_alg_instance(tfm);
39581c4c35eSHerbert Xu 	struct ccm_instance_ctx *ictx = aead_instance_ctx(inst);
39681c4c35eSHerbert Xu 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
397f15f05b0SArd Biesheuvel 	struct crypto_ahash *mac;
398464b93a3SHerbert Xu 	struct crypto_skcipher *ctr;
3994a49b499SJoy Latten 	unsigned long align;
4004a49b499SJoy Latten 	int err;
4014a49b499SJoy Latten 
402f15f05b0SArd Biesheuvel 	mac = crypto_spawn_ahash(&ictx->mac);
403f15f05b0SArd Biesheuvel 	if (IS_ERR(mac))
404f15f05b0SArd Biesheuvel 		return PTR_ERR(mac);
4054a49b499SJoy Latten 
40660425a8bSEric Biggers 	ctr = crypto_spawn_skcipher(&ictx->ctr);
4074a49b499SJoy Latten 	err = PTR_ERR(ctr);
4084a49b499SJoy Latten 	if (IS_ERR(ctr))
409f15f05b0SArd Biesheuvel 		goto err_free_mac;
4104a49b499SJoy Latten 
411f15f05b0SArd Biesheuvel 	ctx->mac = mac;
4124a49b499SJoy Latten 	ctx->ctr = ctr;
4134a49b499SJoy Latten 
41481c4c35eSHerbert Xu 	align = crypto_aead_alignmask(tfm);
4154a49b499SJoy Latten 	align &= ~(crypto_tfm_ctx_alignment() - 1);
41681c4c35eSHerbert Xu 	crypto_aead_set_reqsize(
41781c4c35eSHerbert Xu 		tfm,
4182c221ad3SHerbert Xu 		align + sizeof(struct crypto_ccm_req_priv_ctx) +
419ebf533adSArd Biesheuvel 		max(crypto_ahash_reqsize(mac), crypto_skcipher_reqsize(ctr)));
4204a49b499SJoy Latten 
4214a49b499SJoy Latten 	return 0;
4224a49b499SJoy Latten 
423f15f05b0SArd Biesheuvel err_free_mac:
424f15f05b0SArd Biesheuvel 	crypto_free_ahash(mac);
4254a49b499SJoy Latten 	return err;
4264a49b499SJoy Latten }
4274a49b499SJoy Latten 
crypto_ccm_exit_tfm(struct crypto_aead * tfm)42881c4c35eSHerbert Xu static void crypto_ccm_exit_tfm(struct crypto_aead *tfm)
4294a49b499SJoy Latten {
43081c4c35eSHerbert Xu 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
4314a49b499SJoy Latten 
432f15f05b0SArd Biesheuvel 	crypto_free_ahash(ctx->mac);
433464b93a3SHerbert Xu 	crypto_free_skcipher(ctx->ctr);
4344a49b499SJoy Latten }
4354a49b499SJoy Latten 
crypto_ccm_free(struct aead_instance * inst)43681c4c35eSHerbert Xu static void crypto_ccm_free(struct aead_instance *inst)
43781c4c35eSHerbert Xu {
43881c4c35eSHerbert Xu 	struct ccm_instance_ctx *ctx = aead_instance_ctx(inst);
43981c4c35eSHerbert Xu 
440f15f05b0SArd Biesheuvel 	crypto_drop_ahash(&ctx->mac);
44181c4c35eSHerbert Xu 	crypto_drop_skcipher(&ctx->ctr);
44281c4c35eSHerbert Xu 	kfree(inst);
44381c4c35eSHerbert Xu }
44481c4c35eSHerbert Xu 
crypto_ccm_create_common(struct crypto_template * tmpl,struct rtattr ** tb,const char * ctr_name,const char * mac_name)44581c4c35eSHerbert Xu static int crypto_ccm_create_common(struct crypto_template *tmpl,
44681c4c35eSHerbert Xu 				    struct rtattr **tb,
4474a49b499SJoy Latten 				    const char *ctr_name,
448f15f05b0SArd Biesheuvel 				    const char *mac_name)
4494a49b499SJoy Latten {
450b9f76dddSEric Biggers 	u32 mask;
45181c4c35eSHerbert Xu 	struct aead_instance *inst;
4524a49b499SJoy Latten 	struct ccm_instance_ctx *ictx;
45305b3bbb5SEric Biggers 	struct skcipher_alg *ctr;
45405b3bbb5SEric Biggers 	struct hash_alg_common *mac;
4554a49b499SJoy Latten 	int err;
4564a49b499SJoy Latten 
4577bcb2c99SEric Biggers 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
4587bcb2c99SEric Biggers 	if (err)
4597bcb2c99SEric Biggers 		return err;
460b9f76dddSEric Biggers 
46105b3bbb5SEric Biggers 	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
46205b3bbb5SEric Biggers 	if (!inst)
46305b3bbb5SEric Biggers 		return -ENOMEM;
46405b3bbb5SEric Biggers 	ictx = aead_instance_ctx(inst);
4654a49b499SJoy Latten 
46605b3bbb5SEric Biggers 	err = crypto_grab_ahash(&ictx->mac, aead_crypto_instance(inst),
4677bcb2c99SEric Biggers 				mac_name, 0, mask | CRYPTO_ALG_ASYNC);
46805b3bbb5SEric Biggers 	if (err)
46905b3bbb5SEric Biggers 		goto err_free_inst;
47005b3bbb5SEric Biggers 	mac = crypto_spawn_ahash_alg(&ictx->mac);
47105b3bbb5SEric Biggers 
4724a49b499SJoy Latten 	err = -EINVAL;
4736a1faa4aSEric Biggers 	if (strncmp(mac->base.cra_name, "cbcmac(", 7) != 0 ||
4746a1faa4aSEric Biggers 	    mac->digestsize != 16)
4754a49b499SJoy Latten 		goto err_free_inst;
4764a49b499SJoy Latten 
477b9f76dddSEric Biggers 	err = crypto_grab_skcipher(&ictx->ctr, aead_crypto_instance(inst),
478b9f76dddSEric Biggers 				   ctr_name, 0, mask);
4794a49b499SJoy Latten 	if (err)
48005b3bbb5SEric Biggers 		goto err_free_inst;
481464b93a3SHerbert Xu 	ctr = crypto_spawn_skcipher_alg(&ictx->ctr);
4824a49b499SJoy Latten 
4836a1faa4aSEric Biggers 	/* The skcipher algorithm must be CTR mode, using 16-byte blocks. */
4844a49b499SJoy Latten 	err = -EINVAL;
4856a1faa4aSEric Biggers 	if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 ||
4866a1faa4aSEric Biggers 	    crypto_skcipher_alg_ivsize(ctr) != 16 ||
4876a1faa4aSEric Biggers 	    ctr->base.cra_blocksize != 1)
48805b3bbb5SEric Biggers 		goto err_free_inst;
4894a49b499SJoy Latten 
4906a1faa4aSEric Biggers 	/* ctr and cbcmac must use the same underlying block cipher. */
4916a1faa4aSEric Biggers 	if (strcmp(ctr->base.cra_name + 4, mac->base.cra_name + 7) != 0)
49205b3bbb5SEric Biggers 		goto err_free_inst;
4934a49b499SJoy Latten 
4944a49b499SJoy Latten 	err = -ENAMETOOLONG;
4956a1faa4aSEric Biggers 	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
4966a1faa4aSEric Biggers 		     "ccm(%s", ctr->base.cra_name + 4) >= CRYPTO_MAX_ALG_NAME)
49705b3bbb5SEric Biggers 		goto err_free_inst;
4986a1faa4aSEric Biggers 
49981c4c35eSHerbert Xu 	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
500464b93a3SHerbert Xu 		     "ccm_base(%s,%s)", ctr->base.cra_driver_name,
501f15f05b0SArd Biesheuvel 		     mac->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
50205b3bbb5SEric Biggers 		goto err_free_inst;
5034a49b499SJoy Latten 
504f15f05b0SArd Biesheuvel 	inst->alg.base.cra_priority = (mac->base.cra_priority +
505464b93a3SHerbert Xu 				       ctr->base.cra_priority) / 2;
50681c4c35eSHerbert Xu 	inst->alg.base.cra_blocksize = 1;
507f15f05b0SArd Biesheuvel 	inst->alg.base.cra_alignmask = mac->base.cra_alignmask |
5085ba8e2a0SArd Biesheuvel 				       ctr->base.cra_alignmask;
50981c4c35eSHerbert Xu 	inst->alg.ivsize = 16;
510464b93a3SHerbert Xu 	inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
51181c4c35eSHerbert Xu 	inst->alg.maxauthsize = 16;
51281c4c35eSHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct crypto_ccm_ctx);
51381c4c35eSHerbert Xu 	inst->alg.init = crypto_ccm_init_tfm;
51481c4c35eSHerbert Xu 	inst->alg.exit = crypto_ccm_exit_tfm;
51581c4c35eSHerbert Xu 	inst->alg.setkey = crypto_ccm_setkey;
51681c4c35eSHerbert Xu 	inst->alg.setauthsize = crypto_ccm_setauthsize;
51781c4c35eSHerbert Xu 	inst->alg.encrypt = crypto_ccm_encrypt;
51881c4c35eSHerbert Xu 	inst->alg.decrypt = crypto_ccm_decrypt;
5194a49b499SJoy Latten 
52081c4c35eSHerbert Xu 	inst->free = crypto_ccm_free;
52181c4c35eSHerbert Xu 
52281c4c35eSHerbert Xu 	err = aead_register_instance(tmpl, inst);
52305b3bbb5SEric Biggers 	if (err) {
5244a49b499SJoy Latten err_free_inst:
52505b3bbb5SEric Biggers 		crypto_ccm_free(inst);
52605b3bbb5SEric Biggers 	}
52705b3bbb5SEric Biggers 	return err;
5284a49b499SJoy Latten }
5294a49b499SJoy Latten 
crypto_ccm_create(struct crypto_template * tmpl,struct rtattr ** tb)53081c4c35eSHerbert Xu static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb)
5314a49b499SJoy Latten {
5324a49b499SJoy Latten 	const char *cipher_name;
5334a49b499SJoy Latten 	char ctr_name[CRYPTO_MAX_ALG_NAME];
534f15f05b0SArd Biesheuvel 	char mac_name[CRYPTO_MAX_ALG_NAME];
5354a49b499SJoy Latten 
5364a49b499SJoy Latten 	cipher_name = crypto_attr_alg_name(tb[1]);
5374a49b499SJoy Latten 	if (IS_ERR(cipher_name))
53881c4c35eSHerbert Xu 		return PTR_ERR(cipher_name);
5394a49b499SJoy Latten 
5404a49b499SJoy Latten 	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
5414a49b499SJoy Latten 		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
54281c4c35eSHerbert Xu 		return -ENAMETOOLONG;
5434a49b499SJoy Latten 
544f15f05b0SArd Biesheuvel 	if (snprintf(mac_name, CRYPTO_MAX_ALG_NAME, "cbcmac(%s)",
545f15f05b0SArd Biesheuvel 		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
546f15f05b0SArd Biesheuvel 		return -ENAMETOOLONG;
547f15f05b0SArd Biesheuvel 
5486a1faa4aSEric Biggers 	return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);
5494a49b499SJoy Latten }
5504a49b499SJoy Latten 
crypto_ccm_base_create(struct crypto_template * tmpl,struct rtattr ** tb)55181c4c35eSHerbert Xu static int crypto_ccm_base_create(struct crypto_template *tmpl,
55281c4c35eSHerbert Xu 				  struct rtattr **tb)
5534a49b499SJoy Latten {
5544a49b499SJoy Latten 	const char *ctr_name;
5556a1faa4aSEric Biggers 	const char *mac_name;
5564a49b499SJoy Latten 
5574a49b499SJoy Latten 	ctr_name = crypto_attr_alg_name(tb[1]);
5584a49b499SJoy Latten 	if (IS_ERR(ctr_name))
55981c4c35eSHerbert Xu 		return PTR_ERR(ctr_name);
5604a49b499SJoy Latten 
5616a1faa4aSEric Biggers 	mac_name = crypto_attr_alg_name(tb[2]);
5626a1faa4aSEric Biggers 	if (IS_ERR(mac_name))
5636a1faa4aSEric Biggers 		return PTR_ERR(mac_name);
5644a49b499SJoy Latten 
5656a1faa4aSEric Biggers 	return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);
5664a49b499SJoy Latten }
5674a49b499SJoy Latten 
crypto_rfc4309_setkey(struct crypto_aead * parent,const u8 * key,unsigned int keylen)5684a49b499SJoy Latten static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key,
5694a49b499SJoy Latten 				 unsigned int keylen)
5704a49b499SJoy Latten {
5714a49b499SJoy Latten 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
5724a49b499SJoy Latten 	struct crypto_aead *child = ctx->child;
5734a49b499SJoy Latten 
5744a49b499SJoy Latten 	if (keylen < 3)
5754a49b499SJoy Latten 		return -EINVAL;
5764a49b499SJoy Latten 
5774a49b499SJoy Latten 	keylen -= 3;
5784a49b499SJoy Latten 	memcpy(ctx->nonce, key + keylen, 3);
5794a49b499SJoy Latten 
5804a49b499SJoy Latten 	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
5814a49b499SJoy Latten 	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
5824a49b499SJoy Latten 				     CRYPTO_TFM_REQ_MASK);
583af5034e8SEric Biggers 	return crypto_aead_setkey(child, key, keylen);
5844a49b499SJoy Latten }
5854a49b499SJoy Latten 
crypto_rfc4309_setauthsize(struct crypto_aead * parent,unsigned int authsize)5864a49b499SJoy Latten static int crypto_rfc4309_setauthsize(struct crypto_aead *parent,
5874a49b499SJoy Latten 				      unsigned int authsize)
5884a49b499SJoy Latten {
5894a49b499SJoy Latten 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
5904a49b499SJoy Latten 
5914a49b499SJoy Latten 	switch (authsize) {
5924a49b499SJoy Latten 	case 8:
5934a49b499SJoy Latten 	case 12:
5944a49b499SJoy Latten 	case 16:
5954a49b499SJoy Latten 		break;
5964a49b499SJoy Latten 	default:
5974a49b499SJoy Latten 		return -EINVAL;
5984a49b499SJoy Latten 	}
5994a49b499SJoy Latten 
6004a49b499SJoy Latten 	return crypto_aead_setauthsize(ctx->child, authsize);
6014a49b499SJoy Latten }
6024a49b499SJoy Latten 
crypto_rfc4309_crypt(struct aead_request * req)6034a49b499SJoy Latten static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req)
6044a49b499SJoy Latten {
60581c4c35eSHerbert Xu 	struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req);
60681c4c35eSHerbert Xu 	struct aead_request *subreq = &rctx->subreq;
6074a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
6084a49b499SJoy Latten 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(aead);
6094a49b499SJoy Latten 	struct crypto_aead *child = ctx->child;
61081c4c35eSHerbert Xu 	struct scatterlist *sg;
6114a49b499SJoy Latten 	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
6124a49b499SJoy Latten 			   crypto_aead_alignmask(child) + 1);
6134a49b499SJoy Latten 
6144a49b499SJoy Latten 	/* L' */
6154a49b499SJoy Latten 	iv[0] = 3;
6164a49b499SJoy Latten 
6174a49b499SJoy Latten 	memcpy(iv + 1, ctx->nonce, 3);
6184a49b499SJoy Latten 	memcpy(iv + 4, req->iv, 8);
6194a49b499SJoy Latten 
62081c4c35eSHerbert Xu 	scatterwalk_map_and_copy(iv + 16, req->src, 0, req->assoclen - 8, 0);
62181c4c35eSHerbert Xu 
62281c4c35eSHerbert Xu 	sg_init_table(rctx->src, 3);
62381c4c35eSHerbert Xu 	sg_set_buf(rctx->src, iv + 16, req->assoclen - 8);
62481c4c35eSHerbert Xu 	sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen);
62581c4c35eSHerbert Xu 	if (sg != rctx->src + 1)
62681c4c35eSHerbert Xu 		sg_chain(rctx->src, 2, sg);
62781c4c35eSHerbert Xu 
62881c4c35eSHerbert Xu 	if (req->src != req->dst) {
62981c4c35eSHerbert Xu 		sg_init_table(rctx->dst, 3);
63081c4c35eSHerbert Xu 		sg_set_buf(rctx->dst, iv + 16, req->assoclen - 8);
63181c4c35eSHerbert Xu 		sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen);
63281c4c35eSHerbert Xu 		if (sg != rctx->dst + 1)
63381c4c35eSHerbert Xu 			sg_chain(rctx->dst, 2, sg);
63481c4c35eSHerbert Xu 	}
63581c4c35eSHerbert Xu 
6364a49b499SJoy Latten 	aead_request_set_tfm(subreq, child);
6374a49b499SJoy Latten 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
6384a49b499SJoy Latten 				  req->base.data);
63981c4c35eSHerbert Xu 	aead_request_set_crypt(subreq, rctx->src,
64081c4c35eSHerbert Xu 			       req->src == req->dst ? rctx->src : rctx->dst,
64181c4c35eSHerbert Xu 			       req->cryptlen, iv);
64281c4c35eSHerbert Xu 	aead_request_set_ad(subreq, req->assoclen - 8);
6434a49b499SJoy Latten 
6444a49b499SJoy Latten 	return subreq;
6454a49b499SJoy Latten }
6464a49b499SJoy Latten 
crypto_rfc4309_encrypt(struct aead_request * req)6474a49b499SJoy Latten static int crypto_rfc4309_encrypt(struct aead_request *req)
6484a49b499SJoy Latten {
64981c4c35eSHerbert Xu 	if (req->assoclen != 16 && req->assoclen != 20)
65081c4c35eSHerbert Xu 		return -EINVAL;
65181c4c35eSHerbert Xu 
6524a49b499SJoy Latten 	req = crypto_rfc4309_crypt(req);
6534a49b499SJoy Latten 
6544a49b499SJoy Latten 	return crypto_aead_encrypt(req);
6554a49b499SJoy Latten }
6564a49b499SJoy Latten 
crypto_rfc4309_decrypt(struct aead_request * req)6574a49b499SJoy Latten static int crypto_rfc4309_decrypt(struct aead_request *req)
6584a49b499SJoy Latten {
65981c4c35eSHerbert Xu 	if (req->assoclen != 16 && req->assoclen != 20)
66081c4c35eSHerbert Xu 		return -EINVAL;
66181c4c35eSHerbert Xu 
6624a49b499SJoy Latten 	req = crypto_rfc4309_crypt(req);
6634a49b499SJoy Latten 
6644a49b499SJoy Latten 	return crypto_aead_decrypt(req);
6654a49b499SJoy Latten }
6664a49b499SJoy Latten 
crypto_rfc4309_init_tfm(struct crypto_aead * tfm)66781c4c35eSHerbert Xu static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm)
6684a49b499SJoy Latten {
66981c4c35eSHerbert Xu 	struct aead_instance *inst = aead_alg_instance(tfm);
67081c4c35eSHerbert Xu 	struct crypto_aead_spawn *spawn = aead_instance_ctx(inst);
67181c4c35eSHerbert Xu 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
6724a49b499SJoy Latten 	struct crypto_aead *aead;
6734a49b499SJoy Latten 	unsigned long align;
6744a49b499SJoy Latten 
6754a49b499SJoy Latten 	aead = crypto_spawn_aead(spawn);
6764a49b499SJoy Latten 	if (IS_ERR(aead))
6774a49b499SJoy Latten 		return PTR_ERR(aead);
6784a49b499SJoy Latten 
6794a49b499SJoy Latten 	ctx->child = aead;
6804a49b499SJoy Latten 
6814a49b499SJoy Latten 	align = crypto_aead_alignmask(aead);
6824a49b499SJoy Latten 	align &= ~(crypto_tfm_ctx_alignment() - 1);
68381c4c35eSHerbert Xu 	crypto_aead_set_reqsize(
68481c4c35eSHerbert Xu 		tfm,
68581c4c35eSHerbert Xu 		sizeof(struct crypto_rfc4309_req_ctx) +
6862c221ad3SHerbert Xu 		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
68781c4c35eSHerbert Xu 		align + 32);
6884a49b499SJoy Latten 
6894a49b499SJoy Latten 	return 0;
6904a49b499SJoy Latten }
6914a49b499SJoy Latten 
crypto_rfc4309_exit_tfm(struct crypto_aead * tfm)69281c4c35eSHerbert Xu static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm)
6934a49b499SJoy Latten {
69481c4c35eSHerbert Xu 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
6954a49b499SJoy Latten 
6964a49b499SJoy Latten 	crypto_free_aead(ctx->child);
6974a49b499SJoy Latten }
6984a49b499SJoy Latten 
crypto_rfc4309_free(struct aead_instance * inst)69981c4c35eSHerbert Xu static void crypto_rfc4309_free(struct aead_instance *inst)
70081c4c35eSHerbert Xu {
70181c4c35eSHerbert Xu 	crypto_drop_aead(aead_instance_ctx(inst));
70281c4c35eSHerbert Xu 	kfree(inst);
70381c4c35eSHerbert Xu }
70481c4c35eSHerbert Xu 
crypto_rfc4309_create(struct crypto_template * tmpl,struct rtattr ** tb)70581c4c35eSHerbert Xu static int crypto_rfc4309_create(struct crypto_template *tmpl,
70681c4c35eSHerbert Xu 				 struct rtattr **tb)
7074a49b499SJoy Latten {
708cd900f0cSEric Biggers 	u32 mask;
70981c4c35eSHerbert Xu 	struct aead_instance *inst;
7104a49b499SJoy Latten 	struct crypto_aead_spawn *spawn;
71181c4c35eSHerbert Xu 	struct aead_alg *alg;
7124a49b499SJoy Latten 	int err;
7134a49b499SJoy Latten 
7147bcb2c99SEric Biggers 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
7157bcb2c99SEric Biggers 	if (err)
7167bcb2c99SEric Biggers 		return err;
717cd900f0cSEric Biggers 
7184a49b499SJoy Latten 	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
7194a49b499SJoy Latten 	if (!inst)
72081c4c35eSHerbert Xu 		return -ENOMEM;
7214a49b499SJoy Latten 
72281c4c35eSHerbert Xu 	spawn = aead_instance_ctx(inst);
723cd900f0cSEric Biggers 	err = crypto_grab_aead(spawn, aead_crypto_instance(inst),
72464d66793SEric Biggers 			       crypto_attr_alg_name(tb[1]), 0, mask);
7254a49b499SJoy Latten 	if (err)
72664d66793SEric Biggers 		goto err_free_inst;
7274a49b499SJoy Latten 
72881c4c35eSHerbert Xu 	alg = crypto_spawn_aead_alg(spawn);
7294a49b499SJoy Latten 
7304a49b499SJoy Latten 	err = -EINVAL;
7314a49b499SJoy Latten 
7324a49b499SJoy Latten 	/* We only support 16-byte blocks. */
73381c4c35eSHerbert Xu 	if (crypto_aead_alg_ivsize(alg) != 16)
73464d66793SEric Biggers 		goto err_free_inst;
7354a49b499SJoy Latten 
7364a49b499SJoy Latten 	/* Not a stream cipher? */
73781c4c35eSHerbert Xu 	if (alg->base.cra_blocksize != 1)
73864d66793SEric Biggers 		goto err_free_inst;
7394a49b499SJoy Latten 
7404a49b499SJoy Latten 	err = -ENAMETOOLONG;
74181c4c35eSHerbert Xu 	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
74281c4c35eSHerbert Xu 		     "rfc4309(%s)", alg->base.cra_name) >=
74381c4c35eSHerbert Xu 	    CRYPTO_MAX_ALG_NAME ||
74481c4c35eSHerbert Xu 	    snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
74581c4c35eSHerbert Xu 		     "rfc4309(%s)", alg->base.cra_driver_name) >=
7464a49b499SJoy Latten 	    CRYPTO_MAX_ALG_NAME)
74764d66793SEric Biggers 		goto err_free_inst;
7484a49b499SJoy Latten 
74981c4c35eSHerbert Xu 	inst->alg.base.cra_priority = alg->base.cra_priority;
75081c4c35eSHerbert Xu 	inst->alg.base.cra_blocksize = 1;
75181c4c35eSHerbert Xu 	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
7524a49b499SJoy Latten 
75381c4c35eSHerbert Xu 	inst->alg.ivsize = 8;
754464b93a3SHerbert Xu 	inst->alg.chunksize = crypto_aead_alg_chunksize(alg);
75581c4c35eSHerbert Xu 	inst->alg.maxauthsize = 16;
7564a49b499SJoy Latten 
75781c4c35eSHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);
7584a49b499SJoy Latten 
75981c4c35eSHerbert Xu 	inst->alg.init = crypto_rfc4309_init_tfm;
76081c4c35eSHerbert Xu 	inst->alg.exit = crypto_rfc4309_exit_tfm;
7614a49b499SJoy Latten 
76281c4c35eSHerbert Xu 	inst->alg.setkey = crypto_rfc4309_setkey;
76381c4c35eSHerbert Xu 	inst->alg.setauthsize = crypto_rfc4309_setauthsize;
76481c4c35eSHerbert Xu 	inst->alg.encrypt = crypto_rfc4309_encrypt;
76581c4c35eSHerbert Xu 	inst->alg.decrypt = crypto_rfc4309_decrypt;
7664a49b499SJoy Latten 
76781c4c35eSHerbert Xu 	inst->free = crypto_rfc4309_free;
76881c4c35eSHerbert Xu 
76981c4c35eSHerbert Xu 	err = aead_register_instance(tmpl, inst);
77064d66793SEric Biggers 	if (err) {
77164d66793SEric Biggers err_free_inst:
77264d66793SEric Biggers 		crypto_rfc4309_free(inst);
77364d66793SEric Biggers 	}
77481c4c35eSHerbert Xu 	return err;
7754a49b499SJoy Latten }
7764a49b499SJoy Latten 
crypto_cbcmac_digest_setkey(struct crypto_shash * parent,const u8 * inkey,unsigned int keylen)777f15f05b0SArd Biesheuvel static int crypto_cbcmac_digest_setkey(struct crypto_shash *parent,
778f15f05b0SArd Biesheuvel 				     const u8 *inkey, unsigned int keylen)
779f15f05b0SArd Biesheuvel {
780f15f05b0SArd Biesheuvel 	struct cbcmac_tfm_ctx *ctx = crypto_shash_ctx(parent);
781f15f05b0SArd Biesheuvel 
782f15f05b0SArd Biesheuvel 	return crypto_cipher_setkey(ctx->child, inkey, keylen);
783f15f05b0SArd Biesheuvel }
784f15f05b0SArd Biesheuvel 
crypto_cbcmac_digest_init(struct shash_desc * pdesc)785f15f05b0SArd Biesheuvel static int crypto_cbcmac_digest_init(struct shash_desc *pdesc)
786f15f05b0SArd Biesheuvel {
787f15f05b0SArd Biesheuvel 	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
788f15f05b0SArd Biesheuvel 	int bs = crypto_shash_digestsize(pdesc->tfm);
7895338ad70SArd Biesheuvel 	u8 *dg = (u8 *)ctx + crypto_shash_descsize(pdesc->tfm) - bs;
790f15f05b0SArd Biesheuvel 
791f15f05b0SArd Biesheuvel 	ctx->len = 0;
7925338ad70SArd Biesheuvel 	memset(dg, 0, bs);
793f15f05b0SArd Biesheuvel 
794f15f05b0SArd Biesheuvel 	return 0;
795f15f05b0SArd Biesheuvel }
796f15f05b0SArd Biesheuvel 
crypto_cbcmac_digest_update(struct shash_desc * pdesc,const u8 * p,unsigned int len)797f15f05b0SArd Biesheuvel static int crypto_cbcmac_digest_update(struct shash_desc *pdesc, const u8 *p,
798f15f05b0SArd Biesheuvel 				       unsigned int len)
799f15f05b0SArd Biesheuvel {
800f15f05b0SArd Biesheuvel 	struct crypto_shash *parent = pdesc->tfm;
801f15f05b0SArd Biesheuvel 	struct cbcmac_tfm_ctx *tctx = crypto_shash_ctx(parent);
802f15f05b0SArd Biesheuvel 	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
803f15f05b0SArd Biesheuvel 	struct crypto_cipher *tfm = tctx->child;
804f15f05b0SArd Biesheuvel 	int bs = crypto_shash_digestsize(parent);
8055338ad70SArd Biesheuvel 	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
806f15f05b0SArd Biesheuvel 
807f15f05b0SArd Biesheuvel 	while (len > 0) {
808f15f05b0SArd Biesheuvel 		unsigned int l = min(len, bs - ctx->len);
809f15f05b0SArd Biesheuvel 
8105338ad70SArd Biesheuvel 		crypto_xor(dg + ctx->len, p, l);
811f15f05b0SArd Biesheuvel 		ctx->len +=l;
812f15f05b0SArd Biesheuvel 		len -= l;
813f15f05b0SArd Biesheuvel 		p += l;
814f15f05b0SArd Biesheuvel 
815f15f05b0SArd Biesheuvel 		if (ctx->len == bs) {
8165338ad70SArd Biesheuvel 			crypto_cipher_encrypt_one(tfm, dg, dg);
817f15f05b0SArd Biesheuvel 			ctx->len = 0;
818f15f05b0SArd Biesheuvel 		}
819f15f05b0SArd Biesheuvel 	}
820f15f05b0SArd Biesheuvel 
821f15f05b0SArd Biesheuvel 	return 0;
822f15f05b0SArd Biesheuvel }
823f15f05b0SArd Biesheuvel 
crypto_cbcmac_digest_final(struct shash_desc * pdesc,u8 * out)824f15f05b0SArd Biesheuvel static int crypto_cbcmac_digest_final(struct shash_desc *pdesc, u8 *out)
825f15f05b0SArd Biesheuvel {
826f15f05b0SArd Biesheuvel 	struct crypto_shash *parent = pdesc->tfm;
827f15f05b0SArd Biesheuvel 	struct cbcmac_tfm_ctx *tctx = crypto_shash_ctx(parent);
828f15f05b0SArd Biesheuvel 	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
829f15f05b0SArd Biesheuvel 	struct crypto_cipher *tfm = tctx->child;
830f15f05b0SArd Biesheuvel 	int bs = crypto_shash_digestsize(parent);
8315338ad70SArd Biesheuvel 	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
832f15f05b0SArd Biesheuvel 
833f15f05b0SArd Biesheuvel 	if (ctx->len)
8345338ad70SArd Biesheuvel 		crypto_cipher_encrypt_one(tfm, dg, dg);
835f15f05b0SArd Biesheuvel 
8365338ad70SArd Biesheuvel 	memcpy(out, dg, bs);
837f15f05b0SArd Biesheuvel 	return 0;
838f15f05b0SArd Biesheuvel }
839f15f05b0SArd Biesheuvel 
cbcmac_init_tfm(struct crypto_tfm * tfm)840f15f05b0SArd Biesheuvel static int cbcmac_init_tfm(struct crypto_tfm *tfm)
841f15f05b0SArd Biesheuvel {
842f15f05b0SArd Biesheuvel 	struct crypto_cipher *cipher;
843f15f05b0SArd Biesheuvel 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
844d5ed3b65SEric Biggers 	struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst);
845f15f05b0SArd Biesheuvel 	struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
846f15f05b0SArd Biesheuvel 
847f15f05b0SArd Biesheuvel 	cipher = crypto_spawn_cipher(spawn);
848f15f05b0SArd Biesheuvel 	if (IS_ERR(cipher))
849f15f05b0SArd Biesheuvel 		return PTR_ERR(cipher);
850f15f05b0SArd Biesheuvel 
851f15f05b0SArd Biesheuvel 	ctx->child = cipher;
852f15f05b0SArd Biesheuvel 
853f15f05b0SArd Biesheuvel 	return 0;
854f15f05b0SArd Biesheuvel };
855f15f05b0SArd Biesheuvel 
cbcmac_exit_tfm(struct crypto_tfm * tfm)856f15f05b0SArd Biesheuvel static void cbcmac_exit_tfm(struct crypto_tfm *tfm)
857f15f05b0SArd Biesheuvel {
858f15f05b0SArd Biesheuvel 	struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
859f15f05b0SArd Biesheuvel 	crypto_free_cipher(ctx->child);
860f15f05b0SArd Biesheuvel }
861f15f05b0SArd Biesheuvel 
cbcmac_create(struct crypto_template * tmpl,struct rtattr ** tb)862f15f05b0SArd Biesheuvel static int cbcmac_create(struct crypto_template *tmpl, struct rtattr **tb)
863f15f05b0SArd Biesheuvel {
864f15f05b0SArd Biesheuvel 	struct shash_instance *inst;
86516672970SEric Biggers 	struct crypto_cipher_spawn *spawn;
866f15f05b0SArd Biesheuvel 	struct crypto_alg *alg;
8677bcb2c99SEric Biggers 	u32 mask;
868f15f05b0SArd Biesheuvel 	int err;
869f15f05b0SArd Biesheuvel 
8707bcb2c99SEric Biggers 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH, &mask);
871f15f05b0SArd Biesheuvel 	if (err)
872f15f05b0SArd Biesheuvel 		return err;
873f15f05b0SArd Biesheuvel 
87416672970SEric Biggers 	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
87516672970SEric Biggers 	if (!inst)
87616672970SEric Biggers 		return -ENOMEM;
87716672970SEric Biggers 	spawn = shash_instance_ctx(inst);
878f15f05b0SArd Biesheuvel 
87916672970SEric Biggers 	err = crypto_grab_cipher(spawn, shash_crypto_instance(inst),
8807bcb2c99SEric Biggers 				 crypto_attr_alg_name(tb[1]), 0, mask);
881f15f05b0SArd Biesheuvel 	if (err)
88216672970SEric Biggers 		goto err_free_inst;
88316672970SEric Biggers 	alg = crypto_spawn_cipher_alg(spawn);
88416672970SEric Biggers 
88516672970SEric Biggers 	err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg);
88616672970SEric Biggers 	if (err)
88716672970SEric Biggers 		goto err_free_inst;
888f15f05b0SArd Biesheuvel 
889f15f05b0SArd Biesheuvel 	inst->alg.base.cra_priority = alg->cra_priority;
890f15f05b0SArd Biesheuvel 	inst->alg.base.cra_blocksize = 1;
891f15f05b0SArd Biesheuvel 
892f15f05b0SArd Biesheuvel 	inst->alg.digestsize = alg->cra_blocksize;
8935338ad70SArd Biesheuvel 	inst->alg.descsize = ALIGN(sizeof(struct cbcmac_desc_ctx),
8945338ad70SArd Biesheuvel 				   alg->cra_alignmask + 1) +
895f15f05b0SArd Biesheuvel 			     alg->cra_blocksize;
896f15f05b0SArd Biesheuvel 
897f15f05b0SArd Biesheuvel 	inst->alg.base.cra_ctxsize = sizeof(struct cbcmac_tfm_ctx);
898f15f05b0SArd Biesheuvel 	inst->alg.base.cra_init = cbcmac_init_tfm;
899f15f05b0SArd Biesheuvel 	inst->alg.base.cra_exit = cbcmac_exit_tfm;
900f15f05b0SArd Biesheuvel 
901f15f05b0SArd Biesheuvel 	inst->alg.init = crypto_cbcmac_digest_init;
902f15f05b0SArd Biesheuvel 	inst->alg.update = crypto_cbcmac_digest_update;
903f15f05b0SArd Biesheuvel 	inst->alg.final = crypto_cbcmac_digest_final;
904f15f05b0SArd Biesheuvel 	inst->alg.setkey = crypto_cbcmac_digest_setkey;
905f15f05b0SArd Biesheuvel 
906a39c66ccSEric Biggers 	inst->free = shash_free_singlespawn_instance;
907a39c66ccSEric Biggers 
908f15f05b0SArd Biesheuvel 	err = shash_register_instance(tmpl, inst);
90916672970SEric Biggers 	if (err) {
91016672970SEric Biggers err_free_inst:
911a39c66ccSEric Biggers 		shash_free_singlespawn_instance(inst);
91216672970SEric Biggers 	}
913f15f05b0SArd Biesheuvel 	return err;
914f15f05b0SArd Biesheuvel }
915f15f05b0SArd Biesheuvel 
9160db19035SXiongfeng Wang static struct crypto_template crypto_ccm_tmpls[] = {
9170db19035SXiongfeng Wang 	{
918f15f05b0SArd Biesheuvel 		.name = "cbcmac",
919f15f05b0SArd Biesheuvel 		.create = cbcmac_create,
920f15f05b0SArd Biesheuvel 		.module = THIS_MODULE,
9210db19035SXiongfeng Wang 	}, {
9220db19035SXiongfeng Wang 		.name = "ccm_base",
9230db19035SXiongfeng Wang 		.create = crypto_ccm_base_create,
9240db19035SXiongfeng Wang 		.module = THIS_MODULE,
9250db19035SXiongfeng Wang 	}, {
9260db19035SXiongfeng Wang 		.name = "ccm",
9270db19035SXiongfeng Wang 		.create = crypto_ccm_create,
9280db19035SXiongfeng Wang 		.module = THIS_MODULE,
9290db19035SXiongfeng Wang 	}, {
9300db19035SXiongfeng Wang 		.name = "rfc4309",
9310db19035SXiongfeng Wang 		.create = crypto_rfc4309_create,
9320db19035SXiongfeng Wang 		.module = THIS_MODULE,
9330db19035SXiongfeng Wang 	},
934f15f05b0SArd Biesheuvel };
935f15f05b0SArd Biesheuvel 
crypto_ccm_module_init(void)9364a49b499SJoy Latten static int __init crypto_ccm_module_init(void)
9374a49b499SJoy Latten {
9380db19035SXiongfeng Wang 	return crypto_register_templates(crypto_ccm_tmpls,
9390db19035SXiongfeng Wang 					 ARRAY_SIZE(crypto_ccm_tmpls));
9404a49b499SJoy Latten }
9414a49b499SJoy Latten 
crypto_ccm_module_exit(void)9424a49b499SJoy Latten static void __exit crypto_ccm_module_exit(void)
9434a49b499SJoy Latten {
9440db19035SXiongfeng Wang 	crypto_unregister_templates(crypto_ccm_tmpls,
9450db19035SXiongfeng Wang 				    ARRAY_SIZE(crypto_ccm_tmpls));
9464a49b499SJoy Latten }
9474a49b499SJoy Latten 
948c4741b23SEric Biggers subsys_initcall(crypto_ccm_module_init);
9494a49b499SJoy Latten module_exit(crypto_ccm_module_exit);
9504a49b499SJoy Latten 
9514a49b499SJoy Latten MODULE_LICENSE("GPL");
9524a49b499SJoy Latten MODULE_DESCRIPTION("Counter with CBC MAC");
9535d26a105SKees Cook MODULE_ALIAS_CRYPTO("ccm_base");
9545d26a105SKees Cook MODULE_ALIAS_CRYPTO("rfc4309");
9554943ba16SKees Cook MODULE_ALIAS_CRYPTO("ccm");
956ae748b9cSArd Biesheuvel MODULE_ALIAS_CRYPTO("cbcmac");
9570eb76ba2SArd Biesheuvel MODULE_IMPORT_NS(CRYPTO_INTERNAL);
958