Coverage Report

Created: 2026-10-28 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptofuzz/modules/botan/bn_ops.cpp
Line
Count
Source
1
#include <cryptofuzz/util.h>
2
#include <cryptofuzz/repository.h>
3
#include <fuzzing/datasource/id.hpp>
4
#include <botan/numthry.h>
5
#include <botan/reducer.h>
6
#include <botan/internal/divide.h>
7
#include <botan/internal/barrett.h>
8
#include <botan/internal/primality.h>
9
#include <botan/system_rng.h>
10
11
#include "bn_ops.h"
12
13
namespace cryptofuzz {
14
namespace module {
15
namespace Botan_bignum {
16
17
namespace detail {
18
803
    std::optional<size_t> To_size_t(const Bignum& bn) {
19
        /* TODO use #if */
20
21
803
        if ( sizeof(size_t) == 4 ) {
22
0
            try {
23
0
                return bn.ConstRef().to_u32bit();
24
0
            } catch ( ::Botan::Encoding_Error ) {
25
0
                return std::nullopt;
26
0
            }
27
803
        } else if ( sizeof(size_t) == 8 ) {
28
803
            if( bn.ConstRef().is_negative() ) {
29
19
                return std::nullopt;
30
19
            }
31
32
784
            if( bn.ConstRef().bits() > 64 ) {
33
58
                return std::nullopt;
34
58
            }
35
36
726
            uint64_t out = 0;
37
38
6.53k
            for (size_t i = 0; i != 8; ++i) {
39
5.80k
                out = (out << 8) | bn.ConstRef().byte_at(7-i);
40
5.80k
            }
41
42
726
            return out;
43
784
        } else {
44
0
            CF_UNREACHABLE();
45
0
        }
46
803
    }
47
}
48
49
#if !defined(CRYPTOFUZZ_BOTAN_IS_ORACLE)
50
 #define GET_UINT8_FOR_SWITCH() ds.Get<uint8_t>()
51
#else
52
399
 #define GET_UINT8_FOR_SWITCH() 0
53
#endif /* CRYPTOFUZZ_BOTAN_IS_ORACLE */
54
55
1.22k
#define APPLY_MODULO if (modulo != std::nullopt) res = (res.ConstRef() % modulo->ConstRef())
56
57
230
bool Add::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
58
230
    (void)ds;
59
60
230
    res = bn[0].Ref() + bn[1].Ref();
61
62
230
    APPLY_MODULO;
63
64
230
    return true;
65
230
}
66
67
91
bool Sub::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
68
91
    (void)ds;
69
70
91
    res = bn[0].Ref() - bn[1].Ref();
71
72
91
    APPLY_MODULO;
73
74
91
    return true;
75
91
}
76
77
592
bool Mul::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
78
592
    (void)ds;
79
80
592
    res = bn[0].Ref() * bn[1].Ref();
81
82
592
    APPLY_MODULO;
83
84
592
    return true;
85
592
}
86
87
28
bool Div::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
88
28
    (void)modulo;
89
28
    (void)ds;
90
91
    /* Botan handles negative division different than
92
     * other libraries.
93
     */
94
28
    CF_CHECK_TRUE(bn[0].Ref() > 0);
95
18
    CF_CHECK_TRUE(bn[1].Ref() > 0);
