Coverage Report

Created: 2025-03-09 06:52

/src/cryptofuzz/modules/libgmp/bn_ops.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <cryptofuzz/util.h>
2
#include <cryptofuzz/repository.h>
3
#include <fuzzing/datasource/id.hpp>
4
5
#include "bn_ops.h"
6
7
6.21k
#define GET_WHICH(max) uint8_t which = 0; try { which = ds.Get<uint8_t>(); which %= ((max)+1); } catch ( ... ) { }
8
9
namespace cryptofuzz {
10
namespace module {
11
#if !defined(HAVE_MINI_GMP)
12
namespace libgmp_detail {
13
    extern gmp_randstate_t rng_state;
14
}
15
#endif
16
namespace libgmp_bignum {
17
18
121
bool Add::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
19
121
    bool ret = false;
20
21
121
    GET_WHICH(1);
22
121
    switch ( which ) {
23
39
        case    0:
24
39
            /* noret */ mpz_add(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
25
39
            CF_NORET(bn.CopyResult(res));
26
39
            break;
27
82
        case    1:
28
82
            {
29
82
                const auto bn1 = bn[1].GetUnsignedLong();
30
82
                CF_CHECK_NE(bn1, std::nullopt);
31
32
64
                /* noret */ mpz_add_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
33
64
                CF_NORET(bn.CopyResult(res));
34
64
            }
35
0
            break;
36
0
        default:
37
0
            return false;
38
121
    }
39
40
103
    ret = true;
41
42
121
end:
43
121
    return ret;
44
103
}
45
46
148
bool Sub::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
47
148
    bool ret = false;
48
49
148
    GET_WHICH(2);
50
148
    switch ( which ) {
51
30
        case    0:
52
30
            /* noret */ mpz_sub(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
53
30
            CF_NORET(bn.CopyResult(res));
54
30
            break;
55
52
        case    1:
56
52
            {
57
52
                const auto bn1 = bn[1].GetUnsignedLong();
58
52
                CF_CHECK_NE(bn1, std::nullopt);
59
60
49
                /* noret */ mpz_sub_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
61
49
                CF_NORET(bn.CopyResult(res));
62
49
            }
63
0
            break;
64
66
        case    2:
65
66
            {
66
66
                const auto bn0 = bn[0].GetUnsignedLong();
67
66
                CF_CHECK_NE(bn0, std::nullopt);
68
69
62
                /* noret */ mpz_ui_sub(bn.GetResPtr(), *bn0, bn[1].GetPtr());
70
62
                CF_NORET(bn.CopyResult(res));
71
62
            }
72
0
            break;
73
0
        default:
74
0
            return false;
75
148
    }
76
77
141
    ret = true;
78
79
148
end:
80
148
    return ret;
81
141
}
82
83
115
bool Mul::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
84
115
    bool ret = false;
85
86
115
    GET_WHICH(2);
87
115
    switch ( which ) {
88
37
        case    0:
89
37
            /* noret */ mpz_mul(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
90
37
            CF_NORET(bn.CopyResult(res));
91
37
            break;
92
41
        case    1:
93
41
            {
94
41
                const auto bn1 = bn[1].GetUnsignedLong();
95
41
                CF_CHECK_NE(bn1, std::nullopt);
96
97
36
                /* noret */ mpz_mul_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
98
36
                CF_NORET(bn.CopyResult(res));
99
36
            }
100
0
            break;
101
37
        case    2:
102
37
            {
103
37
                const auto bn1 = bn[1].GetSignedLong();
104
37
                CF_CHECK_NE(bn1, std::nullopt);
105
106
35
                /* noret */ mpz_mul_si(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
107
35
                CF_NORET(bn.CopyResult(res));
108
35
            }
109
0
            break;
110
0
        default:
111
0
            return false;
112
115
    }
113
114
108
    ret = true;
115
116
115
end:
117
115
    return ret;
118
108
}
119
120
335
bool Div::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
121
335
    bool ret = false;
122
123
335
    GET_WHICH(3);
124
335
    switch ( which ) {
125
0
#if !defined(HAVE_MINI_GMP)
126
119
        case    0:
127
119
            CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
128
129
106
            /* noret */ mpz_div(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
130
106
            CF_NORET(bn.CopyResult(res));
131
106
            break;
132
57
        case    1:
133
57
            {
134
57
                CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
135
136
51
                const auto bn1 = bn[1].GetUnsignedLong();
137
51
                CF_CHECK_NE(bn1, std::nullopt);
138
139
39
                /* noret */ mpz_div_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
140
39
                CF_NORET(bn.CopyResult(res));
141
39
            }
142
0
            break;
143
0
#endif
144
95
        case    2:
145
95
            {
146
95
                CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
147
148
82
                CF_CHECK_NE(mpz_divisible_p(bn[0].GetPtr(), bn[1].GetPtr()), 0);
149
150
24
                /* noret */ mpz_divexact(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
151
24
                CF_NORET(bn.CopyResult(res));
152
24
            }
153
0
            break;
154
64
        case    3:
155
64
            {
156
64
                CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
157
158
53
                const auto bn1 = bn[1].GetUnsignedLong();
159
53
                CF_CHECK_NE(bn1, std::nullopt);
160
161
40
                CF_CHECK_NE(mpz_divisible_ui_p(bn[0].GetPtr(), *bn1), 0);
162
163
21
                /* noret */ mpz_divexact_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
164
21
                CF_NORET(bn.CopyResult(res));
165
21
            }
166
0
            break;
167
0
        default:
168
0
            return false;
169
335
    }
170
171
    /* Negative not supported */
172
190
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
173
96
    CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
174
175
71
    ret = true;
176
177
335
end:
178
335
    return ret;
179
71
}
180
181
1.63k
bool ExpMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
182
1.63k
    bool ret = false;
183
184
1.63k
    GET_WHICH(2);
185
186
1.63k
    CF_CHECK_NE(mpz_cmp_ui(bn[2].GetPtr(), 0), 0);
187
188
#if defined(HAVE_MINI_GMP)
189
    /* Avoid timeouts */
190
    CF_CHECK_LTE(mpz_sizeinbase(bn[0].GetPtr(), 2), 2000);
191
    CF_CHECK_LTE(mpz_sizeinbase(bn[1].GetPtr(), 2), 2000);
192
    CF_CHECK_LTE(mpz_sizeinbase(bn[2].GetPtr(), 2), 2000);
193
#endif
194
195
1.58k
    switch ( which ) {
196
1.19k
        case    0:
197
            /* "Negative exp is supported if the inverse base-1 mod mod exists.
198
             *  If an inverse doesn’t exist then a divide by zero is raised."
199
             */
200
1.19k
            CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
201
202
1.19k
            /* noret */ mpz_powm(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr());
203
1.19k
            CF_NORET(bn.CopyResult(res));
204
1.19k
            break;
205
196
        case    1:
206
196
            {
207
196
                const auto bn1 = bn[1].GetUnsignedLong();
208
196
                CF_CHECK_NE(bn1, std::nullopt);
209
210
176
                /* noret */ mpz_powm_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1, bn[2].GetPtr());
211
176
                CF_NORET(bn.CopyResult(res));
212
176
            }
213
0
            break;
214
0
#if !defined(HAVE_MINI_GMP)
215
191
        case    2:
216
191
            {
217
191
                CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
218
219
                /* "It is required that exp > 0 and that mod is odd." */
220
189
                CF_CHECK_GT(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
221
222
172
                const auto ptr = bn[2].GetPtr();
223
172
                CF_CHECK_EQ(mpz_odd_p(ptr), 1);
224
225
132
                /* noret */ mpz_powm_sec(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr());
226
132
                CF_NORET(bn.CopyResult(res));
227
132
            }
228
0
            break;
229
0
#endif
230
0
        default:
231
0
            return false;
232
1.58k
    }
233
234
1.49k
    ret = true;
235
236
1.63k
end:
237
1.63k
    return ret;
238
1.49k
}
239
240
enum GCDType : uint8_t {
241
    GCD = 0,
242
    ExtGCD_X = 1,
243
    ExtGCD_Y = 2,
244
};
245
246
189
static void GCD_ExtGCD_SetResult(mpz_ptr res, const mpz_ptr X, const mpz_ptr Y, const GCDType type) {
247
189
    if ( type == GCDType::GCD ) {
248
        /* do nothing */
249
129
    } else if ( type == GCDType::ExtGCD_X ) {
250
27
        /* noret */ mpz_set(res, X);
251
33
    } else if ( type == GCDType::ExtGCD_Y ) {
252
33
        /* noret */ mpz_set(res, Y);
253
33
    } else {
254
0
        CF_UNREACHABLE();
255
0
    }
256
189
}
257
258
598
static bool GCD_ExtGCD(Datasource& ds, Bignum& res, BignumCluster& bn, const GCDType type) {
259
598
    bool ret = false;
260
261
598
    GET_WHICH(2);
262
598
    switch ( which ) {
263
321
        case    0:
264
321
            CF_CHECK_EQ(type, GCDType::GCD);
265
313
            /* noret */ mpz_gcd(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
266
313
            CF_NORET(bn.CopyResult(res));
267
313
            break;
268
88
        case    1:
269
88
            {
270
88
                CF_CHECK_EQ(type, GCDType::GCD);
271
272
80
                const auto bn1 = bn[1].GetUnsignedLong();
273
80
                CF_CHECK_NE(bn1, std::nullopt);
274
275
75
                /* ignore ret */ mpz_gcd_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
276
75
                CF_NORET(bn.CopyResult(res));
277
75
            }
278
0
            break;
279
189
        case    2:
280
189
            {
281
189
                Bignum t1, t2;
282
283
189
                /* noret */ mpz_gcdext(res.GetPtr(), t1.GetPtr(), t2.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
284
189
                CF_NORET(GCD_ExtGCD_SetResult(res.GetPtr(), t1.GetPtr(), t2.GetPtr(), type));
285
189
            }
286
189
            break;
287
0
        default:
288
0
            return false;
289
598
    }
290
291
577
    ret = true;
292
293
598
end:
294
598
    return ret;
295
577
}
296
297
522
bool GCD::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
298
522
    return GCD_ExtGCD(ds, res, bn, GCDType::GCD);
299
522
}
300
301
41
bool ExtGCD_X::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
302
41
    return GCD_ExtGCD(ds, res, bn, GCDType::ExtGCD_X);
303
41
}
304
305
35
bool ExtGCD_Y::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
306
35
    return GCD_ExtGCD(ds, res, bn, GCDType::ExtGCD_Y);
307
35
}
308
309
1.19k
bool Jacobi::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
310
1.19k
#if !defined(HAVE_MINI_GMP)
311
1.19k
    GET_WHICH(2);
312
1.19k
    switch ( which ) {
313
1.02k
        case    0:
314
1.02k
            res.Set( std::to_string(mpz_jacobi(bn[0].GetPtr(), bn[1].GetPtr())) );
315
1.02k
            return true;
316
103
        case    1:
317
103
            {
318
103
                const auto bn1 = bn[1].GetSignedLong();
319
103
                CF_CHECK_NE(bn1, std::nullopt);
320
92
                res.Set( std::to_string(mpz_kronecker_si(bn[0].GetPtr(), *bn1)) );
321
92
            }
322
0
            return true;
323
62
        case    2:
324
62
            {
325
62
                const auto bn1 = bn[1].GetUnsignedLong();
326
62
                CF_CHECK_NE(bn1, std::nullopt);
327
44
                res.Set( std::to_string(mpz_kronecker_ui(bn[0].GetPtr(), *bn1)) );
328
44
            }
329
0
            return true;
330
0
        default:
331
0
            return false;
332
1.19k
    }
333
334
29
end:
335
29
    return false;
336
#else
337
    (void)ds;
338
    (void)res;
339
    (void)bn;
340
341
    return false;
342
#endif
343
1.19k
}
344
345
94
bool Cmp::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
346
94
    bool ret = false;
347
348
94
    int cmp;
349
350
94
    GET_WHICH(2);
351
94
    switch ( which ) {
352
34
        case    0:
353
34
            cmp = mpz_cmp(bn[0].GetPtr(), bn[1].GetPtr());
354
34
            break;
355
36
        case    1:
356
36
            {
357
36
                const auto bn1 = bn[1].GetSignedLong();
358
36
                CF_CHECK_NE(bn1, std::nullopt);
359
360
33
                cmp = mpz_cmp_si(bn[0].GetPtr(), *bn1);
361
33
            }
362
0
            break;
363
24
        case    2:
364
24
            {
365
24
                const auto bn1 = bn[1].GetUnsignedLong();
366
24
                CF_CHECK_NE(bn1, std::nullopt);
367
368
19
                cmp = mpz_cmp_ui(bn[0].GetPtr(), *bn1);
369
19
            }
370
0
            break;
371
0
        default:
372
0
            goto end;
373
94
    }
374
375
86
    if ( cmp < 0 ) {
376
20
        res.Set("-1");
377
66
    } else if ( cmp > 0 ) {
378
39
        res.Set("1");
379
39
    } else {
380
27
        res.Set("0");
381
27
    }
382
383
86
    ret = true;
384
385
94
end:
386
94
    return ret;
387
86
}
388
389
305
bool LCM::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
390
305
    bool ret = false;
391
392
305
    GET_WHICH(1);
393
305
    switch ( which ) {
394
272
        case    0:
395
272
            /* noret */ mpz_lcm(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
396
272
            CF_NORET(bn.CopyResult(res));
397
272
            break;
398
33
        case    1:
399
33
            {
400
33
                const auto bn1 = bn[1].GetUnsignedLong();
401
33
                CF_CHECK_NE(bn1, std::nullopt);
402
403
27
                /* noret */ mpz_lcm_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
404
27
                CF_NORET(bn.CopyResult(res));
405
27
            }
406
0
            break;
407
0
        default:
408
0
            return false;
409
305
    }
410
411
    /* Negative not supported */
412
299
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
413
292
    CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
414
415
268
    ret = true;
416
417
305
end:
418
305
    return ret;
419
268
}
420
421
99
bool Xor::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
422
99
    (void)ds;
423
424
99
    /* noret */ mpz_xor(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
425
99
    CF_NORET(bn.CopyResult(res));
426
427
99
    return true;
428
99
}
429
430
124
bool And::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
431
124
    (void)ds;
432
433
124
    /* noret */ mpz_and(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
434
124
    CF_NORET(bn.CopyResult(res));
435
436
124
    return true;
437
124
}
438
439
25
bool Abs::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
440
25
    (void)ds;
441
442
25
    /* noret */ mpz_abs(bn.GetResPtr(), bn[0].GetPtr());
443
25
    CF_NORET(bn.CopyResult(res));
444
445
25
    return true;
446
25
}
447
448
21
bool Neg::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
449
21
    (void)ds;
