Bitcoin ABC 0.32.4
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#include <crypto/common.h>
6#include <crypto/poly1305.h>
7
8#include <cstring>
9
10namespace poly1305_donna {
11
12// Based on the public domain implementation by Andrew Moon
13// poly1305-donna-32.h from https://github.com/floodyberry/poly1305-donna
14
15void poly1305_init(poly1305_context *st, const uint8_t key[32]) noexcept {
16 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
17 st->r[0] = (ReadLE32(&key[0])) & 0x3ffffff;
18 st->r[1] = (ReadLE32(&key[3]) >> 2) & 0x3ffff03;
19 st->r[2] = (ReadLE32(&key[6]) >> 4) & 0x3ffc0ff;
20 st->r[3] = (ReadLE32(&key[9]) >> 6) & 0x3f03fff;
21 st->r[4] = (ReadLE32(&key[12]) >> 8) & 0x00fffff;
22
23 /* h = 0 */
24 st->h[0] = 0;
25 st->h[1] = 0;
26 st->h[2] = 0;
27 st->h[3] = 0;
28 st->h[4] = 0;
29
30 /* save pad for later */
31 st->pad[0] = ReadLE32(&key[16]);
32 st->pad[1] = ReadLE32(&key[20]);
33 st->pad[2] = ReadLE32(&key[24]);
34 st->pad[3] = ReadLE32(&key[28]);
35
36 st->leftover = 0;
37 st->final = 0;
38}
39
40static void poly1305_blocks(poly1305_context *st, const uint8_t *m,
41 size_t bytes) noexcept {
42 const uint32_t hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */
43 uint32_t r0, r1, r2, r3, r4;
44 uint32_t s1, s2, s3, s4;
45 uint32_t h0, h1, h2, h3, h4;
46 uint64_t d0, d1, d2, d3, d4;
47 uint32_t c;
48
49 r0 = st->r[0];
50 r1 = st->r[1];
51 r2 = st->r[2];
52 r3 = st->r[3];
53 r4 = st->r[4];
54
55 s1 = r1 * 5;
56 s2 = r2 * 5;
57 s3 = r3 * 5;
58 s4 = r4 * 5;
59
60 h0 = st->h[0];
61 h1 = st->h[1];
62 h2 = st->h[2];
63 h3 = st->h[3];
64 h4 = st->h[4];
65
66 while (bytes >= POLY1305_BLOCK_SIZE) {
67 /* h += m[i] */
68 h0 += (ReadLE32(m + 0)) & 0x3ffffff;
69 h1 += (ReadLE32(m + 3) >> 2) & 0x3ffffff;
70 h2 += (ReadLE32(m + 6) >> 4) & 0x3ffffff;
71 h3 += (ReadLE32(m + 9) >> 6) & 0x3ffffff;
72 h4 += (ReadLE32(m + 12) >> 8) | hibit;
73
74 /* h *= r */
75 d0 = ((uint64_t)h0 * r0) + ((uint64_t)h1 * s4) + ((uint64_t)h2 * s3) +
76 ((uint64_t)h3 * s2) + ((uint64_t)h4 * s1);
77 d1 = ((uint64_t)h0 * r1) + ((uint64_t)h1 * r0) + ((uint64_t)h2 * s4) +
78 ((uint64_t)h3 * s3) + ((uint64_t)h4 * s2);
79 d2 = ((uint64_t)h0 * r2) + ((uint64_t)h1 * r1) + ((uint64_t)h2 * r0) +
80 ((uint64_t)h3 * s4) + ((uint64_t)h4 * s3);
81 d3 = ((uint64_t)h0 * r3) + ((uint64_t)h1 * r2) + ((uint64_t)h2 * r1) +
82 ((uint64_t)h3 * r0) + ((uint64_t)h4 * s4);
83 d4 = ((uint64_t)h0 * r4) + ((uint64_t)h1 * r3) + ((uint64_t)h2 * r2) +
84 ((uint64_t)h3 * r1) + ((uint64_t)h4 * r0);
85
86 /* (partial) h %= p */
87 c = (uint32_t)(d0 >> 26);
88 h0 = (uint32_t)d0 & 0x3ffffff;
89 d1 += c;
90 c = (uint32_t)(d1 >> 26);
91 h1 = (uint32_t)d1 & 0x3ffffff;
92 d2 += c;
93 c = (uint32_t)(d2 >> 26);
94 h2 = (uint32_t)d2 & 0x3ffffff;
95 d3 += c;
96 c = (uint32_t)(d3 >> 26);
97 h3 = (uint32_t)d3 & 0x3ffffff;
98 d4 += c;
99 c = (uint32_t)(d4 >> 26);
100 h4 = (uint32_t)d4 & 0x3ffffff;
101 h0 += c * 5;
102 c = (h0 >> 26);
103 h0 = h0 & 0x3ffffff;
104 h1 += c;
105
107 bytes -= POLY1305_BLOCK_SIZE;
108 }
109
110 st->h[0] = h0;
111 st->h[1] = h1;
112 st->h[2] = h2;
113 st->h[3] = h3;
114 st->h[4] = h4;
115}
116
117void poly1305_finish(poly1305_context *st, uint8_t mac[16]) noexcept {
118 uint32_t h0, h1, h2, h3, h4, c;
119 uint32_t g0, g1, g2, g3, g4;
120 uint64_t f;
121 uint32_t mask;
122
123 /* process the remaining block */
124 if (st->leftover) {
125 size_t i = st->leftover;
126 st->buffer[i++] = 1;
127 for (; i < POLY1305_BLOCK_SIZE; i++) {
128 st->buffer[i] = 0;
129 }
130 st->final = 1;
131 poly1305_blocks(st, st->buffer, POLY1305_BLOCK_SIZE);
132 }
133
134 /* fully carry h */
135 h0 = st->h[0];
136 h1 = st->h[1];
137 h2 = st->h[2];
138 h3 = st->h[3];
139 h4 = st->h[4];
140
141 c = h1 >> 26;
142 h1 = h1 & 0x3ffffff;
143 h2 += c;
144 c = h2 >> 26;
145 h2 = h2 & 0x3ffffff;
146 h3 += c;
147 c = h3 >> 26;
148 h3 = h3 & 0x3ffffff;
149 h4 += c;
150 c = h4 >> 26;
151 h4 = h4 & 0x3ffffff;
152 h0 += c * 5;
153 c = h0 >> 26;
154 h0 = h0 & 0x3ffffff;
155 h1 += c;
156
157 /* compute h + -p */
158 g0 = h0 + 5;
159 c = g0 >> 26;
160 g0 &= 0x3ffffff;
161 g1 = h1 + c;
162 c = g1 >> 26;
163 g1 &= 0x3ffffff;
164 g2 = h2 + c;
165 c = g2 >> 26;
166 g2 &= 0x3ffffff;
167 g3 = h3 + c;
168 c = g3 >> 26;
169 g3 &= 0x3ffffff;
170 g4 = h4 + c - (1UL << 26);
171
172 /* select h if h < p, or h + -p if h >= p */
173 mask = (g4 >> ((sizeof(uint32_t) * 8) - 1)) - 1;
174 g0 &= mask;
175 g1 &= mask;
176 g2 &= mask;
177 g3 &= mask;
178 g4 &= mask;
179 mask = ~mask;
180 h0 = (h0 & mask) | g0;
181 h1 = (h1 & mask) | g1;
182 h2 = (h2 & mask) | g2;
183 h3 = (h3 & mask) | g3;
184 h4 = (h4 & mask) | g4;
185
186 /* h = h % (2^128) */
187 h0 = ((h0) | (h1 << 26)) & 0xffffffff;
188 h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
189 h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
190 h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
191
192 /* mac = (h + pad) % (2^128) */
193 f = (uint64_t)h0 + st->pad[0];
194 h0 = (uint32_t)f;
195 f = (uint64_t)h1 + st->pad[1] + (f >> 32);
196 h1 = (uint32_t)f;
197 f = (uint64_t)h2 + st->pad[2] + (f >> 32);
198 h2 = (uint32_t)f;
199 f = (uint64_t)h3 + st->pad[3] + (f >> 32);
200 h3 = (uint32_t)f;
201
202 WriteLE32(mac + 0, h0);
203 WriteLE32(mac + 4, h1);
204 WriteLE32(mac + 8, h2);
205 WriteLE32(mac + 12, h3);
206
207 /* zero out the state */
208 st->h[0] = 0;
209 st->h[1] = 0;
210 st->h[2] = 0;
211 st->h[3] = 0;
212 st->h[4] = 0;
213 st->r[0] = 0;
214 st->r[1] = 0;
215 st->r[2] = 0;
216 st->r[3] = 0;
217 st->r[4] = 0;
218 st->pad[0] = 0;
219 st->pad[1] = 0;
220 st->pad[2] = 0;
221 st->pad[3] = 0;
222}
223
224void poly1305_update(poly1305_context *st, const uint8_t *m,
225 size_t bytes) noexcept {
226 size_t i;
227
228 /* handle leftover */
229 if (st->leftover) {
230 size_t want = (POLY1305_BLOCK_SIZE - st->leftover);
231 if (want > bytes) {
232 want = bytes;
233 }
234 for (i = 0; i < want; i++) {
235 st->buffer[st->leftover + i] = m[i];
236 }
237 bytes -= want;
238 m += want;
239 st->leftover += want;
240 if (st->leftover < POLY1305_BLOCK_SIZE) {
241 return;
242 }
243 poly1305_blocks(st, st->buffer, POLY1305_BLOCK_SIZE);
244 st->leftover = 0;
245 }
246
247 /* process full blocks */
248 if (bytes >= POLY1305_BLOCK_SIZE) {
249 size_t want = (bytes & ~(POLY1305_BLOCK_SIZE - 1));
250 poly1305_blocks(st, m, want);
251 m += want;
252 bytes -= want;
253 }
254
255 /* store leftover */
256 if (bytes) {
257 for (i = 0; i < bytes; i++) {
258 st->buffer[st->leftover + i] = m[i];
259 }
260 st->leftover += bytes;
261 }
262}
263
264} // namespace poly1305_donna
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
void poly1305_init(poly1305_context *st, const uint8_t key[32]) noexcept
Definition: poly1305.cpp:15
void poly1305_finish(poly1305_context *st, uint8_t mac[16]) noexcept
Definition: poly1305.cpp:117
static void poly1305_blocks(poly1305_context *st, const uint8_t *m, size_t bytes) noexcept
Definition: poly1305.cpp:40
void poly1305_update(poly1305_context *st, const uint8_t *m, size_t bytes) noexcept
Definition: poly1305.cpp:224
#define POLY1305_BLOCK_SIZE
Definition: poly1305.h:14