96
97
12
    try {
98
12
        switch ( GET_UINT8_FOR_SWITCH() ) {
99
12
            case    0:
100
                /* / operator */
101
12
                res = bn[0].Ref() / bn[1].Ref();
102
12
                return true;
103
0
            case    1:
104
0
                {
105
0
                    CF_CHECK_TRUE(bn[1].Ref() != 0);
106
0
                    Bignum dummy;
107
0
                    /* noret */ ::Botan::vartime_divide(bn[0].Ref(), bn[1].Ref(), res.Ref(), dummy.Ref());
108
0
                }
109
0
                return true;
110
0
            case    2:
111
0
                {
112
0
                    CF_CHECK_GT(bn[1].Ref(), 0);
113
0
                    CF_CHECK_TRUE(bn[1].Ref() < 256);
114
0
                    ::Botan::word dummy;
115
0
                    CF_NORET(::Botan::ct_divide_word(bn[0].Ref(), bn[1].Ref().word_at(0), res.Ref(), dummy));
116
0
                }
117
0
                return true;
118
0
            case    3:
119
0
                CF_CHECK_TRUE(bn[1].Ref() != 0);
120
0
                res = ::Botan::ct_divide(bn[0].Ref(), bn[1].Ref());
121
0
                return true;
122
0
            case    4:
123
                /* /= operator */
124
0
                res = bn[0].Ref();
125
0
                res.Ref() /= bn[1].Ref();
126
0
                return true;
127
12
        }
128
12
    } catch ( fuzzing::datasource::Datasource::OutOfData ) {
129
0
        return false;
130
0
    } catch ( ::Botan::Invalid_Argument& e ) {
131
        /* Botan is expected to throw an exception when divisor is 0 */
132
0
        if ( bn[1].Ref() == 0 ) {
133
0
            return false;
134
0
        }
135
136
        /* Rethrow */
137
0
        throw e;
138
0
    }
139
140
16
end:
141
16
    return false;
142
12
}
143
144
276
bool Mod::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
145
276
    (void)modulo;
146
276
    (void)ds;
147
148
276
    try {
149
276
        switch ( GET_UINT8_FOR_SWITCH() ) {
150
276
            case    0:
151
276
                {
152
276
                    try {
153
276
                        const Botan::Modular_Reducer reducer(bn[1].Ref());
154
276
                        res = reducer.reduce(bn[0].Ref());
155
276
                    } catch ( ::Botan::Invalid_State& e ) {
156
                        /* Modular reducer is expected to throw an exception when modulo is 0 */
157
0
                        if ( bn[1].Ref() == 0 ) {
158
0
                            return false;
159
0
                        }
160
161
                        /* Rethrow */
162
0
                        throw e;
163
0
                    }
164
276
                }
165
270
                return true;
166
0
            case    1:
167
0
                res = ct_modulo(bn[0].Ref(), bn[1].Ref());
168
0
                return true;
169
0
            case    2:
170
                /* % operator */
171
0
                res = bn[0].Ref() % bn[1].Ref();
172
0
                return true;
173
0
            case    3:
174
                /* %= operator */
175
0
                {
176
0
                    res = bn[0].Ref();
177
178
0
                    const ::Botan::word modulo = bn[1].Ref().word_at(0);
179
180
                    /* Ensure no truncation occurred */
181
0
                    if ( modulo != bn[1].Ref() ) {
182
0
                        return false;
183
0
                    }
184
185
0
                    res = bn[0].Ref() %= modulo;
186
0
                }
187
0
                return true;
188
276
        }
189
276
    } catch ( fuzzing::datasource::Datasource::OutOfData ) {
190
0
        return false;
191
6
    } catch ( ::Botan::Invalid_Argument& e ) {
192
        /* Botan is expected to throw an exception when modulo is <= 0 */
193
6
        if ( bn[1].Ref() <= 0 ) {
194
6
            return false;
195
6
        }
196
197
        /* Rethrow */
198
0
        throw e;
199
6
    }
200
201
0
    return false;
202
276
}
203
204
215
bool Exp::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
205
215
    (void)ds;
206
207
215
    if ( modulo == std::nullopt ) {
208
215
        return false;
209
215
    }
210
211
0
    res = ::Botan::power_mod(bn[0].Ref(), bn[1].Ref(), modulo->ConstRef());
212
213
0
    return true;
214
215
}
215
216
2.43k
bool ExpMod::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
217
2.43k
    (void)modulo;
218
2.43k
    (void)ds;
219
220
    /* Exponent and modulus must be positive, according to the documentation */
