171ebc4d1SMartin Willi /* 271ebc4d1SMartin Willi * ChaCha20-Poly1305 AEAD, RFC7539 371ebc4d1SMartin Willi * 471ebc4d1SMartin Willi * Copyright (C) 2015 Martin Willi 571ebc4d1SMartin Willi * 671ebc4d1SMartin Willi * This program is free software; you can redistribute it and/or modify 771ebc4d1SMartin Willi * it under the terms of the GNU General Public License as published by 871ebc4d1SMartin Willi * the Free Software Foundation; either version 2 of the License, or 971ebc4d1SMartin Willi * (at your option) any later version. 1071ebc4d1SMartin Willi */ 1171ebc4d1SMartin Willi 1271ebc4d1SMartin Willi #include <crypto/internal/aead.h> 1371ebc4d1SMartin Willi #include <crypto/internal/hash.h> 1471ebc4d1SMartin Willi #include <crypto/internal/skcipher.h> 1571ebc4d1SMartin Willi #include <crypto/scatterwalk.h> 1671ebc4d1SMartin Willi #include <linux/err.h> 1771ebc4d1SMartin Willi #include <linux/init.h> 1871ebc4d1SMartin Willi #include <linux/kernel.h> 1971ebc4d1SMartin Willi #include <linux/module.h> 2071ebc4d1SMartin Willi 2171ebc4d1SMartin Willi #include "internal.h" 2271ebc4d1SMartin Willi 2371ebc4d1SMartin Willi #define POLY1305_BLOCK_SIZE 16 2471ebc4d1SMartin Willi #define POLY1305_DIGEST_SIZE 16 2571ebc4d1SMartin Willi #define POLY1305_KEY_SIZE 32 2671ebc4d1SMartin Willi #define CHACHA20_KEY_SIZE 32 2771ebc4d1SMartin Willi #define CHACHA20_IV_SIZE 16 2871ebc4d1SMartin Willi #define CHACHAPOLY_IV_SIZE 12 2971ebc4d1SMartin Willi 3071ebc4d1SMartin Willi struct chachapoly_instance_ctx { 3171ebc4d1SMartin Willi struct crypto_skcipher_spawn chacha; 3271ebc4d1SMartin Willi struct crypto_ahash_spawn poly; 3371ebc4d1SMartin Willi unsigned int saltlen; 3471ebc4d1SMartin Willi }; 3571ebc4d1SMartin Willi 3671ebc4d1SMartin Willi struct chachapoly_ctx { 3771ebc4d1SMartin Willi struct crypto_ablkcipher *chacha; 3871ebc4d1SMartin Willi struct crypto_ahash *poly; 3971ebc4d1SMartin Willi /* key bytes we use for the ChaCha20 IV */ 4071ebc4d1SMartin Willi unsigned int saltlen; 4171ebc4d1SMartin Willi u8 salt[]; 4271ebc4d1SMartin Willi }; 4371ebc4d1SMartin Willi 4471ebc4d1SMartin Willi struct poly_req { 4571ebc4d1SMartin Willi /* zero byte padding for AD/ciphertext, as needed */ 4671ebc4d1SMartin Willi u8 pad[POLY1305_BLOCK_SIZE]; 4771ebc4d1SMartin Willi /* tail data with AD/ciphertext lengths */ 4871ebc4d1SMartin Willi struct { 4971ebc4d1SMartin Willi __le64 assoclen; 5071ebc4d1SMartin Willi __le64 cryptlen; 5171ebc4d1SMartin Willi } tail; 5271ebc4d1SMartin Willi struct scatterlist src[1]; 5371ebc4d1SMartin Willi struct ahash_request req; /* must be last member */ 5471ebc4d1SMartin Willi }; 5571ebc4d1SMartin Willi 5671ebc4d1SMartin Willi struct chacha_req { 5771ebc4d1SMartin Willi u8 iv[CHACHA20_IV_SIZE]; 5871ebc4d1SMartin Willi struct scatterlist src[1]; 5971ebc4d1SMartin Willi struct ablkcipher_request req; /* must be last member */ 6071ebc4d1SMartin Willi }; 6171ebc4d1SMartin Willi 6271ebc4d1SMartin Willi struct chachapoly_req_ctx { 6374790922SHerbert Xu struct scatterlist src[2]; 6474790922SHerbert Xu struct scatterlist dst[2]; 65c2b7b20aSMartin Willi /* the key we generate for Poly1305 using Chacha20 */ 66c2b7b20aSMartin Willi u8 key[POLY1305_KEY_SIZE]; 6771ebc4d1SMartin Willi /* calculated Poly1305 tag */ 6871ebc4d1SMartin Willi u8 tag[POLY1305_DIGEST_SIZE]; 6971ebc4d1SMartin Willi /* length of data to en/decrypt, without ICV */ 7071ebc4d1SMartin Willi unsigned int cryptlen; 7174790922SHerbert Xu /* Actual AD, excluding IV */ 7274790922SHerbert Xu unsigned int assoclen; 7371ebc4d1SMartin Willi union { 7471ebc4d1SMartin Willi struct poly_req poly; 7571ebc4d1SMartin Willi struct chacha_req chacha; 7671ebc4d1SMartin Willi } u; 7771ebc4d1SMartin Willi }; 7871ebc4d1SMartin Willi 7971ebc4d1SMartin Willi static inline void async_done_continue(struct aead_request *req, int err, 8071ebc4d1SMartin Willi int (*cont)(struct aead_request *)) 8171ebc4d1SMartin Willi { 8271ebc4d1SMartin Willi if (!err) 8371ebc4d1SMartin Willi err = cont(req); 8471ebc4d1SMartin Willi 8571ebc4d1SMartin Willi if (err != -EINPROGRESS && err != -EBUSY) 8671ebc4d1SMartin Willi aead_request_complete(req, err); 8771ebc4d1SMartin Willi } 8871ebc4d1SMartin Willi 8971ebc4d1SMartin Willi static void chacha_iv(u8 *iv, struct aead_request *req, u32 icb) 9071ebc4d1SMartin Willi { 9171ebc4d1SMartin Willi struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 9271ebc4d1SMartin Willi __le32 leicb = cpu_to_le32(icb); 9371ebc4d1SMartin Willi 9471ebc4d1SMartin Willi memcpy(iv, &leicb, sizeof(leicb)); 9571ebc4d1SMartin Willi memcpy(iv + sizeof(leicb), ctx->salt, ctx->saltlen); 9671ebc4d1SMartin Willi memcpy(iv + sizeof(leicb) + ctx->saltlen, req->iv, 9771ebc4d1SMartin Willi CHACHA20_IV_SIZE - sizeof(leicb) - ctx->saltlen); 9871ebc4d1SMartin Willi } 9971ebc4d1SMartin Willi 10071ebc4d1SMartin Willi static int poly_verify_tag(struct aead_request *req) 10171ebc4d1SMartin Willi { 10271ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 10371ebc4d1SMartin Willi u8 tag[sizeof(rctx->tag)]; 10471ebc4d1SMartin Willi 10574790922SHerbert Xu scatterwalk_map_and_copy(tag, req->src, 10674790922SHerbert Xu req->assoclen + rctx->cryptlen, 10774790922SHerbert Xu sizeof(tag), 0); 10871ebc4d1SMartin Willi if (crypto_memneq(tag, rctx->tag, sizeof(tag))) 10971ebc4d1SMartin Willi return -EBADMSG; 11071ebc4d1SMartin Willi return 0; 11171ebc4d1SMartin Willi } 11271ebc4d1SMartin Willi 11371ebc4d1SMartin Willi static int poly_copy_tag(struct aead_request *req) 11471ebc4d1SMartin Willi { 11571ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 11671ebc4d1SMartin Willi 11774790922SHerbert Xu scatterwalk_map_and_copy(rctx->tag, req->dst, 11874790922SHerbert Xu req->assoclen + rctx->cryptlen, 11971ebc4d1SMartin Willi sizeof(rctx->tag), 1); 12071ebc4d1SMartin Willi return 0; 12171ebc4d1SMartin Willi } 12271ebc4d1SMartin Willi 12371ebc4d1SMartin Willi static void chacha_decrypt_done(struct crypto_async_request *areq, int err) 12471ebc4d1SMartin Willi { 12571ebc4d1SMartin Willi async_done_continue(areq->data, err, poly_verify_tag); 12671ebc4d1SMartin Willi } 12771ebc4d1SMartin Willi 12871ebc4d1SMartin Willi static int chacha_decrypt(struct aead_request *req) 12971ebc4d1SMartin Willi { 13071ebc4d1SMartin Willi struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 13171ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 13271ebc4d1SMartin Willi struct chacha_req *creq = &rctx->u.chacha; 13374790922SHerbert Xu struct scatterlist *src, *dst; 13471ebc4d1SMartin Willi int err; 13571ebc4d1SMartin Willi 13671ebc4d1SMartin Willi chacha_iv(creq->iv, req, 1); 13771ebc4d1SMartin Willi 13874790922SHerbert Xu sg_init_table(rctx->src, 2); 13974790922SHerbert Xu src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen); 14074790922SHerbert Xu dst = src; 14174790922SHerbert Xu 14274790922SHerbert Xu if (req->src != req->dst) { 14374790922SHerbert Xu sg_init_table(rctx->dst, 2); 14474790922SHerbert Xu dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen); 14574790922SHerbert Xu } 14674790922SHerbert Xu 14771ebc4d1SMartin Willi ablkcipher_request_set_callback(&creq->req, aead_request_flags(req), 14871ebc4d1SMartin Willi chacha_decrypt_done, req); 14971ebc4d1SMartin Willi ablkcipher_request_set_tfm(&creq->req, ctx->chacha); 15074790922SHerbert Xu ablkcipher_request_set_crypt(&creq->req, src, dst, 15171ebc4d1SMartin Willi rctx->cryptlen, creq->iv); 15271ebc4d1SMartin Willi err = crypto_ablkcipher_decrypt(&creq->req); 15371ebc4d1SMartin Willi if (err) 15471ebc4d1SMartin Willi return err; 15571ebc4d1SMartin Willi 15671ebc4d1SMartin Willi return poly_verify_tag(req); 15771ebc4d1SMartin Willi } 15871ebc4d1SMartin Willi 15971ebc4d1SMartin Willi static int poly_tail_continue(struct aead_request *req) 16071ebc4d1SMartin Willi { 16171ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 16271ebc4d1SMartin Willi 16371ebc4d1SMartin Willi if (rctx->cryptlen == req->cryptlen) /* encrypting */ 16471ebc4d1SMartin Willi return poly_copy_tag(req); 16571ebc4d1SMartin Willi 16671ebc4d1SMartin Willi return chacha_decrypt(req); 16771ebc4d1SMartin Willi } 16871ebc4d1SMartin Willi 16971ebc4d1SMartin Willi static void poly_tail_done(struct crypto_async_request *areq, int err) 17071ebc4d1SMartin Willi { 17171ebc4d1SMartin Willi async_done_continue(areq->data, err, poly_tail_continue); 17271ebc4d1SMartin Willi } 17371ebc4d1SMartin Willi 17471ebc4d1SMartin Willi static int poly_tail(struct aead_request *req) 17571ebc4d1SMartin Willi { 17674790922SHerbert Xu struct crypto_aead *tfm = crypto_aead_reqtfm(req); 17774790922SHerbert Xu struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 17871ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 17971ebc4d1SMartin Willi struct poly_req *preq = &rctx->u.poly; 18071ebc4d1SMartin Willi __le64 len; 18171ebc4d1SMartin Willi int err; 18271ebc4d1SMartin Willi 18371ebc4d1SMartin Willi sg_init_table(preq->src, 1); 18474790922SHerbert Xu len = cpu_to_le64(rctx->assoclen); 18571ebc4d1SMartin Willi memcpy(&preq->tail.assoclen, &len, sizeof(len)); 18671ebc4d1SMartin Willi len = cpu_to_le64(rctx->cryptlen); 18771ebc4d1SMartin Willi memcpy(&preq->tail.cryptlen, &len, sizeof(len)); 18871ebc4d1SMartin Willi sg_set_buf(preq->src, &preq->tail, sizeof(preq->tail)); 18971ebc4d1SMartin Willi 19071ebc4d1SMartin Willi ahash_request_set_callback(&preq->req, aead_request_flags(req), 19171ebc4d1SMartin Willi poly_tail_done, req); 19271ebc4d1SMartin Willi ahash_request_set_tfm(&preq->req, ctx->poly); 19371ebc4d1SMartin Willi ahash_request_set_crypt(&preq->req, preq->src, 19471ebc4d1SMartin Willi rctx->tag, sizeof(preq->tail)); 19571ebc4d1SMartin Willi 19671ebc4d1SMartin Willi err = crypto_ahash_finup(&preq->req); 19771ebc4d1SMartin Willi if (err) 19871ebc4d1SMartin Willi return err; 19971ebc4d1SMartin Willi 20071ebc4d1SMartin Willi return poly_tail_continue(req); 20171ebc4d1SMartin Willi } 20271ebc4d1SMartin Willi 20371ebc4d1SMartin Willi static void poly_cipherpad_done(struct crypto_async_request *areq, int err) 20471ebc4d1SMartin Willi { 20571ebc4d1SMartin Willi async_done_continue(areq->data, err, poly_tail); 20671ebc4d1SMartin Willi } 20771ebc4d1SMartin Willi 20871ebc4d1SMartin Willi static int poly_cipherpad(struct aead_request *req) 20971ebc4d1SMartin Willi { 21071ebc4d1SMartin Willi struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 21171ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 21271ebc4d1SMartin Willi struct poly_req *preq = &rctx->u.poly; 21371ebc4d1SMartin Willi unsigned int padlen, bs = POLY1305_BLOCK_SIZE; 21471ebc4d1SMartin Willi int err; 21571ebc4d1SMartin Willi 21671ebc4d1SMartin Willi padlen = (bs - (rctx->cryptlen % bs)) % bs; 21771ebc4d1SMartin Willi memset(preq->pad, 0, sizeof(preq->pad)); 21871ebc4d1SMartin Willi sg_init_table(preq->src, 1); 21971ebc4d1SMartin Willi sg_set_buf(preq->src, &preq->pad, padlen); 22071ebc4d1SMartin Willi 22171ebc4d1SMartin Willi ahash_request_set_callback(&preq->req, aead_request_flags(req), 22271ebc4d1SMartin Willi poly_cipherpad_done, req); 22371ebc4d1SMartin Willi ahash_request_set_tfm(&preq->req, ctx->poly); 22471ebc4d1SMartin Willi ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); 22571ebc4d1SMartin Willi 22671ebc4d1SMartin Willi err = crypto_ahash_update(&preq->req); 22771ebc4d1SMartin Willi if (err) 22871ebc4d1SMartin Willi return err; 22971ebc4d1SMartin Willi 23071ebc4d1SMartin Willi return poly_tail(req); 23171ebc4d1SMartin Willi } 23271ebc4d1SMartin Willi 23371ebc4d1SMartin Willi static void poly_cipher_done(struct crypto_async_request *areq, int err) 23471ebc4d1SMartin Willi { 23571ebc4d1SMartin Willi async_done_continue(areq->data, err, poly_cipherpad); 23671ebc4d1SMartin Willi } 23771ebc4d1SMartin Willi 23871ebc4d1SMartin Willi static int poly_cipher(struct aead_request *req) 23971ebc4d1SMartin Willi { 24071ebc4d1SMartin Willi struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 24171ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 24271ebc4d1SMartin Willi struct poly_req *preq = &rctx->u.poly; 24371ebc4d1SMartin Willi struct scatterlist *crypt = req->src; 24471ebc4d1SMartin Willi int err; 24571ebc4d1SMartin Willi 24671ebc4d1SMartin Willi if (rctx->cryptlen == req->cryptlen) /* encrypting */ 24771ebc4d1SMartin Willi crypt = req->dst; 24871ebc4d1SMartin Willi 24974790922SHerbert Xu sg_init_table(rctx->src, 2); 25074790922SHerbert Xu crypt = scatterwalk_ffwd(rctx->src, crypt, req->assoclen); 25174790922SHerbert Xu 25271ebc4d1SMartin Willi ahash_request_set_callback(&preq->req, aead_request_flags(req), 25371ebc4d1SMartin Willi poly_cipher_done, req); 25471ebc4d1SMartin Willi ahash_request_set_tfm(&preq->req, ctx->poly); 25571ebc4d1SMartin Willi ahash_request_set_crypt(&preq->req, crypt, NULL, rctx->cryptlen); 25671ebc4d1SMartin Willi 25771ebc4d1SMartin Willi err = crypto_ahash_update(&preq->req); 25871ebc4d1SMartin Willi if (err) 25971ebc4d1SMartin Willi return err; 26071ebc4d1SMartin Willi 26171ebc4d1SMartin Willi return poly_cipherpad(req); 26271ebc4d1SMartin Willi } 26371ebc4d1SMartin Willi 26471ebc4d1SMartin Willi static void poly_adpad_done(struct crypto_async_request *areq, int err) 26571ebc4d1SMartin Willi { 26671ebc4d1SMartin Willi async_done_continue(areq->data, err, poly_cipher); 26771ebc4d1SMartin Willi } 26871ebc4d1SMartin Willi 26971ebc4d1SMartin Willi static int poly_adpad(struct aead_request *req) 27071ebc4d1SMartin Willi { 27171ebc4d1SMartin Willi struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 27271ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 27371ebc4d1SMartin Willi struct poly_req *preq = &rctx->u.poly; 27471ebc4d1SMartin Willi unsigned int padlen, bs = POLY1305_BLOCK_SIZE; 27571ebc4d1SMartin Willi int err; 27671ebc4d1SMartin Willi 27774790922SHerbert Xu padlen = (bs - (rctx->assoclen % bs)) % bs; 27871ebc4d1SMartin Willi memset(preq->pad, 0, sizeof(preq->pad)); 27971ebc4d1SMartin Willi sg_init_table(preq->src, 1); 28071ebc4d1SMartin Willi sg_set_buf(preq->src, preq->pad, padlen); 28171ebc4d1SMartin Willi 28271ebc4d1SMartin Willi ahash_request_set_callback(&preq->req, aead_request_flags(req), 28371ebc4d1SMartin Willi poly_adpad_done, req); 28471ebc4d1SMartin Willi ahash_request_set_tfm(&preq->req, ctx->poly); 28571ebc4d1SMartin Willi ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); 28671ebc4d1SMartin Willi 28771ebc4d1SMartin Willi err = crypto_ahash_update(&preq->req); 28871ebc4d1SMartin Willi if (err) 28971ebc4d1SMartin Willi return err; 29071ebc4d1SMartin Willi 29171ebc4d1SMartin Willi return poly_cipher(req); 29271ebc4d1SMartin Willi } 29371ebc4d1SMartin Willi 29471ebc4d1SMartin Willi static void poly_ad_done(struct crypto_async_request *areq, int err) 29571ebc4d1SMartin Willi { 29671ebc4d1SMartin Willi async_done_continue(areq->data, err, poly_adpad); 29771ebc4d1SMartin Willi } 29871ebc4d1SMartin Willi 29971ebc4d1SMartin Willi static int poly_ad(struct aead_request *req) 30071ebc4d1SMartin Willi { 30171ebc4d1SMartin Willi struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 30271ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 30371ebc4d1SMartin Willi struct poly_req *preq = &rctx->u.poly; 30471ebc4d1SMartin Willi int err; 30571ebc4d1SMartin Willi 30671ebc4d1SMartin Willi ahash_request_set_callback(&preq->req, aead_request_flags(req), 30771ebc4d1SMartin Willi poly_ad_done, req); 30871ebc4d1SMartin Willi ahash_request_set_tfm(&preq->req, ctx->poly); 30974790922SHerbert Xu ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen); 31071ebc4d1SMartin Willi 31171ebc4d1SMartin Willi err = crypto_ahash_update(&preq->req); 31271ebc4d1SMartin Willi if (err) 31371ebc4d1SMartin Willi return err; 31471ebc4d1SMartin Willi 31571ebc4d1SMartin Willi return poly_adpad(req); 31671ebc4d1SMartin Willi } 31771ebc4d1SMartin Willi 318c2b7b20aSMartin Willi static void poly_setkey_done(struct crypto_async_request *areq, int err) 31971ebc4d1SMartin Willi { 32071ebc4d1SMartin Willi async_done_continue(areq->data, err, poly_ad); 32171ebc4d1SMartin Willi } 32271ebc4d1SMartin Willi 323c2b7b20aSMartin Willi static int poly_setkey(struct aead_request *req) 324c2b7b20aSMartin Willi { 325c2b7b20aSMartin Willi struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 326c2b7b20aSMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 327c2b7b20aSMartin Willi struct poly_req *preq = &rctx->u.poly; 328c2b7b20aSMartin Willi int err; 329c2b7b20aSMartin Willi 330c2b7b20aSMartin Willi sg_init_table(preq->src, 1); 331c2b7b20aSMartin Willi sg_set_buf(preq->src, rctx->key, sizeof(rctx->key)); 332c2b7b20aSMartin Willi 333c2b7b20aSMartin Willi ahash_request_set_callback(&preq->req, aead_request_flags(req), 334c2b7b20aSMartin Willi poly_setkey_done, req); 335c2b7b20aSMartin Willi ahash_request_set_tfm(&preq->req, ctx->poly); 336c2b7b20aSMartin Willi ahash_request_set_crypt(&preq->req, preq->src, NULL, sizeof(rctx->key)); 337c2b7b20aSMartin Willi 338c2b7b20aSMartin Willi err = crypto_ahash_update(&preq->req); 339c2b7b20aSMartin Willi if (err) 340c2b7b20aSMartin Willi return err; 341c2b7b20aSMartin Willi 342c2b7b20aSMartin Willi return poly_ad(req); 343c2b7b20aSMartin Willi } 344c2b7b20aSMartin Willi 345c2b7b20aSMartin Willi static void poly_init_done(struct crypto_async_request *areq, int err) 346c2b7b20aSMartin Willi { 347c2b7b20aSMartin Willi async_done_continue(areq->data, err, poly_setkey); 348c2b7b20aSMartin Willi } 349c2b7b20aSMartin Willi 35071ebc4d1SMartin Willi static int poly_init(struct aead_request *req) 35171ebc4d1SMartin Willi { 35271ebc4d1SMartin Willi struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 35371ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 35471ebc4d1SMartin Willi struct poly_req *preq = &rctx->u.poly; 35571ebc4d1SMartin Willi int err; 35671ebc4d1SMartin Willi 35771ebc4d1SMartin Willi ahash_request_set_callback(&preq->req, aead_request_flags(req), 35871ebc4d1SMartin Willi poly_init_done, req); 35971ebc4d1SMartin Willi ahash_request_set_tfm(&preq->req, ctx->poly); 36071ebc4d1SMartin Willi 36171ebc4d1SMartin Willi err = crypto_ahash_init(&preq->req); 36271ebc4d1SMartin Willi if (err) 36371ebc4d1SMartin Willi return err; 36471ebc4d1SMartin Willi 365c2b7b20aSMartin Willi return poly_setkey(req); 36671ebc4d1SMartin Willi } 36771ebc4d1SMartin Willi 36871ebc4d1SMartin Willi static void poly_genkey_done(struct crypto_async_request *areq, int err) 36971ebc4d1SMartin Willi { 370c2b7b20aSMartin Willi async_done_continue(areq->data, err, poly_init); 37171ebc4d1SMartin Willi } 37271ebc4d1SMartin Willi 37371ebc4d1SMartin Willi static int poly_genkey(struct aead_request *req) 37471ebc4d1SMartin Willi { 37574790922SHerbert Xu struct crypto_aead *tfm = crypto_aead_reqtfm(req); 37674790922SHerbert Xu struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 37771ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 37871ebc4d1SMartin Willi struct chacha_req *creq = &rctx->u.chacha; 37971ebc4d1SMartin Willi int err; 38071ebc4d1SMartin Willi 38174790922SHerbert Xu rctx->assoclen = req->assoclen; 38274790922SHerbert Xu 38374790922SHerbert Xu if (crypto_aead_ivsize(tfm) == 8) { 38474790922SHerbert Xu if (rctx->assoclen < 8) 38574790922SHerbert Xu return -EINVAL; 38674790922SHerbert Xu rctx->assoclen -= 8; 38774790922SHerbert Xu } 38874790922SHerbert Xu 38971ebc4d1SMartin Willi sg_init_table(creq->src, 1); 390c2b7b20aSMartin Willi memset(rctx->key, 0, sizeof(rctx->key)); 391c2b7b20aSMartin Willi sg_set_buf(creq->src, rctx->key, sizeof(rctx->key)); 39271ebc4d1SMartin Willi 39371ebc4d1SMartin Willi chacha_iv(creq->iv, req, 0); 39471ebc4d1SMartin Willi 39571ebc4d1SMartin Willi ablkcipher_request_set_callback(&creq->req, aead_request_flags(req), 39671ebc4d1SMartin Willi poly_genkey_done, req); 39771ebc4d1SMartin Willi ablkcipher_request_set_tfm(&creq->req, ctx->chacha); 39871ebc4d1SMartin Willi ablkcipher_request_set_crypt(&creq->req, creq->src, creq->src, 39971ebc4d1SMartin Willi POLY1305_KEY_SIZE, creq->iv); 40071ebc4d1SMartin Willi 40171ebc4d1SMartin Willi err = crypto_ablkcipher_decrypt(&creq->req); 40271ebc4d1SMartin Willi if (err) 40371ebc4d1SMartin Willi return err; 40471ebc4d1SMartin Willi 405c2b7b20aSMartin Willi return poly_init(req); 40671ebc4d1SMartin Willi } 40771ebc4d1SMartin Willi 40871ebc4d1SMartin Willi static void chacha_encrypt_done(struct crypto_async_request *areq, int err) 40971ebc4d1SMartin Willi { 41071ebc4d1SMartin Willi async_done_continue(areq->data, err, poly_genkey); 41171ebc4d1SMartin Willi } 41271ebc4d1SMartin Willi 41371ebc4d1SMartin Willi static int chacha_encrypt(struct aead_request *req) 41471ebc4d1SMartin Willi { 41571ebc4d1SMartin Willi struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 41671ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 41771ebc4d1SMartin Willi struct chacha_req *creq = &rctx->u.chacha; 41874790922SHerbert Xu struct scatterlist *src, *dst; 41971ebc4d1SMartin Willi int err; 42071ebc4d1SMartin Willi 42171ebc4d1SMartin Willi chacha_iv(creq->iv, req, 1); 42271ebc4d1SMartin Willi 42374790922SHerbert Xu sg_init_table(rctx->src, 2); 42474790922SHerbert Xu src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen); 42574790922SHerbert Xu dst = src; 42674790922SHerbert Xu 42774790922SHerbert Xu if (req->src != req->dst) { 42874790922SHerbert Xu sg_init_table(rctx->dst, 2); 42974790922SHerbert Xu dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen); 43074790922SHerbert Xu } 43174790922SHerbert Xu 43271ebc4d1SMartin Willi ablkcipher_request_set_callback(&creq->req, aead_request_flags(req), 43371ebc4d1SMartin Willi chacha_encrypt_done, req); 43471ebc4d1SMartin Willi ablkcipher_request_set_tfm(&creq->req, ctx->chacha); 43574790922SHerbert Xu ablkcipher_request_set_crypt(&creq->req, src, dst, 43671ebc4d1SMartin Willi req->cryptlen, creq->iv); 43771ebc4d1SMartin Willi err = crypto_ablkcipher_encrypt(&creq->req); 43871ebc4d1SMartin Willi if (err) 43971ebc4d1SMartin Willi return err; 44071ebc4d1SMartin Willi 44171ebc4d1SMartin Willi return poly_genkey(req); 44271ebc4d1SMartin Willi } 44371ebc4d1SMartin Willi 44471ebc4d1SMartin Willi static int chachapoly_encrypt(struct aead_request *req) 44571ebc4d1SMartin Willi { 44671ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 44771ebc4d1SMartin Willi 44871ebc4d1SMartin Willi rctx->cryptlen = req->cryptlen; 44971ebc4d1SMartin Willi 45071ebc4d1SMartin Willi /* encrypt call chain: 45171ebc4d1SMartin Willi * - chacha_encrypt/done() 452c2b7b20aSMartin Willi * - poly_genkey/done() 45371ebc4d1SMartin Willi * - poly_init/done() 454c2b7b20aSMartin Willi * - poly_setkey/done() 45571ebc4d1SMartin Willi * - poly_ad/done() 45671ebc4d1SMartin Willi * - poly_adpad/done() 45771ebc4d1SMartin Willi * - poly_cipher/done() 45871ebc4d1SMartin Willi * - poly_cipherpad/done() 45971ebc4d1SMartin Willi * - poly_tail/done/continue() 46071ebc4d1SMartin Willi * - poly_copy_tag() 46171ebc4d1SMartin Willi */ 46271ebc4d1SMartin Willi return chacha_encrypt(req); 46371ebc4d1SMartin Willi } 46471ebc4d1SMartin Willi 46571ebc4d1SMartin Willi static int chachapoly_decrypt(struct aead_request *req) 46671ebc4d1SMartin Willi { 46771ebc4d1SMartin Willi struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 46871ebc4d1SMartin Willi 46971ebc4d1SMartin Willi rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE; 47071ebc4d1SMartin Willi 47171ebc4d1SMartin Willi /* decrypt call chain: 472c2b7b20aSMartin Willi * - poly_genkey/done() 47371ebc4d1SMartin Willi * - poly_init/done() 474c2b7b20aSMartin Willi * - poly_setkey/done() 47571ebc4d1SMartin Willi * - poly_ad/done() 47671ebc4d1SMartin Willi * - poly_adpad/done() 47771ebc4d1SMartin Willi * - poly_cipher/done() 47871ebc4d1SMartin Willi * - poly_cipherpad/done() 47971ebc4d1SMartin Willi * - poly_tail/done/continue() 48071ebc4d1SMartin Willi * - chacha_decrypt/done() 48171ebc4d1SMartin Willi * - poly_verify_tag() 48271ebc4d1SMartin Willi */ 48371ebc4d1SMartin Willi return poly_genkey(req); 48471ebc4d1SMartin Willi } 48571ebc4d1SMartin Willi 48671ebc4d1SMartin Willi static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key, 48771ebc4d1SMartin Willi unsigned int keylen) 48871ebc4d1SMartin Willi { 48971ebc4d1SMartin Willi struct chachapoly_ctx *ctx = crypto_aead_ctx(aead); 49071ebc4d1SMartin Willi int err; 49171ebc4d1SMartin Willi 49271ebc4d1SMartin Willi if (keylen != ctx->saltlen + CHACHA20_KEY_SIZE) 49371ebc4d1SMartin Willi return -EINVAL; 49471ebc4d1SMartin Willi 49571ebc4d1SMartin Willi keylen -= ctx->saltlen; 49671ebc4d1SMartin Willi memcpy(ctx->salt, key + keylen, ctx->saltlen); 49771ebc4d1SMartin Willi 49871ebc4d1SMartin Willi crypto_ablkcipher_clear_flags(ctx->chacha, CRYPTO_TFM_REQ_MASK); 49971ebc4d1SMartin Willi crypto_ablkcipher_set_flags(ctx->chacha, crypto_aead_get_flags(aead) & 50071ebc4d1SMartin Willi CRYPTO_TFM_REQ_MASK); 50171ebc4d1SMartin Willi 50271ebc4d1SMartin Willi err = crypto_ablkcipher_setkey(ctx->chacha, key, keylen); 50371ebc4d1SMartin Willi crypto_aead_set_flags(aead, crypto_ablkcipher_get_flags(ctx->chacha) & 50471ebc4d1SMartin Willi CRYPTO_TFM_RES_MASK); 50571ebc4d1SMartin Willi return err; 50671ebc4d1SMartin Willi } 50771ebc4d1SMartin Willi 50871ebc4d1SMartin Willi static int chachapoly_setauthsize(struct crypto_aead *tfm, 50971ebc4d1SMartin Willi unsigned int authsize) 51071ebc4d1SMartin Willi { 51171ebc4d1SMartin Willi if (authsize != POLY1305_DIGEST_SIZE) 51271ebc4d1SMartin Willi return -EINVAL; 51371ebc4d1SMartin Willi 51471ebc4d1SMartin Willi return 0; 51571ebc4d1SMartin Willi } 51671ebc4d1SMartin Willi 51774790922SHerbert Xu static int chachapoly_init(struct crypto_aead *tfm) 51871ebc4d1SMartin Willi { 51974790922SHerbert Xu struct aead_instance *inst = aead_alg_instance(tfm); 52074790922SHerbert Xu struct chachapoly_instance_ctx *ictx = aead_instance_ctx(inst); 52174790922SHerbert Xu struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 52271ebc4d1SMartin Willi struct crypto_ablkcipher *chacha; 52371ebc4d1SMartin Willi struct crypto_ahash *poly; 52471ebc4d1SMartin Willi unsigned long align; 52571ebc4d1SMartin Willi 52671ebc4d1SMartin Willi poly = crypto_spawn_ahash(&ictx->poly); 52771ebc4d1SMartin Willi if (IS_ERR(poly)) 52871ebc4d1SMartin Willi return PTR_ERR(poly); 52971ebc4d1SMartin Willi 53071ebc4d1SMartin Willi chacha = crypto_spawn_skcipher(&ictx->chacha); 53171ebc4d1SMartin Willi if (IS_ERR(chacha)) { 53271ebc4d1SMartin Willi crypto_free_ahash(poly); 53371ebc4d1SMartin Willi return PTR_ERR(chacha); 53471ebc4d1SMartin Willi } 53571ebc4d1SMartin Willi 53671ebc4d1SMartin Willi ctx->chacha = chacha; 53771ebc4d1SMartin Willi ctx->poly = poly; 53871ebc4d1SMartin Willi ctx->saltlen = ictx->saltlen; 53971ebc4d1SMartin Willi 54074790922SHerbert Xu align = crypto_aead_alignmask(tfm); 54171ebc4d1SMartin Willi align &= ~(crypto_tfm_ctx_alignment() - 1); 54274790922SHerbert Xu crypto_aead_set_reqsize( 54374790922SHerbert Xu tfm, 54471ebc4d1SMartin Willi align + offsetof(struct chachapoly_req_ctx, u) + 54571ebc4d1SMartin Willi max(offsetof(struct chacha_req, req) + 54671ebc4d1SMartin Willi sizeof(struct ablkcipher_request) + 54771ebc4d1SMartin Willi crypto_ablkcipher_reqsize(chacha), 54871ebc4d1SMartin Willi offsetof(struct poly_req, req) + 54971ebc4d1SMartin Willi sizeof(struct ahash_request) + 55071ebc4d1SMartin Willi crypto_ahash_reqsize(poly))); 55171ebc4d1SMartin Willi 55271ebc4d1SMartin Willi return 0; 55371ebc4d1SMartin Willi } 55471ebc4d1SMartin Willi 55574790922SHerbert Xu static void chachapoly_exit(struct crypto_aead *tfm) 55671ebc4d1SMartin Willi { 55774790922SHerbert Xu struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 55871ebc4d1SMartin Willi 55971ebc4d1SMartin Willi crypto_free_ahash(ctx->poly); 56071ebc4d1SMartin Willi crypto_free_ablkcipher(ctx->chacha); 56171ebc4d1SMartin Willi } 56271ebc4d1SMartin Willi 56374790922SHerbert Xu static void chachapoly_free(struct aead_instance *inst) 56474790922SHerbert Xu { 56574790922SHerbert Xu struct chachapoly_instance_ctx *ctx = aead_instance_ctx(inst); 56674790922SHerbert Xu 56774790922SHerbert Xu crypto_drop_skcipher(&ctx->chacha); 56874790922SHerbert Xu crypto_drop_ahash(&ctx->poly); 56974790922SHerbert Xu kfree(inst); 57074790922SHerbert Xu } 57174790922SHerbert Xu 57274790922SHerbert Xu static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, 57374790922SHerbert Xu const char *name, unsigned int ivsize) 57471ebc4d1SMartin Willi { 57571ebc4d1SMartin Willi struct crypto_attr_type *algt; 57674790922SHerbert Xu struct aead_instance *inst; 57771ebc4d1SMartin Willi struct crypto_alg *chacha; 57871ebc4d1SMartin Willi struct crypto_alg *poly; 57974790922SHerbert Xu struct hash_alg_common *poly_hash; 58071ebc4d1SMartin Willi struct chachapoly_instance_ctx *ctx; 58171ebc4d1SMartin Willi const char *chacha_name, *poly_name; 58271ebc4d1SMartin Willi int err; 58371ebc4d1SMartin Willi 58471ebc4d1SMartin Willi if (ivsize > CHACHAPOLY_IV_SIZE) 58574790922SHerbert Xu return -EINVAL; 58671ebc4d1SMartin Willi 58771ebc4d1SMartin Willi algt = crypto_get_attr_type(tb); 58871ebc4d1SMartin Willi if (IS_ERR(algt)) 58974790922SHerbert Xu return PTR_ERR(algt); 59071ebc4d1SMartin Willi 59174790922SHerbert Xu if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_AEAD_NEW)) & 59274790922SHerbert Xu algt->mask) 59374790922SHerbert Xu return -EINVAL; 59471ebc4d1SMartin Willi 59571ebc4d1SMartin Willi chacha_name = crypto_attr_alg_name(tb[1]); 59671ebc4d1SMartin Willi if (IS_ERR(chacha_name)) 59774790922SHerbert Xu return PTR_ERR(chacha_name); 59871ebc4d1SMartin Willi poly_name = crypto_attr_alg_name(tb[2]); 59971ebc4d1SMartin Willi if (IS_ERR(poly_name)) 60074790922SHerbert Xu return PTR_ERR(poly_name); 60171ebc4d1SMartin Willi 60271ebc4d1SMartin Willi poly = crypto_find_alg(poly_name, &crypto_ahash_type, 60371ebc4d1SMartin Willi CRYPTO_ALG_TYPE_HASH, 60471ebc4d1SMartin Willi CRYPTO_ALG_TYPE_AHASH_MASK); 60571ebc4d1SMartin Willi if (IS_ERR(poly)) 60674790922SHerbert Xu return PTR_ERR(poly); 60771ebc4d1SMartin Willi 60871ebc4d1SMartin Willi err = -ENOMEM; 60971ebc4d1SMartin Willi inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 61071ebc4d1SMartin Willi if (!inst) 61171ebc4d1SMartin Willi goto out_put_poly; 61271ebc4d1SMartin Willi 61374790922SHerbert Xu ctx = aead_instance_ctx(inst); 61471ebc4d1SMartin Willi ctx->saltlen = CHACHAPOLY_IV_SIZE - ivsize; 61574790922SHerbert Xu poly_hash = __crypto_hash_alg_common(poly); 61674790922SHerbert Xu err = crypto_init_ahash_spawn(&ctx->poly, poly_hash, 61774790922SHerbert Xu aead_crypto_instance(inst)); 61871ebc4d1SMartin Willi if (err) 61971ebc4d1SMartin Willi goto err_free_inst; 62071ebc4d1SMartin Willi 62174790922SHerbert Xu crypto_set_skcipher_spawn(&ctx->chacha, aead_crypto_instance(inst)); 62271ebc4d1SMartin Willi err = crypto_grab_skcipher(&ctx->chacha, chacha_name, 0, 62371ebc4d1SMartin Willi crypto_requires_sync(algt->type, 62471ebc4d1SMartin Willi algt->mask)); 62571ebc4d1SMartin Willi if (err) 62671ebc4d1SMartin Willi goto err_drop_poly; 62771ebc4d1SMartin Willi 62871ebc4d1SMartin Willi chacha = crypto_skcipher_spawn_alg(&ctx->chacha); 62971ebc4d1SMartin Willi 63071ebc4d1SMartin Willi err = -EINVAL; 63171ebc4d1SMartin Willi /* Need 16-byte IV size, including Initial Block Counter value */ 63271ebc4d1SMartin Willi if (chacha->cra_ablkcipher.ivsize != CHACHA20_IV_SIZE) 63371ebc4d1SMartin Willi goto out_drop_chacha; 63471ebc4d1SMartin Willi /* Not a stream cipher? */ 63571ebc4d1SMartin Willi if (chacha->cra_blocksize != 1) 63671ebc4d1SMartin Willi goto out_drop_chacha; 63771ebc4d1SMartin Willi 63871ebc4d1SMartin Willi err = -ENAMETOOLONG; 63974790922SHerbert Xu if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 64071ebc4d1SMartin Willi "%s(%s,%s)", name, chacha_name, 64171ebc4d1SMartin Willi poly_name) >= CRYPTO_MAX_ALG_NAME) 64271ebc4d1SMartin Willi goto out_drop_chacha; 64374790922SHerbert Xu if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 64471ebc4d1SMartin Willi "%s(%s,%s)", name, chacha->cra_driver_name, 64571ebc4d1SMartin Willi poly->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 64671ebc4d1SMartin Willi goto out_drop_chacha; 64771ebc4d1SMartin Willi 64874790922SHerbert Xu inst->alg.base.cra_flags = (chacha->cra_flags | poly->cra_flags) & 64974790922SHerbert Xu CRYPTO_ALG_ASYNC; 65074790922SHerbert Xu inst->alg.base.cra_flags |= CRYPTO_ALG_AEAD_NEW; 65174790922SHerbert Xu inst->alg.base.cra_priority = (chacha->cra_priority + 65271ebc4d1SMartin Willi poly->cra_priority) / 2; 65374790922SHerbert Xu inst->alg.base.cra_blocksize = 1; 65474790922SHerbert Xu inst->alg.base.cra_alignmask = chacha->cra_alignmask | 65574790922SHerbert Xu poly->cra_alignmask; 65674790922SHerbert Xu inst->alg.base.cra_ctxsize = sizeof(struct chachapoly_ctx) + 65774790922SHerbert Xu ctx->saltlen; 65874790922SHerbert Xu inst->alg.ivsize = ivsize; 65974790922SHerbert Xu inst->alg.maxauthsize = POLY1305_DIGEST_SIZE; 66074790922SHerbert Xu inst->alg.init = chachapoly_init; 66174790922SHerbert Xu inst->alg.exit = chachapoly_exit; 66274790922SHerbert Xu inst->alg.encrypt = chachapoly_encrypt; 66374790922SHerbert Xu inst->alg.decrypt = chachapoly_decrypt; 66474790922SHerbert Xu inst->alg.setkey = chachapoly_setkey; 66574790922SHerbert Xu inst->alg.setauthsize = chachapoly_setauthsize; 66671ebc4d1SMartin Willi 66774790922SHerbert Xu inst->free = chachapoly_free; 66874790922SHerbert Xu 66974790922SHerbert Xu err = aead_register_instance(tmpl, inst); 67074790922SHerbert Xu if (err) 67174790922SHerbert Xu goto out_drop_chacha; 67274790922SHerbert Xu 67374790922SHerbert Xu out_put_poly: 67471ebc4d1SMartin Willi crypto_mod_put(poly); 67574790922SHerbert Xu return err; 67671ebc4d1SMartin Willi 67771ebc4d1SMartin Willi out_drop_chacha: 67871ebc4d1SMartin Willi crypto_drop_skcipher(&ctx->chacha); 67971ebc4d1SMartin Willi err_drop_poly: 68071ebc4d1SMartin Willi crypto_drop_ahash(&ctx->poly); 68171ebc4d1SMartin Willi err_free_inst: 68271ebc4d1SMartin Willi kfree(inst); 68374790922SHerbert Xu goto out_put_poly; 68471ebc4d1SMartin Willi } 68571ebc4d1SMartin Willi 68674790922SHerbert Xu static int rfc7539_create(struct crypto_template *tmpl, struct rtattr **tb) 68771ebc4d1SMartin Willi { 68874790922SHerbert Xu return chachapoly_create(tmpl, tb, "rfc7539", 12); 68971ebc4d1SMartin Willi } 69071ebc4d1SMartin Willi 69174790922SHerbert Xu static int rfc7539esp_create(struct crypto_template *tmpl, struct rtattr **tb) 6924db4ad26SMartin Willi { 69374790922SHerbert Xu return chachapoly_create(tmpl, tb, "rfc7539esp", 8); 69471ebc4d1SMartin Willi } 69571ebc4d1SMartin Willi 69671ebc4d1SMartin Willi static struct crypto_template rfc7539_tmpl = { 69771ebc4d1SMartin Willi .name = "rfc7539", 69874790922SHerbert Xu .create = rfc7539_create, 69971ebc4d1SMartin Willi .module = THIS_MODULE, 70071ebc4d1SMartin Willi }; 70171ebc4d1SMartin Willi 7024db4ad26SMartin Willi static struct crypto_template rfc7539esp_tmpl = { 7034db4ad26SMartin Willi .name = "rfc7539esp", 70474790922SHerbert Xu .create = rfc7539esp_create, 7054db4ad26SMartin Willi .module = THIS_MODULE, 7064db4ad26SMartin Willi }; 7074db4ad26SMartin Willi 70871ebc4d1SMartin Willi static int __init chacha20poly1305_module_init(void) 70971ebc4d1SMartin Willi { 7104db4ad26SMartin Willi int err; 7114db4ad26SMartin Willi 7124db4ad26SMartin Willi err = crypto_register_template(&rfc7539_tmpl); 7134db4ad26SMartin Willi if (err) 7144db4ad26SMartin Willi return err; 7154db4ad26SMartin Willi 7164db4ad26SMartin Willi err = crypto_register_template(&rfc7539esp_tmpl); 7174db4ad26SMartin Willi if (err) 7184db4ad26SMartin Willi crypto_unregister_template(&rfc7539_tmpl); 7194db4ad26SMartin Willi 7204db4ad26SMartin Willi return err; 72171ebc4d1SMartin Willi } 72271ebc4d1SMartin Willi 72371ebc4d1SMartin Willi static void __exit chacha20poly1305_module_exit(void) 72471ebc4d1SMartin Willi { 7254db4ad26SMartin Willi crypto_unregister_template(&rfc7539esp_tmpl); 72671ebc4d1SMartin Willi crypto_unregister_template(&rfc7539_tmpl); 72771ebc4d1SMartin Willi } 72871ebc4d1SMartin Willi 72971ebc4d1SMartin Willi module_init(chacha20poly1305_module_init); 73071ebc4d1SMartin Willi module_exit(chacha20poly1305_module_exit); 73171ebc4d1SMartin Willi 73271ebc4d1SMartin Willi MODULE_LICENSE("GPL"); 73371ebc4d1SMartin Willi MODULE_AUTHOR("Martin Willi <martin@strongswan.org>"); 73471ebc4d1SMartin Willi MODULE_DESCRIPTION("ChaCha20-Poly1305 AEAD"); 73571ebc4d1SMartin Willi MODULE_ALIAS_CRYPTO("rfc7539"); 7364db4ad26SMartin Willi MODULE_ALIAS_CRYPTO("rfc7539esp"); 737