450
451
21
    /* noret */ mpz_neg(bn.GetResPtr(), bn[0].GetPtr());
452
21
    CF_NORET(bn.CopyResult(res));
453
454
21
    return true;
455
21
}
456
457
124
bool Sqrt::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
458
124
    bool ret = false;
459
124
    (void)ds;
460
461
124
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
462
463
120
    /* noret */ mpz_sqrt(bn.GetResPtr(), bn[0].GetPtr());
464
120
    CF_NORET(bn.CopyResult(res));
465
120
    ret = true;
466
467
124
end:
468
124
    return ret;
469
120
}
470
471
569
bool SqrtCeil::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
472
569
    bool ret = false;
473
569
    (void)ds;
474
475
569
    libgmp_bignum::Bignum rem;
476
477
569
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
478
479
558
    /* noret */ mpz_sqrt(res.GetPtr(), bn[0].GetPtr());
480
558
    /* noret */ mpz_sqrtrem(bn[1].GetPtr(), rem.GetPtr(), bn[0].GetPtr());
481
558
    if ( mpz_sgn(rem.GetPtr()) != 0 ) {
482
519
        /* noret */ mpz_add_ui(res.GetPtr(), res.GetPtr(), 1);
483
519
    }
484
558
    ret = true;
485
486
569
end:
487
569
    return ret;
