/Users/eugenesiegel/btc/bitcoin/src/crypto/muhash.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2017-present 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/muhash.h> |
6 | | |
7 | | #include <crypto/chacha20.h> |
8 | | #include <crypto/common.h> |
9 | | #include <hash.h> |
10 | | #include <util/check.h> |
11 | | |
12 | | #include <bit> |
13 | | #include <cassert> |
14 | | #include <cstdio> |
15 | | #include <limits> |
16 | | |
17 | | namespace { |
18 | | |
19 | | using limb_t = Num3072::limb_t; |
20 | | using signed_limb_t = Num3072::signed_limb_t; |
21 | | using double_limb_t = Num3072::double_limb_t; |
22 | | using signed_double_limb_t = Num3072::signed_double_limb_t; |
23 | | constexpr int LIMB_SIZE = Num3072::LIMB_SIZE; |
24 | | constexpr int SIGNED_LIMB_SIZE = Num3072::SIGNED_LIMB_SIZE; |
25 | | constexpr int LIMBS = Num3072::LIMBS; |
26 | | constexpr int SIGNED_LIMBS = Num3072::SIGNED_LIMBS; |
27 | | constexpr int FINAL_LIMB_POSITION = 3072 / SIGNED_LIMB_SIZE; |
28 | | constexpr int FINAL_LIMB_MODULUS_BITS = 3072 % SIGNED_LIMB_SIZE; |
29 | | constexpr limb_t MAX_LIMB = (limb_t)(-1); |
30 | | constexpr limb_t MAX_SIGNED_LIMB = (((limb_t)1) << SIGNED_LIMB_SIZE) - 1; |
31 | | /** 2^3072 - 1103717, the largest 3072-bit safe prime number, is used as the modulus. */ |
32 | | constexpr limb_t MAX_PRIME_DIFF = 1103717; |
33 | | /** The modular inverse of (2**3072 - MAX_PRIME_DIFF) mod (MAX_SIGNED_LIMB + 1). */ |
34 | | constexpr limb_t MODULUS_INVERSE = limb_t(0x70a1421da087d93); |
35 | | |
36 | | |
37 | | /** Extract the lowest limb of [c0,c1,c2] into n, and left shift the number by 1 limb. */ |
38 | | inline void extract3(limb_t& c0, limb_t& c1, limb_t& c2, limb_t& n) |
39 | 0 | { |
40 | 0 | n = c0; |
41 | 0 | c0 = c1; |
42 | 0 | c1 = c2; |
43 | 0 | c2 = 0; |
44 | 0 | } |
45 | | |
46 | | /** [c0,c1] = a * b */ |
47 | | inline void mul(limb_t& c0, limb_t& c1, const limb_t& a, const limb_t& b) |
48 | 0 | { |
49 | 0 | double_limb_t t = (double_limb_t)a * b; |
50 | 0 | c1 = t >> LIMB_SIZE; |
51 | 0 | c0 = t; |
52 | 0 | } |
53 | | |
54 | | /* [c0,c1,c2] += n * [d0,d1,d2]. c2 is 0 initially */ |
55 | | inline void mulnadd3(limb_t& c0, limb_t& c1, limb_t& c2, limb_t& d0, limb_t& d1, limb_t& d2, const limb_t& n) |
56 | 0 | { |
57 | 0 | double_limb_t t = (double_limb_t)d0 * n + c0; |
58 | 0 | c0 = t; |
59 | 0 | t >>= LIMB_SIZE; |
60 | 0 | t += (double_limb_t)d1 * n + c1; |
61 | 0 | c1 = t; |
62 | 0 | t >>= LIMB_SIZE; |
63 | 0 | c2 = t + d2 * n; |
64 | 0 | } |
65 | | |
66 | | /* [c0,c1] *= n */ |
67 | | inline void muln2(limb_t& c0, limb_t& c1, const limb_t& n) |
68 | 0 | { |
69 | 0 | double_limb_t t = (double_limb_t)c0 * n; |
70 | 0 | c0 = t; |
71 | 0 | t >>= LIMB_SIZE; |
72 | 0 | t += (double_limb_t)c1 * n; |
73 | 0 | c1 = t; |
74 | 0 | } |
75 | | |
76 | | /** [c0,c1,c2] += a * b */ |
77 | | inline void muladd3(limb_t& c0, limb_t& c1, limb_t& c2, const limb_t& a, const limb_t& b) |
78 | 0 | { |
79 | 0 | double_limb_t t = (double_limb_t)a * b; |
80 | 0 | limb_t th = t >> LIMB_SIZE; |
81 | 0 | limb_t tl = t; |
82 | |
|
83 | 0 | c0 += tl; |
84 | 0 | th += (c0 < tl) ? 1 : 0; |
85 | 0 | c1 += th; |
86 | 0 | c2 += (c1 < th) ? 1 : 0; |
87 | 0 | } |
88 | | |
89 | | /** |
90 | | * Add limb a to [c0,c1]: [c0,c1] += a. Then extract the lowest |
91 | | * limb of [c0,c1] into n, and left shift the number by 1 limb. |
92 | | * */ |
93 | | inline void addnextract2(limb_t& c0, limb_t& c1, const limb_t& a, limb_t& n) |
94 | 0 | { |
95 | 0 | limb_t c2 = 0; |
96 | | |
97 | | // add |
98 | 0 | c0 += a; |
99 | 0 | if (c0 < a) { |
100 | 0 | c1 += 1; |
101 | | |
102 | | // Handle case when c1 has overflown |
103 | 0 | if (c1 == 0) c2 = 1; |
104 | 0 | } |
105 | | |
106 | | // extract |
107 | 0 | n = c0; |
108 | 0 | c0 = c1; |
109 | 0 | c1 = c2; |
110 | 0 | } |
111 | | |
112 | | } // namespace |
113 | | |
114 | | /** Indicates whether d is larger than the modulus. */ |
115 | | bool Num3072::IsOverflow() const |
116 | 0 | { |
117 | 0 | if (this->limbs[0] <= std::numeric_limits<limb_t>::max() - MAX_PRIME_DIFF) return false; |
118 | 0 | for (int i = 1; i < LIMBS; ++i) { |
119 | 0 | if (this->limbs[i] != std::numeric_limits<limb_t>::max()) return false; |
120 | 0 | } |
121 | 0 | return true; |
122 | 0 | } |
123 | | |
124 | | void Num3072::FullReduce() |
125 | 0 | { |
126 | 0 | limb_t c0 = MAX_PRIME_DIFF; |
127 | 0 | limb_t c1 = 0; |
128 | 0 | for (int i = 0; i < LIMBS; ++i) { |
129 | 0 | addnextract2(c0, c1, this->limbs[i], this->limbs[i]); |
130 | 0 | } |
131 | 0 | } |
132 | | |
133 | | namespace { |
134 | | /** A type representing a number in signed limb representation. */ |
135 | | struct Num3072Signed |
136 | | { |
137 | | /** The represented value is sum(limbs[i]*2^(SIGNED_LIMB_SIZE*i), i=0..SIGNED_LIMBS-1). |
138 | | * Note that limbs may be negative, or exceed 2^SIGNED_LIMB_SIZE-1. */ |
139 | | signed_limb_t limbs[SIGNED_LIMBS]; |
140 | | |
141 | | /** Construct a Num3072Signed with value 0. */ |
142 | | Num3072Signed() |
143 | 0 | { |
144 | 0 | memset(limbs, 0, sizeof(limbs)); |
145 | 0 | } |
146 | | |
147 | | /** Convert a Num3072 to a Num3072Signed. Output will be normalized and in |
148 | | * range 0..2^3072-1. */ |
149 | | void FromNum3072(const Num3072& in) |
150 | 0 | { |
151 | 0 | double_limb_t c = 0; |
152 | 0 | int b = 0, outpos = 0; |
153 | 0 | for (int i = 0; i < LIMBS; ++i) { |
154 | 0 | c += double_limb_t{in.limbs[i]} << b; |
155 | 0 | b += LIMB_SIZE; |
156 | 0 | while (b >= SIGNED_LIMB_SIZE) { |
157 | 0 | limbs[outpos++] = limb_t(c) & MAX_SIGNED_LIMB; |
158 | 0 | c >>= SIGNED_LIMB_SIZE; |
159 | 0 | b -= SIGNED_LIMB_SIZE; |
160 | 0 | } |
161 | 0 | } |
162 | 0 | Assume(outpos == SIGNED_LIMBS - 1); Line | Count | Source | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) |
|
163 | 0 | limbs[SIGNED_LIMBS - 1] = c; |
164 | 0 | c >>= SIGNED_LIMB_SIZE; |
165 | 0 | Assume(c == 0); Line | Count | Source | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) |
|
166 | 0 | } |
167 | | |
168 | | /** Convert a Num3072Signed to a Num3072. Input must be in range 0..modulus-1. */ |
169 | | void ToNum3072(Num3072& out) const |
170 | 0 | { |
171 | 0 | double_limb_t c = 0; |
172 | 0 | int b = 0, outpos = 0; |
173 | 0 | for (int i = 0; i < SIGNED_LIMBS; ++i) { |
174 | 0 | c += double_limb_t(limbs[i]) << b; |
175 | 0 | b += SIGNED_LIMB_SIZE; |
176 | 0 | if (b >= LIMB_SIZE) { |
177 | 0 | out.limbs[outpos++] = c; |
178 | 0 | c >>= LIMB_SIZE; |
179 | 0 | b -= LIMB_SIZE; |
180 | 0 | } |
181 | 0 | } |
182 | 0 | Assume(outpos == LIMBS); Line | Count | Source | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) |
|
183 | 0 | Assume(c == 0); Line | Count | Source | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) |
|
184 | 0 | } |
185 | | |
186 | | /** Take a Num3072Signed in range 1-2*2^3072..2^3072-1, and: |
187 | | * - optionally negate it (if negate is true) |
188 | | * - reduce it modulo the modulus (2^3072 - MAX_PRIME_DIFF) |
189 | | * - produce output with all limbs in range 0..2^SIGNED_LIMB_SIZE-1 |
190 | | */ |
191 | | void Normalize(bool negate) |
192 | 0 | { |
193 | | // Add modulus if this was negative. This brings the range of *this to 1-2^3072..2^3072-1. |
194 | 0 | signed_limb_t cond_add = limbs[SIGNED_LIMBS-1] >> (LIMB_SIZE-1); // -1 if this is negative; 0 otherwise |
195 | 0 | limbs[0] += signed_limb_t(-MAX_PRIME_DIFF) & cond_add; |
196 | 0 | limbs[FINAL_LIMB_POSITION] += (signed_limb_t(1) << FINAL_LIMB_MODULUS_BITS) & cond_add; |
197 | | // Next negate all limbs if negate was set. This does not change the range of *this. |
198 | 0 | signed_limb_t cond_negate = -signed_limb_t(negate); // -1 if this negate is true; 0 otherwise |
199 | 0 | for (int i = 0; i < SIGNED_LIMBS; ++i) { |
200 | 0 | limbs[i] = (limbs[i] ^ cond_negate) - cond_negate; |
201 | 0 | } |
202 | | // Perform carry (make all limbs except the top one be in range 0..2^SIGNED_LIMB_SIZE-1). |
203 | 0 | for (int i = 0; i < SIGNED_LIMBS - 1; ++i) { |
204 | 0 | limbs[i + 1] += limbs[i] >> SIGNED_LIMB_SIZE; |
205 | 0 | limbs[i] &= MAX_SIGNED_LIMB; |
206 | 0 | } |
207 | | // Again add modulus if *this was negative. This brings the range of *this to 0..2^3072-1. |
208 | 0 | cond_add = limbs[SIGNED_LIMBS-1] >> (LIMB_SIZE-1); // -1 if this is negative; 0 otherwise |
209 | 0 | limbs[0] += signed_limb_t(-MAX_PRIME_DIFF) & cond_add; |
210 | 0 | limbs[FINAL_LIMB_POSITION] += (signed_limb_t(1) << FINAL_LIMB_MODULUS_BITS) & cond_add; |
211 | | // Perform another carry. Now all limbs are in range 0..2^SIGNED_LIMB_SIZE-1. |
212 | 0 | for (int i = 0; i < SIGNED_LIMBS - 1; ++i) { |
213 | 0 | limbs[i + 1] += limbs[i] >> SIGNED_LIMB_SIZE; |
214 | 0 | limbs[i] &= MAX_SIGNED_LIMB; |
215 | 0 | } |
216 | 0 | } |
217 | | }; |
218 | | |
219 | | /** 2x2 transformation matrix with signed_limb_t elements. */ |
220 | | struct SignedMatrix |
221 | | { |
222 | | signed_limb_t u, v, q, r; |
223 | | }; |
224 | | |
225 | | /** Compute the transformation matrix for SIGNED_LIMB_SIZE divsteps. |
226 | | * |
227 | | * eta: initial eta value |
228 | | * f: bottom SIGNED_LIMB_SIZE bits of initial f value |
229 | | * g: bottom SIGNED_LIMB_SIZE bits of initial g value |
230 | | * out: resulting transformation matrix, scaled by 2^SIGNED_LIMB_SIZE |
231 | | * return: eta value after SIGNED_LIMB_SIZE divsteps |
232 | | */ |
233 | | inline limb_t ComputeDivstepMatrix(signed_limb_t eta, limb_t f, limb_t g, SignedMatrix& out) |
234 | 0 | { |
235 | | /** inv256[i] = -1/(2*i+1) (mod 256) */ |
236 | 0 | static const uint8_t NEGINV256[128] = { |
237 | 0 | 0xFF, 0x55, 0x33, 0x49, 0xC7, 0x5D, 0x3B, 0x11, 0x0F, 0xE5, 0xC3, 0x59, |
238 | 0 | 0xD7, 0xED, 0xCB, 0x21, 0x1F, 0x75, 0x53, 0x69, 0xE7, 0x7D, 0x5B, 0x31, |
239 | 0 | 0x2F, 0x05, 0xE3, 0x79, 0xF7, 0x0D, 0xEB, 0x41, 0x3F, 0x95, 0x73, 0x89, |
240 | 0 | 0x07, 0x9D, 0x7B, 0x51, 0x4F, 0x25, 0x03, 0x99, 0x17, 0x2D, 0x0B, 0x61, |
241 | 0 | 0x5F, 0xB5, 0x93, 0xA9, 0x27, 0xBD, 0x9B, 0x71, 0x6F, 0x45, 0x23, 0xB9, |
242 | 0 | 0x37, 0x4D, 0x2B, 0x81, 0x7F, 0xD5, 0xB3, 0xC9, 0x47, 0xDD, 0xBB, 0x91, |
243 | 0 | 0x8F, 0x65, 0x43, 0xD9, 0x57, 0x6D, 0x4B, 0xA1, 0x9F, 0xF5, 0xD3, 0xE9, |
244 | 0 | 0x67, 0xFD, 0xDB, 0xB1, 0xAF, 0x85, 0x63, 0xF9, 0x77, 0x8D, 0x6B, 0xC1, |
245 | 0 | 0xBF, 0x15, 0xF3, 0x09, 0x87, 0x1D, 0xFB, 0xD1, 0xCF, 0xA5, 0x83, 0x19, |
246 | 0 | 0x97, 0xAD, 0x8B, 0xE1, 0xDF, 0x35, 0x13, 0x29, 0xA7, 0x3D, 0x1B, 0xF1, |
247 | 0 | 0xEF, 0xC5, 0xA3, 0x39, 0xB7, 0xCD, 0xAB, 0x01 |
248 | 0 | }; |
249 | | // Coefficients of returned SignedMatrix; starts off as identity matrix. */ |
250 | 0 | limb_t u = 1, v = 0, q = 0, r = 1; |
251 | | // The number of divsteps still left. |
252 | 0 | int i = SIGNED_LIMB_SIZE; |
253 | 0 | while (true) { |
254 | | /* Use a sentinel bit to count zeros only up to i. */ |
255 | 0 | int zeros = std::countr_zero(g | (MAX_LIMB << i)); |
256 | | /* Perform zeros divsteps at once; they all just divide g by two. */ |
257 | 0 | g >>= zeros; |
258 | 0 | u <<= zeros; |
259 | 0 | v <<= zeros; |
260 | 0 | eta -= zeros; |
261 | 0 | i -= zeros; |
262 | | /* We're done once we've performed SIGNED_LIMB_SIZE divsteps. */ |
263 | 0 | if (i == 0) break; |
264 | | /* If eta is negative, negate it and replace f,g with g,-f. */ |
265 | 0 | if (eta < 0) { |
266 | 0 | limb_t tmp; |
267 | 0 | eta = -eta; |
268 | 0 | tmp = f; f = g; g = -tmp; |
269 | 0 | tmp = u; u = q; q = -tmp; |
270 | 0 | tmp = v; v = r; r = -tmp; |
271 | 0 | } |
272 | | /* eta is now >= 0. In what follows we're going to cancel out the bottom bits of g. No more |
273 | | * than i can be cancelled out (as we'd be done before that point), and no more than eta+1 |
274 | | * can be done as its sign will flip once that happens. */ |
275 | 0 | int limit = ((int)eta + 1) > i ? i : ((int)eta + 1); |
276 | | /* m is a mask for the bottom min(limit, 8) bits (our table only supports 8 bits). */ |
277 | 0 | limb_t m = (MAX_LIMB >> (LIMB_SIZE - limit)) & 255U; |
278 | | /* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */ |
279 | 0 | limb_t w = (g * NEGINV256[(f >> 1) & 127]) & m; |
280 | | /* Do so. */ |
281 | 0 | g += f * w; |
282 | 0 | q += u * w; |
283 | 0 | r += v * w; |
284 | 0 | } |
285 | 0 | out.u = (signed_limb_t)u; |
286 | 0 | out.v = (signed_limb_t)v; |
287 | 0 | out.q = (signed_limb_t)q; |
288 | 0 | out.r = (signed_limb_t)r; |
289 | 0 | return eta; |
290 | 0 | } |
291 | | |
292 | | /** Apply matrix t/2^SIGNED_LIMB_SIZE to vector [d,e], modulo modulus. |
293 | | * |
294 | | * On input and output, d and e are in range 1-2*modulus..modulus-1. |
295 | | */ |
296 | | inline void UpdateDE(Num3072Signed& d, Num3072Signed& e, const SignedMatrix& t) |
297 | 0 | { |
298 | 0 | const signed_limb_t u = t.u, v=t.v, q=t.q, r=t.r; |
299 | | |
300 | | /* [md,me] start as zero; plus [u,q] if d is negative; plus [v,r] if e is negative. */ |
301 | 0 | signed_limb_t sd = d.limbs[SIGNED_LIMBS - 1] >> (LIMB_SIZE - 1); |
302 | 0 | signed_limb_t se = e.limbs[SIGNED_LIMBS - 1] >> (LIMB_SIZE - 1); |
303 | 0 | signed_limb_t md = (u & sd) + (v & se); |
304 | 0 | signed_limb_t me = (q & sd) + (r & se); |
305 | | /* Begin computing t*[d,e]. */ |
306 | 0 | signed_limb_t di = d.limbs[0], ei = e.limbs[0]; |
307 | 0 | signed_double_limb_t cd = (signed_double_limb_t)u * di + (signed_double_limb_t)v * ei; |
308 | 0 | signed_double_limb_t ce = (signed_double_limb_t)q * di + (signed_double_limb_t)r * ei; |
309 | | /* Correct md,me so that t*[d,e]+modulus*[md,me] has SIGNED_LIMB_SIZE zero bottom bits. */ |
310 | 0 | md -= (MODULUS_INVERSE * limb_t(cd) + md) & MAX_SIGNED_LIMB; |
311 | 0 | me -= (MODULUS_INVERSE * limb_t(ce) + me) & MAX_SIGNED_LIMB; |
312 | | /* Update the beginning of computation for t*[d,e]+modulus*[md,me] now md,me are known. */ |
313 | 0 | cd -= (signed_double_limb_t)1103717 * md; |
314 | 0 | ce -= (signed_double_limb_t)1103717 * me; |
315 | | /* Verify that the low SIGNED_LIMB_SIZE bits of the computation are indeed zero, and then throw them away. */ |
316 | 0 | Assume((cd & MAX_SIGNED_LIMB) == 0); Line | Count | Source | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) |
|
317 | 0 | Assume((ce & MAX_SIGNED_LIMB) == 0); Line | Count | Source | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) |
|
318 | 0 | cd >>= SIGNED_LIMB_SIZE; |
319 | 0 | ce >>= SIGNED_LIMB_SIZE; |
320 | | /* Now iteratively compute limb i=1..SIGNED_LIMBS-2 of t*[d,e]+modulus*[md,me], and store them in output |
321 | | * limb i-1 (shifting down by SIGNED_LIMB_SIZE bits). The corresponding limbs in modulus are all zero, |
322 | | * so modulus/md/me are not actually involved here. */ |
323 | 0 | for (int i = 1; i < SIGNED_LIMBS - 1; ++i) { |
324 | 0 | di = d.limbs[i]; |
325 | 0 | ei = e.limbs[i]; |
326 | 0 | cd += (signed_double_limb_t)u * di + (signed_double_limb_t)v * ei; |
327 | 0 | ce += (signed_double_limb_t)q * di + (signed_double_limb_t)r * ei; |
328 | 0 | d.limbs[i - 1] = (signed_limb_t)cd & MAX_SIGNED_LIMB; cd >>= SIGNED_LIMB_SIZE; |
329 | 0 | e.limbs[i - 1] = (signed_limb_t)ce & MAX_SIGNED_LIMB; ce >>= SIGNED_LIMB_SIZE; |
330 | 0 | } |
331 | | /* Compute limb SIGNED_LIMBS-1 of t*[d,e]+modulus*[md,me], and store it in output limb SIGNED_LIMBS-2. */ |
332 | 0 | di = d.limbs[SIGNED_LIMBS - 1]; |
333 | 0 | ei = e.limbs[SIGNED_LIMBS - 1]; |
334 | 0 | cd += (signed_double_limb_t)u * di + (signed_double_limb_t)v * ei; |
335 | 0 | ce += (signed_double_limb_t)q * di + (signed_double_limb_t)r * ei; |
336 | 0 | cd += (signed_double_limb_t)md << FINAL_LIMB_MODULUS_BITS; |
337 | 0 | ce += (signed_double_limb_t)me << FINAL_LIMB_MODULUS_BITS; |
338 | 0 | d.limbs[SIGNED_LIMBS - 2] = (signed_limb_t)cd & MAX_SIGNED_LIMB; cd >>= SIGNED_LIMB_SIZE; |
339 | 0 | e.limbs[SIGNED_LIMBS - 2] = (signed_limb_t)ce & MAX_SIGNED_LIMB; ce >>= SIGNED_LIMB_SIZE; |
340 | | /* What remains goes into output limb SINGED_LIMBS-1 */ |
341 | 0 | d.limbs[SIGNED_LIMBS - 1] = (signed_limb_t)cd; |
342 | 0 | e.limbs[SIGNED_LIMBS - 1] = (signed_limb_t)ce; |
343 | 0 | } |
344 | | |
345 | | /** Apply matrix t/2^SIGNED_LIMB_SIZE to vector (f,g). |
346 | | * |
347 | | * The matrix t must be chosen such that t*(f,g) results in multiples of 2^SIGNED_LIMB_SIZE. |
348 | | * This is the case for matrices computed by ComputeDivstepMatrix(). |
349 | | */ |
350 | | inline void UpdateFG(Num3072Signed& f, Num3072Signed& g, const SignedMatrix& t, int len) |
351 | 0 | { |
352 | 0 | const signed_limb_t u = t.u, v=t.v, q=t.q, r=t.r; |
353 | |
|
354 | 0 | signed_limb_t fi, gi; |
355 | 0 | signed_double_limb_t cf, cg; |
356 | | /* Start computing t*[f,g]. */ |
357 | 0 | fi = f.limbs[0]; |
358 | 0 | gi = g.limbs[0]; |
359 | 0 | cf = (signed_double_limb_t)u * fi + (signed_double_limb_t)v * gi; |
360 | 0 | cg = (signed_double_limb_t)q * fi + (signed_double_limb_t)r * gi; |
361 | | /* Verify that the bottom SIGNED_LIMB_BITS bits of the result are zero, and then throw them away. */ |
362 | 0 | Assume((cf & MAX_SIGNED_LIMB) == 0); Line | Count | Source | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) |
|
363 | 0 | Assume((cg & MAX_SIGNED_LIMB) == 0); Line | Count | Source | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) |
|
364 | 0 | cf >>= SIGNED_LIMB_SIZE; |
365 | 0 | cg >>= SIGNED_LIMB_SIZE; |
366 | | /* Now iteratively compute limb i=1..SIGNED_LIMBS-1 of t*[f,g], and store them in output limb i-1 (shifting |
367 | | * down by SIGNED_LIMB_BITS bits). */ |
368 | 0 | for (int i = 1; i < len; ++i) { |
369 | 0 | fi = f.limbs[i]; |
370 | 0 | gi = g.limbs[i]; |
371 | 0 | cf += (signed_double_limb_t)u * fi + (signed_double_limb_t)v * gi; |
372 | 0 | cg += (signed_double_limb_t)q * fi + (signed_double_limb_t)r * gi; |
373 | 0 | f.limbs[i - 1] = (signed_limb_t)cf & MAX_SIGNED_LIMB; cf >>= SIGNED_LIMB_SIZE; |
374 | 0 | g.limbs[i - 1] = (signed_limb_t)cg & MAX_SIGNED_LIMB; cg >>= SIGNED_LIMB_SIZE; |
375 | 0 | } |
376 | | /* What remains is limb SIGNED_LIMBS of t*[f,g]; store it as output limb SIGNED_LIMBS-1. */ |
377 | 0 | f.limbs[len - 1] = (signed_limb_t)cf; |
378 | 0 | g.limbs[len - 1] = (signed_limb_t)cg; |
379 | |
|
380 | 0 | } |
381 | | } // namespace |
382 | | |
383 | | Num3072 Num3072::GetInverse() const |
384 | 0 | { |
385 | | // Compute a modular inverse based on a variant of the safegcd algorithm: |
386 | | // - Paper: https://gcd.cr.yp.to/papers.html |
387 | | // - Inspired by this code in libsecp256k1: |
388 | | // https://github.com/bitcoin-core/secp256k1/blob/master/src/modinv32_impl.h |
389 | | // - Explanation of the algorithm: |
390 | | // https://github.com/bitcoin-core/secp256k1/blob/master/doc/safegcd_implementation.md |
391 | | |
392 | | // Local variables d, e, f, g: |
393 | | // - f and g are the variables whose gcd we compute (despite knowing the answer is 1): |
394 | | // - f is always odd, and initialized as modulus |
395 | | // - g is initialized as *this (called x in what follows) |
396 | | // - d and e are the numbers for which at every step it is the case that: |
397 | | // - f = d * x mod modulus; d is initialized as 0 |
398 | | // - g = e * x mod modulus; e is initialized as 1 |
399 | 0 | Num3072Signed d, e, f, g; |
400 | 0 | e.limbs[0] = 1; |
401 | | // F is initialized as modulus, which in signed limb representation can be expressed |
402 | | // simply as 2^3072 + -MAX_PRIME_DIFF. |
403 | 0 | f.limbs[0] = -MAX_PRIME_DIFF; |
404 | 0 | f.limbs[FINAL_LIMB_POSITION] = ((limb_t)1) << FINAL_LIMB_MODULUS_BITS; |
405 | 0 | g.FromNum3072(*this); |
406 | 0 | int len = SIGNED_LIMBS; //!< The number of significant limbs in f and g |
407 | 0 | signed_limb_t eta = -1; //!< State to track knowledge about ratio of f and g |
408 | | // Perform divsteps on [f,g] until g=0 is reached, keeping (d,e) synchronized with them. |
409 | 0 | while (true) { |
410 | | // Compute transformation matrix t that represents the next SIGNED_LIMB_SIZE divsteps |
411 | | // to apply. This can be computed from just the bottom limb of f and g, and eta. |
412 | 0 | SignedMatrix t; |
413 | 0 | eta = ComputeDivstepMatrix(eta, f.limbs[0], g.limbs[0], t); |
414 | | // Apply that transformation matrix to the full [f,g] vector. |
415 | 0 | UpdateFG(f, g, t, len); |
416 | | // Apply that transformation matrix to the full [d,e] vector (mod modulus). |
417 | 0 | UpdateDE(d, e, t); |
418 | | |
419 | | // Check if g is zero. |
420 | 0 | if (g.limbs[0] == 0) { |
421 | 0 | signed_limb_t cond = 0; |
422 | 0 | for (int j = 1; j < len; ++j) { |
423 | 0 | cond |= g.limbs[j]; |
424 | 0 | } |
425 | | // If so, we're done. |
426 | 0 | if (cond == 0) break; |
427 | 0 | } |
428 | | |
429 | | // Check if the top limbs of both f and g are both 0 or -1. |
430 | 0 | signed_limb_t fn = f.limbs[len - 1], gn = g.limbs[len - 1]; |
431 | 0 | signed_limb_t cond = ((signed_limb_t)len - 2) >> (LIMB_SIZE - 1); |
432 | 0 | cond |= fn ^ (fn >> (LIMB_SIZE - 1)); |
433 | 0 | cond |= gn ^ (gn >> (LIMB_SIZE - 1)); |
434 | 0 | if (cond == 0) { |
435 | | // If so, drop the top limb, shrinking the size of f and g, by |
436 | | // propagating the sign to the previous limb. |
437 | 0 | f.limbs[len - 2] |= (limb_t)f.limbs[len - 1] << SIGNED_LIMB_SIZE; |
438 | 0 | g.limbs[len - 2] |= (limb_t)g.limbs[len - 1] << SIGNED_LIMB_SIZE; |
439 | 0 | --len; |
440 | 0 | } |
441 | 0 | } |
442 | | // At some point, [f,g] will have been rewritten into [f',0], such that gcd(f,g) = gcd(f',0). |
443 | | // This is proven in the paper. As f started out being modulus, a prime number, we know that |
444 | | // gcd is 1, and thus f' is 1 or -1. |
445 | 0 | Assume((f.limbs[0] & MAX_SIGNED_LIMB) == 1 || (f.limbs[0] & MAX_SIGNED_LIMB) == MAX_SIGNED_LIMB); Line | Count | Source | 118 | 0 | #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) |
|
446 | | // As we've maintained the invariant that f = d * x mod modulus, we get d/f mod modulus is the |
447 | | // modular inverse of x we're looking for. As f is 1 or -1, it is also true that d/f = d*f. |
448 | | // Normalize d to prepare it for output, while negating it if f is negative. |
449 | 0 | d.Normalize(f.limbs[len - 1] >> (LIMB_SIZE - 1)); |
450 | 0 | Num3072 ret; |
451 | 0 | d.ToNum3072(ret); |
452 | 0 | return ret; |
453 | 0 | } |
454 | | |
455 | | void Num3072::Multiply(const Num3072& a) |
456 | 0 | { |
457 | 0 | limb_t c0 = 0, c1 = 0, c2 = 0; |
458 | 0 | Num3072 tmp; |
459 | | |
460 | | /* Compute limbs 0..N-2 of this*a into tmp, including one reduction. */ |
461 | 0 | for (int j = 0; j < LIMBS - 1; ++j) { |
462 | 0 | limb_t d0 = 0, d1 = 0, d2 = 0; |
463 | 0 | mul(d0, d1, this->limbs[1 + j], a.limbs[LIMBS + j - (1 + j)]); |
464 | 0 | for (int i = 2 + j; i < LIMBS; ++i) muladd3(d0, d1, d2, this->limbs[i], a.limbs[LIMBS + j - i]); |
465 | 0 | mulnadd3(c0, c1, c2, d0, d1, d2, MAX_PRIME_DIFF); |
466 | 0 | for (int i = 0; i < j + 1; ++i) muladd3(c0, c1, c2, this->limbs[i], a.limbs[j - i]); |
467 | 0 | extract3(c0, c1, c2, tmp.limbs[j]); |
468 | 0 | } |
469 | | |
470 | | /* Compute limb N-1 of a*b into tmp. */ |
471 | 0 | assert(c2 == 0); |
472 | 0 | for (int i = 0; i < LIMBS; ++i) muladd3(c0, c1, c2, this->limbs[i], a.limbs[LIMBS - 1 - i]); |
473 | 0 | extract3(c0, c1, c2, tmp.limbs[LIMBS - 1]); |
474 | | |
475 | | /* Perform a second reduction. */ |
476 | 0 | muln2(c0, c1, MAX_PRIME_DIFF); |
477 | 0 | for (int j = 0; j < LIMBS; ++j) { |
478 | 0 | addnextract2(c0, c1, tmp.limbs[j], this->limbs[j]); |
479 | 0 | } |
480 | |
|
481 | 0 | assert(c1 == 0); |
482 | 0 | assert(c0 == 0 || c0 == 1); |
483 | | |
484 | | /* Perform up to two more reductions if the internal state has already |
485 | | * overflown the MAX of Num3072 or if it is larger than the modulus or |
486 | | * if both are the case. |
487 | | * */ |
488 | 0 | if (this->IsOverflow()) this->FullReduce(); |
489 | 0 | if (c0) this->FullReduce(); |
490 | 0 | } |
491 | | |
492 | | void Num3072::SetToOne() |
493 | 0 | { |
494 | 0 | this->limbs[0] = 1; |
495 | 0 | for (int i = 1; i < LIMBS; ++i) this->limbs[i] = 0; |
496 | 0 | } |
497 | | |
498 | | void Num3072::Divide(const Num3072& a) |
499 | 0 | { |
500 | 0 | if (this->IsOverflow()) this->FullReduce(); |
501 | |
|
502 | 0 | Num3072 inv{}; |
503 | 0 | if (a.IsOverflow()) { |
504 | 0 | Num3072 b = a; |
505 | 0 | b.FullReduce(); |
506 | 0 | inv = b.GetInverse(); |
507 | 0 | } else { |
508 | 0 | inv = a.GetInverse(); |
509 | 0 | } |
510 | |
|
511 | 0 | this->Multiply(inv); |
512 | 0 | if (this->IsOverflow()) this->FullReduce(); |
513 | 0 | } |
514 | | |
515 | 0 | Num3072::Num3072(const unsigned char (&data)[BYTE_SIZE]) { |
516 | 0 | for (int i = 0; i < LIMBS; ++i) { |
517 | 0 | if (sizeof(limb_t) == 4) { |
518 | 0 | this->limbs[i] = ReadLE32(data + 4 * i); |
519 | 0 | } else if (sizeof(limb_t) == 8) { |
520 | 0 | this->limbs[i] = ReadLE64(data + 8 * i); |
521 | 0 | } |
522 | 0 | } |
523 | 0 | } |
524 | | |
525 | 0 | void Num3072::ToBytes(unsigned char (&out)[BYTE_SIZE]) { |
526 | 0 | for (int i = 0; i < LIMBS; ++i) { |
527 | 0 | if (sizeof(limb_t) == 4) { |
528 | 0 | WriteLE32(out + i * 4, this->limbs[i]); |
529 | 0 | } else if (sizeof(limb_t) == 8) { |
530 | 0 | WriteLE64(out + i * 8, this->limbs[i]); |
531 | 0 | } |
532 | 0 | } |
533 | 0 | } |
534 | | |
535 | 0 | Num3072 MuHash3072::ToNum3072(std::span<const unsigned char> in) { |
536 | 0 | unsigned char tmp[Num3072::BYTE_SIZE]; |
537 | |
|
538 | 0 | uint256 hashed_in{(HashWriter{} << in).GetSHA256()}; |
539 | 0 | static_assert(sizeof(tmp) % ChaCha20Aligned::BLOCKLEN == 0); |
540 | 0 | ChaCha20Aligned{MakeByteSpan(hashed_in)}.Keystream(MakeWritableByteSpan(tmp)); |
541 | 0 | Num3072 out{tmp}; |
542 | |
|
543 | 0 | return out; |
544 | 0 | } |
545 | | |
546 | | MuHash3072::MuHash3072(std::span<const unsigned char> in) noexcept |
547 | 0 | { |
548 | 0 | m_numerator = ToNum3072(in); |
549 | 0 | } |
550 | | |
551 | | void MuHash3072::Finalize(uint256& out) noexcept |
552 | 0 | { |
553 | 0 | m_numerator.Divide(m_denominator); |
554 | 0 | m_denominator.SetToOne(); // Needed to keep the MuHash object valid |
555 | |
|
556 | 0 | unsigned char data[Num3072::BYTE_SIZE]; |
557 | 0 | m_numerator.ToBytes(data); |
558 | |
|
559 | 0 | out = (HashWriter{} << data).GetSHA256(); |
560 | 0 | } |
561 | | |
562 | | MuHash3072& MuHash3072::operator*=(const MuHash3072& mul) noexcept |
563 | 0 | { |
564 | 0 | m_numerator.Multiply(mul.m_numerator); |
565 | 0 | m_denominator.Multiply(mul.m_denominator); |
566 | 0 | return *this; |
567 | 0 | } |
568 | | |
569 | | MuHash3072& MuHash3072::operator/=(const MuHash3072& div) noexcept |
570 | 0 | { |
571 | 0 | m_numerator.Multiply(div.m_denominator); |
572 | 0 | m_denominator.Multiply(div.m_numerator); |
573 | 0 | return *this; |
574 | 0 | } |
575 | | |
576 | 0 | MuHash3072& MuHash3072::Insert(std::span<const unsigned char> in) noexcept { |
577 | 0 | m_numerator.Multiply(ToNum3072(in)); |
578 | 0 | return *this; |
579 | 0 | } |
580 | | |
581 | 0 | MuHash3072& MuHash3072::Remove(std::span<const unsigned char> in) noexcept { |
582 | 0 | m_denominator.Multiply(ToNum3072(in)); |
583 | 0 | return *this; |
584 | 0 | } |