221
2.43k
    if ( bn[1].Ref() < 0 || bn[2].Ref() <= 0 ) {
222
518
        return false;
223
518
    }
224
225
1.91k
    res = ::Botan::power_mod(bn[0].Ref(), bn[1].Ref(), bn[2].Ref());
226
227
1.91k
    return true;
228
2.43k
}
229
230
82
bool Sqr::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
231
82
    (void)ds;
232
233
82
    res = ::Botan::square(bn[0].Ref());
234
235
82
    APPLY_MODULO;
236
237
82
    return true;
238
82
}
239
240
208
bool GCD::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
241
208
    (void)modulo;
242
208
    (void)ds;
243
244
208
    res = ::Botan::gcd(bn[0].Ref(), bn[1].Ref());
245
246
208
    return true;
247
208
}
248
249
42
bool SqrMod::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
250
42
    (void)modulo;
251
42
    (void)ds;
252
253
42
    if ( bn[1].Ref().is_negative() ) {
254
1
        return false;
255
41
    } else {
256
41
        try {
257
41
            switch ( GET_UINT8_FOR_SWITCH() ) {
258
41
                case    0:
259
41
                    {
260
41
                        try {
261
41
                            ::Botan::Modular_Reducer mod(bn[1].Ref());
262
41
                            res = mod.square(bn[0].Ref());
263
41
                        } catch ( ::Botan::Invalid_State& e ) {
264
                            /* Modular reducer is expected to throw an exception when modulo is 0 */
265
0
                            if ( bn[1].Ref() == 0 ) {
266
0
                                return false;
267
0
                            }
268
269
                            /* Rethrow */
270
0
                            throw e;
271
0
                        }
272
41
                    }
273
25
                    break;
274
0
                case    1:
275
0
                    res = ::Botan::square(bn[0].Ref()) % bn[1].Ref();
276
0
                    break;
277
0
                default:
278
0
                    return false;
279
41
            }
280
41
        } catch ( fuzzing::datasource::Datasource::OutOfData ) {
281
0
            return false;
282
16
        } catch ( ::Botan::Invalid_Argument& e ) {
283
            /* Botan is expected to throw an exception when modulo is 0 */
284
16
            if ( bn[1].Ref() == 0 ) {
285
16
                return false;
286
16
            }
287
288
            /* Rethrow */
289
0
            throw e;
290
16
        }
291
41
    }
292
293
25
    return true;
294
42
}
295
296
783
bool InvMod::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
297
783
    (void)modulo;
298
783
    (void)ds;
299
300
783
    const auto mod = modulo == std::nullopt ? bn[1].ConstRef() : modulo->ConstRef();
301
302
783
    try {
303
783
        res = ::Botan::inverse_mod(bn[0].Ref(), mod);
304
783
    } catch ( ::Botan::Invalid_Argument& e ) {
305
        /* inverse_mod() is expected to throw an exception when modulo is 0 */
306
273
        if ( mod == 0 ) {
307
38
            return false;
308
38
        }
309
310
        /* inverse_mod() is expected to throw an exception when either argument is negative */
311
235
        if ( bn[0].Ref() < 0 || mod < 0 ) {
312
235
            return false;
313
235
        }
314
315
        /* Rethrow */
316
0
        throw e;
317
235
    }
318
319
510
    return true;
320
783
}
321
322
14
bool Cmp::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
323
14
    (void)modulo;
324
14
    (void)ds;
325
326
14
    if ( bn[0].Ref() < bn[1].Ref() ) {
327
8
        res = Bignum("-1");
328
8
    } else if ( bn[0].Ref() > bn[1].Ref() ) {
329
1
        res = 1;
330
5
    } else {
331
5
        res = 0;
332
5
    }
333
334
14
    return true;
335
14
}
336
337
480
bool LCM::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
338
480
    (void)modulo;
339
480
    (void)ds;
