]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/e_chacha20_poly1305.c
Standard style for all EVP_xxx_free routines
[thirdparty/openssl.git] / crypto / evp / e_chacha20_poly1305.c
CommitLineData
62867571 1/*
e39e295e 2 * Copyright 2015-2020 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
58static int chacha_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out,
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,
bd989745
AP
134 chacha_init_key,
135 chacha_cipher,
136 NULL,
137 sizeof(EVP_CHACHA_KEY),
138 NULL,
139 NULL,
140 NULL,
141 NULL
142};
143
144const EVP_CIPHER *EVP_chacha20(void)
145{
26a7d938 146 return &chacha20;
bd989745
AP
147}
148
149# ifndef OPENSSL_NO_POLY1305
25f2138b 150# include "crypto/poly1305.h"
bd989745
AP
151
152typedef struct {
153 EVP_CHACHA_KEY key;
154 unsigned int nonce[12/4];
155 unsigned char tag[POLY1305_BLOCK_SIZE];
a091e212 156 unsigned char tls_aad[POLY1305_BLOCK_SIZE];
bd989745
AP
157 struct { uint64_t aad, text; } len;
158 int aad, mac_inited, tag_len, nonce_len;
159 size_t tls_payload_length;
160} EVP_CHACHA_AEAD_CTX;
161
162# define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
163# define aead_data(ctx) ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data)
164# define POLY1305_ctx(actx) ((POLY1305 *)(actx + 1))
165
166static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx,
167 const unsigned char *inkey,
168 const unsigned char *iv, int enc)
169{
170 EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
bd989745
AP
171
172 if (!inkey && !iv)
173 return 1;
174
175 actx->len.aad = 0;
176 actx->len.text = 0;
177 actx->aad = 0;
178 actx->mac_inited = 0;
179 actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
180
d2dfd482
KY
181 if (iv != NULL) {
182 unsigned char temp[CHACHA_CTR_SIZE] = { 0 };
bd989745 183
d2dfd482
KY
184 /* pad on the left */
185 if (actx->nonce_len <= CHACHA_CTR_SIZE)
a091e212
AP
186 memcpy(temp + CHACHA_CTR_SIZE - actx->nonce_len, iv,
187 actx->nonce_len);
bd989745 188
d2dfd482
KY
189 chacha_init_key(ctx, inkey, temp, enc);
190
191 actx->nonce[0] = actx->key.counter[1];
192 actx->nonce[1] = actx->key.counter[2];
193 actx->nonce[2] = actx->key.counter[3];
194 } else {
195 chacha_init_key(ctx, inkey, NULL, enc);
196 }
bd989745
AP
197
198 return 1;
199}
200
a091e212 201# if !defined(OPENSSL_SMALL_FOOTPRINT)
0edb109f
AP
202
203# if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
204 defined(_M_AMD64) || defined(_M_X64))
205# define XOR128_HELPERS
206void *xor128_encrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
207void *xor128_decrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
208static const unsigned char zero[4 * CHACHA_BLK_SIZE] = { 0 };
209# else
a091e212 210static const unsigned char zero[2 * CHACHA_BLK_SIZE] = { 0 };
0edb109f 211# endif
a091e212
AP
212
213static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
214 const unsigned char *in, size_t len)
215{
216 EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
0edb109f
AP
217 size_t tail, tohash_len, buf_len, plen = actx->tls_payload_length;
218 unsigned char *buf, *tohash, *ctr, storage[sizeof(zero) + 32];
a091e212
AP
219
220 if (len != plen + POLY1305_BLOCK_SIZE)
221 return -1;
222
223 buf = storage + ((0 - (size_t)storage) & 15); /* align */
224 ctr = buf + CHACHA_BLK_SIZE;
225 tohash = buf + CHACHA_BLK_SIZE - POLY1305_BLOCK_SIZE;
226
0edb109f
AP
227# ifdef XOR128_HELPERS
228 if (plen <= 3 * CHACHA_BLK_SIZE) {
a091e212 229 actx->key.counter[0] = 0;
0edb109f
AP
230 buf_len = (plen + 2 * CHACHA_BLK_SIZE - 1) & (0 - CHACHA_BLK_SIZE);
231 ChaCha20_ctr32(buf, zero, buf_len, actx->key.key.d,
a091e212
AP
232 actx->key.counter);
233 Poly1305_Init(POLY1305_ctx(actx), buf);
234 actx->key.partial_len = 0;
235 memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE);
236 tohash_len = POLY1305_BLOCK_SIZE;
237 actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
238 actx->len.text = plen;
239
0edb109f
AP
240 if (plen) {
241 if (ctx->encrypt)
242 ctr = xor128_encrypt_n_pad(out, in, ctr, plen);
243 else
244 ctr = xor128_decrypt_n_pad(out, in, ctr, plen);
245
246 in += plen;
247 out += plen;
248 tohash_len = (size_t)(ctr - tohash);
249 }
250 }
251# else
252 if (plen <= CHACHA_BLK_SIZE) {
253 size_t i;
254
255 actx->key.counter[0] = 0;
256 ChaCha20_ctr32(buf, zero, (buf_len = 2 * CHACHA_BLK_SIZE),
257 actx->key.key.d, actx->key.counter);
258 Poly1305_Init(POLY1305_ctx(actx), buf);
259 actx->key.partial_len = 0;
260 memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE);
261 tohash_len = POLY1305_BLOCK_SIZE;
262 actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
263 actx->len.text = plen;
264
a091e212
AP
265 if (ctx->encrypt) {
266 for (i = 0; i < plen; i++) {
267 out[i] = ctr[i] ^= in[i];
268 }
269 } else {
270 for (i = 0; i < plen; i++) {
271 unsigned char c = in[i];
272 out[i] = ctr[i] ^ c;
273 ctr[i] = c;
274 }
275 }
276
277 in += i;
278 out += i;
279
280 tail = (0 - i) & (POLY1305_BLOCK_SIZE - 1);
281 memset(ctr + i, 0, tail);
282 ctr += i + tail;
283 tohash_len += i + tail;
0edb109f
AP
284 }
285# endif
286 else {
a091e212 287 actx->key.counter[0] = 0;
0edb109f
AP
288 ChaCha20_ctr32(buf, zero, (buf_len = CHACHA_BLK_SIZE),
289 actx->key.key.d, actx->key.counter);
a091e212
AP
290 Poly1305_Init(POLY1305_ctx(actx), buf);
291 actx->key.counter[0] = 1;
292 actx->key.partial_len = 0;
293 Poly1305_Update(POLY1305_ctx(actx), actx->tls_aad, POLY1305_BLOCK_SIZE);
294 tohash = ctr;
295 tohash_len = 0;
296 actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
297 actx->len.text = plen;
298
299 if (ctx->encrypt) {
300 ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter);
301 Poly1305_Update(POLY1305_ctx(actx), out, plen);
302 } else {
303 Poly1305_Update(POLY1305_ctx(actx), in, plen);
304 ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter);
305 }
306
307 in += plen;
308 out += plen;
309 tail = (0 - plen) & (POLY1305_BLOCK_SIZE - 1);
310 Poly1305_Update(POLY1305_ctx(actx), zero, tail);
311 }
312
313 {
e23d850f 314 DECLARE_IS_ENDIAN;
a091e212 315
e23d850f 316 if (IS_LITTLE_ENDIAN) {
a091e212
AP
317 memcpy(ctr, (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
318 } else {
319 ctr[0] = (unsigned char)(actx->len.aad);
320 ctr[1] = (unsigned char)(actx->len.aad>>8);
321 ctr[2] = (unsigned char)(actx->len.aad>>16);
322 ctr[3] = (unsigned char)(actx->len.aad>>24);
323 ctr[4] = (unsigned char)(actx->len.aad>>32);
324 ctr[5] = (unsigned char)(actx->len.aad>>40);
325 ctr[6] = (unsigned char)(actx->len.aad>>48);
326 ctr[7] = (unsigned char)(actx->len.aad>>56);
327
328 ctr[8] = (unsigned char)(actx->len.text);
329 ctr[9] = (unsigned char)(actx->len.text>>8);
330 ctr[10] = (unsigned char)(actx->len.text>>16);
331 ctr[11] = (unsigned char)(actx->len.text>>24);
332 ctr[12] = (unsigned char)(actx->len.text>>32);
333 ctr[13] = (unsigned char)(actx->len.text>>40);
334 ctr[14] = (unsigned char)(actx->len.text>>48);
335 ctr[15] = (unsigned char)(actx->len.text>>56);
336 }
337 tohash_len += POLY1305_BLOCK_SIZE;
338 }
339
340 Poly1305_Update(POLY1305_ctx(actx), tohash, tohash_len);
0edb109f 341 OPENSSL_cleanse(buf, buf_len);
a091e212
AP
342 Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
343 : tohash);
344
345 actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
346
347 if (ctx->encrypt) {
348 memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
349 } else {
350 if (CRYPTO_memcmp(tohash, in, POLY1305_BLOCK_SIZE)) {
351 memset(out - (len - POLY1305_BLOCK_SIZE), 0,
352 len - POLY1305_BLOCK_SIZE);
353 return -1;
354 }
355 }
356
357 return len;
358}
359# else
360static const unsigned char zero[CHACHA_BLK_SIZE] = { 0 };
361# endif
362
bd989745
AP
363static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
364 const unsigned char *in, size_t len)
365{
366 EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
367 size_t rem, plen = actx->tls_payload_length;
bd989745
AP
368
369 if (!actx->mac_inited) {
a091e212
AP
370# if !defined(OPENSSL_SMALL_FOOTPRINT)
371 if (plen != NO_TLS_PAYLOAD_LENGTH && out != NULL)
372 return chacha20_poly1305_tls_cipher(ctx, out, in, len);
373# endif
bd989745 374 actx->key.counter[0] = 0;
a091e212 375 ChaCha20_ctr32(actx->key.buf, zero, CHACHA_BLK_SIZE,
bd989745
AP
376 actx->key.key.d, actx->key.counter);
377 Poly1305_Init(POLY1305_ctx(actx), actx->key.buf);
378 actx->key.counter[0] = 1;
30a5f322
AP
379 actx->key.partial_len = 0;
380 actx->len.aad = actx->len.text = 0;
bd989745 381 actx->mac_inited = 1;
a091e212
AP
382 if (plen != NO_TLS_PAYLOAD_LENGTH) {
383 Poly1305_Update(POLY1305_ctx(actx), actx->tls_aad,
384 EVP_AEAD_TLS1_AAD_LEN);
385 actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
386 actx->aad = 1;
387 }
bd989745
AP
388 }
389
390 if (in) { /* aad or text */
391 if (out == NULL) { /* aad */
392 Poly1305_Update(POLY1305_ctx(actx), in, len);
393 actx->len.aad += len;
394 actx->aad = 1;
395 return len;
396 } else { /* plain- or ciphertext */
397 if (actx->aad) { /* wrap up aad */
398 if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
399 Poly1305_Update(POLY1305_ctx(actx), zero,
400 POLY1305_BLOCK_SIZE - rem);
401 actx->aad = 0;
402 }
403
404 actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
405 if (plen == NO_TLS_PAYLOAD_LENGTH)
406 plen = len;
407 else if (len != plen + POLY1305_BLOCK_SIZE)
408 return -1;
409
410 if (ctx->encrypt) { /* plaintext */
411 chacha_cipher(ctx, out, in, plen);
412 Poly1305_Update(POLY1305_ctx(actx), out, plen);
413 in += plen;
414 out += plen;
415 actx->len.text += plen;
416 } else { /* ciphertext */
417 Poly1305_Update(POLY1305_ctx(actx), in, plen);
418 chacha_cipher(ctx, out, in, plen);
419 in += plen;
420 out += plen;
421 actx->len.text += plen;
422 }
423 }
424 }
425 if (in == NULL /* explicit final */
426 || plen != len) { /* or tls mode */
e23d850f 427 DECLARE_IS_ENDIAN;
bd989745
AP
428 unsigned char temp[POLY1305_BLOCK_SIZE];
429
430 if (actx->aad) { /* wrap up aad */
431 if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
432 Poly1305_Update(POLY1305_ctx(actx), zero,
433 POLY1305_BLOCK_SIZE - rem);
434 actx->aad = 0;
435 }
436
437 if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE))
438 Poly1305_Update(POLY1305_ctx(actx), zero,
439 POLY1305_BLOCK_SIZE - rem);
440
e23d850f 441 if (IS_LITTLE_ENDIAN) {
bd989745
AP
442 Poly1305_Update(POLY1305_ctx(actx),
443 (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
444 } else {
445 temp[0] = (unsigned char)(actx->len.aad);
446 temp[1] = (unsigned char)(actx->len.aad>>8);
447 temp[2] = (unsigned char)(actx->len.aad>>16);
448 temp[3] = (unsigned char)(actx->len.aad>>24);
449 temp[4] = (unsigned char)(actx->len.aad>>32);
450 temp[5] = (unsigned char)(actx->len.aad>>40);
451 temp[6] = (unsigned char)(actx->len.aad>>48);
452 temp[7] = (unsigned char)(actx->len.aad>>56);
453
454 temp[8] = (unsigned char)(actx->len.text);
455 temp[9] = (unsigned char)(actx->len.text>>8);
456 temp[10] = (unsigned char)(actx->len.text>>16);
457 temp[11] = (unsigned char)(actx->len.text>>24);
458 temp[12] = (unsigned char)(actx->len.text>>32);
459 temp[13] = (unsigned char)(actx->len.text>>40);
460 temp[14] = (unsigned char)(actx->len.text>>48);
461 temp[15] = (unsigned char)(actx->len.text>>56);
462
463 Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE);
464 }
465 Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
466 : temp);
467 actx->mac_inited = 0;
468
469 if (in != NULL && len != plen) { /* tls mode */
470 if (ctx->encrypt) {
471 memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
472 } else {
473 if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) {
bf52165b 474 memset(out - plen, 0, plen);
bd989745
AP
475 return -1;
476 }
477 }
478 }
479 else if (!ctx->encrypt) {
480 if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len))
481 return -1;
482 }
483 }
484 return len;
485}
486
487static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx)
488{
489 EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
490 if (actx)
a8f95768 491 OPENSSL_cleanse(ctx->cipher_data, sizeof(*actx) + Poly1305_ctx_size());
bd989745
AP
492 return 1;
493}
494
495static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
496 void *ptr)
497{
498 EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
499
500 switch(type) {
501 case EVP_CTRL_INIT:
502 if (actx == NULL)
503 actx = ctx->cipher_data
504 = OPENSSL_zalloc(sizeof(*actx) + Poly1305_ctx_size());
505 if (actx == NULL) {
9311d0c4 506 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
bd989745
AP
507 return 0;
508 }
509 actx->len.aad = 0;
510 actx->len.text = 0;
511 actx->aad = 0;
512 actx->mac_inited = 0;
513 actx->tag_len = 0;
514 actx->nonce_len = 12;
515 actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
a091e212 516 memset(actx->tls_aad, 0, POLY1305_BLOCK_SIZE);
bd989745
AP
517 return 1;
518
519 case EVP_CTRL_COPY:
520 if (actx) {
700b8145
F
521 EVP_CIPHER_CTX *dst = (EVP_CIPHER_CTX *)ptr;
522
523 dst->cipher_data =
524 OPENSSL_memdup(actx, sizeof(*actx) + Poly1305_ctx_size());
525 if (dst->cipher_data == NULL) {
9311d0c4 526 ERR_raise(ERR_LIB_EVP, EVP_R_COPY_ERROR);
bd989745
AP
527 return 0;
528 }
529 }
530 return 1;
531
7dddf2fc
SL
532 case EVP_CTRL_GET_IVLEN:
533 *(int *)ptr = actx->nonce_len;
534 return 1;
535
bd989745 536 case EVP_CTRL_AEAD_SET_IVLEN:
2a3d0ee9 537 if (arg <= 0 || arg > CHACHA20_POLY1305_MAX_IVLEN)
bd989745
AP
538 return 0;
539 actx->nonce_len = arg;
540 return 1;
541
542 case EVP_CTRL_AEAD_SET_IV_FIXED:
543 if (arg != 12)
544 return 0;
545 actx->nonce[0] = actx->key.counter[1]
546 = CHACHA_U8TOU32((unsigned char *)ptr);
547 actx->nonce[1] = actx->key.counter[2]
548 = CHACHA_U8TOU32((unsigned char *)ptr+4);
549 actx->nonce[2] = actx->key.counter[3]
550 = CHACHA_U8TOU32((unsigned char *)ptr+8);
551 return 1;
552
553 case EVP_CTRL_AEAD_SET_TAG:
554 if (arg <= 0 || arg > POLY1305_BLOCK_SIZE)
555 return 0;
556 if (ptr != NULL) {
557 memcpy(actx->tag, ptr, arg);
558 actx->tag_len = arg;
559 }
560 return 1;
561
562 case EVP_CTRL_AEAD_GET_TAG:
563 if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || !ctx->encrypt)
564 return 0;
565 memcpy(ptr, actx->tag, arg);
566 return 1;
567
568 case EVP_CTRL_AEAD_TLS1_AAD:
569 if (arg != EVP_AEAD_TLS1_AAD_LEN)
570 return 0;
571 {
572 unsigned int len;
a091e212 573 unsigned char *aad = ptr;
bd989745 574
a091e212 575 memcpy(actx->tls_aad, ptr, EVP_AEAD_TLS1_AAD_LEN);
30a5f322
AP
576 len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 |
577 aad[EVP_AEAD_TLS1_AAD_LEN - 1];
a091e212 578 aad = actx->tls_aad;
bd989745 579 if (!ctx->encrypt) {
2198b3a5
AP
580 if (len < POLY1305_BLOCK_SIZE)
581 return 0;
bd989745 582 len -= POLY1305_BLOCK_SIZE; /* discount attached tag */
a091e212
AP
583 aad[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8);
584 aad[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len;
bd989745
AP
585 }
586 actx->tls_payload_length = len;
587
588 /*
2198b3a5 589 * merge record sequence number as per RFC7905
bd989745
AP
590 */
591 actx->key.counter[1] = actx->nonce[0];
30a5f322
AP
592 actx->key.counter[2] = actx->nonce[1] ^ CHACHA_U8TOU32(aad);
593 actx->key.counter[3] = actx->nonce[2] ^ CHACHA_U8TOU32(aad+4);
bd989745 594 actx->mac_inited = 0;
a091e212 595
bd989745
AP
596 return POLY1305_BLOCK_SIZE; /* tag length */
597 }
598
599 case EVP_CTRL_AEAD_SET_MAC_KEY:
600 /* no-op */
601 return 1;
602
603 default:
604 return -1;
605 }
606}
607
608static EVP_CIPHER chacha20_poly1305 = {
609 NID_chacha20_poly1305,
610 1, /* block_size */
611 CHACHA_KEY_SIZE, /* key_len */
612 12, /* iv_len, 96-bit nonce in the context */
613 EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV |
614 EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
7dddf2fc
SL
615 EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER |
616 EVP_CIPH_CUSTOM_IV_LENGTH,
bd989745
AP
617 chacha20_poly1305_init_key,
618 chacha20_poly1305_cipher,
619 chacha20_poly1305_cleanup,
620 0, /* 0 moves context-specific structure allocation to ctrl */
621 NULL, /* set_asn1_parameters */
622 NULL, /* get_asn1_parameters */
623 chacha20_poly1305_ctrl,
624 NULL /* app_data */
625};
626
627const EVP_CIPHER *EVP_chacha20_poly1305(void)
628{
629 return(&chacha20_poly1305);
630}
631# endif
632#endif