1 /* $OpenBSD: e_chacha20poly1305.c,v 1.35 2024/04/09 13:52:41 beck 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(void) 349 { 350 return &aead_chacha20_poly1305; 351 } 352 LCRYPTO_ALIAS(EVP_aead_chacha20_poly1305); 353 354 static const EVP_AEAD aead_xchacha20_poly1305 = { 355 .key_len = 32, 356 .nonce_len = XCHACHA20_NONCE_LEN, 357 .overhead = POLY1305_TAG_LEN, 358 .max_tag_len = POLY1305_TAG_LEN, 359 360 .init = aead_chacha20_poly1305_init, 361 .cleanup = aead_chacha20_poly1305_cleanup, 362 .seal = aead_xchacha20_poly1305_seal, 363 .open = aead_xchacha20_poly1305_open, 364 }; 365 366 const EVP_AEAD * 367 EVP_aead_xchacha20_poly1305(void) 368 { 369 return &aead_xchacha20_poly1305; 370 } 371 LCRYPTO_ALIAS(EVP_aead_xchacha20_poly1305); 372 373 struct chacha20_poly1305_ctx { 374 ChaCha_ctx chacha; 375 poly1305_state poly1305; 376 377 unsigned char key[32]; 378 unsigned char nonce[CHACHA20_NONCE_LEN]; 379 size_t nonce_len; 380 unsigned char tag[POLY1305_TAG_LEN]; 381 size_t tag_len; 382 383 size_t ad_len; 384 size_t in_len; 385 386 int in_ad; 387 int started; 388 }; 389 390 static int 391 chacha20_poly1305_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 392 const unsigned char *iv, int encrypt) 393 { 394 struct chacha20_poly1305_ctx *cpx = ctx->cipher_data; 395 uint8_t *data; 396 CBB cbb; 397 int ret = 0; 398 399 memset(&cbb, 0, sizeof(cbb)); 400 401 if (key == NULL && iv == NULL) 402 goto done; 403 404 cpx->started = 0; 405 406 if (key != NULL) 407 memcpy(cpx->key, key, sizeof(cpx->key)); 408 409 if (iv != NULL) { 410 /* 411 * Left zero pad if configured nonce length is less than ChaCha 412 * nonce length. 413 */ 414 if (!CBB_init_fixed(&cbb, cpx->nonce, sizeof(cpx->nonce))) 415 goto err; 416 if (!CBB_add_space(&cbb, &data, sizeof(cpx->nonce) - cpx->nonce_len)) 417 goto err; 418 if (!CBB_add_bytes(&cbb, iv, cpx->nonce_len)) 419 goto err; 420 if (!CBB_finish(&cbb, NULL, NULL)) 421 goto err; 422 } 423 424 done: 425 ret = 1; 426 427 err: 428 CBB_cleanup(&cbb); 429 430 return ret; 431 } 432 433 static int 434 chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 435 const unsigned char *in, size_t len) 436 { 437 struct chacha20_poly1305_ctx *cpx = ctx->cipher_data; 438 439 /* 440 * Since we're making AEAD work within the constraints of EVP_CIPHER... 441 * If in is non-NULL then this is an update, while if in is NULL then 442 * this is a final. If in is non-NULL but out is NULL, then the input 443 * being provided is associated data. Plus we have to handle encryption 444 * (sealing) and decryption (opening) in the same function. 445 */ 446 447 if (!cpx->started) { 448 unsigned char poly1305_key[32]; 449 const unsigned char *iv; 450 uint64_t ctr; 451 452 ctr = (uint64_t)((uint32_t)(cpx->nonce[0]) | 453 (uint32_t)(cpx->nonce[1]) << 8 | 454 (uint32_t)(cpx->nonce[2]) << 16 | 455 (uint32_t)(cpx->nonce[3]) << 24) << 32; 456 iv = cpx->nonce + CHACHA20_CONSTANT_LEN; 457 458 ChaCha_set_key(&cpx->chacha, cpx->key, 8 * sizeof(cpx->key)); 459 ChaCha_set_iv(&cpx->chacha, iv, NULL); 460 461 /* See chacha.c for details re handling of counter. */ 462 cpx->chacha.input[12] = (uint32_t)ctr; 463 cpx->chacha.input[13] = (uint32_t)(ctr >> 32); 464 465 memset(poly1305_key, 0, sizeof(poly1305_key)); 466 ChaCha(&cpx->chacha, poly1305_key, poly1305_key, 467 sizeof(poly1305_key)); 468 CRYPTO_poly1305_init(&cpx->poly1305, poly1305_key); 469 470 /* Mark remaining key block as used. */ 471 cpx->chacha.unused = 0; 472 473 cpx->ad_len = 0; 474 cpx->in_len = 0; 475 cpx->in_ad = 0; 476 477 cpx->started = 1; 478 } 479 480 if (len > SIZE_MAX - cpx->in_len) { 481 EVPerror(EVP_R_TOO_LARGE); 482 return -1; 483 } 484 485 /* Disallow authenticated data after plaintext/ciphertext. */ 486 if (cpx->in_len > 0 && in != NULL && out == NULL) 487 return -1; 488 489 if (cpx->in_ad && (in == NULL || out != NULL)) { 490 poly1305_pad16(&cpx->poly1305, cpx->ad_len); 491 cpx->in_ad = 0; 492 } 493 494 /* Update with AD or plaintext/ciphertext. */ 495 if (in != NULL) { 496 if (out == NULL) { 497 cpx->ad_len += len; 498 cpx->in_ad = 1; 499 } else { 500 ChaCha(&cpx->chacha, out, in, len); 501 cpx->in_len += len; 502 } 503 if (ctx->encrypt && out != NULL) 504 CRYPTO_poly1305_update(&cpx->poly1305, out, len); 505 else 506 CRYPTO_poly1305_update(&cpx->poly1305, in, len); 507 508 return len; 509 } 510 511 /* Final. */ 512 poly1305_pad16(&cpx->poly1305, cpx->in_len); 513 poly1305_update_with_length(&cpx->poly1305, NULL, cpx->ad_len); 514 poly1305_update_with_length(&cpx->poly1305, NULL, cpx->in_len); 515 516 if (ctx->encrypt) { 517 CRYPTO_poly1305_finish(&cpx->poly1305, cpx->tag); 518 cpx->tag_len = sizeof(cpx->tag); 519 } else { 520 unsigned char tag[POLY1305_TAG_LEN]; 521 522 /* Ensure that a tag has been provided. */ 523 if (cpx->tag_len <= 0) 524 return -1; 525 526 CRYPTO_poly1305_finish(&cpx->poly1305, tag); 527 if (timingsafe_memcmp(tag, cpx->tag, cpx->tag_len) != 0) 528 return -1; 529 } 530 531 cpx->started = 0; 532 533 return len; 534 } 535 536 static int 537 chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx) 538 { 539 struct chacha20_poly1305_ctx *cpx = ctx->cipher_data; 540 541 explicit_bzero(cpx, sizeof(*cpx)); 542 543 return 1; 544 } 545 546 static int 547 chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) 548 { 549 struct chacha20_poly1305_ctx *cpx = ctx->cipher_data; 550 551 switch (type) { 552 case EVP_CTRL_INIT: 553 memset(cpx, 0, sizeof(*cpx)); 554 cpx->nonce_len = sizeof(cpx->nonce); 555 return 1; 556 557 case EVP_CTRL_AEAD_GET_IVLEN: 558 if (cpx->nonce_len > INT_MAX) 559 return 0; 560 *(int *)ptr = (int)cpx->nonce_len; 561 return 1; 562 563 case EVP_CTRL_AEAD_SET_IVLEN: 564 if (arg <= 0 || arg > sizeof(cpx->nonce)) 565 return 0; 566 cpx->nonce_len = arg; 567 return 1; 568 569 case EVP_CTRL_AEAD_SET_TAG: 570 if (ctx->encrypt) 571 return 0; 572 if (arg <= 0 || arg > sizeof(cpx->tag)) 573 return 0; 574 if (ptr != NULL) { 575 memcpy(cpx->tag, ptr, arg); 576 cpx->tag_len = arg; 577 } 578 return 1; 579 580 case EVP_CTRL_AEAD_GET_TAG: 581 if (!ctx->encrypt) 582 return 0; 583 if (arg <= 0 || arg > cpx->tag_len) 584 return 0; 585 memcpy(ptr, cpx->tag, arg); 586 return 1; 587 588 case EVP_CTRL_AEAD_SET_IV_FIXED: 589 if (arg != sizeof(cpx->nonce)) 590 return 0; 591 memcpy(cpx->nonce, ptr, arg); 592 return 1; 593 } 594 595 return 0; 596 } 597 598 static const EVP_CIPHER cipher_chacha20_poly1305 = { 599 .nid = NID_chacha20_poly1305, 600 .block_size = 1, 601 .key_len = 32, 602 .iv_len = 12, 603 .flags = EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | 604 EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_IV_LENGTH | 605 EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_CUSTOM_CIPHER | 606 EVP_CIPH_FLAG_DEFAULT_ASN1, 607 .init = chacha20_poly1305_init, 608 .do_cipher = chacha20_poly1305_cipher, 609 .cleanup = chacha20_poly1305_cleanup, 610 .ctx_size = sizeof(struct chacha20_poly1305_ctx), 611 .ctrl = chacha20_poly1305_ctrl, 612 }; 613 614 const EVP_CIPHER * 615 EVP_chacha20_poly1305(void) 616 { 617 return &cipher_chacha20_poly1305; 618 } 619 LCRYPTO_ALIAS(EVP_chacha20_poly1305); 620 621 #endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */ 622