Back to home page

LXR

 
 

    


0001 /*
0002  * ChaCha20-Poly1305 AEAD, RFC7539
0003  *
0004  * Copyright (C) 2015 Martin Willi
0005  *
0006  * This program is free software; you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License as published by
0008  * the Free Software Foundation; either version 2 of the License, or
0009  * (at your option) any later version.
0010  */
0011 
0012 #include <crypto/internal/aead.h>
0013 #include <crypto/internal/hash.h>
0014 #include <crypto/internal/skcipher.h>
0015 #include <crypto/scatterwalk.h>
0016 #include <crypto/chacha20.h>
0017 #include <crypto/poly1305.h>
0018 #include <linux/err.h>
0019 #include <linux/init.h>
0020 #include <linux/kernel.h>
0021 #include <linux/module.h>
0022 
0023 #include "internal.h"
0024 
0025 #define CHACHAPOLY_IV_SIZE  12
0026 
0027 struct chachapoly_instance_ctx {
0028     struct crypto_skcipher_spawn chacha;
0029     struct crypto_ahash_spawn poly;
0030     unsigned int saltlen;
0031 };
0032 
0033 struct chachapoly_ctx {
0034     struct crypto_skcipher *chacha;
0035     struct crypto_ahash *poly;
0036     /* key bytes we use for the ChaCha20 IV */
0037     unsigned int saltlen;
0038     u8 salt[];
0039 };
0040 
0041 struct poly_req {
0042     /* zero byte padding for AD/ciphertext, as needed */
0043     u8 pad[POLY1305_BLOCK_SIZE];
0044     /* tail data with AD/ciphertext lengths */
0045     struct {
0046         __le64 assoclen;
0047         __le64 cryptlen;
0048     } tail;
0049     struct scatterlist src[1];
0050     struct ahash_request req; /* must be last member */
0051 };
0052 
0053 struct chacha_req {
0054     u8 iv[CHACHA20_IV_SIZE];
0055     struct scatterlist src[1];
0056     struct skcipher_request req; /* must be last member */
0057 };
0058 
0059 struct chachapoly_req_ctx {
0060     struct scatterlist src[2];
0061     struct scatterlist dst[2];
0062     /* the key we generate for Poly1305 using Chacha20 */
0063     u8 key[POLY1305_KEY_SIZE];
0064     /* calculated Poly1305 tag */
0065     u8 tag[POLY1305_DIGEST_SIZE];
0066     /* length of data to en/decrypt, without ICV */
0067     unsigned int cryptlen;
0068     /* Actual AD, excluding IV */
0069     unsigned int assoclen;
0070     union {
0071         struct poly_req poly;
0072         struct chacha_req chacha;
0073     } u;
0074 };
0075 
0076 static inline void async_done_continue(struct aead_request *req, int err,
0077                        int (*cont)(struct aead_request *))
0078 {
0079     if (!err)
0080         err = cont(req);
0081 
0082     if (err != -EINPROGRESS && err != -EBUSY)
0083         aead_request_complete(req, err);
0084 }
0085 
0086 static void chacha_iv(u8 *iv, struct aead_request *req, u32 icb)
0087 {
0088     struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
0089     __le32 leicb = cpu_to_le32(icb);
0090 
0091     memcpy(iv, &leicb, sizeof(leicb));
0092     memcpy(iv + sizeof(leicb), ctx->salt, ctx->saltlen);
0093     memcpy(iv + sizeof(leicb) + ctx->saltlen, req->iv,
0094            CHACHA20_IV_SIZE - sizeof(leicb) - ctx->saltlen);
0095 }
0096 
0097 static int poly_verify_tag(struct aead_request *req)
0098 {
0099     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0100     u8 tag[sizeof(rctx->tag)];
0101 
0102     scatterwalk_map_and_copy(tag, req->src,
0103                  req->assoclen + rctx->cryptlen,
0104                  sizeof(tag), 0);
0105     if (crypto_memneq(tag, rctx->tag, sizeof(tag)))
0106         return -EBADMSG;
0107     return 0;
0108 }
0109 
0110 static int poly_copy_tag(struct aead_request *req)
0111 {
0112     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0113 
0114     scatterwalk_map_and_copy(rctx->tag, req->dst,
0115                  req->assoclen + rctx->cryptlen,
0116                  sizeof(rctx->tag), 1);
0117     return 0;
0118 }
0119 
0120 static void chacha_decrypt_done(struct crypto_async_request *areq, int err)
0121 {
0122     async_done_continue(areq->data, err, poly_verify_tag);
0123 }
0124 
0125 static int chacha_decrypt(struct aead_request *req)
0126 {
0127     struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
0128     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0129     struct chacha_req *creq = &rctx->u.chacha;
0130     struct scatterlist *src, *dst;
0131     int err;
0132 
0133     if (rctx->cryptlen == 0)
0134         goto skip;
0135 
0136     chacha_iv(creq->iv, req, 1);
0137 
0138     sg_init_table(rctx->src, 2);
0139     src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen);
0140     dst = src;
0141 
0142     if (req->src != req->dst) {
0143         sg_init_table(rctx->dst, 2);
0144         dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen);
0145     }
0146 
0147     skcipher_request_set_callback(&creq->req, aead_request_flags(req),
0148                       chacha_decrypt_done, req);
0149     skcipher_request_set_tfm(&creq->req, ctx->chacha);
0150     skcipher_request_set_crypt(&creq->req, src, dst,
0151                    rctx->cryptlen, creq->iv);
0152     err = crypto_skcipher_decrypt(&creq->req);
0153     if (err)
0154         return err;
0155 
0156 skip:
0157     return poly_verify_tag(req);
0158 }
0159 
0160 static int poly_tail_continue(struct aead_request *req)
0161 {
0162     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0163 
0164     if (rctx->cryptlen == req->cryptlen) /* encrypting */
0165         return poly_copy_tag(req);
0166 
0167     return chacha_decrypt(req);
0168 }
0169 
0170 static void poly_tail_done(struct crypto_async_request *areq, int err)
0171 {
0172     async_done_continue(areq->data, err, poly_tail_continue);
0173 }
0174 
0175 static int poly_tail(struct aead_request *req)
0176 {
0177     struct crypto_aead *tfm = crypto_aead_reqtfm(req);
0178     struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
0179     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0180     struct poly_req *preq = &rctx->u.poly;
0181     __le64 len;
0182     int err;
0183 
0184     sg_init_table(preq->src, 1);
0185     len = cpu_to_le64(rctx->assoclen);
0186     memcpy(&preq->tail.assoclen, &len, sizeof(len));
0187     len = cpu_to_le64(rctx->cryptlen);
0188     memcpy(&preq->tail.cryptlen, &len, sizeof(len));
0189     sg_set_buf(preq->src, &preq->tail, sizeof(preq->tail));
0190 
0191     ahash_request_set_callback(&preq->req, aead_request_flags(req),
0192                    poly_tail_done, req);
0193     ahash_request_set_tfm(&preq->req, ctx->poly);
0194     ahash_request_set_crypt(&preq->req, preq->src,
0195                 rctx->tag, sizeof(preq->tail));
0196 
0197     err = crypto_ahash_finup(&preq->req);
0198     if (err)
0199         return err;
0200 
0201     return poly_tail_continue(req);
0202 }
0203 
0204 static void poly_cipherpad_done(struct crypto_async_request *areq, int err)
0205 {
0206     async_done_continue(areq->data, err, poly_tail);
0207 }
0208 
0209 static int poly_cipherpad(struct aead_request *req)
0210 {
0211     struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
0212     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0213     struct poly_req *preq = &rctx->u.poly;
0214     unsigned int padlen, bs = POLY1305_BLOCK_SIZE;
0215     int err;
0216 
0217     padlen = (bs - (rctx->cryptlen % bs)) % bs;
0218     memset(preq->pad, 0, sizeof(preq->pad));
0219     sg_init_table(preq->src, 1);
0220     sg_set_buf(preq->src, &preq->pad, padlen);
0221 
0222     ahash_request_set_callback(&preq->req, aead_request_flags(req),
0223                    poly_cipherpad_done, req);
0224     ahash_request_set_tfm(&preq->req, ctx->poly);
0225     ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen);
0226 
0227     err = crypto_ahash_update(&preq->req);
0228     if (err)
0229         return err;
0230 
0231     return poly_tail(req);
0232 }
0233 
0234 static void poly_cipher_done(struct crypto_async_request *areq, int err)
0235 {
0236     async_done_continue(areq->data, err, poly_cipherpad);
0237 }
0238 
0239 static int poly_cipher(struct aead_request *req)
0240 {
0241     struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
0242     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0243     struct poly_req *preq = &rctx->u.poly;
0244     struct scatterlist *crypt = req->src;
0245     int err;
0246 
0247     if (rctx->cryptlen == req->cryptlen) /* encrypting */
0248         crypt = req->dst;
0249 
0250     sg_init_table(rctx->src, 2);
0251     crypt = scatterwalk_ffwd(rctx->src, crypt, req->assoclen);
0252 
0253     ahash_request_set_callback(&preq->req, aead_request_flags(req),
0254                    poly_cipher_done, req);
0255     ahash_request_set_tfm(&preq->req, ctx->poly);
0256     ahash_request_set_crypt(&preq->req, crypt, NULL, rctx->cryptlen);
0257 
0258     err = crypto_ahash_update(&preq->req);
0259     if (err)
0260         return err;
0261 
0262     return poly_cipherpad(req);
0263 }
0264 
0265 static void poly_adpad_done(struct crypto_async_request *areq, int err)
0266 {
0267     async_done_continue(areq->data, err, poly_cipher);
0268 }
0269 
0270 static int poly_adpad(struct aead_request *req)
0271 {
0272     struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
0273     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0274     struct poly_req *preq = &rctx->u.poly;
0275     unsigned int padlen, bs = POLY1305_BLOCK_SIZE;
0276     int err;
0277 
0278     padlen = (bs - (rctx->assoclen % bs)) % bs;
0279     memset(preq->pad, 0, sizeof(preq->pad));
0280     sg_init_table(preq->src, 1);
0281     sg_set_buf(preq->src, preq->pad, padlen);
0282 
0283     ahash_request_set_callback(&preq->req, aead_request_flags(req),
0284                    poly_adpad_done, req);
0285     ahash_request_set_tfm(&preq->req, ctx->poly);
0286     ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen);
0287 
0288     err = crypto_ahash_update(&preq->req);
0289     if (err)
0290         return err;
0291 
0292     return poly_cipher(req);
0293 }
0294 
0295 static void poly_ad_done(struct crypto_async_request *areq, int err)
0296 {
0297     async_done_continue(areq->data, err, poly_adpad);
0298 }
0299 
0300 static int poly_ad(struct aead_request *req)
0301 {
0302     struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
0303     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0304     struct poly_req *preq = &rctx->u.poly;
0305     int err;
0306 
0307     ahash_request_set_callback(&preq->req, aead_request_flags(req),
0308                    poly_ad_done, req);
0309     ahash_request_set_tfm(&preq->req, ctx->poly);
0310     ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen);
0311 
0312     err = crypto_ahash_update(&preq->req);
0313     if (err)
0314         return err;
0315 
0316     return poly_adpad(req);
0317 }
0318 
0319 static void poly_setkey_done(struct crypto_async_request *areq, int err)
0320 {
0321     async_done_continue(areq->data, err, poly_ad);
0322 }
0323 
0324 static int poly_setkey(struct aead_request *req)
0325 {
0326     struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
0327     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0328     struct poly_req *preq = &rctx->u.poly;
0329     int err;
0330 
0331     sg_init_table(preq->src, 1);
0332     sg_set_buf(preq->src, rctx->key, sizeof(rctx->key));
0333 
0334     ahash_request_set_callback(&preq->req, aead_request_flags(req),
0335                    poly_setkey_done, req);
0336     ahash_request_set_tfm(&preq->req, ctx->poly);
0337     ahash_request_set_crypt(&preq->req, preq->src, NULL, sizeof(rctx->key));
0338 
0339     err = crypto_ahash_update(&preq->req);
0340     if (err)
0341         return err;
0342 
0343     return poly_ad(req);
0344 }
0345 
0346 static void poly_init_done(struct crypto_async_request *areq, int err)
0347 {
0348     async_done_continue(areq->data, err, poly_setkey);
0349 }
0350 
0351 static int poly_init(struct aead_request *req)
0352 {
0353     struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
0354     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0355     struct poly_req *preq = &rctx->u.poly;
0356     int err;
0357 
0358     ahash_request_set_callback(&preq->req, aead_request_flags(req),
0359                    poly_init_done, req);
0360     ahash_request_set_tfm(&preq->req, ctx->poly);
0361 
0362     err = crypto_ahash_init(&preq->req);
0363     if (err)
0364         return err;
0365 
0366     return poly_setkey(req);
0367 }
0368 
0369 static void poly_genkey_done(struct crypto_async_request *areq, int err)
0370 {
0371     async_done_continue(areq->data, err, poly_init);
0372 }
0373 
0374 static int poly_genkey(struct aead_request *req)
0375 {
0376     struct crypto_aead *tfm = crypto_aead_reqtfm(req);
0377     struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
0378     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0379     struct chacha_req *creq = &rctx->u.chacha;
0380     int err;
0381 
0382     rctx->assoclen = req->assoclen;
0383 
0384     if (crypto_aead_ivsize(tfm) == 8) {
0385         if (rctx->assoclen < 8)
0386             return -EINVAL;
0387         rctx->assoclen -= 8;
0388     }
0389 
0390     sg_init_table(creq->src, 1);
0391     memset(rctx->key, 0, sizeof(rctx->key));
0392     sg_set_buf(creq->src, rctx->key, sizeof(rctx->key));
0393 
0394     chacha_iv(creq->iv, req, 0);
0395 
0396     skcipher_request_set_callback(&creq->req, aead_request_flags(req),
0397                       poly_genkey_done, req);
0398     skcipher_request_set_tfm(&creq->req, ctx->chacha);
0399     skcipher_request_set_crypt(&creq->req, creq->src, creq->src,
0400                    POLY1305_KEY_SIZE, creq->iv);
0401 
0402     err = crypto_skcipher_decrypt(&creq->req);
0403     if (err)
0404         return err;
0405 
0406     return poly_init(req);
0407 }
0408 
0409 static void chacha_encrypt_done(struct crypto_async_request *areq, int err)
0410 {
0411     async_done_continue(areq->data, err, poly_genkey);
0412 }
0413 
0414 static int chacha_encrypt(struct aead_request *req)
0415 {
0416     struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
0417     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0418     struct chacha_req *creq = &rctx->u.chacha;
0419     struct scatterlist *src, *dst;
0420     int err;
0421 
0422     if (req->cryptlen == 0)
0423         goto skip;
0424 
0425     chacha_iv(creq->iv, req, 1);
0426 
0427     sg_init_table(rctx->src, 2);
0428     src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen);
0429     dst = src;
0430 
0431     if (req->src != req->dst) {
0432         sg_init_table(rctx->dst, 2);
0433         dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen);
0434     }
0435 
0436     skcipher_request_set_callback(&creq->req, aead_request_flags(req),
0437                       chacha_encrypt_done, req);
0438     skcipher_request_set_tfm(&creq->req, ctx->chacha);
0439     skcipher_request_set_crypt(&creq->req, src, dst,
0440                    req->cryptlen, creq->iv);
0441     err = crypto_skcipher_encrypt(&creq->req);
0442     if (err)
0443         return err;
0444 
0445 skip:
0446     return poly_genkey(req);
0447 }
0448 
0449 static int chachapoly_encrypt(struct aead_request *req)
0450 {
0451     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0452 
0453     rctx->cryptlen = req->cryptlen;
0454 
0455     /* encrypt call chain:
0456      * - chacha_encrypt/done()
0457      * - poly_genkey/done()
0458      * - poly_init/done()
0459      * - poly_setkey/done()
0460      * - poly_ad/done()
0461      * - poly_adpad/done()
0462      * - poly_cipher/done()
0463      * - poly_cipherpad/done()
0464      * - poly_tail/done/continue()
0465      * - poly_copy_tag()
0466      */
0467     return chacha_encrypt(req);
0468 }
0469 
0470 static int chachapoly_decrypt(struct aead_request *req)
0471 {
0472     struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
0473 
0474     rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE;
0475 
0476     /* decrypt call chain:
0477      * - poly_genkey/done()
0478      * - poly_init/done()
0479      * - poly_setkey/done()
0480      * - poly_ad/done()
0481      * - poly_adpad/done()
0482      * - poly_cipher/done()
0483      * - poly_cipherpad/done()
0484      * - poly_tail/done/continue()
0485      * - chacha_decrypt/done()
0486      * - poly_verify_tag()
0487      */
0488     return poly_genkey(req);
0489 }
0490 
0491 static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
0492                  unsigned int keylen)
0493 {
0494     struct chachapoly_ctx *ctx = crypto_aead_ctx(aead);
0495     int err;
0496 
0497     if (keylen != ctx->saltlen + CHACHA20_KEY_SIZE)
0498         return -EINVAL;
0499 
0500     keylen -= ctx->saltlen;
0501     memcpy(ctx->salt, key + keylen, ctx->saltlen);
0502 
0503     crypto_skcipher_clear_flags(ctx->chacha, CRYPTO_TFM_REQ_MASK);
0504     crypto_skcipher_set_flags(ctx->chacha, crypto_aead_get_flags(aead) &
0505                            CRYPTO_TFM_REQ_MASK);
0506 
0507     err = crypto_skcipher_setkey(ctx->chacha, key, keylen);
0508     crypto_aead_set_flags(aead, crypto_skcipher_get_flags(ctx->chacha) &
0509                     CRYPTO_TFM_RES_MASK);
0510     return err;
0511 }
0512 
0513 static int chachapoly_setauthsize(struct crypto_aead *tfm,
0514                   unsigned int authsize)
0515 {
0516     if (authsize != POLY1305_DIGEST_SIZE)
0517         return -EINVAL;
0518 
0519     return 0;
0520 }
0521 
0522 static int chachapoly_init(struct crypto_aead *tfm)
0523 {
0524     struct aead_instance *inst = aead_alg_instance(tfm);
0525     struct chachapoly_instance_ctx *ictx = aead_instance_ctx(inst);
0526     struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
0527     struct crypto_skcipher *chacha;
0528     struct crypto_ahash *poly;
0529     unsigned long align;
0530 
0531     poly = crypto_spawn_ahash(&ictx->poly);
0532     if (IS_ERR(poly))
0533         return PTR_ERR(poly);
0534 
0535     chacha = crypto_spawn_skcipher(&ictx->chacha);
0536     if (IS_ERR(chacha)) {
0537         crypto_free_ahash(poly);
0538         return PTR_ERR(chacha);
0539     }
0540 
0541     ctx->chacha = chacha;
0542     ctx->poly = poly;
0543     ctx->saltlen = ictx->saltlen;
0544 
0545     align = crypto_aead_alignmask(tfm);
0546     align &= ~(crypto_tfm_ctx_alignment() - 1);
0547     crypto_aead_set_reqsize(
0548         tfm,
0549         align + offsetof(struct chachapoly_req_ctx, u) +
0550         max(offsetof(struct chacha_req, req) +
0551             sizeof(struct skcipher_request) +
0552             crypto_skcipher_reqsize(chacha),
0553             offsetof(struct poly_req, req) +
0554             sizeof(struct ahash_request) +
0555             crypto_ahash_reqsize(poly)));
0556 
0557     return 0;
0558 }
0559 
0560 static void chachapoly_exit(struct crypto_aead *tfm)
0561 {
0562     struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
0563 
0564     crypto_free_ahash(ctx->poly);
0565     crypto_free_skcipher(ctx->chacha);
0566 }
0567 
0568 static void chachapoly_free(struct aead_instance *inst)
0569 {
0570     struct chachapoly_instance_ctx *ctx = aead_instance_ctx(inst);
0571 
0572     crypto_drop_skcipher(&ctx->chacha);
0573     crypto_drop_ahash(&ctx->poly);
0574     kfree(inst);
0575 }
0576 
0577 static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
0578                  const char *name, unsigned int ivsize)
0579 {
0580     struct crypto_attr_type *algt;
0581     struct aead_instance *inst;
0582     struct skcipher_alg *chacha;
0583     struct crypto_alg *poly;
0584     struct hash_alg_common *poly_hash;
0585     struct chachapoly_instance_ctx *ctx;
0586     const char *chacha_name, *poly_name;
0587     int err;
0588 
0589     if (ivsize > CHACHAPOLY_IV_SIZE)
0590         return -EINVAL;
0591 
0592     algt = crypto_get_attr_type(tb);
0593     if (IS_ERR(algt))
0594         return PTR_ERR(algt);
0595 
0596     if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
0597         return -EINVAL;
0598 
0599     chacha_name = crypto_attr_alg_name(tb[1]);
0600     if (IS_ERR(chacha_name))
0601         return PTR_ERR(chacha_name);
0602     poly_name = crypto_attr_alg_name(tb[2]);
0603     if (IS_ERR(poly_name))
0604         return PTR_ERR(poly_name);
0605 
0606     poly = crypto_find_alg(poly_name, &crypto_ahash_type,
0607                    CRYPTO_ALG_TYPE_HASH,
0608                    CRYPTO_ALG_TYPE_AHASH_MASK |
0609                    crypto_requires_sync(algt->type,
0610                             algt->mask));
0611     if (IS_ERR(poly))
0612         return PTR_ERR(poly);
0613 
0614     err = -ENOMEM;
0615     inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
0616     if (!inst)
0617         goto out_put_poly;
0618 
0619     ctx = aead_instance_ctx(inst);
0620     ctx->saltlen = CHACHAPOLY_IV_SIZE - ivsize;
0621     poly_hash = __crypto_hash_alg_common(poly);
0622     err = crypto_init_ahash_spawn(&ctx->poly, poly_hash,
0623                       aead_crypto_instance(inst));
0624     if (err)
0625         goto err_free_inst;
0626 
0627     crypto_set_skcipher_spawn(&ctx->chacha, aead_crypto_instance(inst));
0628     err = crypto_grab_skcipher(&ctx->chacha, chacha_name, 0,
0629                    crypto_requires_sync(algt->type,
0630                             algt->mask));
0631     if (err)
0632         goto err_drop_poly;
0633 
0634     chacha = crypto_spawn_skcipher_alg(&ctx->chacha);
0635 
0636     err = -EINVAL;
0637     /* Need 16-byte IV size, including Initial Block Counter value */
0638     if (crypto_skcipher_alg_ivsize(chacha) != CHACHA20_IV_SIZE)
0639         goto out_drop_chacha;
0640     /* Not a stream cipher? */
0641     if (chacha->base.cra_blocksize != 1)
0642         goto out_drop_chacha;
0643 
0644     err = -ENAMETOOLONG;
0645     if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
0646              "%s(%s,%s)", name, chacha_name,
0647              poly_name) >= CRYPTO_MAX_ALG_NAME)
0648         goto out_drop_chacha;
0649     if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
0650              "%s(%s,%s)", name, chacha->base.cra_driver_name,
0651              poly->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
0652         goto out_drop_chacha;
0653 
0654     inst->alg.base.cra_flags = (chacha->base.cra_flags | poly->cra_flags) &
0655                    CRYPTO_ALG_ASYNC;
0656     inst->alg.base.cra_priority = (chacha->base.cra_priority +
0657                        poly->cra_priority) / 2;
0658     inst->alg.base.cra_blocksize = 1;
0659     inst->alg.base.cra_alignmask = chacha->base.cra_alignmask |
0660                        poly->cra_alignmask;
0661     inst->alg.base.cra_ctxsize = sizeof(struct chachapoly_ctx) +
0662                      ctx->saltlen;
0663     inst->alg.ivsize = ivsize;
0664     inst->alg.chunksize = crypto_skcipher_alg_chunksize(chacha);
0665     inst->alg.maxauthsize = POLY1305_DIGEST_SIZE;
0666     inst->alg.init = chachapoly_init;
0667     inst->alg.exit = chachapoly_exit;
0668     inst->alg.encrypt = chachapoly_encrypt;
0669     inst->alg.decrypt = chachapoly_decrypt;
0670     inst->alg.setkey = chachapoly_setkey;
0671     inst->alg.setauthsize = chachapoly_setauthsize;
0672 
0673     inst->free = chachapoly_free;
0674 
0675     err = aead_register_instance(tmpl, inst);
0676     if (err)
0677         goto out_drop_chacha;
0678 
0679 out_put_poly:
0680     crypto_mod_put(poly);
0681     return err;
0682 
0683 out_drop_chacha:
0684     crypto_drop_skcipher(&ctx->chacha);
0685 err_drop_poly:
0686     crypto_drop_ahash(&ctx->poly);
0687 err_free_inst:
0688     kfree(inst);
0689     goto out_put_poly;
0690 }
0691 
0692 static int rfc7539_create(struct crypto_template *tmpl, struct rtattr **tb)
0693 {
0694     return chachapoly_create(tmpl, tb, "rfc7539", 12);
0695 }
0696 
0697 static int rfc7539esp_create(struct crypto_template *tmpl, struct rtattr **tb)
0698 {
0699     return chachapoly_create(tmpl, tb, "rfc7539esp", 8);
0700 }
0701 
0702 static struct crypto_template rfc7539_tmpl = {
0703     .name = "rfc7539",
0704     .create = rfc7539_create,
0705     .module = THIS_MODULE,
0706 };
0707 
0708 static struct crypto_template rfc7539esp_tmpl = {
0709     .name = "rfc7539esp",
0710     .create = rfc7539esp_create,
0711     .module = THIS_MODULE,
0712 };
0713 
0714 static int __init chacha20poly1305_module_init(void)
0715 {
0716     int err;
0717 
0718     err = crypto_register_template(&rfc7539_tmpl);
0719     if (err)
0720         return err;
0721 
0722     err = crypto_register_template(&rfc7539esp_tmpl);
0723     if (err)
0724         crypto_unregister_template(&rfc7539_tmpl);
0725 
0726     return err;
0727 }
0728 
0729 static void __exit chacha20poly1305_module_exit(void)
0730 {
0731     crypto_unregister_template(&rfc7539esp_tmpl);
0732     crypto_unregister_template(&rfc7539_tmpl);
0733 }
0734 
0735 module_init(chacha20poly1305_module_init);
0736 module_exit(chacha20poly1305_module_exit);
0737 
0738 MODULE_LICENSE("GPL");
0739 MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");
0740 MODULE_DESCRIPTION("ChaCha20-Poly1305 AEAD");
0741 MODULE_ALIAS_CRYPTO("rfc7539");
0742 MODULE_ALIAS_CRYPTO("rfc7539esp");