Line data Source code
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 :
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 : /* Reference unoptimized poly1305 implementation using 32 bit * 32 bit = 64 bit
102 : * multiplication and 64 bit addition.
103 : */
104 :
105 : typedef struct poly1305_state_ref32_s
106 : {
107 : u32 r[5];
108 : u32 h[5];
109 : u32 pad[4];
110 : byte final;
111 : } poly1305_state_ref32_t;
112 :
113 :
114 : static OPS_FUNC_ABI void
115 0 : poly1305_init_ext_ref32 (void *state, const poly1305_key_t * key)
116 : {
117 0 : poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state;
118 :
119 : gcry_assert (sizeof (*st) + POLY1305_STATE_ALIGNMENT <=
120 : sizeof (((poly1305_context_t *) 0)->state));
121 :
122 : /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
123 0 : st->r[0] = (buf_get_le32 (&key->b[0])) & 0x3ffffff;
124 0 : st->r[1] = (buf_get_le32 (&key->b[3]) >> 2) & 0x3ffff03;
125 0 : st->r[2] = (buf_get_le32 (&key->b[6]) >> 4) & 0x3ffc0ff;
126 0 : st->r[3] = (buf_get_le32 (&key->b[9]) >> 6) & 0x3f03fff;
127 0 : st->r[4] = (buf_get_le32 (&key->b[12]) >> 8) & 0x00fffff;
128 :
129 : /* h = 0 */
130 0 : st->h[0] = 0;
131 0 : st->h[1] = 0;
132 0 : st->h[2] = 0;
133 0 : st->h[3] = 0;
134 0 : st->h[4] = 0;
135 :
136 : /* save pad for later */
137 0 : st->pad[0] = buf_get_le32 (&key->b[16]);
138 0 : st->pad[1] = buf_get_le32 (&key->b[20]);
139 0 : st->pad[2] = buf_get_le32 (&key->b[24]);
140 0 : st->pad[3] = buf_get_le32 (&key->b[28]);
141 :
142 0 : st->final = 0;
143 0 : }
144 :
145 :
146 : static OPS_FUNC_ABI unsigned int
147 0 : poly1305_blocks_ref32 (void *state, const byte * m, size_t bytes)
148 : {
149 0 : poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state;
150 0 : const u32 hibit = (st->final) ? 0 : (1 << 24); /* 1 << 128 */
151 : u32 r0, r1, r2, r3, r4;
152 : u32 s1, s2, s3, s4;
153 : u32 h0, h1, h2, h3, h4;
154 : u64 d0, d1, d2, d3, d4;
155 : u32 c;
156 :
157 0 : r0 = st->r[0];
158 0 : r1 = st->r[1];
159 0 : r2 = st->r[2];
160 0 : r3 = st->r[3];
161 0 : r4 = st->r[4];
162 :
163 0 : s1 = r1 * 5;
164 0 : s2 = r2 * 5;
165 0 : s3 = r3 * 5;
166 0 : s4 = r4 * 5;
167 :
168 0 : h0 = st->h[0];
169 0 : h1 = st->h[1];
170 0 : h2 = st->h[2];
171 0 : h3 = st->h[3];
172 0 : h4 = st->h[4];
173 :
174 0 : while (bytes >= POLY1305_REF_BLOCKSIZE)
175 : {
176 : /* h += m[i] */
177 0 : h0 += (buf_get_le32 (m + 0)) & 0x3ffffff;
178 0 : h1 += (buf_get_le32 (m + 3) >> 2) & 0x3ffffff;
179 0 : h2 += (buf_get_le32 (m + 6) >> 4) & 0x3ffffff;
180 0 : h3 += (buf_get_le32 (m + 9) >> 6) & 0x3ffffff;
181 0 : h4 += (buf_get_le32 (m + 12) >> 8) | hibit;
182 :
183 : /* h *= r */
184 0 : d0 =
185 0 : ((u64) h0 * r0) + ((u64) h1 * s4) +
186 0 : ((u64) h2 * s3) + ((u64) h3 * s2) + ((u64) h4 * s1);
187 0 : d1 =
188 0 : ((u64) h0 * r1) + ((u64) h1 * r0) +
189 0 : ((u64) h2 * s4) + ((u64) h3 * s3) + ((u64) h4 * s2);
190 0 : d2 =
191 0 : ((u64) h0 * r2) + ((u64) h1 * r1) +
192 0 : ((u64) h2 * r0) + ((u64) h3 * s4) + ((u64) h4 * s3);
193 0 : d3 =
194 0 : ((u64) h0 * r3) + ((u64) h1 * r2) +
195 0 : ((u64) h2 * r1) + ((u64) h3 * r0) + ((u64) h4 * s4);
196 0 : d4 =
197 0 : ((u64) h0 * r4) + ((u64) h1 * r3) +
198 0 : ((u64) h2 * r2) + ((u64) h3 * r1) + ((u64) h4 * r0);
199 :
200 : /* (partial) h %= p */
201 0 : c = (u32) (d0 >> 26);
202 0 : h0 = (u32) d0 & 0x3ffffff;
203 0 : d1 += c;
204 0 : c = (u32) (d1 >> 26);
205 0 : h1 = (u32) d1 & 0x3ffffff;
206 0 : d2 += c;
207 0 : c = (u32) (d2 >> 26);
208 0 : h2 = (u32) d2 & 0x3ffffff;
209 0 : d3 += c;
210 0 : c = (u32) (d3 >> 26);
211 0 : h3 = (u32) d3 & 0x3ffffff;
212 0 : d4 += c;
213 0 : c = (u32) (d4 >> 26);
214 0 : h4 = (u32) d4 & 0x3ffffff;
215 0 : h0 += c * 5;
216 0 : c = (h0 >> 26);
217 0 : h0 = h0 & 0x3ffffff;
218 0 : h1 += c;
219 :
220 0 : m += POLY1305_REF_BLOCKSIZE;
221 0 : bytes -= POLY1305_REF_BLOCKSIZE;
222 : }
223 :
224 0 : st->h[0] = h0;
225 0 : st->h[1] = h1;
226 0 : st->h[2] = h2;
227 0 : st->h[3] = h3;
228 0 : st->h[4] = h4;
229 :
230 0 : return (16 * sizeof (u32) + 5 * sizeof (u64) + 5 * sizeof (void *));
231 : }
232 :
233 :
234 : static OPS_FUNC_ABI unsigned int
235 0 : poly1305_finish_ext_ref32 (void *state, const byte * m,
236 : size_t remaining, byte mac[POLY1305_TAGLEN])
237 : {
238 0 : poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state;
239 : u32 h0, h1, h2, h3, h4, c;
240 : u32 g0, g1, g2, g3, g4;
241 : u64 f;
242 : u32 mask;
243 0 : unsigned int burn = 0;
244 :
245 : /* process the remaining block */
246 0 : if (remaining)
247 : {
248 0 : byte final[POLY1305_REF_BLOCKSIZE] = { 0 };
249 : size_t i;
250 0 : for (i = 0; i < remaining; i++)
251 0 : final[i] = m[i];
252 0 : final[remaining] = 1;
253 0 : st->final = 1;
254 0 : burn = poly1305_blocks_ref32 (st, final, POLY1305_REF_BLOCKSIZE);
255 : }
256 :
257 : /* fully carry h */
258 0 : h0 = st->h[0];
259 0 : h1 = st->h[1];
260 0 : h2 = st->h[2];
261 0 : h3 = st->h[3];
262 0 : h4 = st->h[4];
263 :
264 0 : c = h1 >> 26;
265 0 : h1 = h1 & 0x3ffffff;
266 0 : h2 += c;
267 0 : c = h2 >> 26;
268 0 : h2 = h2 & 0x3ffffff;
269 0 : h3 += c;
270 0 : c = h3 >> 26;
271 0 : h3 = h3 & 0x3ffffff;
272 0 : h4 += c;
273 0 : c = h4 >> 26;
274 0 : h4 = h4 & 0x3ffffff;
275 0 : h0 += c * 5;
276 0 : c = h0 >> 26;
277 0 : h0 = h0 & 0x3ffffff;
278 0 : h1 += c;
279 :
280 : /* compute h + -p */
281 0 : g0 = h0 + 5;
282 0 : c = g0 >> 26;
283 0 : g0 &= 0x3ffffff;
284 0 : g1 = h1 + c;
285 0 : c = g1 >> 26;
286 0 : g1 &= 0x3ffffff;
287 0 : g2 = h2 + c;
288 0 : c = g2 >> 26;
289 0 : g2 &= 0x3ffffff;
290 0 : g3 = h3 + c;
291 0 : c = g3 >> 26;
292 0 : g3 &= 0x3ffffff;
293 0 : g4 = h4 + c - (1 << 26);
294 :
295 : /* select h if h < p, or h + -p if h >= p */
296 0 : mask = (g4 >> ((sizeof (u32) * 8) - 1)) - 1;
297 0 : g0 &= mask;
298 0 : g1 &= mask;
299 0 : g2 &= mask;
300 0 : g3 &= mask;
301 0 : g4 &= mask;
302 0 : mask = ~mask;
303 0 : h0 = (h0 & mask) | g0;
304 0 : h1 = (h1 & mask) | g1;
305 0 : h2 = (h2 & mask) | g2;
306 0 : h3 = (h3 & mask) | g3;
307 0 : h4 = (h4 & mask) | g4;
308 :
309 : /* h = h % (2^128) */
310 0 : h0 = ((h0) | (h1 << 26)) & 0xffffffff;
311 0 : h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
312 0 : h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
313 0 : h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
314 :
315 : /* mac = (h + pad) % (2^128) */
316 0 : f = (u64) h0 + st->pad[0];
317 0 : h0 = (u32) f;
318 0 : f = (u64) h1 + st->pad[1] + (f >> 32);
319 0 : h1 = (u32) f;
320 0 : f = (u64) h2 + st->pad[2] + (f >> 32);
321 0 : h2 = (u32) f;
322 0 : f = (u64) h3 + st->pad[3] + (f >> 32);
323 0 : h3 = (u32) f;
324 :
325 0 : buf_put_le32 (mac + 0, h0);
326 0 : buf_put_le32 (mac + 4, h1);
327 0 : buf_put_le32 (mac + 8, h2);
328 0 : buf_put_le32 (mac + 12, h3);
329 :
330 : /* zero out the state */
331 0 : st->h[0] = 0;
332 0 : st->h[1] = 0;
333 0 : st->h[2] = 0;
334 0 : st->h[3] = 0;
335 0 : st->h[4] = 0;
336 0 : st->r[0] = 0;
337 0 : st->r[1] = 0;
338 0 : st->r[2] = 0;
339 0 : st->r[3] = 0;
340 0 : st->r[4] = 0;
341 0 : st->pad[0] = 0;
342 0 : st->pad[1] = 0;
343 0 : st->pad[2] = 0;
344 0 : st->pad[3] = 0;
345 :
346 : /* burn_stack */
347 : return (13 * sizeof (u32) + sizeof (u64) +
348 0 : POLY1305_REF_BLOCKSIZE + 6 * sizeof (void *)) + burn;
349 : }
350 :
351 :
352 : static const poly1305_ops_t poly1305_default_ops = {
353 : POLY1305_REF_BLOCKSIZE,
354 : poly1305_init_ext_ref32,
355 : poly1305_blocks_ref32,
356 : poly1305_finish_ext_ref32
357 : };
358 :
359 :
360 :
361 :
362 : static inline void *
363 720970 : poly1305_get_state (poly1305_context_t * ctx)
364 : {
365 720970 : byte *c = ctx->state;
366 720970 : c += POLY1305_STATE_ALIGNMENT - 1;
367 720970 : c -= (uintptr_t) c & (POLY1305_STATE_ALIGNMENT - 1);
368 720970 : return c;
369 : }
370 :
371 :
372 : static void
373 9336 : poly1305_init (poly1305_context_t * ctx, const poly1305_key_t * key)
374 : {
375 9336 : void *state = poly1305_get_state (ctx);
376 :
377 9336 : ctx->leftover = 0;
378 :
379 9336 : ctx->ops->init_ext (state, key);
380 9336 : }
381 :
382 :
383 : void
384 702560 : _gcry_poly1305_update (poly1305_context_t * ctx, const byte * m, size_t bytes)
385 : {
386 702560 : void *state = poly1305_get_state (ctx);
387 702560 : unsigned int burn = 0;
388 702560 : size_t block_size = ctx->ops->block_size;
389 :
390 : /* handle leftover */
391 702560 : if (ctx->leftover)
392 : {
393 644914 : size_t want = (block_size - ctx->leftover);
394 644914 : if (want > bytes)
395 387478 : want = bytes;
396 644914 : buf_cpy (ctx->buffer + ctx->leftover, m, want);
397 644914 : bytes -= want;
398 644914 : m += want;
399 644914 : ctx->leftover += want;
400 644914 : if (ctx->leftover < block_size)
401 387478 : return;
402 257436 : burn = ctx->ops->blocks (state, ctx->buffer, block_size);
403 257436 : ctx->leftover = 0;
404 : }
405 :
406 : /* process full blocks */
407 315082 : if (bytes >= block_size)
408 : {
409 82952 : size_t want = (bytes & ~(block_size - 1));
410 82952 : burn = ctx->ops->blocks (state, m, want);
411 82952 : m += want;
412 82952 : bytes -= want;
413 : }
414 :
415 : /* store leftover */
416 315082 : if (bytes)
417 : {
418 264424 : buf_cpy (ctx->buffer + ctx->leftover, m, bytes);
419 264424 : ctx->leftover += bytes;
420 : }
421 :
422 315082 : if (burn)
423 213634 : _gcry_burn_stack (burn);
424 : }
425 :
426 :
427 : void
428 9074 : _gcry_poly1305_finish (poly1305_context_t * ctx, byte mac[POLY1305_TAGLEN])
429 : {
430 9074 : void *state = poly1305_get_state (ctx);
431 : unsigned int burn;
432 :
433 9074 : burn = ctx->ops->finish_ext (state, ctx->buffer, ctx->leftover, mac);
434 :
435 9074 : _gcry_burn_stack (burn);
436 9074 : }
437 :
438 :
439 : gcry_err_code_t
440 9336 : _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key,
441 : size_t keylen)
442 : {
443 : static int initialized;
444 : static const char *selftest_failed;
445 : poly1305_key_t keytmp;
446 9336 : unsigned int features = _gcry_get_hw_features ();
447 :
448 9336 : if (!initialized)
449 : {
450 4 : initialized = 1;
451 4 : selftest_failed = selftest ();
452 4 : if (selftest_failed)
453 0 : log_error ("Poly1305 selftest failed (%s)\n", selftest_failed);
454 : }
455 :
456 9336 : if (keylen != POLY1305_KEYLEN)
457 0 : return GPG_ERR_INV_KEYLEN;
458 :
459 9336 : if (selftest_failed)
460 0 : return GPG_ERR_SELFTEST_FAILED;
461 :
462 : #ifdef POLY1305_USE_SSE2
463 9336 : ctx->ops = &poly1305_amd64_sse2_ops;
464 : #else
465 : ctx->ops = &poly1305_default_ops;
466 : #endif
467 :
468 : #ifdef POLY1305_USE_AVX2
469 9336 : if (features & HWF_INTEL_AVX2)
470 0 : ctx->ops = &poly1305_amd64_avx2_ops;
471 : #endif
472 : #ifdef POLY1305_USE_NEON
473 : if (features & HWF_ARM_NEON)
474 : ctx->ops = &poly1305_armv7_neon_ops;
475 : #endif
476 : (void)features;
477 :
478 9336 : buf_cpy (keytmp.b, key, POLY1305_KEYLEN);
479 9336 : poly1305_init (ctx, &keytmp);
480 :
481 9336 : wipememory (&keytmp, sizeof (keytmp));
482 :
483 9336 : return 0;
484 : }
485 :
486 :
487 : static void
488 1032 : poly1305_auth (byte mac[POLY1305_TAGLEN], const byte * m, size_t bytes,
489 : const byte * key)
490 : {
491 : poly1305_context_t ctx;
492 :
493 1032 : memset (&ctx, 0, sizeof (ctx));
494 :
495 1032 : _gcry_poly1305_init (&ctx, key, POLY1305_KEYLEN);
496 1032 : _gcry_poly1305_update (&ctx, m, bytes);
497 1032 : _gcry_poly1305_finish (&ctx, mac);
498 :
499 1032 : wipememory (&ctx, sizeof (ctx));
500 1032 : }
501 :
502 :
503 : static const char *
504 4 : selftest (void)
505 : {
506 : /* example from nacl */
507 : static const byte nacl_key[POLY1305_KEYLEN] = {
508 : 0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91,
509 : 0x6d, 0x11, 0xc2, 0xcb, 0x21, 0x4d, 0x3c, 0x25,
510 : 0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65,
511 : 0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80,
512 : };
513 :
514 : static const byte nacl_msg[131] = {
515 : 0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73,
516 : 0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce,
517 : 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4,
518 : 0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a,
519 : 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b,
520 : 0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72,
521 : 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2,
522 : 0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38,
523 : 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a,
524 : 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae,
525 : 0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea,
526 : 0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda,
527 : 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde,
528 : 0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3,
529 : 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6,
530 : 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74,
531 : 0xe3, 0x55, 0xa5
532 : };
533 :
534 : static const byte nacl_mac[16] = {
535 : 0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5,
536 : 0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9
537 : };
538 :
539 : /* generates a final value of (2^130 - 2) == 3 */
540 : static const byte wrap_key[POLY1305_KEYLEN] = {
541 : 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 : };
546 :
547 : static const byte wrap_msg[16] = {
548 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
549 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
550 : };
551 :
552 : static const byte wrap_mac[16] = {
553 : 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 : };
556 :
557 : /* mac of the macs of messages of length 0 to 256, where the key and messages
558 : * have all their values set to the length
559 : */
560 : static const byte total_key[POLY1305_KEYLEN] = {
561 : 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
562 : 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9,
563 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
564 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
565 : };
566 :
567 : static const byte total_mac[16] = {
568 : 0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
569 : 0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39
570 : };
571 :
572 : poly1305_context_t ctx;
573 : poly1305_context_t total_ctx;
574 : byte all_key[POLY1305_KEYLEN];
575 : byte all_msg[256];
576 : byte mac[16];
577 : size_t i, j;
578 :
579 4 : memset (&ctx, 0, sizeof (ctx));
580 4 : memset (&total_ctx, 0, sizeof (total_ctx));
581 :
582 4 : memset (mac, 0, sizeof (mac));
583 4 : poly1305_auth (mac, nacl_msg, sizeof (nacl_msg), nacl_key);
584 4 : if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0)
585 0 : return "Poly1305 test 1 failed.";
586 :
587 : /* SSE2/AVX have a 32 byte block size, but also support 64 byte blocks, so
588 : * make sure everything still works varying between them */
589 4 : memset (mac, 0, sizeof (mac));
590 4 : _gcry_poly1305_init (&ctx, nacl_key, POLY1305_KEYLEN);
591 4 : _gcry_poly1305_update (&ctx, nacl_msg + 0, 32);
592 4 : _gcry_poly1305_update (&ctx, nacl_msg + 32, 64);
593 4 : _gcry_poly1305_update (&ctx, nacl_msg + 96, 16);
594 4 : _gcry_poly1305_update (&ctx, nacl_msg + 112, 8);
595 4 : _gcry_poly1305_update (&ctx, nacl_msg + 120, 4);
596 4 : _gcry_poly1305_update (&ctx, nacl_msg + 124, 2);
597 4 : _gcry_poly1305_update (&ctx, nacl_msg + 126, 1);
598 4 : _gcry_poly1305_update (&ctx, nacl_msg + 127, 1);
599 4 : _gcry_poly1305_update (&ctx, nacl_msg + 128, 1);
600 4 : _gcry_poly1305_update (&ctx, nacl_msg + 129, 1);
601 4 : _gcry_poly1305_update (&ctx, nacl_msg + 130, 1);
602 4 : _gcry_poly1305_finish (&ctx, mac);
603 4 : if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0)
604 0 : return "Poly1305 test 2 failed.";
605 :
606 4 : memset (mac, 0, sizeof (mac));
607 4 : poly1305_auth (mac, wrap_msg, sizeof (wrap_msg), wrap_key);
608 4 : if (memcmp (wrap_mac, mac, sizeof (nacl_mac)) != 0)
609 0 : return "Poly1305 test 3 failed.";
610 :
611 4 : _gcry_poly1305_init (&total_ctx, total_key, POLY1305_KEYLEN);
612 1028 : for (i = 0; i < 256; i++)
613 : {
614 : /* set key and message to 'i,i,i..' */
615 33792 : for (j = 0; j < sizeof (all_key); j++)
616 32768 : all_key[j] = i;
617 131584 : for (j = 0; j < i; j++)
618 130560 : all_msg[j] = i;
619 1024 : poly1305_auth (mac, all_msg, i, all_key);
620 1024 : _gcry_poly1305_update (&total_ctx, mac, 16);
621 : }
622 4 : _gcry_poly1305_finish (&total_ctx, mac);
623 4 : if (memcmp (total_mac, mac, sizeof (total_mac)) != 0)
624 0 : return "Poly1305 test 4 failed.";
625 :
626 4 : return NULL;
627 : }
|