Coverage Report

Created: 2025-04-11 06:45

/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.54k
#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
207
bool Add::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
19
207
    bool ret = false;
20
21
207
    GET_WHICH(1);
22
207
    switch ( which ) {
23
59
        case    0:
24
59
            /* noret */ mpz_add(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
25
59
            CF_NORET(bn.CopyResult(res));
26
59
            break;
27
148
        case    1:
28
148
            {
29
148
                const auto bn1 = bn[1].GetUnsignedLong();
30
148
                CF_CHECK_NE(bn1, std::nullopt);
31
32
141
                /* noret */ mpz_add_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
33
141
                CF_NORET(bn.CopyResult(res));
34
141
            }
35
0
            break;
36
0
        default:
37
0
            return false;
38
207
    }
39
40
200
    ret = true;
41
42
207
end:
43
207
    return ret;
44
200
}
45
46
448
bool Sub::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
47
448
    bool ret = false;
48
49
448
    GET_WHICH(2);
50
448
    switch ( which ) {
51
108
        case    0:
52
108
            /* noret */ mpz_sub(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
53
108
            CF_NORET(bn.CopyResult(res));
54
108
            break;
55
182
        case    1:
56
182
            {
57
182
                const auto bn1 = bn[1].GetUnsignedLong();
58
182
                CF_CHECK_NE(bn1, std::nullopt);
59
60
175
                /* noret */ mpz_sub_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
61
175
                CF_NORET(bn.CopyResult(res));
62
175
            }
63
0
            break;
64
158
        case    2:
65
158
            {
66
158
                const auto bn0 = bn[0].GetUnsignedLong();
67
158
                CF_CHECK_NE(bn0, std::nullopt);
68
69
134
                /* noret */ mpz_ui_sub(bn.GetResPtr(), *bn0, bn[1].GetPtr());
70
134
                CF_NORET(bn.CopyResult(res));
71
134
            }
72
0
            break;
73
0
        default:
74
0
            return false;
75
448
    }
76
77
417
    ret = true;
78
79
448
end:
80
448
    return ret;
81
417
}
82
83
245
bool Mul::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
84
245
    bool ret = false;
85
86
245
    GET_WHICH(2);
