Coverage Report

Created: 2025-04-24 07:09

/src/cryptofuzz/modules/blst/module.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "module.h"
2
#include <cryptofuzz/util.h>
3
#include <cryptofuzz/repository.h>
4
#include <fuzzing/datasource/id.hpp>
5
#include <boost/multiprecision/cpp_int.hpp>
6
7
extern "C" {
8
#include <blst.h>
9
}
10
11
namespace cryptofuzz {
12
namespace module {
13
14
blst::blst(void) :
15
4
    Module("blst") {
16
4
}
17
18
namespace blst_detail {
19
    template <size_t Size>
20
342k
    void Reverse(std::array<uint8_t, Size>& v) {
21
342k
        std::reverse(v.begin(), v.end());
22
342k
    }
void cryptofuzz::module::blst_detail::Reverse<32ul>(std::__1::array<unsigned char, 32ul>&)
Line
Count
Source
20
10.7k
    void Reverse(std::array<uint8_t, Size>& v) {
21
10.7k
        std::reverse(v.begin(), v.end());
22
10.7k
    }
void cryptofuzz::module::blst_detail::Reverse<48ul>(std::__1::array<unsigned char, 48ul>&)
Line
Count
Source
20
332k
    void Reverse(std::array<uint8_t, Size>& v) {
21
332k
        std::reverse(v.begin(), v.end());
22
332k
    }
23
24
    template <size_t Size>
25
278k
    std::optional<std::array<uint8_t, Size>> ToArray(const component::Bignum& bn, const bool reverse = true) {
26
278k
        const auto _ret = util::DecToBin(bn.ToTrimmedString(), Size);
27
278k
        if ( _ret == std::nullopt ) {
28
3.55k
            return std::nullopt;
29
3.55k
        }
30
31
274k
        std::array<uint8_t, Size> ret;
32
274k
        memcpy(ret.data(), _ret->data(), Size);
33
274k
        if ( reverse == true ) {
34
273k
            Reverse<>(ret);
35
273k
        }
36
37
274k
        return ret;
38
278k
    }
std::__1::optional<std::__1::array<unsigned char, 32ul> > cryptofuzz::module::blst_detail::ToArray<32ul>(cryptofuzz::Bignum const&, bool)
Line
Count
Source
25
9.00k
    std::optional<std::array<uint8_t, Size>> ToArray(const component::Bignum& bn, const bool reverse = true) {
26
9.00k
        const auto _ret = util::DecToBin(bn.ToTrimmedString(), Size);
27
9.00k
        if ( _ret == std::nullopt ) {
28
427
            return std::nullopt;
29
427
        }
30
31
8.57k
        std::array<uint8_t, Size> ret;
32
8.57k
        memcpy(ret.data(), _ret->data(), Size);
33
8.57k
        if ( reverse == true ) {
34
8.57k
            Reverse<>(ret);
35
8.57k
        }
36
37
8.57k
        return ret;
38
9.00k
    }
std::__1::optional<std::__1::array<unsigned char, 48ul> > cryptofuzz::module::blst_detail::ToArray<48ul>(cryptofuzz::Bignum const&, bool)
Line
Count
Source
25
269k
    std::optional<std::array<uint8_t, Size>> ToArray(const component::Bignum& bn, const bool reverse = true) {
26
269k
        const auto _ret = util::DecToBin(bn.ToTrimmedString(), Size);
27
269k
        if ( _ret == std::nullopt ) {
28
3.12k
            return std::nullopt;
29
3.12k
        }
30
31
266k
        std::array<uint8_t, Size> ret;
32
266k
        memcpy(ret.data(), _ret->data(), Size);
33
266k
        if ( reverse == true ) {
34
265k
            Reverse<>(ret);
35
265k
        }
36
37
266k
        return ret;
38
269k
    }
39
4.09k
    bool To_blst_fr(const component::Bignum& bn, blst_fr& out) {
40
4.09k
        const auto ret = ToArray<32>(bn);
41
42
4.09k
        if ( ret == std::nullopt ) {
43
336
            return false;
44
336
        }
45
46
3.75k
        CF_NORET(blst_fr_from_uint64(&out, (const uint64_t*)ret->data()));
47
3.75k
        return true;
48
4.09k
    }
49
268k
    bool To_blst_fp(const component::Bignum& bn, blst_fp& out) {
50
268k
        const auto ret = ToArray<48>(bn);
51
52
268k
        if ( ret == std::nullopt ) {
53
3.05k
            return false;
54
3.05k
        }
55
56
265k
        CF_NORET(blst_fp_from_uint64(&out, (const uint64_t*)ret->data()));
57
265k
        return true;
58
268k
    }
59
2.34k
    bool To_blst_fp2(const component::Fp2& bn, blst_fp2& out) {
60
2.34k
        return  To_blst_fp(bn.first, out.fp[0]) &&
61
2.34k
                To_blst_fp(bn.second, out.fp[1]);
62
2.34k
    }
63
1.67k
    bool To_blst_fp12(const component::Fp12& bn, blst_fp12& out) {
64
1.67k
        return  To_blst_fp(bn.bn1, out.fp6[0].fp2[0].fp[0]) &&
65
1.67k
                To_blst_fp(bn.bn2, out.fp6[0].fp2[0].fp[1]) &&
66
1.67k
                To_blst_fp(bn.bn3, out.fp6[0].fp2[1].fp[0]) &&
67
1.67k
                To_blst_fp(bn.bn4, out.fp6[0].fp2[1].fp[1]) &&
68
1.67k
                To_blst_fp(bn.bn5, out.fp6[0].fp2[2].fp[0]) &&
69
1.67k
                To_blst_fp(bn.bn6, out.fp6[0].fp2[2].fp[1]) &&
70
71
1.67k
                To_blst_fp(bn.bn7, out.fp6[1].fp2[0].fp[0]) &&
72
1.67k
                To_blst_fp(bn.bn8, out.fp6[1].fp2[0].fp[1]) &&
73
1.67k
                To_blst_fp(bn.bn9, out.fp6[1].fp2[1].fp[0]) &&
74
1.67k
                To_blst_fp(bn.bn10, out.fp6[1].fp2[1].fp[1]) &&
75
1.67k
                To_blst_fp(bn.bn11, out.fp6[1].fp2[2].fp[0]) &&
76
1.67k
                To_blst_fp(bn.bn12, out.fp6[1].fp2[2].fp[1]);
77
1.67k
    }
78
2.05k
    component::Bignum To_component_bignum(const blst_fr& in) {
79
2.05k
        std::array<uint8_t, 32> v;
80
81
2.05k
        blst_uint64_from_fr((uint64_t*)v.data(), &in);
82
83
2.05k
        Reverse<>(v);
84
2.05k
        return util::BinToDec(v.data(), 32);
85
2.05k
    }
86
1.88k
    component::Bignum To_component_bignum(const blst_fp& in) {
87
1.88k
        std::array<uint8_t, 48> v;
88
89
1.88k
        blst_uint64_from_fp((uint64_t*)v.data(), &in);
90
91
1.88k
        Reverse<>(v);
92
1.88k
        return util::BinToDec(v.data(), 48);
93
1.88k
    }
94
770
    component::Fp2 To_component_Fp2(const blst_fp2& in) {
95
770
        std::array<uint8_t, 48> v1, v2;
96
97
770
        blst_uint64_from_fp((uint64_t*)v1.data(), &in.fp[0]);
98
770
        Reverse<>(v1);
99
100
770
        blst_uint64_from_fp((uint64_t*)v2.data(), &in.fp[1]);
101
770
        Reverse<>(v2);
102
103
770
        return {
104
770
            util::BinToDec(v1.data(), 48),
105
770
            util::BinToDec(v2.data(), 48),
106
770
        };
107
770
    }
108
858
    boost::multiprecision::cpp_int To_cpp_int(const component::Bignum& in) {
109
858
        return boost::multiprecision::cpp_int(in.ToTrimmedString());
110
858
    }
111
112
    class G1 {
113
        private:
114
            fuzzing::datasource::Datasource& ds;
115
            blst_p1_affine g1;
116
        public:
117
            G1(const blst_p1_affine& g1, fuzzing::datasource::Datasource& ds) :
118
7.53k
                ds(ds) {
119
7.53k
                memcpy(&this->g1, &g1, sizeof(g1));
120
7.53k
            }
121
7.53k
            const blst_p1_affine* Get(void) {
122
7.53k
                return &g1;
123
7.53k
            }
124
7.53k
            component::G1 To_Component_G1(void) {
125
7.53k
                std::array<uint8_t, 48> x, y;
126
127
7.53k
                const blst_p1_affine* ptr = Get();
128
129
7.53k
                blst_uint64_from_fp((uint64_t*)x.data(), &ptr->x);
130
7.53k
                blst_uint64_from_fp((uint64_t*)y.data(), &ptr->y);
131
132
7.53k
                Reverse<>(x);
133
7.53k
                Reverse<>(y);
134
135
7.53k
                return {util::BinToDec(x.data(), 48), util::BinToDec(y.data(), 48)};
136
7.53k
            }
137
    };
138
8.90k
    component::G2 To_G2(const blst_p2_affine& g2) {
139
8.90k
        std::array<uint8_t, 48> x1, y1, x2, y2;
140
141
8.90k
        blst_uint64_from_fp((uint64_t*)x1.data(), &g2.x.fp[0]);
142
8.90k
        blst_uint64_from_fp((uint64_t*)y1.data(), &g2.y.fp[0]);
143
8.90k
        blst_uint64_from_fp((uint64_t*)x2.data(), &g2.x.fp[1]);
144
8.90k
        blst_uint64_from_fp((uint64_t*)y2.data(), &g2.y.fp[1]);
145
146
8.90k
        Reverse<>(x1);
147
8.90k
        Reverse<>(y1);
148
8.90k
        Reverse<>(x2);
149
8.90k
        Reverse<>(y2);
150
151
8.90k
        return {
152
8.90k
            util::BinToDec(x1.data(), 48),
153
8.90k
            util::BinToDec(y1.data(), 48),
154
8.90k
            util::BinToDec(x2.data(), 48),
155
8.90k
            util::BinToDec(y2.data(), 48)
156
8.90k
        };
157
8.90k
    }
158
159
1.04k
    component::Fp12 To_component_Fp12(const blst_fp12& fp12) {
160
1.04k
        std::array<uint8_t, 48> bn1, bn2, bn3, bn4, bn5, bn6, bn7, bn8, bn9, bn10, bn11, bn12;
161
162
1.04k
        blst_uint64_from_fp((uint64_t*)bn1.data(), &fp12.fp6[0].fp2[0].fp[0]);
163
1.04k
        Reverse<>(bn1);
164
165
1.04k
        blst_uint64_from_fp((uint64_t*)bn2.data(), &fp12.fp6[0].fp2[0].fp[1]);
166
1.04k
        Reverse<>(bn2);
167
168
1.04k
        blst_uint64_from_fp((uint64_t*)bn3.data(), &fp12.fp6[0].fp2[1].fp[0]);
169
1.04k
        Reverse<>(bn3);
170
171
1.04k
        blst_uint64_from_fp((uint64_t*)bn4.data(), &fp12.fp6[0].fp2[1].fp[1]);
172
1.04k
        Reverse<>(bn4);
173
174
1.04k
        blst_uint64_from_fp((uint64_t*)bn5.data(), &fp12.fp6[0].fp2[2].fp[0]);
175
1.04k
        Reverse<>(bn5);
176
177
1.04k
        blst_uint64_from_fp((uint64_t*)bn6.data(), &fp12.fp6[0].fp2[2].fp[1]);
178
1.04k
        Reverse<>(bn6);
179
180
1.04k
        blst_uint64_from_fp((uint64_t*)bn7.data(), &fp12.fp6[1].fp2[0].fp[0]);
181
1.04k
        Reverse<>(bn7);
182
183
1.04k
        blst_uint64_from_fp((uint64_t*)bn8.data(), &fp12.fp6[1].fp2[0].fp[1]);
184
1.04k
        Reverse<>(bn8);
185
186
1.04k
        blst_uint64_from_fp((uint64_t*)bn9.data(), &fp12.fp6[1].fp2[1].fp[0]);
187
1.04k
        Reverse<>(bn9);
188
189
1.04k
        blst_uint64_from_fp((uint64_t*)bn10.data(), &fp12.fp6[1].fp2[1].fp[1]);
190
1.04k
        Reverse<>(bn10);
191
192
1.04k
        blst_uint64_from_fp((uint64_t*)bn11.data(), &fp12.fp6[1].fp2[2].fp[0]);
193
1.04k
        Reverse<>(bn11);
194
195
1.04k
        blst_uint64_from_fp((uint64_t*)bn12.data(), &fp12.fp6[1].fp2[2].fp[1]);
196
1.04k
        Reverse<>(bn12);
197
198
1.04k
        return {
199
1.04k
            util::BinToDec(bn1.data(), 48),
200
1.04k
            util::BinToDec(bn2.data(), 48),
201
1.04k
            util::BinToDec(bn3.data(), 48),
202
1.04k
            util::BinToDec(bn4.data(), 48),
203
1.04k
            util::BinToDec(bn5.data(), 48),
204
1.04k
            util::BinToDec(bn6.data(), 48),
205
1.04k
            util::BinToDec(bn7.data(), 48),
206
1.04k
            util::BinToDec(bn8.data(), 48),
207
1.04k
            util::BinToDec(bn9.data(), 48),
208
1.04k
            util::BinToDec(bn10.data(), 48),
209
1.04k
            util::BinToDec(bn11.data(), 48),
210
1.04k
            util::BinToDec(bn12.data(), 48),
211
1.04k
        };
212
1.04k
    }
213
214
4.90k
    bool To_blst_scalar(const component::Bignum& bn, blst_scalar& out) {
215
4.90k
        const auto ret = ToArray<32>(bn);
216
217
4.90k
        if ( ret == std::nullopt ) {
218
91
            return false;
219
91
        }
220
221
4.81k
        CF_NORET(blst_scalar_from_uint64(&out, (const uint64_t*)ret->data()));
222
223
4.81k
        return true;
224
4.90k
    }
225
0
    bool IsLessThan(const blst_fp& A, const blst_fp& B) {
226
0
        std::array<uint8_t, 48> A_words, B_words;
227
228
0
        uint64_t* A_ptr = (uint64_t*)A_words.data();
229
0
        uint64_t* B_ptr = (uint64_t*)B_words.data();
230
231
0
        blst_uint64_from_fp(A_ptr, &A);
232
0
        blst_uint64_from_fp(B_ptr, &B);
233
234
0
        for (int i = 5; i >= 0; i--) {
235
0
            if ( A_ptr[i] == B_ptr[i] ) {
236
0
                continue;
237
0
            }
238
0
            return A_ptr[i] < B_ptr[i];
239
0
        }
240
241
0
        return false;
242
0
    }
243
595
    static size_t isMultipleOf2(const std::string s) {
244
595
        auto i = boost::multiprecision::cpp_int(s);
245
595
        if ( i == 0 || i == 1 ) {
246
44
            return 0;
247
44
        }
248
551
        size_t num = 0;
249
18.5k
        while ( i ) {
250
18.3k
            if ( i != 1 && i & 1 ) {
251
324
                return 0;
252
324
            }
253
17.9k
            i >>= 1;
254
17.9k
            num++;
255
17.9k
        }
256
257
227
        return num - 1;
258
551
    }
259
2.60k
    static bool IsZero(const blst_p2_affine* g2) {
260
2.60k
        blst_p2_affine zero;
261
2.60k
        memset(&zero, 0, sizeof(zero));
262
2.60k
        return memcmp(g2, &zero, sizeof(zero)) == 0;
263
2.60k
    }
264
265
10.1k
    static std::optional<blst_p1_affine> Load_G1_Affine(const component::G1& g1) {
266
10.1k
        std::optional<blst_p1_affine> ret = std::nullopt;
267
268
10.1k
        blst_p1_affine aff_a;
269
270
10.1k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(g1.first, aff_a.x));
271
10.0k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(g1.second, aff_a.y));
272
273
9.93k
        ret = aff_a;
274
10.1k
end:
275
10.1k
        return ret;
276
9.93k
    }
277
278
    static std::optional<blst_p1> Load_G1_Projective(
279
            fuzzing::datasource::Datasource& ds,
280
14.0k
            const component::G1& g1) {
281
14.0k
        std::optional<blst_p1> ret = std::nullopt;
282
283
14.0k
        blst_p1 a;
284
285
14.0k
        const auto proj = util::ToRandomProjective(
286
14.0k
                ds,
287
14.0k
                g1.first.ToTrimmedString(),
288
14.0k
                g1.second.ToTrimmedString(),
289
14.0k
                CF_ECC_CURVE("BLS12_381"));
290
291
14.0k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(proj[0], a.x));
292
13.9k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(proj[1], a.y));
293
13.9k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(proj[2], a.z));
294
295
13.9k
        ret = a;
