1 /* $OpenBSD: e_chacha20poly1305.c,v 1.32 2023/09/28 11:29:10 tb Exp $ */
2 
3 /*
4  * Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
5  * Copyright (c) 2015 Reyk Floter <reyk@openbsd.org>
6  * Copyright (c) 2014, Google Inc.
7  *
8  * Permission to use, copy, modify, and/or distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
17  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <limits.h>
22 #include <stdint.h>
23 #include <string.h>
24 
25 #include <openssl/opensslconf.h>
26 
27 #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
28 
29 #include <openssl/err.h>
30 #include <openssl/evp.h>
31 #include <openssl/chacha.h>
32 #include <openssl/poly1305.h>
33 
34 #include "bytestring.h"
35 #include "evp_local.h"
36 
37 #define POLY1305_TAG_LEN 16
38 
39 #define CHACHA20_CONSTANT_LEN 4
40 #define CHACHA20_IV_LEN 8
41 #define CHACHA20_NONCE_LEN (CHACHA20_CONSTANT_LEN + CHACHA20_IV_LEN)
42 #define XCHACHA20_NONCE_LEN 24
43 
44 struct aead_chacha20_poly1305_ctx {
45 	unsigned char key[32];
46 	unsigned char tag_len;
47 };
48 
49 static int
50 aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const unsigned char *key,
51     size_t key_len, size_t tag_len)
52 {
53 	struct aead_chacha20_poly1305_ctx *c20_ctx;
54 
55 	if (tag_len == 0)
56 		tag_len = POLY1305_TAG_LEN;
57 
58 	if (tag_len > POLY1305_TAG_LEN) {
59 		EVPerror(EVP_R_TOO_LARGE);
60 		return 0;
61 	}
62 
63 	/* Internal error - EVP_AEAD_CTX_init should catch this. */
64 	if (key_len != sizeof(c20_ctx->key))
65 		return 0;
66 
67 	c20_ctx = malloc(sizeof(struct aead_chacha20_poly1305_ctx));
68 	if (c20_ctx == NULL)
69 		return 0;
70 
71 	memcpy(&c20_ctx->key[0], key, key_len);
72 	c20_ctx->tag_len = tag_len;
73 	ctx->aead_state = c20_ctx;
74 
75 	return 1;
76 }
77 
78 static void
79 aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx)
80 {
81 	struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
82 
83 	freezero(c20_ctx, sizeof(*c20_ctx));
84 }
85 
86 static void
87 poly1305_update_with_length(poly1305_state *poly1305,
88     const unsigned char *data, size_t data_len)
89 {
90 	size_t j = data_len;
91 	unsigned char length_bytes[8];
92 	unsigned i;
93 
94 	for (i = 0; i < sizeof(length_bytes); i++) {
95 		length_bytes[i] = j;
96 		j >>= 8;
97 	}
98 
99 	if (data != NULL)
100 		CRYPTO_poly1305_update(poly1305, data, data_len);
101 	CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
102 }
103 
104 static void
105 poly1305_pad16(poly1305_state *poly1305, size_t data_len)
106 {
107 	static const unsigned char zero_pad16[16];
108 	size_t pad_len;
109 
110 	/* pad16() is defined in RFC 8439 2.8.1. */
111 	if ((pad_len = data_len % 16) == 0)
112 		return;
113 
114 	CRYPTO_poly1305_update(poly1305, zero_pad16, 16 - pad_len);
115 }
116 
117 static void
118 poly1305_update_with_pad16(poly1305_state *poly1305,
119     const unsigned char *data, size_t data_len)
120 {
121 	CRYPTO_poly1305_update(poly1305, data, data_len);
122 	poly1305_pad16(poly1305, data_len);
123 }
124 
125 static int
126 aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
127     size_t *out_len, size_t max_out_len, const unsigned char *nonce,
128     size_t nonce_len, const unsigned char *in, size_t in_len,
129     const unsigned char *ad, size_t ad_len)
130 {
131 	const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
132 	unsigned char poly1305_key[32];
133 	poly1305_state poly1305;
134 	const unsigned char *iv;
135 	uint64_t ctr;
136 
137 	if (max_out_len < in_len + c20_ctx->tag_len) {
138 		EVPerror(EVP_R_BUFFER_TOO_SMALL);
139 		return 0;
140 	}
141 
142 	if (nonce_len != ctx->aead->nonce_len) {
143 		EVPerror(EVP_R_IV_TOO_LARGE);
144 		return 0;
145 	}
146 
147 	ctr = (uint64_t)((uint32_t)(nonce[0]) | (uint32_t)(nonce[1]) << 8 |
148 	    (uint32_t)(nonce[2]) << 16 | (uint32_t)(nonce[3]) << 24) << 32;
149 	iv = nonce + CHACHA20_CONSTANT_LEN;
150 
151 	memset(poly1305_key, 0, sizeof(poly1305_key));
152 	CRYPTO_chacha_20(poly1305_key, poly1305_key,
153 	    sizeof(poly1305_key), c20_ctx->key, iv, ctr);
154 
155 	CRYPTO_poly1305_init(&poly1305, poly1305_key);
156 	poly1305_update_with_pad16(&poly1305, ad, ad_len);
157 	CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, iv, ctr + 1);
158 	poly1305_update_with_pad16(&poly1305, out, in_len);
159 	poly1305_update_with_length(&poly1305, NULL, ad_len);
160 	poly1305_update_with_length(&poly1305, NULL, in_len);
161 
162 	if (c20_ctx->tag_len != POLY1305_TAG_LEN) {
163 		unsigned char tag[POLY1305_TAG_LEN];
164 		CRYPTO_poly1305_finish(&poly1305, tag);
165 		memcpy(out + in_len, tag, c20_ctx->tag_len);
166 		*out_len = in_len + c20_ctx->tag_len;
167 		return 1;
168 	}
169 
170 	CRYPTO_poly1305_finish(&poly1305, out + in_len);
171 	*out_len = in_len + POLY1305_TAG_LEN;
172 	return 1;
173 }
174 
175 static int
176 aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
177     size_t *out_len, size_t max_out_len, const unsigned char *nonce,
178     size_t nonce_len, const unsigned char *in, size_t in_len,
179     const unsigned char *ad, size_t ad_len)
180 {
181 	const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
182 	unsigned char mac[POLY1305_TAG_LEN];
183 	unsigned char poly1305_key[32];
184 	const unsigned char *iv = nonce;
185 	poly1305_state poly1305;
186 	size_t plaintext_len;
187 	uint64_t ctr = 0;
188 
189 	if (in_len < c20_ctx->tag_len) {
190 		EVPerror(EVP_R_BAD_DECRYPT);
191 		return 0;
192 	}
193 
194 	if (nonce_len != ctx->aead->nonce_len) {
195 		EVPerror(EVP_R_IV_TOO_LARGE);
196 		return 0;
197 	}
198 
199 	plaintext_len = in_len - c20_ctx->tag_len;
200 
201 	if (max_out_len < plaintext_len) {
202 		EVPerror(EVP_R_BUFFER_TOO_SMALL);
203 		return 0;
204 	}
205 
206 	ctr = (uint64_t)((uint32_t)(nonce[0]) | (uint32_t)(nonce[1]) << 8 |
207 	    (uint32_t)(nonce[2]) << 16 | (uint32_t)(nonce[3]) << 24) << 32;
208 	iv = nonce + CHACHA20_CONSTANT_LEN;
209 
210 	memset(poly1305_key, 0, sizeof(poly1305_key));
211 	CRYPTO_chacha_20(poly1305_key, poly1305_key,
212 	    sizeof(poly1305_key), c20_ctx->key, iv, ctr);
213 
214 	CRYPTO_poly1305_init(&poly1305, poly1305_key);
215 	poly1305_update_with_pad16(&poly1305, ad, ad_len);
216 	poly1305_update_with_pad16(&poly1305, in, plaintext_len);
217 	poly1305_update_with_length(&poly1305, NULL, ad_len);
218 	poly1305_update_with_length(&poly1305, NULL, plaintext_len);
219 
220 	CRYPTO_poly1305_finish(&poly1305, mac);
221 
222 	if (timingsafe_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) {
223 		EVPerror(EVP_R_BAD_DECRYPT);
224 		return 0;
225 	}
226 
227 	CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, iv, ctr + 1);
228 	*out_len = plaintext_len;
229 	return 1;
230 }
231 
232 static int
233 aead_xchacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
234     size_t *out_len, size_t max_out_len, const unsigned char *nonce,
235     size_t nonce_len, const unsigned char *in, size_t in_len,
236     const unsigned char *ad, size_t ad_len)
237 {
238 	const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
239 	unsigned char poly1305_key[32];
240 	unsigned char subkey[32];
241 	poly1305_state poly1305;
242 
243 	if (max_out_len < in_len + c20_ctx->tag_len) {
244 		EVPerror(EVP_R_BUFFER_TOO_SMALL);
245 		return 0;
246 	}
247 
248 	if (nonce_len != ctx->aead->nonce_len) {
249 		EVPerror(EVP_R_IV_TOO_LARGE);
250 		return 0;
251 	}
252 
253 	CRYPTO_hchacha_20(subkey, c20_ctx->key, nonce);
254 
255 	CRYPTO_chacha_20(out, in, in_len, subkey, nonce + 16, 1);
256 
257 	memset(poly1305_key, 0, sizeof(poly1305_key));
258 	CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
259 	    subkey, nonce + 16, 0);
260 
261 	CRYPTO_poly1305_init(&poly1305, poly1305_key);
262 	poly1305_update_with_pad16(&poly1305, ad, ad_len);
263 	poly1305_update_with_pad16(&poly1305, out, in_len);
264 	poly1305_update_with_length(&poly1305, NULL, ad_len);
265 	poly1305_update_with_length(&poly1305, NULL, in_len);
266 
267 	if (c20_ctx->tag_len != POLY1305_TAG_LEN) {
268 		unsigned char tag[POLY1305_TAG_LEN];
269 		CRYPTO_poly1305_finish(&poly1305, tag);
270 		memcpy(out + in_len, tag, c20_ctx->tag_len);
271 		*out_len = in_len + c20_ctx->tag_len;
272 		return 1;
273 	}
274 
275 	CRYPTO_poly1305_finish(&poly1305, out + in_len);
276 	*out_len = in_len + POLY1305_TAG_LEN;
277 	return 1;
278 }
279 
280 static int
281 aead_xchacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
282     size_t *out_len, size_t max_out_len, const unsigned char *nonce,
283     size_t nonce_len, const unsigned char *in, size_t in_len,
284     const unsigned char *ad, size_t ad_len)
285 {
286 	const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
287 	unsigned char mac[POLY1305_TAG_LEN];
288 	unsigned char poly1305_key[32];
289 	unsigned char subkey[32];
290 	poly1305_state poly1305;
291 	size_t plaintext_len;
292 
293 	if (in_len < c20_ctx->tag_len) {
294 		EVPerror(EVP_R_BAD_DECRYPT);
295 		return 0;
296 	}
297 
298 	if (nonce_len != ctx->aead->nonce_len) {
299 		EVPerror(EVP_R_IV_TOO_LARGE);
300 		return 0;
301 	}
302 
303 	plaintext_len = in_len - c20_ctx->tag_len;
304 
305 	if (max_out_len < plaintext_len) {
306 		EVPerror(EVP_R_BUFFER_TOO_SMALL);
307 		return 0;
308 	}
309 
310 	CRYPTO_hchacha_20(subkey, c20_ctx->key, nonce);
311 
312 	memset(poly1305_key, 0, sizeof(poly1305_key));
313 	CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
314 	    subkey, nonce + 16, 0);
315 
316 	CRYPTO_poly1305_init(&poly1305, poly1305_key);
317 	poly1305_update_with_pad16(&poly1305, ad, ad_len);
318 	poly1305_update_with_pad16(&poly1305, in, plaintext_len);
319 	poly1305_update_with_length(&poly1305, NULL, ad_len);
320 	poly1305_update_with_length(&poly1305, NULL, plaintext_len);
321 
322 	CRYPTO_poly1305_finish(&poly1305, mac);
323 	if (timingsafe_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) {
324 		EVPerror(EVP_R_BAD_DECRYPT);
325 		return 0;
326 	}
327 
328 	CRYPTO_chacha_20(out, in, plaintext_len, subkey, nonce + 16, 1);
329 
330 	*out_len = plaintext_len;
331 	return 1;
332 }
333 
334 /* RFC 8439 */
335 static const EVP_AEAD aead_chacha20_poly1305 = {
336 	.key_len = 32,
337 	.nonce_len = CHACHA20_NONCE_LEN,
338 	.overhead = POLY1305_TAG_LEN,
339 	.max_tag_len = POLY1305_TAG_LEN,
340 
341 	.init = aead_chacha20_poly1305_init,
342 	.cleanup = aead_chacha20_poly1305_cleanup,
343 	.seal = aead_chacha20_poly1305_seal,
344 	.open = aead_chacha20_poly1305_open,
345 };
346 
347 const EVP_AEAD *
348 EVP_aead_chacha20_poly1305()
349 {
350 	return &aead_chacha20_poly1305;
351 }
352 
353 static const EVP_AEAD aead_xchacha20_poly1305 = {
354 	.key_len = 32,
355 	.nonce_len = XCHACHA20_NONCE_LEN,
356 	.overhead = POLY1305_TAG_LEN,
357 	.max_tag_len = POLY1305_TAG_LEN,
358 
359 	.init = aead_chacha20_poly1305_init,
360 	.cleanup = aead_chacha20_poly1305_cleanup,
361 	.seal = aead_xchacha20_poly1305_seal,
362 	.open = aead_xchacha20_poly1305_open,
363 };
364 
365 const EVP_AEAD *
366 EVP_aead_xchacha20_poly1305()
367 {
368 	return &aead_xchacha20_poly1305;
369 }
370 
371 struct chacha20_poly1305_ctx {
372 	ChaCha_ctx chacha;
373 	poly1305_state poly1305;
374 
375 	unsigned char key[32];
376 	unsigned char nonce[CHACHA20_NONCE_LEN];
377 	size_t nonce_len;
378 	unsigned char tag[POLY1305_TAG_LEN];
379 	size_t tag_len;
380 
381 	size_t ad_len;
382 	size_t in_len;
383 
384 	int in_ad;
385 	int started;
386 };
387 
388 static int
389 chacha20_poly1305_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
390     const unsigned char *iv, int encrypt)
391 {
392 	struct chacha20_poly1305_ctx *cpx = ctx->cipher_data;
393 	uint8_t *data;
394 	CBB cbb;
395 	int ret = 0;
396 
397 	memset(&cbb, 0, sizeof(cbb));
398 
399 	if (key == NULL && iv == NULL)
400 		goto done;
401 
402 	cpx->started = 0;
403 
404 	if (key != NULL)
405 		memcpy(cpx->key, key, sizeof(cpx->key));
406 
407 	if (iv != NULL) {
408 		/*
409 		 * Left zero pad if configured nonce length is less than ChaCha
410 		 * nonce length.
411 		 */
412 		if (!CBB_init_fixed(&cbb, cpx->nonce, sizeof(cpx->nonce)))
413 			goto err;
414 		if (!CBB_add_space(&cbb, &data, sizeof(cpx->nonce) - cpx->nonce_len))
415 			goto err;
416 		if (!CBB_add_bytes(&cbb, iv, cpx->nonce_len))
417 			goto err;
418 		if (!CBB_finish(&cbb, NULL, NULL))
419 			goto err;
420 	}
421 
422  done:
423 	ret = 1;
424 
425  err:
426 	CBB_cleanup(&cbb);
427 
428 	return ret;
429 }
430 
431 static int
432 chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
433     const unsigned char *in, size_t len)
434 {
435 	struct chacha20_poly1305_ctx *cpx = ctx->cipher_data;
436 
437 	/*
438 	 * Since we're making AEAD work within the constraints of EVP_CIPHER...
439 	 * If in is non-NULL then this is an update, while if in is NULL then
440 	 * this is a final. If in is non-NULL but out is NULL, then the input
441 	 * being provided is associated data. Plus we have to handle encryption
442 	 * (sealing) and decryption (opening) in the same function.
443 	 */
444 
445 	if (!cpx->started) {
446 		unsigned char poly1305_key[32];
447 		const unsigned char *iv;
448 		uint64_t ctr;
449 
450 		ctr = (uint64_t)((uint32_t)(cpx->nonce[0]) |
451 		    (uint32_t)(cpx->nonce[1]) << 8 |
452 		    (uint32_t)(cpx->nonce[2]) << 16 |
453 		    (uint32_t)(cpx->nonce[3]) << 24) << 32;
454 		iv = cpx->nonce + CHACHA20_CONSTANT_LEN;
455 
456 		ChaCha_set_key(&cpx->chacha, cpx->key, 8 * sizeof(cpx->key));
457 		ChaCha_set_iv(&cpx->chacha, iv, NULL);
458 
459 		/* See chacha.c for details re handling of counter. */
460 		cpx->chacha.input[12] = (uint32_t)ctr;
461 		cpx->chacha.input[13] = (uint32_t)(ctr >> 32);
462 
463 		memset(poly1305_key, 0, sizeof(poly1305_key));
464 		ChaCha(&cpx->chacha, poly1305_key, poly1305_key,
465 		    sizeof(poly1305_key));
466 		CRYPTO_poly1305_init(&cpx->poly1305, poly1305_key);
467 
468 		/* Mark remaining key block as used. */
469 		cpx->chacha.unused = 0;
470 
471 		cpx->ad_len = 0;
472 		cpx->in_len = 0;
473 		cpx->in_ad = 0;
474 
475 		cpx->started = 1;
476 	}
477 
478 	if (len > SIZE_MAX - cpx->in_len) {
479 		EVPerror(EVP_R_TOO_LARGE);
480 		return 0;
481 	}
482 
483 	/* Disallow authenticated data after plaintext/ciphertext. */
484 	if (cpx->in_len > 0 && in != NULL && out == NULL)
485 		return -1;
486 
487 	if (cpx->in_ad && (in == NULL || out != NULL)) {
488 		poly1305_pad16(&cpx->poly1305, cpx->ad_len);
489 		cpx->in_ad = 0;
490 	}
491 
492 	/* Update with AD or plaintext/ciphertext. */
493 	if (in != NULL) {
494 		if (out == NULL) {
495 			cpx->ad_len += len;
496 			cpx->in_ad = 1;
497 		} else {
498 			ChaCha(&cpx->chacha, out, in, len);
499 			cpx->in_len += len;
500 		}
501 		if (ctx->encrypt && out != NULL)
502 			CRYPTO_poly1305_update(&cpx->poly1305, out, len);
503 		else
504 			CRYPTO_poly1305_update(&cpx->poly1305, in, len);
505 
506 		return len;
507 	}
508 
509 	/* Final. */
510 	poly1305_pad16(&cpx->poly1305, cpx->in_len);
511 	poly1305_update_with_length(&cpx->poly1305, NULL, cpx->ad_len);
512 	poly1305_update_with_length(&cpx->poly1305, NULL, cpx->in_len);
513 
514 	if (ctx->encrypt) {
515 		CRYPTO_poly1305_finish(&cpx->poly1305, cpx->tag);
516 		cpx->tag_len = sizeof(cpx->tag);
517 	} else {
518 		unsigned char tag[POLY1305_TAG_LEN];
519 
520 		/* Ensure that a tag has been provided. */
521 		if (cpx->tag_len <= 0)
522 			return -1;
523 
524 		CRYPTO_poly1305_finish(&cpx->poly1305, tag);
525 		if (timingsafe_memcmp(tag, cpx->tag, cpx->tag_len) != 0)
526 			return -1;
527 	}
528 
529 	cpx->started = 0;
530 
531 	return len;
532 }
533 
534 static int
535 chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx)
536 {
537 	struct chacha20_poly1305_ctx *cpx = ctx->cipher_data;
538 
539 	explicit_bzero(cpx, sizeof(*cpx));
540 
541 	return 1;
542 }
543 
544 static int
545 chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
546 {
547 	struct chacha20_poly1305_ctx *cpx = ctx->cipher_data;
548 
549 	switch (type) {
550 	case EVP_CTRL_INIT:
551 		memset(cpx, 0, sizeof(*cpx));
552 		cpx->nonce_len = sizeof(cpx->nonce);
553 		return 1;
554 
555 	case EVP_CTRL_AEAD_GET_IVLEN:
556 		if (cpx->nonce_len > INT_MAX)
557 			return 0;
558 		*(int *)ptr = (int)cpx->nonce_len;
559 		return 1;
560 
561 	case EVP_CTRL_AEAD_SET_IVLEN:
562 		if (arg <= 0 || arg > sizeof(cpx->nonce))
563 			return 0;
564 		cpx->nonce_len = arg;
565 		return 1;
566 
567 	case EVP_CTRL_AEAD_SET_TAG:
568 		if (ctx->encrypt)
569 			return 0;
570 		if (arg <= 0 || arg > sizeof(cpx->tag))
571 			return 0;
572 		if (ptr != NULL) {
573 			memcpy(cpx->tag, ptr, arg);
574 			cpx->tag_len = arg;
575 		}
576 		return 1;
577 
578 	case EVP_CTRL_AEAD_GET_TAG:
579 		if (!ctx->encrypt)
580 			return 0;
581 		if (arg <= 0 || arg > cpx->tag_len)
582 			return 0;
583 		memcpy(ptr, cpx->tag, arg);
584 		return 1;
585 
586 	case EVP_CTRL_AEAD_SET_IV_FIXED:
587 		if (arg != sizeof(cpx->nonce))
588 			return 0;
589 		memcpy(cpx->nonce, ptr, arg);
590 		return 1;
591 	}
592 
593 	return 0;
594 }
595 
596 static const EVP_CIPHER cipher_chacha20_poly1305 = {
597 	.nid = NID_chacha20_poly1305,
598 	.block_size = 1,
599 	.key_len = 32,
600 	.iv_len = 12,
601 	.flags = EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
602 	    EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_IV_LENGTH |
603 	    EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_CUSTOM_CIPHER |
604 	    EVP_CIPH_FLAG_DEFAULT_ASN1,
605 	.init = chacha20_poly1305_init,
606 	.do_cipher = chacha20_poly1305_cipher,
607 	.cleanup = chacha20_poly1305_cleanup,
608 	.ctx_size = sizeof(struct chacha20_poly1305_ctx),
609 	.ctrl = chacha20_poly1305_ctrl,
610 };
611 
612 const EVP_CIPHER *
613 EVP_chacha20_poly1305(void)
614 {
615 	return &cipher_chacha20_poly1305;
616 }
617 
618 #endif  /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */
619