brintos

brintos / linux-shallow public Read only

0
0
Text · 23.1 KiB · 36f0ace Raw
953 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * CCM: Counter with CBC-MAC4 *5 * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>6 */7 8#include <crypto/internal/aead.h>9#include <crypto/internal/cipher.h>10#include <crypto/internal/hash.h>11#include <crypto/internal/skcipher.h>12#include <crypto/scatterwalk.h>13#include <linux/err.h>14#include <linux/init.h>15#include <linux/kernel.h>16#include <linux/module.h>17#include <linux/slab.h>18 19struct ccm_instance_ctx {20	struct crypto_skcipher_spawn ctr;21	struct crypto_ahash_spawn mac;22};23 24struct crypto_ccm_ctx {25	struct crypto_ahash *mac;26	struct crypto_skcipher *ctr;27};28 29struct crypto_rfc4309_ctx {30	struct crypto_aead *child;31	u8 nonce[3];32};33 34struct crypto_rfc4309_req_ctx {35	struct scatterlist src[3];36	struct scatterlist dst[3];37	struct aead_request subreq;38};39 40struct crypto_ccm_req_priv_ctx {41	u8 odata[16];42	u8 idata[16];43	u8 auth_tag[16];44	u32 flags;45	struct scatterlist src[3];46	struct scatterlist dst[3];47	union {48		struct ahash_request ahreq;49		struct skcipher_request skreq;50	};51};52 53struct cbcmac_tfm_ctx {54	struct crypto_cipher *child;55};56 57struct cbcmac_desc_ctx {58	unsigned int len;59	u8 dg[];60};61 62static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx(63	struct aead_request *req)64{65	unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));66 67	return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);68}69 70static int set_msg_len(u8 *block, unsigned int msglen, int csize)71{72	__be32 data;73 74	memset(block, 0, csize);75	block += csize;76 77	if (csize >= 4)78		csize = 4;79	else if (msglen > (1 << (8 * csize)))80		return -EOVERFLOW;81 82	data = cpu_to_be32(msglen);83	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);84 85	return 0;86}87 88static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key,89			     unsigned int keylen)90{91	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);92	struct crypto_skcipher *ctr = ctx->ctr;93	struct crypto_ahash *mac = ctx->mac;94	int err;95 96	crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);97	crypto_skcipher_set_flags(ctr, crypto_aead_get_flags(aead) &98				       CRYPTO_TFM_REQ_MASK);99	err = crypto_skcipher_setkey(ctr, key, keylen);100	if (err)101		return err;102 103	crypto_ahash_clear_flags(mac, CRYPTO_TFM_REQ_MASK);104	crypto_ahash_set_flags(mac, crypto_aead_get_flags(aead) &105				    CRYPTO_TFM_REQ_MASK);106	return crypto_ahash_setkey(mac, key, keylen);107}108 109static int crypto_ccm_setauthsize(struct crypto_aead *tfm,110				  unsigned int authsize)111{112	switch (authsize) {113	case 4:114	case 6:115	case 8:116	case 10:117	case 12:118	case 14:119	case 16:120		break;121	default:122		return -EINVAL;123	}124 125	return 0;126}127 128static int format_input(u8 *info, struct aead_request *req,129			unsigned int cryptlen)130{131	struct crypto_aead *aead = crypto_aead_reqtfm(req);132	unsigned int lp = req->iv[0];133	unsigned int l = lp + 1;134	unsigned int m;135 136	m = crypto_aead_authsize(aead);137 138	memcpy(info, req->iv, 16);139 140	/* format control info per RFC 3610 and141	 * NIST Special Publication 800-38C142	 */143	*info |= (8 * ((m - 2) / 2));144	if (req->assoclen)145		*info |= 64;146 147	return set_msg_len(info + 16 - l, cryptlen, l);148}149 150static int format_adata(u8 *adata, unsigned int a)151{152	int len = 0;153 154	/* add control info for associated data155	 * RFC 3610 and NIST Special Publication 800-38C156	 */157	if (a < 65280) {158		*(__be16 *)adata = cpu_to_be16(a);159		len = 2;160	} else  {161		*(__be16 *)adata = cpu_to_be16(0xfffe);162		*(__be32 *)&adata[2] = cpu_to_be32(a);163		len = 6;164	}165 166	return len;167}168 169static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,170			   unsigned int cryptlen)171{172	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);173	struct crypto_aead *aead = crypto_aead_reqtfm(req);174	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);175	struct ahash_request *ahreq = &pctx->ahreq;176	unsigned int assoclen = req->assoclen;177	struct scatterlist sg[3];178	u8 *odata = pctx->odata;179	u8 *idata = pctx->idata;180	int ilen, err;181 182	/* format control data for input */183	err = format_input(odata, req, cryptlen);184	if (err)185		goto out;186 187	sg_init_table(sg, 3);188	sg_set_buf(&sg[0], odata, 16);189 190	/* format associated data and compute into mac */191	if (assoclen) {192		ilen = format_adata(idata, assoclen);193		sg_set_buf(&sg[1], idata, ilen);194		sg_chain(sg, 3, req->src);195	} else {196		ilen = 0;197		sg_chain(sg, 2, req->src);198	}199 200	ahash_request_set_tfm(ahreq, ctx->mac);201	ahash_request_set_callback(ahreq, pctx->flags, NULL, NULL);202	ahash_request_set_crypt(ahreq, sg, NULL, assoclen + ilen + 16);203	err = crypto_ahash_init(ahreq);204	if (err)205		goto out;206	err = crypto_ahash_update(ahreq);207	if (err)208		goto out;209 210	/* we need to pad the MAC input to a round multiple of the block size */211	ilen = 16 - (assoclen + ilen) % 16;212	if (ilen < 16) {213		memset(idata, 0, ilen);214		sg_init_table(sg, 2);215		sg_set_buf(&sg[0], idata, ilen);216		if (plain)217			sg_chain(sg, 2, plain);218		plain = sg;219		cryptlen += ilen;220	}221 222	ahash_request_set_crypt(ahreq, plain, odata, cryptlen);223	err = crypto_ahash_finup(ahreq);224out:225	return err;226}227 228static void crypto_ccm_encrypt_done(void *data, int err)229{230	struct aead_request *req = data;231	struct crypto_aead *aead = crypto_aead_reqtfm(req);232	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);233	u8 *odata = pctx->odata;234 235	if (!err)236		scatterwalk_map_and_copy(odata, req->dst,237					 req->assoclen + req->cryptlen,238					 crypto_aead_authsize(aead), 1);239	aead_request_complete(req, err);240}241 242static inline int crypto_ccm_check_iv(const u8 *iv)243{244	/* 2 <= L <= 8, so 1 <= L' <= 7. */245	if (1 > iv[0] || iv[0] > 7)246		return -EINVAL;247 248	return 0;249}250 251static int crypto_ccm_init_crypt(struct aead_request *req, u8 *tag)252{253	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);254	struct scatterlist *sg;255	u8 *iv = req->iv;256	int err;257 258	err = crypto_ccm_check_iv(iv);259	if (err)260		return err;261 262	pctx->flags = aead_request_flags(req);263 264	 /* Note: rfc 3610 and NIST 800-38C require counter of265	 * zero to encrypt auth tag.266	 */267	memset(iv + 15 - iv[0], 0, iv[0] + 1);268 269	sg_init_table(pctx->src, 3);270	sg_set_buf(pctx->src, tag, 16);271	sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);272	if (sg != pctx->src + 1)273		sg_chain(pctx->src, 2, sg);274 275	if (req->src != req->dst) {276		sg_init_table(pctx->dst, 3);277		sg_set_buf(pctx->dst, tag, 16);278		sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);279		if (sg != pctx->dst + 1)280			sg_chain(pctx->dst, 2, sg);281	}282 283	return 0;284}285 286static int crypto_ccm_encrypt(struct aead_request *req)287{288	struct crypto_aead *aead = crypto_aead_reqtfm(req);289	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);290	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);291	struct skcipher_request *skreq = &pctx->skreq;292	struct scatterlist *dst;293	unsigned int cryptlen = req->cryptlen;294	u8 *odata = pctx->odata;295	u8 *iv = req->iv;296	int err;297 298	err = crypto_ccm_init_crypt(req, odata);299	if (err)300		return err;301 302	err = crypto_ccm_auth(req, sg_next(pctx->src), cryptlen);303	if (err)304		return err;305 306	dst = pctx->src;307	if (req->src != req->dst)308		dst = pctx->dst;309 310	skcipher_request_set_tfm(skreq, ctx->ctr);311	skcipher_request_set_callback(skreq, pctx->flags,312				      crypto_ccm_encrypt_done, req);313	skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv);314	err = crypto_skcipher_encrypt(skreq);315	if (err)316		return err;317 318	/* copy authtag to end of dst */319	scatterwalk_map_and_copy(odata, sg_next(dst), cryptlen,320				 crypto_aead_authsize(aead), 1);321	return err;322}323 324static void crypto_ccm_decrypt_done(void *data, int err)325{326	struct aead_request *req = data;327	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);328	struct crypto_aead *aead = crypto_aead_reqtfm(req);329	unsigned int authsize = crypto_aead_authsize(aead);330	unsigned int cryptlen = req->cryptlen - authsize;331	struct scatterlist *dst;332 333	pctx->flags = 0;334 335	dst = sg_next(req->src == req->dst ? pctx->src : pctx->dst);336 337	if (!err) {338		err = crypto_ccm_auth(req, dst, cryptlen);339		if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize))340			err = -EBADMSG;341	}342	aead_request_complete(req, err);343}344 345static int crypto_ccm_decrypt(struct aead_request *req)346{347	struct crypto_aead *aead = crypto_aead_reqtfm(req);348	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);349	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);350	struct skcipher_request *skreq = &pctx->skreq;351	struct scatterlist *dst;352	unsigned int authsize = crypto_aead_authsize(aead);353	unsigned int cryptlen = req->cryptlen;354	u8 *authtag = pctx->auth_tag;355	u8 *odata = pctx->odata;356	u8 *iv = pctx->idata;357	int err;358 359	cryptlen -= authsize;360 361	err = crypto_ccm_init_crypt(req, authtag);362	if (err)363		return err;364 365	scatterwalk_map_and_copy(authtag, sg_next(pctx->src), cryptlen,366				 authsize, 0);367 368	dst = pctx->src;369	if (req->src != req->dst)370		dst = pctx->dst;371 372	memcpy(iv, req->iv, 16);373 374	skcipher_request_set_tfm(skreq, ctx->ctr);375	skcipher_request_set_callback(skreq, pctx->flags,376				      crypto_ccm_decrypt_done, req);377	skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv);378	err = crypto_skcipher_decrypt(skreq);379	if (err)380		return err;381 382	err = crypto_ccm_auth(req, sg_next(dst), cryptlen);383	if (err)384		return err;385 386	/* verify */387	if (crypto_memneq(authtag, odata, authsize))388		return -EBADMSG;389 390	return err;391}392 393static int crypto_ccm_init_tfm(struct crypto_aead *tfm)394{395	struct aead_instance *inst = aead_alg_instance(tfm);396	struct ccm_instance_ctx *ictx = aead_instance_ctx(inst);397	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);398	struct crypto_ahash *mac;399	struct crypto_skcipher *ctr;400	unsigned long align;401	int err;402 403	mac = crypto_spawn_ahash(&ictx->mac);404	if (IS_ERR(mac))405		return PTR_ERR(mac);406 407	ctr = crypto_spawn_skcipher(&ictx->ctr);408	err = PTR_ERR(ctr);409	if (IS_ERR(ctr))410		goto err_free_mac;411 412	ctx->mac = mac;413	ctx->ctr = ctr;414 415	align = crypto_aead_alignmask(tfm);416	align &= ~(crypto_tfm_ctx_alignment() - 1);417	crypto_aead_set_reqsize(418		tfm,419		align + sizeof(struct crypto_ccm_req_priv_ctx) +420		max(crypto_ahash_reqsize(mac), crypto_skcipher_reqsize(ctr)));421 422	return 0;423 424err_free_mac:425	crypto_free_ahash(mac);426	return err;427}428 429static void crypto_ccm_exit_tfm(struct crypto_aead *tfm)430{431	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);432 433	crypto_free_ahash(ctx->mac);434	crypto_free_skcipher(ctx->ctr);435}436 437static void crypto_ccm_free(struct aead_instance *inst)438{439	struct ccm_instance_ctx *ctx = aead_instance_ctx(inst);440 441	crypto_drop_ahash(&ctx->mac);442	crypto_drop_skcipher(&ctx->ctr);443	kfree(inst);444}445 446static int crypto_ccm_create_common(struct crypto_template *tmpl,447				    struct rtattr **tb,448				    const char *ctr_name,449				    const char *mac_name)450{451	struct skcipher_alg_common *ctr;452	u32 mask;453	struct aead_instance *inst;454	struct ccm_instance_ctx *ictx;455	struct hash_alg_common *mac;456	int err;457 458	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);459	if (err)460		return err;461 462	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);463	if (!inst)464		return -ENOMEM;465	ictx = aead_instance_ctx(inst);466 467	err = crypto_grab_ahash(&ictx->mac, aead_crypto_instance(inst),468				mac_name, 0, mask | CRYPTO_ALG_ASYNC);469	if (err)470		goto err_free_inst;471	mac = crypto_spawn_ahash_alg(&ictx->mac);472 473	err = -EINVAL;474	if (strncmp(mac->base.cra_name, "cbcmac(", 7) != 0 ||475	    mac->digestsize != 16)476		goto err_free_inst;477 478	err = crypto_grab_skcipher(&ictx->ctr, aead_crypto_instance(inst),479				   ctr_name, 0, mask);480	if (err)481		goto err_free_inst;482	ctr = crypto_spawn_skcipher_alg_common(&ictx->ctr);483 484	/* The skcipher algorithm must be CTR mode, using 16-byte blocks. */485	err = -EINVAL;486	if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 ||487	    ctr->ivsize != 16 || ctr->base.cra_blocksize != 1)488		goto err_free_inst;489 490	/* ctr and cbcmac must use the same underlying block cipher. */491	if (strcmp(ctr->base.cra_name + 4, mac->base.cra_name + 7) != 0)492		goto err_free_inst;493 494	err = -ENAMETOOLONG;495	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,496		     "ccm(%s", ctr->base.cra_name + 4) >= CRYPTO_MAX_ALG_NAME)497		goto err_free_inst;498 499	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,500		     "ccm_base(%s,%s)", ctr->base.cra_driver_name,501		     mac->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)502		goto err_free_inst;503 504	inst->alg.base.cra_priority = (mac->base.cra_priority +505				       ctr->base.cra_priority) / 2;506	inst->alg.base.cra_blocksize = 1;507	inst->alg.base.cra_alignmask = ctr->base.cra_alignmask;508	inst->alg.ivsize = 16;509	inst->alg.chunksize = ctr->chunksize;510	inst->alg.maxauthsize = 16;511	inst->alg.base.cra_ctxsize = sizeof(struct crypto_ccm_ctx);512	inst->alg.init = crypto_ccm_init_tfm;513	inst->alg.exit = crypto_ccm_exit_tfm;514	inst->alg.setkey = crypto_ccm_setkey;515	inst->alg.setauthsize = crypto_ccm_setauthsize;516	inst->alg.encrypt = crypto_ccm_encrypt;517	inst->alg.decrypt = crypto_ccm_decrypt;518 519	inst->free = crypto_ccm_free;520 521	err = aead_register_instance(tmpl, inst);522	if (err) {523err_free_inst:524		crypto_ccm_free(inst);525	}526	return err;527}528 529static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb)530{531	const char *cipher_name;532	char ctr_name[CRYPTO_MAX_ALG_NAME];533	char mac_name[CRYPTO_MAX_ALG_NAME];534 535	cipher_name = crypto_attr_alg_name(tb[1]);536	if (IS_ERR(cipher_name))537		return PTR_ERR(cipher_name);538 539	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",540		     cipher_name) >= CRYPTO_MAX_ALG_NAME)541		return -ENAMETOOLONG;542 543	if (snprintf(mac_name, CRYPTO_MAX_ALG_NAME, "cbcmac(%s)",544		     cipher_name) >= CRYPTO_MAX_ALG_NAME)545		return -ENAMETOOLONG;546 547	return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);548}549 550static int crypto_ccm_base_create(struct crypto_template *tmpl,551				  struct rtattr **tb)552{553	const char *ctr_name;554	const char *mac_name;555 556	ctr_name = crypto_attr_alg_name(tb[1]);557	if (IS_ERR(ctr_name))558		return PTR_ERR(ctr_name);559 560	mac_name = crypto_attr_alg_name(tb[2]);561	if (IS_ERR(mac_name))562		return PTR_ERR(mac_name);563 564	return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);565}566 567static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key,568				 unsigned int keylen)569{570	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);571	struct crypto_aead *child = ctx->child;572 573	if (keylen < 3)574		return -EINVAL;575 576	keylen -= 3;577	memcpy(ctx->nonce, key + keylen, 3);578 579	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);580	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &581				     CRYPTO_TFM_REQ_MASK);582	return crypto_aead_setkey(child, key, keylen);583}584 585static int crypto_rfc4309_setauthsize(struct crypto_aead *parent,586				      unsigned int authsize)587{588	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);589 590	switch (authsize) {591	case 8:592	case 12:593	case 16:594		break;595	default:596		return -EINVAL;597	}598 599	return crypto_aead_setauthsize(ctx->child, authsize);600}601 602static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req)603{604	struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req);605	struct aead_request *subreq = &rctx->subreq;606	struct crypto_aead *aead = crypto_aead_reqtfm(req);607	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(aead);608	struct crypto_aead *child = ctx->child;609	struct scatterlist *sg;610	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),611			   crypto_aead_alignmask(child) + 1);612 613	/* L' */614	iv[0] = 3;615 616	memcpy(iv + 1, ctx->nonce, 3);617	memcpy(iv + 4, req->iv, 8);618 619	scatterwalk_map_and_copy(iv + 16, req->src, 0, req->assoclen - 8, 0);620 621	sg_init_table(rctx->src, 3);622	sg_set_buf(rctx->src, iv + 16, req->assoclen - 8);623	sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen);624	if (sg != rctx->src + 1)625		sg_chain(rctx->src, 2, sg);626 627	if (req->src != req->dst) {628		sg_init_table(rctx->dst, 3);629		sg_set_buf(rctx->dst, iv + 16, req->assoclen - 8);630		sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen);631		if (sg != rctx->dst + 1)632			sg_chain(rctx->dst, 2, sg);633	}634 635	aead_request_set_tfm(subreq, child);636	aead_request_set_callback(subreq, req->base.flags, req->base.complete,637				  req->base.data);638	aead_request_set_crypt(subreq, rctx->src,639			       req->src == req->dst ? rctx->src : rctx->dst,640			       req->cryptlen, iv);641	aead_request_set_ad(subreq, req->assoclen - 8);642 643	return subreq;644}645 646static int crypto_rfc4309_encrypt(struct aead_request *req)647{648	if (req->assoclen != 16 && req->assoclen != 20)649		return -EINVAL;650 651	req = crypto_rfc4309_crypt(req);652 653	return crypto_aead_encrypt(req);654}655 656static int crypto_rfc4309_decrypt(struct aead_request *req)657{658	if (req->assoclen != 16 && req->assoclen != 20)659		return -EINVAL;660 661	req = crypto_rfc4309_crypt(req);662 663	return crypto_aead_decrypt(req);664}665 666static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm)667{668	struct aead_instance *inst = aead_alg_instance(tfm);669	struct crypto_aead_spawn *spawn = aead_instance_ctx(inst);670	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);671	struct crypto_aead *aead;672	unsigned long align;673 674	aead = crypto_spawn_aead(spawn);675	if (IS_ERR(aead))676		return PTR_ERR(aead);677 678	ctx->child = aead;679 680	align = crypto_aead_alignmask(aead);681	align &= ~(crypto_tfm_ctx_alignment() - 1);682	crypto_aead_set_reqsize(683		tfm,684		sizeof(struct crypto_rfc4309_req_ctx) +685		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +686		align + 32);687 688	return 0;689}690 691static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm)692{693	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);694 695	crypto_free_aead(ctx->child);696}697 698static void crypto_rfc4309_free(struct aead_instance *inst)699{700	crypto_drop_aead(aead_instance_ctx(inst));701	kfree(inst);702}703 704static int crypto_rfc4309_create(struct crypto_template *tmpl,705				 struct rtattr **tb)706{707	u32 mask;708	struct aead_instance *inst;709	struct crypto_aead_spawn *spawn;710	struct aead_alg *alg;711	int err;712 713	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);714	if (err)715		return err;716 717	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);718	if (!inst)719		return -ENOMEM;720 721	spawn = aead_instance_ctx(inst);722	err = crypto_grab_aead(spawn, aead_crypto_instance(inst),723			       crypto_attr_alg_name(tb[1]), 0, mask);724	if (err)725		goto err_free_inst;726 727	alg = crypto_spawn_aead_alg(spawn);728 729	err = -EINVAL;730 731	/* We only support 16-byte blocks. */732	if (crypto_aead_alg_ivsize(alg) != 16)733		goto err_free_inst;734 735	/* Not a stream cipher? */736	if (alg->base.cra_blocksize != 1)737		goto err_free_inst;738 739	err = -ENAMETOOLONG;740	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,741		     "rfc4309(%s)", alg->base.cra_name) >=742	    CRYPTO_MAX_ALG_NAME ||743	    snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,744		     "rfc4309(%s)", alg->base.cra_driver_name) >=745	    CRYPTO_MAX_ALG_NAME)746		goto err_free_inst;747 748	inst->alg.base.cra_priority = alg->base.cra_priority;749	inst->alg.base.cra_blocksize = 1;750	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;751 752	inst->alg.ivsize = 8;753	inst->alg.chunksize = crypto_aead_alg_chunksize(alg);754	inst->alg.maxauthsize = 16;755 756	inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);757 758	inst->alg.init = crypto_rfc4309_init_tfm;759	inst->alg.exit = crypto_rfc4309_exit_tfm;760 761	inst->alg.setkey = crypto_rfc4309_setkey;762	inst->alg.setauthsize = crypto_rfc4309_setauthsize;763	inst->alg.encrypt = crypto_rfc4309_encrypt;764	inst->alg.decrypt = crypto_rfc4309_decrypt;765 766	inst->free = crypto_rfc4309_free;767 768	err = aead_register_instance(tmpl, inst);769	if (err) {770err_free_inst:771		crypto_rfc4309_free(inst);772	}773	return err;774}775 776static int crypto_cbcmac_digest_setkey(struct crypto_shash *parent,777				     const u8 *inkey, unsigned int keylen)778{779	struct cbcmac_tfm_ctx *ctx = crypto_shash_ctx(parent);780 781	return crypto_cipher_setkey(ctx->child, inkey, keylen);782}783 784static int crypto_cbcmac_digest_init(struct shash_desc *pdesc)785{786	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);787	int bs = crypto_shash_digestsize(pdesc->tfm);788 789	ctx->len = 0;790	memset(ctx->dg, 0, bs);791 792	return 0;793}794 795static int crypto_cbcmac_digest_update(struct shash_desc *pdesc, const u8 *p,796				       unsigned int len)797{798	struct crypto_shash *parent = pdesc->tfm;799	struct cbcmac_tfm_ctx *tctx = crypto_shash_ctx(parent);800	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);801	struct crypto_cipher *tfm = tctx->child;802	int bs = crypto_shash_digestsize(parent);803 804	while (len > 0) {805		unsigned int l = min(len, bs - ctx->len);806 807		crypto_xor(&ctx->dg[ctx->len], p, l);808		ctx->len +=l;809		len -= l;810		p += l;811 812		if (ctx->len == bs) {813			crypto_cipher_encrypt_one(tfm, ctx->dg, ctx->dg);814			ctx->len = 0;815		}816	}817 818	return 0;819}820 821static int crypto_cbcmac_digest_final(struct shash_desc *pdesc, u8 *out)822{823	struct crypto_shash *parent = pdesc->tfm;824	struct cbcmac_tfm_ctx *tctx = crypto_shash_ctx(parent);825	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);826	struct crypto_cipher *tfm = tctx->child;827	int bs = crypto_shash_digestsize(parent);828 829	if (ctx->len)830		crypto_cipher_encrypt_one(tfm, ctx->dg, ctx->dg);831 832	memcpy(out, ctx->dg, bs);833	return 0;834}835 836static int cbcmac_init_tfm(struct crypto_tfm *tfm)837{838	struct crypto_cipher *cipher;839	struct crypto_instance *inst = (void *)tfm->__crt_alg;840	struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst);841	struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm);842 843	cipher = crypto_spawn_cipher(spawn);844	if (IS_ERR(cipher))845		return PTR_ERR(cipher);846 847	ctx->child = cipher;848 849	return 0;850};851 852static void cbcmac_exit_tfm(struct crypto_tfm *tfm)853{854	struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm);855	crypto_free_cipher(ctx->child);856}857 858static int cbcmac_create(struct crypto_template *tmpl, struct rtattr **tb)859{860	struct shash_instance *inst;861	struct crypto_cipher_spawn *spawn;862	struct crypto_alg *alg;863	u32 mask;864	int err;865 866	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH, &mask);867	if (err)868		return err;869 870	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);871	if (!inst)872		return -ENOMEM;873	spawn = shash_instance_ctx(inst);874 875	err = crypto_grab_cipher(spawn, shash_crypto_instance(inst),876				 crypto_attr_alg_name(tb[1]), 0, mask);877	if (err)878		goto err_free_inst;879	alg = crypto_spawn_cipher_alg(spawn);880 881	err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg);882	if (err)883		goto err_free_inst;884 885	inst->alg.base.cra_priority = alg->cra_priority;886	inst->alg.base.cra_blocksize = 1;887 888	inst->alg.digestsize = alg->cra_blocksize;889	inst->alg.descsize = sizeof(struct cbcmac_desc_ctx) +890			     alg->cra_blocksize;891 892	inst->alg.base.cra_ctxsize = sizeof(struct cbcmac_tfm_ctx);893	inst->alg.base.cra_init = cbcmac_init_tfm;894	inst->alg.base.cra_exit = cbcmac_exit_tfm;895 896	inst->alg.init = crypto_cbcmac_digest_init;897	inst->alg.update = crypto_cbcmac_digest_update;898	inst->alg.final = crypto_cbcmac_digest_final;899	inst->alg.setkey = crypto_cbcmac_digest_setkey;900 901	inst->free = shash_free_singlespawn_instance;902 903	err = shash_register_instance(tmpl, inst);904	if (err) {905err_free_inst:906		shash_free_singlespawn_instance(inst);907	}908	return err;909}910 911static struct crypto_template crypto_ccm_tmpls[] = {912	{913		.name = "cbcmac",914		.create = cbcmac_create,915		.module = THIS_MODULE,916	}, {917		.name = "ccm_base",918		.create = crypto_ccm_base_create,919		.module = THIS_MODULE,920	}, {921		.name = "ccm",922		.create = crypto_ccm_create,923		.module = THIS_MODULE,924	}, {925		.name = "rfc4309",926		.create = crypto_rfc4309_create,927		.module = THIS_MODULE,928	},929};930 931static int __init crypto_ccm_module_init(void)932{933	return crypto_register_templates(crypto_ccm_tmpls,934					 ARRAY_SIZE(crypto_ccm_tmpls));935}936 937static void __exit crypto_ccm_module_exit(void)938{939	crypto_unregister_templates(crypto_ccm_tmpls,940				    ARRAY_SIZE(crypto_ccm_tmpls));941}942 943subsys_initcall(crypto_ccm_module_init);944module_exit(crypto_ccm_module_exit);945 946MODULE_LICENSE("GPL");947MODULE_DESCRIPTION("Counter with CBC MAC");948MODULE_ALIAS_CRYPTO("ccm_base");949MODULE_ALIAS_CRYPTO("rfc4309");950MODULE_ALIAS_CRYPTO("ccm");951MODULE_ALIAS_CRYPTO("cbcmac");952MODULE_IMPORT_NS(CRYPTO_INTERNAL);953