296
14.0k
end:
297
14.0k
        return ret;
298
13.9k
    }
299
}
300
301
3.21k
std::optional<component::BLS_PublicKey> blst::OpBLS_PrivateToPublic(operation::BLS_PrivateToPublic& op) {
302
3.21k
    if ( op.curveType.Get() != CF_ECC_CURVE("BLS12_381") ) {
303
        //return std::nullopt;
304
0
    }
305
306
3.21k
    std::optional<component::BLS_PublicKey> ret = std::nullopt;
307
3.21k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
308
309
3.21k
    blst_scalar priv;
310
3.21k
    blst_p1 pub;
311
3.21k
    blst_p1_affine pub_affine;
312
313
3.21k
    CF_CHECK_TRUE(blst_detail::To_blst_scalar(op.priv, priv));
314
315
    /* blst_sk_to_pk_in_g1 does not reduce the private key,
316
     * so check if it's valid first
317
     */
318
3.18k
    CF_CHECK_TRUE(blst_sk_check(&priv));
319
320
3.04k
    CF_NORET(blst_sk_to_pk_in_g1(&pub, &priv));
321
3.04k
    CF_ASSERT(blst_p1_on_curve(&pub) == true, "Generated pubkey not on curve");
322
3.04k
    CF_ASSERT(blst_p1_in_g1(&pub) == true, "Generated pubkey not in group");
323
324
3.04k
    CF_NORET(blst_p1_to_affine(&pub_affine, &pub));
325
326
3.04k
    {
327
3.04k
        blst_detail::G1 g1(pub_affine, ds);
328
3.04k
        ret = g1.To_Component_G1();
329
3.04k
    }
330
331
3.21k
end:
332
3.21k
    return ret;
333
3.04k
}
334
335
770
std::optional<component::G2> blst::OpBLS_PrivateToPublic_G2(operation::BLS_PrivateToPublic_G2& op) {
336
770
    if ( op.curveType.Get() != CF_ECC_CURVE("BLS12_381") ) {
337
        //return std::nullopt;
338
418
    }
339
340
770
    std::optional<component::G2> ret = std::nullopt;
341
770
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
342
343
770
    blst_scalar priv;
344
770
    blst_p2 pub;
345
770
    blst_p2_affine pub_affine;
346
347
770
    CF_CHECK_TRUE(blst_detail::To_blst_scalar(op.priv, priv));
348
349
    /* blst_sk_to_pk_in_g2 does not reduce the private key,
350
     * so check if it's valid first
351
     */
352
731
    CF_CHECK_TRUE(blst_sk_check(&priv));
353
354
659
    CF_NORET(blst_sk_to_pk_in_g2(&pub, &priv));
355
659
    CF_ASSERT(blst_p2_on_curve(&pub) == true, "Generated pubkey not on curve");
356
659
    CF_ASSERT(blst_p2_in_g2(&pub) == true, "Generated pubkey not in group");
357
358
659
    CF_NORET(blst_p2_to_affine(&pub_affine, &pub));
359
360
659
    ret = blst_detail::To_G2(pub_affine);
361
362
770
end:
363
770
    return ret;
364
659
}
365
366
214
std::optional<component::G1> blst::OpBLS_HashToG1(operation::BLS_HashToG1& op) {
367
214
    if ( op.curveType.Get() != CF_ECC_CURVE("BLS12_381") ) {
368
        //return std::nullopt;
369
0
    }
370
371
214
    std::optional<component::G1> ret = std::nullopt;
372
214
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
373
374
214
    blst_p1 g1;
375
214
    blst_p1_affine g1_affine;
376
377
214
    CF_NORET(blst_hash_to_g1(
378
214
            &g1,
379
214
            op.cleartext.GetPtr(&ds), op.cleartext.GetSize(),
380
214
            op.dest.GetPtr(&ds), op.dest.GetSize(),
381
214
            op.aug.GetPtr(&ds), op.aug.GetSize()));
382
383
214
    CF_ASSERT(blst_p1_on_curve(&g1) == true, "Generated g1 not on curve");
384
214
    CF_ASSERT(blst_p1_in_g1(&g1) == true, "Generated g1 not in group");
385
386
214
    CF_NORET(blst_p1_to_affine(&g1_affine, &g1));
387
388
214
    {
389
214
        blst_detail::G1 _g1(g1_affine, ds);
390
214
        ret = _g1.To_Component_G1();
391
214
    }
392
393
214
    return ret;
394
214
}
395
396
228
std::optional<component::G2> blst::OpBLS_HashToG2(operation::BLS_HashToG2& op) {
397
228
    if ( op.curveType.Get() != CF_ECC_CURVE("BLS12_381") ) {
398
        //return std::nullopt;
399
0
    }
400
401
228
    std::optional<component::G2> ret = std::nullopt;
402
228
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
403
404
228
    blst_p2 g2;
405
228
    blst_p2_affine g2_affine;
406
407
228
    CF_NORET(blst_hash_to_g2(
408
228
            &g2,
409
228
            op.cleartext.GetPtr(&ds), op.cleartext.GetSize(),
410
228
            op.dest.GetPtr(&ds), op.dest.GetSize(),
411
228
            op.aug.GetPtr(&ds), op.aug.GetSize()));
412
413
228
    CF_ASSERT(blst_p2_on_curve(&g2) == true, "Generated g2 not on curve");
414
228
    CF_ASSERT(blst_p2_in_g2(&g2) == true, "Generated g2 not in group");
415
416
228
    CF_NORET(blst_p2_to_affine(&g2_affine, &g2));
417
418
228
    ret = blst_detail::To_G2(g2_affine);
419
420
228
    return ret;
421
228
}
422
423
305
std::optional<component::G1> blst::OpBLS_MapToG1(operation::BLS_MapToG1& op) {
424
305
    if ( op.curveType.Get() != CF_ECC_CURVE("BLS12_381") ) {
425
        //return std::nullopt;
426
110
    }
427
428
305
    std::optional<component::G1> ret = std::nullopt;
429
305
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
430
431
305
    blst_p1 g1;
432
305
    blst_p1_affine g1_affine;
433
305
    blst_fp u, v;
434
435
305
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.u, u));
436
283
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.v, v));
437
438
261
    CF_NORET(blst_map_to_g1(&g1, &u, &v));
439
440
261
    CF_ASSERT(blst_p1_on_curve(&g1) == true, "Generated g1 not on curve");
441
261
    CF_ASSERT(blst_p1_in_g1(&g1) == true, "Generated g1 not in group");
442
443
261
    CF_NORET(blst_p1_to_affine(&g1_affine, &g1));
444
445
261
    {
446
261
        blst_detail::G1 _g1(g1_affine, ds);
447
261
        ret = _g1.To_Component_G1();
448
261
    }
449
450
305
end:
451
305
    return ret;
452
261
}
453
454
319
std::optional<component::G2> blst::OpBLS_MapToG2(operation::BLS_MapToG2& op) {
455
319
    if ( op.curveType.Get() != CF_ECC_CURVE("BLS12_381") ) {
456
        //return std::nullopt;
457
182
    }
458
459
319
    std::optional<component::G2> ret = std::nullopt;
460
319
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
461
462
319
    blst_p2 g2;
463
319
    blst_p2_affine g2_affine;
464
319
    blst_fp2 u, v;
465
466
319
    CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.u, u));
467
279
    CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.v, v));
468
469
236
    CF_NORET(blst_map_to_g2(&g2, &u, &v));
470
471
236
    CF_ASSERT(blst_p2_on_curve(&g2) == true, "Generated g2 not on curve");
472
236
    CF_ASSERT(blst_p2_in_g2(&g2) == true, "Generated g2 not in group");
473
474
236
    CF_NORET(blst_p2_to_affine(&g2_affine, &g2));
475
476
236
    ret = blst_detail::To_G2(g2_affine);
477
478
319
end:
479
319
    return ret;