340
341
480
    try {
342
480
        res = ::Botan::lcm(bn[0].Ref(), bn[1].Ref());
343
480
    } catch ( ::Botan::Invalid_Argument& e ) {
344
        /* lcm() is expected to throw in these cases */
345
0
        if ( bn[0].Ref() == 0 || bn[1].Ref() == 0 ) {
346
0
            return false;
347
0
        }
348
349
        /* Rethrow */
350
0
        throw e;
351
0
    }
352
353
354
480
    return true;
355
480
}
356
357
38
bool Abs::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
358
38
    (void)modulo;
359
38
    (void)ds;
360
361
38
    res = ::Botan::abs(bn[0].Ref());
362
363
38
    return true;
364
38
}
365
366
98
bool Jacobi::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
367
98
    (void)modulo;
368
98
    (void)ds;
369
370
371
98
    int resInt;
372
373
98
    try {
374
98
        resInt = ::Botan::jacobi(bn[0].Ref(), bn[1].Ref());
375
98
    } catch ( ::Botan::Invalid_Argument& e ) {
376
        /* jacobi() is expected to throw in these cases */
377
4
        if ( (bn[1].Ref() % 2) == 0 || bn[1].Ref() <= 1 ) {
378
4
            return false;
379
4
        }
380
381
        /* Rethrow */
382
0
        throw e;
383
4
    }
384
385
94
    if ( resInt == -1 ) {
386
41
        res = Bignum("-1");
387
53
    } else {
388
53
        res = resInt;
389
53
    }
390
391
94
    return true;
392
98
}
393
394
101
bool Neg::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
395
101
    (void)modulo;
396
101
    (void)ds;
397
398
101
    res = -bn[0].Ref();
399
400
101
    return true;
401
101
}
402
403
474
bool IsPrime::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
404
474
    (void)modulo;
405
474
    (void)ds;
406
407
474
    if ( bn[0].Ref().is_negative() ) {
408
1
        return false;
409
1
    }
410
411
    /* Avoid time-outs */
412
473
    if ( bn[0].Ref().bytes() > 300 ) {
413
2
        return false;
414
2
    }
415
416
471
    auto mod_n = Botan::Barrett_Reduction::for_public_modulus(bn[0].Ref());
417
471
    if ( Botan::is_bailie_psw_probable_prime(bn[0].Ref(), mod_n) ) {
418
89
        res = 1;
419
382
    } else {
420
382
        res = 0;
421
382
    }
422
423
471
    return true;
424
473
}
425
426
201
bool RShift::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
427
201
    (void)ds;
428
429
201
    const auto count = detail::To_size_t(bn[1].Ref());
430
431
201
    if ( count == std::nullopt ) {
432
42
        return false;
433
42
    }
434
435
159
    Bignum toShift = bn[0];
436
159
    if ( modulo && bn[0].Ref() % 2 ) {
437
0
        toShift = toShift.Ref() + modulo->ConstRef();
438
0
    }
439
440
159
    res = toShift.Ref() >> *count;
441
442
159
    APPLY_MODULO;
443
444
159
    return true;
445
201
}
446
447
19
bool LShift1::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
448
19
    (void)ds;
449
450
19
    res = bn[0].Ref() << 1;
451
452
19
    APPLY_MODULO;
453
454
19
    return true;
455
19
}
456
457
10
bool IsNeg::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
458
10
    (void)modulo;
459
10
    (void)ds;
460
461
10
    res = bn[0].Ref() < 0 ? 1 : 0;
462
463
10
    return true;
464
10
}
465
466
253
bool IsEq::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
467
253
    (void)ds;
468
469
253
    auto A = modulo == std::nullopt ? bn[0] : bn[0].Ref() % modulo->ConstRef();
470
253
    auto B = modulo == std::nullopt ? bn[1] : bn[1].Ref() % modulo->ConstRef();
471
472
253
    res = A.Ref() == B.Ref() ? 1 : 0;
473
474
253
    return true;
