/src/nettle-with-libgmp/chacha-poly1305.c
Line  | Count  | Source  | 
1  |  | /* chacha-poly1305.c  | 
2  |  |  | 
3  |  |    AEAD mechanism based on chacha and poly1305.  | 
4  |  |  | 
5  |  |    Copyright (C) 2014, 2015 Niels Möller  | 
6  |  |  | 
7  |  |    This file is part of GNU Nettle.  | 
8  |  |  | 
9  |  |    GNU Nettle is free software: you can redistribute it and/or  | 
10  |  |    modify it under the terms of either:  | 
11  |  |  | 
12  |  |      * the GNU Lesser General Public License as published by the Free  | 
13  |  |        Software Foundation; either version 3 of the License, or (at your  | 
14  |  |        option) any later version.  | 
15  |  |  | 
16  |  |    or  | 
17  |  |  | 
18  |  |      * the GNU General Public License as published by the Free  | 
19  |  |        Software Foundation; either version 2 of the License, or (at your  | 
20  |  |        option) any later version.  | 
21  |  |  | 
22  |  |    or both in parallel, as here.  | 
23  |  |  | 
24  |  |    GNU Nettle is distributed in the hope that it will be useful,  | 
25  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of  | 
26  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  | 
27  |  |    General Public License for more details.  | 
28  |  |  | 
29  |  |    You should have received copies of the GNU General Public License and  | 
30  |  |    the GNU Lesser General Public License along with this program.  If  | 
31  |  |    not, see http://www.gnu.org/licenses/.  | 
32  |  | */  | 
33  |  |  | 
34  |  | /* This implements chacha-poly1305 according to  | 
35  |  |    draft-irtf-cfrg-chacha20-poly1305-08. The inputs to poly1305 are:  | 
36  |  |  | 
37  |  |      associated data  | 
38  |  |      zero padding  | 
39  |  |      ciphertext  | 
40  |  |      zero padding  | 
41  |  |      length of associated data (64-bit, little endian)  | 
42  |  |      length of ciphertext (64-bit, little endian)  | 
43  |  |  | 
44  |  |    where the padding fields are 0-15 zero bytes, filling up to a  | 
45  |  |    16-byte boundary.  | 
46  |  | */  | 
47  |  |  | 
48  |  | #if HAVE_CONFIG_H  | 
49  |  | # include "config.h"  | 
50  |  | #endif  | 
51  |  |  | 
52  |  | #include <assert.h>  | 
53  |  | #include <string.h>  | 
54  |  |  | 
55  |  | #include "chacha-internal.h"  | 
56  |  | #include "chacha-poly1305.h"  | 
57  |  | #include "poly1305-internal.h"  | 
58  |  |  | 
59  |  | #include "macros.h"  | 
60  |  |  | 
61  | 205  | #define CHACHA_ROUNDS 20  | 
62  |  |  | 
63  |  | /* FIXME: Also set nonce to zero, and implement nonce  | 
64  |  |    auto-increment? */  | 
65  |  | void  | 
66  |  | chacha_poly1305_set_key (struct chacha_poly1305_ctx *ctx,  | 
67  |  |        const uint8_t *key)  | 
68  | 205  | { | 
69  | 205  |   chacha_set_key (&ctx->chacha, key);  | 
70  | 205  | }  | 
71  |  |  | 
72  |  | void  | 
73  |  | chacha_poly1305_set_nonce (struct chacha_poly1305_ctx *ctx,  | 
74  |  |          const uint8_t *nonce)  | 
75  | 205  | { | 
76  | 205  |   union { | 
77  | 205  |     uint32_t x[_CHACHA_STATE_LENGTH];  | 
78  | 205  |     uint8_t subkey[32];  | 
79  | 205  |   } u;  | 
80  |  |  | 
81  | 205  |   chacha_set_nonce96 (&ctx->chacha, nonce);  | 
82  |  |   /* Generate authentication key */  | 
83  | 205  |   _nettle_chacha_core (u.x, ctx->chacha.state, CHACHA_ROUNDS);  | 
84  | 205  |   _nettle_poly1305_set_key (&ctx->poly1305, u.subkey);  | 
85  |  |   /* For final poly1305 processing */  | 
86  | 205  |   memcpy (ctx->s.b, u.subkey + 16, 16);  | 
87  |  |   /* Increment block count */  | 
88  | 205  |   ctx->chacha.state[12] = 1;  | 
89  |  |  | 
90  | 205  |   ctx->auth_size = ctx->data_size = ctx->index = 0;  | 
91  | 205  | }  | 
92  |  |  | 
93  |  | /* FIXME: Duplicated in poly1305-aes128.c */  | 
94  |  | #define COMPRESS(ctx, data) _nettle_poly1305_block(&(ctx)->poly1305, (data), 1)  | 
95  |  |  | 
96  |  | static void  | 
97  |  | poly1305_update (struct chacha_poly1305_ctx *ctx,  | 
98  |  |      size_t length, const uint8_t *data)  | 
99  | 1.15k  | { | 
100  | 1.15k  |   ctx->index = _nettle_poly1305_update (&(ctx)->poly1305,  | 
101  | 1.15k  |           ctx->block, ctx->index, length, data);  | 
102  | 1.15k  | }  | 
103  |  |  | 
104  |  | static void  | 
105  |  | poly1305_pad (struct chacha_poly1305_ctx *ctx)  | 
106  | 439  | { | 
107  | 439  |   if (ctx->index)  | 
108  | 112  |     { | 
109  | 112  |       memset (ctx->block + ctx->index, 0,  | 
110  | 112  |         POLY1305_BLOCK_SIZE - ctx->index);  | 
111  | 112  |       _nettle_poly1305_block(&ctx->poly1305, ctx->block, 1);  | 
112  | 112  |       ctx->index = 0;  | 
113  | 112  |     }  | 
114  | 439  | }  | 
115  |  | void  | 
116  |  | chacha_poly1305_update (struct chacha_poly1305_ctx *ctx,  | 
117  |  |       size_t length, const uint8_t *data)  | 
118  | 922  | { | 
119  | 922  |   assert (ctx->data_size == 0);    | 
120  | 922  |   poly1305_update (ctx, length, data);  | 
121  | 922  |   ctx->auth_size += length;  | 
122  | 922  | }  | 
123  |  |  | 
124  |  |  | 
125  |  | void  | 
126  |  | chacha_poly1305_encrypt (struct chacha_poly1305_ctx *ctx,  | 
127  |  |        size_t length, uint8_t *dst, const uint8_t *src)  | 
128  | 255  | { | 
129  | 255  |   if (!length)  | 
130  | 170  |     return;  | 
131  |  |  | 
132  | 85  |   assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0);  | 
133  | 85  |   poly1305_pad (ctx);  | 
134  |  |  | 
135  | 85  |   chacha_crypt32 (&ctx->chacha, length, dst, src);  | 
136  | 85  |   poly1305_update (ctx, length, dst);  | 
137  | 85  |   ctx->data_size += length;  | 
138  | 85  | }  | 
139  |  |          | 
140  |  | void  | 
141  |  | chacha_poly1305_decrypt (struct chacha_poly1305_ctx *ctx,  | 
142  |  |        size_t length, uint8_t *dst, const uint8_t *src)  | 
143  | 545  | { | 
144  | 545  |   if (!length)  | 
145  | 396  |     return;  | 
146  |  |  | 
147  | 149  |   assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0);  | 
148  | 149  |   poly1305_pad (ctx);  | 
149  |  |  | 
150  | 149  |   poly1305_update (ctx, length, src);  | 
151  | 149  |   chacha_crypt32 (&ctx->chacha, length, dst, src);  | 
152  | 149  |   ctx->data_size += length;  | 
153  | 149  | }  | 
154  |  |          | 
155  |  | void  | 
156  |  | chacha_poly1305_digest (struct chacha_poly1305_ctx *ctx,  | 
157  |  |       size_t length, uint8_t *digest)  | 
158  | 205  | { | 
159  | 205  |   uint8_t buf[16];  | 
160  |  |  | 
161  | 205  |   poly1305_pad (ctx);  | 
162  | 205  |   LE_WRITE_UINT64 (buf, ctx->auth_size);  | 
163  | 205  |   LE_WRITE_UINT64 (buf + 8, ctx->data_size);  | 
164  |  |  | 
165  | 205  |   _nettle_poly1305_block (&ctx->poly1305, buf, 1);  | 
166  |  |  | 
167  | 205  |   _nettle_poly1305_digest (&ctx->poly1305, &ctx->s);  | 
168  | 205  |   memcpy (digest, &ctx->s.b, length);  | 
169  | 205  | }  |