480
236
}
481
482
919
std::optional<component::BLS_Signature> blst::OpBLS_Sign(operation::BLS_Sign& op) {
483
919
    if ( op.curveType.Get() != CF_ECC_CURVE("BLS12_381") ) {
484
        //return std::nullopt;
485
634
    }
486
487
919
    std::optional<component::BLS_Signature> ret;
488
919
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
489
490
919
    blst_scalar priv;
491
919
    blst_p1 pub;
492
919
    blst_p1_affine pub_affine;
493
919
    blst_p2_affine hash_affine;
494
919
    blst_p2 hash;
495
919
    blst_p2 signature;
496
919
    blst_p2_affine signature_affine;
497
498
919
    CF_CHECK_TRUE(blst_detail::To_blst_scalar(op.priv, priv));
499
899
    CF_CHECK_TRUE(blst_sk_check(&priv));
500
501
857
    CF_NORET(blst_sk_to_pk_in_g1(&pub, &priv));
502
857
    CF_ASSERT(blst_p1_on_curve(&pub) == true, "Generated pubkey not on curve");
503
857
    CF_ASSERT(blst_p1_in_g1(&pub) == true, "Generated pubkey not in group");
504
857
    CF_NORET(blst_p1_to_affine(&pub_affine, &pub));
505
506
857
    if ( op.hashOrPoint == true ) {
507
642
        CF_NORET(blst_hash_to_g2(
508
642
                &hash,
509
642
                op.cleartext.GetPtr(&ds), op.cleartext.GetSize(),
510
642
                op.dest.GetPtr(&ds), op.dest.GetSize(),
511
642
                op.aug.GetPtr(&ds), op.aug.GetSize()));
512
642
    } else {
513
215
        CF_CHECK_TRUE(blst_detail::To_blst_fp(op.point.first.first, hash_affine.x.fp[0]));
514
195
        CF_CHECK_TRUE(blst_detail::To_blst_fp(op.point.first.second, hash_affine.y.fp[0]));
515
173
        CF_CHECK_TRUE(blst_detail::To_blst_fp(op.point.second.first, hash_affine.x.fp[1]));
516
153
        CF_CHECK_TRUE(blst_detail::To_blst_fp(op.point.second.second, hash_affine.y.fp[1]));
517
133
        CF_NORET(blst_p2_from_affine(&hash, &hash_affine));
518
133
    }
519
775
    CF_NORET(blst_sign_pk_in_g1(&signature, &hash, &priv));
520
521
775
    if ( op.hashOrPoint == true ) {
522
642
        CF_ASSERT(blst_p2_on_curve(&signature) == true, "Generated signature not on curve");
523
642
        CF_ASSERT(blst_p2_in_g2(&signature) == true, "Generated signature not in group");
524
642
    } else {
525
133
        if ( blst_p2_affine_on_curve(&hash_affine) ) {
526
87
            CF_ASSERT(blst_p2_on_curve(&signature) == true, "Generated signature not on curve");
527
87
        }
528
529
133
        if ( blst_p2_affine_in_g2(&hash_affine) ) {
530
87
            CF_ASSERT(blst_p2_in_g2(&signature) == true, "Generated signature not in group");
531
87
        }
532
133
    }
533
534
775
    CF_NORET(blst_p2_to_affine(&signature_affine, &signature));
535
536
775
    {
537
775
        blst_detail::G1 g1(pub_affine, ds);
538
775
        ret = {blst_detail::To_G2(signature_affine), g1.To_Component_G1()};
539
775
    }
540
541
775
    if ( op.hashOrPoint == true ) {
542
642
        if ( blst_core_verify_pk_in_g1(
543
642
                    &pub_affine, &signature_affine,
544
642
                    true,
545
642
                    op.cleartext.GetPtr(&ds), op.cleartext.GetSize(),
546
642
                    op.dest.GetPtr(&ds), op.dest.GetSize(),
547
642
                    op.aug.GetPtr(&ds), op.aug.GetSize()) != BLST_SUCCESS ) {
548
0
            abort();
549
0
        }
550
642
    }
551
552
919
end:
553
919
    return ret;
554
775
}
555
556
namespace blst_detail {
557
    std::optional<bool> Verify(
558
            Datasource& ds,
559
            const component::Cleartext& msg,
560
            const component::Cleartext& dst,
561
            const component::Cleartext& aug,
562
            const component::G1& pub,
563
            const component::G2& sig,
564
0
            const bool hashOrEncode) {
565
0
    std::optional<bool> ret = std::nullopt;
566
567
0
    blst_p1_affine pub_affine;
568
0
    blst_p2_affine sig_affine;
569
570
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(pub.first, pub_affine.x));
571
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(pub.second, pub_affine.y));
572
573
0
    if ( !(blst_p1_affine_on_curve(&pub_affine) && blst_p1_affine_in_g1(&pub_affine)) ) {
574
0
        return false;
575
0
    }
576
577
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(sig.first.first, sig_affine.x.fp[0]));
578
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(sig.first.second, sig_affine.y.fp[0]));
579
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(sig.second.first, sig_affine.x.fp[1]));
580
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(sig.second.second, sig_affine.y.fp[1]));
581
582
0
    if ( !(blst_p2_affine_on_curve(&sig_affine) && blst_p2_affine_in_g2(&sig_affine)) ) {
583
0
        return false;
584
0
    }
585
586
0
    ret = blst_core_verify_pk_in_g1(
587
0
                &pub_affine, &sig_affine,
588
0
                hashOrEncode,
589
0
                msg.GetPtr(&ds), msg.GetSize(),
590
0
                dst.GetPtr(&ds), dst.GetSize(),
591
0
                aug.GetPtr(&ds), aug.GetSize()) == BLST_SUCCESS;
592
593
0
end:
594
0
    return ret;
595
0
}
596
}
597
598
331
std::optional<bool> blst::OpBLS_Verify(operation::BLS_Verify& op) {
599
331
    if ( op.curveType.Get() != CF_ECC_CURVE("BLS12_381") ) {
600
        //return std::nullopt;
601
251
    }
602
331
    if ( op.hashOrPoint == false ) {
603
67
        return std::nullopt;
604
67
    }
605
606
264
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
607
608
264
    std::optional<bool> ret = std::nullopt;
609
610
264
    blst_p1_affine pub;
611
264
    blst_p2_affine sig;
612
613
264
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.pub.first, pub.x));
614
243
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.pub.second, pub.y));
615
616
222
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.signature.first.first, sig.x.fp[0]));
617
201
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.signature.first.second, sig.y.fp[0]));
618
181
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.signature.second.first, sig.x.fp[1]));
619
161
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.signature.second.second, sig.y.fp[1]));
620
621
141
    ret = blst_core_verify_pk_in_g1(
622
141
                &pub, &sig,
623
141
                true,
624
141
                op.cleartext.GetPtr(&ds), op.cleartext.GetSize(),
625
141
                op.dest.GetPtr(&ds), op.dest.GetSize(),
626
141
                nullptr, 0) == BLST_SUCCESS;
627
628
264
end:
629
264
    return ret;
630
141
}
631
632
1.62k
std::optional<bool> blst::OpBLS_BatchVerify(operation::BLS_BatchVerify& op) {
633
1.62k
    std::optional<bool> ret = std::nullopt;
634
635
1.62k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
636
637
1.62k
    const blst_fp12 one = *blst_fp12_one();
638
1.62k
    blst_fp12 f = *blst_fp12_one();
639
640
13.7k
    for (const auto& cur : op.bf.c) {
641
13.7k
            blst_p1_affine g1_affine;
642
13.7k
            blst_p2_affine g2_affine;
643
644
            /* Load G1 */
645
13.7k
            CF_CHECK_TRUE(blst_detail::To_blst_fp(cur.g1.first, g1_affine.x));
646
13.7k
            CF_CHECK_TRUE(blst_detail::To_blst_fp(cur.g1.second, g1_affine.y));
647
648
13.6k
            CF_CHECK_TRUE(blst_p1_affine_on_curve(&g1_affine) && blst_p1_affine_in_g1(&g1_affine));
649
650
            /* Load G2 */
651
12.4k
            CF_CHECK_TRUE(blst_detail::To_blst_fp(cur.g2.first.first, g2_affine.x.fp[0]));
652
12.4k
            CF_CHECK_TRUE(blst_detail::To_blst_fp(cur.g2.first.second, g2_affine.y.fp[0]));
653
12.4k
            CF_CHECK_TRUE(blst_detail::To_blst_fp(cur.g2.second.first, g2_affine.x.fp[1]));
654
12.4k
            CF_CHECK_TRUE(blst_detail::To_blst_fp(cur.g2.second.second, g2_affine.y.fp[1]));
655
656
12.4k
            CF_CHECK_TRUE(blst_p2_affine_on_curve(&g2_affine) && blst_p2_affine_in_g2(&g2_affine));
657
658
12.3k
            blst_fp12 tmp;
659
12.3k
            CF_NORET(blst_miller_loop(&tmp, &g2_affine, &g1_affine));
660
12.3k
            CF_NORET(blst_fp12_mul(&f, &f, &tmp));
661
12.3k
    }
662
663
170
    CF_NORET(blst_final_exp(&f, &f));
664
665
170
    ret = blst_fp12_is_equal(&f, &one) == 1;
666
667
1.62k
end:
668
1.62k
    return ret;
669
170
}
670
671
2.03k
std::optional<bool> blst::OpBLS_IsG1OnCurve(operation::BLS_IsG1OnCurve& op) {
672
2.03k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
673
674
2.03k
    bool useAffine = true;
675
676
2.03k
    try {
677
2.03k
        useAffine = ds.Get<bool>();
678
2.03k
    } catch ( fuzzing::datasource::Base::OutOfData ) { }
679
680
2.03k
    if ( useAffine ) {
681
1.61k
        std::optional<blst_p1_affine> aff_g1;
682
1.61k
        CF_CHECK_NE(aff_g1 = blst_detail::Load_G1_Affine(op.g1), std::nullopt);
683
1.56k
        return
684
1.56k
            !blst_p1_affine_is_inf(&*aff_g1) &&
685
1.56k
            blst_p1_affine_on_curve(&*aff_g1) &&
686
1.56k
            blst_p1_affine_in_g1(&*aff_g1);
687
1.61k
    } else {
688
423
        std::optional<blst_p1> g1;
689
423
        CF_CHECK_NE(g1 = blst_detail::Load_G1_Projective(ds, op.g1), std::nullopt);
690
403
        return
691
403
            !blst_p1_is_inf(&*g1) &&
692
403
            blst_p1_on_curve(&*g1) &&
693
403
            blst_p1_in_g1(&*g1);
694
423
    }
695
61
end:
696
61
    return false;
697
2.03k
}
698
699
2.69k
std::optional<bool> blst::OpBLS_IsG2OnCurve(operation::BLS_IsG2OnCurve& op) {
700
2.69k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
701
702
2.69k
    bool useAffine = true;
703
704
2.69k
    try {
705
2.69k
        useAffine = ds.Get<bool>();
706
2.69k
    } catch ( fuzzing::datasource::Base::OutOfData ) { }
707
708
2.69k
    blst_p2 g2;
709
2.69k
    blst_p2_affine g2_affine;
710
711
2.69k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.first.first, g2_affine.x.fp[0]));
712
2.66k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.first.second, g2_affine.y.fp[0]));
713
2.64k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.second.first, g2_affine.x.fp[1]));
714
2.62k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.second.second, g2_affine.y.fp[1]));
715
716
2.60k
    CF_CHECK_FALSE(blst_detail::IsZero(&g2_affine));
717
718
2.44k
    if ( useAffine ) {
719
1.99k
        return blst_p2_affine_on_curve(&g2_affine) && blst_p2_affine_in_g2(&g2_affine);
720
1.99k
    } else {
721
451
        CF_NORET(blst_p2_from_affine(&g2, &g2_affine));
722
451
        return blst_p2_on_curve(&g2) && blst_p2_in_g2(&g2);
723
451
    }
724
725
255
end:
726
255
    return false;
727
2.44k
}
728
729
214
std::optional<component::BLS_KeyPair> blst::OpBLS_GenerateKeyPair(operation::BLS_GenerateKeyPair& op) {
730
214
    std::optional<component::BLS_KeyPair> ret = std::nullopt;
731
214
    if ( op.ikm.GetSize() < 32 ) {
732
98
        return std::nullopt;
733
98
    }
734
735
116
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
736
737
116
    blst_scalar priv;
738
116
    blst_p1 pub;
739
116
    blst_p1_affine pub_affine;
740
741
116
    CF_NORET(blst_keygen(&priv, op.ikm.GetPtr(&ds), op.ikm.GetSize(), op.info.GetPtr(&ds), op.info.GetSize()));
742
116
    CF_ASSERT(blst_sk_check(&priv) == true, "blst_keygen generated invalid private key");
743
744
116
    CF_NORET(blst_sk_to_pk_in_g1(&pub, &priv));
745
116
    CF_NORET(blst_p1_to_affine(&pub_affine, &pub));
746
747
116
    {
748
116
        std::array<uint8_t, 32> priv_bytes;
749
116
        CF_NORET(blst_uint64_from_scalar((uint64_t*)priv_bytes.data(), &priv));
750
751
116
        blst_detail::Reverse<>(priv_bytes);
752
116
        blst_detail::G1 g1(pub_affine, ds);
753
754
116
        {
755
116
            const auto priv = util::BinToDec(priv_bytes.data(), 32);
756
116
            const auto pub = g1.To_Component_G1();
757
758
116
            CF_ASSERT(blst_p1_affine_on_curve(&pub_affine) == true, "Generated public key not on curve");
759
116
            CF_ASSERT(blst_p1_affine_in_g1(&pub_affine), "Generated public key not in group");
760
761
116
            ret = {priv, pub};
762
116
        }
763
116
    }
764
765
0
    return ret;
766
116
}
767
768
261
std::optional<component::G1> blst::OpBLS_Aggregate_G1(operation::BLS_Aggregate_G1& op) {
769
261
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
770
261
    std::optional<component::G1> ret = std::nullopt;
771
772
261
    blst_p1 res;
773
261
    blst_p1_affine res_affine;
774
775
261
    bool first = true;
776
2.52k
    for (const auto& sig : op.points.points) {
777
2.52k
        uint8_t serialized[96];
778
2.52k
        blst_p1_affine a;
779
2.52k
        blst_p1 a_;
780
781
2.52k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(sig.first, a.x));
782
2.49k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(sig.second, a.y));
783
784
2.47k
        CF_NORET(blst_p1_from_affine(&a_, &a));