475
253
}
476
477
91
bool IsGt::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
478
91
    (void)modulo;
479
91
    (void)ds;
480
481
91
    res = bn[0].Ref() > bn[1].Ref() ? 1 : 0;
482
483
91
    return true;
484
91
}
485
486
119
bool IsGte::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
487
119
    (void)modulo;
488
119
    (void)ds;
489
490
119
    res = bn[0].Ref() >= bn[1].Ref() ? 1 : 0;
491
492
119
    return true;
493
119
}
494
495
124
bool IsLt::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
496
124
    (void)modulo;
497
124
    (void)ds;
498
499
124
    res = bn[0].Ref() < bn[1].Ref() ? 1 : 0;
500
501
124
    return true;
502
124
}
503
504
273
bool IsLte::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
505
273
    (void)modulo;
506
273
    (void)ds;
507
508
273
    res = bn[0].Ref() <= bn[1].Ref() ? 1 : 0;
509
510
273
    return true;
511
273
}
512
513
22
bool IsEven::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
514
22
    (void)modulo;
515
22
    (void)ds;
516
517
22
    res = !(bn[0].Ref() % 2) ? 1 : 0;
518
519
22
    return true;
520
22
}
521
522
20
bool IsOdd::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
523
20
    (void)modulo;
524
20
    (void)ds;
525
526
20
    res = (bn[0].Ref() % 2) ? 1 : 0;
527
528
20
    return true;
529
20
}
530
531
12
bool IsZero::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
532
12
    (void)ds;
533
534
12
    auto A = modulo == std::nullopt ? bn[0] : bn[0].Ref() % modulo->ConstRef();
535
536
12
    res = A.Ref() == 0 ? 1 : 0;
537
538
12
    return true;
539
12
}
540
541
4
bool IsNotZero::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
542
4
    (void)modulo;
543
4
    (void)ds;
544
545
4
    res = bn[0].Ref() == 0 ? 0 : 1;
546
547
4
    return true;
548
4
}
549
550
104
bool IsOne::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
551
104
    (void)ds;
552
553
104
    auto A = modulo == std::nullopt ? bn[0] : bn[0].Ref() % modulo->ConstRef();
554
555
104
    res = A.Ref() == 1 ? 1 : 0;
556
557
104
    return true;
558
104
}
559
560
12
bool MulMod::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
561
12
    (void)modulo;
562
12
    (void)ds;
563
564
12
    try {
565
12
        switch ( GET_UINT8_FOR_SWITCH() ) {
566
12
            case    0:
567
12
                {
568
12
                    try {
569
12
                        ::Botan::Modular_Reducer mod(bn[2].Ref());
570
12
                        res = mod.multiply(bn[0].Ref(), bn[1].Ref());
571
12
                    } catch ( ::Botan::Invalid_State& e ) {
572
                        /* Modular reducer is expected to throw an exception when modulo is 0 */
573
0
                        if ( bn[2].Ref() == 0 ) {
574
0
                            return false;
575
0
                        }
576
577
                        /* Rethrow */
578
0
                        throw e;
579
0
                    }
580
12
                }
581
10
                break;
582
0
            case    1:
583
0
                res = (bn[0].Ref() * bn[1].Ref()) % bn[2].Ref();
584
0
                break;
585
0
            default:
586
0
                return false;
587
12
        }
588
12
    } catch ( fuzzing::datasource::Datasource::OutOfData ) {
589
0
        return false;
590
2
    } catch ( ::Botan::Invalid_Argument& e ) {
591
        /* Botan is expected to throw an exception when modulo is <= 0 */
592
2
        if ( bn[2].Ref() <= 0 ) {
593
2
            return false;
594
2
        }
595
596
        /* Rethrow */
597
0
        throw e;
598
2
    }
599
600
10
    return true;
601
12
}
602
603
141
bool Bit::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
604
141
    (void)modulo;
605
141
    (void)ds;
