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