18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * ChaCha20-Poly1305 AEAD, RFC7539 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Martin Willi 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h> 98c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h> 108c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 118c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 128c2ecf20Sopenharmony_ci#include <crypto/chacha.h> 138c2ecf20Sopenharmony_ci#include <crypto/poly1305.h> 148c2ecf20Sopenharmony_ci#include <linux/err.h> 158c2ecf20Sopenharmony_ci#include <linux/init.h> 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <linux/module.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistruct chachapoly_instance_ctx { 208c2ecf20Sopenharmony_ci struct crypto_skcipher_spawn chacha; 218c2ecf20Sopenharmony_ci struct crypto_ahash_spawn poly; 228c2ecf20Sopenharmony_ci unsigned int saltlen; 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct chachapoly_ctx { 268c2ecf20Sopenharmony_ci struct crypto_skcipher *chacha; 278c2ecf20Sopenharmony_ci struct crypto_ahash *poly; 288c2ecf20Sopenharmony_ci /* key bytes we use for the ChaCha20 IV */ 298c2ecf20Sopenharmony_ci unsigned int saltlen; 308c2ecf20Sopenharmony_ci u8 salt[]; 318c2ecf20Sopenharmony_ci}; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistruct poly_req { 348c2ecf20Sopenharmony_ci /* zero byte padding for AD/ciphertext, as needed */ 358c2ecf20Sopenharmony_ci u8 pad[POLY1305_BLOCK_SIZE]; 368c2ecf20Sopenharmony_ci /* tail data with AD/ciphertext lengths */ 378c2ecf20Sopenharmony_ci struct { 388c2ecf20Sopenharmony_ci __le64 assoclen; 398c2ecf20Sopenharmony_ci __le64 cryptlen; 408c2ecf20Sopenharmony_ci } tail; 418c2ecf20Sopenharmony_ci struct scatterlist src[1]; 428c2ecf20Sopenharmony_ci struct ahash_request req; /* must be last member */ 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct chacha_req { 468c2ecf20Sopenharmony_ci u8 iv[CHACHA_IV_SIZE]; 478c2ecf20Sopenharmony_ci struct scatterlist src[1]; 488c2ecf20Sopenharmony_ci struct skcipher_request req; /* must be last member */ 498c2ecf20Sopenharmony_ci}; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistruct chachapoly_req_ctx { 528c2ecf20Sopenharmony_ci struct scatterlist src[2]; 538c2ecf20Sopenharmony_ci struct scatterlist dst[2]; 548c2ecf20Sopenharmony_ci /* the key we generate for Poly1305 using Chacha20 */ 558c2ecf20Sopenharmony_ci u8 key[POLY1305_KEY_SIZE]; 568c2ecf20Sopenharmony_ci /* calculated Poly1305 tag */ 578c2ecf20Sopenharmony_ci u8 tag[POLY1305_DIGEST_SIZE]; 588c2ecf20Sopenharmony_ci /* length of data to en/decrypt, without ICV */ 598c2ecf20Sopenharmony_ci unsigned int cryptlen; 608c2ecf20Sopenharmony_ci /* Actual AD, excluding IV */ 618c2ecf20Sopenharmony_ci unsigned int assoclen; 628c2ecf20Sopenharmony_ci /* request flags, with MAY_SLEEP cleared if needed */ 638c2ecf20Sopenharmony_ci u32 flags; 648c2ecf20Sopenharmony_ci union { 658c2ecf20Sopenharmony_ci struct poly_req poly; 668c2ecf20Sopenharmony_ci struct chacha_req chacha; 678c2ecf20Sopenharmony_ci } u; 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic inline void async_done_continue(struct aead_request *req, int err, 718c2ecf20Sopenharmony_ci int (*cont)(struct aead_request *)) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci if (!err) { 748c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci rctx->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 778c2ecf20Sopenharmony_ci err = cont(req); 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci if (err != -EINPROGRESS && err != -EBUSY) 818c2ecf20Sopenharmony_ci aead_request_complete(req, err); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic void chacha_iv(u8 *iv, struct aead_request *req, u32 icb) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 878c2ecf20Sopenharmony_ci __le32 leicb = cpu_to_le32(icb); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci memcpy(iv, &leicb, sizeof(leicb)); 908c2ecf20Sopenharmony_ci memcpy(iv + sizeof(leicb), ctx->salt, ctx->saltlen); 918c2ecf20Sopenharmony_ci memcpy(iv + sizeof(leicb) + ctx->saltlen, req->iv, 928c2ecf20Sopenharmony_ci CHACHA_IV_SIZE - sizeof(leicb) - ctx->saltlen); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int poly_verify_tag(struct aead_request *req) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 988c2ecf20Sopenharmony_ci u8 tag[sizeof(rctx->tag)]; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(tag, req->src, 1018c2ecf20Sopenharmony_ci req->assoclen + rctx->cryptlen, 1028c2ecf20Sopenharmony_ci sizeof(tag), 0); 1038c2ecf20Sopenharmony_ci if (crypto_memneq(tag, rctx->tag, sizeof(tag))) 1048c2ecf20Sopenharmony_ci return -EBADMSG; 1058c2ecf20Sopenharmony_ci return 0; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic int poly_copy_tag(struct aead_request *req) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(rctx->tag, req->dst, 1138c2ecf20Sopenharmony_ci req->assoclen + rctx->cryptlen, 1148c2ecf20Sopenharmony_ci sizeof(rctx->tag), 1); 1158c2ecf20Sopenharmony_ci return 0; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic void chacha_decrypt_done(struct crypto_async_request *areq, int err) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci async_done_continue(areq->data, err, poly_verify_tag); 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic int chacha_decrypt(struct aead_request *req) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 1268c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 1278c2ecf20Sopenharmony_ci struct chacha_req *creq = &rctx->u.chacha; 1288c2ecf20Sopenharmony_ci struct scatterlist *src, *dst; 1298c2ecf20Sopenharmony_ci int err; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (rctx->cryptlen == 0) 1328c2ecf20Sopenharmony_ci goto skip; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci chacha_iv(creq->iv, req, 1); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen); 1378c2ecf20Sopenharmony_ci dst = src; 1388c2ecf20Sopenharmony_ci if (req->src != req->dst) 1398c2ecf20Sopenharmony_ci dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci skcipher_request_set_callback(&creq->req, rctx->flags, 1428c2ecf20Sopenharmony_ci chacha_decrypt_done, req); 1438c2ecf20Sopenharmony_ci skcipher_request_set_tfm(&creq->req, ctx->chacha); 1448c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&creq->req, src, dst, 1458c2ecf20Sopenharmony_ci rctx->cryptlen, creq->iv); 1468c2ecf20Sopenharmony_ci err = crypto_skcipher_decrypt(&creq->req); 1478c2ecf20Sopenharmony_ci if (err) 1488c2ecf20Sopenharmony_ci return err; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ciskip: 1518c2ecf20Sopenharmony_ci return poly_verify_tag(req); 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic int poly_tail_continue(struct aead_request *req) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if (rctx->cryptlen == req->cryptlen) /* encrypting */ 1598c2ecf20Sopenharmony_ci return poly_copy_tag(req); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci return chacha_decrypt(req); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic void poly_tail_done(struct crypto_async_request *areq, int err) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci async_done_continue(areq->data, err, poly_tail_continue); 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic int poly_tail(struct aead_request *req) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 1728c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 1738c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 1748c2ecf20Sopenharmony_ci struct poly_req *preq = &rctx->u.poly; 1758c2ecf20Sopenharmony_ci int err; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci preq->tail.assoclen = cpu_to_le64(rctx->assoclen); 1788c2ecf20Sopenharmony_ci preq->tail.cryptlen = cpu_to_le64(rctx->cryptlen); 1798c2ecf20Sopenharmony_ci sg_init_one(preq->src, &preq->tail, sizeof(preq->tail)); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci ahash_request_set_callback(&preq->req, rctx->flags, 1828c2ecf20Sopenharmony_ci poly_tail_done, req); 1838c2ecf20Sopenharmony_ci ahash_request_set_tfm(&preq->req, ctx->poly); 1848c2ecf20Sopenharmony_ci ahash_request_set_crypt(&preq->req, preq->src, 1858c2ecf20Sopenharmony_ci rctx->tag, sizeof(preq->tail)); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci err = crypto_ahash_finup(&preq->req); 1888c2ecf20Sopenharmony_ci if (err) 1898c2ecf20Sopenharmony_ci return err; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci return poly_tail_continue(req); 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic void poly_cipherpad_done(struct crypto_async_request *areq, int err) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci async_done_continue(areq->data, err, poly_tail); 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic int poly_cipherpad(struct aead_request *req) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 2028c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 2038c2ecf20Sopenharmony_ci struct poly_req *preq = &rctx->u.poly; 2048c2ecf20Sopenharmony_ci unsigned int padlen; 2058c2ecf20Sopenharmony_ci int err; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci padlen = -rctx->cryptlen % POLY1305_BLOCK_SIZE; 2088c2ecf20Sopenharmony_ci memset(preq->pad, 0, sizeof(preq->pad)); 2098c2ecf20Sopenharmony_ci sg_init_one(preq->src, preq->pad, padlen); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci ahash_request_set_callback(&preq->req, rctx->flags, 2128c2ecf20Sopenharmony_ci poly_cipherpad_done, req); 2138c2ecf20Sopenharmony_ci ahash_request_set_tfm(&preq->req, ctx->poly); 2148c2ecf20Sopenharmony_ci ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci err = crypto_ahash_update(&preq->req); 2178c2ecf20Sopenharmony_ci if (err) 2188c2ecf20Sopenharmony_ci return err; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci return poly_tail(req); 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic void poly_cipher_done(struct crypto_async_request *areq, int err) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci async_done_continue(areq->data, err, poly_cipherpad); 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic int poly_cipher(struct aead_request *req) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 2318c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 2328c2ecf20Sopenharmony_ci struct poly_req *preq = &rctx->u.poly; 2338c2ecf20Sopenharmony_ci struct scatterlist *crypt = req->src; 2348c2ecf20Sopenharmony_ci int err; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci if (rctx->cryptlen == req->cryptlen) /* encrypting */ 2378c2ecf20Sopenharmony_ci crypt = req->dst; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci crypt = scatterwalk_ffwd(rctx->src, crypt, req->assoclen); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci ahash_request_set_callback(&preq->req, rctx->flags, 2428c2ecf20Sopenharmony_ci poly_cipher_done, req); 2438c2ecf20Sopenharmony_ci ahash_request_set_tfm(&preq->req, ctx->poly); 2448c2ecf20Sopenharmony_ci ahash_request_set_crypt(&preq->req, crypt, NULL, rctx->cryptlen); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci err = crypto_ahash_update(&preq->req); 2478c2ecf20Sopenharmony_ci if (err) 2488c2ecf20Sopenharmony_ci return err; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci return poly_cipherpad(req); 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic void poly_adpad_done(struct crypto_async_request *areq, int err) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci async_done_continue(areq->data, err, poly_cipher); 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic int poly_adpad(struct aead_request *req) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 2618c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 2628c2ecf20Sopenharmony_ci struct poly_req *preq = &rctx->u.poly; 2638c2ecf20Sopenharmony_ci unsigned int padlen; 2648c2ecf20Sopenharmony_ci int err; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci padlen = -rctx->assoclen % POLY1305_BLOCK_SIZE; 2678c2ecf20Sopenharmony_ci memset(preq->pad, 0, sizeof(preq->pad)); 2688c2ecf20Sopenharmony_ci sg_init_one(preq->src, preq->pad, padlen); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci ahash_request_set_callback(&preq->req, rctx->flags, 2718c2ecf20Sopenharmony_ci poly_adpad_done, req); 2728c2ecf20Sopenharmony_ci ahash_request_set_tfm(&preq->req, ctx->poly); 2738c2ecf20Sopenharmony_ci ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci err = crypto_ahash_update(&preq->req); 2768c2ecf20Sopenharmony_ci if (err) 2778c2ecf20Sopenharmony_ci return err; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci return poly_cipher(req); 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic void poly_ad_done(struct crypto_async_request *areq, int err) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci async_done_continue(areq->data, err, poly_adpad); 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic int poly_ad(struct aead_request *req) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 2908c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 2918c2ecf20Sopenharmony_ci struct poly_req *preq = &rctx->u.poly; 2928c2ecf20Sopenharmony_ci int err; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci ahash_request_set_callback(&preq->req, rctx->flags, 2958c2ecf20Sopenharmony_ci poly_ad_done, req); 2968c2ecf20Sopenharmony_ci ahash_request_set_tfm(&preq->req, ctx->poly); 2978c2ecf20Sopenharmony_ci ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci err = crypto_ahash_update(&preq->req); 3008c2ecf20Sopenharmony_ci if (err) 3018c2ecf20Sopenharmony_ci return err; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci return poly_adpad(req); 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic void poly_setkey_done(struct crypto_async_request *areq, int err) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci async_done_continue(areq->data, err, poly_ad); 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic int poly_setkey(struct aead_request *req) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 3148c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 3158c2ecf20Sopenharmony_ci struct poly_req *preq = &rctx->u.poly; 3168c2ecf20Sopenharmony_ci int err; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci sg_init_one(preq->src, rctx->key, sizeof(rctx->key)); 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci ahash_request_set_callback(&preq->req, rctx->flags, 3218c2ecf20Sopenharmony_ci poly_setkey_done, req); 3228c2ecf20Sopenharmony_ci ahash_request_set_tfm(&preq->req, ctx->poly); 3238c2ecf20Sopenharmony_ci ahash_request_set_crypt(&preq->req, preq->src, NULL, sizeof(rctx->key)); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci err = crypto_ahash_update(&preq->req); 3268c2ecf20Sopenharmony_ci if (err) 3278c2ecf20Sopenharmony_ci return err; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci return poly_ad(req); 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic void poly_init_done(struct crypto_async_request *areq, int err) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci async_done_continue(areq->data, err, poly_setkey); 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic int poly_init(struct aead_request *req) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 3408c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 3418c2ecf20Sopenharmony_ci struct poly_req *preq = &rctx->u.poly; 3428c2ecf20Sopenharmony_ci int err; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci ahash_request_set_callback(&preq->req, rctx->flags, 3458c2ecf20Sopenharmony_ci poly_init_done, req); 3468c2ecf20Sopenharmony_ci ahash_request_set_tfm(&preq->req, ctx->poly); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci err = crypto_ahash_init(&preq->req); 3498c2ecf20Sopenharmony_ci if (err) 3508c2ecf20Sopenharmony_ci return err; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci return poly_setkey(req); 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic void poly_genkey_done(struct crypto_async_request *areq, int err) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci async_done_continue(areq->data, err, poly_init); 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic int poly_genkey(struct aead_request *req) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 3638c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 3648c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 3658c2ecf20Sopenharmony_ci struct chacha_req *creq = &rctx->u.chacha; 3668c2ecf20Sopenharmony_ci int err; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci rctx->assoclen = req->assoclen; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (crypto_aead_ivsize(tfm) == 8) { 3718c2ecf20Sopenharmony_ci if (rctx->assoclen < 8) 3728c2ecf20Sopenharmony_ci return -EINVAL; 3738c2ecf20Sopenharmony_ci rctx->assoclen -= 8; 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci memset(rctx->key, 0, sizeof(rctx->key)); 3778c2ecf20Sopenharmony_ci sg_init_one(creq->src, rctx->key, sizeof(rctx->key)); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci chacha_iv(creq->iv, req, 0); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci skcipher_request_set_callback(&creq->req, rctx->flags, 3828c2ecf20Sopenharmony_ci poly_genkey_done, req); 3838c2ecf20Sopenharmony_ci skcipher_request_set_tfm(&creq->req, ctx->chacha); 3848c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&creq->req, creq->src, creq->src, 3858c2ecf20Sopenharmony_ci POLY1305_KEY_SIZE, creq->iv); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci err = crypto_skcipher_decrypt(&creq->req); 3888c2ecf20Sopenharmony_ci if (err) 3898c2ecf20Sopenharmony_ci return err; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci return poly_init(req); 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic void chacha_encrypt_done(struct crypto_async_request *areq, int err) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci async_done_continue(areq->data, err, poly_genkey); 3978c2ecf20Sopenharmony_ci} 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_cistatic int chacha_encrypt(struct aead_request *req) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 4028c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 4038c2ecf20Sopenharmony_ci struct chacha_req *creq = &rctx->u.chacha; 4048c2ecf20Sopenharmony_ci struct scatterlist *src, *dst; 4058c2ecf20Sopenharmony_ci int err; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci if (req->cryptlen == 0) 4088c2ecf20Sopenharmony_ci goto skip; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci chacha_iv(creq->iv, req, 1); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen); 4138c2ecf20Sopenharmony_ci dst = src; 4148c2ecf20Sopenharmony_ci if (req->src != req->dst) 4158c2ecf20Sopenharmony_ci dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci skcipher_request_set_callback(&creq->req, rctx->flags, 4188c2ecf20Sopenharmony_ci chacha_encrypt_done, req); 4198c2ecf20Sopenharmony_ci skcipher_request_set_tfm(&creq->req, ctx->chacha); 4208c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&creq->req, src, dst, 4218c2ecf20Sopenharmony_ci req->cryptlen, creq->iv); 4228c2ecf20Sopenharmony_ci err = crypto_skcipher_encrypt(&creq->req); 4238c2ecf20Sopenharmony_ci if (err) 4248c2ecf20Sopenharmony_ci return err; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ciskip: 4278c2ecf20Sopenharmony_ci return poly_genkey(req); 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic int chachapoly_encrypt(struct aead_request *req) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci rctx->cryptlen = req->cryptlen; 4358c2ecf20Sopenharmony_ci rctx->flags = aead_request_flags(req); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci /* encrypt call chain: 4388c2ecf20Sopenharmony_ci * - chacha_encrypt/done() 4398c2ecf20Sopenharmony_ci * - poly_genkey/done() 4408c2ecf20Sopenharmony_ci * - poly_init/done() 4418c2ecf20Sopenharmony_ci * - poly_setkey/done() 4428c2ecf20Sopenharmony_ci * - poly_ad/done() 4438c2ecf20Sopenharmony_ci * - poly_adpad/done() 4448c2ecf20Sopenharmony_ci * - poly_cipher/done() 4458c2ecf20Sopenharmony_ci * - poly_cipherpad/done() 4468c2ecf20Sopenharmony_ci * - poly_tail/done/continue() 4478c2ecf20Sopenharmony_ci * - poly_copy_tag() 4488c2ecf20Sopenharmony_ci */ 4498c2ecf20Sopenharmony_ci return chacha_encrypt(req); 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistatic int chachapoly_decrypt(struct aead_request *req) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE; 4578c2ecf20Sopenharmony_ci rctx->flags = aead_request_flags(req); 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci /* decrypt call chain: 4608c2ecf20Sopenharmony_ci * - poly_genkey/done() 4618c2ecf20Sopenharmony_ci * - poly_init/done() 4628c2ecf20Sopenharmony_ci * - poly_setkey/done() 4638c2ecf20Sopenharmony_ci * - poly_ad/done() 4648c2ecf20Sopenharmony_ci * - poly_adpad/done() 4658c2ecf20Sopenharmony_ci * - poly_cipher/done() 4668c2ecf20Sopenharmony_ci * - poly_cipherpad/done() 4678c2ecf20Sopenharmony_ci * - poly_tail/done/continue() 4688c2ecf20Sopenharmony_ci * - chacha_decrypt/done() 4698c2ecf20Sopenharmony_ci * - poly_verify_tag() 4708c2ecf20Sopenharmony_ci */ 4718c2ecf20Sopenharmony_ci return poly_genkey(req); 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_cistatic int chachapoly_setkey(struct crypto_aead *aead, const u8 *key, 4758c2ecf20Sopenharmony_ci unsigned int keylen) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(aead); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci if (keylen != ctx->saltlen + CHACHA_KEY_SIZE) 4808c2ecf20Sopenharmony_ci return -EINVAL; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci keylen -= ctx->saltlen; 4838c2ecf20Sopenharmony_ci memcpy(ctx->salt, key + keylen, ctx->saltlen); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci crypto_skcipher_clear_flags(ctx->chacha, CRYPTO_TFM_REQ_MASK); 4868c2ecf20Sopenharmony_ci crypto_skcipher_set_flags(ctx->chacha, crypto_aead_get_flags(aead) & 4878c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 4888c2ecf20Sopenharmony_ci return crypto_skcipher_setkey(ctx->chacha, key, keylen); 4898c2ecf20Sopenharmony_ci} 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_cistatic int chachapoly_setauthsize(struct crypto_aead *tfm, 4928c2ecf20Sopenharmony_ci unsigned int authsize) 4938c2ecf20Sopenharmony_ci{ 4948c2ecf20Sopenharmony_ci if (authsize != POLY1305_DIGEST_SIZE) 4958c2ecf20Sopenharmony_ci return -EINVAL; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci return 0; 4988c2ecf20Sopenharmony_ci} 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_cistatic int chachapoly_init(struct crypto_aead *tfm) 5018c2ecf20Sopenharmony_ci{ 5028c2ecf20Sopenharmony_ci struct aead_instance *inst = aead_alg_instance(tfm); 5038c2ecf20Sopenharmony_ci struct chachapoly_instance_ctx *ictx = aead_instance_ctx(inst); 5048c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 5058c2ecf20Sopenharmony_ci struct crypto_skcipher *chacha; 5068c2ecf20Sopenharmony_ci struct crypto_ahash *poly; 5078c2ecf20Sopenharmony_ci unsigned long align; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci poly = crypto_spawn_ahash(&ictx->poly); 5108c2ecf20Sopenharmony_ci if (IS_ERR(poly)) 5118c2ecf20Sopenharmony_ci return PTR_ERR(poly); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci chacha = crypto_spawn_skcipher(&ictx->chacha); 5148c2ecf20Sopenharmony_ci if (IS_ERR(chacha)) { 5158c2ecf20Sopenharmony_ci crypto_free_ahash(poly); 5168c2ecf20Sopenharmony_ci return PTR_ERR(chacha); 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci ctx->chacha = chacha; 5208c2ecf20Sopenharmony_ci ctx->poly = poly; 5218c2ecf20Sopenharmony_ci ctx->saltlen = ictx->saltlen; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci align = crypto_aead_alignmask(tfm); 5248c2ecf20Sopenharmony_ci align &= ~(crypto_tfm_ctx_alignment() - 1); 5258c2ecf20Sopenharmony_ci crypto_aead_set_reqsize( 5268c2ecf20Sopenharmony_ci tfm, 5278c2ecf20Sopenharmony_ci align + offsetof(struct chachapoly_req_ctx, u) + 5288c2ecf20Sopenharmony_ci max(offsetof(struct chacha_req, req) + 5298c2ecf20Sopenharmony_ci sizeof(struct skcipher_request) + 5308c2ecf20Sopenharmony_ci crypto_skcipher_reqsize(chacha), 5318c2ecf20Sopenharmony_ci offsetof(struct poly_req, req) + 5328c2ecf20Sopenharmony_ci sizeof(struct ahash_request) + 5338c2ecf20Sopenharmony_ci crypto_ahash_reqsize(poly))); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci return 0; 5368c2ecf20Sopenharmony_ci} 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_cistatic void chachapoly_exit(struct crypto_aead *tfm) 5398c2ecf20Sopenharmony_ci{ 5408c2ecf20Sopenharmony_ci struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci crypto_free_ahash(ctx->poly); 5438c2ecf20Sopenharmony_ci crypto_free_skcipher(ctx->chacha); 5448c2ecf20Sopenharmony_ci} 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic void chachapoly_free(struct aead_instance *inst) 5478c2ecf20Sopenharmony_ci{ 5488c2ecf20Sopenharmony_ci struct chachapoly_instance_ctx *ctx = aead_instance_ctx(inst); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci crypto_drop_skcipher(&ctx->chacha); 5518c2ecf20Sopenharmony_ci crypto_drop_ahash(&ctx->poly); 5528c2ecf20Sopenharmony_ci kfree(inst); 5538c2ecf20Sopenharmony_ci} 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_cistatic int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb, 5568c2ecf20Sopenharmony_ci const char *name, unsigned int ivsize) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci u32 mask; 5598c2ecf20Sopenharmony_ci struct aead_instance *inst; 5608c2ecf20Sopenharmony_ci struct chachapoly_instance_ctx *ctx; 5618c2ecf20Sopenharmony_ci struct skcipher_alg *chacha; 5628c2ecf20Sopenharmony_ci struct hash_alg_common *poly; 5638c2ecf20Sopenharmony_ci int err; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci if (ivsize > CHACHAPOLY_IV_SIZE) 5668c2ecf20Sopenharmony_ci return -EINVAL; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask); 5698c2ecf20Sopenharmony_ci if (err) 5708c2ecf20Sopenharmony_ci return err; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 5738c2ecf20Sopenharmony_ci if (!inst) 5748c2ecf20Sopenharmony_ci return -ENOMEM; 5758c2ecf20Sopenharmony_ci ctx = aead_instance_ctx(inst); 5768c2ecf20Sopenharmony_ci ctx->saltlen = CHACHAPOLY_IV_SIZE - ivsize; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci err = crypto_grab_skcipher(&ctx->chacha, aead_crypto_instance(inst), 5798c2ecf20Sopenharmony_ci crypto_attr_alg_name(tb[1]), 0, mask); 5808c2ecf20Sopenharmony_ci if (err) 5818c2ecf20Sopenharmony_ci goto err_free_inst; 5828c2ecf20Sopenharmony_ci chacha = crypto_spawn_skcipher_alg(&ctx->chacha); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci err = crypto_grab_ahash(&ctx->poly, aead_crypto_instance(inst), 5858c2ecf20Sopenharmony_ci crypto_attr_alg_name(tb[2]), 0, mask); 5868c2ecf20Sopenharmony_ci if (err) 5878c2ecf20Sopenharmony_ci goto err_free_inst; 5888c2ecf20Sopenharmony_ci poly = crypto_spawn_ahash_alg(&ctx->poly); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci err = -EINVAL; 5918c2ecf20Sopenharmony_ci if (poly->digestsize != POLY1305_DIGEST_SIZE) 5928c2ecf20Sopenharmony_ci goto err_free_inst; 5938c2ecf20Sopenharmony_ci /* Need 16-byte IV size, including Initial Block Counter value */ 5948c2ecf20Sopenharmony_ci if (crypto_skcipher_alg_ivsize(chacha) != CHACHA_IV_SIZE) 5958c2ecf20Sopenharmony_ci goto err_free_inst; 5968c2ecf20Sopenharmony_ci /* Not a stream cipher? */ 5978c2ecf20Sopenharmony_ci if (chacha->base.cra_blocksize != 1) 5988c2ecf20Sopenharmony_ci goto err_free_inst; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci err = -ENAMETOOLONG; 6018c2ecf20Sopenharmony_ci if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 6028c2ecf20Sopenharmony_ci "%s(%s,%s)", name, chacha->base.cra_name, 6038c2ecf20Sopenharmony_ci poly->base.cra_name) >= CRYPTO_MAX_ALG_NAME) 6048c2ecf20Sopenharmony_ci goto err_free_inst; 6058c2ecf20Sopenharmony_ci if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 6068c2ecf20Sopenharmony_ci "%s(%s,%s)", name, chacha->base.cra_driver_name, 6078c2ecf20Sopenharmony_ci poly->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 6088c2ecf20Sopenharmony_ci goto err_free_inst; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci inst->alg.base.cra_priority = (chacha->base.cra_priority + 6118c2ecf20Sopenharmony_ci poly->base.cra_priority) / 2; 6128c2ecf20Sopenharmony_ci inst->alg.base.cra_blocksize = 1; 6138c2ecf20Sopenharmony_ci inst->alg.base.cra_alignmask = chacha->base.cra_alignmask | 6148c2ecf20Sopenharmony_ci poly->base.cra_alignmask; 6158c2ecf20Sopenharmony_ci inst->alg.base.cra_ctxsize = sizeof(struct chachapoly_ctx) + 6168c2ecf20Sopenharmony_ci ctx->saltlen; 6178c2ecf20Sopenharmony_ci inst->alg.ivsize = ivsize; 6188c2ecf20Sopenharmony_ci inst->alg.chunksize = crypto_skcipher_alg_chunksize(chacha); 6198c2ecf20Sopenharmony_ci inst->alg.maxauthsize = POLY1305_DIGEST_SIZE; 6208c2ecf20Sopenharmony_ci inst->alg.init = chachapoly_init; 6218c2ecf20Sopenharmony_ci inst->alg.exit = chachapoly_exit; 6228c2ecf20Sopenharmony_ci inst->alg.encrypt = chachapoly_encrypt; 6238c2ecf20Sopenharmony_ci inst->alg.decrypt = chachapoly_decrypt; 6248c2ecf20Sopenharmony_ci inst->alg.setkey = chachapoly_setkey; 6258c2ecf20Sopenharmony_ci inst->alg.setauthsize = chachapoly_setauthsize; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci inst->free = chachapoly_free; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci err = aead_register_instance(tmpl, inst); 6308c2ecf20Sopenharmony_ci if (err) { 6318c2ecf20Sopenharmony_cierr_free_inst: 6328c2ecf20Sopenharmony_ci chachapoly_free(inst); 6338c2ecf20Sopenharmony_ci } 6348c2ecf20Sopenharmony_ci return err; 6358c2ecf20Sopenharmony_ci} 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic int rfc7539_create(struct crypto_template *tmpl, struct rtattr **tb) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci return chachapoly_create(tmpl, tb, "rfc7539", 12); 6408c2ecf20Sopenharmony_ci} 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_cistatic int rfc7539esp_create(struct crypto_template *tmpl, struct rtattr **tb) 6438c2ecf20Sopenharmony_ci{ 6448c2ecf20Sopenharmony_ci return chachapoly_create(tmpl, tb, "rfc7539esp", 8); 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic struct crypto_template rfc7539_tmpls[] = { 6488c2ecf20Sopenharmony_ci { 6498c2ecf20Sopenharmony_ci .name = "rfc7539", 6508c2ecf20Sopenharmony_ci .create = rfc7539_create, 6518c2ecf20Sopenharmony_ci .module = THIS_MODULE, 6528c2ecf20Sopenharmony_ci }, { 6538c2ecf20Sopenharmony_ci .name = "rfc7539esp", 6548c2ecf20Sopenharmony_ci .create = rfc7539esp_create, 6558c2ecf20Sopenharmony_ci .module = THIS_MODULE, 6568c2ecf20Sopenharmony_ci }, 6578c2ecf20Sopenharmony_ci}; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cistatic int __init chacha20poly1305_module_init(void) 6608c2ecf20Sopenharmony_ci{ 6618c2ecf20Sopenharmony_ci return crypto_register_templates(rfc7539_tmpls, 6628c2ecf20Sopenharmony_ci ARRAY_SIZE(rfc7539_tmpls)); 6638c2ecf20Sopenharmony_ci} 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_cistatic void __exit chacha20poly1305_module_exit(void) 6668c2ecf20Sopenharmony_ci{ 6678c2ecf20Sopenharmony_ci crypto_unregister_templates(rfc7539_tmpls, 6688c2ecf20Sopenharmony_ci ARRAY_SIZE(rfc7539_tmpls)); 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cisubsys_initcall(chacha20poly1305_module_init); 6728c2ecf20Sopenharmony_cimodule_exit(chacha20poly1305_module_exit); 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 6758c2ecf20Sopenharmony_ciMODULE_AUTHOR("Martin Willi <martin@strongswan.org>"); 6768c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ChaCha20-Poly1305 AEAD"); 6778c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("rfc7539"); 6788c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("rfc7539esp"); 679