]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/e_chacha20_poly1305.c
"foo * bar" should be "foo *bar"
[thirdparty/openssl.git] / crypto / evp / e_chacha20_poly1305.c
CommitLineData
62867571 1/*
f5afac4b 2 * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
bd989745 3 *
4a8b0c55 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
62867571
RS
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
bd989745
AP
8 */
9
10#include <stdio.h>
11#include "internal/cryptlib.h"
e23d850f 12#include "internal/endian.h"
bd989745
AP
13
14#ifndef OPENSSL_NO_CHACHA
15
16# include <openssl/evp.h>
17# include <openssl/objects.h>
25f2138b 18# include "crypto/evp.h"
706457b7 19# include "evp_local.h"
25f2138b 20# include "crypto/chacha.h"
bd989745
AP
21
22typedef struct {
23 union {
39147079 24 OSSL_UNION_ALIGN; /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
bd989745
AP
25 unsigned int d[CHACHA_KEY_SIZE / 4];
26 } key;
27 unsigned int counter[CHACHA_CTR_SIZE / 4];
28 unsigned char buf[CHACHA_BLK_SIZE];
29 unsigned int partial_len;
30} EVP_CHACHA_KEY;
31
32#define data(ctx) ((EVP_CHACHA_KEY *)(ctx)->cipher_data)
33
2a3d0ee9
MC
34#define CHACHA20_POLY1305_MAX_IVLEN 12
35
bd989745
AP
36static int chacha_init_key(EVP_CIPHER_CTX *ctx,
37 const unsigned char user_key[CHACHA_KEY_SIZE],
38 const unsigned char iv[CHACHA_CTR_SIZE], int enc)
39{
40 EVP_CHACHA_KEY *key = data(ctx);
41 unsigned int i;
42
43 if (user_key)
44 for (i = 0; i < CHACHA_KEY_SIZE; i+=4) {
45 key->key.d[i/4] = CHACHA_U8TOU32(user_key+i);
46 }
47
48 if (iv)
49 for (i = 0; i < CHACHA_CTR_SIZE; i+=4) {
50 key->counter[i/4] = CHACHA_U8TOU32(iv+i);
51 }
52
53 key->partial_len = 0;
54
55 return 1;
56}
57
bbaeadb0 58static int chacha_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
bd989745
AP
59 const unsigned char *inp, size_t len)
60{
61 EVP_CHACHA_KEY *key = data(ctx);
62 unsigned int n, rem, ctr32;
63
64 if ((n = key->partial_len)) {
65 while (len && n < CHACHA_BLK_SIZE) {
66 *out++ = *inp++ ^ key->buf[n++];
67 len--;
68 }
69 key->partial_len = n;
70
71 if (len == 0)
72 return 1;
73
74 if (n == CHACHA_BLK_SIZE) {
75 key->partial_len = 0;
76 key->counter[0]++;
77 if (key->counter[0] == 0)
78 key->counter[1]++;
79 }
80 }
81
82 rem = (unsigned int)(len % CHACHA_BLK_SIZE);
83 len -= rem;
84 ctr32 = key->counter[0];
85 while (len >= CHACHA_BLK_SIZE) {
86 size_t blocks = len / CHACHA_BLK_SIZE;
87 /*
88 * 1<<28 is just a not-so-small yet not-so-large number...
89 * Below condition is practically never met, but it has to
90 * be checked for code correctness.
91 */
92 if (sizeof(size_t)>sizeof(unsigned int) && blocks>(1U<<28))
93 blocks = (1U<<28);
94
95 /*
96 * As ChaCha20_ctr32 operates on 32-bit counter, caller
97 * has to handle overflow. 'if' below detects the
98 * overflow, which is then handled by limiting the
99 * amount of blocks to the exact overflow point...
100 */
101 ctr32 += (unsigned int)blocks;
102 if (ctr32 < blocks) {
103 blocks -= ctr32;
104 ctr32 = 0;
105 }
106 blocks *= CHACHA_BLK_SIZE;
107 ChaCha20_ctr32(out, inp, blocks, key->key.d, key->counter);
108 len -= blocks;
109 inp += blocks;
110 out += blocks;
111
112 key->counter[0] = ctr32;
113 if (ctr32 == 0) key->counter[1]++;
114 }
115
116 if (rem) {
117 memset(key->buf, 0, sizeof(key->buf));
118 ChaCha20_ctr32(key->buf, key->buf, CHACHA_BLK_SIZE,
119 key->key.d, key->counter);
120 for (n = 0; n < rem; n++)
121 out[n] = inp[n] ^ key->buf[n];
122 key->partial_len = rem;
123 }
124
125 return 1;
126}
127
128static const EVP_CIPHER chacha20 = {
129 NID_chacha20,
130 1, /* block_size */
131 CHACHA_KEY_SIZE, /* key_len */
132 CHACHA_CTR_SIZE, /* iv_len, 128-bit counter in the context */
c83680a0 133 EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT,
f6c95e46 134 EVP_ORIG_GLOBAL,
bd989745
AP
135 chacha_init_key,
136 chacha_cipher,
137 NULL,
138 sizeof(EVP_CHACHA_KEY),
139 NULL,
140 NULL,
141 NULL,
142 NULL
143};
144
145const EVP_CIPHER *EVP_chacha20(void)
146{
26a7d938 147 return &chacha20;
bd989745
AP
148}
149
150# ifndef OPENSSL_NO_POLY1305
25f2138b 151# include "crypto/poly1305.h"
bd989745
AP
152
153typedef struct {
154 EVP_CHACHA_KEY key;
155 unsigned int nonce[12/4];
156 unsigned char tag[POLY1305_BLOCK_SIZE];
a091e212 157 unsigned char tls_aad[POLY1305_BLOCK_SIZE];
bd989745
AP
158 struct { uint64_t aad, text; } len;
159 int aad, mac_inited, tag_len, nonce_len;
160 size_t tls_payload_length;
161} EVP_CHACHA_AEAD_CTX;
162
163# define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
164# define aead_data(ctx) ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data)
165# define POLY1305_ctx(actx) ((POLY1305 *)(actx + 1))
166
167static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx,
168 const unsigned char *inkey,
169 const unsigned char *iv, int enc)
170{
171 EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
bd989745
AP
172
173 if (!inkey && !iv)
174 return 1;
175
176 actx->len.aad = 0;
177 actx->len.text = 0;
178 actx->aad = 0;
179 actx->mac_inited = 0;
180 actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
181
d2dfd482
KY
182 if (iv != NULL) {
183 unsigned char temp[CHACHA_CTR_SIZE] = { 0 };
bd989745 184
d2dfd482
KY
185 /* pad on the left */
186 if (actx->nonce_len <= CHACHA_CTR_SIZE)
a091e212
AP
187 memcpy(temp + CHACHA_CTR_SIZE - actx->nonce_len, iv,
188 actx->nonce_len);
bd989745 189
d2dfd482
KY
190 chacha_init_key(ctx, inkey, temp, enc);
191
192 actx->nonce[0] = actx->key.counter[1];
193 actx->nonce[1] = actx->key.counter[2];
194 actx->nonce[2] = actx->key.counter[3];
195 } else {
196 chacha_init_key(ctx, inkey, NULL, enc);
197 }
bd989745
AP
198
199 return 1;
200}
201
a091e212 202# if !defined(OPENSSL_SMALL_FOOTPRINT)
0edb109f
AP
203
204# if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
205 defined(_M_AMD64) || defined(_M_X64))
206# define XOR128_HELPERS
207void *xor128_encrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
208void *xor128_decrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
209static const unsigned char zero[4 * CHACHA_BLK_SIZE] = { 0 };
210# else
a091e212 211static const unsigned char zero[2 * CHACHA_BLK_SIZE] = { 0 };
0edb109f 212# endif
a091e212
AP
213
214static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
215 const unsigned char *in, size_t len)
216{
217 EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
0edb109f
AP
218 size_t tail, tohash_len, buf_len, plen = actx->tls_payload_length;
219 unsigned char *buf, *tohash, *ctr, storage[sizeof(zero) + 32];
a091e212
AP
220
221 if (len != plen + POLY1305_BLOCK_SIZE)
222 return -1;
223
224 buf = storage + ((0 - (size_t)storage) & 15); /* align */
225 ctr = buf + CHACHA_BLK_SIZE;
226 tohash = buf + CHACHA_BLK_SIZE - POLY1305_BLOCK_SIZE;
227
0edb109f
AP
228# ifdef XOR128_HELPERS
229 if (plen <= 3 * CHACHA_BLK_SIZE) {
a091e212 230 actx->key.counter[0] = 0;
0edb109f
AP
231 buf_len = (plen + 2 * CHACHA_BLK_SIZE - 1) & (0 - CHACHA_BLK_SIZE);
232 ChaCha20_ctr32(buf, zero, buf_len, actx->key.key.d,
a091e212
AP
233 actx->key.counter);
234 Poly1305_Init(POLY1305_ctx(actx), buf);
235 actx->key.partial_len = 0;
236 memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE);
237 tohash_len = POLY1305_BLOCK_SIZE;
238 actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
239 actx->len.text = plen;
240
0edb109f 241 if (plen) {
b134300a 242 if (EVP_CIPHER_CTX_is_encrypting(ctx))
0edb109f
AP
243 ctr = xor128_encrypt_n_pad(out, in, ctr, plen);
244 else
245 ctr = xor128_decrypt_n_pad(out, in, ctr, plen);
246
247 in += plen;
248 out += plen;
249 tohash_len = (size_t)(ctr - tohash);
250 }
251 }
252# else
253 if (plen <= CHACHA_BLK_SIZE) {
254 size_t i;
255
256 actx->key.counter[0] = 0;
257 ChaCha20_ctr32(buf, zero, (buf_len = 2 * CHACHA_BLK_SIZE),
258 actx->key.key.d, actx->key.counter);
259 Poly1305_Init(POLY1305_ctx(actx), buf);
260 actx->key.partial_len = 0;
261 memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE);
262 tohash_len = POLY1305_BLOCK_SIZE;
263 actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
264 actx->len.text = plen;
265
b134300a 266 if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
a091e212
AP
267 for (i = 0; i < plen; i++) {
268 out[i] = ctr[i] ^= in[i];
269 }
270 } else {
271 for (i = 0; i < plen; i++) {
272 unsigned char c = in[i];
273 out[i] = ctr[i] ^ c;
274 ctr[i] = c;
275 }
276 }
277
278 in += i;
279 out += i;
280
281 tail = (0 - i) & (POLY1305_BLOCK_SIZE - 1);
282 memset(ctr + i, 0, tail);
283 ctr += i + tail;
284 tohash_len += i + tail;
0edb109f
AP
285 }
286# endif
287 else {
a091e212 288 actx->key.counter[0] = 0;
0edb109f
AP
289 ChaCha20_ctr32(buf, zero, (buf_len = CHACHA_BLK_SIZE),
290 actx->key.key.d, actx->key.counter);
a091e212
AP
291 Poly1305_Init(POLY1305_ctx(actx), buf);
292 actx->key.counter[0] = 1;
293 actx->key.partial_len = 0;
294 Poly1305_Update(POLY1305_ctx(actx), actx->tls_aad, POLY1305_BLOCK_SIZE);
295 tohash = ctr;
296 tohash_len = 0;
297 actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
298 actx->len.text = plen;
299
b134300a 300 if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
a091e212
AP
301 ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter);
302 Poly1305_Update(POLY1305_ctx(actx), out, plen);
303 } else {
304 Poly1305_Update(POLY1305_ctx(actx), in, plen);
305 ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter);
306 }
307
308 in += plen;
309 out += plen;
310 tail = (0 - plen) & (POLY1305_BLOCK_SIZE - 1);
311 Poly1305_Update(POLY1305_ctx(actx), zero, tail);
312 }
313
314 {
e23d850f 315 DECLARE_IS_ENDIAN;
a091e212 316
e23d850f 317 if (IS_LITTLE_ENDIAN) {
a091e212
AP
318 memcpy(ctr, (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
319 } else {
320 ctr[0] = (unsigned char)(actx->len.aad);
321 ctr[1] = (unsigned char)(actx->len.aad>>8);
322 ctr[2] = (unsigned char)(actx->len.aad>>16);
323 ctr[3] = (unsigned char)(actx->len.aad>>24);
324 ctr[4] = (unsigned char)(actx->len.aad>>32);
325 ctr[5] = (unsigned char)(actx->len.aad>>40);
326 ctr[6] = (unsigned char)(actx->len.aad>>48);
327 ctr[7] = (unsigned char)(actx->len.aad>>56);
328
329 ctr[8] = (unsigned char)(actx->len.text);
330 ctr[9] = (unsigned char)(actx->len.text>>8);
331 ctr[10] = (unsigned char)(actx->len.text>>16);
332 ctr[11] = (unsigned char)(actx->len.text>>24);
333 ctr[12] = (unsigned char)(actx->len.text>>32);
334 ctr[13] = (unsigned char)(actx->len.text>>40);
335 ctr[14] = (unsigned char)(actx->len.text>>48);
336 ctr[15] = (unsigned char)(actx->len.text>>56);
337 }
338 tohash_len += POLY1305_BLOCK_SIZE;
339 }
340
341 Poly1305_Update(POLY1305_ctx(actx), tohash, tohash_len);
0edb109f 342 OPENSSL_cleanse(buf, buf_len);
b134300a
TZ
343 Poly1305_Final(POLY1305_ctx(actx),
344 EVP_CIPHER_CTX_is_encrypting(ctx) ? actx->tag : tohash);
a091e212
AP
345
346 actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
347
b134300a 348 if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
a091e212
AP
349 memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
350 } else {
351 if (CRYPTO_memcmp(tohash, in, POLY1305_BLOCK_SIZE)) {
352 memset(out - (len - POLY1305_BLOCK_SIZE), 0,
353 len - POLY1305_BLOCK_SIZE);
354 return -1;
355 }
356 }
357
358 return len;
359}
360# else
361static const unsigned char zero[CHACHA_BLK_SIZE] = { 0 };
362# endif
363
bd989745
AP
364static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
365 const unsigned char *in, size_t len)
366{
367 EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
368 size_t rem, plen = actx->tls_payload_length;
bd989745
AP
369
370 if (!actx->mac_inited) {
a091e212
AP
371# if !defined(OPENSSL_SMALL_FOOTPRINT)
372 if (plen != NO_TLS_PAYLOAD_LENGTH && out != NULL)
373 return chacha20_poly1305_tls_cipher(ctx, out, in, len);
374# endif
bd989745 375 actx->key.counter[0] = 0;
a091e212 376 ChaCha20_ctr32(actx->key.buf, zero, CHACHA_BLK_SIZE,
bd989745
AP
377 actx->key.key.d, actx->key.counter);
378 Poly1305_Init(POLY1305_ctx(actx), actx->key.buf);
379 actx->key.counter[0] = 1;
30a5f322
AP
380 actx->key.partial_len = 0;
381 actx->len.aad = actx->len.text = 0;
bd989745 382 actx->mac_inited = 1;
a091e212
AP
383 if (plen != NO_TLS_PAYLOAD_LENGTH) {
384 Poly1305_Update(POLY1305_ctx(actx), actx->tls_aad,
385 EVP_AEAD_TLS1_AAD_LEN);
386 actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
387 actx->aad = 1;
388 }
bd989745
AP
389 }
390
391 if (in) { /* aad or text */
392 if (out == NULL) { /* aad */
393 Poly1305_Update(POLY1305_ctx(actx), in, len);
394 actx->len.aad += len;
395 actx->aad = 1;
396 return len;
397 } else { /* plain- or ciphertext */
398 if (actx->aad) { /* wrap up aad */
399 if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
400 Poly1305_Update(POLY1305_ctx(actx), zero,
401 POLY1305_BLOCK_SIZE - rem);
402 actx->aad = 0;
403 }
404
405 actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
406 if (plen == NO_TLS_PAYLOAD_LENGTH)
407 plen = len;
408 else if (len != plen + POLY1305_BLOCK_SIZE)
409 return -1;
410
b134300a 411 if (EVP_CIPHER_CTX_is_encrypting(ctx)) { /* plaintext */
bd989745
AP
412 chacha_cipher(ctx, out, in, plen);
413 Poly1305_Update(POLY1305_ctx(actx), out, plen);
414 in += plen;
415 out += plen;
416 actx->len.text += plen;
417 } else { /* ciphertext */
418 Poly1305_Update(POLY1305_ctx(actx), in, plen);
419 chacha_cipher(ctx, out, in, plen);
420 in += plen;
421 out += plen;
422 actx->len.text += plen;
423 }
424 }
425 }
426 if (in == NULL /* explicit final */
427 || plen != len) { /* or tls mode */
e23d850f 428 DECLARE_IS_ENDIAN;
bd989745
AP
429 unsigned char temp[POLY1305_BLOCK_SIZE];
430
431 if (actx->aad) { /* wrap up aad */
432 if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
433 Poly1305_Update(POLY1305_ctx(actx), zero,
434 POLY1305_BLOCK_SIZE - rem);
435 actx->aad = 0;
436 }
437
438 if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE))
439 Poly1305_Update(POLY1305_ctx(actx), zero,
440 POLY1305_BLOCK_SIZE - rem);
441
e23d850f 442 if (IS_LITTLE_ENDIAN) {
bd989745
AP
443 Poly1305_Update(POLY1305_ctx(actx),
444 (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
445 } else {
446 temp[0] = (unsigned char)(actx->len.aad);
447 temp[1] = (unsigned char)(actx->len.aad>>8);
448 temp[2] = (unsigned char)(actx->len.aad>>16);
449 temp[3] = (unsigned char)(actx->len.aad>>24);
450 temp[4] = (unsigned char)(actx->len.aad>>32);
451 temp[5] = (unsigned char)(actx->len.aad>>40);
452 temp[6] = (unsigned char)(actx->len.aad>>48);
453 temp[7] = (unsigned char)(actx->len.aad>>56);
454
455 temp[8] = (unsigned char)(actx->len.text);
456 temp[9] = (unsigned char)(actx->len.text>>8);
457 temp[10] = (unsigned char)(actx->len.text>>16);
458 temp[11] = (unsigned char)(actx->len.text>>24);
459 temp[12] = (unsigned char)(actx->len.text>>32);
460 temp[13] = (unsigned char)(actx->len.text>>40);
461 temp[14] = (unsigned char)(actx->len.text>>48);
462 temp[15] = (unsigned char)(actx->len.text>>56);
463
464 Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE);
465 }
b134300a
TZ
466 Poly1305_Final(POLY1305_ctx(actx),
467 EVP_CIPHER_CTX_is_encrypting(ctx) ? actx->tag : temp);
bd989745
AP
468 actx->mac_inited = 0;
469
470 if (in != NULL && len != plen) { /* tls mode */
b134300a 471 if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
bd989745
AP
472 memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
473 } else {
474 if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) {
bf52165b 475 memset(out - plen, 0, plen);
bd989745
AP
476 return -1;
477 }
478 }
479 }
b134300a 480 else if (!EVP_CIPHER_CTX_is_encrypting(ctx)) {
bd989745
AP
481 if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len))
482 return -1;
483 }
484 }
485 return len;
486}
487
488static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx)
489{
490 EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
491 if (actx)
a8f95768 492 OPENSSL_cleanse(ctx->cipher_data, sizeof(*actx) + Poly1305_ctx_size());
bd989745
AP
493 return 1;
494}
495
496static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
497 void *ptr)
498{
499 EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
500
1287dabd 501 switch (type) {
bd989745
AP
502 case EVP_CTRL_INIT:
503 if (actx == NULL)
504 actx = ctx->cipher_data
505 = OPENSSL_zalloc(sizeof(*actx) + Poly1305_ctx_size());
506 if (actx == NULL) {
9311d0c4 507 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
bd989745
AP
508 return 0;
509 }
510 actx->len.aad = 0;
511 actx->len.text = 0;
512 actx->aad = 0;
513 actx->mac_inited = 0;
514 actx->tag_len = 0;
515 actx->nonce_len = 12;
516 actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
a091e212 517 memset(actx->tls_aad, 0, POLY1305_BLOCK_SIZE);
bd989745
AP
518 return 1;
519
520 case EVP_CTRL_COPY:
521 if (actx) {
700b8145
F
522 EVP_CIPHER_CTX *dst = (EVP_CIPHER_CTX *)ptr;
523
524 dst->cipher_data =
525 OPENSSL_memdup(actx, sizeof(*actx) + Poly1305_ctx_size());
526 if (dst->cipher_data == NULL) {
9311d0c4 527 ERR_raise(ERR_LIB_EVP, EVP_R_COPY_ERROR);
bd989745
AP
528 return 0;
529 }
530 }
531 return 1;
532
7dddf2fc
SL
533 case EVP_CTRL_GET_IVLEN:
534 *(int *)ptr = actx->nonce_len;
535 return 1;
536
bd989745 537 case EVP_CTRL_AEAD_SET_IVLEN:
2a3d0ee9 538 if (arg <= 0 || arg > CHACHA20_POLY1305_MAX_IVLEN)
bd989745
AP
539 return 0;
540 actx->nonce_len = arg;
541 return 1;
542
543 case EVP_CTRL_AEAD_SET_IV_FIXED:
544 if (arg != 12)
545 return 0;
546 actx->nonce[0] = actx->key.counter[1]
547 = CHACHA_U8TOU32((unsigned char *)ptr);
548 actx->nonce[1] = actx->key.counter[2]
549 = CHACHA_U8TOU32((unsigned char *)ptr+4);
550 actx->nonce[2] = actx->key.counter[3]
551 = CHACHA_U8TOU32((unsigned char *)ptr+8);
552 return 1;
553
554 case EVP_CTRL_AEAD_SET_TAG:
555 if (arg <= 0 || arg > POLY1305_BLOCK_SIZE)
556 return 0;
557 if (ptr != NULL) {
558 memcpy(actx->tag, ptr, arg);
559 actx->tag_len = arg;
560 }
561 return 1;
562
563 case EVP_CTRL_AEAD_GET_TAG:
b134300a
TZ
564 if (arg <= 0 || arg > POLY1305_BLOCK_SIZE ||
565 !EVP_CIPHER_CTX_is_encrypting(ctx))
bd989745
AP
566 return 0;
567 memcpy(ptr, actx->tag, arg);
568 return 1;
569
570 case EVP_CTRL_AEAD_TLS1_AAD:
571 if (arg != EVP_AEAD_TLS1_AAD_LEN)
572 return 0;
573 {
574 unsigned int len;
a091e212 575 unsigned char *aad = ptr;
bd989745 576
a091e212 577 memcpy(actx->tls_aad, ptr, EVP_AEAD_TLS1_AAD_LEN);
30a5f322
AP
578 len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 |
579 aad[EVP_AEAD_TLS1_AAD_LEN - 1];
a091e212 580 aad = actx->tls_aad;
b134300a 581 if (!EVP_CIPHER_CTX_is_encrypting(ctx)) {
2198b3a5
AP
582 if (len < POLY1305_BLOCK_SIZE)
583 return 0;
bd989745 584 len -= POLY1305_BLOCK_SIZE; /* discount attached tag */
a091e212
AP
585 aad[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8);
586 aad[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len;
bd989745
AP
587 }
588 actx->tls_payload_length = len;
589
590 /*
2198b3a5 591 * merge record sequence number as per RFC7905
bd989745
AP
592 */
593 actx->key.counter[1] = actx->nonce[0];
30a5f322
AP
594 actx->key.counter[2] = actx->nonce[1] ^ CHACHA_U8TOU32(aad);
595 actx->key.counter[3] = actx->nonce[2] ^ CHACHA_U8TOU32(aad+4);
bd989745 596 actx->mac_inited = 0;
a091e212 597
bd989745
AP
598 return POLY1305_BLOCK_SIZE; /* tag length */
599 }
600
601 case EVP_CTRL_AEAD_SET_MAC_KEY:
602 /* no-op */
603 return 1;
604
605 default:
606 return -1;
607 }
608}
609
610static EVP_CIPHER chacha20_poly1305 = {
611 NID_chacha20_poly1305,
612 1, /* block_size */
613 CHACHA_KEY_SIZE, /* key_len */
614 12, /* iv_len, 96-bit nonce in the context */
615 EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV |
616 EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
7dddf2fc
SL
617 EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER |
618 EVP_CIPH_CUSTOM_IV_LENGTH,
f6c95e46 619 EVP_ORIG_GLOBAL,
bd989745
AP
620 chacha20_poly1305_init_key,
621 chacha20_poly1305_cipher,
622 chacha20_poly1305_cleanup,
623 0, /* 0 moves context-specific structure allocation to ctrl */
624 NULL, /* set_asn1_parameters */
625 NULL, /* get_asn1_parameters */
626 chacha20_poly1305_ctrl,
627 NULL /* app_data */
628};
629
630const EVP_CIPHER *EVP_chacha20_poly1305(void)
631{
632 return(&chacha20_poly1305);
633}
634# endif
635#endif