Bitcoin ABC 0.30.5
P2P Digital Currency
poly1305.cpp
Go to the documentation of this file.
1// Copyright (c) 2019 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5// Based on the public domain implementation by Andrew Moon
6// poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
7
8#include <crypto/common.h>
9#include <crypto/poly1305.h>
10
11#include <cstring>
12
13#define mul32x32_64(a, b) ((uint64_t)(a) * (b))
14
15void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen,
16 const uint8_t key[POLY1305_KEYLEN]) {
17 uint32_t t0, t1, t2, t3;
18 uint32_t h0, h1, h2, h3, h4;
19 uint32_t r0, r1, r2, r3, r4;
20 uint32_t s1, s2, s3, s4;
21 uint32_t b, nb;
22 size_t j;
23 uint64_t t[5];
24 uint64_t f0, f1, f2, f3;
25 uint64_t g0, g1, g2, g3, g4;
26 uint64_t c;
27 uint8_t mp[16];
28
29 /* clamp key */
30 t0 = ReadLE32(key + 0);
31 t1 = ReadLE32(key + 4);
32 t2 = ReadLE32(key + 8);
33 t3 = ReadLE32(key + 12);
34
35 /* precompute multipliers */
36 r0 = t0 & 0x3ffffff;
37 t0 >>= 26;
38 t0 |= t1 << 6;
39 r1 = t0 & 0x3ffff03;
40 t1 >>= 20;
41 t1 |= t2 << 12;
42 r2 = t1 & 0x3ffc0ff;
43 t2 >>= 14;
44 t2 |= t3 << 18;
45 r3 = t2 & 0x3f03fff;
46 t3 >>= 8;
47 r4 = t3 & 0x00fffff;
48
49 s1 = r1 * 5;
50 s2 = r2 * 5;
51 s3 = r3 * 5;
52 s4 = r4 * 5;
53
54 /* init state */
55 h0 = 0;
56 h1 = 0;
57 h2 = 0;
58 h3 = 0;
59 h4 = 0;
60
61 /* full blocks */
62 if (inlen < 16) {
63 goto poly1305_donna_atmost15bytes;
64 }
65
66poly1305_donna_16bytes:
67 m += 16;
68 inlen -= 16;
69
70 t0 = ReadLE32(m - 16);
71 t1 = ReadLE32(m - 12);
72 t2 = ReadLE32(m - 8);
73 t3 = ReadLE32(m - 4);
74
75 h0 += t0 & 0x3ffffff;
76 h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
77 h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
78 h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
79 h4 += (t3 >> 8) | (1 << 24);
80
81poly1305_donna_mul:
82 t[0] = mul32x32_64(h0, r0) + mul32x32_64(h1, s4) + mul32x32_64(h2, s3) +
83 mul32x32_64(h3, s2) + mul32x32_64(h4, s1);
84 t[1] = mul32x32_64(h0, r1) + mul32x32_64(h1, r0) + mul32x32_64(h2, s4) +
85 mul32x32_64(h3, s3) + mul32x32_64(h4, s2);
86 t[2] = mul32x32_64(h0, r2) + mul32x32_64(h1, r1) + mul32x32_64(h2, r0) +
87 mul32x32_64(h3, s4) + mul32x32_64(h4, s3);
88 t[3] = mul32x32_64(h0, r3) + mul32x32_64(h1, r2) + mul32x32_64(h2, r1) +
89 mul32x32_64(h3, r0) + mul32x32_64(h4, s4);
90 t[4] = mul32x32_64(h0, r4) + mul32x32_64(h1, r3) + mul32x32_64(h2, r2) +
91 mul32x32_64(h3, r1) + mul32x32_64(h4, r0);
92
93 h0 = (uint32_t)t[0] & 0x3ffffff;
94 c = (t[0] >> 26);
95 t[1] += c;
96 h1 = (uint32_t)t[1] & 0x3ffffff;
97 b = (uint32_t)(t[1] >> 26);
98 t[2] += b;
99 h2 = (uint32_t)t[2] & 0x3ffffff;
100 b = (uint32_t)(t[2] >> 26);
101 t[3] += b;
102 h3 = (uint32_t)t[3] & 0x3ffffff;
103 b = (uint32_t)(t[3] >> 26);
104 t[4] += b;
105 h4 = (uint32_t)t[4] & 0x3ffffff;
106 b = (uint32_t)(t[4] >> 26);
107 h0 += b * 5;
108
109 if (inlen >= 16) {
110 goto poly1305_donna_16bytes;
111 }
112
113 /* final bytes */
114poly1305_donna_atmost15bytes:
115 if (!inlen) {
116 goto poly1305_donna_finish;
117 }
118
119 for (j = 0; j < inlen; j++) {
120 mp[j] = m[j];
121 }
122 mp[j++] = 1;
123 for (; j < 16; j++) {
124 mp[j] = 0;
125 }
126 inlen = 0;
127
128 t0 = ReadLE32(mp + 0);
129 t1 = ReadLE32(mp + 4);
130 t2 = ReadLE32(mp + 8);
131 t3 = ReadLE32(mp + 12);
132
133 h0 += t0 & 0x3ffffff;
134 h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
135 h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
136 h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
137 h4 += (t3 >> 8);
138
139 goto poly1305_donna_mul;
140
141poly1305_donna_finish:
142 b = h0 >> 26;
143 h0 = h0 & 0x3ffffff;
144 h1 += b;
145 b = h1 >> 26;
146 h1 = h1 & 0x3ffffff;
147 h2 += b;
148 b = h2 >> 26;
149 h2 = h2 & 0x3ffffff;
150 h3 += b;
151 b = h3 >> 26;
152 h3 = h3 & 0x3ffffff;
153 h4 += b;
154 b = h4 >> 26;
155 h4 = h4 & 0x3ffffff;
156 h0 += b * 5;
157 b = h0 >> 26;
158 h0 = h0 & 0x3ffffff;
159 h1 += b;
160
161 g0 = h0 + 5;
162 b = g0 >> 26;
163 g0 &= 0x3ffffff;
164 g1 = h1 + b;
165 b = g1 >> 26;
166 g1 &= 0x3ffffff;
167 g2 = h2 + b;
168 b = g2 >> 26;
169 g2 &= 0x3ffffff;
170 g3 = h3 + b;
171 b = g3 >> 26;
172 g3 &= 0x3ffffff;
173 g4 = h4 + b - (1 << 26);
174
175 b = (g4 >> 31) - 1;
176 nb = ~b;
177 h0 = (h0 & nb) | (g0 & b);
178 h1 = (h1 & nb) | (g1 & b);
179 h2 = (h2 & nb) | (g2 & b);
180 h3 = (h3 & nb) | (g3 & b);
181 h4 = (h4 & nb) | (g4 & b);
182
183 f0 = ((h0) | (h1 << 26)) + (uint64_t)ReadLE32(&key[16]);
184 f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t)ReadLE32(&key[20]);
185 f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)ReadLE32(&key[24]);
186 f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t)ReadLE32(&key[28]);
187
188 WriteLE32(&out[0], f0);
189 f1 += (f0 >> 32);
190 WriteLE32(&out[4], f1);
191 f2 += (f1 >> 32);
192 WriteLE32(&out[8], f2);
193 f3 += (f2 >> 32);
194 WriteLE32(&out[12], f3);
195}
static void WriteLE32(uint8_t *ptr, uint32_t x)
Definition: common.h:40
static uint32_t ReadLE32(const uint8_t *ptr)
Definition: common.h:23
#define mul32x32_64(a, b)
Definition: poly1305.cpp:13
void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen, const uint8_t key[POLY1305_KEYLEN])
Definition: poly1305.cpp:15
#define POLY1305_KEYLEN
Definition: poly1305.h:11
#define POLY1305_TAGLEN
Definition: poly1305.h:12