785
786
2.47k
        CF_NORET(blst_p1_serialize(serialized, &a_));
787
788
2.47k
        CF_CHECK_EQ(
789
2.47k
                blst_aggregate_in_g1(
790
2.47k
                    &res,
791
2.47k
                    first == true ? nullptr : &res,
792
2.47k
                    serialized), BLST_SUCCESS);
793
794
2.42k
        first = false;
795
2.42k
    }
796
797
162
    if ( first == false ) {
798
76
        CF_NORET(blst_p1_to_affine(&res_affine, &res));
799
76
        CF_ASSERT(blst_p1_affine_on_curve(&res_affine) && blst_p1_affine_in_g1(&res_affine), "Aggregate created invalid point");
800
76
        blst_detail::G1 _g1(res_affine, ds);
801
76
        ret = _g1.To_Component_G1();
802
76
    }
803
804
261
end:
805
261
    return ret;
806
162
}
807
808
312
std::optional<component::G2> blst::OpBLS_Aggregate_G2(operation::BLS_Aggregate_G2& op) {
809
312
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
810
312
    std::optional<component::G2> ret = std::nullopt;
811
812
312
    blst_p2 res;
813
312
    blst_p2_affine res_affine;
814
815
312
    bool first = true;
816
2.07k
    for (const auto& sig : op.points.points) {
817
2.07k
        uint8_t serialized[192];
818
2.07k
        blst_p2_affine a;
819
2.07k
        blst_p2 a_;
820
821
2.07k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(sig.first.first, a.x.fp[0]));
822
2.05k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(sig.first.second, a.y.fp[0]));
823
2.02k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(sig.second.first, a.x.fp[1]));
824
2.00k
        CF_CHECK_TRUE(blst_detail::To_blst_fp(sig.second.second, a.y.fp[1]));
825
826
1.98k
        CF_NORET(blst_p2_from_affine(&a_, &a));
827
828
1.98k
        CF_NORET(blst_p2_serialize(serialized, &a_));
829
830
1.98k
        CF_CHECK_EQ(
831
1.98k
                blst_aggregate_in_g2(
832
1.98k
                    &res,
833
1.98k
                    first == true ? nullptr : &res,
834
1.98k
                    serialized), BLST_SUCCESS);
835
836
1.92k
        first = false;
837
1.92k
    }
838
839
168
    if ( first == false ) {
840
70
        CF_NORET(blst_p2_to_affine(&res_affine, &res));
841
70
        CF_ASSERT(blst_p2_affine_on_curve(&res_affine) && blst_p2_affine_in_g2(&res_affine), "Aggregate created invalid point");
842
70
        ret = blst_detail::To_G2(res_affine);
843
70
    }
844
845
312
end:
846
312
    return ret;
847
168
}
848
849
284
std::optional<component::Fp12> blst::OpBLS_Pairing(operation::BLS_Pairing& op) {
850
284
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
851
284
    std::optional<component::Fp12> ret = std::nullopt;
852
853
284
    blst_p1_affine g1_affine;
854
284
    blst_p2_affine g2_affine;
855
284
    blst_fp12 out;
856
857
284
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g1.first, g1_affine.x));
858
264
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g1.second, g1_affine.y));
859
860
244
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.first.first, g2_affine.x.fp[0]));
861
222
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.first.second, g2_affine.y.fp[0]));
862
202
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.second.first, g2_affine.x.fp[1]));
863
182
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.second.second, g2_affine.y.fp[1]));
864
865
162
    CF_NORET(blst_miller_loop(&out, &g2_affine, &g1_affine));
866
162
    CF_NORET(blst_final_exp(&out, &out));
867
868
162
    ret = blst_detail::To_component_Fp12(out);
869
870
284
end:
871
284
    return ret;
872
162
}
873
874
0
std::optional<component::Fp12> blst::OpBLS_MillerLoop(operation::BLS_MillerLoop& op) {
875
0
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
876
0
    std::optional<component::Fp12> ret = std::nullopt;
877
878
0
    blst_p1_affine g1_affine;
879
0
    blst_p2_affine g2_affine;
880
0
    blst_fp12 out;
881
882
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g1.first, g1_affine.x));
883
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g1.second, g1_affine.y));
884
885
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.first.first, g2_affine.x.fp[0]));
886
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.first.second, g2_affine.y.fp[0]));
887
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.second.first, g2_affine.x.fp[1]));
888
0
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.g2.second.second, g2_affine.y.fp[1]));
889
890
0
    CF_NORET(blst_miller_loop(&out, &g2_affine, &g1_affine));
891
892
0
    ret = blst_detail::To_component_Fp12(out);
893
894
0
end:
895
0
    return ret;
896
0
}
897
898
305
std::optional<component::Fp12> blst::OpBLS_FinalExp(operation::BLS_FinalExp& op) {
899
305
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
900
305
    std::optional<component::Fp12> ret = std::nullopt;
901
902
305
    blst_fp12 out;
903
904
305
    CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.fp12, out));
905
906
200
    CF_NORET(blst_final_exp(&out, &out));
907
908
200
    ret = blst_detail::To_component_Fp12(out);
909
910
305
end:
911
305
    return ret;
912
200
}
913
914
namespace blst_detail {
915
    template <class T>
916
2.37k
    bool UseParamTwice(fuzzing::datasource::Datasource& ds, const T* A, const T* B) {
917
2.37k
        if ( memcmp(A, B, sizeof(T)) != 0 ) {
918
1.81k
            return false;
919
1.81k
        }
920
921
562
        try {
922
562
            return ds.Get<bool>();
923
562
        } catch ( fuzzing::datasource::Base::OutOfData ) {
924
305
        }
925
926
305
        return false;
927
562
    }
bool cryptofuzz::module::blst_detail::UseParamTwice<blst_fr>(fuzzing::datasource::Datasource&, blst_fr const*, blst_fr const*)
Line
Count
Source
916
998
    bool UseParamTwice(fuzzing::datasource::Datasource& ds, const T* A, const T* B) {
917
998
        if ( memcmp(A, B, sizeof(T)) != 0 ) {
918
825
            return false;
919
825
        }
920
921
173
        try {
922
173
            return ds.Get<bool>();
923
173
        } catch ( fuzzing::datasource::Base::OutOfData ) {
924
94
        }
925
926
94
        return false;
927
173
    }
bool cryptofuzz::module::blst_detail::UseParamTwice<blst_fp>(fuzzing::datasource::Datasource&, blst_fp const*, blst_fp const*)
Line
Count
Source
916
786
    bool UseParamTwice(fuzzing::datasource::Datasource& ds, const T* A, const T* B) {
917
786
        if ( memcmp(A, B, sizeof(T)) != 0 ) {
918
636
            return false;
919
636
        }
920
921
150
        try {
922
150
            return ds.Get<bool>();
923
150
        } catch ( fuzzing::datasource::Base::OutOfData ) {
924
80
        }
925
926
80
        return false;
927
150
    }
bool cryptofuzz::module::blst_detail::UseParamTwice<blst_fp2>(fuzzing::datasource::Datasource&, blst_fp2 const*, blst_fp2 const*)
Line
Count
Source
916
319
    bool UseParamTwice(fuzzing::datasource::Datasource& ds, const T* A, const T* B) {
917
319
        if ( memcmp(A, B, sizeof(T)) != 0 ) {
918
154
            return false;
919
154
        }
920
921
165
        try {
922
165
            return ds.Get<bool>();
923
165
        } catch ( fuzzing::datasource::Base::OutOfData ) {
924
86
        }
925
926
86
        return false;
927
165
    }
bool cryptofuzz::module::blst_detail::UseParamTwice<blst_fp12>(fuzzing::datasource::Datasource&, blst_fp12 const*, blst_fp12 const*)
Line
Count
Source
916
269
    bool UseParamTwice(fuzzing::datasource::Datasource& ds, const T* A, const T* B) {
917
269
        if ( memcmp(A, B, sizeof(T)) != 0 ) {
918
195
            return false;
919
195
        }
920
921
74
        try {
922
74
            return ds.Get<bool>();
923
74
        } catch ( fuzzing::datasource::Base::OutOfData ) {
924
45
        }
925
926
45
        return false;
927
74
    }
928
929
4.85k
    uint8_t GetMod3(fuzzing::datasource::Datasource& ds) {
930
4.85k
        try {
931
4.85k
            return ds.Get<uint8_t>() % 3;
932
4.85k
        } catch ( fuzzing::datasource::Base::OutOfData ) {
933
2.64k
        }
934
935
2.64k
        return 0;
936
4.85k
    }
937
938
3.66k
    #define PREPARE_RESULT() {resultIdx = GetMod3(ds);}
939
1.73k
    #define RESULT_PTR() (resultIdx == 0 ? &result : (resultIdx == 1 ? &A : &B))
940
3.64k
    #define RESULT() (resultIdx == 0 ? result : (resultIdx == 1 ? A : B))
941
723
    #define PARAM_B() (UseParamTwice(ds, &A, &B) ? &A : &B)
942
943
8.30k
    std::optional<component::Bignum> OpBignumCalc_order(operation::BignumCalc& op) {
944
8.30k
        std::optional<component::Bignum> ret = std::nullopt;
945
8.30k
        Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
946
8.30k
        blst_fr result, A, B;
947
8.30k
        uint8_t resultIdx;
948
8.30k
        static const blst_fr zero = {0};
949
950
8.30k
        switch ( op.calcOp.Get() ) {
951
235
            case    CF_CALCOP("Add(A,B)"):
952
235
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
953
215
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn1, B));
954
195
                PREPARE_RESULT();
955
195
                blst_fr_add(RESULT_PTR(), &A, PARAM_B());
956
195
                ret = blst_detail::To_component_bignum(RESULT());
957
195
                break;
958
217
            case    CF_CALCOP("Sub(A,B)"):
959
217
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
960
196
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn1, B));
961
172
                PREPARE_RESULT();
962
172
                blst_fr_sub(RESULT_PTR(), &A, PARAM_B());
963
172
                ret = blst_detail::To_component_bignum(RESULT());
964
172
                break;
965
813
            case    CF_CALCOP("Mul(A,B)"):
966
813
                {
967
813
                    CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
968
969
793
                    size_t shiftCount;
970
793
                    uint8_t which = 0;
971
793
                    try {
972
793
                        which = ds.Get<uint8_t>() % 3;
973
793
                    } catch ( fuzzing::datasource::Base::OutOfData ) {
974
317
                    }
975
793
                    if ( which == 1 ) {
976
177
                        if ( op.bn1.ToTrimmedString() != "3" ) {
977
119
                            which = 0;
978
119
                        }
979
616
                    } else if ( which == 2 ) {
980
284
                        shiftCount = blst_detail::isMultipleOf2(op.bn1.ToTrimmedString());
981
284
                        if ( shiftCount == 0 ) {
982
213
                            which = 0;
983
213
                        }
984
284
                    }
985
986
793
                    switch ( which ) {
987
664
                        case    0:
988
664
                            CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn1, B));
989
631
                            PREPARE_RESULT();
990
631
                            CF_NORET(blst_fr_mul(RESULT_PTR(), &A, PARAM_B()));
991
631
                            break;
992
58
                        case    1:
993
58
                            PREPARE_RESULT();
994
58
                            CF_NORET(blst_fr_mul_by_3(RESULT_PTR(), &A));
995
58
                            break;
996
71
                        case    2:
997
71
                            PREPARE_RESULT();
998
71
                            blst_fr_lshift(RESULT_PTR(), &A, shiftCount);
999
71
                            ret = blst_detail::To_component_bignum(RESULT());
1000
71
                            break;
1001
793
                    }
1002
1003
760
                    ret = blst_detail::To_component_bignum(RESULT());
1004
760
                }
1005
0
                break;
