Back to home page

OSCL-LXR

 
 

    


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