1/* 2 * ChaCha20-Poly1305 AEAD, RFC7539 3 * 4 * Copyright (C) 2015 Martin Willi 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 */ 11 12#include <crypto/internal/aead.h> 13#include <crypto/internal/hash.h> 14#include <crypto/internal/skcipher.h> 15#include <crypto/scatterwalk.h> 16#include <crypto/chacha20.h> 17#include <crypto/poly1305.h> 18#include <linux/err.h> 19#include <linux/init.h> 20#include <linux/kernel.h> 21#include <linux/module.h> 22 23#include "internal.h" 24 25#define CHACHAPOLY_IV_SIZE 12 26 27struct chachapoly_instance_ctx { 28 struct crypto_skcipher_spawn chacha; 29 struct crypto_ahash_spawn poly; 30 unsigned int saltlen; 31}; 32 33struct chachapoly_ctx { 34 struct crypto_ablkcipher *chacha; 35 struct crypto_ahash *poly; 36 /* key bytes we use for the ChaCha20 IV */ 37 unsigned int saltlen; 38 u8 salt[]; 39}; 40 41struct poly_req { 42 /* zero byte padding for AD/ciphertext, as needed */ 43 u8 pad[POLY1305_BLOCK_SIZE]; 44 /* tail data with AD/ciphertext lengths */ 45 struct { 46 __le64 assoclen; 47 __le64 cryptlen; 48 } tail; 49 struct scatterlist src[1]; 50 struct ahash_request req; /* must be last member */ 51}; 52 53struct chacha_req { 54 u8 iv[CHACHA20_IV_SIZE]; 55 struct scatterlist src[1]; 56 struct ablkcipher_request req; /* must be last member */ 57}; 58 59struct chachapoly_req_ctx { 60 struct scatterlist src[2]; 61 struct scatterlist dst[2]; 62 /* the key we generate for Poly1305 using Chacha20 */ 63 u8 key[POLY1305_KEY_SIZE]; 64 /* calculated Poly1305 tag */ 65 u8 tag[POLY1305_DIGEST_SIZE]; 66 /* length of data to en/decrypt, without ICV */ 67 unsigned int cryptlen; 68 /* Actual AD, excluding IV */ 69 unsigned int assoclen; 70 union { 71 struct poly_req poly; 72 struct chacha_req chacha; 73 } u; 74}; 75 76static inline void async_done_continue(struct aead_request *req, int err, 77 int (*cont)(struct aead_request *)) 78{ 79 if (!err) 80 err = cont(req); 81 82 if (err != -EINPROGRESS && err != -EBUSY) 83 aead_request_complete(req, err); 84} 85 86static void chacha_iv(u8 *iv, struct aead_request *req, u32 icb) 87{ 88 struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 89 __le32 leicb = cpu_to_le32(icb); 90 91 memcpy(iv, &leicb, sizeof(leicb)); 92 memcpy(iv + sizeof(leicb), ctx->salt, ctx->saltlen); 93 memcpy(iv + sizeof(leicb) + ctx->saltlen, req->iv, 94 CHACHA20_IV_SIZE - sizeof(leicb) - ctx->saltlen); 95} 96 97static int poly_verify_tag(struct aead_request *req) 98{ 99 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 100 u8 tag[sizeof(rctx->tag)]; 101 102 scatterwalk_map_and_copy(tag, req->src, 103 req->assoclen + rctx->cryptlen, 104 sizeof(tag), 0); 105 if (crypto_memneq(tag, rctx->tag, sizeof(tag))) 106 return -EBADMSG; 107 return 0; 108} 109 110static int poly_copy_tag(struct aead_request *req) 111{ 112 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 113 114 scatterwalk_map_and_copy(rctx->tag, req->dst, 115 req->assoclen + rctx->cryptlen, 116 sizeof(rctx->tag), 1); 117 return 0; 118} 119 120static void chacha_decrypt_done(struct crypto_async_request *areq, int err) 121{ 122 async_done_continue(areq->data, err, poly_verify_tag); 123} 124 125static int chacha_decrypt(struct aead_request *req) 126{ 127 struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 128 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 129 struct chacha_req *creq = &rctx->u.chacha; 130 struct scatterlist *src, *dst; 131 int err; 132 133 chacha_iv(creq->iv, req, 1); 134 135 sg_init_table(rctx->src, 2); 136 src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen); 137 dst = src; 138 139 if (req->src != req->dst) { 140 sg_init_table(rctx->dst, 2); 141 dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen); 142 } 143 144 ablkcipher_request_set_callback(&creq->req, aead_request_flags(req), 145 chacha_decrypt_done, req); 146 ablkcipher_request_set_tfm(&creq->req, ctx->chacha); 147 ablkcipher_request_set_crypt(&creq->req, src, dst, 148 rctx->cryptlen, creq->iv); 149 err = crypto_ablkcipher_decrypt(&creq->req); 150 if (err) 151 return err; 152 153 return poly_verify_tag(req); 154} 155 156static int poly_tail_continue(struct aead_request *req) 157{ 158 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 159 160 if (rctx->cryptlen == req->cryptlen) /* encrypting */ 161 return poly_copy_tag(req); 162 163 return chacha_decrypt(req); 164} 165 166static void poly_tail_done(struct crypto_async_request *areq, int err) 167{ 168 async_done_continue(areq->data, err, poly_tail_continue); 169} 170 171static int poly_tail(struct aead_request *req) 172{ 173 struct crypto_aead *tfm = crypto_aead_reqtfm(req); 174 struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 175 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 176 struct poly_req *preq = &rctx->u.poly; 177 __le64 len; 178 int err; 179 180 sg_init_table(preq->src, 1); 181 len = cpu_to_le64(rctx->assoclen); 182 memcpy(&preq->tail.assoclen, &len, sizeof(len)); 183 len = cpu_to_le64(rctx->cryptlen); 184 memcpy(&preq->tail.cryptlen, &len, sizeof(len)); 185 sg_set_buf(preq->src, &preq->tail, sizeof(preq->tail)); 186 187 ahash_request_set_callback(&preq->req, aead_request_flags(req), 188 poly_tail_done, req); 189 ahash_request_set_tfm(&preq->req, ctx->poly); 190 ahash_request_set_crypt(&preq->req, preq->src, 191 rctx->tag, sizeof(preq->tail)); 192 193 err = crypto_ahash_finup(&preq->req); 194 if (err) 195 return err; 196 197 return poly_tail_continue(req); 198} 199 200static void poly_cipherpad_done(struct crypto_async_request *areq, int err) 201{ 202 async_done_continue(areq->data, err, poly_tail); 203} 204 205static int poly_cipherpad(struct aead_request *req) 206{ 207 struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 208 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 209 struct poly_req *preq = &rctx->u.poly; 210 unsigned int padlen, bs = POLY1305_BLOCK_SIZE; 211 int err; 212 213 padlen = (bs - (rctx->cryptlen % bs)) % bs; 214 memset(preq->pad, 0, sizeof(preq->pad)); 215 sg_init_table(preq->src, 1); 216 sg_set_buf(preq->src, &preq->pad, padlen); 217 218 ahash_request_set_callback(&preq->req, aead_request_flags(req), 219 poly_cipherpad_done, req); 220 ahash_request_set_tfm(&preq->req, ctx->poly); 221 ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); 222 223 err = crypto_ahash_update(&preq->req); 224 if (err) 225 return err; 226 227 return poly_tail(req); 228} 229 230static void poly_cipher_done(struct crypto_async_request *areq, int err) 231{ 232 async_done_continue(areq->data, err, poly_cipherpad); 233} 234 235static int poly_cipher(struct aead_request *req) 236{ 237 struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 238 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 239 struct poly_req *preq = &rctx->u.poly; 240 struct scatterlist *crypt = req->src; 241 int err; 242 243 if (rctx->cryptlen == req->cryptlen) /* encrypting */ 244 crypt = req->dst; 245 246 sg_init_table(rctx->src, 2); 247 crypt = scatterwalk_ffwd(rctx->src, crypt, req->assoclen); 248 249 ahash_request_set_callback(&preq->req, aead_request_flags(req), 250 poly_cipher_done, req); 251 ahash_request_set_tfm(&preq->req, ctx->poly); 252 ahash_request_set_crypt(&preq->req, crypt, NULL, rctx->cryptlen); 253 254 err = crypto_ahash_update(&preq->req); 255 if (err) 256 return err; 257 258 return poly_cipherpad(req); 259} 260 261static void poly_adpad_done(struct crypto_async_request *areq, int err) 262{ 263 async_done_continue(areq->data, err, poly_cipher); 264} 265 266static int poly_adpad(struct aead_request *req) 267{ 268 struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 269 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 270 struct poly_req *preq = &rctx->u.poly; 271 unsigned int padlen, bs = POLY1305_BLOCK_SIZE; 272 int err; 273 274 padlen = (bs - (rctx->assoclen % bs)) % bs; 275 memset(preq->pad, 0, sizeof(preq->pad)); 276 sg_init_table(preq->src, 1); 277 sg_set_buf(preq->src, preq->pad, padlen); 278 279 ahash_request_set_callback(&preq->req, aead_request_flags(req), 280 poly_adpad_done, req); 281 ahash_request_set_tfm(&preq->req, ctx->poly); 282 ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); 283 284 err = crypto_ahash_update(&preq->req); 285 if (err) 286 return err; 287 288 return poly_cipher(req); 289} 290 291static void poly_ad_done(struct crypto_async_request *areq, int err) 292{ 293 async_done_continue(areq->data, err, poly_adpad); 294} 295 296static int poly_ad(struct aead_request *req) 297{ 298 struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 299 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 300 struct poly_req *preq = &rctx->u.poly; 301 int err; 302 303 ahash_request_set_callback(&preq->req, aead_request_flags(req), 304 poly_ad_done, req); 305 ahash_request_set_tfm(&preq->req, ctx->poly); 306 ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen); 307 308 err = crypto_ahash_update(&preq->req); 309 if (err) 310 return err; 311 312 return poly_adpad(req); 313} 314 315static void poly_setkey_done(struct crypto_async_request *areq, int err) 316{ 317 async_done_continue(areq->data, err, poly_ad); 318} 319 320static int poly_setkey(struct aead_request *req) 321{ 322 struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 323 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 324 struct poly_req *preq = &rctx->u.poly; 325 int err; 326 327 sg_init_table(preq->src, 1); 328 sg_set_buf(preq->src, rctx->key, sizeof(rctx->key)); 329 330 ahash_request_set_callback(&preq->req, aead_request_flags(req), 331 poly_setkey_done, req); 332 ahash_request_set_tfm(&preq->req, ctx->poly); 333 ahash_request_set_crypt(&preq->req, preq->src, NULL, sizeof(rctx->key)); 334 335 err = crypto_ahash_update(&preq->req); 336 if (err) 337 return err; 338 339 return poly_ad(req); 340} 341 342static void poly_init_done(struct crypto_async_request *areq, int err) 343{ 344 async_done_continue(areq->data, err, poly_setkey); 345} 346 347static int poly_init(struct aead_request *req) 348{ 349 struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 350 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 351 struct poly_req *preq = &rctx->u.poly; 352 int err; 353 354 ahash_request_set_callback(&preq->req, aead_request_flags(req), 355 poly_init_done, req); 356 ahash_request_set_tfm(&preq->req, ctx->poly); 357 358 err = crypto_ahash_init(&preq->req); 359 if (err) 360 return err; 361 362 return poly_setkey(req); 363} 364 365static void poly_genkey_done(struct crypto_async_request *areq, int err) 366{ 367 async_done_continue(areq->data, err, poly_init); 368} 369 370static int poly_genkey(struct aead_request *req) 371{ 372 struct crypto_aead *tfm = crypto_aead_reqtfm(req); 373 struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 374 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 375 struct chacha_req *creq = &rctx->u.chacha; 376 int err; 377 378 rctx->assoclen = req->assoclen; 379 380 if (crypto_aead_ivsize(tfm) == 8) { 381 if (rctx->assoclen < 8) 382 return -EINVAL; 383 rctx->assoclen -= 8; 384 } 385 386 sg_init_table(creq->src, 1); 387 memset(rctx->key, 0, sizeof(rctx->key)); 388 sg_set_buf(creq->src, rctx->key, sizeof(rctx->key)); 389 390 chacha_iv(creq->iv, req, 0); 391 392 ablkcipher_request_set_callback(&creq->req, aead_request_flags(req), 393 poly_genkey_done, req); 394 ablkcipher_request_set_tfm(&creq->req, ctx->chacha); 395 ablkcipher_request_set_crypt(&creq->req, creq->src, creq->src, 396 POLY1305_KEY_SIZE, creq->iv); 397 398 err = crypto_ablkcipher_decrypt(&creq->req); 399 if (err) 400 return err; 401 402 return poly_init(req); 403} 404 405static void chacha_encrypt_done(struct crypto_async_request *areq, int err) 406{ 407 async_done_continue(areq->data, err, poly_genkey); 408} 409 410static int chacha_encrypt(struct aead_request *req) 411{ 412 struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 413 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 414 struct chacha_req *creq = &rctx->u.chacha; 415 struct scatterlist *src, *dst; 416 int err; 417 418 chacha_iv(creq->iv, req, 1); 419 420 sg_init_table(rctx->src, 2); 421 src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen); 422 dst = src; 423 424 if (req->src != req->dst) { 425 sg_init_table(rctx->dst, 2); 426 dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen); 427 } 428 429 ablkcipher_request_set_callback(&creq->req, aead_request_flags(req), 430 chacha_encrypt_done, req); 431 ablkcipher_request_set_tfm(&creq->req, ctx->chacha); 432 ablkcipher_request_set_crypt(&creq->req, src, dst, 433 req->cryptlen, creq->iv); 434 err = crypto_ablkcipher_encrypt(&creq->req); 435 if (err) 436 return err; 437 438 return poly_genkey(req); 439} 440 441static int chachapoly_encrypt(struct aead_request *req) 442{ 443 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 444 445 rctx->cryptlen = req->cryptlen; 446 447 /* encrypt call chain: 448 * - chacha_encrypt/done() 449 * - poly_genkey/done() 450 * - poly_init/done() 451 * - poly_setkey/done() 452 * - poly_ad/done() 453 * - poly_adpad/done() 454 * - poly_cipher/done() 455 * - poly_cipherpad/done() 456 * - poly_tail/done/continue() 457 * - poly_copy_tag() 458 */ 459 return chacha_encrypt(req); 460} 461 462static int chachapoly_decrypt(struct aead_request *req) 463{ 464 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 465 466 rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE; 467 468 /* decrypt call chain: 469 * - poly_genkey/done() 470 * - poly_init/done() 471 * - poly_setkey/done() 472 * - poly_ad/done() 473 * - poly_adpad/done() 474 * - poly_cipher/done() 475 * - poly_cipherpad/done() 476 * - poly_tail/done/continue() 477 * - chacha_decrypt/done() 478 * - poly_verify_tag() 479 */ 480 return poly_genkey(req); 481} 482 483static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key, 484 unsigned int keylen) 485{ 486 struct chachapoly_ctx *ctx = crypto_aead_ctx(aead); 487 int err; 488 489 if (keylen != ctx->saltlen + CHACHA20_KEY_SIZE) 490 return -EINVAL; 491 492 keylen -= ctx->saltlen; 493 memcpy(ctx->salt, key + keylen, ctx->saltlen); 494 495 crypto_ablkcipher_clear_flags(ctx->chacha, CRYPTO_TFM_REQ_MASK); 496 crypto_ablkcipher_set_flags(ctx->chacha, crypto_aead_get_flags(aead) & 497 CRYPTO_TFM_REQ_MASK); 498 499 err = crypto_ablkcipher_setkey(ctx->chacha, key, keylen); 500 crypto_aead_set_flags(aead, crypto_ablkcipher_get_flags(ctx->chacha) & 501 CRYPTO_TFM_RES_MASK); 502 return err; 503} 504 505static int chachapoly_setauthsize(struct crypto_aead *tfm, 506 unsigned int authsize) 507{ 508 if (authsize != POLY1305_DIGEST_SIZE) 509 return -EINVAL; 510 511 return 0; 512} 513 514static int chachapoly_init(struct crypto_aead *tfm) 515{ 516 struct aead_instance *inst = aead_alg_instance(tfm); 517 struct chachapoly_instance_ctx *ictx = aead_instance_ctx(inst); 518 struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 519 struct crypto_ablkcipher *chacha; 520 struct crypto_ahash *poly; 521 unsigned long align; 522 523 poly = crypto_spawn_ahash(&ictx->poly); 524 if (IS_ERR(poly)) 525 return PTR_ERR(poly); 526 527 chacha = crypto_spawn_skcipher(&ictx->chacha); 528 if (IS_ERR(chacha)) { 529 crypto_free_ahash(poly); 530 return PTR_ERR(chacha); 531 } 532 533 ctx->chacha = chacha; 534 ctx->poly = poly; 535 ctx->saltlen = ictx->saltlen; 536 537 align = crypto_aead_alignmask(tfm); 538 align &= ~(crypto_tfm_ctx_alignment() - 1); 539 crypto_aead_set_reqsize( 540 tfm, 541 align + offsetof(struct chachapoly_req_ctx, u) + 542 max(offsetof(struct chacha_req, req) + 543 sizeof(struct ablkcipher_request) + 544 crypto_ablkcipher_reqsize(chacha), 545 offsetof(struct poly_req, req) + 546 sizeof(struct ahash_request) + 547 crypto_ahash_reqsize(poly))); 548 549 return 0; 550} 551 552static void chachapoly_exit(struct crypto_aead *tfm) 553{ 554 struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 555 556 crypto_free_ahash(ctx->poly); 557 crypto_free_ablkcipher(ctx->chacha); 558} 559 560static void chachapoly_free(struct aead_instance *inst) 561{ 562 struct chachapoly_instance_ctx *ctx = aead_instance_ctx(inst); 563 564 crypto_drop_skcipher(&ctx->chacha); 565 crypto_drop_ahash(&ctx->poly); 566 kfree(inst); 567} 568 569static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, 570 const char *name, unsigned int ivsize) 571{ 572 struct crypto_attr_type *algt; 573 struct aead_instance *inst; 574 struct crypto_alg *chacha; 575 struct crypto_alg *poly; 576 struct hash_alg_common *poly_hash; 577 struct chachapoly_instance_ctx *ctx; 578 const char *chacha_name, *poly_name; 579 int err; 580 581 if (ivsize > CHACHAPOLY_IV_SIZE) 582 return -EINVAL; 583 584 algt = crypto_get_attr_type(tb); 585 if (IS_ERR(algt)) 586 return PTR_ERR(algt); 587 588 if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) 589 return -EINVAL; 590 591 chacha_name = crypto_attr_alg_name(tb[1]); 592 if (IS_ERR(chacha_name)) 593 return PTR_ERR(chacha_name); 594 poly_name = crypto_attr_alg_name(tb[2]); 595 if (IS_ERR(poly_name)) 596 return PTR_ERR(poly_name); 597 598 poly = crypto_find_alg(poly_name, &crypto_ahash_type, 599 CRYPTO_ALG_TYPE_HASH, 600 CRYPTO_ALG_TYPE_AHASH_MASK); 601 if (IS_ERR(poly)) 602 return PTR_ERR(poly); 603 604 err = -ENOMEM; 605 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 606 if (!inst) 607 goto out_put_poly; 608 609 ctx = aead_instance_ctx(inst); 610 ctx->saltlen = CHACHAPOLY_IV_SIZE - ivsize; 611 poly_hash = __crypto_hash_alg_common(poly); 612 err = crypto_init_ahash_spawn(&ctx->poly, poly_hash, 613 aead_crypto_instance(inst)); 614 if (err) 615 goto err_free_inst; 616 617 crypto_set_skcipher_spawn(&ctx->chacha, aead_crypto_instance(inst)); 618 err = crypto_grab_skcipher(&ctx->chacha, chacha_name, 0, 619 crypto_requires_sync(algt->type, 620 algt->mask)); 621 if (err) 622 goto err_drop_poly; 623 624 chacha = crypto_skcipher_spawn_alg(&ctx->chacha); 625 626 err = -EINVAL; 627 /* Need 16-byte IV size, including Initial Block Counter value */ 628 if (chacha->cra_ablkcipher.ivsize != CHACHA20_IV_SIZE) 629 goto out_drop_chacha; 630 /* Not a stream cipher? */ 631 if (chacha->cra_blocksize != 1) 632 goto out_drop_chacha; 633 634 err = -ENAMETOOLONG; 635 if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 636 "%s(%s,%s)", name, chacha_name, 637 poly_name) >= CRYPTO_MAX_ALG_NAME) 638 goto out_drop_chacha; 639 if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 640 "%s(%s,%s)", name, chacha->cra_driver_name, 641 poly->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 642 goto out_drop_chacha; 643 644 inst->alg.base.cra_flags = (chacha->cra_flags | poly->cra_flags) & 645 CRYPTO_ALG_ASYNC; 646 inst->alg.base.cra_priority = (chacha->cra_priority + 647 poly->cra_priority) / 2; 648 inst->alg.base.cra_blocksize = 1; 649 inst->alg.base.cra_alignmask = chacha->cra_alignmask | 650 poly->cra_alignmask; 651 inst->alg.base.cra_ctxsize = sizeof(struct chachapoly_ctx) + 652 ctx->saltlen; 653 inst->alg.ivsize = ivsize; 654 inst->alg.maxauthsize = POLY1305_DIGEST_SIZE; 655 inst->alg.init = chachapoly_init; 656 inst->alg.exit = chachapoly_exit; 657 inst->alg.encrypt = chachapoly_encrypt; 658 inst->alg.decrypt = chachapoly_decrypt; 659 inst->alg.setkey = chachapoly_setkey; 660 inst->alg.setauthsize = chachapoly_setauthsize; 661 662 inst->free = chachapoly_free; 663 664 err = aead_register_instance(tmpl, inst); 665 if (err) 666 goto out_drop_chacha; 667 668out_put_poly: 669 crypto_mod_put(poly); 670 return err; 671 672out_drop_chacha: 673 crypto_drop_skcipher(&ctx->chacha); 674err_drop_poly: 675 crypto_drop_ahash(&ctx->poly); 676err_free_inst: 677 kfree(inst); 678 goto out_put_poly; 679} 680 681static int rfc7539_create(struct crypto_template *tmpl, struct rtattr **tb) 682{ 683 return chachapoly_create(tmpl, tb, "rfc7539", 12); 684} 685 686static int rfc7539esp_create(struct crypto_template *tmpl, struct rtattr **tb) 687{ 688 return chachapoly_create(tmpl, tb, "rfc7539esp", 8); 689} 690 691static struct crypto_template rfc7539_tmpl = { 692 .name = "rfc7539", 693 .create = rfc7539_create, 694 .module = THIS_MODULE, 695}; 696 697static struct crypto_template rfc7539esp_tmpl = { 698 .name = "rfc7539esp", 699 .create = rfc7539esp_create, 700 .module = THIS_MODULE, 701}; 702 703static int __init chacha20poly1305_module_init(void) 704{ 705 int err; 706 707 err = crypto_register_template(&rfc7539_tmpl); 708 if (err) 709 return err; 710 711 err = crypto_register_template(&rfc7539esp_tmpl); 712 if (err) 713 crypto_unregister_template(&rfc7539_tmpl); 714 715 return err; 716} 717 718static void __exit chacha20poly1305_module_exit(void) 719{ 720 crypto_unregister_template(&rfc7539esp_tmpl); 721 crypto_unregister_template(&rfc7539_tmpl); 722} 723 724module_init(chacha20poly1305_module_init); 725module_exit(chacha20poly1305_module_exit); 726 727MODULE_LICENSE("GPL"); 728MODULE_AUTHOR("Martin Willi <martin@strongswan.org>"); 729MODULE_DESCRIPTION("ChaCha20-Poly1305 AEAD"); 730MODULE_ALIAS_CRYPTO("rfc7539"); 731MODULE_ALIAS_CRYPTO("rfc7539esp"); 732