xref: /freebsd/crypto/openssl/crypto/evp/e_chacha20_poly1305.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
1 /*
2  * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (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 #include "internal/endian.h"
13 
14 #ifndef OPENSSL_NO_CHACHA
15 
16 # include <openssl/evp.h>
17 # include <openssl/objects.h>
18 # include "crypto/evp.h"
19 # include "evp_local.h"
20 # include "crypto/chacha.h"
21 
22 typedef struct {
23     union {
24         OSSL_UNION_ALIGN;  /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
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 
34 #define CHACHA20_POLY1305_MAX_IVLEN     12
35 
chacha_init_key(EVP_CIPHER_CTX * ctx,const unsigned char user_key[CHACHA_KEY_SIZE],const unsigned char iv[CHACHA_CTR_SIZE],int enc)36 static 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 
chacha_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * inp,size_t len)58 static 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 
128 static 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 */
133     EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT,
134     EVP_ORIG_GLOBAL,
135     chacha_init_key,
136     chacha_cipher,
137     NULL,
138     sizeof(EVP_CHACHA_KEY),
139     NULL,
140     NULL,
141     NULL,
142     NULL
143 };
144 
EVP_chacha20(void)145 const EVP_CIPHER *EVP_chacha20(void)
146 {
147     return &chacha20;
148 }
149 
150 # ifndef OPENSSL_NO_POLY1305
151 #  include "crypto/poly1305.h"
152 
153 typedef struct {
154     EVP_CHACHA_KEY key;
155     unsigned int nonce[12/4];
156     unsigned char tag[POLY1305_BLOCK_SIZE];
157     unsigned char tls_aad[POLY1305_BLOCK_SIZE];
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 
chacha20_poly1305_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * inkey,const unsigned char * iv,int enc)167 static 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);
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 
182     if (iv != NULL) {
183         unsigned char temp[CHACHA_CTR_SIZE] = { 0 };
184 
185         /* pad on the left */
186         if (actx->nonce_len <= CHACHA_CTR_SIZE)
187             memcpy(temp + CHACHA_CTR_SIZE - actx->nonce_len, iv,
188                    actx->nonce_len);
189 
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     }
198 
199     return 1;
200 }
201 
202 #  if !defined(OPENSSL_SMALL_FOOTPRINT)
203 
204 #   if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
205                                  defined(_M_AMD64) || defined(_M_X64))
206 #    define XOR128_HELPERS
207 void *xor128_encrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
208 void *xor128_decrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
209 static const unsigned char zero[4 * CHACHA_BLK_SIZE] = { 0 };
210 #   else
211 static const unsigned char zero[2 * CHACHA_BLK_SIZE] = { 0 };
212 #   endif
213 
chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)214 static 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);
218     size_t tail, tohash_len, buf_len, plen = actx->tls_payload_length;
219     unsigned char *buf, *tohash, *ctr, storage[sizeof(zero) + 32];
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 
228 #   ifdef XOR128_HELPERS
229     if (plen <= 3 * CHACHA_BLK_SIZE) {
230         actx->key.counter[0] = 0;
231         buf_len = (plen + 2 * CHACHA_BLK_SIZE - 1) & (0 - CHACHA_BLK_SIZE);
232         ChaCha20_ctr32(buf, zero, buf_len, actx->key.key.d,
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 
241         if (plen) {
242             if (ctx->encrypt)
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 
266         if (ctx->encrypt) {
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;
285     }
286 #   endif
287     else {
288         actx->key.counter[0] = 0;
289         ChaCha20_ctr32(buf, zero, (buf_len = CHACHA_BLK_SIZE),
290                        actx->key.key.d, actx->key.counter);
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 
300         if (ctx->encrypt) {
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     {
315         DECLARE_IS_ENDIAN;
316 
317         if (IS_LITTLE_ENDIAN) {
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);
342     OPENSSL_cleanse(buf, buf_len);
343     Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
344                                                     : tohash);
345 
346     actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
347 
348     if (ctx->encrypt) {
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
361 static const unsigned char zero[CHACHA_BLK_SIZE] = { 0 };
362 #  endif
363 
chacha20_poly1305_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)364 static 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;
369 
370     if (!actx->mac_inited) {
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
375         actx->key.counter[0] = 0;
376         ChaCha20_ctr32(actx->key.buf, zero, CHACHA_BLK_SIZE,
377                        actx->key.key.d, actx->key.counter);
378         Poly1305_Init(POLY1305_ctx(actx), actx->key.buf);
379         actx->key.counter[0] = 1;
380         actx->key.partial_len = 0;
381         actx->len.aad = actx->len.text = 0;
382         actx->mac_inited = 1;
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         }
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 
411             if (ctx->encrypt) {                 /* plaintext */
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 */
428         DECLARE_IS_ENDIAN;
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 
442         if (IS_LITTLE_ENDIAN) {
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         }
466         Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
467                                                         : temp);
468         actx->mac_inited = 0;
469 
470         if (in != NULL && len != plen) {        /* tls mode */
471             if (ctx->encrypt) {
472                 memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
473             } else {
474                 if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) {
475                     memset(out - plen, 0, plen);
476                     return -1;
477                 }
478             }
479         }
480         else if (!ctx->encrypt) {
481             if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len))
482                 return -1;
483         }
484     }
485     return len;
486 }
487 
chacha20_poly1305_cleanup(EVP_CIPHER_CTX * ctx)488 static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx)
489 {
490     EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
491     if (actx)
492         OPENSSL_cleanse(ctx->cipher_data, sizeof(*actx) + Poly1305_ctx_size());
493     return 1;
494 }
495 
chacha20_poly1305_ctrl(EVP_CIPHER_CTX * ctx,int type,int arg,void * ptr)496 static 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 
501     switch(type) {
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) {
507             ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
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;
517         memset(actx->tls_aad, 0, POLY1305_BLOCK_SIZE);
518         return 1;
519 
520     case EVP_CTRL_COPY:
521         if (actx) {
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) {
527                 ERR_raise(ERR_LIB_EVP, EVP_R_COPY_ERROR);
528                 return 0;
529             }
530         }
531         return 1;
532 
533     case EVP_CTRL_GET_IVLEN:
534         *(int *)ptr = actx->nonce_len;
535         return 1;
536 
537     case EVP_CTRL_AEAD_SET_IVLEN:
538         if (arg <= 0 || arg > CHACHA20_POLY1305_MAX_IVLEN)
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:
564         if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || !ctx->encrypt)
565             return 0;
566         memcpy(ptr, actx->tag, arg);
567         return 1;
568 
569     case EVP_CTRL_AEAD_TLS1_AAD:
570         if (arg != EVP_AEAD_TLS1_AAD_LEN)
571             return 0;
572         {
573             unsigned int len;
574             unsigned char *aad = ptr;
575 
576             memcpy(actx->tls_aad, ptr, EVP_AEAD_TLS1_AAD_LEN);
577             len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 |
578                   aad[EVP_AEAD_TLS1_AAD_LEN - 1];
579             aad = actx->tls_aad;
580             if (!ctx->encrypt) {
581                 if (len < POLY1305_BLOCK_SIZE)
582                     return 0;
583                 len -= POLY1305_BLOCK_SIZE;     /* discount attached tag */
584                 aad[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8);
585                 aad[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len;
586             }
587             actx->tls_payload_length = len;
588 
589             /*
590              * merge record sequence number as per RFC7905
591              */
592             actx->key.counter[1] = actx->nonce[0];
593             actx->key.counter[2] = actx->nonce[1] ^ CHACHA_U8TOU32(aad);
594             actx->key.counter[3] = actx->nonce[2] ^ CHACHA_U8TOU32(aad+4);
595             actx->mac_inited = 0;
596 
597             return POLY1305_BLOCK_SIZE;         /* tag length */
598         }
599 
600     case EVP_CTRL_AEAD_SET_MAC_KEY:
601         /* no-op */
602         return 1;
603 
604     default:
605         return -1;
606     }
607 }
608 
609 static EVP_CIPHER chacha20_poly1305 = {
610     NID_chacha20_poly1305,
611     1,                  /* block_size */
612     CHACHA_KEY_SIZE,    /* key_len */
613     12,                 /* iv_len, 96-bit nonce in the context */
614     EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV |
615     EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
616     EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER |
617     EVP_CIPH_CUSTOM_IV_LENGTH,
618     EVP_ORIG_GLOBAL,
619     chacha20_poly1305_init_key,
620     chacha20_poly1305_cipher,
621     chacha20_poly1305_cleanup,
622     0,          /* 0 moves context-specific structure allocation to ctrl */
623     NULL,       /* set_asn1_parameters */
624     NULL,       /* get_asn1_parameters */
625     chacha20_poly1305_ctrl,
626     NULL        /* app_data */
627 };
628 
EVP_chacha20_poly1305(void)629 const EVP_CIPHER *EVP_chacha20_poly1305(void)
630 {
631     return(&chacha20_poly1305);
632 }
633 # endif
634 #endif
635