Coverage Report

Created: 2024-06-28 06:19

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