Speed-up SHA-1 NEON assembly implementation
[libgcrypt.git] / cipher / poly1305.c
1 /* poly1305.c  -  Poly1305 internals and generic implementation
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 /* The code is based on public-domain Poly1305 implementation by
21  * Andrew Moon at
22  *  https://github.com/floodyberry/poly1305-opt
23  */
24
25 #include <config.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "types.h"
31 #include "g10lib.h"
32 #include "cipher.h"
33 #include "bufhelp.h"
34 #include "poly1305-internal.h"
35
36
37 static const char *selftest (void);
38 \f
39
40
41 #ifdef POLY1305_USE_SSE2
42
43 void _gcry_poly1305_amd64_sse2_init_ext(void *state, const poly1305_key_t *key);
44 unsigned int _gcry_poly1305_amd64_sse2_finish_ext(void *state, const byte *m,
45                                                   size_t remaining,
46                                                   byte mac[16]);
47 unsigned int _gcry_poly1305_amd64_sse2_blocks(void *ctx, const byte *m,
48                                               size_t bytes);
49
50 static const poly1305_ops_t poly1305_amd64_sse2_ops = {
51   POLY1305_SSE2_BLOCKSIZE,
52   _gcry_poly1305_amd64_sse2_init_ext,
53   _gcry_poly1305_amd64_sse2_blocks,
54   _gcry_poly1305_amd64_sse2_finish_ext
55 };
56
57 #endif
58
59
60 #ifdef POLY1305_USE_AVX2
61
62 void _gcry_poly1305_amd64_avx2_init_ext(void *state, const poly1305_key_t *key);
63 unsigned int _gcry_poly1305_amd64_avx2_finish_ext(void *state, const byte *m,
64                                                   size_t remaining,
65                                                   byte mac[16]);
66 unsigned int _gcry_poly1305_amd64_avx2_blocks(void *ctx, const byte *m,
67                                               size_t bytes);
68
69 static const poly1305_ops_t poly1305_amd64_avx2_ops = {
70   POLY1305_AVX2_BLOCKSIZE,
71   _gcry_poly1305_amd64_avx2_init_ext,
72   _gcry_poly1305_amd64_avx2_blocks,
73   _gcry_poly1305_amd64_avx2_finish_ext
74 };
75
76 #endif
77
78
79 #ifdef HAVE_U64_TYPEDEF
80
81 /* Reference unoptimized poly1305 implementation using 32 bit * 32 bit = 64 bit
82  * multiplication and 64 bit addition.
83  */
84
85 typedef struct poly1305_state_ref32_s
86 {
87   u32 r[5];
88   u32 h[5];
89   u32 pad[4];
90   byte final;
91 } poly1305_state_ref32_t;
92
93
94 static void
95 poly1305_init_ext_ref32 (void *state, const poly1305_key_t * key)
96 {
97   poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state;
98
99   gcry_assert (sizeof (*st) + POLY1305_STATE_ALIGNMENT <=
100                sizeof (((poly1305_context_t *) 0)->state));
101
102   /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
103   st->r[0] = (buf_get_le32 (&key->b[0])) & 0x3ffffff;
104   st->r[1] = (buf_get_le32 (&key->b[3]) >> 2) & 0x3ffff03;
105   st->r[2] = (buf_get_le32 (&key->b[6]) >> 4) & 0x3ffc0ff;
106   st->r[3] = (buf_get_le32 (&key->b[9]) >> 6) & 0x3f03fff;
107   st->r[4] = (buf_get_le32 (&key->b[12]) >> 8) & 0x00fffff;
108
109   /* h = 0 */
110   st->h[0] = 0;
111   st->h[1] = 0;
112   st->h[2] = 0;
113   st->h[3] = 0;
114   st->h[4] = 0;
115
116   /* save pad for later */
117   st->pad[0] = buf_get_le32 (&key->b[16]);
118   st->pad[1] = buf_get_le32 (&key->b[20]);
119   st->pad[2] = buf_get_le32 (&key->b[24]);
120   st->pad[3] = buf_get_le32 (&key->b[28]);
121
122   st->final = 0;
123 }
124
125
126 static unsigned int
127 poly1305_blocks_ref32 (void *state, const byte * m, size_t bytes)
128 {
129   poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state;
130   const u32 hibit = (st->final) ? 0 : (1 << 24);        /* 1 << 128 */
131   u32 r0, r1, r2, r3, r4;
132   u32 s1, s2, s3, s4;
133   u32 h0, h1, h2, h3, h4;
134   u64 d0, d1, d2, d3, d4;
135   u32 c;
136
137   r0 = st->r[0];
138   r1 = st->r[1];
139   r2 = st->r[2];
140   r3 = st->r[3];
141   r4 = st->r[4];
142
143   s1 = r1 * 5;
144   s2 = r2 * 5;
145   s3 = r3 * 5;
146   s4 = r4 * 5;
147
148   h0 = st->h[0];
149   h1 = st->h[1];
150   h2 = st->h[2];
151   h3 = st->h[3];
152   h4 = st->h[4];
153
154   while (bytes >= POLY1305_REF_BLOCKSIZE)
155     {
156       /* h += m[i] */
157       h0 += (buf_get_le32 (m + 0)) & 0x3ffffff;
158       h1 += (buf_get_le32 (m + 3) >> 2) & 0x3ffffff;
159       h2 += (buf_get_le32 (m + 6) >> 4) & 0x3ffffff;
160       h3 += (buf_get_le32 (m + 9) >> 6) & 0x3ffffff;
161       h4 += (buf_get_le32 (m + 12) >> 8) | hibit;
162
163       /* h *= r */
164       d0 =
165         ((u64) h0 * r0) + ((u64) h1 * s4) +
166         ((u64) h2 * s3) + ((u64) h3 * s2) + ((u64) h4 * s1);
167       d1 =
168         ((u64) h0 * r1) + ((u64) h1 * r0) +
169         ((u64) h2 * s4) + ((u64) h3 * s3) + ((u64) h4 * s2);
170       d2 =
171         ((u64) h0 * r2) + ((u64) h1 * r1) +
172         ((u64) h2 * r0) + ((u64) h3 * s4) + ((u64) h4 * s3);
173       d3 =
174         ((u64) h0 * r3) + ((u64) h1 * r2) +
175         ((u64) h2 * r1) + ((u64) h3 * r0) + ((u64) h4 * s4);
176       d4 =
177         ((u64) h0 * r4) + ((u64) h1 * r3) +
178         ((u64) h2 * r2) + ((u64) h3 * r1) + ((u64) h4 * r0);
179
180       /* (partial) h %= p */
181       c = (u32) (d0 >> 26);
182       h0 = (u32) d0 & 0x3ffffff;
183       d1 += c;
184       c = (u32) (d1 >> 26);
185       h1 = (u32) d1 & 0x3ffffff;
186       d2 += c;
187       c = (u32) (d2 >> 26);
188       h2 = (u32) d2 & 0x3ffffff;
189       d3 += c;
190       c = (u32) (d3 >> 26);
191       h3 = (u32) d3 & 0x3ffffff;
192       d4 += c;
193       c = (u32) (d4 >> 26);
194       h4 = (u32) d4 & 0x3ffffff;
195       h0 += c * 5;
196       c = (h0 >> 26);
197       h0 = h0 & 0x3ffffff;
198       h1 += c;
199
200       m += POLY1305_REF_BLOCKSIZE;
201       bytes -= POLY1305_REF_BLOCKSIZE;
202     }
203
204   st->h[0] = h0;
205   st->h[1] = h1;
206   st->h[2] = h2;
207   st->h[3] = h3;
208   st->h[4] = h4;
209
210   return (16 * sizeof (u32) + 5 * sizeof (u64) + 5 * sizeof (void *));
211 }
212
213
214 static unsigned int
215 poly1305_finish_ext_ref32 (void *state, const byte * m,
216                            size_t remaining, byte mac[POLY1305_TAGLEN])
217 {
218   poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state;
219   u32 h0, h1, h2, h3, h4, c;
220   u32 g0, g1, g2, g3, g4;
221   u64 f;
222   u32 mask;
223   unsigned int burn = 0;
224
225   /* process the remaining block */
226   if (remaining)
227     {
228       byte final[POLY1305_REF_BLOCKSIZE] = { 0 };
229       size_t i;
230       for (i = 0; i < remaining; i++)
231         final[i] = m[i];
232       final[remaining] = 1;
233       st->final = 1;
234       burn = poly1305_blocks_ref32 (st, final, POLY1305_REF_BLOCKSIZE);
235     }
236
237   /* fully carry h */
238   h0 = st->h[0];
239   h1 = st->h[1];
240   h2 = st->h[2];
241   h3 = st->h[3];
242   h4 = st->h[4];
243
244   c = h1 >> 26;
245   h1 = h1 & 0x3ffffff;
246   h2 += c;
247   c = h2 >> 26;
248   h2 = h2 & 0x3ffffff;
249   h3 += c;
250   c = h3 >> 26;
251   h3 = h3 & 0x3ffffff;
252   h4 += c;
253   c = h4 >> 26;
254   h4 = h4 & 0x3ffffff;
255   h0 += c * 5;
256   c = h0 >> 26;
257   h0 = h0 & 0x3ffffff;
258   h1 += c;
259
260   /* compute h + -p */
261   g0 = h0 + 5;
262   c = g0 >> 26;
263   g0 &= 0x3ffffff;
264   g1 = h1 + c;
265   c = g1 >> 26;
266   g1 &= 0x3ffffff;
267   g2 = h2 + c;
268   c = g2 >> 26;
269   g2 &= 0x3ffffff;
270   g3 = h3 + c;
271   c = g3 >> 26;
272   g3 &= 0x3ffffff;
273   g4 = h4 + c - (1 << 26);
274
275   /* select h if h < p, or h + -p if h >= p */
276   mask = (g4 >> ((sizeof (u32) * 8) - 1)) - 1;
277   g0 &= mask;
278   g1 &= mask;
279   g2 &= mask;
280   g3 &= mask;
281   g4 &= mask;
282   mask = ~mask;
283   h0 = (h0 & mask) | g0;
284   h1 = (h1 & mask) | g1;
285   h2 = (h2 & mask) | g2;
286   h3 = (h3 & mask) | g3;
287   h4 = (h4 & mask) | g4;
288
289   /* h = h % (2^128) */
290   h0 = ((h0) | (h1 << 26)) & 0xffffffff;
291   h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
292   h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
293   h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
294
295   /* mac = (h + pad) % (2^128) */
296   f = (u64) h0 + st->pad[0];
297   h0 = (u32) f;
298   f = (u64) h1 + st->pad[1] + (f >> 32);
299   h1 = (u32) f;
300   f = (u64) h2 + st->pad[2] + (f >> 32);
301   h2 = (u32) f;
302   f = (u64) h3 + st->pad[3] + (f >> 32);
303   h3 = (u32) f;
304
305   buf_put_le32 (mac + 0, h0);
306   buf_put_le32 (mac + 4, h1);
307   buf_put_le32 (mac + 8, h2);
308   buf_put_le32 (mac + 12, h3);
309
310   /* zero out the state */
311   st->h[0] = 0;
312   st->h[1] = 0;
313   st->h[2] = 0;
314   st->h[3] = 0;
315   st->h[4] = 0;
316   st->r[0] = 0;
317   st->r[1] = 0;
318   st->r[2] = 0;
319   st->r[3] = 0;
320   st->r[4] = 0;
321   st->pad[0] = 0;
322   st->pad[1] = 0;
323   st->pad[2] = 0;
324   st->pad[3] = 0;
325
326   /* burn_stack */
327   return (13 * sizeof (u32) + sizeof (u64) +
328           POLY1305_REF_BLOCKSIZE + 6 * sizeof (void *)) + burn;
329 }
330
331
332 static const poly1305_ops_t poly1305_default_ops = {
333   POLY1305_REF_BLOCKSIZE,
334   poly1305_init_ext_ref32,
335   poly1305_blocks_ref32,
336   poly1305_finish_ext_ref32
337 };
338
339 #else /* !HAVE_U64_TYPEDEF */
340
341 /* Reference unoptimized poly1305 implementation using 8 bit * 8 bit = 16 bit
342  * multiplication and 16 bit addition, used when we don't have 'u64'.
343  */
344
345 typedef struct poly1305_state_ref8_t
346 {
347   byte h[17];
348   byte r[17];
349   byte pad[17];
350   byte final;
351 } poly1305_state_ref8_t;
352
353
354 static void
355 poly1305_init_ext_ref8 (void *state, const poly1305_key_t * key)
356 {
357   poly1305_state_ref8_t *st = (poly1305_state_ref8_t *) state;
358   size_t i;
359
360   /* h = 0 */
361   for (i = 0; i < 17; i++)
362     st->h[i] = 0;
363
364   /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
365   st->r[0] = key->b[0];
366   st->r[1] = key->b[1];
367   st->r[2] = key->b[2];
368   st->r[3] = key->b[3] & 0x0f;
369   st->r[4] = key->b[4] & 0xfc;
370   st->r[5] = key->b[5];
371   st->r[6] = key->b[6];
372   st->r[7] = key->b[7] & 0x0f;
373   st->r[8] = key->b[8] & 0xfc;
374   st->r[9] = key->b[9];
375   st->r[10] = key->b[10];
376   st->r[11] = key->b[11] & 0x0f;
377   st->r[12] = key->b[12] & 0xfc;
378   st->r[13] = key->b[13];
379   st->r[14] = key->b[14];
380   st->r[15] = key->b[15] & 0x0f;
381   st->r[16] = 0;
382
383   /* save pad for later */
384   for (i = 0; i < 16; i++)
385     st->pad[i] = key->b[i + 16];
386   st->pad[16] = 0;
387
388   st->final = 0;
389 }
390
391
392 static void
393 poly1305_add_ref8 (byte h[17], const byte c[17])
394 {
395   u16 u;
396   unsigned int i;
397   for (u = 0, i = 0; i < 17; i++)
398     {
399       u += (u16) h[i] + (u16) c[i];
400       h[i] = (byte) u & 0xff;
401       u >>= 8;
402     }
403 }
404
405
406 static void
407 poly1305_squeeze_ref8 (byte h[17], u32 hr[17])
408 {
409   u32 u;
410   unsigned int i;
411   u = 0;
412   for (i = 0; i < 16; i++)
413     {
414       u += hr[i];
415       h[i] = (byte) u & 0xff;
416       u >>= 8;
417     }
418   u += hr[16];
419   h[16] = (byte) u & 0x03;
420   u >>= 2;
421   u += (u << 2);                /* u *= 5; */
422   for (i = 0; i < 16; i++)
423     {
424       u += h[i];
425       h[i] = (byte) u & 0xff;
426       u >>= 8;
427     }
428   h[16] += (byte) u;
429 }
430
431
432 static void
433 poly1305_freeze_ref8 (byte h[17])
434 {
435   static const byte minusp[17] = {
436     0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438     0xfc
439   };
440   byte horig[17], negative;
441   unsigned int i;
442
443   /* compute h + -p */
444   for (i = 0; i < 17; i++)
445     horig[i] = h[i];
446   poly1305_add_ref8 (h, minusp);
447
448   /* select h if h < p, or h + -p if h >= p */
449   negative = -(h[16] >> 7);
450   for (i = 0; i < 17; i++)
451     h[i] ^= negative & (horig[i] ^ h[i]);
452 }
453
454
455 static unsigned int
456 poly1305_blocks_ref8 (void *state, const byte * m, size_t bytes)
457 {
458   poly1305_state_ref8_t *st = (poly1305_state_ref8_t *) state;
459   const byte hibit = st->final ^ 1;     /* 1 << 128 */
460
461   while (bytes >= POLY1305_REF_BLOCKSIZE)
462     {
463       u32 hr[17], u;
464       byte c[17];
465       unsigned int i, j;
466
467       /* h += m */
468       for (i = 0; i < 16; i++)
469         c[i] = m[i];
470       c[16] = hibit;
471       poly1305_add_ref8 (st->h, c);
472
473       /* h *= r */
474       for (i = 0; i < 17; i++)
475         {
476           u = 0;
477           for (j = 0; j <= i; j++)
478             {
479               u += (u16) st->h[j] * st->r[i - j];
480             }
481           for (j = i + 1; j < 17; j++)
482             {
483               u32 v = (u16) st->h[j] * st->r[i + 17 - j];
484               v = ((v << 8) + (v << 6));        /* v *= (5 << 6); */
485               u += v;
486             }
487           hr[i] = u;
488         }
489
490       /* (partial) h %= p */
491       poly1305_squeeze_ref8 (st->h, hr);
492
493       m += POLY1305_REF_BLOCKSIZE;
494       bytes -= POLY1305_REF_BLOCKSIZE;
495     }
496
497   /* burn_stack */
498   return (18 + 2) * sizeof (u32) + 18 + 6 * sizeof (void *) +
499     6 * sizeof (void *);
500 }
501
502
503 static unsigned int
504 poly1305_finish_ext_ref8 (void *state, const byte * m, size_t remaining,
505                           byte mac[POLY1305_TAGLEN])
506 {
507   poly1305_state_ref8_t *st = (poly1305_state_ref8_t *) state;
508   size_t i;
509   unsigned int burn = 0;
510
511   /* process the remaining block */
512   if (remaining)
513     {
514       byte final[POLY1305_REF_BLOCKSIZE] = { 0 };
515       for (i = 0; i < remaining; i++)
516         final[i] = m[i];
517       final[remaining] = 1;
518       st->final = 1;
519       burn = poly1305_blocks_ref8 (st, final, POLY1305_REF_BLOCKSIZE);
520     }
521
522   /* fully reduce h */
523   poly1305_freeze_ref8 (st->h);
524
525   /* h = (h + pad) % (1 << 128) */
526   poly1305_add_ref8 (st->h, st->pad);
527   for (i = 0; i < 16; i++)
528     mac[i] = st->h[i];
529
530   /* zero out the state */
531   for (i = 0; i < 17; i++)
532     st->h[i] = 0;
533   for (i = 0; i < 17; i++)
534     st->r[i] = 0;
535   for (i = 0; i < 17; i++)
536     st->pad[i] = 0;
537
538   /* burn_stack */
539   return POLY1305_REF_BLOCKSIZE + 18 + 16 * sizeof (void *) + burn;
540 }
541
542
543 static const poly1305_ops_t poly1305_default_ops = {
544   POLY1305_REF_BLOCKSIZE,
545   poly1305_init_ext_ref8,
546   poly1305_blocks_ref8,
547   poly1305_finish_ext_ref8
548 };
549
550 #endif /* HAVE_U64_TYPEDEF */
551 \f
552
553
554 static inline void *
555 poly1305_get_state (poly1305_context_t * ctx)
556 {
557   byte *c = ctx->state;
558   c += POLY1305_STATE_ALIGNMENT - 1;
559   c -= (uintptr_t) c & (POLY1305_STATE_ALIGNMENT - 1);
560   return c;
561 }
562
563
564 static void
565 poly1305_init (poly1305_context_t * ctx, const poly1305_key_t * key)
566 {
567   void *state = poly1305_get_state (ctx);
568
569   ctx->leftover = 0;
570
571   ctx->ops->init_ext (state, key);
572 }
573
574
575 void
576 _gcry_poly1305_update (poly1305_context_t * ctx, const byte * m, size_t bytes)
577 {
578   void *state = poly1305_get_state (ctx);
579   unsigned int burn = 0;
580   size_t block_size = ctx->ops->block_size;
581
582   /* handle leftover */
583   if (ctx->leftover)
584     {
585       size_t want = (block_size - ctx->leftover);
586       if (want > bytes)
587         want = bytes;
588       buf_cpy (ctx->buffer + ctx->leftover, m, want);
589       bytes -= want;
590       m += want;
591       ctx->leftover += want;
592       if (ctx->leftover < block_size)
593         return;
594       burn = ctx->ops->blocks (state, ctx->buffer, block_size);
595       ctx->leftover = 0;
596     }
597
598   /* process full blocks */
599   if (bytes >= block_size)
600     {
601       size_t want = (bytes & ~(block_size - 1));
602       burn = ctx->ops->blocks (state, m, want);
603       m += want;
604       bytes -= want;
605     }
606
607   /* store leftover */
608   if (bytes)
609     {
610       buf_cpy (ctx->buffer + ctx->leftover, m, bytes);
611       ctx->leftover += bytes;
612     }
613
614   if (burn)
615     _gcry_burn_stack (burn);
616 }
617
618
619 void
620 _gcry_poly1305_finish (poly1305_context_t * ctx, byte mac[POLY1305_TAGLEN])
621 {
622   void *state = poly1305_get_state (ctx);
623   unsigned int burn;
624
625   burn = ctx->ops->finish_ext (state, ctx->buffer, ctx->leftover, mac);
626
627   _gcry_burn_stack (burn);
628 }
629
630
631 gcry_err_code_t
632 _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key,
633                      size_t keylen)
634 {
635   static int initialized;
636   static const char *selftest_failed;
637   poly1305_key_t keytmp;
638   unsigned int features = _gcry_get_hw_features ();
639
640   if (!initialized)
641     {
642       initialized = 1;
643       selftest_failed = selftest ();
644       if (selftest_failed)
645         log_error ("Poly1305 selftest failed (%s)\n", selftest_failed);
646     }
647
648   if (keylen != POLY1305_KEYLEN)
649     return GPG_ERR_INV_KEYLEN;
650
651   if (selftest_failed)
652     return GPG_ERR_SELFTEST_FAILED;
653
654 #ifdef POLY1305_USE_SSE2
655   ctx->ops = &poly1305_amd64_sse2_ops;
656 #else
657   ctx->ops = &poly1305_default_ops;
658 #endif
659
660 #ifdef POLY1305_USE_AVX2
661   if (features & HWF_INTEL_AVX2)
662     ctx->ops = &poly1305_amd64_avx2_ops;
663 #endif
664   (void)features;
665
666   buf_cpy (keytmp.b, key, POLY1305_KEYLEN);
667   poly1305_init (ctx, &keytmp);
668
669   wipememory (&keytmp, sizeof (keytmp));
670
671   return 0;
672 }
673
674
675 static void
676 poly1305_auth (byte mac[POLY1305_TAGLEN], const byte * m, size_t bytes,
677                const byte * key)
678 {
679   poly1305_context_t ctx;
680
681   memset (&ctx, 0, sizeof (ctx));
682
683   _gcry_poly1305_init (&ctx, key, POLY1305_KEYLEN);
684   _gcry_poly1305_update (&ctx, m, bytes);
685   _gcry_poly1305_finish (&ctx, mac);
686
687   wipememory (&ctx, sizeof (ctx));
688 }
689
690
691 static const char *
692 selftest (void)
693 {
694   /* example from nacl */
695   static const byte nacl_key[POLY1305_KEYLEN] = {
696     0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91,
697     0x6d, 0x11, 0xc2, 0xcb, 0x21, 0x4d, 0x3c, 0x25,
698     0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65,
699     0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80,
700   };
701
702   static const byte nacl_msg[131] = {
703     0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73,
704     0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce,
705     0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4,
706     0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a,
707     0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b,
708     0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72,
709     0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2,
710     0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38,
711     0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a,
712     0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae,
713     0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea,
714     0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda,
715     0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde,
716     0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3,
717     0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6,
718     0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74,
719     0xe3, 0x55, 0xa5
720   };
721
722   static const byte nacl_mac[16] = {
723     0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5,
724     0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9
725   };
726
727   /* generates a final value of (2^130 - 2) == 3 */
728   static const byte wrap_key[POLY1305_KEYLEN] = {
729     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733   };
734
735   static const byte wrap_msg[16] = {
736     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
737     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
738   };
739
740   static const byte wrap_mac[16] = {
741     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
742     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
743   };
744
745   /* mac of the macs of messages of length 0 to 256, where the key and messages
746    * have all their values set to the length
747    */
748   static const byte total_key[POLY1305_KEYLEN] = {
749     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
750     0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9,
751     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
752     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
753   };
754
755   static const byte total_mac[16] = {
756     0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
757     0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39
758   };
759
760   poly1305_context_t ctx;
761   poly1305_context_t total_ctx;
762   byte all_key[POLY1305_KEYLEN];
763   byte all_msg[256];
764   byte mac[16];
765   size_t i, j;
766
767   memset (&ctx, 0, sizeof (ctx));
768   memset (&total_ctx, 0, sizeof (total_ctx));
769
770   memset (mac, 0, sizeof (mac));
771   poly1305_auth (mac, nacl_msg, sizeof (nacl_msg), nacl_key);
772   if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0)
773     return "Poly1305 test 1 failed.";
774
775   /* SSE2/AVX have a 32 byte block size, but also support 64 byte blocks, so
776    * make sure everything still works varying between them */
777   memset (mac, 0, sizeof (mac));
778   _gcry_poly1305_init (&ctx, nacl_key, POLY1305_KEYLEN);
779   _gcry_poly1305_update (&ctx, nacl_msg + 0, 32);
780   _gcry_poly1305_update (&ctx, nacl_msg + 32, 64);
781   _gcry_poly1305_update (&ctx, nacl_msg + 96, 16);
782   _gcry_poly1305_update (&ctx, nacl_msg + 112, 8);
783   _gcry_poly1305_update (&ctx, nacl_msg + 120, 4);
784   _gcry_poly1305_update (&ctx, nacl_msg + 124, 2);
785   _gcry_poly1305_update (&ctx, nacl_msg + 126, 1);
786   _gcry_poly1305_update (&ctx, nacl_msg + 127, 1);
787   _gcry_poly1305_update (&ctx, nacl_msg + 128, 1);
788   _gcry_poly1305_update (&ctx, nacl_msg + 129, 1);
789   _gcry_poly1305_update (&ctx, nacl_msg + 130, 1);
790   _gcry_poly1305_finish (&ctx, mac);
791   if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0)
792     return "Poly1305 test 2 failed.";
793
794   memset (mac, 0, sizeof (mac));
795   poly1305_auth (mac, wrap_msg, sizeof (wrap_msg), wrap_key);
796   if (memcmp (wrap_mac, mac, sizeof (nacl_mac)) != 0)
797     return "Poly1305 test 3 failed.";
798
799   _gcry_poly1305_init (&total_ctx, total_key, POLY1305_KEYLEN);
800   for (i = 0; i < 256; i++)
801     {
802       /* set key and message to 'i,i,i..' */
803       for (j = 0; j < sizeof (all_key); j++)
804         all_key[j] = i;
805       for (j = 0; j < i; j++)
806         all_msg[j] = i;
807       poly1305_auth (mac, all_msg, i, all_key);
808       _gcry_poly1305_update (&total_ctx, mac, 16);
809     }
810   _gcry_poly1305_finish (&total_ctx, mac);
811   if (memcmp (total_mac, mac, sizeof (total_mac)) != 0)
812     return "Poly1305 test 4 failed.";
813
814   return NULL;
815 }