Coverage Report

Created: 2022-08-24 06:37

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