xref: /openbmc/linux/crypto/ccm.c (revision 464b93a3)
14a49b499SJoy Latten /*
24a49b499SJoy Latten  * CCM: Counter with CBC-MAC
34a49b499SJoy Latten  *
44a49b499SJoy Latten  * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
54a49b499SJoy Latten  *
64a49b499SJoy Latten  * This program is free software; you can redistribute it and/or modify it
74a49b499SJoy Latten  * under the terms of the GNU General Public License as published by the Free
84a49b499SJoy Latten  * Software Foundation; either version 2 of the License, or (at your option)
94a49b499SJoy Latten  * any later version.
104a49b499SJoy Latten  *
114a49b499SJoy Latten  */
124a49b499SJoy Latten 
134a49b499SJoy Latten #include <crypto/internal/aead.h>
144a49b499SJoy Latten #include <crypto/internal/skcipher.h>
154a49b499SJoy Latten #include <crypto/scatterwalk.h>
164a49b499SJoy Latten #include <linux/err.h>
174a49b499SJoy Latten #include <linux/init.h>
184a49b499SJoy Latten #include <linux/kernel.h>
194a49b499SJoy Latten #include <linux/module.h>
204a49b499SJoy Latten #include <linux/slab.h>
214a49b499SJoy Latten 
224a49b499SJoy Latten #include "internal.h"
234a49b499SJoy Latten 
244a49b499SJoy Latten struct ccm_instance_ctx {
254a49b499SJoy Latten 	struct crypto_skcipher_spawn ctr;
264a49b499SJoy Latten 	struct crypto_spawn cipher;
274a49b499SJoy Latten };
284a49b499SJoy Latten 
294a49b499SJoy Latten struct crypto_ccm_ctx {
304a49b499SJoy Latten 	struct crypto_cipher *cipher;
31464b93a3SHerbert Xu 	struct crypto_skcipher *ctr;
324a49b499SJoy Latten };
334a49b499SJoy Latten 
344a49b499SJoy Latten struct crypto_rfc4309_ctx {
354a49b499SJoy Latten 	struct crypto_aead *child;
364a49b499SJoy Latten 	u8 nonce[3];
374a49b499SJoy Latten };
384a49b499SJoy Latten 
3981c4c35eSHerbert Xu struct crypto_rfc4309_req_ctx {
4081c4c35eSHerbert Xu 	struct scatterlist src[3];
4181c4c35eSHerbert Xu 	struct scatterlist dst[3];
4281c4c35eSHerbert Xu 	struct aead_request subreq;
4381c4c35eSHerbert Xu };
4481c4c35eSHerbert Xu 
454a49b499SJoy Latten struct crypto_ccm_req_priv_ctx {
464a49b499SJoy Latten 	u8 odata[16];
474a49b499SJoy Latten 	u8 idata[16];
484a49b499SJoy Latten 	u8 auth_tag[16];
494a49b499SJoy Latten 	u32 ilen;
504a49b499SJoy Latten 	u32 flags;
5181c4c35eSHerbert Xu 	struct scatterlist src[3];
5281c4c35eSHerbert Xu 	struct scatterlist dst[3];
53464b93a3SHerbert Xu 	struct skcipher_request skreq;
544a49b499SJoy Latten };
554a49b499SJoy Latten 
564a49b499SJoy Latten static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx(
574a49b499SJoy Latten 	struct aead_request *req)
584a49b499SJoy Latten {
594a49b499SJoy Latten 	unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
604a49b499SJoy Latten 
614a49b499SJoy Latten 	return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
624a49b499SJoy Latten }
634a49b499SJoy Latten 
644a49b499SJoy Latten static int set_msg_len(u8 *block, unsigned int msglen, int csize)
654a49b499SJoy Latten {
664a49b499SJoy Latten 	__be32 data;
674a49b499SJoy Latten 
684a49b499SJoy Latten 	memset(block, 0, csize);
694a49b499SJoy Latten 	block += csize;
704a49b499SJoy Latten 
714a49b499SJoy Latten 	if (csize >= 4)
724a49b499SJoy Latten 		csize = 4;
734a49b499SJoy Latten 	else if (msglen > (1 << (8 * csize)))
744a49b499SJoy Latten 		return -EOVERFLOW;
754a49b499SJoy Latten 
764a49b499SJoy Latten 	data = cpu_to_be32(msglen);
774a49b499SJoy Latten 	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
784a49b499SJoy Latten 
794a49b499SJoy Latten 	return 0;
804a49b499SJoy Latten }
814a49b499SJoy Latten 
824a49b499SJoy Latten static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key,
834a49b499SJoy Latten 			     unsigned int keylen)
844a49b499SJoy Latten {
854a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
86464b93a3SHerbert Xu 	struct crypto_skcipher *ctr = ctx->ctr;
874a49b499SJoy Latten 	struct crypto_cipher *tfm = ctx->cipher;
884a49b499SJoy Latten 	int err = 0;
894a49b499SJoy Latten 
90464b93a3SHerbert Xu 	crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
91464b93a3SHerbert Xu 	crypto_skcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
924a49b499SJoy Latten 				       CRYPTO_TFM_REQ_MASK);
93464b93a3SHerbert Xu 	err = crypto_skcipher_setkey(ctr, key, keylen);
94464b93a3SHerbert Xu 	crypto_aead_set_flags(aead, crypto_skcipher_get_flags(ctr) &
954a49b499SJoy Latten 			      CRYPTO_TFM_RES_MASK);
964a49b499SJoy Latten 	if (err)
974a49b499SJoy Latten 		goto out;
984a49b499SJoy Latten 
994a49b499SJoy Latten 	crypto_cipher_clear_flags(tfm, CRYPTO_TFM_REQ_MASK);
1004a49b499SJoy Latten 	crypto_cipher_set_flags(tfm, crypto_aead_get_flags(aead) &
1014a49b499SJoy Latten 				    CRYPTO_TFM_REQ_MASK);
1024a49b499SJoy Latten 	err = crypto_cipher_setkey(tfm, key, keylen);
1034a49b499SJoy Latten 	crypto_aead_set_flags(aead, crypto_cipher_get_flags(tfm) &
1044a49b499SJoy Latten 			      CRYPTO_TFM_RES_MASK);
1054a49b499SJoy Latten 
1064a49b499SJoy Latten out:
1074a49b499SJoy Latten 	return err;
1084a49b499SJoy Latten }
1094a49b499SJoy Latten 
1104a49b499SJoy Latten static int crypto_ccm_setauthsize(struct crypto_aead *tfm,
1114a49b499SJoy Latten 				  unsigned int authsize)
1124a49b499SJoy Latten {
1134a49b499SJoy Latten 	switch (authsize) {
1144a49b499SJoy Latten 	case 4:
1154a49b499SJoy Latten 	case 6:
1164a49b499SJoy Latten 	case 8:
1174a49b499SJoy Latten 	case 10:
1184a49b499SJoy Latten 	case 12:
1194a49b499SJoy Latten 	case 14:
1204a49b499SJoy Latten 	case 16:
1214a49b499SJoy Latten 		break;
1224a49b499SJoy Latten 	default:
1234a49b499SJoy Latten 		return -EINVAL;
1244a49b499SJoy Latten 	}
1254a49b499SJoy Latten 
1264a49b499SJoy Latten 	return 0;
1274a49b499SJoy Latten }
1284a49b499SJoy Latten 
1294a49b499SJoy Latten static int format_input(u8 *info, struct aead_request *req,
1304a49b499SJoy Latten 			unsigned int cryptlen)
1314a49b499SJoy Latten {
1324a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
1334a49b499SJoy Latten 	unsigned int lp = req->iv[0];
1344a49b499SJoy Latten 	unsigned int l = lp + 1;
1354a49b499SJoy Latten 	unsigned int m;
1364a49b499SJoy Latten 
1374a49b499SJoy Latten 	m = crypto_aead_authsize(aead);
1384a49b499SJoy Latten 
1394a49b499SJoy Latten 	memcpy(info, req->iv, 16);
1404a49b499SJoy Latten 
1414a49b499SJoy Latten 	/* format control info per RFC 3610 and
1424a49b499SJoy Latten 	 * NIST Special Publication 800-38C
1434a49b499SJoy Latten 	 */
1444a49b499SJoy Latten 	*info |= (8 * ((m - 2) / 2));
1454a49b499SJoy Latten 	if (req->assoclen)
1464a49b499SJoy Latten 		*info |= 64;
1474a49b499SJoy Latten 
1484a49b499SJoy Latten 	return set_msg_len(info + 16 - l, cryptlen, l);
1494a49b499SJoy Latten }
1504a49b499SJoy Latten 
1514a49b499SJoy Latten static int format_adata(u8 *adata, unsigned int a)
1524a49b499SJoy Latten {
1534a49b499SJoy Latten 	int len = 0;
1544a49b499SJoy Latten 
1554a49b499SJoy Latten 	/* add control info for associated data
1564a49b499SJoy Latten 	 * RFC 3610 and NIST Special Publication 800-38C
1574a49b499SJoy Latten 	 */
1584a49b499SJoy Latten 	if (a < 65280) {
1594a49b499SJoy Latten 		*(__be16 *)adata = cpu_to_be16(a);
1604a49b499SJoy Latten 		len = 2;
1614a49b499SJoy Latten 	} else  {
1624a49b499SJoy Latten 		*(__be16 *)adata = cpu_to_be16(0xfffe);
1634a49b499SJoy Latten 		*(__be32 *)&adata[2] = cpu_to_be32(a);
1644a49b499SJoy Latten 		len = 6;
1654a49b499SJoy Latten 	}
1664a49b499SJoy Latten 
1674a49b499SJoy Latten 	return len;
1684a49b499SJoy Latten }
1694a49b499SJoy Latten 
1704a49b499SJoy Latten static void compute_mac(struct crypto_cipher *tfm, u8 *data, int n,
1714a49b499SJoy Latten 		       struct crypto_ccm_req_priv_ctx *pctx)
1724a49b499SJoy Latten {
1734a49b499SJoy Latten 	unsigned int bs = 16;
1744a49b499SJoy Latten 	u8 *odata = pctx->odata;
1754a49b499SJoy Latten 	u8 *idata = pctx->idata;
1764a49b499SJoy Latten 	int datalen, getlen;
1774a49b499SJoy Latten 
1784a49b499SJoy Latten 	datalen = n;
1794a49b499SJoy Latten 
1804a49b499SJoy Latten 	/* first time in here, block may be partially filled. */
1814a49b499SJoy Latten 	getlen = bs - pctx->ilen;
1824a49b499SJoy Latten 	if (datalen >= getlen) {
1834a49b499SJoy Latten 		memcpy(idata + pctx->ilen, data, getlen);
1844a49b499SJoy Latten 		crypto_xor(odata, idata, bs);
1854a49b499SJoy Latten 		crypto_cipher_encrypt_one(tfm, odata, odata);
1864a49b499SJoy Latten 		datalen -= getlen;
1874a49b499SJoy Latten 		data += getlen;
1884a49b499SJoy Latten 		pctx->ilen = 0;
1894a49b499SJoy Latten 	}
1904a49b499SJoy Latten 
1914a49b499SJoy Latten 	/* now encrypt rest of data */
1924a49b499SJoy Latten 	while (datalen >= bs) {
1934a49b499SJoy Latten 		crypto_xor(odata, data, bs);
1944a49b499SJoy Latten 		crypto_cipher_encrypt_one(tfm, odata, odata);
1954a49b499SJoy Latten 
1964a49b499SJoy Latten 		datalen -= bs;
1974a49b499SJoy Latten 		data += bs;
1984a49b499SJoy Latten 	}
1994a49b499SJoy Latten 
2004a49b499SJoy Latten 	/* check and see if there's leftover data that wasn't
2014a49b499SJoy Latten 	 * enough to fill a block.
2024a49b499SJoy Latten 	 */
2034a49b499SJoy Latten 	if (datalen) {
2044a49b499SJoy Latten 		memcpy(idata + pctx->ilen, data, datalen);
2054a49b499SJoy Latten 		pctx->ilen += datalen;
2064a49b499SJoy Latten 	}
2074a49b499SJoy Latten }
2084a49b499SJoy Latten 
2094a49b499SJoy Latten static void get_data_to_compute(struct crypto_cipher *tfm,
2104a49b499SJoy Latten 			       struct crypto_ccm_req_priv_ctx *pctx,
2114a49b499SJoy Latten 			       struct scatterlist *sg, unsigned int len)
2124a49b499SJoy Latten {
2134a49b499SJoy Latten 	struct scatter_walk walk;
2144a49b499SJoy Latten 	u8 *data_src;
2154a49b499SJoy Latten 	int n;
2164a49b499SJoy Latten 
2174a49b499SJoy Latten 	scatterwalk_start(&walk, sg);
2184a49b499SJoy Latten 
2194a49b499SJoy Latten 	while (len) {
2204a49b499SJoy Latten 		n = scatterwalk_clamp(&walk, len);
2214a49b499SJoy Latten 		if (!n) {
2224a49b499SJoy Latten 			scatterwalk_start(&walk, sg_next(walk.sg));
2234a49b499SJoy Latten 			n = scatterwalk_clamp(&walk, len);
2244a49b499SJoy Latten 		}
225f0dfc0b0SCong Wang 		data_src = scatterwalk_map(&walk);
2264a49b499SJoy Latten 
2274a49b499SJoy Latten 		compute_mac(tfm, data_src, n, pctx);
2284a49b499SJoy Latten 		len -= n;
2294a49b499SJoy Latten 
230f0dfc0b0SCong Wang 		scatterwalk_unmap(data_src);
2314a49b499SJoy Latten 		scatterwalk_advance(&walk, n);
2324a49b499SJoy Latten 		scatterwalk_done(&walk, 0, len);
2334a49b499SJoy Latten 		if (len)
2344a49b499SJoy Latten 			crypto_yield(pctx->flags);
2354a49b499SJoy Latten 	}
2364a49b499SJoy Latten 
2374a49b499SJoy Latten 	/* any leftover needs padding and then encrypted */
2384a49b499SJoy Latten 	if (pctx->ilen) {
2394a49b499SJoy Latten 		int padlen;
2404a49b499SJoy Latten 		u8 *odata = pctx->odata;
2414a49b499SJoy Latten 		u8 *idata = pctx->idata;
2424a49b499SJoy Latten 
2434a49b499SJoy Latten 		padlen = 16 - pctx->ilen;
2444a49b499SJoy Latten 		memset(idata + pctx->ilen, 0, padlen);
2454a49b499SJoy Latten 		crypto_xor(odata, idata, 16);
2464a49b499SJoy Latten 		crypto_cipher_encrypt_one(tfm, odata, odata);
2474a49b499SJoy Latten 		pctx->ilen = 0;
2484a49b499SJoy Latten 	}
2494a49b499SJoy Latten }
2504a49b499SJoy Latten 
2514a49b499SJoy Latten static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
2524a49b499SJoy Latten 			   unsigned int cryptlen)
2534a49b499SJoy Latten {
2544a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2554a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
2564a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
2574a49b499SJoy Latten 	struct crypto_cipher *cipher = ctx->cipher;
2584a49b499SJoy Latten 	unsigned int assoclen = req->assoclen;
2594a49b499SJoy Latten 	u8 *odata = pctx->odata;
2604a49b499SJoy Latten 	u8 *idata = pctx->idata;
2614a49b499SJoy Latten 	int err;
2624a49b499SJoy Latten 
2634a49b499SJoy Latten 	/* format control data for input */
2644a49b499SJoy Latten 	err = format_input(odata, req, cryptlen);
2654a49b499SJoy Latten 	if (err)
2664a49b499SJoy Latten 		goto out;
2674a49b499SJoy Latten 
2684a49b499SJoy Latten 	/* encrypt first block to use as start in computing mac  */
2694a49b499SJoy Latten 	crypto_cipher_encrypt_one(cipher, odata, odata);
2704a49b499SJoy Latten 
2714a49b499SJoy Latten 	/* format associated data and compute into mac */
2724a49b499SJoy Latten 	if (assoclen) {
2734a49b499SJoy Latten 		pctx->ilen = format_adata(idata, assoclen);
27481c4c35eSHerbert Xu 		get_data_to_compute(cipher, pctx, req->src, req->assoclen);
275516280e7SJarod Wilson 	} else {
276516280e7SJarod Wilson 		pctx->ilen = 0;
2774a49b499SJoy Latten 	}
2784a49b499SJoy Latten 
2794a49b499SJoy Latten 	/* compute plaintext into mac */
2805638cabfSHoria Geanta 	if (cryptlen)
2814a49b499SJoy Latten 		get_data_to_compute(cipher, pctx, plain, cryptlen);
2824a49b499SJoy Latten 
2834a49b499SJoy Latten out:
2844a49b499SJoy Latten 	return err;
2854a49b499SJoy Latten }
2864a49b499SJoy Latten 
2874a49b499SJoy Latten static void crypto_ccm_encrypt_done(struct crypto_async_request *areq, int err)
2884a49b499SJoy Latten {
2894a49b499SJoy Latten 	struct aead_request *req = areq->data;
2904a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2914a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
2924a49b499SJoy Latten 	u8 *odata = pctx->odata;
2934a49b499SJoy Latten 
2944a49b499SJoy Latten 	if (!err)
29581c4c35eSHerbert Xu 		scatterwalk_map_and_copy(odata, req->dst,
29681c4c35eSHerbert Xu 					 req->assoclen + req->cryptlen,
2974a49b499SJoy Latten 					 crypto_aead_authsize(aead), 1);
2984a49b499SJoy Latten 	aead_request_complete(req, err);
2994a49b499SJoy Latten }
3004a49b499SJoy Latten 
3014a49b499SJoy Latten static inline int crypto_ccm_check_iv(const u8 *iv)
3024a49b499SJoy Latten {
3034a49b499SJoy Latten 	/* 2 <= L <= 8, so 1 <= L' <= 7. */
3044a49b499SJoy Latten 	if (1 > iv[0] || iv[0] > 7)
3054a49b499SJoy Latten 		return -EINVAL;
3064a49b499SJoy Latten 
3074a49b499SJoy Latten 	return 0;
3084a49b499SJoy Latten }
3094a49b499SJoy Latten 
31081c4c35eSHerbert Xu static int crypto_ccm_init_crypt(struct aead_request *req, u8 *tag)
31181c4c35eSHerbert Xu {
31281c4c35eSHerbert Xu 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
31381c4c35eSHerbert Xu 	struct scatterlist *sg;
31481c4c35eSHerbert Xu 	u8 *iv = req->iv;
31581c4c35eSHerbert Xu 	int err;
31681c4c35eSHerbert Xu 
31781c4c35eSHerbert Xu 	err = crypto_ccm_check_iv(iv);
31881c4c35eSHerbert Xu 	if (err)
31981c4c35eSHerbert Xu 		return err;
32081c4c35eSHerbert Xu 
32181c4c35eSHerbert Xu 	pctx->flags = aead_request_flags(req);
32281c4c35eSHerbert Xu 
32381c4c35eSHerbert Xu 	 /* Note: rfc 3610 and NIST 800-38C require counter of
32481c4c35eSHerbert Xu 	 * zero to encrypt auth tag.
32581c4c35eSHerbert Xu 	 */
32681c4c35eSHerbert Xu 	memset(iv + 15 - iv[0], 0, iv[0] + 1);
32781c4c35eSHerbert Xu 
32881c4c35eSHerbert Xu 	sg_init_table(pctx->src, 3);
32981c4c35eSHerbert Xu 	sg_set_buf(pctx->src, tag, 16);
33081c4c35eSHerbert Xu 	sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
33181c4c35eSHerbert Xu 	if (sg != pctx->src + 1)
33281c4c35eSHerbert Xu 		sg_chain(pctx->src, 2, sg);
33381c4c35eSHerbert Xu 
33481c4c35eSHerbert Xu 	if (req->src != req->dst) {
33581c4c35eSHerbert Xu 		sg_init_table(pctx->dst, 3);
33681c4c35eSHerbert Xu 		sg_set_buf(pctx->dst, tag, 16);
33781c4c35eSHerbert Xu 		sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
33881c4c35eSHerbert Xu 		if (sg != pctx->dst + 1)
33981c4c35eSHerbert Xu 			sg_chain(pctx->dst, 2, sg);
34081c4c35eSHerbert Xu 	}
34181c4c35eSHerbert Xu 
34281c4c35eSHerbert Xu 	return 0;
34381c4c35eSHerbert Xu }
34481c4c35eSHerbert Xu 
3454a49b499SJoy Latten static int crypto_ccm_encrypt(struct aead_request *req)
3464a49b499SJoy Latten {
3474a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
3484a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
3494a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
350464b93a3SHerbert Xu 	struct skcipher_request *skreq = &pctx->skreq;
3514a49b499SJoy Latten 	struct scatterlist *dst;
3524a49b499SJoy Latten 	unsigned int cryptlen = req->cryptlen;
3534a49b499SJoy Latten 	u8 *odata = pctx->odata;
3544a49b499SJoy Latten 	u8 *iv = req->iv;
3554a49b499SJoy Latten 	int err;
3564a49b499SJoy Latten 
35781c4c35eSHerbert Xu 	err = crypto_ccm_init_crypt(req, odata);
3584a49b499SJoy Latten 	if (err)
3594a49b499SJoy Latten 		return err;
3604a49b499SJoy Latten 
36181c4c35eSHerbert Xu 	err = crypto_ccm_auth(req, sg_next(pctx->src), cryptlen);
3624a49b499SJoy Latten 	if (err)
3634a49b499SJoy Latten 		return err;
3644a49b499SJoy Latten 
3654a49b499SJoy Latten 	dst = pctx->src;
36681c4c35eSHerbert Xu 	if (req->src != req->dst)
3674a49b499SJoy Latten 		dst = pctx->dst;
3684a49b499SJoy Latten 
369464b93a3SHerbert Xu 	skcipher_request_set_tfm(skreq, ctx->ctr);
370464b93a3SHerbert Xu 	skcipher_request_set_callback(skreq, pctx->flags,
3714a49b499SJoy Latten 				      crypto_ccm_encrypt_done, req);
372464b93a3SHerbert Xu 	skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv);
373464b93a3SHerbert Xu 	err = crypto_skcipher_encrypt(skreq);
3744a49b499SJoy Latten 	if (err)
3754a49b499SJoy Latten 		return err;
3764a49b499SJoy Latten 
3774a49b499SJoy Latten 	/* copy authtag to end of dst */
37881c4c35eSHerbert Xu 	scatterwalk_map_and_copy(odata, sg_next(dst), cryptlen,
3794a49b499SJoy Latten 				 crypto_aead_authsize(aead), 1);
3804a49b499SJoy Latten 	return err;
3814a49b499SJoy Latten }
3824a49b499SJoy Latten 
3834a49b499SJoy Latten static void crypto_ccm_decrypt_done(struct crypto_async_request *areq,
3844a49b499SJoy Latten 				   int err)
3854a49b499SJoy Latten {
3864a49b499SJoy Latten 	struct aead_request *req = areq->data;
3874a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
3884a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
3894a49b499SJoy Latten 	unsigned int authsize = crypto_aead_authsize(aead);
3904a49b499SJoy Latten 	unsigned int cryptlen = req->cryptlen - authsize;
39181c4c35eSHerbert Xu 	struct scatterlist *dst;
39281c4c35eSHerbert Xu 
39381c4c35eSHerbert Xu 	pctx->flags = 0;
39481c4c35eSHerbert Xu 
39581c4c35eSHerbert Xu 	dst = sg_next(req->src == req->dst ? pctx->src : pctx->dst);
3964a49b499SJoy Latten 
3974a49b499SJoy Latten 	if (!err) {
39881c4c35eSHerbert Xu 		err = crypto_ccm_auth(req, dst, cryptlen);
3996bf37e5aSJames Yonan 		if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize))
4004a49b499SJoy Latten 			err = -EBADMSG;
4014a49b499SJoy Latten 	}
4024a49b499SJoy Latten 	aead_request_complete(req, err);
4034a49b499SJoy Latten }
4044a49b499SJoy Latten 
4054a49b499SJoy Latten static int crypto_ccm_decrypt(struct aead_request *req)
4064a49b499SJoy Latten {
4074a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
4084a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
4094a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
410464b93a3SHerbert Xu 	struct skcipher_request *skreq = &pctx->skreq;
4114a49b499SJoy Latten 	struct scatterlist *dst;
4124a49b499SJoy Latten 	unsigned int authsize = crypto_aead_authsize(aead);
4134a49b499SJoy Latten 	unsigned int cryptlen = req->cryptlen;
4144a49b499SJoy Latten 	u8 *authtag = pctx->auth_tag;
4154a49b499SJoy Latten 	u8 *odata = pctx->odata;
4164a49b499SJoy Latten 	u8 *iv = req->iv;
4174a49b499SJoy Latten 	int err;
4184a49b499SJoy Latten 
4194a49b499SJoy Latten 	cryptlen -= authsize;
4204a49b499SJoy Latten 
42181c4c35eSHerbert Xu 	err = crypto_ccm_init_crypt(req, authtag);
4224a49b499SJoy Latten 	if (err)
4234a49b499SJoy Latten 		return err;
4244a49b499SJoy Latten 
42581c4c35eSHerbert Xu 	scatterwalk_map_and_copy(authtag, sg_next(pctx->src), cryptlen,
42681c4c35eSHerbert Xu 				 authsize, 0);
4274a49b499SJoy Latten 
4284a49b499SJoy Latten 	dst = pctx->src;
42981c4c35eSHerbert Xu 	if (req->src != req->dst)
4304a49b499SJoy Latten 		dst = pctx->dst;
4314a49b499SJoy Latten 
432464b93a3SHerbert Xu 	skcipher_request_set_tfm(skreq, ctx->ctr);
433464b93a3SHerbert Xu 	skcipher_request_set_callback(skreq, pctx->flags,
4344a49b499SJoy Latten 				      crypto_ccm_decrypt_done, req);
435464b93a3SHerbert Xu 	skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv);
436464b93a3SHerbert Xu 	err = crypto_skcipher_decrypt(skreq);
4374a49b499SJoy Latten 	if (err)
4384a49b499SJoy Latten 		return err;
4394a49b499SJoy Latten 
44081c4c35eSHerbert Xu 	err = crypto_ccm_auth(req, sg_next(dst), cryptlen);
4414a49b499SJoy Latten 	if (err)
4424a49b499SJoy Latten 		return err;
4434a49b499SJoy Latten 
4444a49b499SJoy Latten 	/* verify */
4456bf37e5aSJames Yonan 	if (crypto_memneq(authtag, odata, authsize))
4464a49b499SJoy Latten 		return -EBADMSG;
4474a49b499SJoy Latten 
4484a49b499SJoy Latten 	return err;
4494a49b499SJoy Latten }
4504a49b499SJoy Latten 
45181c4c35eSHerbert Xu static int crypto_ccm_init_tfm(struct crypto_aead *tfm)
4524a49b499SJoy Latten {
45381c4c35eSHerbert Xu 	struct aead_instance *inst = aead_alg_instance(tfm);
45481c4c35eSHerbert Xu 	struct ccm_instance_ctx *ictx = aead_instance_ctx(inst);
45581c4c35eSHerbert Xu 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
4564a49b499SJoy Latten 	struct crypto_cipher *cipher;
457464b93a3SHerbert Xu 	struct crypto_skcipher *ctr;
4584a49b499SJoy Latten 	unsigned long align;
4594a49b499SJoy Latten 	int err;
4604a49b499SJoy Latten 
4614a49b499SJoy Latten 	cipher = crypto_spawn_cipher(&ictx->cipher);
4624a49b499SJoy Latten 	if (IS_ERR(cipher))
4634a49b499SJoy Latten 		return PTR_ERR(cipher);
4644a49b499SJoy Latten 
465464b93a3SHerbert Xu 	ctr = crypto_spawn_skcipher2(&ictx->ctr);
4664a49b499SJoy Latten 	err = PTR_ERR(ctr);
4674a49b499SJoy Latten 	if (IS_ERR(ctr))
4684a49b499SJoy Latten 		goto err_free_cipher;
4694a49b499SJoy Latten 
4704a49b499SJoy Latten 	ctx->cipher = cipher;
4714a49b499SJoy Latten 	ctx->ctr = ctr;
4724a49b499SJoy Latten 
47381c4c35eSHerbert Xu 	align = crypto_aead_alignmask(tfm);
4744a49b499SJoy Latten 	align &= ~(crypto_tfm_ctx_alignment() - 1);
47581c4c35eSHerbert Xu 	crypto_aead_set_reqsize(
47681c4c35eSHerbert Xu 		tfm,
4772c221ad3SHerbert Xu 		align + sizeof(struct crypto_ccm_req_priv_ctx) +
478464b93a3SHerbert Xu 		crypto_skcipher_reqsize(ctr));
4794a49b499SJoy Latten 
4804a49b499SJoy Latten 	return 0;
4814a49b499SJoy Latten 
4824a49b499SJoy Latten err_free_cipher:
4834a49b499SJoy Latten 	crypto_free_cipher(cipher);
4844a49b499SJoy Latten 	return err;
4854a49b499SJoy Latten }
4864a49b499SJoy Latten 
48781c4c35eSHerbert Xu static void crypto_ccm_exit_tfm(struct crypto_aead *tfm)
4884a49b499SJoy Latten {
48981c4c35eSHerbert Xu 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
4904a49b499SJoy Latten 
4914a49b499SJoy Latten 	crypto_free_cipher(ctx->cipher);
492464b93a3SHerbert Xu 	crypto_free_skcipher(ctx->ctr);
4934a49b499SJoy Latten }
4944a49b499SJoy Latten 
49581c4c35eSHerbert Xu static void crypto_ccm_free(struct aead_instance *inst)
49681c4c35eSHerbert Xu {
49781c4c35eSHerbert Xu 	struct ccm_instance_ctx *ctx = aead_instance_ctx(inst);
49881c4c35eSHerbert Xu 
49981c4c35eSHerbert Xu 	crypto_drop_spawn(&ctx->cipher);
50081c4c35eSHerbert Xu 	crypto_drop_skcipher(&ctx->ctr);
50181c4c35eSHerbert Xu 	kfree(inst);
50281c4c35eSHerbert Xu }
50381c4c35eSHerbert Xu 
50481c4c35eSHerbert Xu static int crypto_ccm_create_common(struct crypto_template *tmpl,
50581c4c35eSHerbert Xu 				    struct rtattr **tb,
5064a49b499SJoy Latten 				    const char *full_name,
5074a49b499SJoy Latten 				    const char *ctr_name,
5084a49b499SJoy Latten 				    const char *cipher_name)
5094a49b499SJoy Latten {
5104a49b499SJoy Latten 	struct crypto_attr_type *algt;
51181c4c35eSHerbert Xu 	struct aead_instance *inst;
512464b93a3SHerbert Xu 	struct skcipher_alg *ctr;
5134a49b499SJoy Latten 	struct crypto_alg *cipher;
5144a49b499SJoy Latten 	struct ccm_instance_ctx *ictx;
5154a49b499SJoy Latten 	int err;
5164a49b499SJoy Latten 
5174a49b499SJoy Latten 	algt = crypto_get_attr_type(tb);
5184a49b499SJoy Latten 	if (IS_ERR(algt))
51981c4c35eSHerbert Xu 		return PTR_ERR(algt);
5204a49b499SJoy Latten 
5215e4b8c1fSHerbert Xu 	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
52281c4c35eSHerbert Xu 		return -EINVAL;
5234a49b499SJoy Latten 
5244a49b499SJoy Latten 	cipher = crypto_alg_mod_lookup(cipher_name,  CRYPTO_ALG_TYPE_CIPHER,
5254a49b499SJoy Latten 				       CRYPTO_ALG_TYPE_MASK);
5264a49b499SJoy Latten 	if (IS_ERR(cipher))
52781c4c35eSHerbert Xu 		return PTR_ERR(cipher);
5284a49b499SJoy Latten 
5294a49b499SJoy Latten 	err = -EINVAL;
5304a49b499SJoy Latten 	if (cipher->cra_blocksize != 16)
5314a49b499SJoy Latten 		goto out_put_cipher;
5324a49b499SJoy Latten 
5334a49b499SJoy Latten 	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
5344a49b499SJoy Latten 	err = -ENOMEM;
5354a49b499SJoy Latten 	if (!inst)
5364a49b499SJoy Latten 		goto out_put_cipher;
5374a49b499SJoy Latten 
53881c4c35eSHerbert Xu 	ictx = aead_instance_ctx(inst);
5394a49b499SJoy Latten 
54081c4c35eSHerbert Xu 	err = crypto_init_spawn(&ictx->cipher, cipher,
54181c4c35eSHerbert Xu 				aead_crypto_instance(inst),
5424a49b499SJoy Latten 				CRYPTO_ALG_TYPE_MASK);
5434a49b499SJoy Latten 	if (err)
5444a49b499SJoy Latten 		goto err_free_inst;
5454a49b499SJoy Latten 
54681c4c35eSHerbert Xu 	crypto_set_skcipher_spawn(&ictx->ctr, aead_crypto_instance(inst));
547464b93a3SHerbert Xu 	err = crypto_grab_skcipher2(&ictx->ctr, ctr_name, 0,
5484a49b499SJoy Latten 				    crypto_requires_sync(algt->type,
5494a49b499SJoy Latten 							 algt->mask));
5504a49b499SJoy Latten 	if (err)
5514a49b499SJoy Latten 		goto err_drop_cipher;
5524a49b499SJoy Latten 
553464b93a3SHerbert Xu 	ctr = crypto_spawn_skcipher_alg(&ictx->ctr);
5544a49b499SJoy Latten 
5554a49b499SJoy Latten 	/* Not a stream cipher? */
5564a49b499SJoy Latten 	err = -EINVAL;
557464b93a3SHerbert Xu 	if (ctr->base.cra_blocksize != 1)
5584a49b499SJoy Latten 		goto err_drop_ctr;
5594a49b499SJoy Latten 
5604a49b499SJoy Latten 	/* We want the real thing! */
561464b93a3SHerbert Xu 	if (crypto_skcipher_alg_ivsize(ctr) != 16)
5624a49b499SJoy Latten 		goto err_drop_ctr;
5634a49b499SJoy Latten 
5644a49b499SJoy Latten 	err = -ENAMETOOLONG;
56581c4c35eSHerbert Xu 	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
566464b93a3SHerbert Xu 		     "ccm_base(%s,%s)", ctr->base.cra_driver_name,
5674a49b499SJoy Latten 		     cipher->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
5684a49b499SJoy Latten 		goto err_drop_ctr;
5694a49b499SJoy Latten 
57081c4c35eSHerbert Xu 	memcpy(inst->alg.base.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
5714a49b499SJoy Latten 
572464b93a3SHerbert Xu 	inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC;
57381c4c35eSHerbert Xu 	inst->alg.base.cra_priority = (cipher->cra_priority +
574464b93a3SHerbert Xu 				       ctr->base.cra_priority) / 2;
57581c4c35eSHerbert Xu 	inst->alg.base.cra_blocksize = 1;
57681c4c35eSHerbert Xu 	inst->alg.base.cra_alignmask = cipher->cra_alignmask |
577464b93a3SHerbert Xu 				       ctr->base.cra_alignmask |
5784a49b499SJoy Latten 				       (__alignof__(u32) - 1);
57981c4c35eSHerbert Xu 	inst->alg.ivsize = 16;
580464b93a3SHerbert Xu 	inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
58181c4c35eSHerbert Xu 	inst->alg.maxauthsize = 16;
58281c4c35eSHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct crypto_ccm_ctx);
58381c4c35eSHerbert Xu 	inst->alg.init = crypto_ccm_init_tfm;
58481c4c35eSHerbert Xu 	inst->alg.exit = crypto_ccm_exit_tfm;
58581c4c35eSHerbert Xu 	inst->alg.setkey = crypto_ccm_setkey;
58681c4c35eSHerbert Xu 	inst->alg.setauthsize = crypto_ccm_setauthsize;
58781c4c35eSHerbert Xu 	inst->alg.encrypt = crypto_ccm_encrypt;
58881c4c35eSHerbert Xu 	inst->alg.decrypt = crypto_ccm_decrypt;
5894a49b499SJoy Latten 
59081c4c35eSHerbert Xu 	inst->free = crypto_ccm_free;
59181c4c35eSHerbert Xu 
59281c4c35eSHerbert Xu 	err = aead_register_instance(tmpl, inst);
59381c4c35eSHerbert Xu 	if (err)
59481c4c35eSHerbert Xu 		goto err_drop_ctr;
59581c4c35eSHerbert Xu 
59681c4c35eSHerbert Xu out_put_cipher:
5974a49b499SJoy Latten 	crypto_mod_put(cipher);
59881c4c35eSHerbert Xu 	return err;
5994a49b499SJoy Latten 
6004a49b499SJoy Latten err_drop_ctr:
6014a49b499SJoy Latten 	crypto_drop_skcipher(&ictx->ctr);
6024a49b499SJoy Latten err_drop_cipher:
6034a49b499SJoy Latten 	crypto_drop_spawn(&ictx->cipher);
6044a49b499SJoy Latten err_free_inst:
6054a49b499SJoy Latten 	kfree(inst);
60681c4c35eSHerbert Xu 	goto out_put_cipher;
6074a49b499SJoy Latten }
6084a49b499SJoy Latten 
60981c4c35eSHerbert Xu static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb)
6104a49b499SJoy Latten {
6114a49b499SJoy Latten 	const char *cipher_name;
6124a49b499SJoy Latten 	char ctr_name[CRYPTO_MAX_ALG_NAME];
6134a49b499SJoy Latten 	char full_name[CRYPTO_MAX_ALG_NAME];
6144a49b499SJoy Latten 
6154a49b499SJoy Latten 	cipher_name = crypto_attr_alg_name(tb[1]);
6164a49b499SJoy Latten 	if (IS_ERR(cipher_name))
61781c4c35eSHerbert Xu 		return PTR_ERR(cipher_name);
6184a49b499SJoy Latten 
6194a49b499SJoy Latten 	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
6204a49b499SJoy Latten 		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
62181c4c35eSHerbert Xu 		return -ENAMETOOLONG;
6224a49b499SJoy Latten 
6234a49b499SJoy Latten 	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >=
6244a49b499SJoy Latten 	    CRYPTO_MAX_ALG_NAME)
62581c4c35eSHerbert Xu 		return -ENAMETOOLONG;
6264a49b499SJoy Latten 
62781c4c35eSHerbert Xu 	return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
62881c4c35eSHerbert Xu 					cipher_name);
6294a49b499SJoy Latten }
6304a49b499SJoy Latten 
6314a49b499SJoy Latten static struct crypto_template crypto_ccm_tmpl = {
6324a49b499SJoy Latten 	.name = "ccm",
63381c4c35eSHerbert Xu 	.create = crypto_ccm_create,
6344a49b499SJoy Latten 	.module = THIS_MODULE,
6354a49b499SJoy Latten };
6364a49b499SJoy Latten 
63781c4c35eSHerbert Xu static int crypto_ccm_base_create(struct crypto_template *tmpl,
63881c4c35eSHerbert Xu 				  struct rtattr **tb)
6394a49b499SJoy Latten {
6404a49b499SJoy Latten 	const char *ctr_name;
6414a49b499SJoy Latten 	const char *cipher_name;
6424a49b499SJoy Latten 	char full_name[CRYPTO_MAX_ALG_NAME];
6434a49b499SJoy Latten 
6444a49b499SJoy Latten 	ctr_name = crypto_attr_alg_name(tb[1]);
6454a49b499SJoy Latten 	if (IS_ERR(ctr_name))
64681c4c35eSHerbert Xu 		return PTR_ERR(ctr_name);
6474a49b499SJoy Latten 
6484a49b499SJoy Latten 	cipher_name = crypto_attr_alg_name(tb[2]);
6494a49b499SJoy Latten 	if (IS_ERR(cipher_name))
65081c4c35eSHerbert Xu 		return PTR_ERR(cipher_name);
6514a49b499SJoy Latten 
6524a49b499SJoy Latten 	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)",
6534a49b499SJoy Latten 		     ctr_name, cipher_name) >= CRYPTO_MAX_ALG_NAME)
65481c4c35eSHerbert Xu 		return -ENAMETOOLONG;
6554a49b499SJoy Latten 
65681c4c35eSHerbert Xu 	return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
65781c4c35eSHerbert Xu 					cipher_name);
6584a49b499SJoy Latten }
6594a49b499SJoy Latten 
6604a49b499SJoy Latten static struct crypto_template crypto_ccm_base_tmpl = {
6614a49b499SJoy Latten 	.name = "ccm_base",
66281c4c35eSHerbert Xu 	.create = crypto_ccm_base_create,
6634a49b499SJoy Latten 	.module = THIS_MODULE,
6644a49b499SJoy Latten };
6654a49b499SJoy Latten 
6664a49b499SJoy Latten static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key,
6674a49b499SJoy Latten 				 unsigned int keylen)
6684a49b499SJoy Latten {
6694a49b499SJoy Latten 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
6704a49b499SJoy Latten 	struct crypto_aead *child = ctx->child;
6714a49b499SJoy Latten 	int err;
6724a49b499SJoy Latten 
6734a49b499SJoy Latten 	if (keylen < 3)
6744a49b499SJoy Latten 		return -EINVAL;
6754a49b499SJoy Latten 
6764a49b499SJoy Latten 	keylen -= 3;
6774a49b499SJoy Latten 	memcpy(ctx->nonce, key + keylen, 3);
6784a49b499SJoy Latten 
6794a49b499SJoy Latten 	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
6804a49b499SJoy Latten 	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
6814a49b499SJoy Latten 				     CRYPTO_TFM_REQ_MASK);
6824a49b499SJoy Latten 	err = crypto_aead_setkey(child, key, keylen);
6834a49b499SJoy Latten 	crypto_aead_set_flags(parent, crypto_aead_get_flags(child) &
6844a49b499SJoy Latten 				      CRYPTO_TFM_RES_MASK);
6854a49b499SJoy Latten 
6864a49b499SJoy Latten 	return err;
6874a49b499SJoy Latten }
6884a49b499SJoy Latten 
6894a49b499SJoy Latten static int crypto_rfc4309_setauthsize(struct crypto_aead *parent,
6904a49b499SJoy Latten 				      unsigned int authsize)
6914a49b499SJoy Latten {
6924a49b499SJoy Latten 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
6934a49b499SJoy Latten 
6944a49b499SJoy Latten 	switch (authsize) {
6954a49b499SJoy Latten 	case 8:
6964a49b499SJoy Latten 	case 12:
6974a49b499SJoy Latten 	case 16:
6984a49b499SJoy Latten 		break;
6994a49b499SJoy Latten 	default:
7004a49b499SJoy Latten 		return -EINVAL;
7014a49b499SJoy Latten 	}
7024a49b499SJoy Latten 
7034a49b499SJoy Latten 	return crypto_aead_setauthsize(ctx->child, authsize);
7044a49b499SJoy Latten }
7054a49b499SJoy Latten 
7064a49b499SJoy Latten static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req)
7074a49b499SJoy Latten {
70881c4c35eSHerbert Xu 	struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req);
70981c4c35eSHerbert Xu 	struct aead_request *subreq = &rctx->subreq;
7104a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
7114a49b499SJoy Latten 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(aead);
7124a49b499SJoy Latten 	struct crypto_aead *child = ctx->child;
71381c4c35eSHerbert Xu 	struct scatterlist *sg;
7144a49b499SJoy Latten 	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
7154a49b499SJoy Latten 			   crypto_aead_alignmask(child) + 1);
7164a49b499SJoy Latten 
7174a49b499SJoy Latten 	/* L' */
7184a49b499SJoy Latten 	iv[0] = 3;
7194a49b499SJoy Latten 
7204a49b499SJoy Latten 	memcpy(iv + 1, ctx->nonce, 3);
7214a49b499SJoy Latten 	memcpy(iv + 4, req->iv, 8);
7224a49b499SJoy Latten 
72381c4c35eSHerbert Xu 	scatterwalk_map_and_copy(iv + 16, req->src, 0, req->assoclen - 8, 0);
72481c4c35eSHerbert Xu 
72581c4c35eSHerbert Xu 	sg_init_table(rctx->src, 3);
72681c4c35eSHerbert Xu 	sg_set_buf(rctx->src, iv + 16, req->assoclen - 8);
72781c4c35eSHerbert Xu 	sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen);
72881c4c35eSHerbert Xu 	if (sg != rctx->src + 1)
72981c4c35eSHerbert Xu 		sg_chain(rctx->src, 2, sg);
73081c4c35eSHerbert Xu 
73181c4c35eSHerbert Xu 	if (req->src != req->dst) {
73281c4c35eSHerbert Xu 		sg_init_table(rctx->dst, 3);
73381c4c35eSHerbert Xu 		sg_set_buf(rctx->dst, iv + 16, req->assoclen - 8);
73481c4c35eSHerbert Xu 		sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen);
73581c4c35eSHerbert Xu 		if (sg != rctx->dst + 1)
73681c4c35eSHerbert Xu 			sg_chain(rctx->dst, 2, sg);
73781c4c35eSHerbert Xu 	}
73881c4c35eSHerbert Xu 
7394a49b499SJoy Latten 	aead_request_set_tfm(subreq, child);
7404a49b499SJoy Latten 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
7414a49b499SJoy Latten 				  req->base.data);
74281c4c35eSHerbert Xu 	aead_request_set_crypt(subreq, rctx->src,
74381c4c35eSHerbert Xu 			       req->src == req->dst ? rctx->src : rctx->dst,
74481c4c35eSHerbert Xu 			       req->cryptlen, iv);
74581c4c35eSHerbert Xu 	aead_request_set_ad(subreq, req->assoclen - 8);
7464a49b499SJoy Latten 
7474a49b499SJoy Latten 	return subreq;
7484a49b499SJoy Latten }
7494a49b499SJoy Latten 
7504a49b499SJoy Latten static int crypto_rfc4309_encrypt(struct aead_request *req)
7514a49b499SJoy Latten {
75281c4c35eSHerbert Xu 	if (req->assoclen != 16 && req->assoclen != 20)
75381c4c35eSHerbert Xu 		return -EINVAL;
75481c4c35eSHerbert Xu 
7554a49b499SJoy Latten 	req = crypto_rfc4309_crypt(req);
7564a49b499SJoy Latten 
7574a49b499SJoy Latten 	return crypto_aead_encrypt(req);
7584a49b499SJoy Latten }
7594a49b499SJoy Latten 
7604a49b499SJoy Latten static int crypto_rfc4309_decrypt(struct aead_request *req)
7614a49b499SJoy Latten {
76281c4c35eSHerbert Xu 	if (req->assoclen != 16 && req->assoclen != 20)
76381c4c35eSHerbert Xu 		return -EINVAL;
76481c4c35eSHerbert Xu 
7654a49b499SJoy Latten 	req = crypto_rfc4309_crypt(req);
7664a49b499SJoy Latten 
7674a49b499SJoy Latten 	return crypto_aead_decrypt(req);
7684a49b499SJoy Latten }
7694a49b499SJoy Latten 
77081c4c35eSHerbert Xu static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm)
7714a49b499SJoy Latten {
77281c4c35eSHerbert Xu 	struct aead_instance *inst = aead_alg_instance(tfm);
77381c4c35eSHerbert Xu 	struct crypto_aead_spawn *spawn = aead_instance_ctx(inst);
77481c4c35eSHerbert Xu 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
7754a49b499SJoy Latten 	struct crypto_aead *aead;
7764a49b499SJoy Latten 	unsigned long align;
7774a49b499SJoy Latten 
7784a49b499SJoy Latten 	aead = crypto_spawn_aead(spawn);
7794a49b499SJoy Latten 	if (IS_ERR(aead))
7804a49b499SJoy Latten 		return PTR_ERR(aead);
7814a49b499SJoy Latten 
7824a49b499SJoy Latten 	ctx->child = aead;
7834a49b499SJoy Latten 
7844a49b499SJoy Latten 	align = crypto_aead_alignmask(aead);
7854a49b499SJoy Latten 	align &= ~(crypto_tfm_ctx_alignment() - 1);
78681c4c35eSHerbert Xu 	crypto_aead_set_reqsize(
78781c4c35eSHerbert Xu 		tfm,
78881c4c35eSHerbert Xu 		sizeof(struct crypto_rfc4309_req_ctx) +
7892c221ad3SHerbert Xu 		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
79081c4c35eSHerbert Xu 		align + 32);
7914a49b499SJoy Latten 
7924a49b499SJoy Latten 	return 0;
7934a49b499SJoy Latten }
7944a49b499SJoy Latten 
79581c4c35eSHerbert Xu static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm)
7964a49b499SJoy Latten {
79781c4c35eSHerbert Xu 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
7984a49b499SJoy Latten 
7994a49b499SJoy Latten 	crypto_free_aead(ctx->child);
8004a49b499SJoy Latten }
8014a49b499SJoy Latten 
80281c4c35eSHerbert Xu static void crypto_rfc4309_free(struct aead_instance *inst)
80381c4c35eSHerbert Xu {
80481c4c35eSHerbert Xu 	crypto_drop_aead(aead_instance_ctx(inst));
80581c4c35eSHerbert Xu 	kfree(inst);
80681c4c35eSHerbert Xu }
80781c4c35eSHerbert Xu 
80881c4c35eSHerbert Xu static int crypto_rfc4309_create(struct crypto_template *tmpl,
80981c4c35eSHerbert Xu 				 struct rtattr **tb)
8104a49b499SJoy Latten {
8114a49b499SJoy Latten 	struct crypto_attr_type *algt;
81281c4c35eSHerbert Xu 	struct aead_instance *inst;
8134a49b499SJoy Latten 	struct crypto_aead_spawn *spawn;
81481c4c35eSHerbert Xu 	struct aead_alg *alg;
8154a49b499SJoy Latten 	const char *ccm_name;
8164a49b499SJoy Latten 	int err;
8174a49b499SJoy Latten 
8184a49b499SJoy Latten 	algt = crypto_get_attr_type(tb);
8194a49b499SJoy Latten 	if (IS_ERR(algt))
82081c4c35eSHerbert Xu 		return PTR_ERR(algt);
8214a49b499SJoy Latten 
8225e4b8c1fSHerbert Xu 	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
82381c4c35eSHerbert Xu 		return -EINVAL;
8244a49b499SJoy Latten 
8254a49b499SJoy Latten 	ccm_name = crypto_attr_alg_name(tb[1]);
8264a49b499SJoy Latten 	if (IS_ERR(ccm_name))
82781c4c35eSHerbert Xu 		return PTR_ERR(ccm_name);
8284a49b499SJoy Latten 
8294a49b499SJoy Latten 	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
8304a49b499SJoy Latten 	if (!inst)
83181c4c35eSHerbert Xu 		return -ENOMEM;
8324a49b499SJoy Latten 
83381c4c35eSHerbert Xu 	spawn = aead_instance_ctx(inst);
83481c4c35eSHerbert Xu 	crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
8354a49b499SJoy Latten 	err = crypto_grab_aead(spawn, ccm_name, 0,
8364a49b499SJoy Latten 			       crypto_requires_sync(algt->type, algt->mask));
8374a49b499SJoy Latten 	if (err)
8384a49b499SJoy Latten 		goto out_free_inst;
8394a49b499SJoy Latten 
84081c4c35eSHerbert Xu 	alg = crypto_spawn_aead_alg(spawn);
8414a49b499SJoy Latten 
8424a49b499SJoy Latten 	err = -EINVAL;
8434a49b499SJoy Latten 
8444a49b499SJoy Latten 	/* We only support 16-byte blocks. */
84581c4c35eSHerbert Xu 	if (crypto_aead_alg_ivsize(alg) != 16)
8464a49b499SJoy Latten 		goto out_drop_alg;
8474a49b499SJoy Latten 
8484a49b499SJoy Latten 	/* Not a stream cipher? */
84981c4c35eSHerbert Xu 	if (alg->base.cra_blocksize != 1)
8504a49b499SJoy Latten 		goto out_drop_alg;
8514a49b499SJoy Latten 
8524a49b499SJoy Latten 	err = -ENAMETOOLONG;
85381c4c35eSHerbert Xu 	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
85481c4c35eSHerbert Xu 		     "rfc4309(%s)", alg->base.cra_name) >=
85581c4c35eSHerbert Xu 	    CRYPTO_MAX_ALG_NAME ||
85681c4c35eSHerbert Xu 	    snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
85781c4c35eSHerbert Xu 		     "rfc4309(%s)", alg->base.cra_driver_name) >=
8584a49b499SJoy Latten 	    CRYPTO_MAX_ALG_NAME)
8594a49b499SJoy Latten 		goto out_drop_alg;
8604a49b499SJoy Latten 
86181c4c35eSHerbert Xu 	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
86281c4c35eSHerbert Xu 	inst->alg.base.cra_priority = alg->base.cra_priority;
86381c4c35eSHerbert Xu 	inst->alg.base.cra_blocksize = 1;
86481c4c35eSHerbert Xu 	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
8654a49b499SJoy Latten 
86681c4c35eSHerbert Xu 	inst->alg.ivsize = 8;
867464b93a3SHerbert Xu 	inst->alg.chunksize = crypto_aead_alg_chunksize(alg);
86881c4c35eSHerbert Xu 	inst->alg.maxauthsize = 16;
8694a49b499SJoy Latten 
87081c4c35eSHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);
8714a49b499SJoy Latten 
87281c4c35eSHerbert Xu 	inst->alg.init = crypto_rfc4309_init_tfm;
87381c4c35eSHerbert Xu 	inst->alg.exit = crypto_rfc4309_exit_tfm;
8744a49b499SJoy Latten 
87581c4c35eSHerbert Xu 	inst->alg.setkey = crypto_rfc4309_setkey;
87681c4c35eSHerbert Xu 	inst->alg.setauthsize = crypto_rfc4309_setauthsize;
87781c4c35eSHerbert Xu 	inst->alg.encrypt = crypto_rfc4309_encrypt;
87881c4c35eSHerbert Xu 	inst->alg.decrypt = crypto_rfc4309_decrypt;
8794a49b499SJoy Latten 
88081c4c35eSHerbert Xu 	inst->free = crypto_rfc4309_free;
88181c4c35eSHerbert Xu 
88281c4c35eSHerbert Xu 	err = aead_register_instance(tmpl, inst);
88381c4c35eSHerbert Xu 	if (err)
88481c4c35eSHerbert Xu 		goto out_drop_alg;
8854a49b499SJoy Latten 
8864a49b499SJoy Latten out:
88781c4c35eSHerbert Xu 	return err;
8884a49b499SJoy Latten 
8894a49b499SJoy Latten out_drop_alg:
8904a49b499SJoy Latten 	crypto_drop_aead(spawn);
8914a49b499SJoy Latten out_free_inst:
8924a49b499SJoy Latten 	kfree(inst);
8934a49b499SJoy Latten 	goto out;
8944a49b499SJoy Latten }
8954a49b499SJoy Latten 
8964a49b499SJoy Latten static struct crypto_template crypto_rfc4309_tmpl = {
8974a49b499SJoy Latten 	.name = "rfc4309",
89881c4c35eSHerbert Xu 	.create = crypto_rfc4309_create,
8994a49b499SJoy Latten 	.module = THIS_MODULE,
9004a49b499SJoy Latten };
9014a49b499SJoy Latten 
9024a49b499SJoy Latten static int __init crypto_ccm_module_init(void)
9034a49b499SJoy Latten {
9044a49b499SJoy Latten 	int err;
9054a49b499SJoy Latten 
9064a49b499SJoy Latten 	err = crypto_register_template(&crypto_ccm_base_tmpl);
9074a49b499SJoy Latten 	if (err)
9084a49b499SJoy Latten 		goto out;
9094a49b499SJoy Latten 
9104a49b499SJoy Latten 	err = crypto_register_template(&crypto_ccm_tmpl);
9114a49b499SJoy Latten 	if (err)
9124a49b499SJoy Latten 		goto out_undo_base;
9134a49b499SJoy Latten 
9144a49b499SJoy Latten 	err = crypto_register_template(&crypto_rfc4309_tmpl);
9154a49b499SJoy Latten 	if (err)
9164a49b499SJoy Latten 		goto out_undo_ccm;
9174a49b499SJoy Latten 
9184a49b499SJoy Latten out:
9194a49b499SJoy Latten 	return err;
9204a49b499SJoy Latten 
9214a49b499SJoy Latten out_undo_ccm:
9224a49b499SJoy Latten 	crypto_unregister_template(&crypto_ccm_tmpl);
9234a49b499SJoy Latten out_undo_base:
9244a49b499SJoy Latten 	crypto_unregister_template(&crypto_ccm_base_tmpl);
9254a49b499SJoy Latten 	goto out;
9264a49b499SJoy Latten }
9274a49b499SJoy Latten 
9284a49b499SJoy Latten static void __exit crypto_ccm_module_exit(void)
9294a49b499SJoy Latten {
9304a49b499SJoy Latten 	crypto_unregister_template(&crypto_rfc4309_tmpl);
9314a49b499SJoy Latten 	crypto_unregister_template(&crypto_ccm_tmpl);
9324a49b499SJoy Latten 	crypto_unregister_template(&crypto_ccm_base_tmpl);
9334a49b499SJoy Latten }
9344a49b499SJoy Latten 
9354a49b499SJoy Latten module_init(crypto_ccm_module_init);
9364a49b499SJoy Latten module_exit(crypto_ccm_module_exit);
9374a49b499SJoy Latten 
9384a49b499SJoy Latten MODULE_LICENSE("GPL");
9394a49b499SJoy Latten MODULE_DESCRIPTION("Counter with CBC MAC");
9405d26a105SKees Cook MODULE_ALIAS_CRYPTO("ccm_base");
9415d26a105SKees Cook MODULE_ALIAS_CRYPTO("rfc4309");
9424943ba16SKees Cook MODULE_ALIAS_CRYPTO("ccm");
943