1006
131
            case    CF_CALCOP("Sqr(A)"):
1007
131
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
1008
95
                PREPARE_RESULT();
1009
95
                blst_fr_sqr(RESULT_PTR(), &A);
1010
95
                ret = blst_detail::To_component_bignum(RESULT());
1011
95
                break;
1012
439
            case    CF_CALCOP("InvMod(A,B)"):
1013
439
                {
1014
439
                    CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
1015
1016
419
                    bool which = false;
1017
419
                    try {
1018
419
                        which = ds.Get<bool>();
1019
419
                    } catch ( fuzzing::datasource::Base::OutOfData ) {
1020
260
                    }
1021
1022
419
                    if ( which ) {
1023
91
                        PREPARE_RESULT();
1024
91
                        CF_NORET(blst_fr_eucl_inverse(RESULT_PTR(), &A));
1025
328
                    } else {
1026
328
                        PREPARE_RESULT();
1027
328
                        CF_NORET(blst_fr_inverse(RESULT_PTR(), &A));
1028
328
                    }
1029
1030
419
                    ret = blst_detail::To_component_bignum(RESULT());
1031
419
                }
1032
0
                break;
1033
122
            case    CF_CALCOP("LShift1(A)"):
1034
122
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
1035
102
                PREPARE_RESULT();
1036
102
                blst_fr_lshift(RESULT_PTR(), &A, 1);
1037
102
                ret = blst_detail::To_component_bignum(RESULT());
1038
102
                break;
1039
648
            case    CF_CALCOP("RShift(A,B)"):
1040
648
                {
1041
648
                    CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
1042
628
                    const auto B_cpp_int = blst_detail::To_cpp_int(op.bn1);
1043
628
                    size_t count = static_cast<size_t>(B_cpp_int);
1044
628
                    CF_CHECK_EQ(count, B_cpp_int);
1045
547
                    CF_CHECK_GT(count, 0);
1046
467
                    CF_CHECK_LT(count, 1024000);
1047
1048
304
                    PREPARE_RESULT();
1049
304
                    blst_fr_rshift(RESULT_PTR(), &A, count);
1050
1051
304
                    {
1052
304
                        CF_CHECK_EQ(count, 1);
1053
230
                        const auto A_cpp_int = blst_detail::To_cpp_int(op.bn0);
1054
230
                        CF_CHECK_LT(A_cpp_int, boost::multiprecision::cpp_int("52435875175126190479447740508185965837690552500527637822603658699938581184513"));
1055
180
                        CF_CHECK_EQ(A_cpp_int % 2, 1);
1056
132
                        ret = blst_detail::To_component_bignum(RESULT());
1057
132
                    }
1058
132
                }
1059
0
                break;
1060
105
            case    CF_CALCOP("Not(A)"):
1061
105
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
1062
85
                PREPARE_RESULT();
1063
85
                blst_fr_cneg(RESULT_PTR(), &A, true);
1064
85
                ret = blst_detail::To_component_bignum(RESULT());
1065
85
                break;
1066
42
            case    CF_CALCOP("Set(A)"):
1067
42
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
1068
22
                ret = blst_detail::To_component_bignum(A);
1069
22
                break;
1070
101
            case    CF_CALCOP("IsEq(A,B)"):
1071
101
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
1072
80
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn1, B));
1073
59
                ret = memcmp(&A, &B, sizeof(A)) == 0 ? std::string("1") : std::string("0");
1074
59
                break;
1075
86
            case    CF_CALCOP("IsZero(A)"):
1076
86
                CF_CHECK_TRUE(blst_detail::To_blst_fr(op.bn0, A));
1077
66
                ret = memcmp(&A, &zero, sizeof(A)) == 0 ? std::string("1") : std::string("0");
1078
66
                break;
1079
8.30k
        }
1080
1081
8.30k
end:
1082
8.30k
        return ret;
1083
8.30k
    }
1084
1085
6.49k
    std::optional<component::Bignum> OpBignumCalc_prime(operation::BignumCalc& op) {
1086
6.49k
        std::optional<component::Bignum> ret = std::nullopt;
1087
6.49k
        Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1088
6.49k
        blst_fp result, A, B;
1089
6.49k
        uint8_t resultIdx;
1090
6.49k
        static const blst_fp zero = {0};
1091
1092
6.49k
        switch ( op.calcOp.Get() ) {
1093
205
            case    CF_CALCOP("Add(A,B)"):
1094
205
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1095
185
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn1, B));
1096
165
                PREPARE_RESULT();
1097
165
                blst_fp_add(RESULT_PTR(), &A, PARAM_B());
1098
165
                ret = blst_detail::To_component_bignum(RESULT());
1099
165
                break;
1100
232
            case    CF_CALCOP("Sub(A,B)"):
1101
232
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1102
212
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn1, B));
1103
191
                PREPARE_RESULT();
1104
191
                blst_fp_sub(RESULT_PTR(), &A, PARAM_B());
1105
191
                ret = blst_detail::To_component_bignum(RESULT());
1106
191
                break;
1107
664
            case    CF_CALCOP("Mul(A,B)"):
1108
664
                {
1109
664
                    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1110
1111
642
                    size_t shiftCount;
1112
642
                    uint8_t which = 0;
1113
642
                    try {
1114
642
                        which = ds.Get<uint8_t>() % 4;
1115
642
                    } catch ( fuzzing::datasource::Base::OutOfData ) {
1116
140
                    }
1117
1118
642
                    if ( which == 1 ) {
1119
143
                        if ( op.bn1.ToTrimmedString() != "3" ) {
1120
88
                            which = 0;
1121
88
                        }
1122
499
                    } else if ( which == 2 ) {
1123
113
                        if ( op.bn1.ToTrimmedString() != "8" ) {
1124
60
                            which = 0;
1125
60
                        }
1126
386
                    } else if ( which == 3 ) {
1127
233
                        shiftCount = blst_detail::isMultipleOf2(op.bn1.ToTrimmedString());
1128
233
                        if ( shiftCount == 0 ) {
1129
155
                            which = 0;
1130
155
                        }
1131
233
                    }
1132
1133
642
                    switch ( which ) {
1134
456
                        case    0:
1135
456
                            CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn1, B));
1136
430
                            PREPARE_RESULT();
1137
430
                            CF_NORET(blst_fp_mul(RESULT_PTR(), &A, PARAM_B()));
1138
430
                            break;
1139
55
                        case    1:
1140
55
                            PREPARE_RESULT();
1141
55
                            CF_NORET(blst_fp_mul_by_3(RESULT_PTR(), &A));
1142
55
                            break;
1143
53
                        case    2:
1144
53
                            PREPARE_RESULT();
1145
53
                            CF_NORET(blst_fp_mul_by_8(RESULT_PTR(), &A));
1146
53
                            break;
1147
78
                        case    3:
1148
78
                            size_t shiftCount;
1149
78
                            CF_CHECK_NE(shiftCount = blst_detail::isMultipleOf2(op.bn1.ToTrimmedString()), 0);
1150
1151
78
                            PREPARE_RESULT();
1152
78
                            blst_fp_lshift(RESULT_PTR(), &A, shiftCount);
1153
78
                            ret = blst_detail::To_component_bignum(RESULT());
1154
78
                            break;
1155
642
                    }
1156
1157
616
                    ret = blst_detail::To_component_bignum(RESULT());
1158
616
                }
1159
0
                break;
1160
118
            case    CF_CALCOP("LShift1(A)"):
1161
118
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1162
97
                PREPARE_RESULT();
1163
97
                blst_fp_lshift(RESULT_PTR(), &A, 1);
1164
97
                ret = blst_detail::To_component_bignum(RESULT());
1165
97
                break;
1166
139
            case    CF_CALCOP("Sqr(A)"):
1167
139
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1168
108
                PREPARE_RESULT();
1169
108
                blst_fp_sqr(RESULT_PTR(), &A);
1170
108
                ret = blst_detail::To_component_bignum(RESULT());
1171
108
                break;
1172
306
            case    CF_CALCOP("InvMod(A,B)"):
1173
306
                {
1174
306
                    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1175
1176
286
                    bool which = false;
1177
286
                    try {
1178
286
                        which = ds.Get<bool>();
1179
286
                    } catch ( fuzzing::datasource::Base::OutOfData ) {
1180
163
                    }
1181
1182
286
                    if ( which ) {
1183
73
                        PREPARE_RESULT();
1184
73
                        CF_NORET(blst_fp_eucl_inverse(RESULT_PTR(), &A));
1185
213
                    } else {
1186
213
                        PREPARE_RESULT();
1187
213
                        CF_NORET(blst_fp_inverse(RESULT_PTR(), &A));
1188
213
                    }
1189
1190
286
                    ret = blst_detail::To_component_bignum(RESULT());
1191
286
                }
1192
0
                break;
1193
461
            case    CF_CALCOP("Sqrt(A)"):
1194
461
                {
1195
461
                    blst_fp result2;
1196
461
                    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1197
1198
441
                    if ( blst_fp_sqrt(&result, &A) == true ) {
1199
253
                        CF_NORET(blst_fp_sqr(&result, &result));
1200
253
                        ret = blst_detail::To_component_bignum(result);
1201
253
                    } else {
1202
188
                        CF_NORET(blst_fp_cneg(&A, &A, 1));
1203
188
                        CF_ASSERT(blst_fp_sqrt(&A, &A) == true, "Square root must exist");
1204
1205
188
                        ret = std::string("0");
1206
188
                    }
1207
441
                }
1208
441
                break;
1209
441
            case    CF_CALCOP("IsSquare(A)"):
1210
62
                {
1211
62
                    blst_fp tmp;
1212
1213
62
                    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1214
41
                    const bool is_square = blst_fp_is_square(&A);
1215
1216
41
                    if ( !is_square ) {
1217
21
                        CF_NORET(blst_fp_cneg(&tmp, &A, 1));
1218
21
                        CF_ASSERT(blst_fp_is_square(&tmp) == true, "Must be square");
1219
21
                    } else {
1220
20
                        CF_ASSERT(blst_fp_sqrt(&tmp, &A) == true, "Square root must exist");
1221
20
                    }
1222
1223
41
                    CF_ASSERT(
1224
41
                            is_square ==
1225
41
                            blst_fp_sqrt(&result, &A), "");
1226
41
                    ret = is_square ? std::string("1") : std::string("0");
1227
41
                }
1228
0
                break;
1229
89
            case    CF_CALCOP("Not(A)"):
1230
89
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1231
69
                PREPARE_RESULT();
1232
69
                blst_fp_cneg(RESULT_PTR(), &A, true);
1233
69
                ret = blst_detail::To_component_bignum(RESULT());
1234
69
                break;
1235
46
            case    CF_CALCOP("Set(A)"):
1236
46
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1237
26
                ret = blst_detail::To_component_bignum(A);
1238
26
                break;
1239
104
            case    CF_CALCOP("IsEq(A,B)"):
1240
104
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1241
80
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn1, B));
1242
58
                ret = memcmp(&A, &B, sizeof(A)) == 0 ? std::string("1") : std::string("0");
1243
58
                break;
1244
66
            case    CF_CALCOP("IsZero(A)"):
1245
66
                CF_CHECK_TRUE(blst_detail::To_blst_fp(op.bn0, A));
1246
46
                ret = memcmp(&A, &zero, sizeof(A)) == 0 ? std::string("1") : std::string("0");
1247
46
                break;
1248
6.49k
        }
1249
1250
6.49k
end:
1251
6.49k
        return ret;
1252
6.49k
    }
1253
1254
    #undef PREPARE_RESULT
1255
    #undef RESULT_PTR
1256
    #undef RESULT
1257
    #undef PARAM_B
1258
}
1259
1260
26.2k
std::optional<component::Bignum> blst::OpBignumCalc(operation::BignumCalc& op) {
1261
26.2k
    if ( op.modulo == std::nullopt ) {
1262
11.4k
        return std::nullopt;
1263
11.4k
    }
1264
1265
    /* TODO optimize this */
1266
14.8k
    if ( op.modulo->ToTrimmedString() == "52435875175126190479447740508185965837690552500527637822603658699938581184513" ) {
1267
8.30k
        return blst_detail::OpBignumCalc_order(op);
1268
8.30k
    } else if ( op.modulo->ToTrimmedString() == "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787" ) {
1269
6.49k
        return blst_detail::OpBignumCalc_prime(op);
1270
6.49k
    } else {
1271
0
        return std::nullopt;
1272
0
    }
1273
14.8k
}
1274
1275
namespace blst_detail {
1276
705
    #define PREPARE_RESULT() {resultIdx = GetMod3(ds);}
1277
443
    #define RESULT_PTR() (resultIdx == 0 ? &result : (resultIdx == 1 ? &A : &B))
1278
705
    #define RESULT() (resultIdx == 0 ? result : (resultIdx == 1 ? A : B))
1279
214
    #define PARAM_B() (UseParamTwice(ds, &A, &B) ? &A : &B)
1280
1281
3.52k
    std::optional<component::Fp2> OpBignumCalc_Fp2_prime(operation::BignumCalc_Fp2& op) {
1282
3.52k
        std::optional<component::Fp2> ret = std::nullopt;
1283
3.52k
        Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1284
3.52k
        blst_fp2 result, A, B;
1285
3.52k
        uint8_t resultIdx;
1286
1287
3.52k
        switch ( op.calcOp.Get() ) {
1288
182
            case    CF_CALCOP("Add(A,B)"):
1289
182
                CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn0, A));
1290
142
                CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn1, B));