488
558
}
489
490
16
bool Sqr::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
491
16
    (void)ds;
492
493
16
    /* noret */ mpz_pow_ui(bn.GetResPtr(), bn[0].GetPtr(), 2);
494
16
    CF_NORET(bn.CopyResult(res));
495
496
16
    return true;
497
16
}
498
499
45
bool CmpAbs::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
500
45
    bool ret = false;
501
502
45
    int cmp;
503
504
45
    GET_WHICH(1);
505
45
    switch ( which ) {
506
26
        case    0:
507
26
            cmp = mpz_cmpabs(bn[0].GetPtr(), bn[1].GetPtr());
508
26
            break;
509
19
        case    1:
510
19
            {
511
19
                const auto bn1 = bn[1].GetUnsignedLong();
512
19
                CF_CHECK_NE(bn1, std::nullopt);
513
514
17
                cmp = mpz_cmpabs_ui(bn[0].GetPtr(), *bn1);
515
17
            }
516
0
            break;
517
0
        default:
518
0
            goto end;
519
45
    }
520
521
43
    if ( cmp < 0 ) {
522
5
        res.Set("-1");
523
38
    } else if ( cmp > 0 ) {
524
18
        res.Set("1");
525
20
    } else {
526
20
        res.Set("0");
527
20
    }
