Branch data Line data Source code
1 : : /*
2 : : * Public Domain poly1305 from Andrew Moon
3 : : * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
4 : : */
5 : :
6 : : /* $OpenBSD: poly1305.c,v 1.3 2013/12/19 22:57:13 djm Exp $ */
7 : :
8 : : #include "includes.h"
9 : :
10 : : #include <sys/types.h>
11 : : #ifdef HAVE_STDINT_H
12 : : # include <stdint.h>
13 : : #endif
14 : :
15 : : #include "poly1305.h"
16 : :
17 : : #define mul32x32_64(a,b) ((uint64_t)(a) * (b))
18 : :
19 : : #define U8TO32_LE(p) \
20 : : (((uint32_t)((p)[0])) | \
21 : : ((uint32_t)((p)[1]) << 8) | \
22 : : ((uint32_t)((p)[2]) << 16) | \
23 : : ((uint32_t)((p)[3]) << 24))
24 : :
25 : : #define U32TO8_LE(p, v) \
26 : : do { \
27 : : (p)[0] = (uint8_t)((v)); \
28 : : (p)[1] = (uint8_t)((v) >> 8); \
29 : : (p)[2] = (uint8_t)((v) >> 16); \
30 : : (p)[3] = (uint8_t)((v) >> 24); \
31 : : } while (0)
32 : :
33 : : void
34 : 1137 : poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
35 : : uint32_t t0,t1,t2,t3;
36 : : uint32_t h0,h1,h2,h3,h4;
37 : : uint32_t r0,r1,r2,r3,r4;
38 : : uint32_t s1,s2,s3,s4;
39 : : uint32_t b, nb;
40 : : size_t j;
41 : : uint64_t t[5];
42 : : uint64_t f0,f1,f2,f3;
43 : : uint32_t g0,g1,g2,g3,g4;
44 : : uint64_t c;
45 : : unsigned char mp[16];
46 : :
47 : : /* clamp key */
48 : 1137 : t0 = U8TO32_LE(key+0);
49 : 1137 : t1 = U8TO32_LE(key+4);
50 : 1137 : t2 = U8TO32_LE(key+8);
51 : 1137 : t3 = U8TO32_LE(key+12);
52 : :
53 : : /* precompute multipliers */
54 : 1137 : r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
55 : 1137 : r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
56 : 1137 : r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
57 : 1137 : r3 = t2 & 0x3f03fff; t3 >>= 8;
58 : 1137 : r4 = t3 & 0x00fffff;
59 : :
60 : 1137 : s1 = r1 * 5;
61 : 1137 : s2 = r2 * 5;
62 : 1137 : s3 = r3 * 5;
63 : 1137 : s4 = r4 * 5;
64 : :
65 : : /* init state */
66 : 1137 : h0 = 0;
67 : 1137 : h1 = 0;
68 : 1137 : h2 = 0;
69 : 1137 : h3 = 0;
70 : 1137 : h4 = 0;
71 : :
72 : : /* full blocks */
73 [ + + ]: 1137 : if (inlen < 16) goto poly1305_donna_atmost15bytes;
74 : : poly1305_donna_16bytes:
75 : 745514 : m += 16;
76 : 745514 : inlen -= 16;
77 : :
78 : 745514 : t0 = U8TO32_LE(m-16);
79 : 745514 : t1 = U8TO32_LE(m-12);
80 : 745514 : t2 = U8TO32_LE(m-8);
81 : 745514 : t3 = U8TO32_LE(m-4);
82 : :
83 : 745514 : h0 += t0 & 0x3ffffff;
84 : 745514 : h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
85 : 745514 : h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
86 : 745514 : h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
87 : 745514 : h4 += (t3 >> 8) | (1 << 24);
88 : :
89 : :
90 : : poly1305_donna_mul:
91 : 746651 : t[0] = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1);
92 : 746651 : t[1] = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2);
93 : 746651 : t[2] = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3);
94 : 746651 : t[3] = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4);
95 : 746651 : t[4] = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0);
96 : :
97 : 746651 : h0 = (uint32_t)t[0] & 0x3ffffff; c = (t[0] >> 26);
98 : 746651 : t[1] += c; h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26);
99 : 746651 : t[2] += b; h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26);
100 : 746651 : t[3] += b; h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26);
101 : 746651 : t[4] += b; h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26);
102 : 746651 : h0 += b * 5;
103 : :
104 [ + + ]: 746651 : if (inlen >= 16) goto poly1305_donna_16bytes;
105 : :
106 : : /* final bytes */
107 : : poly1305_donna_atmost15bytes:
108 [ + + ]: 2274 : if (!inlen) goto poly1305_donna_finish;
109 : :
110 [ + + ]: 8573 : for (j = 0; j < inlen; j++) mp[j] = m[j];
111 : 1137 : mp[j++] = 1;
112 [ + + ]: 10756 : for (; j < 16; j++) mp[j] = 0;
113 : 1137 : inlen = 0;
114 : :
115 : 1137 : t0 = U8TO32_LE(mp+0);
116 : 1137 : t1 = U8TO32_LE(mp+4);
117 : 1137 : t2 = U8TO32_LE(mp+8);
118 : 1137 : t3 = U8TO32_LE(mp+12);
119 : :
120 : 1137 : h0 += t0 & 0x3ffffff;
121 : 1137 : h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
122 : 1137 : h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
123 : 1137 : h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
124 : 1137 : h4 += (t3 >> 8);
125 : :
126 : 1137 : goto poly1305_donna_mul;
127 : :
128 : : poly1305_donna_finish:
129 : 1137 : b = h0 >> 26; h0 = h0 & 0x3ffffff;
130 : 1137 : h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff;
131 : 1137 : h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff;
132 : 1137 : h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff;
133 : 1137 : h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff;
134 : 1137 : h0 += b * 5; b = h0 >> 26; h0 = h0 & 0x3ffffff;
135 : 1137 : h1 += b;
136 : :
137 : 1137 : g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff;
138 : 1137 : g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
139 : 1137 : g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
140 : 1137 : g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
141 : 1137 : g4 = h4 + b - (1 << 26);
142 : :
143 : 1137 : b = (g4 >> 31) - 1;
144 : 1137 : nb = ~b;
145 : 1137 : h0 = (h0 & nb) | (g0 & b);
146 : 1137 : h1 = (h1 & nb) | (g1 & b);
147 : 1137 : h2 = (h2 & nb) | (g2 & b);
148 : 1137 : h3 = (h3 & nb) | (g3 & b);
149 : 1137 : h4 = (h4 & nb) | (g4 & b);
150 : :
151 : 1137 : f0 = ((h0 ) | (h1 << 26)) + (uint64_t)U8TO32_LE(&key[16]);
152 : 1137 : f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t)U8TO32_LE(&key[20]);
153 : 1137 : f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)U8TO32_LE(&key[24]);
154 : 1137 : f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t)U8TO32_LE(&key[28]);
155 : :
156 : 1137 : U32TO8_LE(&out[ 0], f0); f1 += (f0 >> 32);
157 : 1137 : U32TO8_LE(&out[ 4], f1); f2 += (f1 >> 32);
158 : 1137 : U32TO8_LE(&out[ 8], f2); f3 += (f2 >> 32);
159 : 1137 : U32TO8_LE(&out[12], f3);
160 : 1137 : }
|