1291
102
                PREPARE_RESULT();
1292
102
                blst_fp2_add(RESULT_PTR(), &A, PARAM_B());
1293
102
                ret = blst_detail::To_component_Fp2(RESULT());
1294
102
                break;
1295
188
            case    CF_CALCOP("Sub(A,B)"):
1296
188
                CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn0, A));
1297
148
                CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn1, B));
1298
112
                PREPARE_RESULT();
1299
112
                blst_fp2_sub(RESULT_PTR(), &A, PARAM_B());
1300
112
                ret = blst_detail::To_component_Fp2(RESULT());
1301
112
                break;
1302
185
            case    CF_CALCOP("Mul(A,B)"):
1303
185
                CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn0, A));
1304
145
                CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn1, B));
1305
105
                PREPARE_RESULT();
1306
105
                CF_NORET(blst_fp2_mul(RESULT_PTR(), &A, PARAM_B()));
1307
1308
105
                ret = blst_detail::To_component_Fp2(RESULT());
1309
105
                break;
1310
107
            case    CF_CALCOP("LShift1(A)"):
1311
107
                CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn0, A));
1312
71
                PREPARE_RESULT();
1313
71
                blst_fp2_lshift(RESULT_PTR(), &A, 1);
1314
71
                ret = blst_detail::To_component_Fp2(RESULT());
1315
71
                break;
1316
124
            case    CF_CALCOP("Sqr(A)"):
1317
124
                CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn0, A));
1318
87
                PREPARE_RESULT();
1319
87
                blst_fp2_sqr(RESULT_PTR(), &A);
1320
87
                ret = blst_detail::To_component_Fp2(RESULT());
1321
87
                break;
1322
197
            case    CF_CALCOP("InvMod(A,B)"):
1323
197
                {
1324
197
                    CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn0, A));
1325
1326
157
                    bool which = false;
1327
157
                    try {
1328
157
                        which = ds.Get<bool>();
1329
157
                    } catch ( fuzzing::datasource::Base::OutOfData ) {
1330
41
                    }
1331
1332
157
                    if ( which ) {
1333
79
                        PREPARE_RESULT();
1334
79
                        CF_NORET(blst_fp2_eucl_inverse(RESULT_PTR(), &A));
1335
79
                    } else {
1336
78
                        PREPARE_RESULT();
1337
78
                        CF_NORET(blst_fp2_inverse(RESULT_PTR(), &A));
1338
78
                    }
1339
1340
157
                    ret = blst_detail::To_component_Fp2(RESULT());
1341
157
                }
1342
0
                break;
1343
106
            case    CF_CALCOP("Sqrt(A)"):
1344
106
                {
1345
106
                    blst_fp result2;
1346
106
                    CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn0, A));
1347
1348
66
                    if ( blst_fp2_sqrt(&result, &A) == true ) {
1349
45
                        CF_NORET(blst_fp2_sqr(&result, &result));
1350
45
                        ret = blst_detail::To_component_Fp2(result);
1351
45
                    } else {
1352
21
                        ret = { std::string("0"), std::string("0") };
1353
21
                    }
1354
66
                }
1355
0
                break;
1356
56
            case    CF_CALCOP("IsSquare(A)"):
1357
56
                {
1358
56
                    CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn0, A));
1359
20
                    const bool is_square = blst_fp2_is_square(&A);
1360
20
                    CF_ASSERT(
1361
20
                            is_square ==
1362
20
                            blst_fp2_sqrt(&result, &A), "");
1363
20
                }
1364
0
                break;
1365
112
            case    CF_CALCOP("Not(A)"):
1366
112
                CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn0, A));
1367
71
                PREPARE_RESULT();
1368
71
                blst_fp2_cneg(RESULT_PTR(), &A, true);
1369
71
                ret = blst_detail::To_component_Fp2(RESULT());
1370
71
                break;
1371
56
            case    CF_CALCOP("Set(A)"):
1372
56
                CF_CHECK_TRUE(blst_detail::To_blst_fp2(op.bn0, A));
1373
20
                ret = blst_detail::To_component_Fp2(A);
1374
20
                break;
1375
3.52k
        }
1376
1377
3.52k
end:
1378
3.52k
        return ret;
1379
3.52k
    }
1380
1381
    #undef PREPARE_RESULT
1382
    #undef RESULT_PTR
1383
    #undef RESULT
1384
    #undef PARAM_B
1385
}
1386
1387
3.52k
std::optional<component::Fp2> blst::OpBignumCalc_Fp2(operation::BignumCalc_Fp2& op) {
1388
3.52k
    return blst_detail::OpBignumCalc_Fp2_prime(op);
1389
3.52k
}
1390
1391
namespace blst_detail {
1392
490
    #define PREPARE_RESULT() {resultIdx = GetMod3(ds);}
1393
    #define RESULT_PTR() (resultIdx == 0 ? &result : (resultIdx == 1 ? &A : &B))
1394
490
    #define RESULT() (resultIdx == 0 ? result : (resultIdx == 1 ? A : B))
1395
    #define PARAM_B() (UseParamTwice(ds, &A, &B) ? &A : &B)
1396
1397
2.01k
    std::optional<component::Fp12> OpBignumCalc_Fp12_prime(operation::BignumCalc_Fp12& op) {
1398
2.01k
        std::optional<component::Fp12> ret = std::nullopt;
1399
2.01k
        Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1400
2.01k
        blst_fp12 result, A, B;
1401
2.01k
        uint8_t resultIdx;
1402
1403
2.01k
        switch ( op.calcOp.Get() ) {
1404
349
            case    CF_CALCOP("Mul(A,B)"):
1405
349
                CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.bn0, A));
1406
308
                CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.bn1, B));
1407
269
                PREPARE_RESULT();
1408
269
                CF_NORET(blst_fp12_mul(RESULT_PTR(), &A, PARAM_B()));
1409
1410
269
                ret = blst_detail::To_component_Fp12(RESULT());
1411
269
                break;
1412
96
            case    CF_CALCOP("Conjugate(A)"):
1413
96
                CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.bn0, A));
1414
58
                CF_NORET(blst_fp12_conjugate(&A));
1415
58
                ret = blst_detail::To_component_Fp12(A);
1416
58
                break;
1417
118
            case    CF_CALCOP("Sqr(A)"):
1418
118
                CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.bn0, A));
1419
100
                PREPARE_RESULT();
1420
100
                CF_NORET(blst_fp12_sqr(RESULT_PTR(), &A));
1421
100
                ret = blst_detail::To_component_Fp12(RESULT());
1422
100
                break;
1423
64
            case    CF_CALCOP("CyclotomicSqr(A)"):
1424
64
                CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.bn0, A));
1425
44
                CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.bn1, B));
1426
22
                CF_NORET(blst_fp12_cyclotomic_sqr(&A, &B));
1427
22
                ret = blst_detail::To_component_Fp12(A);
1428
22
                break;
1429
147
            case    CF_CALCOP("InvMod(A,B)"):
1430
147
                CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.bn0, A));
1431
1432
121
                PREPARE_RESULT();
1433
121
                CF_NORET(blst_fp12_inverse(RESULT_PTR(), &A));
1434
1435
121
                ret = blst_detail::To_component_Fp12(RESULT());
1436
121
                break;
1437
25
            case    CF_CALCOP("One()"):
1438
25
                ret = blst_detail::To_component_Fp12(*(blst_fp12_one()));
1439
25
                break;
1440
78
            case    CF_CALCOP("IsOne(A)"):
1441
78
                CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.bn0, A));
1442
47
                if ( blst_fp12_is_one(&A) ) {
1443
21
                    ret = blst_detail::To_component_Fp12(*(blst_fp12_one()));
1444
26
                } else {
1445
26
                    memset(&result, 0, sizeof(result));
1446
26
                    ret = blst_detail::To_component_Fp12(result);
1447
26
                }
1448
47
                break;
1449
92
            case    CF_CALCOP("IsEq(A,B)"):
1450
92
                CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.bn0, A));
1451
72
                CF_CHECK_TRUE(blst_detail::To_blst_fp12(op.bn1, B));
1452
1453
40
                if ( blst_fp12_is_equal(&A, &B) ) {
1454
20
                    ret = blst_detail::To_component_Fp12(*(blst_fp12_one()));
1455
20
                } else {
1456
20
                    memset(&result, 0, sizeof(result));
1457
20
                    ret = blst_detail::To_component_Fp12(result);
1458
20
                }
1459
40
                break;
1460
2.01k
        }
1461
1462
2.01k
end:
1463
2.01k
        return ret;
1464
2.01k
    }
1465
1466
    #undef PREPARE_RESULT
1467
    #undef RESULT_PTR
1468
    #undef RESULT
1469
    #undef PARAM_B
1470
}
1471
1472
2.01k
std::optional<component::Fp12> blst::OpBignumCalc_Fp12(operation::BignumCalc_Fp12& op) {
1473
2.01k
    return blst_detail::OpBignumCalc_Fp12_prime(op);
1474
2.01k
}
1475
1476
342
std::optional<component::G1> blst::OpBLS_Decompress_G1(operation::BLS_Decompress_G1& op) {
1477
342
    std::optional<component::G1> ret = std::nullopt;
1478
342
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1479
1480
342
    blst_p1_affine point;
1481
342
    std::optional<std::array<uint8_t, 48>> compressed = std::nullopt;
1482
1483
342
    CF_CHECK_NE(compressed = blst_detail::ToArray<48>(op.compressed, false), std::nullopt);
1484
1485
315
    if ( blst_p1_uncompress(&point, compressed->data()) == BLST_SUCCESS ) {
1486
67
        blst_detail::G1 g1(point, ds);
1487
67
        ret = g1.To_Component_G1();
1488
248
    } else {
1489
248
        ret = component::G1{"0", "0"};
1490
248
    }
1491
1492
342
end:
1493
342
    return ret;
1494
315
}
1495
1496
197
std::optional<component::Bignum> blst::OpBLS_Compress_G1(operation::BLS_Compress_G1& op) {
1497
197
    std::optional<component::Bignum> ret = std::nullopt;
1498
1499
197
    std::array<uint8_t, 48> out;
1500
197
    blst_p1_affine point;
1501
1502
197
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.uncompressed.first, point.x));
1503
176
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.uncompressed.second, point.y));
1504
    //CF_CHECK_FALSE(blst_detail::IsZero(&point));
1505
1506
156
    CF_CHECK_TRUE(blst_p1_affine_on_curve(&point));
1507
1508
115
    CF_NORET(blst_p1_affine_compress(out.data(), &point));
1509
115
    ret = util::BinToDec(out.data(), 48);
1510
1511
197
end:
1512
197
    return ret;
1513
115
}
1514
1515
277
std::optional<component::G2> blst::OpBLS_Decompress_G2(operation::BLS_Decompress_G2& op) {
1516
277
    std::optional<component::G2> ret = std::nullopt;
1517
277
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1518
1519
277
    blst_p2_affine point;
1520
277
    std::optional<std::array<uint8_t, 48>> compressed_x = std::nullopt;
1521
277
    std::optional<std::array<uint8_t, 48>> compressed_y = std::nullopt;
1522
277
    std::array<uint8_t, 96> compressed;
1523
1524
277
    CF_CHECK_NE(compressed_x = blst_detail::ToArray<48>(op.compressed.first, false), std::nullopt);
1525
256
    CF_CHECK_NE(compressed_y = blst_detail::ToArray<48>(op.compressed.second, false), std::nullopt);
1526
1527
236
    memcpy(compressed.data(), compressed_x->data(), 48);
1528
236
    memcpy(compressed.data() + 48, compressed_y->data(), 48);
1529
1530
236
    if ( blst_p2_uncompress(&point, compressed.data()) == BLST_SUCCESS ) {
1531
67
        ret = blst_detail::To_G2(point);
1532
169
    } else {
1533
169
        ret = component::G2{"0", "0", "0", "0"};
1534
169
    }
1535
1536
277
end:
1537
277
    return ret;
1538
236
}
1539
1540
241
std::optional<component::G1> blst::OpBLS_Compress_G2(operation::BLS_Compress_G2& op) {
1541
241
    std::optional<component::G1> ret = std::nullopt;
1542
1543
241
    std::array<uint8_t, 96> out;
1544
241
    blst_p2_affine point;
1545
1546
241
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.uncompressed.first.first, point.x.fp[0]));
1547
221
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.uncompressed.first.second, point.y.fp[0]));
1548
201
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.uncompressed.second.first, point.x.fp[1]));
1549
181
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.uncompressed.second.second, point.y.fp[1]));
1550
1551
156
    CF_CHECK_TRUE(blst_p2_affine_on_curve(&point));
