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