606
607
141
    const auto pos = detail::To_size_t(bn[1].Ref());
608
609
141
    if ( pos == std::nullopt ) {
610
15
        return false;
611
15
    }
612
613
126
    res = bn[0].Ref().get_bit(*pos) ? 1 : 0;
614
615
126
    return true;
616
141
}
617
618
6
bool CmpAbs::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
619
6
    (void)modulo;
620
6
    std::vector<Bignum> bnAbs = {bn[0].Ref().abs(), bn[1].Ref().abs()};
621
6
    auto cmp = std::make_unique<Cmp>();
622
623
6
    return cmp->Run(ds, res, bnAbs, modulo);
624
6
}
625
626
152
bool SetBit::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
627
152
    (void)modulo;
628
152
    (void)ds;
629
630
152
    res = bn[0].Ref();
631
632
152
    const auto pos = detail::To_size_t(bn[1].Ref());
633
634
152
    if ( pos == std::nullopt ) {
635
6
        return false;
636
6
    }
637
638
146
    res.Ref().set_bit(*pos);
639
640
146
    return true;
641
152
}
642
643
309
bool ClearBit::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
644
309
    (void)modulo;
645
309
    (void)ds;
646
647
309
    res = bn[0].Ref();
648
649
309
    const auto pos = detail::To_size_t(bn[1].Ref());
650
651
309
    if ( pos == std::nullopt ) {
652
14
        return false;
653
14
    }
654
655
295
    res.Ref().clear_bit(*pos);
656
657
295
    return true;
658
309
}
659
660
26
bool MulAdd::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
661
26
    (void)modulo;
662
26
    (void)ds;
663
664
26
    res = (bn[0].Ref()*bn[1].Ref()) + bn[2].Ref();
665
666
26
    return true;
667
26
}
668
669
31
bool MulDiv::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
670
31
    (void)modulo;
671
31
    (void)ds;
672
673
31
    if ( bn[2].Ref() == 0 ) {
674
2
        return false;
675
2
    }
676
677
29
    res = (bn[0].Ref()*bn[1].Ref()+1) / bn[2].Ref();
678
679
29
    return true;
680
31
}
681
682
192
bool MulDivCeil::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
683
192
    (void)modulo;
684
192
    (void)ds;
685
686
192
    if ( bn[2].Ref() <= 0 ) {
687
3
        return false;
688
3
    }
689
690
189
    const auto mulRes = bn[0].Ref() * bn[1].Ref();
691
189
    const auto modRes = mulRes % bn[2].Ref();
692
189
    res = mulRes / bn[2].Ref() + (modRes != 0 ? 1 : 0);
693
694
189
    return true;
695
192
}
696
697
9
bool Exp2::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
698
9
    (void)modulo;
699
9
    (void)ds;
700
701
9
    if ( bn[0].Ref() < 1 ) {
702
5
        return false;
703
5
    }
704
705
4
    const size_t exponent = bn[0].Ref().word_at(0) - 1;
706
707
4
    res = Bignum(2).Ref() << exponent;
708
709
4
    return true;
710
9
}
711
712
121
bool NumLSZeroBits::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
713
121
    (void)modulo;
714
121
    (void)ds;
715
716
121
    res = ::Botan::low_zero_bits(bn[0].Ref());
717
718
121
    return true;
719
121
}
720
721
900
bool Sqrt::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
722
900
    (void)ds;
723
724
900
    try {
725
900
        const auto res2 = ::Botan::is_perfect_square(bn[0].Ref());
726
900
        if ( res2 == 0 ) {
727
849
            return false;
728
849
        }
729
730
51
        res = res2;
731
51
    } catch ( ::Botan::Invalid_Argument& e ) {
732
        /* is_perfect_square() is expected to throw in this case */
733
13
        if ( bn[0].Ref() < 1 ) {
734
13
            return false;
735
13
        }
736
737
        /* Rethrow */
738
0
        throw e;
739
13
    }