528
529
43
    ret = true;
530
531
45
end:
532
45
    return ret;
533
43
}
534
535
5
bool IsZero::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
536
5
    (void)ds;
537
538
5
    res.Set( std::to_string(mpz_sgn(bn[0].GetPtr()) == 0 ? 1 : 0) );
539
540
5
    return true;
541
5
}
542
543
17
bool IsNeg::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
544
17
    (void)ds;
545
546
17
    res.Set( std::to_string(mpz_sgn(bn[0].GetPtr()) < 0 ? 1 : 0) );
547
548
17
    return true;
549
17
}
550
551
44
bool AddMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
552
44
    (void)ds;
553
44
    bool ret = false;
554
555
44
    CF_CHECK_NE(mpz_cmp_ui(bn[2].GetPtr(), 0), 0);
556
557
28
    /* noret */ mpz_add(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
558
28
    /* noret */ mpz_mod(res.GetPtr(), res.GetPtr(), bn[2].GetPtr());
559
560
    /* Negative modulus currently not supported */
561
28
    CF_CHECK_GTE(mpz_sgn(bn[2].GetPtr()), 0);
562
563
15
    ret = true;
564
565
44
end:
566
44
    return ret;
567
15
}
568
569
53
bool SubMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
570
53
    (void)ds;
571
53
    bool ret = false;
572
573
53
    CF_CHECK_NE(mpz_cmp_ui(bn[2].GetPtr(), 0), 0);
574
575
42
    /* noret */ mpz_sub(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
576
42
    /* noret */ mpz_mod(res.GetPtr(), res.GetPtr(), bn[2].GetPtr());
577
578
    /* Negative modulus currently not supported */
579
42
    CF_CHECK_GTE(mpz_sgn(bn[2].GetPtr()), 0);
580
581
26
    ret = true;
582
583
53
end:
584
53
    return ret;
585
26
}
586
587
49
bool MulMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
588
49
    (void)ds;
589
49
    bool ret = false;
590
591
49
    CF_CHECK_NE(mpz_cmp_ui(bn[2].GetPtr(), 0), 0);
592
593
32
    /* noret */ mpz_mul(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
594
32
    /* noret */ mpz_mod(res.GetPtr(), res.GetPtr(), bn[2].GetPtr());
595
596
    /* Negative modulus currently not supported */
597
32
    CF_CHECK_GTE(mpz_sgn(bn[2].GetPtr()), 0);
598
599
25
    ret = true;
600
601
49
end:
602
49
    return ret;
603
25
}
604
605
21
bool SqrMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
606
21
    (void)ds;
607
21
    bool ret = false;
608
609
21
    CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
610
611
16
    /* noret */ mpz_pow_ui(res.GetPtr(), bn[0].GetPtr(), 2);
612
16
    /* noret */ mpz_mod(res.GetPtr(), res.GetPtr(), bn[1].GetPtr());
613
614
    /* Negative modulus currently not supported */
615
16
    CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
616
617
8
    ret = true;
618
619
21
end:
620
21
    return ret;
621
8
}
622
623
4
bool Mod_NIST_192::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
624
4
    (void)ds;
625
626
4
    Bignum p192;
627
4
    p192.Set("6277101735386680763835789423207666416083908700390324961279");
628
629
4
    /* noret */ mpz_mod(res.GetPtr(), bn[0].GetPtr(), p192.GetPtr());
630
631
4
    return true;
632
4
}
633
634
6
bool Mod_NIST_224::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
635
6
    (void)ds;
636
637
6
    Bignum p224;
638
6
    p224.Set("26959946667150639794667015087019630673557916260026308143510066298881");
639
640
6
    /* noret */ mpz_mod(res.GetPtr(), bn[0].GetPtr(), p224.GetPtr());
641
642
6
    return true;
643
6
}
644
645
3
bool Mod_NIST_256::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
646
3
    (void)ds;
647
648
3
    Bignum p256;
649
3
    p256.Set("115792089210356248762697446949407573530086143415290314195533631308867097853951");
650
651
3
    /* noret */ mpz_mod(res.GetPtr(), bn[0].GetPtr(), p256.GetPtr());
652
653
3
    return true;
654
3
}
655
656
55
bool Mod_NIST_384::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
657
55
    (void)ds;
658
659
55
    Bignum p384;
660
55
    p384.Set("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319");
661
662
55
    /* noret */ mpz_mod(res.GetPtr(), bn[0].GetPtr(), p384.GetPtr());
663
664
55
    return true;
665
55
}
666
667
6
bool Mod_NIST_521::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
668
6
    (void)ds;
