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