Add PowerPC extra CFLAGS also for chacha20-ppc and crc-ppc
[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   if (LIKELY(inbuflen > 0) && LIKELY(c->spec->algo == GCRY_CIPHER_CHACHA20))
168     {
169       return _gcry_chacha20_poly1305_encrypt (c, outbuf, inbuf, inbuflen);
170     }
171
172   while (inbuflen)
173     {
174       size_t currlen = inbuflen;
175
176       /* Since checksumming is done after encryption, process input in 24KiB
177        * chunks to keep data loaded in L1 cache for checksumming. */
178       if (currlen > 24 * 1024)
179         currlen = 24 * 1024;
180
181       c->spec->stencrypt(&c->context.c, outbuf, (byte*)inbuf, currlen);
182
183       _gcry_poly1305_update (&c->u_mode.poly1305.ctx, outbuf, currlen);
184
185       outbuf += currlen;
186       inbuf += currlen;
187       outbuflen -= currlen;
188       inbuflen -= currlen;
189     }
190
191   return 0;
192 }
193
194
195 gcry_err_code_t
196 _gcry_cipher_poly1305_decrypt (gcry_cipher_hd_t c,
197                                byte *outbuf, size_t outbuflen,
198                                const byte *inbuf, size_t inbuflen)
199 {
200   gcry_err_code_t err;
201
202   if (outbuflen < inbuflen)
203     return GPG_ERR_BUFFER_TOO_SHORT;
204   if (c->marks.tag)
205     return GPG_ERR_INV_STATE;
206   if (c->u_mode.poly1305.bytecount_over_limits)
207     return GPG_ERR_INV_LENGTH;
208
209   if (!c->marks.iv)
210     {
211       err = poly1305_set_zeroiv(c);
212       if (err)
213         return err;
214     }
215
216   if (!c->u_mode.poly1305.aad_finalized)
217     poly1305_aad_finish(c);
218
219   if (poly1305_bytecounter_add(c->u_mode.poly1305.datacount, inbuflen))
220     {
221       c->u_mode.poly1305.bytecount_over_limits = 1;
222       return GPG_ERR_INV_LENGTH;
223     }
224
225   if (LIKELY(inbuflen > 0) && LIKELY(c->spec->algo == GCRY_CIPHER_CHACHA20))
226     {
227       return _gcry_chacha20_poly1305_decrypt (c, outbuf, inbuf, inbuflen);
228     }
229
230   while (inbuflen)
231     {
232       size_t currlen = inbuflen;
233
234       /* Since checksumming is done before decryption, process input in 24KiB
235        * chunks to keep data loaded in L1 cache for decryption. */
236       if (currlen > 24 * 1024)
237         currlen = 24 * 1024;
238
239       _gcry_poly1305_update (&c->u_mode.poly1305.ctx, inbuf, currlen);
240
241       c->spec->stdecrypt(&c->context.c, outbuf, (byte*)inbuf, currlen);
242
243       outbuf += currlen;
244       inbuf += currlen;
245       outbuflen -= currlen;
246       inbuflen -= currlen;
247     }
248
249   return 0;
250 }
251
252
253 static gcry_err_code_t
254 _gcry_cipher_poly1305_tag (gcry_cipher_hd_t c,
255                            byte * outbuf, size_t outbuflen, int check)
256 {
257   gcry_err_code_t err;
258
259   if (outbuflen < POLY1305_TAGLEN)
260     return GPG_ERR_BUFFER_TOO_SHORT;
261   if (c->u_mode.poly1305.bytecount_over_limits)
262     return GPG_ERR_INV_LENGTH;
263
264   if (!c->marks.iv)
265     {
266       err = poly1305_set_zeroiv(c);
267       if (err)
268         return err;
269     }
270
271   if (!c->u_mode.poly1305.aad_finalized)
272     poly1305_aad_finish(c);
273
274   if (!c->marks.tag)
275     {
276       /* After data, feed padding bytes so we get 16 byte alignment. */
277       poly1305_do_padding (c, c->u_mode.poly1305.datacount);
278
279       /* Write byte counts to poly1305. */
280       poly1305_fill_bytecounts(c);
281
282       _gcry_poly1305_finish(&c->u_mode.poly1305.ctx, c->u_iv.iv);
283
284       c->marks.tag = 1;
285     }
286
287   if (!check)
288     {
289       memcpy (outbuf, c->u_iv.iv, POLY1305_TAGLEN);
290     }
291   else
292     {
293       /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF
294        * and thus we need to compare its length first.  */
295       if (outbuflen != POLY1305_TAGLEN
296           || !buf_eq_const (outbuf, c->u_iv.iv, POLY1305_TAGLEN))
297         return GPG_ERR_CHECKSUM;
298     }
299
300   return 0;
301 }
302
303
304 gcry_err_code_t
305 _gcry_cipher_poly1305_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
306                           size_t taglen)
307 {
308   return _gcry_cipher_poly1305_tag (c, outtag, taglen, 0);
309 }
310
311 gcry_err_code_t
312 _gcry_cipher_poly1305_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
313                             size_t taglen)
314 {
315   return _gcry_cipher_poly1305_tag (c, (unsigned char *) intag, taglen, 1);
316 }
317
318
319 void
320 _gcry_cipher_poly1305_setkey (gcry_cipher_hd_t c)
321 {
322   c->u_mode.poly1305.aadcount[0] = 0;
323   c->u_mode.poly1305.aadcount[1] = 0;
324
325   c->u_mode.poly1305.datacount[0] = 0;
326   c->u_mode.poly1305.datacount[1] = 0;
327
328   c->u_mode.poly1305.bytecount_over_limits = 0;
329   c->u_mode.poly1305.aad_finalized = 0;
330   c->marks.tag = 0;
331   c->marks.iv = 0;
332 }
333
334
335 gcry_err_code_t
336 _gcry_cipher_poly1305_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
337 {
338   byte tmpbuf[64]; /* size of ChaCha20 block */
339   gcry_err_code_t err;
340
341   /* IV must be 96-bits */
342   if (!iv && ivlen != (96 / 8))
343     return GPG_ERR_INV_ARG;
344
345   memset(&c->u_mode.poly1305.ctx, 0, sizeof(c->u_mode.poly1305.ctx));
346
347   c->u_mode.poly1305.aadcount[0] = 0;
348   c->u_mode.poly1305.aadcount[1] = 0;
349
350   c->u_mode.poly1305.datacount[0] = 0;
351   c->u_mode.poly1305.datacount[1] = 0;
352
353   c->u_mode.poly1305.bytecount_over_limits = 0;
354   c->u_mode.poly1305.aad_finalized = 0;
355   c->marks.tag = 0;
356   c->marks.iv = 0;
357
358   /* Set up IV for stream cipher. */
359   c->spec->setiv (&c->context.c, iv, ivlen);
360
361   /* Get the first block from ChaCha20. */
362   memset(tmpbuf, 0, sizeof(tmpbuf));
363   c->spec->stencrypt(&c->context.c, tmpbuf, tmpbuf, sizeof(tmpbuf));
364
365   /* Use the first 32-bytes as Poly1305 key. */
366   err = _gcry_poly1305_init (&c->u_mode.poly1305.ctx, tmpbuf, POLY1305_KEYLEN);
367
368   wipememory(tmpbuf, sizeof(tmpbuf));
369
370   if (err)
371     return err;
372
373   c->marks.iv = 1;
374   return 0;
375 }