xref: /openbmc/linux/crypto/ccm.c (revision 5ba8e2a0)
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>
14f15f05b0SArd Biesheuvel #include <crypto/internal/hash.h>
154a49b499SJoy Latten #include <crypto/internal/skcipher.h>
164a49b499SJoy Latten #include <crypto/scatterwalk.h>
174a49b499SJoy Latten #include <linux/err.h>
184a49b499SJoy Latten #include <linux/init.h>
194a49b499SJoy Latten #include <linux/kernel.h>
204a49b499SJoy Latten #include <linux/module.h>
214a49b499SJoy Latten #include <linux/slab.h>
224a49b499SJoy Latten 
234a49b499SJoy Latten #include "internal.h"
244a49b499SJoy Latten 
254a49b499SJoy Latten struct ccm_instance_ctx {
264a49b499SJoy Latten 	struct crypto_skcipher_spawn ctr;
27f15f05b0SArd Biesheuvel 	struct crypto_ahash_spawn mac;
284a49b499SJoy Latten };
294a49b499SJoy Latten 
304a49b499SJoy Latten struct crypto_ccm_ctx {
31f15f05b0SArd Biesheuvel 	struct crypto_ahash *mac;
32464b93a3SHerbert Xu 	struct crypto_skcipher *ctr;
334a49b499SJoy Latten };
344a49b499SJoy Latten 
354a49b499SJoy Latten struct crypto_rfc4309_ctx {
364a49b499SJoy Latten 	struct crypto_aead *child;
374a49b499SJoy Latten 	u8 nonce[3];
384a49b499SJoy Latten };
394a49b499SJoy Latten 
4081c4c35eSHerbert Xu struct crypto_rfc4309_req_ctx {
4181c4c35eSHerbert Xu 	struct scatterlist src[3];
4281c4c35eSHerbert Xu 	struct scatterlist dst[3];
4381c4c35eSHerbert Xu 	struct aead_request subreq;
4481c4c35eSHerbert Xu };
4581c4c35eSHerbert Xu 
464a49b499SJoy Latten struct crypto_ccm_req_priv_ctx {
474a49b499SJoy Latten 	u8 odata[16];
484a49b499SJoy Latten 	u8 auth_tag[16];
494a49b499SJoy Latten 	u32 flags;
5081c4c35eSHerbert Xu 	struct scatterlist src[3];
5181c4c35eSHerbert Xu 	struct scatterlist dst[3];
52464b93a3SHerbert Xu 	struct skcipher_request skreq;
534a49b499SJoy Latten };
544a49b499SJoy Latten 
55f15f05b0SArd Biesheuvel struct cbcmac_tfm_ctx {
56f15f05b0SArd Biesheuvel 	struct crypto_cipher *child;
57f15f05b0SArd Biesheuvel };
58f15f05b0SArd Biesheuvel 
59f15f05b0SArd Biesheuvel struct cbcmac_desc_ctx {
60f15f05b0SArd Biesheuvel 	unsigned int len;
61f15f05b0SArd Biesheuvel };
62f15f05b0SArd Biesheuvel 
634a49b499SJoy Latten static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx(
644a49b499SJoy Latten 	struct aead_request *req)
654a49b499SJoy Latten {
664a49b499SJoy Latten 	unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
674a49b499SJoy Latten 
684a49b499SJoy Latten 	return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
694a49b499SJoy Latten }
704a49b499SJoy Latten 
714a49b499SJoy Latten static int set_msg_len(u8 *block, unsigned int msglen, int csize)
724a49b499SJoy Latten {
734a49b499SJoy Latten 	__be32 data;
744a49b499SJoy Latten 
754a49b499SJoy Latten 	memset(block, 0, csize);
764a49b499SJoy Latten 	block += csize;
774a49b499SJoy Latten 
784a49b499SJoy Latten 	if (csize >= 4)
794a49b499SJoy Latten 		csize = 4;
804a49b499SJoy Latten 	else if (msglen > (1 << (8 * csize)))
814a49b499SJoy Latten 		return -EOVERFLOW;
824a49b499SJoy Latten 
834a49b499SJoy Latten 	data = cpu_to_be32(msglen);
844a49b499SJoy Latten 	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
854a49b499SJoy Latten 
864a49b499SJoy Latten 	return 0;
874a49b499SJoy Latten }
884a49b499SJoy Latten 
894a49b499SJoy Latten static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key,
904a49b499SJoy Latten 			     unsigned int keylen)
914a49b499SJoy Latten {
924a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
93464b93a3SHerbert Xu 	struct crypto_skcipher *ctr = ctx->ctr;
94f15f05b0SArd Biesheuvel 	struct crypto_ahash *mac = ctx->mac;
954a49b499SJoy Latten 	int err = 0;
964a49b499SJoy Latten 
97464b93a3SHerbert Xu 	crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
98464b93a3SHerbert Xu 	crypto_skcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
994a49b499SJoy Latten 				       CRYPTO_TFM_REQ_MASK);
100464b93a3SHerbert Xu 	err = crypto_skcipher_setkey(ctr, key, keylen);
101464b93a3SHerbert Xu 	crypto_aead_set_flags(aead, crypto_skcipher_get_flags(ctr) &
1024a49b499SJoy Latten 			      CRYPTO_TFM_RES_MASK);
1034a49b499SJoy Latten 	if (err)
1044a49b499SJoy Latten 		goto out;
1054a49b499SJoy Latten 
106f15f05b0SArd Biesheuvel 	crypto_ahash_clear_flags(mac, CRYPTO_TFM_REQ_MASK);
107f15f05b0SArd Biesheuvel 	crypto_ahash_set_flags(mac, crypto_aead_get_flags(aead) &
1084a49b499SJoy Latten 				    CRYPTO_TFM_REQ_MASK);
109f15f05b0SArd Biesheuvel 	err = crypto_ahash_setkey(mac, key, keylen);
110f15f05b0SArd Biesheuvel 	crypto_aead_set_flags(aead, crypto_ahash_get_flags(mac) &
1114a49b499SJoy Latten 			      CRYPTO_TFM_RES_MASK);
1124a49b499SJoy Latten 
1134a49b499SJoy Latten out:
1144a49b499SJoy Latten 	return err;
1154a49b499SJoy Latten }
1164a49b499SJoy Latten 
1174a49b499SJoy Latten static int crypto_ccm_setauthsize(struct crypto_aead *tfm,
1184a49b499SJoy Latten 				  unsigned int authsize)
1194a49b499SJoy Latten {
1204a49b499SJoy Latten 	switch (authsize) {
1214a49b499SJoy Latten 	case 4:
1224a49b499SJoy Latten 	case 6:
1234a49b499SJoy Latten 	case 8:
1244a49b499SJoy Latten 	case 10:
1254a49b499SJoy Latten 	case 12:
1264a49b499SJoy Latten 	case 14:
1274a49b499SJoy Latten 	case 16:
1284a49b499SJoy Latten 		break;
1294a49b499SJoy Latten 	default:
1304a49b499SJoy Latten 		return -EINVAL;
1314a49b499SJoy Latten 	}
1324a49b499SJoy Latten 
1334a49b499SJoy Latten 	return 0;
1344a49b499SJoy Latten }
1354a49b499SJoy Latten 
1364a49b499SJoy Latten static int format_input(u8 *info, struct aead_request *req,
1374a49b499SJoy Latten 			unsigned int cryptlen)
1384a49b499SJoy Latten {
1394a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
1404a49b499SJoy Latten 	unsigned int lp = req->iv[0];
1414a49b499SJoy Latten 	unsigned int l = lp + 1;
1424a49b499SJoy Latten 	unsigned int m;
1434a49b499SJoy Latten 
1444a49b499SJoy Latten 	m = crypto_aead_authsize(aead);
1454a49b499SJoy Latten 
1464a49b499SJoy Latten 	memcpy(info, req->iv, 16);
1474a49b499SJoy Latten 
1484a49b499SJoy Latten 	/* format control info per RFC 3610 and
1494a49b499SJoy Latten 	 * NIST Special Publication 800-38C
1504a49b499SJoy Latten 	 */
1514a49b499SJoy Latten 	*info |= (8 * ((m - 2) / 2));
1524a49b499SJoy Latten 	if (req->assoclen)
1534a49b499SJoy Latten 		*info |= 64;
1544a49b499SJoy Latten 
1554a49b499SJoy Latten 	return set_msg_len(info + 16 - l, cryptlen, l);
1564a49b499SJoy Latten }
1574a49b499SJoy Latten 
1584a49b499SJoy Latten static int format_adata(u8 *adata, unsigned int a)
1594a49b499SJoy Latten {
1604a49b499SJoy Latten 	int len = 0;
1614a49b499SJoy Latten 
1624a49b499SJoy Latten 	/* add control info for associated data
1634a49b499SJoy Latten 	 * RFC 3610 and NIST Special Publication 800-38C
1644a49b499SJoy Latten 	 */
1654a49b499SJoy Latten 	if (a < 65280) {
1664a49b499SJoy Latten 		*(__be16 *)adata = cpu_to_be16(a);
1674a49b499SJoy Latten 		len = 2;
1684a49b499SJoy Latten 	} else  {
1694a49b499SJoy Latten 		*(__be16 *)adata = cpu_to_be16(0xfffe);
1704a49b499SJoy Latten 		*(__be32 *)&adata[2] = cpu_to_be32(a);
1714a49b499SJoy Latten 		len = 6;
1724a49b499SJoy Latten 	}
1734a49b499SJoy Latten 
1744a49b499SJoy Latten 	return len;
1754a49b499SJoy Latten }
1764a49b499SJoy Latten 
1774a49b499SJoy Latten static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
1784a49b499SJoy Latten 			   unsigned int cryptlen)
1794a49b499SJoy Latten {
180f15f05b0SArd Biesheuvel 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
1814a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
1824a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
183f15f05b0SArd Biesheuvel 	AHASH_REQUEST_ON_STACK(ahreq, ctx->mac);
1844a49b499SJoy Latten 	unsigned int assoclen = req->assoclen;
185f15f05b0SArd Biesheuvel 	struct scatterlist sg[3];
186f15f05b0SArd Biesheuvel 	u8 odata[16];
187f15f05b0SArd Biesheuvel 	u8 idata[16];
188f15f05b0SArd Biesheuvel 	int ilen, err;
1894a49b499SJoy Latten 
1904a49b499SJoy Latten 	/* format control data for input */
1914a49b499SJoy Latten 	err = format_input(odata, req, cryptlen);
1924a49b499SJoy Latten 	if (err)
1934a49b499SJoy Latten 		goto out;
1944a49b499SJoy Latten 
195f15f05b0SArd Biesheuvel 	sg_init_table(sg, 3);
196f15f05b0SArd Biesheuvel 	sg_set_buf(&sg[0], odata, 16);
1974a49b499SJoy Latten 
1984a49b499SJoy Latten 	/* format associated data and compute into mac */
1994a49b499SJoy Latten 	if (assoclen) {
200f15f05b0SArd Biesheuvel 		ilen = format_adata(idata, assoclen);
201f15f05b0SArd Biesheuvel 		sg_set_buf(&sg[1], idata, ilen);
202f15f05b0SArd Biesheuvel 		sg_chain(sg, 3, req->src);
203516280e7SJarod Wilson 	} else {
204f15f05b0SArd Biesheuvel 		ilen = 0;
205f15f05b0SArd Biesheuvel 		sg_chain(sg, 2, req->src);
2064a49b499SJoy Latten 	}
2074a49b499SJoy Latten 
208f15f05b0SArd Biesheuvel 	ahash_request_set_tfm(ahreq, ctx->mac);
209f15f05b0SArd Biesheuvel 	ahash_request_set_callback(ahreq, pctx->flags, NULL, NULL);
210f15f05b0SArd Biesheuvel 	ahash_request_set_crypt(ahreq, sg, NULL, assoclen + ilen + 16);
211f15f05b0SArd Biesheuvel 	err = crypto_ahash_init(ahreq);
212f15f05b0SArd Biesheuvel 	if (err)
213f15f05b0SArd Biesheuvel 		goto out;
214f15f05b0SArd Biesheuvel 	err = crypto_ahash_update(ahreq);
215f15f05b0SArd Biesheuvel 	if (err)
216f15f05b0SArd Biesheuvel 		goto out;
2174a49b499SJoy Latten 
218f15f05b0SArd Biesheuvel 	/* we need to pad the MAC input to a round multiple of the block size */
219f15f05b0SArd Biesheuvel 	ilen = 16 - (assoclen + ilen) % 16;
220f15f05b0SArd Biesheuvel 	if (ilen < 16) {
221f15f05b0SArd Biesheuvel 		memset(idata, 0, ilen);
222f15f05b0SArd Biesheuvel 		sg_init_table(sg, 2);
223f15f05b0SArd Biesheuvel 		sg_set_buf(&sg[0], idata, ilen);
224f15f05b0SArd Biesheuvel 		if (plain)
225f15f05b0SArd Biesheuvel 			sg_chain(sg, 2, plain);
226f15f05b0SArd Biesheuvel 		plain = sg;
227f15f05b0SArd Biesheuvel 		cryptlen += ilen;
228f15f05b0SArd Biesheuvel 	}
229f15f05b0SArd Biesheuvel 
230f15f05b0SArd Biesheuvel 	ahash_request_set_crypt(ahreq, plain, pctx->odata, cryptlen);
231f15f05b0SArd Biesheuvel 	err = crypto_ahash_finup(ahreq);
2324a49b499SJoy Latten out:
2334a49b499SJoy Latten 	return err;
2344a49b499SJoy Latten }
2354a49b499SJoy Latten 
2364a49b499SJoy Latten static void crypto_ccm_encrypt_done(struct crypto_async_request *areq, int err)
2374a49b499SJoy Latten {
2384a49b499SJoy Latten 	struct aead_request *req = areq->data;
2394a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2404a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
2414a49b499SJoy Latten 	u8 *odata = pctx->odata;
2424a49b499SJoy Latten 
2434a49b499SJoy Latten 	if (!err)
24481c4c35eSHerbert Xu 		scatterwalk_map_and_copy(odata, req->dst,
24581c4c35eSHerbert Xu 					 req->assoclen + req->cryptlen,
2464a49b499SJoy Latten 					 crypto_aead_authsize(aead), 1);
2474a49b499SJoy Latten 	aead_request_complete(req, err);
2484a49b499SJoy Latten }
2494a49b499SJoy Latten 
2504a49b499SJoy Latten static inline int crypto_ccm_check_iv(const u8 *iv)
2514a49b499SJoy Latten {
2524a49b499SJoy Latten 	/* 2 <= L <= 8, so 1 <= L' <= 7. */
2534a49b499SJoy Latten 	if (1 > iv[0] || iv[0] > 7)
2544a49b499SJoy Latten 		return -EINVAL;
2554a49b499SJoy Latten 
2564a49b499SJoy Latten 	return 0;
2574a49b499SJoy Latten }
2584a49b499SJoy Latten 
25981c4c35eSHerbert Xu static int crypto_ccm_init_crypt(struct aead_request *req, u8 *tag)
26081c4c35eSHerbert Xu {
26181c4c35eSHerbert Xu 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
26281c4c35eSHerbert Xu 	struct scatterlist *sg;
26381c4c35eSHerbert Xu 	u8 *iv = req->iv;
26481c4c35eSHerbert Xu 	int err;
26581c4c35eSHerbert Xu 
26681c4c35eSHerbert Xu 	err = crypto_ccm_check_iv(iv);
26781c4c35eSHerbert Xu 	if (err)
26881c4c35eSHerbert Xu 		return err;
26981c4c35eSHerbert Xu 
27081c4c35eSHerbert Xu 	pctx->flags = aead_request_flags(req);
27181c4c35eSHerbert Xu 
27281c4c35eSHerbert Xu 	 /* Note: rfc 3610 and NIST 800-38C require counter of
27381c4c35eSHerbert Xu 	 * zero to encrypt auth tag.
27481c4c35eSHerbert Xu 	 */
27581c4c35eSHerbert Xu 	memset(iv + 15 - iv[0], 0, iv[0] + 1);
27681c4c35eSHerbert Xu 
27781c4c35eSHerbert Xu 	sg_init_table(pctx->src, 3);
27881c4c35eSHerbert Xu 	sg_set_buf(pctx->src, tag, 16);
27981c4c35eSHerbert Xu 	sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
28081c4c35eSHerbert Xu 	if (sg != pctx->src + 1)
28181c4c35eSHerbert Xu 		sg_chain(pctx->src, 2, sg);
28281c4c35eSHerbert Xu 
28381c4c35eSHerbert Xu 	if (req->src != req->dst) {
28481c4c35eSHerbert Xu 		sg_init_table(pctx->dst, 3);
28581c4c35eSHerbert Xu 		sg_set_buf(pctx->dst, tag, 16);
28681c4c35eSHerbert Xu 		sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
28781c4c35eSHerbert Xu 		if (sg != pctx->dst + 1)
28881c4c35eSHerbert Xu 			sg_chain(pctx->dst, 2, sg);
28981c4c35eSHerbert Xu 	}
29081c4c35eSHerbert Xu 
29181c4c35eSHerbert Xu 	return 0;
29281c4c35eSHerbert Xu }
29381c4c35eSHerbert Xu 
2944a49b499SJoy Latten static int crypto_ccm_encrypt(struct aead_request *req)
2954a49b499SJoy Latten {
2964a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2974a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
2984a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
299464b93a3SHerbert Xu 	struct skcipher_request *skreq = &pctx->skreq;
3004a49b499SJoy Latten 	struct scatterlist *dst;
3014a49b499SJoy Latten 	unsigned int cryptlen = req->cryptlen;
3024a49b499SJoy Latten 	u8 *odata = pctx->odata;
3034a49b499SJoy Latten 	u8 *iv = req->iv;
3044a49b499SJoy Latten 	int err;
3054a49b499SJoy Latten 
30681c4c35eSHerbert Xu 	err = crypto_ccm_init_crypt(req, odata);
3074a49b499SJoy Latten 	if (err)
3084a49b499SJoy Latten 		return err;
3094a49b499SJoy Latten 
31081c4c35eSHerbert Xu 	err = crypto_ccm_auth(req, sg_next(pctx->src), cryptlen);
3114a49b499SJoy Latten 	if (err)
3124a49b499SJoy Latten 		return err;
3134a49b499SJoy Latten 
3144a49b499SJoy Latten 	dst = pctx->src;
31581c4c35eSHerbert Xu 	if (req->src != req->dst)
3164a49b499SJoy Latten 		dst = pctx->dst;
3174a49b499SJoy Latten 
318464b93a3SHerbert Xu 	skcipher_request_set_tfm(skreq, ctx->ctr);
319464b93a3SHerbert Xu 	skcipher_request_set_callback(skreq, pctx->flags,
3204a49b499SJoy Latten 				      crypto_ccm_encrypt_done, req);
321464b93a3SHerbert Xu 	skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv);
322464b93a3SHerbert Xu 	err = crypto_skcipher_encrypt(skreq);
3234a49b499SJoy Latten 	if (err)
3244a49b499SJoy Latten 		return err;
3254a49b499SJoy Latten 
3264a49b499SJoy Latten 	/* copy authtag to end of dst */
32781c4c35eSHerbert Xu 	scatterwalk_map_and_copy(odata, sg_next(dst), cryptlen,
3284a49b499SJoy Latten 				 crypto_aead_authsize(aead), 1);
3294a49b499SJoy Latten 	return err;
3304a49b499SJoy Latten }
3314a49b499SJoy Latten 
3324a49b499SJoy Latten static void crypto_ccm_decrypt_done(struct crypto_async_request *areq,
3334a49b499SJoy Latten 				   int err)
3344a49b499SJoy Latten {
3354a49b499SJoy Latten 	struct aead_request *req = areq->data;
3364a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
3374a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
3384a49b499SJoy Latten 	unsigned int authsize = crypto_aead_authsize(aead);
3394a49b499SJoy Latten 	unsigned int cryptlen = req->cryptlen - authsize;
34081c4c35eSHerbert Xu 	struct scatterlist *dst;
34181c4c35eSHerbert Xu 
34281c4c35eSHerbert Xu 	pctx->flags = 0;
34381c4c35eSHerbert Xu 
34481c4c35eSHerbert Xu 	dst = sg_next(req->src == req->dst ? pctx->src : pctx->dst);
3454a49b499SJoy Latten 
3464a49b499SJoy Latten 	if (!err) {
34781c4c35eSHerbert Xu 		err = crypto_ccm_auth(req, dst, cryptlen);
3486bf37e5aSJames Yonan 		if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize))
3494a49b499SJoy Latten 			err = -EBADMSG;
3504a49b499SJoy Latten 	}
3514a49b499SJoy Latten 	aead_request_complete(req, err);
3524a49b499SJoy Latten }
3534a49b499SJoy Latten 
3544a49b499SJoy Latten static int crypto_ccm_decrypt(struct aead_request *req)
3554a49b499SJoy Latten {
3564a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
3574a49b499SJoy Latten 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
3584a49b499SJoy Latten 	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
359464b93a3SHerbert Xu 	struct skcipher_request *skreq = &pctx->skreq;
3604a49b499SJoy Latten 	struct scatterlist *dst;
3614a49b499SJoy Latten 	unsigned int authsize = crypto_aead_authsize(aead);
3624a49b499SJoy Latten 	unsigned int cryptlen = req->cryptlen;
3634a49b499SJoy Latten 	u8 *authtag = pctx->auth_tag;
3644a49b499SJoy Latten 	u8 *odata = pctx->odata;
3654a49b499SJoy Latten 	u8 *iv = req->iv;
3664a49b499SJoy Latten 	int err;
3674a49b499SJoy Latten 
3684a49b499SJoy Latten 	cryptlen -= authsize;
3694a49b499SJoy Latten 
37081c4c35eSHerbert Xu 	err = crypto_ccm_init_crypt(req, authtag);
3714a49b499SJoy Latten 	if (err)
3724a49b499SJoy Latten 		return err;
3734a49b499SJoy Latten 
37481c4c35eSHerbert Xu 	scatterwalk_map_and_copy(authtag, sg_next(pctx->src), cryptlen,
37581c4c35eSHerbert Xu 				 authsize, 0);
3764a49b499SJoy Latten 
3774a49b499SJoy Latten 	dst = pctx->src;
37881c4c35eSHerbert Xu 	if (req->src != req->dst)
3794a49b499SJoy Latten 		dst = pctx->dst;
3804a49b499SJoy Latten 
381464b93a3SHerbert Xu 	skcipher_request_set_tfm(skreq, ctx->ctr);
382464b93a3SHerbert Xu 	skcipher_request_set_callback(skreq, pctx->flags,
3834a49b499SJoy Latten 				      crypto_ccm_decrypt_done, req);
384464b93a3SHerbert Xu 	skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv);
385464b93a3SHerbert Xu 	err = crypto_skcipher_decrypt(skreq);
3864a49b499SJoy Latten 	if (err)
3874a49b499SJoy Latten 		return err;
3884a49b499SJoy Latten 
38981c4c35eSHerbert Xu 	err = crypto_ccm_auth(req, sg_next(dst), cryptlen);
3904a49b499SJoy Latten 	if (err)
3914a49b499SJoy Latten 		return err;
3924a49b499SJoy Latten 
3934a49b499SJoy Latten 	/* verify */
3946bf37e5aSJames Yonan 	if (crypto_memneq(authtag, odata, authsize))
3954a49b499SJoy Latten 		return -EBADMSG;
3964a49b499SJoy Latten 
3974a49b499SJoy Latten 	return err;
3984a49b499SJoy Latten }
3994a49b499SJoy Latten 
40081c4c35eSHerbert Xu static int crypto_ccm_init_tfm(struct crypto_aead *tfm)
4014a49b499SJoy Latten {
40281c4c35eSHerbert Xu 	struct aead_instance *inst = aead_alg_instance(tfm);
40381c4c35eSHerbert Xu 	struct ccm_instance_ctx *ictx = aead_instance_ctx(inst);
40481c4c35eSHerbert Xu 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
405f15f05b0SArd Biesheuvel 	struct crypto_ahash *mac;
406464b93a3SHerbert Xu 	struct crypto_skcipher *ctr;
4074a49b499SJoy Latten 	unsigned long align;
4084a49b499SJoy Latten 	int err;
4094a49b499SJoy Latten 
410f15f05b0SArd Biesheuvel 	mac = crypto_spawn_ahash(&ictx->mac);
411f15f05b0SArd Biesheuvel 	if (IS_ERR(mac))
412f15f05b0SArd Biesheuvel 		return PTR_ERR(mac);
4134a49b499SJoy Latten 
41460425a8bSEric Biggers 	ctr = crypto_spawn_skcipher(&ictx->ctr);
4154a49b499SJoy Latten 	err = PTR_ERR(ctr);
4164a49b499SJoy Latten 	if (IS_ERR(ctr))
417f15f05b0SArd Biesheuvel 		goto err_free_mac;
4184a49b499SJoy Latten 
419f15f05b0SArd Biesheuvel 	ctx->mac = mac;
4204a49b499SJoy Latten 	ctx->ctr = ctr;
4214a49b499SJoy Latten 
42281c4c35eSHerbert Xu 	align = crypto_aead_alignmask(tfm);
4234a49b499SJoy Latten 	align &= ~(crypto_tfm_ctx_alignment() - 1);
42481c4c35eSHerbert Xu 	crypto_aead_set_reqsize(
42581c4c35eSHerbert Xu 		tfm,
4262c221ad3SHerbert Xu 		align + sizeof(struct crypto_ccm_req_priv_ctx) +
427464b93a3SHerbert Xu 		crypto_skcipher_reqsize(ctr));
4284a49b499SJoy Latten 
4294a49b499SJoy Latten 	return 0;
4304a49b499SJoy Latten 
431f15f05b0SArd Biesheuvel err_free_mac:
432f15f05b0SArd Biesheuvel 	crypto_free_ahash(mac);
4334a49b499SJoy Latten 	return err;
4344a49b499SJoy Latten }
4354a49b499SJoy Latten 
43681c4c35eSHerbert Xu static void crypto_ccm_exit_tfm(struct crypto_aead *tfm)
4374a49b499SJoy Latten {
43881c4c35eSHerbert Xu 	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
4394a49b499SJoy Latten 
440f15f05b0SArd Biesheuvel 	crypto_free_ahash(ctx->mac);
441464b93a3SHerbert Xu 	crypto_free_skcipher(ctx->ctr);
4424a49b499SJoy Latten }
4434a49b499SJoy Latten 
44481c4c35eSHerbert Xu static void crypto_ccm_free(struct aead_instance *inst)
44581c4c35eSHerbert Xu {
44681c4c35eSHerbert Xu 	struct ccm_instance_ctx *ctx = aead_instance_ctx(inst);
44781c4c35eSHerbert Xu 
448f15f05b0SArd Biesheuvel 	crypto_drop_ahash(&ctx->mac);
44981c4c35eSHerbert Xu 	crypto_drop_skcipher(&ctx->ctr);
45081c4c35eSHerbert Xu 	kfree(inst);
45181c4c35eSHerbert Xu }
45281c4c35eSHerbert Xu 
45381c4c35eSHerbert Xu static int crypto_ccm_create_common(struct crypto_template *tmpl,
45481c4c35eSHerbert Xu 				    struct rtattr **tb,
4554a49b499SJoy Latten 				    const char *full_name,
4564a49b499SJoy Latten 				    const char *ctr_name,
457f15f05b0SArd Biesheuvel 				    const char *mac_name)
4584a49b499SJoy Latten {
4594a49b499SJoy Latten 	struct crypto_attr_type *algt;
46081c4c35eSHerbert Xu 	struct aead_instance *inst;
461464b93a3SHerbert Xu 	struct skcipher_alg *ctr;
462f15f05b0SArd Biesheuvel 	struct crypto_alg *mac_alg;
463f15f05b0SArd Biesheuvel 	struct hash_alg_common *mac;
4644a49b499SJoy Latten 	struct ccm_instance_ctx *ictx;
4654a49b499SJoy Latten 	int err;
4664a49b499SJoy Latten 
4674a49b499SJoy Latten 	algt = crypto_get_attr_type(tb);
4684a49b499SJoy Latten 	if (IS_ERR(algt))
46981c4c35eSHerbert Xu 		return PTR_ERR(algt);
4704a49b499SJoy Latten 
4715e4b8c1fSHerbert Xu 	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
47281c4c35eSHerbert Xu 		return -EINVAL;
4734a49b499SJoy Latten 
474f15f05b0SArd Biesheuvel 	mac_alg = crypto_find_alg(mac_name, &crypto_ahash_type,
475f15f05b0SArd Biesheuvel 				  CRYPTO_ALG_TYPE_HASH,
476f15f05b0SArd Biesheuvel 				  CRYPTO_ALG_TYPE_AHASH_MASK |
477f15f05b0SArd Biesheuvel 				  CRYPTO_ALG_ASYNC);
478f15f05b0SArd Biesheuvel 	if (IS_ERR(mac_alg))
479f15f05b0SArd Biesheuvel 		return PTR_ERR(mac_alg);
4804a49b499SJoy Latten 
481f15f05b0SArd Biesheuvel 	mac = __crypto_hash_alg_common(mac_alg);
4824a49b499SJoy Latten 	err = -EINVAL;
483f15f05b0SArd Biesheuvel 	if (mac->digestsize != 16)
484f15f05b0SArd Biesheuvel 		goto out_put_mac;
4854a49b499SJoy Latten 
4864a49b499SJoy Latten 	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
4874a49b499SJoy Latten 	err = -ENOMEM;
4884a49b499SJoy Latten 	if (!inst)
489f15f05b0SArd Biesheuvel 		goto out_put_mac;
4904a49b499SJoy Latten 
49181c4c35eSHerbert Xu 	ictx = aead_instance_ctx(inst);
492f15f05b0SArd Biesheuvel 	err = crypto_init_ahash_spawn(&ictx->mac, mac,
493f15f05b0SArd Biesheuvel 				      aead_crypto_instance(inst));
4944a49b499SJoy Latten 	if (err)
4954a49b499SJoy Latten 		goto err_free_inst;
4964a49b499SJoy Latten 
49781c4c35eSHerbert Xu 	crypto_set_skcipher_spawn(&ictx->ctr, aead_crypto_instance(inst));
498a35528ecSEric Biggers 	err = crypto_grab_skcipher(&ictx->ctr, ctr_name, 0,
4994a49b499SJoy Latten 				   crypto_requires_sync(algt->type,
5004a49b499SJoy Latten 							algt->mask));
5014a49b499SJoy Latten 	if (err)
502f15f05b0SArd Biesheuvel 		goto err_drop_mac;
5034a49b499SJoy Latten 
504464b93a3SHerbert Xu 	ctr = crypto_spawn_skcipher_alg(&ictx->ctr);
5054a49b499SJoy Latten 
5064a49b499SJoy Latten 	/* Not a stream cipher? */
5074a49b499SJoy Latten 	err = -EINVAL;
508464b93a3SHerbert Xu 	if (ctr->base.cra_blocksize != 1)
5094a49b499SJoy Latten 		goto err_drop_ctr;
5104a49b499SJoy Latten 
5114a49b499SJoy Latten 	/* We want the real thing! */
512464b93a3SHerbert Xu 	if (crypto_skcipher_alg_ivsize(ctr) != 16)
5134a49b499SJoy Latten 		goto err_drop_ctr;
5144a49b499SJoy Latten 
5154a49b499SJoy Latten 	err = -ENAMETOOLONG;
51681c4c35eSHerbert Xu 	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
517464b93a3SHerbert Xu 		     "ccm_base(%s,%s)", ctr->base.cra_driver_name,
518f15f05b0SArd Biesheuvel 		     mac->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
5194a49b499SJoy Latten 		goto err_drop_ctr;
5204a49b499SJoy Latten 
52181c4c35eSHerbert Xu 	memcpy(inst->alg.base.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
5224a49b499SJoy Latten 
523464b93a3SHerbert Xu 	inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC;
524f15f05b0SArd Biesheuvel 	inst->alg.base.cra_priority = (mac->base.cra_priority +
525464b93a3SHerbert Xu 				       ctr->base.cra_priority) / 2;
52681c4c35eSHerbert Xu 	inst->alg.base.cra_blocksize = 1;
527f15f05b0SArd Biesheuvel 	inst->alg.base.cra_alignmask = mac->base.cra_alignmask |
5285ba8e2a0SArd Biesheuvel 				       ctr->base.cra_alignmask;
52981c4c35eSHerbert Xu 	inst->alg.ivsize = 16;
530464b93a3SHerbert Xu 	inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
53181c4c35eSHerbert Xu 	inst->alg.maxauthsize = 16;
53281c4c35eSHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct crypto_ccm_ctx);
53381c4c35eSHerbert Xu 	inst->alg.init = crypto_ccm_init_tfm;
53481c4c35eSHerbert Xu 	inst->alg.exit = crypto_ccm_exit_tfm;
53581c4c35eSHerbert Xu 	inst->alg.setkey = crypto_ccm_setkey;
53681c4c35eSHerbert Xu 	inst->alg.setauthsize = crypto_ccm_setauthsize;
53781c4c35eSHerbert Xu 	inst->alg.encrypt = crypto_ccm_encrypt;
53881c4c35eSHerbert Xu 	inst->alg.decrypt = crypto_ccm_decrypt;
5394a49b499SJoy Latten 
54081c4c35eSHerbert Xu 	inst->free = crypto_ccm_free;
54181c4c35eSHerbert Xu 
54281c4c35eSHerbert Xu 	err = aead_register_instance(tmpl, inst);
54381c4c35eSHerbert Xu 	if (err)
54481c4c35eSHerbert Xu 		goto err_drop_ctr;
54581c4c35eSHerbert Xu 
546f15f05b0SArd Biesheuvel out_put_mac:
547f15f05b0SArd Biesheuvel 	crypto_mod_put(mac_alg);
54881c4c35eSHerbert Xu 	return err;
5494a49b499SJoy Latten 
5504a49b499SJoy Latten err_drop_ctr:
5514a49b499SJoy Latten 	crypto_drop_skcipher(&ictx->ctr);
552f15f05b0SArd Biesheuvel err_drop_mac:
553f15f05b0SArd Biesheuvel 	crypto_drop_ahash(&ictx->mac);
5544a49b499SJoy Latten err_free_inst:
5554a49b499SJoy Latten 	kfree(inst);
556f15f05b0SArd Biesheuvel 	goto out_put_mac;
5574a49b499SJoy Latten }
5584a49b499SJoy Latten 
55981c4c35eSHerbert Xu static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb)
5604a49b499SJoy Latten {
5614a49b499SJoy Latten 	const char *cipher_name;
5624a49b499SJoy Latten 	char ctr_name[CRYPTO_MAX_ALG_NAME];
563f15f05b0SArd Biesheuvel 	char mac_name[CRYPTO_MAX_ALG_NAME];
5644a49b499SJoy Latten 	char full_name[CRYPTO_MAX_ALG_NAME];
5654a49b499SJoy Latten 
5664a49b499SJoy Latten 	cipher_name = crypto_attr_alg_name(tb[1]);
5674a49b499SJoy Latten 	if (IS_ERR(cipher_name))
56881c4c35eSHerbert Xu 		return PTR_ERR(cipher_name);
5694a49b499SJoy Latten 
5704a49b499SJoy Latten 	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
5714a49b499SJoy Latten 		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
57281c4c35eSHerbert Xu 		return -ENAMETOOLONG;
5734a49b499SJoy Latten 
574f15f05b0SArd Biesheuvel 	if (snprintf(mac_name, CRYPTO_MAX_ALG_NAME, "cbcmac(%s)",
575f15f05b0SArd Biesheuvel 		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
576f15f05b0SArd Biesheuvel 		return -ENAMETOOLONG;
577f15f05b0SArd Biesheuvel 
5784a49b499SJoy Latten 	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >=
5794a49b499SJoy Latten 	    CRYPTO_MAX_ALG_NAME)
58081c4c35eSHerbert Xu 		return -ENAMETOOLONG;
5814a49b499SJoy Latten 
58281c4c35eSHerbert Xu 	return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
583f15f05b0SArd Biesheuvel 					mac_name);
5844a49b499SJoy Latten }
5854a49b499SJoy Latten 
5864a49b499SJoy Latten static struct crypto_template crypto_ccm_tmpl = {
5874a49b499SJoy Latten 	.name = "ccm",
58881c4c35eSHerbert Xu 	.create = crypto_ccm_create,
5894a49b499SJoy Latten 	.module = THIS_MODULE,
5904a49b499SJoy Latten };
5914a49b499SJoy Latten 
59281c4c35eSHerbert Xu static int crypto_ccm_base_create(struct crypto_template *tmpl,
59381c4c35eSHerbert Xu 				  struct rtattr **tb)
5944a49b499SJoy Latten {
5954a49b499SJoy Latten 	const char *ctr_name;
5964a49b499SJoy Latten 	const char *cipher_name;
5974a49b499SJoy Latten 	char full_name[CRYPTO_MAX_ALG_NAME];
5984a49b499SJoy Latten 
5994a49b499SJoy Latten 	ctr_name = crypto_attr_alg_name(tb[1]);
6004a49b499SJoy Latten 	if (IS_ERR(ctr_name))
60181c4c35eSHerbert Xu 		return PTR_ERR(ctr_name);
6024a49b499SJoy Latten 
6034a49b499SJoy Latten 	cipher_name = crypto_attr_alg_name(tb[2]);
6044a49b499SJoy Latten 	if (IS_ERR(cipher_name))
60581c4c35eSHerbert Xu 		return PTR_ERR(cipher_name);
6064a49b499SJoy Latten 
6074a49b499SJoy Latten 	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)",
6084a49b499SJoy Latten 		     ctr_name, cipher_name) >= CRYPTO_MAX_ALG_NAME)
60981c4c35eSHerbert Xu 		return -ENAMETOOLONG;
6104a49b499SJoy Latten 
61181c4c35eSHerbert Xu 	return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
61281c4c35eSHerbert Xu 					cipher_name);
6134a49b499SJoy Latten }
6144a49b499SJoy Latten 
6154a49b499SJoy Latten static struct crypto_template crypto_ccm_base_tmpl = {
6164a49b499SJoy Latten 	.name = "ccm_base",
61781c4c35eSHerbert Xu 	.create = crypto_ccm_base_create,
6184a49b499SJoy Latten 	.module = THIS_MODULE,
6194a49b499SJoy Latten };
6204a49b499SJoy Latten 
6214a49b499SJoy Latten static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key,
6224a49b499SJoy Latten 				 unsigned int keylen)
6234a49b499SJoy Latten {
6244a49b499SJoy Latten 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
6254a49b499SJoy Latten 	struct crypto_aead *child = ctx->child;
6264a49b499SJoy Latten 	int err;
6274a49b499SJoy Latten 
6284a49b499SJoy Latten 	if (keylen < 3)
6294a49b499SJoy Latten 		return -EINVAL;
6304a49b499SJoy Latten 
6314a49b499SJoy Latten 	keylen -= 3;
6324a49b499SJoy Latten 	memcpy(ctx->nonce, key + keylen, 3);
6334a49b499SJoy Latten 
6344a49b499SJoy Latten 	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
6354a49b499SJoy Latten 	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
6364a49b499SJoy Latten 				     CRYPTO_TFM_REQ_MASK);
6374a49b499SJoy Latten 	err = crypto_aead_setkey(child, key, keylen);
6384a49b499SJoy Latten 	crypto_aead_set_flags(parent, crypto_aead_get_flags(child) &
6394a49b499SJoy Latten 				      CRYPTO_TFM_RES_MASK);
6404a49b499SJoy Latten 
6414a49b499SJoy Latten 	return err;
6424a49b499SJoy Latten }
6434a49b499SJoy Latten 
6444a49b499SJoy Latten static int crypto_rfc4309_setauthsize(struct crypto_aead *parent,
6454a49b499SJoy Latten 				      unsigned int authsize)
6464a49b499SJoy Latten {
6474a49b499SJoy Latten 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
6484a49b499SJoy Latten 
6494a49b499SJoy Latten 	switch (authsize) {
6504a49b499SJoy Latten 	case 8:
6514a49b499SJoy Latten 	case 12:
6524a49b499SJoy Latten 	case 16:
6534a49b499SJoy Latten 		break;
6544a49b499SJoy Latten 	default:
6554a49b499SJoy Latten 		return -EINVAL;
6564a49b499SJoy Latten 	}
6574a49b499SJoy Latten 
6584a49b499SJoy Latten 	return crypto_aead_setauthsize(ctx->child, authsize);
6594a49b499SJoy Latten }
6604a49b499SJoy Latten 
6614a49b499SJoy Latten static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req)
6624a49b499SJoy Latten {
66381c4c35eSHerbert Xu 	struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req);
66481c4c35eSHerbert Xu 	struct aead_request *subreq = &rctx->subreq;
6654a49b499SJoy Latten 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
6664a49b499SJoy Latten 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(aead);
6674a49b499SJoy Latten 	struct crypto_aead *child = ctx->child;
66881c4c35eSHerbert Xu 	struct scatterlist *sg;
6694a49b499SJoy Latten 	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
6704a49b499SJoy Latten 			   crypto_aead_alignmask(child) + 1);
6714a49b499SJoy Latten 
6724a49b499SJoy Latten 	/* L' */
6734a49b499SJoy Latten 	iv[0] = 3;
6744a49b499SJoy Latten 
6754a49b499SJoy Latten 	memcpy(iv + 1, ctx->nonce, 3);
6764a49b499SJoy Latten 	memcpy(iv + 4, req->iv, 8);
6774a49b499SJoy Latten 
67881c4c35eSHerbert Xu 	scatterwalk_map_and_copy(iv + 16, req->src, 0, req->assoclen - 8, 0);
67981c4c35eSHerbert Xu 
68081c4c35eSHerbert Xu 	sg_init_table(rctx->src, 3);
68181c4c35eSHerbert Xu 	sg_set_buf(rctx->src, iv + 16, req->assoclen - 8);
68281c4c35eSHerbert Xu 	sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen);
68381c4c35eSHerbert Xu 	if (sg != rctx->src + 1)
68481c4c35eSHerbert Xu 		sg_chain(rctx->src, 2, sg);
68581c4c35eSHerbert Xu 
68681c4c35eSHerbert Xu 	if (req->src != req->dst) {
68781c4c35eSHerbert Xu 		sg_init_table(rctx->dst, 3);
68881c4c35eSHerbert Xu 		sg_set_buf(rctx->dst, iv + 16, req->assoclen - 8);
68981c4c35eSHerbert Xu 		sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen);
69081c4c35eSHerbert Xu 		if (sg != rctx->dst + 1)
69181c4c35eSHerbert Xu 			sg_chain(rctx->dst, 2, sg);
69281c4c35eSHerbert Xu 	}
69381c4c35eSHerbert Xu 
6944a49b499SJoy Latten 	aead_request_set_tfm(subreq, child);
6954a49b499SJoy Latten 	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
6964a49b499SJoy Latten 				  req->base.data);
69781c4c35eSHerbert Xu 	aead_request_set_crypt(subreq, rctx->src,
69881c4c35eSHerbert Xu 			       req->src == req->dst ? rctx->src : rctx->dst,
69981c4c35eSHerbert Xu 			       req->cryptlen, iv);
70081c4c35eSHerbert Xu 	aead_request_set_ad(subreq, req->assoclen - 8);
7014a49b499SJoy Latten 
7024a49b499SJoy Latten 	return subreq;
7034a49b499SJoy Latten }
7044a49b499SJoy Latten 
7054a49b499SJoy Latten static int crypto_rfc4309_encrypt(struct aead_request *req)
7064a49b499SJoy Latten {
70781c4c35eSHerbert Xu 	if (req->assoclen != 16 && req->assoclen != 20)
70881c4c35eSHerbert Xu 		return -EINVAL;
70981c4c35eSHerbert Xu 
7104a49b499SJoy Latten 	req = crypto_rfc4309_crypt(req);
7114a49b499SJoy Latten 
7124a49b499SJoy Latten 	return crypto_aead_encrypt(req);
7134a49b499SJoy Latten }
7144a49b499SJoy Latten 
7154a49b499SJoy Latten static int crypto_rfc4309_decrypt(struct aead_request *req)
7164a49b499SJoy Latten {
71781c4c35eSHerbert Xu 	if (req->assoclen != 16 && req->assoclen != 20)
71881c4c35eSHerbert Xu 		return -EINVAL;
71981c4c35eSHerbert Xu 
7204a49b499SJoy Latten 	req = crypto_rfc4309_crypt(req);
7214a49b499SJoy Latten 
7224a49b499SJoy Latten 	return crypto_aead_decrypt(req);
7234a49b499SJoy Latten }
7244a49b499SJoy Latten 
72581c4c35eSHerbert Xu static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm)
7264a49b499SJoy Latten {
72781c4c35eSHerbert Xu 	struct aead_instance *inst = aead_alg_instance(tfm);
72881c4c35eSHerbert Xu 	struct crypto_aead_spawn *spawn = aead_instance_ctx(inst);
72981c4c35eSHerbert Xu 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
7304a49b499SJoy Latten 	struct crypto_aead *aead;
7314a49b499SJoy Latten 	unsigned long align;
7324a49b499SJoy Latten 
7334a49b499SJoy Latten 	aead = crypto_spawn_aead(spawn);
7344a49b499SJoy Latten 	if (IS_ERR(aead))
7354a49b499SJoy Latten 		return PTR_ERR(aead);
7364a49b499SJoy Latten 
7374a49b499SJoy Latten 	ctx->child = aead;
7384a49b499SJoy Latten 
7394a49b499SJoy Latten 	align = crypto_aead_alignmask(aead);
7404a49b499SJoy Latten 	align &= ~(crypto_tfm_ctx_alignment() - 1);
74181c4c35eSHerbert Xu 	crypto_aead_set_reqsize(
74281c4c35eSHerbert Xu 		tfm,
74381c4c35eSHerbert Xu 		sizeof(struct crypto_rfc4309_req_ctx) +
7442c221ad3SHerbert Xu 		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
74581c4c35eSHerbert Xu 		align + 32);
7464a49b499SJoy Latten 
7474a49b499SJoy Latten 	return 0;
7484a49b499SJoy Latten }
7494a49b499SJoy Latten 
75081c4c35eSHerbert Xu static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm)
7514a49b499SJoy Latten {
75281c4c35eSHerbert Xu 	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
7534a49b499SJoy Latten 
7544a49b499SJoy Latten 	crypto_free_aead(ctx->child);
7554a49b499SJoy Latten }
7564a49b499SJoy Latten 
75781c4c35eSHerbert Xu static void crypto_rfc4309_free(struct aead_instance *inst)
75881c4c35eSHerbert Xu {
75981c4c35eSHerbert Xu 	crypto_drop_aead(aead_instance_ctx(inst));
76081c4c35eSHerbert Xu 	kfree(inst);
76181c4c35eSHerbert Xu }
76281c4c35eSHerbert Xu 
76381c4c35eSHerbert Xu static int crypto_rfc4309_create(struct crypto_template *tmpl,
76481c4c35eSHerbert Xu 				 struct rtattr **tb)
7654a49b499SJoy Latten {
7664a49b499SJoy Latten 	struct crypto_attr_type *algt;
76781c4c35eSHerbert Xu 	struct aead_instance *inst;
7684a49b499SJoy Latten 	struct crypto_aead_spawn *spawn;
76981c4c35eSHerbert Xu 	struct aead_alg *alg;
7704a49b499SJoy Latten 	const char *ccm_name;
7714a49b499SJoy Latten 	int err;
7724a49b499SJoy Latten 
7734a49b499SJoy Latten 	algt = crypto_get_attr_type(tb);
7744a49b499SJoy Latten 	if (IS_ERR(algt))
77581c4c35eSHerbert Xu 		return PTR_ERR(algt);
7764a49b499SJoy Latten 
7775e4b8c1fSHerbert Xu 	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
77881c4c35eSHerbert Xu 		return -EINVAL;
7794a49b499SJoy Latten 
7804a49b499SJoy Latten 	ccm_name = crypto_attr_alg_name(tb[1]);
7814a49b499SJoy Latten 	if (IS_ERR(ccm_name))
78281c4c35eSHerbert Xu 		return PTR_ERR(ccm_name);
7834a49b499SJoy Latten 
7844a49b499SJoy Latten 	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
7854a49b499SJoy Latten 	if (!inst)
78681c4c35eSHerbert Xu 		return -ENOMEM;
7874a49b499SJoy Latten 
78881c4c35eSHerbert Xu 	spawn = aead_instance_ctx(inst);
78981c4c35eSHerbert Xu 	crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
7904a49b499SJoy Latten 	err = crypto_grab_aead(spawn, ccm_name, 0,
7914a49b499SJoy Latten 			       crypto_requires_sync(algt->type, algt->mask));
7924a49b499SJoy Latten 	if (err)
7934a49b499SJoy Latten 		goto out_free_inst;
7944a49b499SJoy Latten 
79581c4c35eSHerbert Xu 	alg = crypto_spawn_aead_alg(spawn);
7964a49b499SJoy Latten 
7974a49b499SJoy Latten 	err = -EINVAL;
7984a49b499SJoy Latten 
7994a49b499SJoy Latten 	/* We only support 16-byte blocks. */
80081c4c35eSHerbert Xu 	if (crypto_aead_alg_ivsize(alg) != 16)
8014a49b499SJoy Latten 		goto out_drop_alg;
8024a49b499SJoy Latten 
8034a49b499SJoy Latten 	/* Not a stream cipher? */
80481c4c35eSHerbert Xu 	if (alg->base.cra_blocksize != 1)
8054a49b499SJoy Latten 		goto out_drop_alg;
8064a49b499SJoy Latten 
8074a49b499SJoy Latten 	err = -ENAMETOOLONG;
80881c4c35eSHerbert Xu 	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
80981c4c35eSHerbert Xu 		     "rfc4309(%s)", alg->base.cra_name) >=
81081c4c35eSHerbert Xu 	    CRYPTO_MAX_ALG_NAME ||
81181c4c35eSHerbert Xu 	    snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
81281c4c35eSHerbert Xu 		     "rfc4309(%s)", alg->base.cra_driver_name) >=
8134a49b499SJoy Latten 	    CRYPTO_MAX_ALG_NAME)
8144a49b499SJoy Latten 		goto out_drop_alg;
8154a49b499SJoy Latten 
81681c4c35eSHerbert Xu 	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
81781c4c35eSHerbert Xu 	inst->alg.base.cra_priority = alg->base.cra_priority;
81881c4c35eSHerbert Xu 	inst->alg.base.cra_blocksize = 1;
81981c4c35eSHerbert Xu 	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
8204a49b499SJoy Latten 
82181c4c35eSHerbert Xu 	inst->alg.ivsize = 8;
822464b93a3SHerbert Xu 	inst->alg.chunksize = crypto_aead_alg_chunksize(alg);
82381c4c35eSHerbert Xu 	inst->alg.maxauthsize = 16;
8244a49b499SJoy Latten 
82581c4c35eSHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);
8264a49b499SJoy Latten 
82781c4c35eSHerbert Xu 	inst->alg.init = crypto_rfc4309_init_tfm;
82881c4c35eSHerbert Xu 	inst->alg.exit = crypto_rfc4309_exit_tfm;
8294a49b499SJoy Latten 
83081c4c35eSHerbert Xu 	inst->alg.setkey = crypto_rfc4309_setkey;
83181c4c35eSHerbert Xu 	inst->alg.setauthsize = crypto_rfc4309_setauthsize;
83281c4c35eSHerbert Xu 	inst->alg.encrypt = crypto_rfc4309_encrypt;
83381c4c35eSHerbert Xu 	inst->alg.decrypt = crypto_rfc4309_decrypt;
8344a49b499SJoy Latten 
83581c4c35eSHerbert Xu 	inst->free = crypto_rfc4309_free;
83681c4c35eSHerbert Xu 
83781c4c35eSHerbert Xu 	err = aead_register_instance(tmpl, inst);
83881c4c35eSHerbert Xu 	if (err)
83981c4c35eSHerbert Xu 		goto out_drop_alg;
8404a49b499SJoy Latten 
8414a49b499SJoy Latten out:
84281c4c35eSHerbert Xu 	return err;
8434a49b499SJoy Latten 
8444a49b499SJoy Latten out_drop_alg:
8454a49b499SJoy Latten 	crypto_drop_aead(spawn);
8464a49b499SJoy Latten out_free_inst:
8474a49b499SJoy Latten 	kfree(inst);
8484a49b499SJoy Latten 	goto out;
8494a49b499SJoy Latten }
8504a49b499SJoy Latten 
8514a49b499SJoy Latten static struct crypto_template crypto_rfc4309_tmpl = {
8524a49b499SJoy Latten 	.name = "rfc4309",
85381c4c35eSHerbert Xu 	.create = crypto_rfc4309_create,
8544a49b499SJoy Latten 	.module = THIS_MODULE,
8554a49b499SJoy Latten };
8564a49b499SJoy Latten 
857f15f05b0SArd Biesheuvel static int crypto_cbcmac_digest_setkey(struct crypto_shash *parent,
858f15f05b0SArd Biesheuvel 				     const u8 *inkey, unsigned int keylen)
859f15f05b0SArd Biesheuvel {
860f15f05b0SArd Biesheuvel 	struct cbcmac_tfm_ctx *ctx = crypto_shash_ctx(parent);
861f15f05b0SArd Biesheuvel 
862f15f05b0SArd Biesheuvel 	return crypto_cipher_setkey(ctx->child, inkey, keylen);
863f15f05b0SArd Biesheuvel }
864f15f05b0SArd Biesheuvel 
865f15f05b0SArd Biesheuvel static int crypto_cbcmac_digest_init(struct shash_desc *pdesc)
866f15f05b0SArd Biesheuvel {
867f15f05b0SArd Biesheuvel 	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
868f15f05b0SArd Biesheuvel 	int bs = crypto_shash_digestsize(pdesc->tfm);
8695338ad70SArd Biesheuvel 	u8 *dg = (u8 *)ctx + crypto_shash_descsize(pdesc->tfm) - bs;
870f15f05b0SArd Biesheuvel 
871f15f05b0SArd Biesheuvel 	ctx->len = 0;
8725338ad70SArd Biesheuvel 	memset(dg, 0, bs);
873f15f05b0SArd Biesheuvel 
874f15f05b0SArd Biesheuvel 	return 0;
875f15f05b0SArd Biesheuvel }
876f15f05b0SArd Biesheuvel 
877f15f05b0SArd Biesheuvel static int crypto_cbcmac_digest_update(struct shash_desc *pdesc, const u8 *p,
878f15f05b0SArd Biesheuvel 				       unsigned int len)
879f15f05b0SArd Biesheuvel {
880f15f05b0SArd Biesheuvel 	struct crypto_shash *parent = pdesc->tfm;
881f15f05b0SArd Biesheuvel 	struct cbcmac_tfm_ctx *tctx = crypto_shash_ctx(parent);
882f15f05b0SArd Biesheuvel 	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
883f15f05b0SArd Biesheuvel 	struct crypto_cipher *tfm = tctx->child;
884f15f05b0SArd Biesheuvel 	int bs = crypto_shash_digestsize(parent);
8855338ad70SArd Biesheuvel 	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
886f15f05b0SArd Biesheuvel 
887f15f05b0SArd Biesheuvel 	while (len > 0) {
888f15f05b0SArd Biesheuvel 		unsigned int l = min(len, bs - ctx->len);
889f15f05b0SArd Biesheuvel 
8905338ad70SArd Biesheuvel 		crypto_xor(dg + ctx->len, p, l);
891f15f05b0SArd Biesheuvel 		ctx->len +=l;
892f15f05b0SArd Biesheuvel 		len -= l;
893f15f05b0SArd Biesheuvel 		p += l;
894f15f05b0SArd Biesheuvel 
895f15f05b0SArd Biesheuvel 		if (ctx->len == bs) {
8965338ad70SArd Biesheuvel 			crypto_cipher_encrypt_one(tfm, dg, dg);
897f15f05b0SArd Biesheuvel 			ctx->len = 0;
898f15f05b0SArd Biesheuvel 		}
899f15f05b0SArd Biesheuvel 	}
900f15f05b0SArd Biesheuvel 
901f15f05b0SArd Biesheuvel 	return 0;
902f15f05b0SArd Biesheuvel }
903f15f05b0SArd Biesheuvel 
904f15f05b0SArd Biesheuvel static int crypto_cbcmac_digest_final(struct shash_desc *pdesc, u8 *out)
905f15f05b0SArd Biesheuvel {
906f15f05b0SArd Biesheuvel 	struct crypto_shash *parent = pdesc->tfm;
907f15f05b0SArd Biesheuvel 	struct cbcmac_tfm_ctx *tctx = crypto_shash_ctx(parent);
908f15f05b0SArd Biesheuvel 	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
909f15f05b0SArd Biesheuvel 	struct crypto_cipher *tfm = tctx->child;
910f15f05b0SArd Biesheuvel 	int bs = crypto_shash_digestsize(parent);
9115338ad70SArd Biesheuvel 	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
912f15f05b0SArd Biesheuvel 
913f15f05b0SArd Biesheuvel 	if (ctx->len)
9145338ad70SArd Biesheuvel 		crypto_cipher_encrypt_one(tfm, dg, dg);
915f15f05b0SArd Biesheuvel 
9165338ad70SArd Biesheuvel 	memcpy(out, dg, bs);
917f15f05b0SArd Biesheuvel 	return 0;
918f15f05b0SArd Biesheuvel }
919f15f05b0SArd Biesheuvel 
920f15f05b0SArd Biesheuvel static int cbcmac_init_tfm(struct crypto_tfm *tfm)
921f15f05b0SArd Biesheuvel {
922f15f05b0SArd Biesheuvel 	struct crypto_cipher *cipher;
923f15f05b0SArd Biesheuvel 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
924f15f05b0SArd Biesheuvel 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
925f15f05b0SArd Biesheuvel 	struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
926f15f05b0SArd Biesheuvel 
927f15f05b0SArd Biesheuvel 	cipher = crypto_spawn_cipher(spawn);
928f15f05b0SArd Biesheuvel 	if (IS_ERR(cipher))
929f15f05b0SArd Biesheuvel 		return PTR_ERR(cipher);
930f15f05b0SArd Biesheuvel 
931f15f05b0SArd Biesheuvel 	ctx->child = cipher;
932f15f05b0SArd Biesheuvel 
933f15f05b0SArd Biesheuvel 	return 0;
934f15f05b0SArd Biesheuvel };
935f15f05b0SArd Biesheuvel 
936f15f05b0SArd Biesheuvel static void cbcmac_exit_tfm(struct crypto_tfm *tfm)
937f15f05b0SArd Biesheuvel {
938f15f05b0SArd Biesheuvel 	struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
939f15f05b0SArd Biesheuvel 	crypto_free_cipher(ctx->child);
940f15f05b0SArd Biesheuvel }
941f15f05b0SArd Biesheuvel 
942f15f05b0SArd Biesheuvel static int cbcmac_create(struct crypto_template *tmpl, struct rtattr **tb)
943f15f05b0SArd Biesheuvel {
944f15f05b0SArd Biesheuvel 	struct shash_instance *inst;
945f15f05b0SArd Biesheuvel 	struct crypto_alg *alg;
946f15f05b0SArd Biesheuvel 	int err;
947f15f05b0SArd Biesheuvel 
948f15f05b0SArd Biesheuvel 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
949f15f05b0SArd Biesheuvel 	if (err)
950f15f05b0SArd Biesheuvel 		return err;
951f15f05b0SArd Biesheuvel 
952f15f05b0SArd Biesheuvel 	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
953f15f05b0SArd Biesheuvel 				  CRYPTO_ALG_TYPE_MASK);
954f15f05b0SArd Biesheuvel 	if (IS_ERR(alg))
955f15f05b0SArd Biesheuvel 		return PTR_ERR(alg);
956f15f05b0SArd Biesheuvel 
957f15f05b0SArd Biesheuvel 	inst = shash_alloc_instance("cbcmac", alg);
958f15f05b0SArd Biesheuvel 	err = PTR_ERR(inst);
959f15f05b0SArd Biesheuvel 	if (IS_ERR(inst))
960f15f05b0SArd Biesheuvel 		goto out_put_alg;
961f15f05b0SArd Biesheuvel 
962f15f05b0SArd Biesheuvel 	err = crypto_init_spawn(shash_instance_ctx(inst), alg,
963f15f05b0SArd Biesheuvel 				shash_crypto_instance(inst),
964f15f05b0SArd Biesheuvel 				CRYPTO_ALG_TYPE_MASK);
965f15f05b0SArd Biesheuvel 	if (err)
966f15f05b0SArd Biesheuvel 		goto out_free_inst;
967f15f05b0SArd Biesheuvel 
968f15f05b0SArd Biesheuvel 	inst->alg.base.cra_priority = alg->cra_priority;
969f15f05b0SArd Biesheuvel 	inst->alg.base.cra_blocksize = 1;
970f15f05b0SArd Biesheuvel 
971f15f05b0SArd Biesheuvel 	inst->alg.digestsize = alg->cra_blocksize;
9725338ad70SArd Biesheuvel 	inst->alg.descsize = ALIGN(sizeof(struct cbcmac_desc_ctx),
9735338ad70SArd Biesheuvel 				   alg->cra_alignmask + 1) +
974f15f05b0SArd Biesheuvel 			     alg->cra_blocksize;
975f15f05b0SArd Biesheuvel 
976f15f05b0SArd Biesheuvel 	inst->alg.base.cra_ctxsize = sizeof(struct cbcmac_tfm_ctx);
977f15f05b0SArd Biesheuvel 	inst->alg.base.cra_init = cbcmac_init_tfm;
978f15f05b0SArd Biesheuvel 	inst->alg.base.cra_exit = cbcmac_exit_tfm;
979f15f05b0SArd Biesheuvel 
980f15f05b0SArd Biesheuvel 	inst->alg.init = crypto_cbcmac_digest_init;
981f15f05b0SArd Biesheuvel 	inst->alg.update = crypto_cbcmac_digest_update;
982f15f05b0SArd Biesheuvel 	inst->alg.final = crypto_cbcmac_digest_final;
983f15f05b0SArd Biesheuvel 	inst->alg.setkey = crypto_cbcmac_digest_setkey;
984f15f05b0SArd Biesheuvel 
985f15f05b0SArd Biesheuvel 	err = shash_register_instance(tmpl, inst);
986f15f05b0SArd Biesheuvel 
987f15f05b0SArd Biesheuvel out_free_inst:
988f15f05b0SArd Biesheuvel 	if (err)
989f15f05b0SArd Biesheuvel 		shash_free_instance(shash_crypto_instance(inst));
990f15f05b0SArd Biesheuvel 
991f15f05b0SArd Biesheuvel out_put_alg:
992f15f05b0SArd Biesheuvel 	crypto_mod_put(alg);
993f15f05b0SArd Biesheuvel 	return err;
994f15f05b0SArd Biesheuvel }
995f15f05b0SArd Biesheuvel 
996f15f05b0SArd Biesheuvel static struct crypto_template crypto_cbcmac_tmpl = {
997f15f05b0SArd Biesheuvel 	.name = "cbcmac",
998f15f05b0SArd Biesheuvel 	.create = cbcmac_create,
999f15f05b0SArd Biesheuvel 	.free = shash_free_instance,
1000f15f05b0SArd Biesheuvel 	.module = THIS_MODULE,
1001f15f05b0SArd Biesheuvel };
1002f15f05b0SArd Biesheuvel 
10034a49b499SJoy Latten static int __init crypto_ccm_module_init(void)
10044a49b499SJoy Latten {
10054a49b499SJoy Latten 	int err;
10064a49b499SJoy Latten 
1007f15f05b0SArd Biesheuvel 	err = crypto_register_template(&crypto_cbcmac_tmpl);
10084a49b499SJoy Latten 	if (err)
10094a49b499SJoy Latten 		goto out;
10104a49b499SJoy Latten 
1011f15f05b0SArd Biesheuvel 	err = crypto_register_template(&crypto_ccm_base_tmpl);
1012f15f05b0SArd Biesheuvel 	if (err)
1013f15f05b0SArd Biesheuvel 		goto out_undo_cbcmac;
1014f15f05b0SArd Biesheuvel 
10154a49b499SJoy Latten 	err = crypto_register_template(&crypto_ccm_tmpl);
10164a49b499SJoy Latten 	if (err)
10174a49b499SJoy Latten 		goto out_undo_base;
10184a49b499SJoy Latten 
10194a49b499SJoy Latten 	err = crypto_register_template(&crypto_rfc4309_tmpl);
10204a49b499SJoy Latten 	if (err)
10214a49b499SJoy Latten 		goto out_undo_ccm;
10224a49b499SJoy Latten 
10234a49b499SJoy Latten out:
10244a49b499SJoy Latten 	return err;
10254a49b499SJoy Latten 
10264a49b499SJoy Latten out_undo_ccm:
10274a49b499SJoy Latten 	crypto_unregister_template(&crypto_ccm_tmpl);
10284a49b499SJoy Latten out_undo_base:
10294a49b499SJoy Latten 	crypto_unregister_template(&crypto_ccm_base_tmpl);
1030f15f05b0SArd Biesheuvel out_undo_cbcmac:
1031f15f05b0SArd Biesheuvel 	crypto_register_template(&crypto_cbcmac_tmpl);
10324a49b499SJoy Latten 	goto out;
10334a49b499SJoy Latten }
10344a49b499SJoy Latten 
10354a49b499SJoy Latten static void __exit crypto_ccm_module_exit(void)
10364a49b499SJoy Latten {
10374a49b499SJoy Latten 	crypto_unregister_template(&crypto_rfc4309_tmpl);
10384a49b499SJoy Latten 	crypto_unregister_template(&crypto_ccm_tmpl);
10394a49b499SJoy Latten 	crypto_unregister_template(&crypto_ccm_base_tmpl);
1040f15f05b0SArd Biesheuvel 	crypto_unregister_template(&crypto_cbcmac_tmpl);
10414a49b499SJoy Latten }
10424a49b499SJoy Latten 
10434a49b499SJoy Latten module_init(crypto_ccm_module_init);
10444a49b499SJoy Latten module_exit(crypto_ccm_module_exit);
10454a49b499SJoy Latten 
10464a49b499SJoy Latten MODULE_LICENSE("GPL");
10474a49b499SJoy Latten MODULE_DESCRIPTION("Counter with CBC MAC");
10485d26a105SKees Cook MODULE_ALIAS_CRYPTO("ccm_base");
10495d26a105SKees Cook MODULE_ALIAS_CRYPTO("rfc4309");
10504943ba16SKees Cook MODULE_ALIAS_CRYPTO("ccm");
1051