669
670
6
    Bignum p521;
671
6
    p521.Set("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151");
672
673
6
    /* noret */ mpz_mod(res.GetPtr(), bn[0].GetPtr(), p521.GetPtr());
674
675
6
    return true;
676
6
}
677
678
24
bool SetBit::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
679
24
    (void)ds;
680
24
    bool ret = false;
681
682
24
    const auto position_sl = bn[1].GetSignedLong();
683
24
    CF_CHECK_NE(position_sl, std::nullopt);
684
24
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
685
21
    CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
686
687
20
    /* noret */ mpz_setbit(bn.GetDestPtr(0), *position_sl);
688
20
    /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
689
690
20
    ret = true;
691
692
24
end:
693
24
    return ret;
694
20
}
695
696
34
bool ClearBit::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
697
34
    (void)ds;
698
34
    bool ret = false;
699
700
34
    const auto position_sl = bn[1].GetSignedLong();
701
34
    CF_CHECK_NE(position_sl, std::nullopt);
702
29
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
703
704
22
    /* noret */ mpz_clrbit(bn.GetDestPtr(0), *position_sl);
705
22
    /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
706
707
22
    ret = true;
708
709
34
end:
710
34
    return ret;
711
22
}
712
713
17
bool Bit::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
714
17
    (void)ds;
715
17
    bool ret = false;
716
717
17
    const auto position_sl = bn[1].GetSignedLong();
718
17
    CF_CHECK_NE(position_sl, std::nullopt);
719
720
    /* Negative not supported */
721
16
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
722
723
15
    res.Set( std::to_string(mpz_tstbit(bn[0].GetPtr(), *position_sl)) );
724
725
15
    ret = true;
726
727
17
end:
728
17
    return ret;
729
15
}
730
731
1.37k
bool InvMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
732
1.37k
    (void)ds;
733
1.37k
    bool ret = false;
734
735
    /* "The behaviour of this function is undefined when op2 is zero." */
736
1.37k
    CF_CHECK_NE(mpz_sgn(bn[1].GetPtr()), 0);
737
738
1.36k
    if ( mpz_invert(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr()) == 0 ) {
739
        /* Modular inverse does not exist */
740
959
        res.Set("0");
741
959
    } else {
742
404
        CF_NORET(bn.CopyResult(res));
743
404
    }
744
745
1.36k
    ret = true;
746
747
1.37k
end:
748
1.37k
    return ret;
749
1.36k
}
750
751
2
bool IsOdd::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
752
2
    (void)ds;
753
754
    /* "These macros evaluate their argument more than once." */
755
2
    const auto ptr = bn[0].GetPtr();
756
2
    res.Set( std::to_string(mpz_odd_p(ptr)) );
757
758
2
    return true;
759
2
}
760
761
7
bool IsEven::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
762
7
    (void)ds;
763
764
    /* "These macros evaluate their argument more than once." */
765
7
    const auto ptr = bn[0].GetPtr();
766
7
    res.Set( std::to_string(mpz_even_p(ptr)) );
767
768
7
    return true;
769
7
}
770
771
5
bool IsPow2::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
772
5
    (void)ds;
773
774
5
    if ( mpz_popcount(bn[0].GetPtr()) == 1 ) {
775
1
        res.Set("1");
776
4
    } else {
777
4
        res.Set("0");
778
4
    }
779
780
5
    return true;
781
5
}
782
783
12
bool NumLSZeroBits::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
784
12
    (void)ds;
785
786
12
    auto numBits = mpz_scan1(bn[0].GetPtr(), 0);
787
12
    if ( numBits == (mp_bitcnt_t)-1 ) {
788
1
        numBits = 0;
789
1
    }
790
12
    res.Set( std::to_string(numBits) );
791
792
12
    return true;
793
12
}
794
795
15
bool Factorial::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
796
15
    (void)ds;
797
15
    bool ret = false;
798
799
15
    const auto bn0 = bn[0].GetUnsignedLong();
800
15
    CF_CHECK_NE(bn0, std::nullopt);
801
14
    CF_CHECK_LTE(*bn0, 1500);
802
803
13
    CF_NORET(mpz_fac_ui(res.GetPtr(), *bn0));
804
805
13
    ret = true;
806
807
15
end:
808
15
    return ret;
809
13
}
810
811
145
bool Cbrt::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
812
145
    (void)ds;
813
814
145
    /* ignore ret */ mpz_root(bn.GetResPtr(), bn[0].GetPtr(), 3);
815
145
    CF_NORET(bn.CopyResult(res));
816
817
145
    return true;
818
145
}
819
820
10
bool SqrtRem::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
821
10
    bool ret = false;
822
10
    (void)ds;
823
824
10
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
825
826
9
    /* noret */ mpz_sqrtrem(bn[1].GetPtr(), res.GetPtr(), bn[0].GetPtr());
827
9
    ret = true;
828
829
10
end:
830
10
    return ret;
831
9
}
832
833
380
bool CbrtRem::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
834
380
    (void)ds;
835
836
380
    /* noret */ mpz_rootrem(bn[1].GetPtr(), res.GetPtr(), bn[0].GetPtr(), 3);
837
838
380
    return true;
839
380
}
840
841
156
bool Nthrt::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
842
/* Too slow in mini-gmp */
843
156
#if !defined(HAVE_MINI_GMP)
844
156
    (void)ds;
845
156
    bool ret = false;
846
847
156
    const auto bn1 = bn[1].GetUnsignedLong();
848
156
    CF_CHECK_NE(bn1, std::nullopt);
