82537aa4d449ae5473db805f3a3cd2a289793ccd
[libgcrypt.git] / cipher / cipher-poly1305.c
1 /* cipher-poly1305.c  -  Poly1305 based AEAD cipher mode, RFC-8439
2  * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser general Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25
26 #include "g10lib.h"
27 #include "cipher.h"
28 #include "bufhelp.h"
29 #include "./cipher-internal.h"
30 #include "./poly1305-internal.h"
31
32
33 static inline int
34 poly1305_bytecounter_add (u32 ctr[2], size_t add)
35 {
36   int overflow = 0;
37
38   if (sizeof(add) > sizeof(u32))
39     {
40       u32 high_add = ((add >> 31) >> 1) & 0xffffffff;
41       ctr[1] += high_add;
42       if (ctr[1] < high_add)
43         overflow = 1;
44     }
45
46   ctr[0] += add;
47   if (ctr[0] >= add)
48     return overflow;
49
50   ctr[1] += 1;
51   return (ctr[1] < 1) || overflow;
52 }
53
54
55 static void
56 poly1305_fill_bytecounts (gcry_cipher_hd_t c)
57 {
58   u32 lenbuf[4];
59
60   lenbuf[0] = le_bswap32(c->u_mode.poly1305.aadcount[0]);
61   lenbuf[1] = le_bswap32(c->u_mode.poly1305.aadcount[1]);
62   lenbuf[2] = le_bswap32(c->u_mode.poly1305.datacount[0]);
63   lenbuf[3] = le_bswap32(c->u_mode.poly1305.datacount[1]);
64   _gcry_poly1305_update (&c->u_mode.poly1305.ctx, (byte*)lenbuf,
65                          sizeof(lenbuf));
66
67   wipememory(lenbuf, sizeof(lenbuf));
68 }
69
70
71 static void
72 poly1305_do_padding (gcry_cipher_hd_t c, u32 ctr[2])
73 {
74   static const byte zero_padding_buf[15] = {};
75   u32 padding_count;
76
77   /* Padding to 16 byte boundary. */
78   if (ctr[0] % 16 > 0)
79     {
80       padding_count = 16 - ctr[0] % 16;
81
82       _gcry_poly1305_update (&c->u_mode.poly1305.ctx, zero_padding_buf,
83                              padding_count);
84     }
85 }
86
87
88 static void
89 poly1305_aad_finish (gcry_cipher_hd_t c)
90 {
91   /* After AAD, feed padding bytes so we get 16 byte alignment. */
92   poly1305_do_padding (c, c->u_mode.poly1305.aadcount);
93
94   /* Start of encryption marks end of AAD stream. */
95   c->u_mode.poly1305.aad_finalized = 1;
96
97   c->u_mode.poly1305.datacount[0] = 0;
98   c->u_mode.poly1305.datacount[1] = 0;
99 }
100
101
102 static gcry_err_code_t
103 poly1305_set_zeroiv (gcry_cipher_hd_t c)
104 {
105   byte zero[8] = { 0, };
106
107   return _gcry_cipher_poly1305_setiv (c, zero, sizeof(zero));
108 }
109
110
111 gcry_err_code_t
112 _gcry_cipher_poly1305_authenticate (gcry_cipher_hd_t c,
113                                     const byte * aadbuf, size_t aadbuflen)
114 {
115   if (c->u_mode.poly1305.bytecount_over_limits)
116     return GPG_ERR_INV_LENGTH;
117   if (c->u_mode.poly1305.aad_finalized)
118     return GPG_ERR_INV_STATE;
119   if (c->marks.tag)
120     return GPG_ERR_INV_STATE;
121
122   if (!c->marks.iv)
123     poly1305_set_zeroiv(c);
124
125   if (poly1305_bytecounter_add(c->u_mode.poly1305.aadcount, aadbuflen))
126     {
127       c->u_mode.poly1305.bytecount_over_limits = 1;
128       return GPG_ERR_INV_LENGTH;
129     }
130
131   _gcry_poly1305_update (&c->u_mode.poly1305.ctx, aadbuf, aadbuflen);
132
133   return 0;
134 }
135
136
137 gcry_err_code_t
138 _gcry_cipher_poly1305_encrypt (gcry_cipher_hd_t c,
139                                byte *outbuf, size_t outbuflen,
140                                const byte *inbuf, size_t inbuflen)
141 {
142   gcry_err_code_t err;
143
144   if (outbuflen < inbuflen)
145     return GPG_ERR_BUFFER_TOO_SHORT;
146   if (c->marks.tag)
147     return GPG_ERR_INV_STATE;
148   if (c->u_mode.poly1305.bytecount_over_limits)
149     return GPG_ERR_INV_LENGTH;
150
151   if (!c->marks.iv)
152     {
153       err = poly1305_set_zeroiv(c);
154       if (err)
155         return err;
156     }
157
158   if (!c->u_mode.poly1305.aad_finalized)
159     poly1305_aad_finish(c);
160
161   if (poly1305_bytecounter_add(c->u_mode.poly1305.datacount, inbuflen))
162     {
163       c->u_mode.poly1305.bytecount_over_limits = 1;
164       return GPG_ERR_INV_LENGTH;
165     }
166
167   c->spec->stencrypt(&c->context.c, outbuf, (byte*)inbuf, inbuflen);
168
169   _gcry_poly1305_update (&c->u_mode.poly1305.ctx, outbuf, inbuflen);
170
171   return 0;
172 }
173
174
175 gcry_err_code_t
176 _gcry_cipher_poly1305_decrypt (gcry_cipher_hd_t c,
177                                byte *outbuf, size_t outbuflen,
178                                const byte *inbuf, size_t inbuflen)
179 {
180   gcry_err_code_t err;
181
182   if (outbuflen < inbuflen)
183     return GPG_ERR_BUFFER_TOO_SHORT;
184   if (c->marks.tag)
185     return GPG_ERR_INV_STATE;
186   if (c->u_mode.poly1305.bytecount_over_limits)
187     return GPG_ERR_INV_LENGTH;
188
189   if (!c->marks.iv)
190     {
191       err = poly1305_set_zeroiv(c);
192       if (err)
193         return err;
194     }
195
196   if (!c->u_mode.poly1305.aad_finalized)
197     poly1305_aad_finish(c);
198
199   if (poly1305_bytecounter_add(c->u_mode.poly1305.datacount, inbuflen))
200     {
201       c->u_mode.poly1305.bytecount_over_limits = 1;
202       return GPG_ERR_INV_LENGTH;
203     }
204
205   _gcry_poly1305_update (&c->u_mode.poly1305.ctx, inbuf, inbuflen);
206
207   c->spec->stdecrypt(&c->context.c, outbuf, (byte*)inbuf, inbuflen);
208   return 0;
209 }
210
211
212 static gcry_err_code_t
213 _gcry_cipher_poly1305_tag (gcry_cipher_hd_t c,
214                            byte * outbuf, size_t outbuflen, int check)
215 {
216   gcry_err_code_t err;
217
218   if (outbuflen < POLY1305_TAGLEN)
219     return GPG_ERR_BUFFER_TOO_SHORT;
220   if (c->u_mode.poly1305.bytecount_over_limits)
221     return GPG_ERR_INV_LENGTH;
222
223   if (!c->marks.iv)
224     {
225       err = poly1305_set_zeroiv(c);
226       if (err)
227         return err;
228     }
229
230   if (!c->u_mode.poly1305.aad_finalized)
231     poly1305_aad_finish(c);
232
233   if (!c->marks.tag)
234     {
235       /* After data, feed padding bytes so we get 16 byte alignment. */
236       poly1305_do_padding (c, c->u_mode.poly1305.datacount);
237
238       /* Write byte counts to poly1305. */
239       poly1305_fill_bytecounts(c);
240
241       _gcry_poly1305_finish(&c->u_mode.poly1305.ctx, c->u_iv.iv);
242
243       c->marks.tag = 1;
244     }
245
246   if (!check)
247     {
248       memcpy (outbuf, c->u_iv.iv, POLY1305_TAGLEN);
249     }
250   else
251     {
252       /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF
253        * and thus we need to compare its length first.  */
254       if (outbuflen != POLY1305_TAGLEN
255           || !buf_eq_const (outbuf, c->u_iv.iv, POLY1305_TAGLEN))
256         return GPG_ERR_CHECKSUM;
257     }
258
259   return 0;
260 }
261
262
263 gcry_err_code_t
264 _gcry_cipher_poly1305_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
265                           size_t taglen)
266 {
267   return _gcry_cipher_poly1305_tag (c, outtag, taglen, 0);
268 }
269
270 gcry_err_code_t
271 _gcry_cipher_poly1305_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
272                             size_t taglen)
273 {
274   return _gcry_cipher_poly1305_tag (c, (unsigned char *) intag, taglen, 1);
275 }
276
277
278 void
279 _gcry_cipher_poly1305_setkey (gcry_cipher_hd_t c)
280 {
281   c->u_mode.poly1305.aadcount[0] = 0;
282   c->u_mode.poly1305.aadcount[1] = 0;
283
284   c->u_mode.poly1305.datacount[0] = 0;
285   c->u_mode.poly1305.datacount[1] = 0;
286
287   c->u_mode.poly1305.bytecount_over_limits = 0;
288   c->u_mode.poly1305.aad_finalized = 0;
289   c->marks.tag = 0;
290   c->marks.iv = 0;
291 }
292
293
294 gcry_err_code_t
295 _gcry_cipher_poly1305_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
296 {
297   byte tmpbuf[64]; /* size of ChaCha20 block */
298   gcry_err_code_t err;
299
300   /* IV must be 96-bits */
301   if (!iv && ivlen != (96 / 8))
302     return GPG_ERR_INV_ARG;
303
304   memset(&c->u_mode.poly1305.ctx, 0, sizeof(c->u_mode.poly1305.ctx));
305
306   c->u_mode.poly1305.aadcount[0] = 0;
307   c->u_mode.poly1305.aadcount[1] = 0;
308
309   c->u_mode.poly1305.datacount[0] = 0;
310   c->u_mode.poly1305.datacount[1] = 0;
311
312   c->u_mode.poly1305.bytecount_over_limits = 0;
313   c->u_mode.poly1305.aad_finalized = 0;
314   c->marks.tag = 0;
315   c->marks.iv = 0;
316
317   /* Set up IV for stream cipher. */
318   c->spec->setiv (&c->context.c, iv, ivlen);
319
320   /* Get the first block from ChaCha20. */
321   memset(tmpbuf, 0, sizeof(tmpbuf));
322   c->spec->stencrypt(&c->context.c, tmpbuf, tmpbuf, sizeof(tmpbuf));
323
324   /* Use the first 32-bytes as Poly1305 key. */
325   err = _gcry_poly1305_init (&c->u_mode.poly1305.ctx, tmpbuf, POLY1305_KEYLEN);
326
327   wipememory(tmpbuf, sizeof(tmpbuf));
328
329   if (err)
330     return err;
331
332   c->marks.iv = 1;
333   return 0;
334 }