1552
1553
122
    CF_NORET(blst_p2_affine_compress(out.data(), &point));
1554
122
    ret = { util::BinToDec(out.data(), 48), util::BinToDec(out.data() + 48, 48) };
1555
1556
241
end:
1557
241
    return ret;
1558
122
}
1559
1560
4.00k
std::optional<component::G1> blst::OpBLS_G1_Add(operation::BLS_G1_Add& op) {
1561
4.00k
    std::optional<component::G1> ret = std::nullopt;
1562
4.00k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1563
1564
4.00k
    std::optional<blst_p1_affine> aff_tmp;
1565
4.00k
    blst_p1_affine aff_a, aff_b, aff_result;
1566
1567
4.00k
    std::optional<blst_p1> tmp;
1568
4.00k
    blst_p1 a, b, result;
1569
1570
4.00k
    bool eq;
1571
4.00k
    uint8_t mode = 0;
1572
4.00k
    bool doAffine = true;
1573
1574
4.00k
    CF_CHECK_NE(aff_tmp = blst_detail::Load_G1_Affine(op.a), std::nullopt);
1575
3.96k
    aff_a = *aff_tmp;
1576
1577
3.96k
    CF_CHECK_NE(aff_tmp = blst_detail::Load_G1_Affine(op.b), std::nullopt);
1578
3.91k
    aff_b = *aff_tmp;
1579
1580
3.91k
    CF_CHECK_NE(tmp = blst_detail::Load_G1_Projective(ds, op.a), std::nullopt);
1581
3.91k
    a = *tmp;
1582
1583
3.91k
    CF_CHECK_NE(tmp = blst_detail::Load_G1_Projective(ds, op.b), std::nullopt);
1584
3.91k
    b = *tmp;
1585
1586
3.91k
    eq = blst_p1_is_equal(&a, &b);
1587
1588
3.91k
    try {
1589
3.91k
        mode = ds.Get<uint8_t>() % 3;
1590
3.91k
    } catch ( fuzzing::datasource::Base::OutOfData ) {
1591
2.62k
    }
1592
1593
    /* Modes:
1594
     *
1595
     * 0 = pure add
1596
     * 1 = pure double
1597
     * 2 = mixed add and double
1598
     */
1599
1600
3.91k
    if ( mode == 0 && eq ) {
1601
80
        mode = 1;
1602
3.83k
    } else if ( mode == 1 && !eq ) {
1603
410
        mode = 0;
1604
410
    }
1605
1606
3.91k
    try {
1607
3.91k
        doAffine = ds.Get<bool>();
1608
3.91k
    } catch ( fuzzing::datasource::Base::OutOfData ) {
1609
2.84k
    }
1610
1611
3.91k
    switch ( mode ) {
1612
3.46k
        case    0:
1613
3.46k
            if ( doAffine == true ) {
1614
3.12k
                bool doMulti = false;
1615
3.12k
                try {
1616
3.12k
                    doMulti = ds.Get<bool>();
1617
3.12k
                } catch ( fuzzing::datasource::Base::OutOfData ) {
1618
2.72k
                }
1619
1620
3.12k
                if ( doMulti == false ) {
1621
2.86k
                    CF_NORET(blst_p1_add_affine(&result, &a, &aff_b));
1622
2.86k
                } else {
1623
260
                    const blst_p1_affine *const points[2] = {&aff_a, &aff_b};
1624
260
                    CF_NORET(blst_p1s_add(&result, points, 2));
1625
260
                }
1626
3.12k
            } else {
1627
344
                CF_NORET(blst_p1_add(&result, &a, &b));
1628
344
            }
1629
3.46k
            break;
1630
3.46k
        case    1:
1631
114
            CF_NORET(blst_p1_double(&result, &a));
1632
114
            break;
1633
337
        case    2:
1634
337
            if ( doAffine == true ) {
1635
203
                CF_NORET(blst_p1_add_or_double_affine(&result, &a, &aff_b));
1636
203
            } else {
1637
134
                CF_NORET(blst_p1_add_or_double(&result, &a, &b));
1638
134
            }
1639
337
            break;
1640
0
        default:
1641
0
            CF_UNREACHABLE();
1642
3.91k
    }
1643
1644
3.91k
    CF_CHECK_TRUE(
1645
3.91k
            !blst_p1_affine_is_inf(&aff_a) &&
1646
3.91k
            blst_p1_affine_on_curve(&aff_a) &&
1647
3.91k
            blst_p1_affine_in_g1(&aff_a));
1648
144
    CF_CHECK_TRUE(
1649
144
            !blst_p1_affine_is_inf(&aff_b) &&
1650
144
            blst_p1_affine_on_curve(&aff_b) &&
1651
144
            blst_p1_affine_in_g1(&aff_b));
1652
1653
56
    CF_NORET(blst_p1_to_affine(&aff_result, &result));
1654
1655
56
    {
1656
56
        blst_detail::G1 g1(aff_result, ds);
1657
56
        ret = g1.To_Component_G1();
1658
56
    }
1659
1660
4.00k
end:
1661
4.00k
    return ret;
1662
56
}
1663
1664
2.48k
std::optional<component::G1> blst::OpBLS_G1_Mul(operation::BLS_G1_Mul& op) {
1665
2.48k
    std::optional<component::G1> ret = std::nullopt;
1666
2.48k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1667
1668
2.48k
    blst_p1_affine aff_result;
1669
2.48k
    std::optional<blst_p1> tmp;
1670
2.48k
    blst_p1 a, result;
1671
2.48k
    std::optional<std::vector<uint8_t>> b;
1672
1673
2.48k
    CF_CHECK_NE(tmp = blst_detail::Load_G1_Projective(ds, op.a), std::nullopt);
1674
2.45k
    a = *tmp;
1675
1676
2.45k
    CF_CHECK_NE(b = util::DecToBin(op.b.ToTrimmedString()), std::nullopt);
1677
1678
2.45k
    {
1679
2.45k
        std::vector<uint8_t> b_reversed = util::AddLeadingZeroes(ds, *b);
1680
2.45k
        CF_NORET(std::reverse(b_reversed.begin(), b_reversed.end()));
1681
1682
2.45k
        Buffer B(b_reversed);
1683
1684
2.45k
        CF_NORET(blst_p1_mult(&result, &a, B.GetPtr(&ds), B.GetSize() * 8));
1685
2.45k
    }
1686
1687
2.45k
    CF_NORET(blst_p1_to_affine(&aff_result, &result));
1688
1689
2.45k
    CF_CHECK_TRUE(
1690
2.45k
            !blst_p1_is_inf(&a) &&
1691
2.45k
            blst_p1_on_curve(&a) &&
1692
2.45k
            blst_p1_in_g1(&a));
1693
1694
134
    {
1695
134
        blst_detail::G1 g1(aff_result, ds);
1696
134
        ret = g1.To_Component_G1();
1697
134
    }
1698
1699
2.48k
end:
1700
2.48k
    return ret;
1701
134
}
1702
1703
303
std::optional<bool> blst::OpBLS_G1_IsEq(operation::BLS_G1_IsEq& op) {
1704
303
    std::optional<bool> ret = std::nullopt;
1705
303
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1706
1707
303
    std::optional<blst_p1_affine> aff_tmp;
1708
303
    blst_p1_affine aff_a, aff_b;
1709
1710
303
    std::optional<blst_p1> tmp;
1711
303
    blst_p1 a, b;
1712
1713
303
    bool doAffine = false;
1714
1715
303
    CF_CHECK_NE(aff_tmp = blst_detail::Load_G1_Affine(op.a), std::nullopt);
1716
261
    aff_a = *aff_tmp;
1717
1718
261
    CF_CHECK_NE(aff_tmp = blst_detail::Load_G1_Affine(op.b), std::nullopt);
1719
218
    aff_b = *aff_tmp;
1720
1721
218
    CF_CHECK_NE(tmp = blst_detail::Load_G1_Projective(ds, op.a), std::nullopt);
1722
218
    a = *tmp;
1723
1724
218
    CF_CHECK_NE(tmp = blst_detail::Load_G1_Projective(ds, op.b), std::nullopt);
1725
218
    b = *tmp;
1726
1727
218
    try {
1728
218
        doAffine = ds.Get<bool>();
1729
218
    } catch ( fuzzing::datasource::Base::OutOfData ) {
1730
117
    }
1731
1732
218
    if ( doAffine == true ) {
1733
79
        ret = blst_p1_affine_is_equal(&aff_a, &aff_b);
1734
139
    } else {
1735
139
        ret = blst_p1_is_equal(&a, &b);
1736
139
    }
1737
1738
303
end:
1739
303
    return ret;
1740
218
}
1741
1742
2.83k
std::optional<component::G1> blst::OpBLS_G1_Neg(operation::BLS_G1_Neg& op) {
1743
2.83k
    std::optional<component::G1> ret = std::nullopt;
1744
2.83k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1745
1746
2.83k
    blst_p1_affine aff_result;
1747
2.83k
    std::optional<blst_p1> tmp;
1748
2.83k
    blst_p1 a;
1749
1750
2.83k
    CF_CHECK_NE(tmp = blst_detail::Load_G1_Projective(ds, op.a), std::nullopt);
1751
2.79k
    a = *tmp;
1752
1753
2.79k
    CF_NORET(blst_p1_cneg(&a, true));
1754
1755
2.79k
    CF_NORET(blst_p1_to_affine(&aff_result, &a));
1756
1757
2.79k
    {
1758
2.79k
        blst_detail::G1 g1(aff_result, ds);
1759
2.79k
        ret = g1.To_Component_G1();
1760
2.79k
    }
1761
1762
2.83k
end:
1763
2.83k
    return ret;
1764
2.79k
}
1765
1766
3.99k
std::optional<component::G2> blst::OpBLS_G2_Add(operation::BLS_G2_Add& op) {
1767
3.99k
    std::optional<component::G2> ret = std::nullopt;
1768
3.99k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1769
1770
3.99k
    blst_p2_affine a, b, result_;
1771
3.99k
    blst_p2 a_, b_, result;
1772
3.99k
    bool doDouble = false;
1773
1774
3.99k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.first.first, a.x.fp[0]));
1775
3.97k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.first.second, a.y.fp[0]));
1776
3.95k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.second.first, a.x.fp[1]));
1777
3.93k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.second.second, a.y.fp[1]));
1778
1779
3.91k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.b.first.first, b.x.fp[0]));
1780
3.89k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.b.first.second, b.y.fp[0]));
1781
3.87k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.b.second.first, b.x.fp[1]));
1782
3.85k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.b.second.second, b.y.fp[1]));
1783
1784
3.82k
    CF_NORET(blst_p2_from_affine(&a_, &a));
1785
3.82k
    CF_NORET(blst_p2_from_affine(&b_, &b));
1786
1787
3.82k
    if ( blst_p2_is_equal(&a_, &b_) ) {
1788
93
        try {
1789
93
            doDouble = ds.Get<bool>();
1790
93
        } catch ( fuzzing::datasource::Base::OutOfData ) {
1791
45
        }
1792
93
    }
1793
1794
3.82k
    if ( doDouble == false ) {
1795
3.78k
        CF_NORET(blst_p2_add_or_double_affine(&result, &a_, &b));
1796
3.78k
    } else {
1797
40
        CF_NORET(blst_p2_double(&result, &a_));
1798
40
    }
1799
1800
1801
3.82k
    CF_NORET(blst_p2_to_affine(&result_, &result));
1802
1803
3.82k
    ret = blst_detail::To_G2(result_);
1804
1805
3.99k
end:
1806
3.99k
    return ret;
1807
3.82k
}
1808
1809
7.86k
std::optional<component::G2> blst::OpBLS_G2_Mul(operation::BLS_G2_Mul& op) {
1810
7.86k
    std::optional<component::G2> ret = std::nullopt;
1811
7.86k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1812
1813
7.86k
    blst_p2_affine a, result_;
1814
7.86k
    blst_p2 a_, result;
1815
7.86k
    std::optional<std::vector<uint8_t>> b;
1816
7.86k
    bool doDouble = false;
1817
1818
7.86k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.first.first, a.x.fp[0]));
1819
7.84k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.first.second, a.y.fp[0]));
1820
7.82k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.second.first, a.x.fp[1]));
1821
7.78k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.second.second, a.y.fp[1]));
1822
7.76k
    CF_CHECK_NE(b = util::DecToBin(op.b.ToTrimmedString()), std::nullopt);