849
150
    CF_CHECK_NE(*bn1, 0);
850
140
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
851
852
135
    /* noret */ mpz_root(res.GetPtr(), bn[0].GetPtr(), *bn1);
853
854
135
    ret = true;
855
156
end:
856
156
    return ret;
857
#else
858
    (void)ds;
859
    (void)res;
860
    (void)bn;
861
862
    return false;
863
#endif
864
135
}
865
866
59
bool NthrtRem::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
867
/* Too slow in mini-gmp */
868
59
#if !defined(HAVE_MINI_GMP)
869
59
    (void)ds;
870
59
    bool ret = false;
871
872
59
    const auto bn1 = bn[1].GetUnsignedLong();
873
59
    CF_CHECK_NE(bn1, std::nullopt);
874
57
    CF_CHECK_NE(*bn1, 0);
875
46
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
876
877
45
    /* noret */ mpz_rootrem(bn[1].GetPtr(), res.GetPtr(), bn[0].GetPtr(), *bn1);
878
879
45
    ret = true;
880
59
end:
881
59
    return ret;
882
#else
883
    (void)ds;
884
    (void)res;
885
    (void)bn;
886
887
    return false;
888
#endif
889
45
}
890
891
85
bool IsSquare::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
892
85
#if !defined(HAVE_MINI_GMP)
893
85
    (void)ds;
894
895
85
    res.Set(
896
85
            mpz_perfect_square_p(bn[0].GetPtr()) == 0 ? std::string("0") : std::string("1")
897
85
    );
898
899
85
    return true;
900
#else
901
    (void)ds;
902
    (void)res;
903
    (void)bn;
904
905
    return false;
906
#endif
907
85
}
908
909
138
bool Exp::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
910
138
    bool ret = false;
911
912
138
    GET_WHICH(1);
913
138
    switch ( which ) {
914
134
        case    0:
915
134
            {
916
134
                const auto bn1 = bn[1].GetUnsignedLong();
917
134
                CF_CHECK_NE(bn1, std::nullopt);
918
919
126
                /* noret */ mpz_pow_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
920
126
                CF_NORET(bn.CopyResult(res));
921
126
            }
922
0
            break;
923
4
        case    1:
924
4
            {
925
4
                const auto bn0 = bn[0].GetUnsignedLong();
926
4
                CF_CHECK_NE(bn0, std::nullopt);
927
928
4
                const auto bn1 = bn[1].GetUnsignedLong();
929
4
                CF_CHECK_NE(bn1, std::nullopt);
930
931
3
                /* noret */ mpz_ui_pow_ui(bn.GetResPtr(), *bn0, *bn1);
932
3
                CF_NORET(bn.CopyResult(res));
933
3
            }
934
0
            break;
935
0
        default:
936
0
            return false;
937
138
    }
938
939
129
    ret = true;
940
941
138
end:
942
138
    return ret;
943
129
}
944
945
125
bool Or::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
946
125
    (void)ds;
947
948
125
    /* noret */ mpz_ior(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
949
950
125
    return true;
951
125
}
952
953
123
bool AddMul::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
954
123
    bool ret = false;
955
956
123
    GET_WHICH(1);
957
123
    switch ( which ) {
958
80
        case    0:
959
80
            /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
960
80
            /* noret */ mpz_addmul(res.GetPtr(), bn[1].GetPtr(), bn[2].GetPtr());
961
80
            break;
962
43
        case    1:
963
43
            {
964
43
                const auto bn2 = bn[2].GetUnsignedLong();
965
43
                CF_CHECK_NE(bn2, std::nullopt);
966
967
28
                /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
968
28
                /* noret */ mpz_addmul_ui(res.GetPtr(), bn[1].GetPtr(), *bn2);
969
28
            }
970
0
            break;
971
0
        default:
972
0
            return false;
973
123
    }
974
975
108
    ret = true;
976
977
123
end:
978
123
    return ret;
979
108
}
980
981
48
bool SubMul::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
982
48
    bool ret = false;
983
984
48
    GET_WHICH(1);
985
48
    switch ( which ) {
986
41
        case    0:
987
41
            /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
988
41
            /* noret */ mpz_submul(res.GetPtr(), bn[1].GetPtr(), bn[2].GetPtr());
989
41
            break;
990
7
        case    1:
991
7
            {
992
7
                const auto bn2 = bn[2].GetUnsignedLong();
993
7
                CF_CHECK_NE(bn2, std::nullopt);
994
995
5
                /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
996
5
                /* noret */ mpz_submul_ui(res.GetPtr(), bn[1].GetPtr(), *bn2);
997
5
            }
998
0
            break;
999
0
        default:
1000
0
            return false;
1001
48
    }
1002
1003
46
    ret = true;
1004
1005
48
end:
1006
48
    return ret;
1007
46
}
1008
1009
9
bool Primorial::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1010
9
#if !defined(HAVE_MINI_GMP)
1011
9
    (void)ds;
1012
9
    bool ret = false;
1013
1014
9
    const auto bn0 = bn[0].GetUnsignedLong();
1015
9
    CF_CHECK_NE(bn0, std::nullopt);
1016
8
    CF_CHECK_LTE(*bn0, 10000);
1017
1018
8
    /* noret */ mpz_primorial_ui(res.GetPtr(), *bn0);
1019
1020
8
    ret = true;
1021
1022
9
end:
1023
9
    return ret;
1024
#else
1025
    (void)ds;
1026
    (void)res;
1027
    (void)bn;
1028
1029
    return false;