87
245
    switch ( which ) {
88
67
        case    0:
89
67
            /* noret */ mpz_mul(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
90
67
            CF_NORET(bn.CopyResult(res));
91
67
            break;
92
89
        case    1:
93
89
            {
94
89
                const auto bn1 = bn[1].GetUnsignedLong();
95
89
                CF_CHECK_NE(bn1, std::nullopt);
96
97
77
                /* noret */ mpz_mul_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
98
77
                CF_NORET(bn.CopyResult(res));
99
77
            }
100
0
            break;
101
89
        case    2:
102
89
            {
103
89
                const auto bn1 = bn[1].GetSignedLong();
104
89
                CF_CHECK_NE(bn1, std::nullopt);
105
106
66
                /* noret */ mpz_mul_si(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
107
66
                CF_NORET(bn.CopyResult(res));
108
66
            }
109
0
            break;
110
0
        default:
111
0
            return false;
112
245
    }
113
114
210
    ret = true;
115
116
245
end:
117
245
    return ret;
118
210
}
119
120
624
bool Div::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
121
624
    bool ret = false;
122
123
624
    GET_WHICH(3);
124
624
    switch ( which ) {
125
0
#if !defined(HAVE_MINI_GMP)
126
187
        case    0:
127
187
            CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
128
129
176
            /* noret */ mpz_div(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
130
176
            CF_NORET(bn.CopyResult(res));
131
176
            break;
132
96
        case    1:
133
96
            {
134
96
                CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
135
136
91
                const auto bn1 = bn[1].GetUnsignedLong();
137
91
                CF_CHECK_NE(bn1, std::nullopt);
138
139
77
                /* noret */ mpz_div_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
140
77
                CF_NORET(bn.CopyResult(res));
141
77
            }
142
0
            break;
143
0
#endif
144
251
        case    2:
145
251
            {
146
251
                CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
147
148
250
                CF_CHECK_NE(mpz_divisible_p(bn[0].GetPtr(), bn[1].GetPtr()), 0);
149
150
22
                /* noret */ mpz_divexact(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
151
22
                CF_NORET(bn.CopyResult(res));
152
22
            }
153
0
            break;
154
90
        case    3:
155
90
            {
156
90
                CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
157
158
88
                const auto bn1 = bn[1].GetUnsignedLong();
159
88
                CF_CHECK_NE(bn1, std::nullopt);
160
161
73
                CF_CHECK_NE(mpz_divisible_ui_p(bn[0].GetPtr(), *bn1), 0);
162
163
33
                /* noret */ mpz_divexact_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
164
33
                CF_NORET(bn.CopyResult(res));
165
33
            }
166
0
            break;
167
0
        default:
168
0
            return false;
169
624
    }
170
171
    /* Negative not supported */
172
308
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
173
308
    CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
174
175
308
    ret = true;
176
177
624
end:
178
624
    return ret;
179
308
}
180
181
3.19k
bool ExpMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
182
3.19k
    bool ret = false;
183
184
3.19k
    GET_WHICH(2);
185
186
3.19k
    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
3.16k
    switch ( which ) {
196
2.69k
        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
2.69k
            CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
201
202
2.69k
            /* noret */ mpz_powm(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr());
203
2.69k
            CF_NORET(bn.CopyResult(res));
204
2.69k
            break;
205
257
        case    1:
206
257
            {
207
257
                const auto bn1 = bn[1].GetUnsignedLong();
208
257
                CF_CHECK_NE(bn1, std::nullopt);
209
210
186
                /* noret */ mpz_powm_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1, bn[2].GetPtr());
211
186
                CF_NORET(bn.CopyResult(res));
212
186
            }
213
0
            break;
214
0
#if !defined(HAVE_MINI_GMP)
215
215
        case    2:
216
215
            {
217
215
                CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
218
219
                /* "It is required that exp > 0 and that mod is odd." */
220
215
                CF_CHECK_GT(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
221
222
210
                const auto ptr = bn[2].GetPtr();
223
210
                CF_CHECK_EQ(mpz_odd_p(ptr), 1);
224
225
190
                /* noret */ mpz_powm_sec(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr());
226
190
                CF_NORET(bn.CopyResult(res));
227
190
            }
228
0
            break;
229
0
#endif
230
0
        default:
231
0
            return false;
232
3.16k
    }
233
234
3.07k
    ret = true;
235
236
3.19k
end:
237
3.19k
    return ret;
238
3.07k
}
239
240
enum GCDType : uint8_t {
241
    GCD = 0,
242
    ExtGCD_X = 1,
243
    ExtGCD_Y = 2,
244
};
245
246
244
static void GCD_ExtGCD_SetResult(mpz_ptr res, const mpz_ptr X, const mpz_ptr Y, const GCDType type) {
247
244
    if ( type == GCDType::GCD ) {
248
        /* do nothing */
249
128
    } else if ( type == GCDType::ExtGCD_X ) {
250
61
        /* noret */ mpz_set(res, X);
251
61
    } else if ( type == GCDType::ExtGCD_Y ) {
252
55
        /* noret */ mpz_set(res, Y);
253
55
    } else {
254
0
        CF_UNREACHABLE();
255
0
    }
256
244
}
257
258
1.39k
static bool GCD_ExtGCD(Datasource& ds, Bignum& res, BignumCluster& bn, const GCDType type) {
259
1.39k
    bool ret = false;
260
261
1.39k
    GET_WHICH(2);
262
1.39k
    switch ( which ) {
263
1.01k
        case    0:
264
1.01k
            CF_CHECK_EQ(type, GCDType::GCD);
265
979
            /* noret */ mpz_gcd(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
266
979
            CF_NORET(bn.CopyResult(res));
267
979
            break;
268
133
        case    1:
269
133
            {
270
133
                CF_CHECK_EQ(type, GCDType::GCD);
271
272
122
                const auto bn1 = bn[1].GetUnsignedLong();
273
122
                CF_CHECK_NE(bn1, std::nullopt);
274
275
107
                /* ignore ret */ mpz_gcd_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
276
107
                CF_NORET(bn.CopyResult(res));
277
107
            }
278
0
            break;
279
244
        case    2:
280
244
            {
281
244
                Bignum t1, t2;
282
283
244
                /* noret */ mpz_gcdext(res.GetPtr(), t1.GetPtr(), t2.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
284
244
                CF_NORET(GCD_ExtGCD_SetResult(res.GetPtr(), t1.GetPtr(), t2.GetPtr(), type));
285
244
            }
286
244
            break;
287
0
        default:
288
0
            return false;
289
1.39k
    }
290
291
1.33k
    ret = true;
292
293
1.39k
end:
294
1.39k
    return ret;
295
1.33k
}
296
297
1.22k
bool GCD::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
298
1.22k
    return GCD_ExtGCD(ds, res, bn, GCDType::GCD);
299
1.22k
}
300
301
85
bool ExtGCD_X::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
302
85
    return GCD_ExtGCD(ds, res, bn, GCDType::ExtGCD_X);
303
85
}
304
305
79
bool ExtGCD_Y::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
306
79
    return GCD_ExtGCD(ds, res, bn, GCDType::ExtGCD_Y);
307
79
}
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
195
bool Cmp::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
346
195
    bool ret = false;