740
741
38
    APPLY_MODULO;
742
743
38
    return true;
744
900
}
745
746
23
bool AddMod::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
747
23
    (void)modulo;
748
23
    (void)ds;
749
750
23
    try {
751
23
        switch ( GET_UINT8_FOR_SWITCH() ) {
752
23
            case    0:
753
23
                res = (bn[0].Ref() + bn[1].Ref()) % bn[2].Ref();
754
23
                break;
755
0
            case    1:
756
0
                {
757
0
                    if ( bn[0].Ref() >= bn[2].Ref() ) {
758
0
                        return false;
759
0
                    }
760
0
                    if ( bn[1].Ref() >= bn[2].Ref() ) {
761
0
                        return false;
762
0
                    }
763
764
0
                    ::Botan::secure_vector<::Botan::word> ws;
765
0
                    try {
766
0
                        res = bn[0].Ref().mod_add(bn[1].Ref(), bn[2].Ref(), ws);
767
0
                    } catch ( ::Botan::Invalid_Argument& e ) {
768
                        /* mod_add is expected to throw an exception when any argument is negative */
769
0
                        if ( bn[0].Ref() < 0 || bn[1].Ref() < 0 || bn[2].Ref() < 0) {
770
0
                            return false;
771
0
                        }
772
773
                        /* Rethrow */
774
0
                        throw e;
775
0
                    }
776
0
                }
777
0
                break;
778
0
            default:
779
0
                return false;
780
23
        }
781
23
    } catch ( fuzzing::datasource::Datasource::OutOfData ) {
782
0
        return false;
783
18
    } catch ( ::Botan::Invalid_Argument& e ) {
784
        /* Botan is expected to throw an exception when modulo is <= 0 */
785
18
        if ( bn[2].Ref() <= 0 ) {
786
18
            return false;
787
18
        }
788
789
        /* Rethrow */
790
0
        throw e;
791
18
    }
792
793
5
    return true;
794
23
}
795
796
35
bool SubMod::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
797
35
    (void)modulo;
798
35
    (void)ds;
799
800
35
    try {
801
35
        switch ( GET_UINT8_FOR_SWITCH() ) {
802
35
            case    0:
803
35
                res = (bn[0].Ref() - bn[1].Ref()) % bn[2].Ref();
804
35
                break;
805
0
            case    1:
806
0
                {
807
0
                    if ( bn[0].Ref() >= bn[2].Ref() ) {
808
0
                        return false;
809
0
                    }
810
0
                    if ( bn[1].Ref() >= bn[2].Ref() ) {
811
0
                        return false;
812
0
                    }
813
814
0
                    ::Botan::secure_vector<::Botan::word> ws;
815
0
                    try {
816
0
                        res = bn[0].Ref().mod_sub(bn[1].Ref(), bn[2].Ref(), ws);
817
0
                    } catch ( ::Botan::Invalid_Argument& e ) {
818
                        /* mod_sub is expected to throw an exception when any argument is negative */
819
0
                        if ( bn[0].Ref() < 0 || bn[1].Ref() < 0 || bn[2].Ref() < 0) {
820
0
                            return false;
821
0
                        }
822
823
                        /* Rethrow */
824
0
                        throw e;
825
0
                    }
826
0
                }
827
0
                break;
828
0
            default:
829
0
                return false;
830
35
        }
831
35
    } catch ( fuzzing::datasource::Datasource::OutOfData ) {
832
0
        return false;
833
10
    } catch ( ::Botan::Invalid_Argument& e ) {
834
        /* Botan is expected to throw an exception when modulo is <= 0 */
835
10
        if ( bn[2].Ref() <= 0 ) {
836
10
            return false;
837
10
        }
838
839
        /* Rethrow */
840
0
        throw e;
841
10
    }
842
843
25
    return true;
844
35
}
845
846
32
bool NumBits::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
847
32
    (void)ds;