1823
1824
7.76k
    if ( !(blst_p2_affine_on_curve(&a) && blst_p2_affine_in_g2(&a)) ) {
1825
7.18k
        return ret;
1826
7.18k
    }
1827
1828
578
    CF_NORET(blst_p2_from_affine(&a_, &a));
1829
1830
578
    if ( op.b.ToTrimmedString() == "2" ) {
1831
73
        try {
1832
73
            doDouble = ds.Get<bool>();
1833
73
        } catch ( fuzzing::datasource::Base::OutOfData ) {
1834
33
        }
1835
73
    }
1836
1837
578
    if ( doDouble == false ) {
1838
543
        std::vector<uint8_t> b_reversed = util::AddLeadingZeroes(ds, *b);
1839
543
        CF_NORET(std::reverse(b_reversed.begin(), b_reversed.end()));
1840
1841
543
        Buffer B(b_reversed);
1842
1843
543
        CF_NORET(blst_p2_mult(&result, &a_, B.GetPtr(&ds), B.GetSize() * 8));
1844
543
    } else {
1845
35
        CF_NORET(blst_p2_double(&result, &a_));
1846
35
    }
1847
1848
578
    CF_NORET(blst_p2_to_affine(&result_, &result));
1849
1850
578
    ret = blst_detail::To_G2(result_);
1851
1852
672
end:
1853
672
    return ret;
1854
578
}
1855
1856
264
std::optional<bool> blst::OpBLS_G2_IsEq(operation::BLS_G2_IsEq& op) {
1857
264
    std::optional<bool> ret = std::nullopt;
1858
1859
264
    blst_p2_affine a, b;
1860
264
    blst_p2 a_, b_;
1861
1862
264
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.first.first, a.x.fp[0]));
1863
244
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.first.second, a.y.fp[0]));
1864
223
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.second.first, a.x.fp[1]));
1865
191
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.second.second, a.y.fp[1]));
1866
1867
167
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.b.first.first, b.x.fp[0]));
1868
146
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.b.first.second, b.y.fp[0]));
1869
121
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.b.second.first, b.x.fp[1]));
1870
101
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.b.second.second, b.y.fp[1]));
1871
1872
81
    CF_NORET(blst_p2_from_affine(&a_, &a));
1873
81
    CF_NORET(blst_p2_from_affine(&b_, &b));
1874
1875
81
    ret = blst_p2_is_equal(&a_, &b_);
1876
1877
264
end:
1878
264
    return ret;
1879
81
}
1880
1881
2.55k
std::optional<component::G2> blst::OpBLS_G2_Neg(operation::BLS_G2_Neg& op) {
1882
2.55k
    std::optional<component::G2> ret = std::nullopt;
1883
2.55k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1884
1885
2.55k
    blst_p2_affine a;
1886
2.55k
    blst_p2 a_;
1887
1888
2.55k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.first.first, a.x.fp[0]));
1889
2.53k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.first.second, a.y.fp[0]));
1890
2.50k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.second.first, a.x.fp[1]));
1891
2.48k
    CF_CHECK_TRUE(blst_detail::To_blst_fp(op.a.second.second, a.y.fp[1]));
1892
1893
2.46k
    CF_NORET(blst_p2_from_affine(&a_, &a));
1894
1895
2.46k
    CF_NORET(blst_p2_cneg(&a_, true));
1896
1897
2.46k
    CF_NORET(blst_p2_to_affine(&a, &a_));
1898
1899
2.46k
    ret = blst_detail::To_G2(a);
1900
1901
2.55k
end:
1902
2.55k
    return ret;
1903
2.46k
}
1904
1905
0
std::optional<component::G1> blst::OpBLS_G1_MultiExp(operation::BLS_G1_MultiExp& op) {
1906
0
    std::optional<component::G1> ret = std::nullopt;
1907
0
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1908
1909
0
    const size_t num = op.points_scalars.points_scalars.size();
1910
    /* blst_p1s_mult_pippenger crashes with num == 0
1911
     * blst_p1s_mult_pippenger OOB read with num == 1
1912
     */
1913
0
    if ( num < 2 ) return std::nullopt;
1914
1915
0
    blst_p1_affine* points = (blst_p1_affine*)util::malloc(num * sizeof(blst_p1_affine));
1916
0
    const blst_p1_affine* points_ptrs[2] = {points, nullptr};
1917
0
    blst_scalar* scalars = (blst_scalar*)util::malloc(num * sizeof(blst_scalar));
1918
0
    const uint8_t* scalars_ptrs[2] = {(uint8_t*)scalars, nullptr};
1919
1920
0
    uint8_t* scratch = util::malloc(blst_p1s_mult_pippenger_scratch_sizeof(num));
1921
1922
0
    bool points_are_valid = true;
1923
1924
0
    for (size_t i = 0; i < num; i++) {
1925
0
        const auto& cur = op.points_scalars.points_scalars[i];
1926
1927
0
        std::optional<blst_p1_affine> point;
1928
0
        CF_CHECK_NE(point = blst_detail::Load_G1_Affine(cur.first), std::nullopt);
1929
0
        points[i] = *point;
1930
1931
0
        points_are_valid &=
1932
0
            !blst_p1_affine_is_inf(&*point) &&
1933
0
            blst_p1_affine_on_curve(&*point) &&
1934
0
            blst_p1_affine_in_g1(&*point);
1935
1936
0
        CF_CHECK_TRUE(blst_detail::To_blst_scalar(cur.second, scalars[i]));
1937
0
    }
1938
1939
0
    {
1940
0
        blst_p1 res;
1941
0
        CF_NORET(blst_p1s_mult_pippenger(
1942
0
                    &res,
1943
0
                    points_ptrs, num,
1944
0
                    scalars_ptrs, sizeof(blst_scalar) * 8,
1945
0
                    (limb_t*)scratch));
1946
1947
0
        CF_CHECK_TRUE(points_are_valid);
1948
1949
0
        blst_p1_affine res_affine;
1950
0
        CF_NORET(blst_p1_to_affine(&res_affine, &res));
1951
0
        blst_detail::G1 g1(res_affine, ds);
1952
0
        ret = g1.To_Component_G1();
1953
0
    }
1954
1955
0
end:
1956
0
    util::free(points);
1957
0
    util::free(scalars);
1958
0
    util::free(scratch);
1959
1960
0
    return ret;
1961
0
}
1962
1963
858
std::optional<Buffer> blst::OpMisc(operation::Misc& op) {
1964
858
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1965
1966
858
    try {
1967
858
        switch ( op.operation.Get() ) {
1968
80
            case    0:
1969
80
                {
1970
80
                    const auto data = ds.GetData(0, 48, 48);
1971
80
                    blst_p1_affine point;
1972
80
                    CF_CHECK_EQ(blst_p1_uncompress(&point, data.data()), BLST_SUCCESS);
1973
51
                    uint8_t out[48];
1974
51
                    CF_NORET(blst_p1_affine_compress(out, &point));
1975
51
                    if ( blst_p1_affine_on_curve(&point) ) {
1976
20
                        CF_ASSERT(memcmp(data.data(), out, data.size()) == 0, "Serialization asymmetry");
1977
20
                    }
1978
51
                }
1979
51
                break;
1980
145
            case    1:
1981
145
                {
1982
145
                    const auto data = ds.GetData(0, 96, 96);
1983
145
                    blst_p1_affine point;
1984
145
                    CF_CHECK_EQ(blst_p1_deserialize(&point, data.data()), BLST_SUCCESS);
1985
57
                    uint8_t out[96];
1986
57
                    CF_NORET(blst_p1_affine_serialize(out, &point));
1987
57
                    if ( blst_p1_affine_on_curve(&point) ) {
1988
20
                        blst_p1_affine point2;
1989
20
                        CF_ASSERT(blst_p1_deserialize(&point2, out) == BLST_SUCCESS, "Cannot deserialize serialized point");
1990
1991
20
                        uint8_t out2[96];
1992
20
                        CF_NORET(blst_p1_affine_serialize(out2, &point2));
1993
20
                        CF_ASSERT(memcmp(out, out2, sizeof(out)) == 0, "Serialization asymmetry");
1994
                        //CF_ASSERT(memcmp(data.data(), out, data.size()) == 0, "Serialization asymmetry");
1995
20
                    }
1996
57
                }
1997
57
                break;
1998
98
            case    2:
1999
98
                {
2000
98
                    const auto data = ds.GetData(0, 96, 96);
2001
98
                    blst_p2_affine point;
2002
98
                    CF_CHECK_EQ(blst_p2_uncompress(&point, data.data()), BLST_SUCCESS);
2003
52
                    uint8_t out[96];
2004
52
                    CF_NORET(blst_p2_affine_compress(out, &point));
2005
52
                    if ( blst_p2_affine_on_curve(&point) ) {
2006
21
                        CF_ASSERT(memcmp(data.data(), out, data.size()) == 0, "Serialization asymmetry");
2007
21
                    }
2008
52
                }
2009
52
                break;
2010
151
            case    3:
2011
151
                {
2012
151
                    const auto data = ds.GetData(0, 192, 192);
2013
151
                    blst_p2_affine point;
2014
151
                    CF_CHECK_EQ(blst_p2_deserialize(&point, data.data()), BLST_SUCCESS);
2015
54
                    uint8_t out[192];
2016
54
                    CF_NORET(blst_p2_affine_serialize(out, &point));
2017
54
                    if ( blst_p2_affine_on_curve(&point) ) {
2018
20
                        blst_p2_affine point2;
2019
20
                        CF_ASSERT(blst_p2_deserialize(&point2, out) == BLST_SUCCESS, "Cannot deserialize serialized point");
2020
2021
20
                        uint8_t out2[192];
2022
20
                        CF_NORET(blst_p2_affine_serialize(out2, &point2));
2023
20
                        CF_ASSERT(memcmp(out, out2, sizeof(out)) == 0, "Serialization asymmetry");
2024
                        //CF_ASSERT(memcmp(data.data(), out, data.size()) == 0, "Serialization asymmetry");
2025
20
                    }
2026
54
                }
2027
54
                break;
2028
85
            case    4:
2029
85
                {
2030
85
                    blst_p1_affine point;
2031
85
                    {
2032
85
                        const auto data = ds.GetData(0, 96, 96);
2033
85
                        CF_CHECK_EQ(blst_p1_deserialize(&point, data.data()), BLST_SUCCESS);
2034
53
                    }
2035
2036
0
                    blst_fp6 Qlines[68];
2037
53
                    {
2038
53
                        const auto data = ds.GetData(0, sizeof(Qlines), sizeof(Qlines));
2039
53
                        memcpy(Qlines, data.data(), sizeof(Qlines));
2040
53
                    }
2041
2042
53
                    blst_fp12 out;
2043
53
                    CF_NORET(blst_miller_loop_lines(&out, Qlines, &point));
2044
53
                }
2045
0
                break;
2046
109
            case    5:
2047
109
                {
2048
109
                    blst_p2_affine point;
2049
109
                    {
2050
109
                        const auto data = ds.GetData(0, 192, 192);
2051
109
                        CF_CHECK_EQ(blst_p2_deserialize(&point, data.data()), BLST_SUCCESS);
2052
58
                    }
2053
2054
0
                    blst_fp6 Qlines[68];
2055
58
                    CF_NORET(blst_precompute_lines(Qlines, &point));
2056
58
                }
2057
0
                break;
2058
142
            case    6:
2059
142
                {
2060
142
                    blst_fp12 out;
2061
142
                    blst_p1_affine p1;
2062
142
                    blst_p2_affine p2;
2063
2064
142
                    {
2065
142
                        const auto data = ds.GetData(0, 96, 96);
2066
142
                        CF_CHECK_EQ(blst_p1_deserialize(&p1, data.data()), BLST_SUCCESS);
2067
117
                    }
2068
2069
0
                    {
2070
117
                        const auto data = ds.GetData(0, 192, 192);
2071
117
                        CF_CHECK_EQ(blst_p2_deserialize(&p2, data.data()), BLST_SUCCESS);
2072
90
                    }
2073
2074
90
                    CF_NORET(blst_miller_loop(&out, &p2, &p1));
2075
90
                }
2076
0
                break;
2077
858
        }
2078
858
    } catch ( fuzzing::datasource::Base::OutOfData ) { }
2079
2080
858
end:
2081
858
    return std::nullopt;
2082
858
}
2083
2084
14.8k
bool blst::SupportsModularBignumCalc(void) const {
2085
14.8k
    return true;
2086
14.8k
}
2087
2088
} /* namespace module */
2089
} /* namespace cryptofuzz */