347
348
195
    int cmp;
349
350
195
    GET_WHICH(2);
351
195
    switch ( which ) {
352
62
        case    0:
353
62
            cmp = mpz_cmp(bn[0].GetPtr(), bn[1].GetPtr());
354
62
            break;
355
91
        case    1:
356
91
            {
357
91
                const auto bn1 = bn[1].GetSignedLong();
358
91
                CF_CHECK_NE(bn1, std::nullopt);
359
360
76
                cmp = mpz_cmp_si(bn[0].GetPtr(), *bn1);
361
76
            }
362
0
            break;
363
42
        case    2:
364
42
            {
365
42
                const auto bn1 = bn[1].GetUnsignedLong();
366
42
                CF_CHECK_NE(bn1, std::nullopt);
367
368
31
                cmp = mpz_cmp_ui(bn[0].GetPtr(), *bn1);
369
31
            }
370
0
            break;
371
0
        default:
372
0
            goto end;
373
195
    }
374
375
169
    if ( cmp < 0 ) {
376
72
        res.Set("-1");
377
97
    } else if ( cmp > 0 ) {
378
81
        res.Set("1");
379
81
    } else {
380
16
        res.Set("0");
381
16
    }
382
383
169
    ret = true;
384
385
195
end:
386
195
    return ret;
387
169
}
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
0
            /* 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
32
bool Xor::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
422
32
    (void)ds;
423
424
32
    /* noret */ mpz_xor(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
425
32
    CF_NORET(bn.CopyResult(res));
426
427
32
    return true;
428
32
}
429
430
37
bool And::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
431
37
    (void)ds;
432
433
37
    /* noret */ mpz_and(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
434
37
    CF_NORET(bn.CopyResult(res));
435
436
37
    return true;
437
37
}
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
0
    /* noret */ mpz_sqrtrem(bn[1].GetPtr(), rem.GetPtr(), bn[0].GetPtr());
481
0
    if ( mpz_sgn(rem.GetPtr()) != 0 ) {
482
0
        /* 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
242
bool Sqr::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
491
242
    (void)ds;
492
493
242
    /* noret */ mpz_pow_ui(bn.GetResPtr(), bn[0].GetPtr(), 2);
494
242
    CF_NORET(bn.CopyResult(res));
495
496
242
    return true;
497
242
}
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
14
bool IsZero::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
536
14
    (void)ds;
537
538
14
    res.Set( std::to_string(mpz_sgn(bn[0].GetPtr()) == 0 ? 1 : 0) );
539
540
14
    return true;
541
14
}
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
162
bool AddMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
552
162
    (void)ds;
553
162
    bool ret = false;
554
555
162
    CF_CHECK_NE(mpz_cmp_ui(bn[2].GetPtr(), 0), 0);
556
557
156
    /* noret */ mpz_add(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
558
156
    /* noret */ mpz_mod(res.GetPtr(), res.GetPtr(), bn[2].GetPtr());
559
560
    /* Negative modulus currently not supported */
561
156
    CF_CHECK_GTE(mpz_sgn(bn[2].GetPtr()), 0);
562
563
156
    ret = true;
564
565
162
end:
566
162
    return ret;
567
156
}
568
569
372
bool SubMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
570
372
    (void)ds;
571
372
    bool ret = false;
572
573
372
    CF_CHECK_NE(mpz_cmp_ui(bn[2].GetPtr(), 0), 0);
574
575
363
    /* noret */ mpz_sub(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
576
363
    /* noret */ mpz_mod(res.GetPtr(), res.GetPtr(), bn[2].GetPtr());
577
578
    /* Negative modulus currently not supported */
579
363
    CF_CHECK_GTE(mpz_sgn(bn[2].GetPtr()), 0);
580
581
363
    ret = true;
582
583
372
end:
584
372
    return ret;
585
363
}
586
587
106
bool MulMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
588
106
    (void)ds;
589
106
    bool ret = false;
590
591
106
    CF_CHECK_NE(mpz_cmp_ui(bn[2].GetPtr(), 0), 0);
592
593
100
    /* noret */ mpz_mul(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
594
100
    /* noret */ mpz_mod(res.GetPtr(), res.GetPtr(), bn[2].GetPtr());
595
596
    /* Negative modulus currently not supported */
597
100
    CF_CHECK_GTE(mpz_sgn(bn[2].GetPtr()), 0);
598
599
100
    ret = true;
600
601
106
end:
602
106
    return ret;
603
100
}
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
0
    /* 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
0
    /* 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
0
    /* 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
137
bool Bit::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
714
137
    (void)ds;
715
137
    bool ret = false;
716
717
137
    const auto position_sl = bn[1].GetSignedLong();
718
137
    CF_CHECK_NE(position_sl, std::nullopt);
719
720
    /* Negative not supported */