1030
#endif
1031
8
}
1032
1033
113
bool Lucas::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1034
113
#if !defined(HAVE_MINI_GMP)
1035
113
    (void)ds;
1036
113
    bool ret = false;
1037
1038
113
    const auto bn0 = bn[0].GetUnsignedLong();
1039
113
    CF_CHECK_NE(bn0, std::nullopt);
1040
106
    CF_CHECK_LTE(*bn0, 10000);
1041
1042
96
    /* noret */ mpz_lucnum_ui(res.GetPtr(), *bn0);
1043
1044
96
    ret = true;
1045
1046
113
end:
1047
113
    return ret;
1048
#else
1049
    (void)ds;
1050
    (void)res;
1051
    (void)bn;
1052
1053
    return false;
1054
#endif
1055
96
}
1056
1057
85
bool Fibonacci::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1058
85
    (void)ds;
1059
85
    bool ret = false;
1060
1061
85
    const auto bn0 = bn[0].GetUnsignedLong();
1062
85
    CF_CHECK_NE(bn0, std::nullopt);
1063
70
    CF_CHECK_LTE(*bn0, 10000);
1064
1065
60
    /* noret */ mpz_fac_ui(res.GetPtr(), *bn0);
1066
1067
60
    ret = true;
1068
1069
85
end:
1070
85
    return ret;
1071
60
}
1072
1073
69
bool Set::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1074
69
    bool ret = false;
1075
1076
69
    GET_WHICH(3);
1077
69
    switch ( which ) {
1078
5
        case    0:
1079
5
            /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
1080
5
            break;
1081
17
        case    1:
1082
17
            {
1083
17
                const auto bn0 = bn[0].GetUnsignedLong();
1084
17
                CF_CHECK_NE(bn0, std::nullopt);
1085
1086
16
                /* noret */ mpz_clear(res.GetPtr());
1087
16
                /* noret */ mpz_init_set_ui(res.GetPtr(), *bn0);
1088
16
            }
1089
0
            break;
1090
40
        case    2:
1091
40
            {
1092
40
                const auto bn0 = bn[0].GetSignedLong();
1093
40
                CF_CHECK_NE(bn0, std::nullopt);
1094
1095
39
                /* noret */ mpz_clear(res.GetPtr());
1096
39
                /* noret */ mpz_init_set_si(res.GetPtr(), *bn0);
1097
39
            }
1098
0
            break;
1099
7
        case    3:
1100
7
            /* noret */ mpz_swap(res.GetPtr(), bn[0].GetPtr());
1101
7
            break;
1102
0
        default:
1103
0
            return false;
1104
69
    }
1105
1106
67
    ret = true;
1107
1108
69
end:
1109
69
    return ret;
1110
67
}
1111
1112
1.16k
bool BinCoeff::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1113
1.16k
    bool ret = false;
1114
1115
1.16k
    std::optional<unsigned long int> bn0, bn1;
1116
1117
1.16k
    GET_WHICH(1);
1118
1119
1.16k
    bn0 = bn[0].GetUnsignedLong();
1120
1.16k
    CF_CHECK_NE(bn0, std::nullopt);
1121
1.15k
#if !defined(HAVE_MINI_GMP)
1122
1.15k
    CF_CHECK_LTE(*bn0, 100000);
1123
#else
1124
    /* Too slow otherwise */
1125
    CF_CHECK_LTE(*bn0, 1000);
1126
#endif
1127
1128
1.14k
    bn1 = bn[1].GetUnsignedLong();
1129
1.14k
    CF_CHECK_NE(bn1, std::nullopt);
1130
1.13k
#if !defined(HAVE_MINI_GMP)
1131
1.13k
    CF_CHECK_LTE(*bn1, 100000);
1132
#else
1133
    /* Too slow otherwise */
1134
    CF_CHECK_LTE(*bn0, 1000);
1135
#endif
1136
1137
1.12k
    switch ( which ) {
1138
0
#if !defined(HAVE_MINI_GMP)
1139
900
        case    0:
1140
900
            /* noret */ mpz_bin_ui(res.GetPtr(), bn[0].GetPtr(), *bn1);
1141
900
            break;
1142
0
#endif
1143
222
        case    1:
1144
222
            /* noret */ mpz_bin_uiui(res.GetPtr(), *bn0, *bn1);
1145
222
            break;
1146
0
        default:
1147
0
            goto end;
1148
1.12k
    }
1149
1150
1.12k
    ret = true;
1151
1152
1.16k
end:
1153
1.16k
    return ret;
1154
1.12k
}
1155
1156
36
bool HamDist::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1157
36
    (void)ds;
1158
1159
36
    res.Set( std::to_string(mpz_hamdist(bn[0].GetPtr(), bn[1].GetPtr())) );
1160
1161
36
    return true;
1162
36
}
1163
1164
77
bool Mod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1165
77
    bool ret = false;
1166
1167
77
    GET_WHICH(1);
1168
77
    switch ( which ) {
1169
40
        case    0:
1170
40
            CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
1171
1172
26
            /* noret */ mpz_mod(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
1173
26
            CF_NORET(bn.CopyResult(res));
1174
26
            break;
1175
37
        case    1:
1176
37
            {
1177
37
                CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
1178
1179
31
                const auto bn1 = bn[1].GetUnsignedLong();
1180
31
                CF_CHECK_NE(bn1, std::nullopt);
1181
1182
17
                /* ignore ret */ mpz_mod_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
1183
17
                CF_NORET(bn.CopyResult(res));
1184
17
            }
1185
0
            break;
1186
0
        default:
1187
0
            return false;
1188
77
    }
1189
1190
    /* Negative not supported */
1191
43
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
1192
35
    CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
1193
1194
28
    ret = true;
1195
1196
77
end:
1197
77
    return ret;
1198
28
}
1199
1200
537
bool IsPower::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1201
537
#if !defined(HAVE_MINI_GMP)
1202
537
    (void)ds;
