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