721
72
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
722
723
72
    res.Set( std::to_string(mpz_tstbit(bn[0].GetPtr(), *position_sl)) );
724
725
72
    ret = true;
726
727
137
end:
728
137
    return ret;
729
72
}
730
731
2.42k
bool InvMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
732
2.42k
    (void)ds;
733
2.42k
    bool ret = false;
734
735
    /* "The behaviour of this function is undefined when op2 is zero." */
736
2.42k
    CF_CHECK_NE(mpz_sgn(bn[1].GetPtr()), 0);
737
738
2.40k
    if ( mpz_invert(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr()) == 0 ) {
739
        /* Modular inverse does not exist */
740
1.35k
        res.Set("0");
741
1.35k
    } else {
742
1.05k
        CF_NORET(bn.CopyResult(res));
743
1.05k
    }
744
745
2.40k
    ret = true;
746
747
2.42k
end:
748
2.42k
    return ret;
749
2.40k
}
750
751
12
bool IsOdd::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
752
12
    (void)ds;
753
754
    /* "These macros evaluate their argument more than once." */
755
12
    const auto ptr = bn[0].GetPtr();
756
12
    res.Set( std::to_string(mpz_odd_p(ptr)) );
757
758
12
    return true;
759
12
}
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
34
bool Or::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
946
34
    (void)ds;
947
948
34
    /* noret */ mpz_ior(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
949
950
34
    return true;
951
34
}
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
0
            /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
960
0
            /* 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
0
                /* 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
0
            /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
988
0
            /* 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
0
                /* 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
0
            /* 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
0
                /* 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
0
                /* noret */ mpz_init_set_si(res.GetPtr(), *bn0);
1097
0
            }
1098
0
            break;
1099
0
        case    3:
1100
0
            /* 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
0
            /* noret */ mpz_bin_ui(res.GetPtr(), bn[0].GetPtr(), *bn1);
1141
0
            break;
1142
0
#endif
1143
0
        case    1:
1144
0
            /* 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
239
bool Mod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1165
239
    bool ret = false;
1166
1167
239
    GET_WHICH(1);
1168
239
    switch ( which ) {
1169
111
        case    0:
1170
111
            CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
1171
1172
105
            /* noret */ mpz_mod(bn.GetResPtr(), bn[0].GetPtr(), bn[1].GetPtr());
1173
105
            CF_NORET(bn.CopyResult(res));
1174
105
            break;
1175
128
        case    1:
1176
128
            {
1177
128
                CF_CHECK_NE(mpz_cmp_ui(bn[1].GetPtr(), 0), 0);
1178
1179
123
                const auto bn1 = bn[1].GetUnsignedLong();
1180
123
                CF_CHECK_NE(bn1, std::nullopt);
1181
1182
92
                /* ignore ret */ mpz_mod_ui(bn.GetResPtr(), bn[0].GetPtr(), *bn1);
1183
92
                CF_NORET(bn.CopyResult(res));
1184
92
            }
1185
0
            break;
1186
0
        default:
1187
0
            return false;
1188
239
    }
1189
1190
    /* Negative not supported */
1191
197
    CF_CHECK_GTE(mpz_sgn(bn[0].GetPtr()), 0);
1192
197
    CF_CHECK_GTE(mpz_sgn(bn[1].GetPtr()), 0);
1193
1194
197
    ret = true;
1195
1196
239
end:
1197
239
    return ret;
1198
197
}
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
0
    /* 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
90
bool NumBits::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1305
90
    (void)ds;
1306
1307
    /* libgmp returns bit size of 1 of the value 0,
1308
     * whereas other libraries return 0
1309
     */
1310
90
    if ( mpz_sgn(bn[0].GetPtr()) == 0 ) {
1311
6
        return false;
1312
6
    }
1313
1314
84
    res.Set( std::to_string( mpz_sizeinbase(bn[0].GetPtr(), 2) ) );
1315
1316
84
    return true;
1317
90
}
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
3
        /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
1324
9
    } else {
1325
9
        /* noret */ mpz_add(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
1326
9
    }
1327
1328
12
    return true;
1329
12
}
1330
1331
35
bool CondSub::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const {
1332
35
    (void)ds;
1333
1334
35
    if ( !mpz_sgn(bn[2].GetPtr()) ) {
1335
3
        /* noret */ mpz_set(res.GetPtr(), bn[0].GetPtr());
1336
32
    } else {
1337
32
        /* noret */ mpz_sub(res.GetPtr(), bn[0].GetPtr(), bn[1].GetPtr());
1338
32
    }
1339
1340
35
    return true;
1341
35
}
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 */