848
849
32
    if ( modulo ) {
850
0
        res = (bn[0].Ref() % modulo->ConstRef()).bits();
851
32
    } else {
852
32
        res = bn[0].Ref().bits();
853
32
    }
854
855
32
    return true;
856
32
}
857
858
7
bool Set::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
859
7
    (void)modulo;
860
7
    (void)ds;
861
862
7
    res = bn[0].Ref();
863
864
7
    APPLY_MODULO;
865
866
7
    return true;
867
7
}
868
869
48
bool CondSet::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
870
48
    (void)modulo;
871
48
    (void)ds;
872
873
48
    res.Ref().ct_cond_assign(bn[1].Ref() != 0, bn[0].Ref());
874
875
48
    return true;
876
48
}
877
878
0
bool Ressol::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
879
0
    (void)ds;
880
881
0
    try {
882
0
        auto mod = modulo == std::nullopt ? bn[1] : *modulo;
883
884
0
        const auto r = ::Botan::sqrt_modulo_prime(bn[0].Ref(), mod.Ref());
885
886
0
        if ( r < 1 ) {
887
0
            if ( modulo != std::nullopt ) {
888
0
                res = 0;
889
0
                return true;
890
0
            } else {
891
0
                return false;
892
0
            }
893
0
        }
894
895
0
        if ( modulo != std::nullopt ) {
896
0
            res = ::Botan::square(r) % mod.Ref();
897
0
        }
898
899
0
        return true;
900
0
    } catch ( ::Botan::Invalid_Argument& e ) {
901
        /* Expected to throw if called with non-prime argument */
902
903
0
        return false;
904
0
    }
905
0
}
906
907
8
bool Not::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
908
8
    (void)ds;
909
910
8
    Bignum max;
911
912
8
    if ( modulo ) {
913
0
        max = *modulo;
914
8
    } else {
915
8
        const size_t numBits = bn[0].Ref().bits();
916
917
8
        if ( numBits == 0 ) {
918
3
            return false;
919
3
        }
920
921
5
        max = (::Botan::BigInt(1) << numBits) - 1;
922
5
    }
923
924
5
    res = max.Ref() - bn[0].Ref();
925
926
5
    APPLY_MODULO;
927
928
5
    return true;
929
8
}
930
931
458
bool Prime::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
932
458
    (void)ds;
933
458
    (void)bn;
934
458
    (void)modulo;
935
936
458
    ::Botan::System_RNG rng;
937
458
    res = Botan::random_prime(rng, (rand() % 512) + 2);
938
939
458
    return true;
940
458
}
941
942
80
bool RandRange::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
943
80
    (void)ds;
944
80
    (void)modulo;
945
946
80
    try {
947
80
        ::Botan::System_RNG rng;
948
80
        res = ::Botan::BigInt::random_integer(rng, bn[0].Ref(), bn[1].Ref());
949
80
    } catch ( ::Botan::Invalid_Argument ) {
950
41
        return false;
951
41
    }
952
953
39
    return true;
954
80
}
955
956
16
bool IsSquare::Run(Datasource& ds, Bignum& res, std::vector<Bignum>& bn, const std::optional<Bignum>& modulo) const {
957
16
    (void)ds;
958
959
16
    if ( modulo != std::nullopt ) {
960
0
        return false;
961
0
    }
962
963
16
    try {
964
16
        res = ::Botan::is_perfect_square(bn[0].Ref()) == 0 ? 0 : 1;
965
16
    } catch ( ::Botan::Invalid_Argument& e ) {
966
        /* is_perfect_square() is expected to throw in this case */
967
1
        if ( bn[0].Ref() < 1 ) {
968
1
            return false;
969
1
        }
970
971
        /* Rethrow */
972
0
        throw e;
973
1
    }
974
975
15
    return true;
976
16
}
977
978
} /* namespace Botan_bignum */
979
} /* namespace module */
980
} /* namespace cryptofuzz */