1203
1204
537
    res.Set(
1205
537
            mpz_perfect_power_p(bn[0].GetPtr()) == 0 ? std::string("0") : std::string("1")
1206
537
    );
1207
1208
537
    return true;
1209
#else
1210
    (void)ds;
1211
    (void)res;
1212
    (void)bn;
1213
1214
    return false;
1215
#endif
1216
537
}
1217
1218
1.28k
bool Prime::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1219
1.28k
#if !defined(HAVE_MINI_GMP)
1220
1.28k
    (void)bn;
1221
1222
1.28k
    uint16_t bits = 0;
1223
1224
1.28k
    try {
1225
1.28k
        bits = ds.Get<uint16_t>();
1226
1.28k
    } catch ( ... ) { }
1227
1228
1.28k
    bits %= (512+1);
1229
1230
1.28k
    if ( bits == 0 ) {
1231
95
        bits = 1;
1232
95
    }
1233
1234
1.28k
    /* noret */ mpz_urandomb(res.GetPtr(), libgmp_detail::rng_state, bits);
1235
1.28k
    /* noret */ mpz_nextprime(res.GetPtr(), res.GetPtr());
1236
1237
1.28k
    return true;
1238
#else
1239
    (void)ds;
1240
    (void)res;
1241
    (void)bn;
1242
1243
    return false;
1244
#endif
1245
1.28k
}
1246
1247
758
bool IsPrime::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1248
758
    (void)ds;
1249
758
    bool ret = false;
1250
1251
#if defined(HAVE_MINI_GMP)
1252
    CF_CHECK_LTE(mpz_sizeinbase(bn[0].GetPtr(), 2), 2000);
1253
#endif
1254
1255
758
    {
1256
758
        const bool isprime = mpz_probab_prime_p(bn[0].GetPtr(), 15) != 0;
1257
1258
758
        if ( mpz_sgn(bn[0].GetPtr()) < 0 ) {
1259
269
            return false;
1260
269
        }
1261
1262
489
        if ( isprime ) {
1263
117
            res.Set("1");
1264
372
        } else {
1265
372
            res.Set("0");
1266
372
        }
1267
489
    }
1268
1269
0
    ret = true;
1270
#if defined(HAVE_MINI_GMP)
1271
end:
1272
#endif
1273
489
    return ret;
1274
758
}
1275
1276
48
bool Rand::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1277
48
#if !defined(HAVE_MINI_GMP)
1278
48
    (void)bn;
1279
1280
48
    uint16_t bits = 0;
1281
1282
48
    try {
1283
48
        bits = ds.Get<uint16_t>();
1284
48
    } catch ( ... ) { }
1285
1286
48
    bits %= (10000+1);
1287
1288
48
    if ( bits == 0 ) {
1289
15
        bits = 1;
1290
15
    }
1291
1292
48
    /* noret */ mpz_urandomb(res.GetPtr(), libgmp_detail::rng_state, 512);
1293
1294
48
    return true;
1295
#else
1296
    (void)ds;
1297
    (void)res;
1298
    (void)bn;
1299
1300
    return false;
1301
#endif
1302
48
}
1303
1304
8
bool NumBits::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1305
8
    (void)ds;
1306
1307
    /* libgmp returns bit size of 1 of the value 0,
1308
     * whereas other libraries return 0
1309
     */
1310
8
    if ( mpz_sgn(bn[0].GetPtr()) == 0 ) {
1311
1
        return false;
1312
1
    }
1313
1314
7
    res.Set( std::to_string( mpz_sizeinbase(bn[0].GetPtr(), 2) ) );
1315
1316
7
    return true;
1317
8
}
1318
1319
7
bool CondAdd::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1320
7
    (void)ds;
1321
1322
7
    if ( !mpz_sgn(bn[2].GetPtr()) ) {
1323
1
        /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
1324
6
    } else {
1325
6
        /* noret */ mpz_add(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
1326
6
    }
1327
1328
7
    return true;
1329
7
}
1330
1331
17
bool CondSub::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1332
17
    (void)ds;
1333
1334
17
    if ( !mpz_sgn(bn[2].GetPtr()) ) {
1335
6
        /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
1336
11
    } else {
1337
11
        /* noret */ mpz_sub(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
1338
11
    }
1339
1340
17
    return true;
1341
17
}
1342
1343
40
bool RandRange::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1344
40
#if !defined(HAVE_MINI_GMP)
1345
40
    (void)ds;
1346
1347
40
    bool ret = false;
1348
1349
40
    CF_CHECK_EQ(mpz_sgn(bn[0].GetPtr()), 0);
1350
12
    CF_CHECK_NE(mpz_sgn(bn[1].GetPtr()), 0);
1351
1352
7
    /* noret */ mpz_urandomm(res.GetPtr(), libgmp_detail::rng_state, bn[1].GetPtr());
1353
1354
7
    ret = true;
1355
1356
40
end:
1357
40
    return ret;
1358
#else
1359
    (void)ds;
1360
    (void)res;
1361
    (void)bn;
1362
1363
    return false;
1364
#endif
1365
7
}
1366
1367
} /* namespace libgmp_bignum */
1368
} /* namespace module */
1369
} /* namespace cryptofuzz */