pkgconfig: Fix libgcrypt.pc.
[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, (u64)0, x0_hi, x0_lo); \
134   } while (0)
135
136 static 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       if (ctx->leftover < POLY1305_BLOCKSIZE)
206         {
207           memset (&ctx->buffer[ctx->leftover], 0,
208                   POLY1305_BLOCKSIZE - ctx->leftover);
209           ctx->leftover = POLY1305_BLOCKSIZE;
210         }
211       burn = poly1305_blocks (ctx, ctx->buffer, POLY1305_BLOCKSIZE, 0);
212     }
213
214   h0 = st->h[0] + ((u64)st->h[1] << 32);
215   h1 = st->h[2] + ((u64)st->h[3] << 32);
216   h2 = st->h[4];
217
218   k0 = st->k[0] + ((u64)st->k[1] << 32);
219   k1 = st->k[2] + ((u64)st->k[3] << 32);
220
221   /* check if h is more than 2^130-5, by adding 5. */
222   add_ssaaaa(carry, u, 0, h0, 0, 5);
223   add_ssaaaa(carry, u, 0, carry, 0, h1);
224   u = (carry + h2) >> 2; /* u == 0 or 1 */
225
226   /* minus 2^130-5 ... (+5) */
227   u = (-u) & 5;
228   add_ssaaaa(h1, h0, h1, h0, 0, u);
229
230   /* add high part of key + h */
231   add_ssaaaa(h1, h0, h1, h0, k1, k0);
232   buf_put_le64(mac + 0, h0);
233   buf_put_le64(mac + 8, h1);
234
235   /* burn_stack */
236   return 4 * sizeof (void *) + 7 * sizeof (u64) + burn;
237 }
238
239 #endif /* USE_MPI_64BIT */
240
241 #ifdef USE_MPI_32BIT
242
243 #ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
244
245 /* HI:LO += A * B (arm) */
246 #define UMUL_ADD_32(HI, LO, A, B) \
247       __asm__ ("umlal %1, %0, %4, %5" \
248                : "=r" (HI), "=r" (LO) \
249                : "0" (HI), "1" (LO), "r" (A), "r" (B) )
250
251 /* A += B (arm) */
252 #define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) \
253       __asm__ ("adds %0, %0, %5\n" \
254                "adcs %1, %1, %6\n" \
255                "adcs %2, %2, %7\n" \
256                "adcs %3, %3, %8\n" \
257                "adc %4, %4, %9\n" \
258                : "+r" (A0), "+r" (A1), "+r" (A2), "+r" (A3), "+r" (A4) \
259                : "r" (B0), "r" (B1), "r" (B2), "r" (B3), "r" (B4) \
260                : "cc" )
261
262 #endif /* HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS */
263
264 #if defined (__i386__) && __GNUC__ >= 4
265
266 /* A += B (i386) */
267 #define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) \
268       __asm__ ("addl %5, %0\n" \
269                "adcl %6, %1\n" \
270                "adcl %7, %2\n" \
271                "adcl %8, %3\n" \
272                "adcl %9, %4\n" \
273                : "+r" (A0), "+r" (A1), "+r" (A2), "+r" (A3), "+r" (A4) \
274                : "g" (B0), "g" (B1), "g" (B2), "g" (B3), "g" (B4) \
275                : "cc" )
276
277 #endif /* __i386__ */
278
279 #ifndef UMUL_ADD_32
280 /* HI:LO += A * B (generic, mpi) */
281 #  define UMUL_ADD_32(HI, LO, A, B) do { \
282     u32 t_lo, t_hi; \
283     umul_ppmm(t_hi, t_lo, A, B); \
284     add_ssaaaa(HI, LO, HI, LO, t_hi, t_lo); \
285   } while (0)
286 #endif
287
288 #ifndef ADD_1305_32
289 /* A += B (generic, mpi) */
290 #  define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) do { \
291     u32 carry0, carry1, carry2; \
292     add_ssaaaa(carry0, A0, 0, A0, 0, B0); \
293     add_ssaaaa(carry1, A1, 0, A1, 0, B1); \
294     add_ssaaaa(carry1, A1, carry1, A1, 0, carry0); \
295     add_ssaaaa(carry2, A2, 0, A2, 0, B2); \
296     add_ssaaaa(carry2, A2, carry2, A2, 0, carry1); \
297     add_ssaaaa(A4, A3, A4, A3, B4, B3); \
298     add_ssaaaa(A4, A3, A4, A3, 0, carry2); \
299   } while (0)
300 #endif
301
302 /* H = H * R mod 2¹³⁰-5 */
303 #define MUL_MOD_1305_32(H4, H3, H2, H1, H0, R3, R2, R1, R0, \
304                         R3_MULT5, R2_MULT5, R1_MULT5) do { \
305     u32 x0_lo, x0_hi, x1_lo, x1_hi, x2_lo, x2_hi, x3_lo, x3_hi; \
306     u32 t0_lo, t0_hi; \
307     \
308     /* x = a * r (partial mod 2^130-5) */ \
309     umul_ppmm(x0_hi, x0_lo, H0, R0);  /* h0 * r0 */ \
310     umul_ppmm(x1_hi, x1_lo, H0, R1);  /* h0 * r1 */ \
311     umul_ppmm(x2_hi, x2_lo, H0, R2);  /* h0 * r2 */ \
312     umul_ppmm(x3_hi, x3_lo, H0, R3);  /* h0 * r3 */ \
313     \
314     UMUL_ADD_32(x0_hi, x0_lo, H1, R3_MULT5); /* h1 * r3 mod 2^130-5 */ \
315     UMUL_ADD_32(x1_hi, x1_lo, H1, R0);       /* h1 * r0 */ \
316     UMUL_ADD_32(x2_hi, x2_lo, H1, R1);       /* h1 * r1 */ \
317     UMUL_ADD_32(x3_hi, x3_lo, H1, R2);       /* h1 * r2 */ \
318     \
319     UMUL_ADD_32(x0_hi, x0_lo, H2, R2_MULT5); /* h2 * r2 mod 2^130-5 */ \
320     UMUL_ADD_32(x1_hi, x1_lo, H2, R3_MULT5); /* h2 * r3 mod 2^130-5 */ \
321     UMUL_ADD_32(x2_hi, x2_lo, H2, R0);       /* h2 * r0 */ \
322     UMUL_ADD_32(x3_hi, x3_lo, H2, R1);       /* h2 * r1 */ \
323     \
324     UMUL_ADD_32(x0_hi, x0_lo, H3, R1_MULT5); /* h3 * r1 mod 2^130-5 */ \
325     H1 = x0_hi; \
326     UMUL_ADD_32(x1_hi, x1_lo, H3, R2_MULT5); /* h3 * r2 mod 2^130-5 */ \
327     UMUL_ADD_32(x2_hi, x2_lo, H3, R3_MULT5); /* h3 * r3 mod 2^130-5 */ \
328     UMUL_ADD_32(x3_hi, x3_lo, H3, R0);       /* h3 * r0 */ \
329     \
330     t0_lo = H4 * R1_MULT5; /* h4 * r1 mod 2^130-5 */ \
331     t0_hi = H4 * R2_MULT5; /* h4 * r2 mod 2^130-5 */ \
332     add_ssaaaa(H2, x1_lo, x1_hi, x1_lo, 0, t0_lo); \
333     add_ssaaaa(H3, x2_lo, x2_hi, x2_lo, 0, t0_hi); \
334     t0_lo = H4 * R3_MULT5; /* h4 * r3 mod 2^130-5 */ \
335     t0_hi = H4 * R0;       /* h4 * r0 */ \
336     add_ssaaaa(H4, x3_lo, x3_hi, x3_lo, t0_hi, t0_lo); \
337     \
338     /* carry propagation */ \
339     H0 = (H4 >> 2) * 5; /* msb mod 2^130-5 */ \
340     H4 = H4 & 3; \
341     ADD_1305_32(H4, H3, H2, H1, H0, 0, x3_lo, x2_lo, x1_lo, x0_lo); \
342   } while (0)
343
344 static unsigned int
345 poly1305_blocks (poly1305_context_t *ctx, const byte *buf, size_t len,
346                  byte high_pad)
347 {
348   POLY1305_STATE *st = &ctx->state;
349   u32 r1_mult5, r2_mult5, r3_mult5;
350   u32 h0, h1, h2, h3, h4;
351   u32 m0, m1, m2, m3, m4;
352
353   m4 = high_pad;
354
355   h0 = st->h[0];
356   h1 = st->h[1];
357   h2 = st->h[2];
358   h3 = st->h[3];
359   h4 = st->h[4];
360
361   r1_mult5 = (st->r[1] >> 2) + st->r[1];
362   r2_mult5 = (st->r[2] >> 2) + st->r[2];
363   r3_mult5 = (st->r[3] >> 2) + st->r[3];
364
365   while (len >= POLY1305_BLOCKSIZE)
366     {
367       m0 = buf_get_le32(buf + 0);
368       m1 = buf_get_le32(buf + 4);
369       m2 = buf_get_le32(buf + 8);
370       m3 = buf_get_le32(buf + 12);
371
372       /* a = h + m */
373       ADD_1305_32(h4, h3, h2, h1, h0, m4, m3, m2, m1, m0);
374
375       /* h = a * r (partial mod 2^130-5) */
376       MUL_MOD_1305_32(h4, h3, h2, h1, h0,
377                       st->r[3], st->r[2], st->r[1], st->r[0],
378                       r3_mult5, r2_mult5, r1_mult5);
379
380       buf += POLY1305_BLOCKSIZE;
381       len -= POLY1305_BLOCKSIZE;
382     }
383
384   st->h[0] = h0;
385   st->h[1] = h1;
386   st->h[2] = h2;
387   st->h[3] = h3;
388   st->h[4] = h4;
389
390   return 6 * sizeof (void *) + 28 * sizeof (u32);
391 }
392
393 static unsigned int poly1305_final (poly1305_context_t *ctx,
394                                     byte mac[POLY1305_TAGLEN])
395 {
396   POLY1305_STATE *st = &ctx->state;
397   unsigned int burn = 0;
398   u32 carry, tmp0, tmp1, tmp2, u;
399   u32 h4, h3, h2, h1, h0;
400
401   /* process the remaining block */
402   if (ctx->leftover)
403     {
404       ctx->buffer[ctx->leftover++] = 1;
405       if (ctx->leftover < POLY1305_BLOCKSIZE)
406         {
407           memset (&ctx->buffer[ctx->leftover], 0,
408                   POLY1305_BLOCKSIZE - ctx->leftover);
409           ctx->leftover = POLY1305_BLOCKSIZE;
410         }
411       burn = poly1305_blocks (ctx, ctx->buffer, POLY1305_BLOCKSIZE, 0);
412     }
413
414   h0 = st->h[0];
415   h1 = st->h[1];
416   h2 = st->h[2];
417   h3 = st->h[3];
418   h4 = st->h[4];
419
420   /* check if h is more than 2^130-5, by adding 5. */
421   add_ssaaaa(carry, tmp0, 0, h0, 0, 5);
422   add_ssaaaa(carry, tmp0, 0, carry, 0, h1);
423   add_ssaaaa(carry, tmp0, 0, carry, 0, h2);
424   add_ssaaaa(carry, tmp0, 0, carry, 0, h3);
425   u = (carry + h4) >> 2; /* u == 0 or 1 */
426
427   /* minus 2^130-5 ... (+5) */
428   u = (-u) & 5;
429   add_ssaaaa(carry, h0, 0, h0, 0, u);
430   add_ssaaaa(carry, h1, 0, h1, 0, carry);
431   add_ssaaaa(carry, h2, 0, h2, 0, carry);
432   add_ssaaaa(carry, h3, 0, h3, 0, carry);
433
434   /* add high part of key + h */
435   add_ssaaaa(tmp0, h0, 0, h0, 0, st->k[0]);
436   add_ssaaaa(tmp1, h1, 0, h1, 0, st->k[1]);
437   add_ssaaaa(tmp1, h1, tmp1, h1, 0, tmp0);
438   add_ssaaaa(tmp2, h2, 0, h2, 0, st->k[2]);
439   add_ssaaaa(tmp2, h2, tmp2, h2, 0, tmp1);
440   add_ssaaaa(carry, h3, 0, h3, 0, st->k[3]);
441   h3 += tmp2;
442
443   buf_put_le32(mac + 0, h0);
444   buf_put_le32(mac + 4, h1);
445   buf_put_le32(mac + 8, h2);
446   buf_put_le32(mac + 12, h3);
447
448   /* burn_stack */
449   return 4 * sizeof (void *) + 10 * sizeof (u32) + burn;
450 }
451
452 #endif /* USE_MPI_32BIT */
453
454
455 unsigned int
456 _gcry_poly1305_update_burn (poly1305_context_t *ctx, const byte *m,
457                             size_t bytes)
458 {
459   unsigned int burn = 0;
460
461   /* handle leftover */
462   if (ctx->leftover)
463     {
464       size_t want = (POLY1305_BLOCKSIZE - ctx->leftover);
465       if (want > bytes)
466         want = bytes;
467       buf_cpy (ctx->buffer + ctx->leftover, m, want);
468       bytes -= want;
469       m += want;
470       ctx->leftover += want;
471       if (ctx->leftover < POLY1305_BLOCKSIZE)
472         return 0;
473       burn = poly1305_blocks (ctx, ctx->buffer, POLY1305_BLOCKSIZE, 1);
474       ctx->leftover = 0;
475     }
476
477   /* process full blocks */
478   if (bytes >= POLY1305_BLOCKSIZE)
479     {
480       size_t nblks = bytes / POLY1305_BLOCKSIZE;
481       burn = poly1305_blocks (ctx, m, nblks * POLY1305_BLOCKSIZE, 1);
482       m += nblks * POLY1305_BLOCKSIZE;
483       bytes -= nblks * POLY1305_BLOCKSIZE;
484     }
485
486   /* store leftover */
487   if (bytes)
488     {
489       buf_cpy (ctx->buffer + ctx->leftover, m, bytes);
490       ctx->leftover += bytes;
491     }
492
493   return burn;
494 }
495
496
497 void
498 _gcry_poly1305_update (poly1305_context_t *ctx, const byte *m, size_t bytes)
499 {
500   unsigned int burn;
501
502   burn = _gcry_poly1305_update_burn (ctx, m, bytes);
503
504   if (burn)
505     _gcry_burn_stack (burn);
506 }
507
508
509 void
510 _gcry_poly1305_finish (poly1305_context_t *ctx, byte mac[POLY1305_TAGLEN])
511 {
512   unsigned int burn;
513
514   burn = poly1305_final (ctx, mac);
515
516   _gcry_burn_stack (burn);
517 }
518
519
520 gcry_err_code_t
521 _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key,
522                      size_t keylen)
523 {
524   static int initialized;
525   static const char *selftest_failed;
526
527   if (!initialized)
528     {
529       initialized = 1;
530       selftest_failed = selftest ();
531       if (selftest_failed)
532         log_error ("Poly1305 selftest failed (%s)\n", selftest_failed);
533     }
534
535   if (keylen != POLY1305_KEYLEN)
536     return GPG_ERR_INV_KEYLEN;
537
538   if (selftest_failed)
539     return GPG_ERR_SELFTEST_FAILED;
540
541   poly1305_init (ctx, key);
542
543   return 0;
544 }
545
546
547 static void
548 poly1305_auth (byte mac[POLY1305_TAGLEN], const byte * m, size_t bytes,
549                const byte * key)
550 {
551   poly1305_context_t ctx;
552
553   memset (&ctx, 0, sizeof (ctx));
554
555   _gcry_poly1305_init (&ctx, key, POLY1305_KEYLEN);
556   _gcry_poly1305_update (&ctx, m, bytes);
557   _gcry_poly1305_finish (&ctx, mac);
558
559   wipememory (&ctx, sizeof (ctx));
560 }
561
562
563 static const char *
564 selftest (void)
565 {
566   /* example from nacl */
567   static const byte nacl_key[POLY1305_KEYLEN] = {
568     0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91,
569     0x6d, 0x11, 0xc2, 0xcb, 0x21, 0x4d, 0x3c, 0x25,
570     0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65,
571     0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80,
572   };
573
574   static const byte nacl_msg[131] = {
575     0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73,
576     0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce,
577     0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4,
578     0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a,
579     0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b,
580     0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72,
581     0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2,
582     0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38,
583     0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a,
584     0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae,
585     0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea,
586     0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda,
587     0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde,
588     0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3,
589     0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6,
590     0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74,
591     0xe3, 0x55, 0xa5
592   };
593
594   static const byte nacl_mac[16] = {
595     0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5,
596     0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9
597   };
598
599   /* generates a final value of (2^130 - 2) == 3 */
600   static const byte wrap_key[POLY1305_KEYLEN] = {
601     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605   };
606
607   static const byte wrap_msg[16] = {
608     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
609     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
610   };
611
612   static const byte wrap_mac[16] = {
613     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615   };
616
617   /* mac of the macs of messages of length 0 to 256, where the key and messages
618    * have all their values set to the length
619    */
620   static const byte total_key[POLY1305_KEYLEN] = {
621     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
622     0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9,
623     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
624     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
625   };
626
627   static const byte total_mac[16] = {
628     0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
629     0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39
630   };
631
632   poly1305_context_t ctx;
633   poly1305_context_t total_ctx;
634   byte all_key[POLY1305_KEYLEN];
635   byte all_msg[256];
636   byte mac[16];
637   size_t i, j;
638
639   memset (&ctx, 0, sizeof (ctx));
640   memset (&total_ctx, 0, sizeof (total_ctx));
641
642   memset (mac, 0, sizeof (mac));
643   poly1305_auth (mac, nacl_msg, sizeof (nacl_msg), nacl_key);
644   if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0)
645     return "Poly1305 test 1 failed.";
646
647   /* SSE2/AVX have a 32 byte block size, but also support 64 byte blocks, so
648    * make sure everything still works varying between them */
649   memset (mac, 0, sizeof (mac));
650   _gcry_poly1305_init (&ctx, nacl_key, POLY1305_KEYLEN);
651   _gcry_poly1305_update (&ctx, nacl_msg + 0, 32);
652   _gcry_poly1305_update (&ctx, nacl_msg + 32, 64);
653   _gcry_poly1305_update (&ctx, nacl_msg + 96, 16);
654   _gcry_poly1305_update (&ctx, nacl_msg + 112, 8);
655   _gcry_poly1305_update (&ctx, nacl_msg + 120, 4);
656   _gcry_poly1305_update (&ctx, nacl_msg + 124, 2);
657   _gcry_poly1305_update (&ctx, nacl_msg + 126, 1);
658   _gcry_poly1305_update (&ctx, nacl_msg + 127, 1);
659   _gcry_poly1305_update (&ctx, nacl_msg + 128, 1);
660   _gcry_poly1305_update (&ctx, nacl_msg + 129, 1);
661   _gcry_poly1305_update (&ctx, nacl_msg + 130, 1);
662   _gcry_poly1305_finish (&ctx, mac);
663   if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0)
664     return "Poly1305 test 2 failed.";
665
666   memset (mac, 0, sizeof (mac));
667   poly1305_auth (mac, wrap_msg, sizeof (wrap_msg), wrap_key);
668   if (memcmp (wrap_mac, mac, sizeof (nacl_mac)) != 0)
669     return "Poly1305 test 3 failed.";
670
671   _gcry_poly1305_init (&total_ctx, total_key, POLY1305_KEYLEN);
672   for (i = 0; i < 256; i++)
673     {
674       /* set key and message to 'i,i,i..' */
675       for (j = 0; j < sizeof (all_key); j++)
676         all_key[j] = i;
677       for (j = 0; j < i; j++)
678         all_msg[j] = i;
679       poly1305_auth (mac, all_msg, i, all_key);
680       _gcry_poly1305_update (&total_ctx, mac, 16);
681     }
682   _gcry_poly1305_finish (&total_ctx, mac);
683   if (memcmp (total_mac, mac, sizeof (total_mac)) != 0)
684     return "Poly1305 test 4 failed.";
685
686   return NULL;
687 }