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