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