Fix some style issues...
[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     0,                      /* flags */
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     struct { uint64_t aad, text; } len;
154     int aad, mac_inited, tag_len, nonce_len;
155     size_t tls_payload_length;
156 } EVP_CHACHA_AEAD_CTX;
157
158 #  define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
159 #  define aead_data(ctx)        ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data)
160 #  define POLY1305_ctx(actx)    ((POLY1305 *)(actx + 1))
161
162 static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx,
163                                       const unsigned char *inkey,
164                                       const unsigned char *iv, int enc)
165 {
166     EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
167
168     if (!inkey && !iv)
169         return 1;
170
171     actx->len.aad = 0;
172     actx->len.text = 0;
173     actx->aad = 0;
174     actx->mac_inited = 0;
175     actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
176
177     if (iv != NULL) {
178         unsigned char temp[CHACHA_CTR_SIZE] = { 0 };
179
180         /* pad on the left */
181         if (actx->nonce_len <= CHACHA_CTR_SIZE)
182             memcpy(temp + CHACHA_CTR_SIZE - actx->nonce_len, iv, actx->nonce_len);
183
184         chacha_init_key(ctx, inkey, temp, enc);
185
186         actx->nonce[0] = actx->key.counter[1];
187         actx->nonce[1] = actx->key.counter[2];
188         actx->nonce[2] = actx->key.counter[3];
189     } else {
190         chacha_init_key(ctx, inkey, NULL, enc);
191     }
192
193     return 1;
194 }
195
196 static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
197                                     const unsigned char *in, size_t len)
198 {
199     EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
200     size_t rem, plen = actx->tls_payload_length;
201     static const unsigned char zero[POLY1305_BLOCK_SIZE] = { 0 };
202
203     if (!actx->mac_inited) {
204         actx->key.counter[0] = 0;
205         memset(actx->key.buf, 0, sizeof(actx->key.buf));
206         ChaCha20_ctr32(actx->key.buf, actx->key.buf, CHACHA_BLK_SIZE,
207                        actx->key.key.d, actx->key.counter);
208         Poly1305_Init(POLY1305_ctx(actx), actx->key.buf);
209         actx->key.counter[0] = 1;
210         actx->key.partial_len = 0;
211         actx->len.aad = actx->len.text = 0;
212         actx->mac_inited = 1;
213     }
214
215     if (in) {                                   /* aad or text */
216         if (out == NULL) {                      /* aad */
217             Poly1305_Update(POLY1305_ctx(actx), in, len);
218             actx->len.aad += len;
219             actx->aad = 1;
220             return len;
221         } else {                                /* plain- or ciphertext */
222             if (actx->aad) {                    /* wrap up aad */
223                 if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
224                     Poly1305_Update(POLY1305_ctx(actx), zero,
225                                     POLY1305_BLOCK_SIZE - rem);
226                 actx->aad = 0;
227             }
228
229             actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
230             if (plen == NO_TLS_PAYLOAD_LENGTH)
231                 plen = len;
232             else if (len != plen + POLY1305_BLOCK_SIZE)
233                 return -1;
234
235             if (ctx->encrypt) {                 /* plaintext */
236                 chacha_cipher(ctx, out, in, plen);
237                 Poly1305_Update(POLY1305_ctx(actx), out, plen);
238                 in += plen;
239                 out += plen;
240                 actx->len.text += plen;
241             } else {                            /* ciphertext */
242                 Poly1305_Update(POLY1305_ctx(actx), in, plen);
243                 chacha_cipher(ctx, out, in, plen);
244                 in += plen;
245                 out += plen;
246                 actx->len.text += plen;
247             }
248         }
249     }
250     if (in == NULL                              /* explicit final */
251         || plen != len) {                       /* or tls mode */
252         const union {
253             long one;
254             char little;
255         } is_endian = { 1 };
256         unsigned char temp[POLY1305_BLOCK_SIZE];
257
258         if (actx->aad) {                        /* wrap up aad */
259             if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
260                 Poly1305_Update(POLY1305_ctx(actx), zero,
261                                 POLY1305_BLOCK_SIZE - rem);
262             actx->aad = 0;
263         }
264
265         if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE))
266             Poly1305_Update(POLY1305_ctx(actx), zero,
267                             POLY1305_BLOCK_SIZE - rem);
268
269         if (is_endian.little) {
270             Poly1305_Update(POLY1305_ctx(actx),
271                             (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
272         } else {
273             temp[0]  = (unsigned char)(actx->len.aad);
274             temp[1]  = (unsigned char)(actx->len.aad>>8);
275             temp[2]  = (unsigned char)(actx->len.aad>>16);
276             temp[3]  = (unsigned char)(actx->len.aad>>24);
277             temp[4]  = (unsigned char)(actx->len.aad>>32);
278             temp[5]  = (unsigned char)(actx->len.aad>>40);
279             temp[6]  = (unsigned char)(actx->len.aad>>48);
280             temp[7]  = (unsigned char)(actx->len.aad>>56);
281
282             temp[8]  = (unsigned char)(actx->len.text);
283             temp[9]  = (unsigned char)(actx->len.text>>8);
284             temp[10] = (unsigned char)(actx->len.text>>16);
285             temp[11] = (unsigned char)(actx->len.text>>24);
286             temp[12] = (unsigned char)(actx->len.text>>32);
287             temp[13] = (unsigned char)(actx->len.text>>40);
288             temp[14] = (unsigned char)(actx->len.text>>48);
289             temp[15] = (unsigned char)(actx->len.text>>56);
290
291             Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE);
292         }
293         Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
294                                                         : temp);
295         actx->mac_inited = 0;
296
297         if (in != NULL && len != plen) {        /* tls mode */
298             if (ctx->encrypt) {
299                 memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
300             } else {
301                 if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) {
302                     memset(out, 0, plen);
303                     return -1;
304                 }
305             }
306         }
307         else if (!ctx->encrypt) {
308             if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len))
309                 return -1;
310         }
311     }
312     return len;
313 }
314
315 static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx)
316 {
317     EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
318     if (actx)
319         OPENSSL_cleanse(ctx->cipher_data, sizeof(*ctx) + Poly1305_ctx_size());
320     return 1;
321 }
322
323 static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
324                                   void *ptr)
325 {
326     EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
327
328     switch(type) {
329     case EVP_CTRL_INIT:
330         if (actx == NULL)
331             actx = ctx->cipher_data
332                  = OPENSSL_zalloc(sizeof(*actx) + Poly1305_ctx_size());
333         if (actx == NULL) {
334             EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_INITIALIZATION_ERROR);
335             return 0;
336         }
337         actx->len.aad = 0;
338         actx->len.text = 0;
339         actx->aad = 0;
340         actx->mac_inited = 0;
341         actx->tag_len = 0;
342         actx->nonce_len = 12;
343         actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
344         return 1;
345
346     case EVP_CTRL_COPY:
347         if (actx) {
348             EVP_CIPHER_CTX *dst = (EVP_CIPHER_CTX *)ptr;
349
350             dst->cipher_data =
351                    OPENSSL_memdup(actx, sizeof(*actx) + Poly1305_ctx_size());
352             if (dst->cipher_data == NULL) {
353                 EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_COPY_ERROR);
354                 return 0;
355             }
356         }
357         return 1;
358
359     case EVP_CTRL_AEAD_SET_IVLEN:
360         if (arg <= 0 || arg > CHACHA_CTR_SIZE)
361             return 0;
362         actx->nonce_len = arg;
363         return 1;
364
365     case EVP_CTRL_AEAD_SET_IV_FIXED:
366         if (arg != 12)
367             return 0;
368         actx->nonce[0] = actx->key.counter[1]
369                        = CHACHA_U8TOU32((unsigned char *)ptr);
370         actx->nonce[1] = actx->key.counter[2]
371                        = CHACHA_U8TOU32((unsigned char *)ptr+4);
372         actx->nonce[2] = actx->key.counter[3]
373                        = CHACHA_U8TOU32((unsigned char *)ptr+8);
374         return 1;
375
376     case EVP_CTRL_AEAD_SET_TAG:
377         if (arg <= 0 || arg > POLY1305_BLOCK_SIZE)
378             return 0;
379         if (ptr != NULL) {
380             memcpy(actx->tag, ptr, arg);
381             actx->tag_len = arg;
382         }
383         return 1;
384
385     case EVP_CTRL_AEAD_GET_TAG:
386         if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || !ctx->encrypt)
387             return 0;
388         memcpy(ptr, actx->tag, arg);
389         return 1;
390
391     case EVP_CTRL_AEAD_TLS1_AAD:
392         if (arg != EVP_AEAD_TLS1_AAD_LEN)
393             return 0;
394         {
395             unsigned int len;
396             unsigned char *aad = ptr, temp[POLY1305_BLOCK_SIZE];
397
398             len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 |
399                   aad[EVP_AEAD_TLS1_AAD_LEN - 1];
400             if (!ctx->encrypt) {
401                 len -= POLY1305_BLOCK_SIZE;     /* discount attached tag */
402                 memcpy(temp, aad, EVP_AEAD_TLS1_AAD_LEN - 2);
403                 aad = temp;
404                 temp[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8);
405                 temp[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len;
406             }
407             actx->tls_payload_length = len;
408
409             /*
410              * merge record sequence number as per
411              * draft-ietf-tls-chacha20-poly1305-03
412              */
413             actx->key.counter[1] = actx->nonce[0];
414             actx->key.counter[2] = actx->nonce[1] ^ CHACHA_U8TOU32(aad);
415             actx->key.counter[3] = actx->nonce[2] ^ CHACHA_U8TOU32(aad+4);
416             actx->mac_inited = 0;
417             chacha20_poly1305_cipher(ctx, NULL, aad, EVP_AEAD_TLS1_AAD_LEN);
418             return POLY1305_BLOCK_SIZE;         /* tag length */
419         }
420
421     case EVP_CTRL_AEAD_SET_MAC_KEY:
422         /* no-op */
423         return 1;
424
425     default:
426         return -1;
427     }
428 }
429
430 static EVP_CIPHER chacha20_poly1305 = {
431     NID_chacha20_poly1305,
432     1,                  /* block_size */
433     CHACHA_KEY_SIZE,    /* key_len */
434     12,                 /* iv_len, 96-bit nonce in the context */
435     EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV |
436     EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
437     EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER,
438     chacha20_poly1305_init_key,
439     chacha20_poly1305_cipher,
440     chacha20_poly1305_cleanup,
441     0,          /* 0 moves context-specific structure allocation to ctrl */
442     NULL,       /* set_asn1_parameters */
443     NULL,       /* get_asn1_parameters */
444     chacha20_poly1305_ctrl,
445     NULL        /* app_data */
446 };
447
448 const EVP_CIPHER *EVP_chacha20_poly1305(void)
449 {
450     return(&chacha20_poly1305);
451 }
452 # endif
453 #endif