Add ARMv8/CE acceleration for AES-XTS
[libgcrypt.git] / cipher / poly1305.c
1 /* poly1305.c  -  Poly1305 internals and generic implementation
2  * Copyright (C) 2014,2017,2018 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
25 #include "types.h"
26 #include "g10lib.h"
27 #include "cipher.h"
28 #include "bufhelp.h"
29 #include "poly1305-internal.h"
30
31 #include "mpi-internal.h"
32 #include "longlong.h"
33
34
35 static const char *selftest (void);
36
37
38 #undef USE_MPI_64BIT
39 #undef USE_MPI_32BIT
40 #if BYTES_PER_MPI_LIMB == 8 && defined(HAVE_U64_TYPEDEF)
41 # define USE_MPI_64BIT 1
42 #elif BYTES_PER_MPI_LIMB == 4
43 # define USE_MPI_32BIT 1
44 #else
45 # error please implement for this limb size.
46 #endif
47
48
49 static void poly1305_init (poly1305_context_t *ctx,
50                            const byte key[POLY1305_KEYLEN])
51 {
52   POLY1305_STATE *st = &ctx->state;
53
54   ctx->leftover = 0;
55
56   st->h[0] = 0;
57   st->h[1] = 0;
58   st->h[2] = 0;
59   st->h[3] = 0;
60   st->h[4] = 0;
61
62   st->r[0] = buf_get_le32(key + 0)  & 0x0fffffff;
63   st->r[1] = buf_get_le32(key + 4)  & 0x0ffffffc;
64   st->r[2] = buf_get_le32(key + 8)  & 0x0ffffffc;
65   st->r[3] = buf_get_le32(key + 12) & 0x0ffffffc;
66
67   st->k[0] = buf_get_le32(key + 16);
68   st->k[1] = buf_get_le32(key + 20);
69   st->k[2] = buf_get_le32(key + 24);
70   st->k[3] = buf_get_le32(key + 28);
71 }
72
73
74 #ifdef USE_MPI_64BIT
75
76 #if defined (__aarch64__) && __GNUC__ >= 4
77
78 /* A += B (armv8/aarch64) */
79 #define ADD_1305_64(A2, A1, A0, B2, B1, B0) \
80       __asm__ ("adds %0, %3, %0\n" \
81                "adcs %1, %4, %1\n" \
82                "adc  %2, %5, %2\n" \
83                : "+r" (A0), "+r" (A1), "+r" (A2) \
84                : "r" (B0), "r" (B1), "r" (B2) \
85                : "cc" )
86
87 #endif /* __aarch64__ */
88
89 #if defined (__x86_64__) && __GNUC__ >= 4
90
91 /* A += B (x86-64) */
92 #define ADD_1305_64(A2, A1, A0, B2, B1, B0) \
93       __asm__ ("addq %3, %0\n" \
94                "adcq %4, %1\n" \
95                "adcq %5, %2\n" \
96                : "+r" (A0), "+r" (A1), "+r" (A2) \
97                : "g" (B0), "g" (B1), "g" (B2) \
98                : "cc" )
99
100 #endif /* __x86_64__ */
101
102 #ifndef ADD_1305_64
103 /* A += B (generic, mpi) */
104 #  define ADD_1305_64(A2, A1, A0, B2, B1, B0) do { \
105     u64 carry; \
106     add_ssaaaa(carry, A0, 0, A0, 0, B0); \
107     add_ssaaaa(A2, A1, A2, A1, B2, B1); \
108     add_ssaaaa(A2, A1, A2, A1, 0, carry); \
109   } while (0)
110 #endif
111
112 /* H = H * R mod 2¹³⁰-5 */
113 #define MUL_MOD_1305_64(H2, H1, H0, R1, R0, R1_MULT5) do { \
114     u64 x0_lo, x0_hi, x1_lo, x1_hi; \
115     u64 t0_lo, t0_hi, t1_lo, t1_hi; \
116     \
117     /* x = a * r (partial mod 2^130-5) */ \
118     umul_ppmm(x0_hi, x0_lo, H0, R0);  /* h0 * r0 */ \
119     umul_ppmm(x1_hi, x1_lo, H0, R1);  /* h0 * r1 */ \
120     \
121     umul_ppmm(t0_hi, t0_lo, H1, R1_MULT5); /* h1 * r1 mod 2^130-5 */ \
122     add_ssaaaa(x0_hi, x0_lo, x0_hi, x0_lo, t0_hi, t0_lo); \
123     umul_ppmm(t1_hi, t1_lo, H1, R0);       /* h1 * r0 */ \
124     add_ssaaaa(x1_hi, x1_lo, x1_hi, x1_lo, t1_hi, t1_lo); \
125     \
126     t1_lo = H2 * R1_MULT5; /* h2 * r1 mod 2^130-5 */ \
127     t1_hi = H2 * R0;       /* h2 * r0 */ \
128     add_ssaaaa(H0, H1, x1_hi, x1_lo, t1_hi, t1_lo); \
129     \
130     /* carry propagation */ \
131     H2 = H0 & 3; \
132     H0 = (H0 >> 2) * 5; /* msb mod 2^130-5 */ \
133     ADD_1305_64(H2, H1, H0, 0, x0_hi, x0_lo); \
134   } while (0)
135
136 unsigned int
137 poly1305_blocks (poly1305_context_t *ctx, const byte *buf, size_t len,
138                  byte high_pad)
139 {
140   POLY1305_STATE *st = &ctx->state;
141   u64 r0, r1, r1_mult5;
142   u64 h0, h1, h2;
143   u64 m0, m1, m2;
144
145   m2 = high_pad;
146
147   h0 = st->h[0] + ((u64)st->h[1] << 32);
148   h1 = st->h[2] + ((u64)st->h[3] << 32);
149   h2 = st->h[4];
150
151   r0 = st->r[0] + ((u64)st->r[1] << 32);
152   r1 = st->r[2] + ((u64)st->r[3] << 32);
153
154   r1_mult5 = (r1 >> 2) + r1;
155
156   m0 = buf_get_le64(buf + 0);
157   m1 = buf_get_le64(buf + 8);
158   buf += POLY1305_BLOCKSIZE;
159   len -= POLY1305_BLOCKSIZE;
160
161   while (len >= POLY1305_BLOCKSIZE)
162     {
163       /* a = h + m */
164       ADD_1305_64(h2, h1, h0, m2, m1, m0);
165
166       m0 = buf_get_le64(buf + 0);
167       m1 = buf_get_le64(buf + 8);
168
169       /* h = a * r (partial mod 2^130-5) */
170       MUL_MOD_1305_64(h2, h1, h0, r1, r0, r1_mult5);
171
172       buf += POLY1305_BLOCKSIZE;
173       len -= POLY1305_BLOCKSIZE;
174     }
175
176   /* a = h + m */
177   ADD_1305_64(h2, h1, h0, m2, m1, m0);
178
179   /* h = a * r (partial mod 2^130-5) */
180   MUL_MOD_1305_64(h2, h1, h0, r1, r0, r1_mult5);
181
182   st->h[0] = h0;
183   st->h[1] = h0 >> 32;
184   st->h[2] = h1;
185   st->h[3] = h1 >> 32;
186   st->h[4] = h2;
187
188   return 6 * sizeof (void *) + 18 * sizeof (u64);
189 }
190
191 static unsigned int poly1305_final (poly1305_context_t *ctx,
192                                     byte mac[POLY1305_TAGLEN])
193 {
194   POLY1305_STATE *st = &ctx->state;
195   unsigned int burn = 0;
196   u64 u, carry;
197   u64 k0, k1;
198   u64 h0, h1;
199   u64 h2;
200
201   /* process the remaining block */
202   if (ctx->leftover)
203     {
204       ctx->buffer[ctx->leftover++] = 1;
205       for (; ctx->leftover < POLY1305_BLOCKSIZE; ctx->leftover++)
206         ctx->buffer[ctx->leftover] = 0;
207       burn = poly1305_blocks (ctx, ctx->buffer, POLY1305_BLOCKSIZE, 0);
208     }
209
210   h0 = st->h[0] + ((u64)st->h[1] << 32);
211   h1 = st->h[2] + ((u64)st->h[3] << 32);
212   h2 = st->h[4];
213
214   k0 = st->k[0] + ((u64)st->k[1] << 32);
215   k1 = st->k[2] + ((u64)st->k[3] << 32);
216
217   /* check if h is more than 2^130-5, by adding 5. */
218   add_ssaaaa(carry, u, 0, h0, 0, 5);
219   add_ssaaaa(carry, u, 0, carry, 0, h1);
220   u = (carry + h2) >> 2; /* u == 0 or 1 */
221
222   /* minus 2^130-5 ... (+5) */
223   u = (-u) & 5;
224   add_ssaaaa(h1, h0, h1, h0, 0, u);
225
226   /* add high part of key + h */
227   add_ssaaaa(h1, h0, h1, h0, k1, k0);
228   buf_put_le64(mac + 0, h0);
229   buf_put_le64(mac + 8, h1);
230
231   /* burn_stack */
232   return 4 * sizeof (void *) + 7 * sizeof (u64) + burn;
233 }
234
235 #endif /* USE_MPI_64BIT */
236
237 #ifdef USE_MPI_32BIT
238
239 #ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
240
241 /* HI:LO += A * B (arm) */
242 #define UMUL_ADD_32(HI, LO, A, B) \
243       __asm__ ("umlal %1, %0, %4, %5" \
244                : "=r" (HI), "=r" (LO) \
245                : "0" (HI), "1" (LO), "r" (A), "r" (B) )
246
247 /* A += B (arm) */
248 #define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) \
249       __asm__ ("adds %0, %0, %5\n" \
250                "adcs %1, %1, %6\n" \
251                "adcs %2, %2, %7\n" \
252                "adcs %3, %3, %8\n" \
253                "adc %4, %4, %9\n" \
254                : "+r" (A0), "+r" (A1), "+r" (A2), "+r" (A3), "+r" (A4) \
255                : "r" (B0), "r" (B1), "r" (B2), "r" (B3), "r" (B4) \
256                : "cc" )
257
258 #endif /* HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS */
259
260 #if defined (__i386__) && __GNUC__ >= 4
261
262 /* A += B (i386) */
263 #define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) \
264       __asm__ ("addl %5, %0\n" \
265                "adcl %6, %1\n" \
266                "adcl %7, %2\n" \
267                "adcl %8, %3\n" \
268                "adcl %9, %4\n" \
269                : "+r" (A0), "+r" (A1), "+r" (A2), "+r" (A3), "+r" (A4) \
270                : "g" (B0), "g" (B1), "g" (B2), "g" (B3), "g" (B4) \
271                : "cc" )
272
273 #endif /* __i386__ */
274
275 #ifndef UMUL_ADD_32
276 /* HI:LO += A * B (generic, mpi) */
277 #  define UMUL_ADD_32(HI, LO, A, B) do { \
278     u32 t_lo, t_hi; \
279     umul_ppmm(t_hi, t_lo, A, B); \
280     add_ssaaaa(HI, LO, HI, LO, t_hi, t_lo); \
281   } while (0)
282 #endif
283
284 #ifndef ADD_1305_32
285 /* A += B (generic, mpi) */
286 #  define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) do { \
287     u32 carry0, carry1, carry2; \
288     add_ssaaaa(carry0, A0, 0, A0, 0, B0); \
289     add_ssaaaa(carry1, A1, 0, A1, 0, B1); \
290     add_ssaaaa(carry1, A1, carry1, A1, 0, carry0); \
291     add_ssaaaa(carry2, A2, 0, A2, 0, B2); \
292     add_ssaaaa(carry2, A2, carry2, A2, 0, carry1); \
293     add_ssaaaa(A4, A3, A4, A3, B4, B3); \
294     add_ssaaaa(A4, A3, A4, A3, 0, carry2); \
295   } while (0)
296 #endif
297
298 /* H = H * R mod 2¹³⁰-5 */
299 #define MUL_MOD_1305_32(H4, H3, H2, H1, H0, R3, R2, R1, R0, \
300                         R3_MULT5, R2_MULT5, R1_MULT5) do { \
301     u32 x0_lo, x0_hi, x1_lo, x1_hi, x2_lo, x2_hi, x3_lo, x3_hi; \
302     u32 t0_lo, t0_hi; \
303     \
304     /* x = a * r (partial mod 2^130-5) */ \
305     umul_ppmm(x0_hi, x0_lo, H0, R0);  /* h0 * r0 */ \
306     umul_ppmm(x1_hi, x1_lo, H0, R1);  /* h0 * r1 */ \
307     umul_ppmm(x2_hi, x2_lo, H0, R2);  /* h0 * r2 */ \
308     umul_ppmm(x3_hi, x3_lo, H0, R3);  /* h0 * r3 */ \
309     \
310     UMUL_ADD_32(x0_hi, x0_lo, H1, R3_MULT5); /* h1 * r3 mod 2^130-5 */ \
311     UMUL_ADD_32(x1_hi, x1_lo, H1, R0);       /* h1 * r0 */ \
312     UMUL_ADD_32(x2_hi, x2_lo, H1, R1);       /* h1 * r1 */ \
313     UMUL_ADD_32(x3_hi, x3_lo, H1, R2);       /* h1 * r2 */ \
314     \
315     UMUL_ADD_32(x0_hi, x0_lo, H2, R2_MULT5); /* h2 * r2 mod 2^130-5 */ \
316     UMUL_ADD_32(x1_hi, x1_lo, H2, R3_MULT5); /* h2 * r3 mod 2^130-5 */ \
317     UMUL_ADD_32(x2_hi, x2_lo, H2, R0);       /* h2 * r0 */ \
318     UMUL_ADD_32(x3_hi, x3_lo, H2, R1);       /* h2 * r1 */ \
319     \
320     UMUL_ADD_32(x0_hi, x0_lo, H3, R1_MULT5); /* h3 * r1 mod 2^130-5 */ \
321     H1 = x0_hi; \
322     UMUL_ADD_32(x1_hi, x1_lo, H3, R2_MULT5); /* h3 * r2 mod 2^130-5 */ \
323     UMUL_ADD_32(x2_hi, x2_lo, H3, R3_MULT5); /* h3 * r3 mod 2^130-5 */ \
324     UMUL_ADD_32(x3_hi, x3_lo, H3, R0);       /* h3 * r0 */ \
325     \
326     t0_lo = H4 * R1_MULT5; /* h4 * r1 mod 2^130-5 */ \
327     t0_hi = H4 * R2_MULT5; /* h4 * r2 mod 2^130-5 */ \
328     add_ssaaaa(H2, x1_lo, x1_hi, x1_lo, 0, t0_lo); \
329     add_ssaaaa(H3, x2_lo, x2_hi, x2_lo, 0, t0_hi); \
330     t0_lo = H4 * R3_MULT5; /* h4 * r3 mod 2^130-5 */ \
331     t0_hi = H4 * R0;       /* h4 * r0 */ \
332     add_ssaaaa(H4, x3_lo, x3_hi, x3_lo, t0_hi, t0_lo); \
333     \
334     /* carry propagation */ \
335     H0 = (H4 >> 2) * 5; /* msb mod 2^130-5 */ \
336     H4 = H4 & 3; \
337     ADD_1305_32(H4, H3, H2, H1, H0, 0, x3_lo, x2_lo, x1_lo, x0_lo); \
338   } while (0)
339
340 unsigned int
341 poly1305_blocks (poly1305_context_t *ctx, const byte *buf, size_t len,
342                  byte high_pad)
343 {
344   POLY1305_STATE *st = &ctx->state;
345   u32 r1_mult5, r2_mult5, r3_mult5;
346   u32 h0, h1, h2, h3, h4;
347   u32 m0, m1, m2, m3, m4;
348
349   m4 = high_pad;
350
351   h0 = st->h[0];
352   h1 = st->h[1];
353   h2 = st->h[2];
354   h3 = st->h[3];
355   h4 = st->h[4];
356
357   r1_mult5 = (st->r[1] >> 2) + st->r[1];
358   r2_mult5 = (st->r[2] >> 2) + st->r[2];
359   r3_mult5 = (st->r[3] >> 2) + st->r[3];
360
361   while (len >= POLY1305_BLOCKSIZE)
362     {
363       m0 = buf_get_le32(buf + 0);
364       m1 = buf_get_le32(buf + 4);
365       m2 = buf_get_le32(buf + 8);
366       m3 = buf_get_le32(buf + 12);
367
368       /* a = h + m */
369       ADD_1305_32(h4, h3, h2, h1, h0, m4, m3, m2, m1, m0);
370
371       /* h = a * r (partial mod 2^130-5) */
372       MUL_MOD_1305_32(h4, h3, h2, h1, h0,
373                       st->r[3], st->r[2], st->r[1], st->r[0],
374                       r3_mult5, r2_mult5, r1_mult5);
375
376       buf += POLY1305_BLOCKSIZE;
377       len -= POLY1305_BLOCKSIZE;
378     }
379
380   st->h[0] = h0;
381   st->h[1] = h1;
382   st->h[2] = h2;
383   st->h[3] = h3;
384   st->h[4] = h4;
385
386   return 6 * sizeof (void *) + 28 * sizeof (u32);
387 }
388
389 static unsigned int poly1305_final (poly1305_context_t *ctx,
390                                     byte mac[POLY1305_TAGLEN])
391 {
392   POLY1305_STATE *st = &ctx->state;
393   unsigned int burn = 0;
394   u32 carry, tmp0, tmp1, tmp2, u;
395   u32 h4, h3, h2, h1, h0;
396
397   /* process the remaining block */
398   if (ctx->leftover)
399     {
400       ctx->buffer[ctx->leftover++] = 1;
401       for (; ctx->leftover < POLY1305_BLOCKSIZE; ctx->leftover++)
402         ctx->buffer[ctx->leftover] = 0;
403       burn = poly1305_blocks (ctx, ctx->buffer, POLY1305_BLOCKSIZE, 0);
404     }
405
406   h0 = st->h[0];
407   h1 = st->h[1];
408   h2 = st->h[2];
409   h3 = st->h[3];
410   h4 = st->h[4];
411
412   /* check if h is more than 2^130-5, by adding 5. */
413   add_ssaaaa(carry, tmp0, 0, h0, 0, 5);
414   add_ssaaaa(carry, tmp0, 0, carry, 0, h1);
415   add_ssaaaa(carry, tmp0, 0, carry, 0, h2);
416   add_ssaaaa(carry, tmp0, 0, carry, 0, h3);
417   u = (carry + h4) >> 2; /* u == 0 or 1 */
418
419   /* minus 2^130-5 ... (+5) */
420   u = (-u) & 5;
421   add_ssaaaa(carry, h0, 0, h0, 0, u);
422   add_ssaaaa(carry, h1, 0, h1, 0, carry);
423   add_ssaaaa(carry, h2, 0, h2, 0, carry);
424   add_ssaaaa(carry, h3, 0, h3, 0, carry);
425
426   /* add high part of key + h */
427   add_ssaaaa(tmp0, h0, 0, h0, 0, st->k[0]);
428   add_ssaaaa(tmp1, h1, 0, h1, 0, st->k[1]);
429   add_ssaaaa(tmp1, h1, tmp1, h1, 0, tmp0);
430   add_ssaaaa(tmp2, h2, 0, h2, 0, st->k[2]);
431   add_ssaaaa(tmp2, h2, tmp2, h2, 0, tmp1);
432   add_ssaaaa(carry, h3, 0, h3, 0, st->k[3]);
433   h3 += tmp2;
434
435   buf_put_le32(mac + 0, h0);
436   buf_put_le32(mac + 4, h1);
437   buf_put_le32(mac + 8, h2);
438   buf_put_le32(mac + 12, h3);
439
440   /* burn_stack */
441   return 4 * sizeof (void *) + 10 * sizeof (u32) + burn;
442 }
443
444 #endif /* USE_MPI_32BIT */
445
446
447 void
448 _gcry_poly1305_update (poly1305_context_t *ctx, const byte *m, size_t bytes)
449 {
450   unsigned int burn = 0;
451
452   /* handle leftover */
453   if (ctx->leftover)
454     {
455       size_t want = (POLY1305_BLOCKSIZE - ctx->leftover);
456       if (want > bytes)
457         want = bytes;
458       buf_cpy (ctx->buffer + ctx->leftover, m, want);
459       bytes -= want;
460       m += want;
461       ctx->leftover += want;
462       if (ctx->leftover < POLY1305_BLOCKSIZE)
463         return;
464       burn = poly1305_blocks (ctx, ctx->buffer, POLY1305_BLOCKSIZE, 1);
465       ctx->leftover = 0;
466     }
467
468   /* process full blocks */
469   if (bytes >= POLY1305_BLOCKSIZE)
470     {
471       size_t nblks = bytes / POLY1305_BLOCKSIZE;
472       burn = poly1305_blocks (ctx, m, nblks * POLY1305_BLOCKSIZE, 1);
473       m += nblks * POLY1305_BLOCKSIZE;
474       bytes -= nblks * POLY1305_BLOCKSIZE;
475     }
476
477   /* store leftover */
478   if (bytes)
479     {
480       buf_cpy (ctx->buffer + ctx->leftover, m, bytes);
481       ctx->leftover += bytes;
482     }
483
484   if (burn)
485     _gcry_burn_stack (burn);
486 }
487
488
489 void
490 _gcry_poly1305_finish (poly1305_context_t *ctx, byte mac[POLY1305_TAGLEN])
491 {
492   unsigned int burn;
493
494   burn = poly1305_final (ctx, mac);
495
496   _gcry_burn_stack (burn);
497 }
498
499
500 gcry_err_code_t
501 _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key,
502                      size_t keylen)
503 {
504   static int initialized;
505   static const char *selftest_failed;
506
507   if (!initialized)
508     {
509       initialized = 1;
510       selftest_failed = selftest ();
511       if (selftest_failed)
512         log_error ("Poly1305 selftest failed (%s)\n", selftest_failed);
513     }
514
515   if (keylen != POLY1305_KEYLEN)
516     return GPG_ERR_INV_KEYLEN;
517
518   if (selftest_failed)
519     return GPG_ERR_SELFTEST_FAILED;
520
521   poly1305_init (ctx, key);
522
523   return 0;
524 }
525
526
527 static void
528 poly1305_auth (byte mac[POLY1305_TAGLEN], const byte * m, size_t bytes,
529                const byte * key)
530 {
531   poly1305_context_t ctx;
532
533   memset (&ctx, 0, sizeof (ctx));
534
535   _gcry_poly1305_init (&ctx, key, POLY1305_KEYLEN);
536   _gcry_poly1305_update (&ctx, m, bytes);
537   _gcry_poly1305_finish (&ctx, mac);
538
539   wipememory (&ctx, sizeof (ctx));
540 }
541
542
543 static const char *
544 selftest (void)
545 {
546   /* example from nacl */
547   static const byte nacl_key[POLY1305_KEYLEN] = {
548     0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91,
549     0x6d, 0x11, 0xc2, 0xcb, 0x21, 0x4d, 0x3c, 0x25,
550     0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65,
551     0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80,
552   };
553
554   static const byte nacl_msg[131] = {
555     0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73,
556     0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce,
557     0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4,
558     0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a,
559     0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b,
560     0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72,
561     0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2,
562     0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38,
563     0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a,
564     0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae,
565     0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea,
566     0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda,
567     0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde,
568     0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3,
569     0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6,
570     0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74,
571     0xe3, 0x55, 0xa5
572   };
573
574   static const byte nacl_mac[16] = {
575     0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5,
576     0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9
577   };
578
579   /* generates a final value of (2^130 - 2) == 3 */
580   static const byte wrap_key[POLY1305_KEYLEN] = {
581     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585   };
586
587   static const byte wrap_msg[16] = {
588     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
589     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
590   };
591
592   static const byte wrap_mac[16] = {
593     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595   };
596
597   /* mac of the macs of messages of length 0 to 256, where the key and messages
598    * have all their values set to the length
599    */
600   static const byte total_key[POLY1305_KEYLEN] = {
601     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
602     0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9,
603     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
604     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
605   };
606
607   static const byte total_mac[16] = {
608     0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
609     0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39
610   };
611
612   poly1305_context_t ctx;
613   poly1305_context_t total_ctx;
614   byte all_key[POLY1305_KEYLEN];
615   byte all_msg[256];
616   byte mac[16];
617   size_t i, j;
618
619   memset (&ctx, 0, sizeof (ctx));
620   memset (&total_ctx, 0, sizeof (total_ctx));
621
622   memset (mac, 0, sizeof (mac));
623   poly1305_auth (mac, nacl_msg, sizeof (nacl_msg), nacl_key);
624   if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0)
625     return "Poly1305 test 1 failed.";
626
627   /* SSE2/AVX have a 32 byte block size, but also support 64 byte blocks, so
628    * make sure everything still works varying between them */
629   memset (mac, 0, sizeof (mac));
630   _gcry_poly1305_init (&ctx, nacl_key, POLY1305_KEYLEN);
631   _gcry_poly1305_update (&ctx, nacl_msg + 0, 32);
632   _gcry_poly1305_update (&ctx, nacl_msg + 32, 64);
633   _gcry_poly1305_update (&ctx, nacl_msg + 96, 16);
634   _gcry_poly1305_update (&ctx, nacl_msg + 112, 8);
635   _gcry_poly1305_update (&ctx, nacl_msg + 120, 4);
636   _gcry_poly1305_update (&ctx, nacl_msg + 124, 2);
637   _gcry_poly1305_update (&ctx, nacl_msg + 126, 1);
638   _gcry_poly1305_update (&ctx, nacl_msg + 127, 1);
639   _gcry_poly1305_update (&ctx, nacl_msg + 128, 1);
640   _gcry_poly1305_update (&ctx, nacl_msg + 129, 1);
641   _gcry_poly1305_update (&ctx, nacl_msg + 130, 1);
642   _gcry_poly1305_finish (&ctx, mac);
643   if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0)
644     return "Poly1305 test 2 failed.";
645
646   memset (mac, 0, sizeof (mac));
647   poly1305_auth (mac, wrap_msg, sizeof (wrap_msg), wrap_key);
648   if (memcmp (wrap_mac, mac, sizeof (nacl_mac)) != 0)
649     return "Poly1305 test 3 failed.";
650
651   _gcry_poly1305_init (&total_ctx, total_key, POLY1305_KEYLEN);
652   for (i = 0; i < 256; i++)
653     {
654       /* set key and message to 'i,i,i..' */
655       for (j = 0; j < sizeof (all_key); j++)
656         all_key[j] = i;
657       for (j = 0; j < i; j++)
658         all_msg[j] = i;
659       poly1305_auth (mac, all_msg, i, all_key);
660       _gcry_poly1305_update (&total_ctx, mac, 16);
661     }
662   _gcry_poly1305_finish (&total_ctx, mac);
663   if (memcmp (total_mac, mac, sizeof (total_mac)) != 0)
664     return "Poly1305 test 4 failed.";
665
666   return NULL;
667 }