0001
0002
0003
0004
0005
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
0029 unsigned int saltlen;
0030 u8 salt[];
0031 };
0032
0033 struct poly_req {
0034
0035 u8 pad[POLY1305_BLOCK_SIZE];
0036
0037 struct {
0038 __le64 assoclen;
0039 __le64 cryptlen;
0040 } tail;
0041 struct scatterlist src[1];
0042 struct ahash_request req;
0043 };
0044
0045 struct chacha_req {
0046 u8 iv[CHACHA_IV_SIZE];
0047 struct scatterlist src[1];
0048 struct skcipher_request req;
0049 };
0050
0051 struct chachapoly_req_ctx {
0052 struct scatterlist src[2];
0053 struct scatterlist dst[2];
0054
0055 u8 key[POLY1305_KEY_SIZE];
0056
0057 u8 tag[POLY1305_DIGEST_SIZE];
0058
0059 unsigned int cryptlen;
0060
0061 unsigned int assoclen;
0062
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)
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)
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
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
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
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
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
0594 if (crypto_skcipher_alg_ivsize(chacha) != CHACHA_IV_SIZE)
0595 goto err_free_inst;
0596
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");