fuzz coverage

Coverage Report

Created: 2025-06-01 19:34

/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
}