xref: /openbmc/linux/crypto/chacha20poly1305.c (revision ae213c44)
1 /*
2  * ChaCha20-Poly1305 AEAD, RFC7539
3  *
4  * Copyright (C) 2015 Martin Willi
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11 
12 #include <crypto/internal/aead.h>
13 #include <crypto/internal/hash.h>
14 #include <crypto/internal/skcipher.h>
15 #include <crypto/scatterwalk.h>
16 #include <crypto/chacha.h>
17 #include <crypto/poly1305.h>
18 #include <linux/err.h>
19 #include <linux/init.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 
23 #include "internal.h"
24 
25 struct chachapoly_instance_ctx {
26 	struct crypto_skcipher_spawn chacha;
27 	struct crypto_ahash_spawn poly;
28 	unsigned int saltlen;
29 };
30 
31 struct chachapoly_ctx {
32 	struct crypto_skcipher *chacha;
33 	struct crypto_ahash *poly;
34 	/* key bytes we use for the ChaCha20 IV */
35 	unsigned int saltlen;
36 	u8 salt[];
37 };
38 
39 struct poly_req {
40 	/* zero byte padding for AD/ciphertext, as needed */
41 	u8 pad[POLY1305_BLOCK_SIZE];
42 	/* tail data with AD/ciphertext lengths */
43 	struct {
44 		__le64 assoclen;
45 		__le64 cryptlen;
46 	} tail;
47 	struct scatterlist src[1];
48 	struct ahash_request req; /* must be last member */
49 };
50 
51 struct chacha_req {
52 	u8 iv[CHACHA_IV_SIZE];
53 	struct scatterlist src[1];
54 	struct skcipher_request req; /* must be last member */
55 };
56 
57 struct chachapoly_req_ctx {
58 	struct scatterlist src[2];
59 	struct scatterlist dst[2];
60 	/* the key we generate for Poly1305 using Chacha20 */
61 	u8 key[POLY1305_KEY_SIZE];
62 	/* calculated Poly1305 tag */
63 	u8 tag[POLY1305_DIGEST_SIZE];
64 	/* length of data to en/decrypt, without ICV */
65 	unsigned int cryptlen;
66 	/* Actual AD, excluding IV */
67 	unsigned int assoclen;
68 	union {
69 		struct poly_req poly;
70 		struct chacha_req chacha;
71 	} u;
72 };
73 
74 static inline void async_done_continue(struct aead_request *req, int err,
75 				       int (*cont)(struct aead_request *))
76 {
77 	if (!err)
78 		err = cont(req);
79 
80 	if (err != -EINPROGRESS && err != -EBUSY)
81 		aead_request_complete(req, err);
82 }
83 
84 static void chacha_iv(u8 *iv, struct aead_request *req, u32 icb)
85 {
86 	struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
87 	__le32 leicb = cpu_to_le32(icb);
88 
89 	memcpy(iv, &leicb, sizeof(leicb));
90 	memcpy(iv + sizeof(leicb), ctx->salt, ctx->saltlen);
91 	memcpy(iv + sizeof(leicb) + ctx->saltlen, req->iv,
92 	       CHACHA_IV_SIZE - sizeof(leicb) - ctx->saltlen);
93 }
94 
95 static int poly_verify_tag(struct aead_request *req)
96 {
97 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
98 	u8 tag[sizeof(rctx->tag)];
99 
100 	scatterwalk_map_and_copy(tag, req->src,
101 				 req->assoclen + rctx->cryptlen,
102 				 sizeof(tag), 0);
103 	if (crypto_memneq(tag, rctx->tag, sizeof(tag)))
104 		return -EBADMSG;
105 	return 0;
106 }
107 
108 static int poly_copy_tag(struct aead_request *req)
109 {
110 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
111 
112 	scatterwalk_map_and_copy(rctx->tag, req->dst,
113 				 req->assoclen + rctx->cryptlen,
114 				 sizeof(rctx->tag), 1);
115 	return 0;
116 }
117 
118 static void chacha_decrypt_done(struct crypto_async_request *areq, int err)
119 {
120 	async_done_continue(areq->data, err, poly_verify_tag);
121 }
122 
123 static int chacha_decrypt(struct aead_request *req)
124 {
125 	struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
126 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
127 	struct chacha_req *creq = &rctx->u.chacha;
128 	struct scatterlist *src, *dst;
129 	int err;
130 
131 	if (rctx->cryptlen == 0)
132 		goto skip;
133 
134 	chacha_iv(creq->iv, req, 1);
135 
136 	sg_init_table(rctx->src, 2);
137 	src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen);
138 	dst = src;
139 
140 	if (req->src != req->dst) {
141 		sg_init_table(rctx->dst, 2);
142 		dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen);
143 	}
144 
145 	skcipher_request_set_callback(&creq->req, aead_request_flags(req),
146 				      chacha_decrypt_done, req);
147 	skcipher_request_set_tfm(&creq->req, ctx->chacha);
148 	skcipher_request_set_crypt(&creq->req, src, dst,
149 				   rctx->cryptlen, creq->iv);
150 	err = crypto_skcipher_decrypt(&creq->req);
151 	if (err)
152 		return err;
153 
154 skip:
155 	return poly_verify_tag(req);
156 }
157 
158 static int poly_tail_continue(struct aead_request *req)
159 {
160 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
161 
162 	if (rctx->cryptlen == req->cryptlen) /* encrypting */
163 		return poly_copy_tag(req);
164 
165 	return chacha_decrypt(req);
166 }
167 
168 static void poly_tail_done(struct crypto_async_request *areq, int err)
169 {
170 	async_done_continue(areq->data, err, poly_tail_continue);
171 }
172 
173 static int poly_tail(struct aead_request *req)
174 {
175 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
176 	struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
177 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
178 	struct poly_req *preq = &rctx->u.poly;
179 	__le64 len;
180 	int err;
181 
182 	sg_init_table(preq->src, 1);
183 	len = cpu_to_le64(rctx->assoclen);
184 	memcpy(&preq->tail.assoclen, &len, sizeof(len));
185 	len = cpu_to_le64(rctx->cryptlen);
186 	memcpy(&preq->tail.cryptlen, &len, sizeof(len));
187 	sg_set_buf(preq->src, &preq->tail, sizeof(preq->tail));
188 
189 	ahash_request_set_callback(&preq->req, aead_request_flags(req),
190 				   poly_tail_done, req);
191 	ahash_request_set_tfm(&preq->req, ctx->poly);
192 	ahash_request_set_crypt(&preq->req, preq->src,
193 				rctx->tag, sizeof(preq->tail));
194 
195 	err = crypto_ahash_finup(&preq->req);
196 	if (err)
197 		return err;
198 
199 	return poly_tail_continue(req);
200 }
201 
202 static void poly_cipherpad_done(struct crypto_async_request *areq, int err)
203 {
204 	async_done_continue(areq->data, err, poly_tail);
205 }
206 
207 static int poly_cipherpad(struct aead_request *req)
208 {
209 	struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
210 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
211 	struct poly_req *preq = &rctx->u.poly;
212 	unsigned int padlen, bs = POLY1305_BLOCK_SIZE;
213 	int err;
214 
215 	padlen = (bs - (rctx->cryptlen % bs)) % bs;
216 	memset(preq->pad, 0, sizeof(preq->pad));
217 	sg_init_table(preq->src, 1);
218 	sg_set_buf(preq->src, &preq->pad, padlen);
219 
220 	ahash_request_set_callback(&preq->req, aead_request_flags(req),
221 				   poly_cipherpad_done, req);
222 	ahash_request_set_tfm(&preq->req, ctx->poly);
223 	ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen);
224 
225 	err = crypto_ahash_update(&preq->req);
226 	if (err)
227 		return err;
228 
229 	return poly_tail(req);
230 }
231 
232 static void poly_cipher_done(struct crypto_async_request *areq, int err)
233 {
234 	async_done_continue(areq->data, err, poly_cipherpad);
235 }
236 
237 static int poly_cipher(struct aead_request *req)
238 {
239 	struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
240 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
241 	struct poly_req *preq = &rctx->u.poly;
242 	struct scatterlist *crypt = req->src;
243 	int err;
244 
245 	if (rctx->cryptlen == req->cryptlen) /* encrypting */
246 		crypt = req->dst;
247 
248 	sg_init_table(rctx->src, 2);
249 	crypt = scatterwalk_ffwd(rctx->src, crypt, req->assoclen);
250 
251 	ahash_request_set_callback(&preq->req, aead_request_flags(req),
252 				   poly_cipher_done, req);
253 	ahash_request_set_tfm(&preq->req, ctx->poly);
254 	ahash_request_set_crypt(&preq->req, crypt, NULL, rctx->cryptlen);
255 
256 	err = crypto_ahash_update(&preq->req);
257 	if (err)
258 		return err;
259 
260 	return poly_cipherpad(req);
261 }
262 
263 static void poly_adpad_done(struct crypto_async_request *areq, int err)
264 {
265 	async_done_continue(areq->data, err, poly_cipher);
266 }
267 
268 static int poly_adpad(struct aead_request *req)
269 {
270 	struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
271 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
272 	struct poly_req *preq = &rctx->u.poly;
273 	unsigned int padlen, bs = POLY1305_BLOCK_SIZE;
274 	int err;
275 
276 	padlen = (bs - (rctx->assoclen % bs)) % bs;
277 	memset(preq->pad, 0, sizeof(preq->pad));
278 	sg_init_table(preq->src, 1);
279 	sg_set_buf(preq->src, preq->pad, padlen);
280 
281 	ahash_request_set_callback(&preq->req, aead_request_flags(req),
282 				   poly_adpad_done, req);
283 	ahash_request_set_tfm(&preq->req, ctx->poly);
284 	ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen);
285 
286 	err = crypto_ahash_update(&preq->req);
287 	if (err)
288 		return err;
289 
290 	return poly_cipher(req);
291 }
292 
293 static void poly_ad_done(struct crypto_async_request *areq, int err)
294 {
295 	async_done_continue(areq->data, err, poly_adpad);
296 }
297 
298 static int poly_ad(struct aead_request *req)
299 {
300 	struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
301 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
302 	struct poly_req *preq = &rctx->u.poly;
303 	int err;
304 
305 	ahash_request_set_callback(&preq->req, aead_request_flags(req),
306 				   poly_ad_done, req);
307 	ahash_request_set_tfm(&preq->req, ctx->poly);
308 	ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen);
309 
310 	err = crypto_ahash_update(&preq->req);
311 	if (err)
312 		return err;
313 
314 	return poly_adpad(req);
315 }
316 
317 static void poly_setkey_done(struct crypto_async_request *areq, int err)
318 {
319 	async_done_continue(areq->data, err, poly_ad);
320 }
321 
322 static int poly_setkey(struct aead_request *req)
323 {
324 	struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
325 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
326 	struct poly_req *preq = &rctx->u.poly;
327 	int err;
328 
329 	sg_init_table(preq->src, 1);
330 	sg_set_buf(preq->src, rctx->key, sizeof(rctx->key));
331 
332 	ahash_request_set_callback(&preq->req, aead_request_flags(req),
333 				   poly_setkey_done, req);
334 	ahash_request_set_tfm(&preq->req, ctx->poly);
335 	ahash_request_set_crypt(&preq->req, preq->src, NULL, sizeof(rctx->key));
336 
337 	err = crypto_ahash_update(&preq->req);
338 	if (err)
339 		return err;
340 
341 	return poly_ad(req);
342 }
343 
344 static void poly_init_done(struct crypto_async_request *areq, int err)
345 {
346 	async_done_continue(areq->data, err, poly_setkey);
347 }
348 
349 static int poly_init(struct aead_request *req)
350 {
351 	struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
352 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
353 	struct poly_req *preq = &rctx->u.poly;
354 	int err;
355 
356 	ahash_request_set_callback(&preq->req, aead_request_flags(req),
357 				   poly_init_done, req);
358 	ahash_request_set_tfm(&preq->req, ctx->poly);
359 
360 	err = crypto_ahash_init(&preq->req);
361 	if (err)
362 		return err;
363 
364 	return poly_setkey(req);
365 }
366 
367 static void poly_genkey_done(struct crypto_async_request *areq, int err)
368 {
369 	async_done_continue(areq->data, err, poly_init);
370 }
371 
372 static int poly_genkey(struct aead_request *req)
373 {
374 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
375 	struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
376 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
377 	struct chacha_req *creq = &rctx->u.chacha;
378 	int err;
379 
380 	rctx->assoclen = req->assoclen;
381 
382 	if (crypto_aead_ivsize(tfm) == 8) {
383 		if (rctx->assoclen < 8)
384 			return -EINVAL;
385 		rctx->assoclen -= 8;
386 	}
387 
388 	sg_init_table(creq->src, 1);
389 	memset(rctx->key, 0, sizeof(rctx->key));
390 	sg_set_buf(creq->src, rctx->key, sizeof(rctx->key));
391 
392 	chacha_iv(creq->iv, req, 0);
393 
394 	skcipher_request_set_callback(&creq->req, aead_request_flags(req),
395 				      poly_genkey_done, req);
396 	skcipher_request_set_tfm(&creq->req, ctx->chacha);
397 	skcipher_request_set_crypt(&creq->req, creq->src, creq->src,
398 				   POLY1305_KEY_SIZE, creq->iv);
399 
400 	err = crypto_skcipher_decrypt(&creq->req);
401 	if (err)
402 		return err;
403 
404 	return poly_init(req);
405 }
406 
407 static void chacha_encrypt_done(struct crypto_async_request *areq, int err)
408 {
409 	async_done_continue(areq->data, err, poly_genkey);
410 }
411 
412 static int chacha_encrypt(struct aead_request *req)
413 {
414 	struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
415 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
416 	struct chacha_req *creq = &rctx->u.chacha;
417 	struct scatterlist *src, *dst;
418 	int err;
419 
420 	if (req->cryptlen == 0)
421 		goto skip;
422 
423 	chacha_iv(creq->iv, req, 1);
424 
425 	sg_init_table(rctx->src, 2);
426 	src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen);
427 	dst = src;
428 
429 	if (req->src != req->dst) {
430 		sg_init_table(rctx->dst, 2);
431 		dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen);
432 	}
433 
434 	skcipher_request_set_callback(&creq->req, aead_request_flags(req),
435 				      chacha_encrypt_done, req);
436 	skcipher_request_set_tfm(&creq->req, ctx->chacha);
437 	skcipher_request_set_crypt(&creq->req, src, dst,
438 				   req->cryptlen, creq->iv);
439 	err = crypto_skcipher_encrypt(&creq->req);
440 	if (err)
441 		return err;
442 
443 skip:
444 	return poly_genkey(req);
445 }
446 
447 static int chachapoly_encrypt(struct aead_request *req)
448 {
449 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
450 
451 	rctx->cryptlen = req->cryptlen;
452 
453 	/* encrypt call chain:
454 	 * - chacha_encrypt/done()
455 	 * - poly_genkey/done()
456 	 * - poly_init/done()
457 	 * - poly_setkey/done()
458 	 * - poly_ad/done()
459 	 * - poly_adpad/done()
460 	 * - poly_cipher/done()
461 	 * - poly_cipherpad/done()
462 	 * - poly_tail/done/continue()
463 	 * - poly_copy_tag()
464 	 */
465 	return chacha_encrypt(req);
466 }
467 
468 static int chachapoly_decrypt(struct aead_request *req)
469 {
470 	struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
471 
472 	rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE;
473 
474 	/* decrypt call chain:
475 	 * - poly_genkey/done()
476 	 * - poly_init/done()
477 	 * - poly_setkey/done()
478 	 * - poly_ad/done()
479 	 * - poly_adpad/done()
480 	 * - poly_cipher/done()
481 	 * - poly_cipherpad/done()
482 	 * - poly_tail/done/continue()
483 	 * - chacha_decrypt/done()
484 	 * - poly_verify_tag()
485 	 */
486 	return poly_genkey(req);
487 }
488 
489 static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
490 			     unsigned int keylen)
491 {
492 	struct chachapoly_ctx *ctx = crypto_aead_ctx(aead);
493 	int err;
494 
495 	if (keylen != ctx->saltlen + CHACHA_KEY_SIZE)
496 		return -EINVAL;
497 
498 	keylen -= ctx->saltlen;
499 	memcpy(ctx->salt, key + keylen, ctx->saltlen);
500 
501 	crypto_skcipher_clear_flags(ctx->chacha, CRYPTO_TFM_REQ_MASK);
502 	crypto_skcipher_set_flags(ctx->chacha, crypto_aead_get_flags(aead) &
503 					       CRYPTO_TFM_REQ_MASK);
504 
505 	err = crypto_skcipher_setkey(ctx->chacha, key, keylen);
506 	crypto_aead_set_flags(aead, crypto_skcipher_get_flags(ctx->chacha) &
507 				    CRYPTO_TFM_RES_MASK);
508 	return err;
509 }
510 
511 static int chachapoly_setauthsize(struct crypto_aead *tfm,
512 				  unsigned int authsize)
513 {
514 	if (authsize != POLY1305_DIGEST_SIZE)
515 		return -EINVAL;
516 
517 	return 0;
518 }
519 
520 static int chachapoly_init(struct crypto_aead *tfm)
521 {
522 	struct aead_instance *inst = aead_alg_instance(tfm);
523 	struct chachapoly_instance_ctx *ictx = aead_instance_ctx(inst);
524 	struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
525 	struct crypto_skcipher *chacha;
526 	struct crypto_ahash *poly;
527 	unsigned long align;
528 
529 	poly = crypto_spawn_ahash(&ictx->poly);
530 	if (IS_ERR(poly))
531 		return PTR_ERR(poly);
532 
533 	chacha = crypto_spawn_skcipher(&ictx->chacha);
534 	if (IS_ERR(chacha)) {
535 		crypto_free_ahash(poly);
536 		return PTR_ERR(chacha);
537 	}
538 
539 	ctx->chacha = chacha;
540 	ctx->poly = poly;
541 	ctx->saltlen = ictx->saltlen;
542 
543 	align = crypto_aead_alignmask(tfm);
544 	align &= ~(crypto_tfm_ctx_alignment() - 1);
545 	crypto_aead_set_reqsize(
546 		tfm,
547 		align + offsetof(struct chachapoly_req_ctx, u) +
548 		max(offsetof(struct chacha_req, req) +
549 		    sizeof(struct skcipher_request) +
550 		    crypto_skcipher_reqsize(chacha),
551 		    offsetof(struct poly_req, req) +
552 		    sizeof(struct ahash_request) +
553 		    crypto_ahash_reqsize(poly)));
554 
555 	return 0;
556 }
557 
558 static void chachapoly_exit(struct crypto_aead *tfm)
559 {
560 	struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
561 
562 	crypto_free_ahash(ctx->poly);
563 	crypto_free_skcipher(ctx->chacha);
564 }
565 
566 static void chachapoly_free(struct aead_instance *inst)
567 {
568 	struct chachapoly_instance_ctx *ctx = aead_instance_ctx(inst);
569 
570 	crypto_drop_skcipher(&ctx->chacha);
571 	crypto_drop_ahash(&ctx->poly);
572 	kfree(inst);
573 }
574 
575 static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
576 			     const char *name, unsigned int ivsize)
577 {
578 	struct crypto_attr_type *algt;
579 	struct aead_instance *inst;
580 	struct skcipher_alg *chacha;
581 	struct crypto_alg *poly;
582 	struct hash_alg_common *poly_hash;
583 	struct chachapoly_instance_ctx *ctx;
584 	const char *chacha_name, *poly_name;
585 	int err;
586 
587 	if (ivsize > CHACHAPOLY_IV_SIZE)
588 		return -EINVAL;
589 
590 	algt = crypto_get_attr_type(tb);
591 	if (IS_ERR(algt))
592 		return PTR_ERR(algt);
593 
594 	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
595 		return -EINVAL;
596 
597 	chacha_name = crypto_attr_alg_name(tb[1]);
598 	if (IS_ERR(chacha_name))
599 		return PTR_ERR(chacha_name);
600 	poly_name = crypto_attr_alg_name(tb[2]);
601 	if (IS_ERR(poly_name))
602 		return PTR_ERR(poly_name);
603 
604 	poly = crypto_find_alg(poly_name, &crypto_ahash_type,
605 			       CRYPTO_ALG_TYPE_HASH,
606 			       CRYPTO_ALG_TYPE_AHASH_MASK |
607 			       crypto_requires_sync(algt->type,
608 						    algt->mask));
609 	if (IS_ERR(poly))
610 		return PTR_ERR(poly);
611 	poly_hash = __crypto_hash_alg_common(poly);
612 
613 	err = -EINVAL;
614 	if (poly_hash->digestsize != POLY1305_DIGEST_SIZE)
615 		goto out_put_poly;
616 
617 	err = -ENOMEM;
618 	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
619 	if (!inst)
620 		goto out_put_poly;
621 
622 	ctx = aead_instance_ctx(inst);
623 	ctx->saltlen = CHACHAPOLY_IV_SIZE - ivsize;
624 	err = crypto_init_ahash_spawn(&ctx->poly, poly_hash,
625 				      aead_crypto_instance(inst));
626 	if (err)
627 		goto err_free_inst;
628 
629 	crypto_set_skcipher_spawn(&ctx->chacha, aead_crypto_instance(inst));
630 	err = crypto_grab_skcipher(&ctx->chacha, chacha_name, 0,
631 				   crypto_requires_sync(algt->type,
632 							algt->mask));
633 	if (err)
634 		goto err_drop_poly;
635 
636 	chacha = crypto_spawn_skcipher_alg(&ctx->chacha);
637 
638 	err = -EINVAL;
639 	/* Need 16-byte IV size, including Initial Block Counter value */
640 	if (crypto_skcipher_alg_ivsize(chacha) != CHACHA_IV_SIZE)
641 		goto out_drop_chacha;
642 	/* Not a stream cipher? */
643 	if (chacha->base.cra_blocksize != 1)
644 		goto out_drop_chacha;
645 
646 	err = -ENAMETOOLONG;
647 	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
648 		     "%s(%s,%s)", name, chacha->base.cra_name,
649 		     poly->cra_name) >= CRYPTO_MAX_ALG_NAME)
650 		goto out_drop_chacha;
651 	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
652 		     "%s(%s,%s)", name, chacha->base.cra_driver_name,
653 		     poly->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
654 		goto out_drop_chacha;
655 
656 	inst->alg.base.cra_flags = (chacha->base.cra_flags | poly->cra_flags) &
657 				   CRYPTO_ALG_ASYNC;
658 	inst->alg.base.cra_priority = (chacha->base.cra_priority +
659 				       poly->cra_priority) / 2;
660 	inst->alg.base.cra_blocksize = 1;
661 	inst->alg.base.cra_alignmask = chacha->base.cra_alignmask |
662 				       poly->cra_alignmask;
663 	inst->alg.base.cra_ctxsize = sizeof(struct chachapoly_ctx) +
664 				     ctx->saltlen;
665 	inst->alg.ivsize = ivsize;
666 	inst->alg.chunksize = crypto_skcipher_alg_chunksize(chacha);
667 	inst->alg.maxauthsize = POLY1305_DIGEST_SIZE;
668 	inst->alg.init = chachapoly_init;
669 	inst->alg.exit = chachapoly_exit;
670 	inst->alg.encrypt = chachapoly_encrypt;
671 	inst->alg.decrypt = chachapoly_decrypt;
672 	inst->alg.setkey = chachapoly_setkey;
673 	inst->alg.setauthsize = chachapoly_setauthsize;
674 
675 	inst->free = chachapoly_free;
676 
677 	err = aead_register_instance(tmpl, inst);
678 	if (err)
679 		goto out_drop_chacha;
680 
681 out_put_poly:
682 	crypto_mod_put(poly);
683 	return err;
684 
685 out_drop_chacha:
686 	crypto_drop_skcipher(&ctx->chacha);
687 err_drop_poly:
688 	crypto_drop_ahash(&ctx->poly);
689 err_free_inst:
690 	kfree(inst);
691 	goto out_put_poly;
692 }
693 
694 static int rfc7539_create(struct crypto_template *tmpl, struct rtattr **tb)
695 {
696 	return chachapoly_create(tmpl, tb, "rfc7539", 12);
697 }
698 
699 static int rfc7539esp_create(struct crypto_template *tmpl, struct rtattr **tb)
700 {
701 	return chachapoly_create(tmpl, tb, "rfc7539esp", 8);
702 }
703 
704 static struct crypto_template rfc7539_tmpls[] = {
705 	{
706 		.name = "rfc7539",
707 		.create = rfc7539_create,
708 		.module = THIS_MODULE,
709 	}, {
710 		.name = "rfc7539esp",
711 		.create = rfc7539esp_create,
712 		.module = THIS_MODULE,
713 	},
714 };
715 
716 static int __init chacha20poly1305_module_init(void)
717 {
718 	return crypto_register_templates(rfc7539_tmpls,
719 					 ARRAY_SIZE(rfc7539_tmpls));
720 }
721 
722 static void __exit chacha20poly1305_module_exit(void)
723 {
724 	crypto_unregister_templates(rfc7539_tmpls,
725 				    ARRAY_SIZE(rfc7539_tmpls));
726 }
727 
728 subsys_initcall(chacha20poly1305_module_init);
729 module_exit(chacha20poly1305_module_exit);
730 
731 MODULE_LICENSE("GPL");
732 MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");
733 MODULE_DESCRIPTION("ChaCha20-Poly1305 AEAD");
734 MODULE_ALIAS_CRYPTO("rfc7539");
735 MODULE_ALIAS_CRYPTO("rfc7539esp");
736