Coverage Report

Created: 2022-08-24 06:37

/src/cryptofuzz-openssl-api/modules/wolfcrypt-openssl/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
/* Not included in public headers */
8
#if defined(CRYPTOFUZZ_BORINGSSL)
9
extern "C" {
10
    int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
11
    int bn_div_consttime(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator, const BIGNUM *divisor, BN_CTX *ctx);
12
    int bn_lcm_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
13
    uint16_t bn_mod_u16_consttime(const BIGNUM *bn, uint16_t d);
14
    int bn_abs_sub_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
15
}
16
#endif
17
18
/* Not included in public headers */
19
#if defined(CRYPTOFUZZ_LIBRESSL)
20
extern "C" {
21
    int BN_gcd_ct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx);
22
}
23
#endif
24
25
namespace cryptofuzz {
26
namespace module {
27
namespace OpenSSL_bignum {
28
29
16
bool Add::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
30
16
    (void)ctx;
31
16
    bool ret = false;
32
33
16
    switch ( ds.Get<uint8_t>() ) {
34
9
        case    0:
35
9
            CF_CHECK_EQ(BN_add(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr()), 1);
36
9
            break;
37
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
38
        case    1:
39
            CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0);
40
            CF_CHECK_EQ(BN_is_negative(bn[1].GetPtr()), 0);
41
            CF_CHECK_EQ(BN_uadd(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr()), 1);
42
            break;
43
#endif
44
0
        case    2:
45
0
            {
46
0
                const auto val = bn[1].AsBN_ULONG();
47
0
                CF_CHECK_NE(val, std::nullopt);
48
49
0
                CF_CHECK_EQ(BN_add_word(bn.GetDestPtr(0), *val), 1);
50
51
0
                CF_CHECK_EQ(res.Set(bn[0]), true);
52
0
            }
53
0
            break;
54
7
        default:
55
7
            goto end;
56
7
            break;
57
16
    }
58
59
9
    ret = true;
60
61
16
end:
62
16
    return ret;
63
9
}
64
65
17
bool Sub::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
66
17
    (void)ctx;
67
17
    bool ret = false;
68
69
17
    switch ( ds.Get<uint8_t>() ) {
70
11
        case    0:
71
11
            CF_CHECK_EQ(BN_sub(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr()), 1);
72
11
            break;
73
74
    /* OpenSSL and LibreSSL return a positive value for BN_usub(A,B)
75
     * where A > B
76
     */
77
#if defined(CRYPTOFUZZ_BORINGSSL)
78
        case    1:
79
            CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0);
80
            CF_CHECK_EQ(BN_is_negative(bn[1].GetPtr()), 0);
81
            CF_CHECK_EQ(BN_usub(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr()), 1);
82
            break;
83
#endif
84
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
85
        case    2:
86
            {
87
                const auto val = bn[1].AsBN_ULONG();
88
                CF_CHECK_NE(val, std::nullopt);
89
90
                CF_CHECK_EQ(BN_sub_word(bn.GetDestPtr(0), *val), 1);
91
92
                CF_CHECK_EQ(res.Set(bn[0]), true);
93
            }
94
            break;
95
#endif
96
#if defined(CRYPTOFUZZ_BORINGSSL)
97
        case    3:
98
            CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0);
99
            CF_CHECK_EQ(BN_is_negative(bn[1].GetPtr()), 0);
100
            CF_CHECK_GTE(BN_cmp(bn[0].GetPtr(), bn[1].GetPtr()), 0);
101
            CF_CHECK_EQ(bn_abs_sub_consttime(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
102
            break;
103
#endif
104
3
        default:
105
3
            goto end;
106
3
            break;
107
17
    }
108
109
11
    ret = true;
110
111
14
end:
112
14
    return ret;
113
11
}
114
115
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
116
bool Mul::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
117
    (void)ds;
118
    (void)ctx;
119
    bool ret = false;
120
121
    switch ( ds.Get<uint8_t>() ) {
122
        case    0:
123
            {
124
                CF_CHECK_EQ(BN_mul(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
125
            }
126
            break;
127
        case    1:
128
            {
129
                const auto val = bn[1].AsBN_ULONG();
130
                CF_CHECK_NE(val, std::nullopt);
131
132
                CF_CHECK_EQ(BN_mul_word(bn.GetDestPtr(0), *val), 1);
133
134
                CF_CHECK_EQ(res.Set(bn[0]), true);
135
            }
136
            break;
137
        default:
138
            goto end;
139
            break;
140
    }
141
142
    ret = true;
143
144
end:
145
    return ret;
146
}
147
#endif
148
149
18
bool Mod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
150
18
    (void)ctx;
151
18
    bool ret = false;
152
153
18
    switch ( ds.Get<uint8_t>() ) {
154
5
        case    0:
155
5
            CF_CHECK_EQ(BN_mod(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
156
3
            break;
157
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
158
        case    1:
159
            /* "BN_mod() corresponds to BN_div() with dv set to NULL" */
160
            CF_CHECK_EQ(BN_div(nullptr, res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
161
            break;
162
#endif
163
#if defined(CRYPTOFUZZ_BORINGSSL)
164
        case    2:
165
            CF_CHECK_EQ(bn_div_consttime(nullptr, res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
166
            break;
167
        case    3:
168
            CF_CHECK_EQ(BN_is_pow2(bn[1].GetPtr()), 1);
169
            CF_CHECK_EQ(BN_mod_pow2(res.GetDestPtr(), bn[0].GetPtr(), BN_num_bits(bn[1].GetPtr()) - 1), 1);
170
            break;
171
        case    4:
172
            {
173
                std::optional<uint64_t> v64;
174
175
                /* Convert bn[1] to uint64_t if possible */
176
                CF_CHECK_NE(v64 = bn[1].AsUint64(), std::nullopt);
177
178
                /* Try to convert the uint64_t to uint16_t */
179
                uint16_t v16;
180
                CF_CHECK_EQ(v16 = *v64, *v64);
181
182
                CF_CHECK_GT(v16, 1);
183
184
                /* This condition is imposed by bn_mod_u16_consttime, which
185
                 * triggers an assert failure otherwise
186
                 */
187
                CF_CHECK_LTE(BN_num_bits_word(v16 - 1), 16);
188
189
                /* ret = bn[0] MOD v16 (which is bn[1]) */
190
                const auto ret = bn_mod_u16_consttime(bn[0].GetPtr(), v16);
191
                res.SetUint32(ret);
192
            }
193
            break;
194
#endif
195
1
        case    5:
196
1
            {
197
1
                const auto val = bn[1].AsBN_ULONG();
198
1
                CF_CHECK_NE(val, std::nullopt);
199
0
                CF_CHECK_NE(*val, 0);
200
201
0
                const auto ret = BN_mod_word(bn[0].GetPtr(), *val);
202
203
                /* Try to convert the BN_ULONG to uint32_t */
204
0
                uint32_t ret32;
205
0
                CF_CHECK_EQ(ret32 = ret, ret);
206
207
0
                res.SetUint32(ret32);
208
0
            }
209
0
            break;
210
11
        default:
211
11
            goto end;
212
11
            break;
213
18
    }
214
215
3
    ret = true;
216
217
17
end:
218
17
    return ret;
219
3
}
220
221
393
bool ExpMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
222
393
    (void)ctx;
223
393
    bool ret = false;
224
225
393
    switch ( ds.Get<uint8_t>() ) {
226
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
227
        case    0:
228
            CF_CHECK_EQ(BN_mod_exp_mont_consttime(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr(), nullptr), 1);
229
            break;
230
        case    1:
231
            CF_CHECK_EQ(BN_mod_exp_mont(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr(), nullptr), 1);
232
            break;
233
#endif
234
373
        case    2:
235
373
            CF_CHECK_EQ(BN_mod_exp(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1);
236
364
            break;
237
4
        case    3:
238
#if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
239
            CF_CHECK_EQ(BN_mod_exp_simple(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1);
240
#else
241
4
            goto end;
242
0
#endif
243
0
            break;
244
9
        default:
245
9
            goto end;
246
9
            break;
247
248
393
    }
249
250
364
    ret = true;
251
252
386
end:
253
386
    return ret;
254
364
}
255
256
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
257
bool Sqr::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
258
    (void)ds;
259
    bool ret = false;
260
261
    CF_CHECK_EQ(BN_sqr(res.GetDestPtr(), bn[0].GetPtr(), ctx.GetPtr()), 1);
262
263
    ret = true;
264
265
end:
266
267
    return ret;
268
}
269
#endif
270
271
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
272
bool GCD::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
273
    (void)ds;
274
    bool ret = false;
275
276
    switch ( ds.Get<uint8_t>() ) {
277
        case    0:
278
            CF_CHECK_EQ(BN_gcd(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
279
            break;
280
#if defined(CRYPTOFUZZ_LIBRESSL)
281
        case    1:
282
            CF_CHECK_EQ(BN_gcd_ct(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
283
            break;
284
#endif
285
        default:
286
            goto end;
287
    }
288
289
    ret = true;
290
291
end:
292
    return ret;
293
}
294
#endif
295
296
38
bool AddMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
297
38
    bool ret = false;
298
299
38
    switch ( ds.Get<uint8_t>() ) {
300
31
        case    0:
301
31
            CF_CHECK_EQ(BN_mod_add(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1);
302
20
            break;
303
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
304
        case    1:
305
            {
306
                Bignum zero(ds);
307
                CF_CHECK_EQ(zero.New(), true);
308
309
                /* "... may be used if both a and b are non-negative and less than m" */
310
                CF_CHECK_GTE(BN_cmp(bn[0].GetPtr(), zero.GetPtr()), 0);
311
                CF_CHECK_GTE(BN_cmp(bn[1].GetPtr(), zero.GetPtr()), 0);
312
                CF_CHECK_LT(BN_cmp(bn[0].GetPtr(), bn[2].GetPtr()), 0);
313
                CF_CHECK_LT(BN_cmp(bn[1].GetPtr(), bn[2].GetPtr()), 0);
314
                CF_CHECK_EQ(BN_mod_add_quick(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr()), 1);
315
            }
316
            break;
317
#endif
318
4
        default:
319
4
            goto end;
320
4
            break;
321
38
    }
322
323
20
    ret = true;
324
325
35
end:
326
35
    return ret;
327
20
}
328
329
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
330
bool SubMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
331
    bool ret = false;
332
333
    switch ( ds.Get<uint8_t>() ) {
334
        case    0:
335
            CF_CHECK_EQ(BN_mod_sub(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1);
336
            break;
337
        case    1:
338
            {
339
                Bignum zero(ds);
340
                CF_CHECK_EQ(zero.New(), true);
341
342
                /* "... may be used if both a and b are non-negative and less than m" */
343
                CF_CHECK_GTE(BN_cmp(bn[0].GetPtr(), zero.GetPtr()), 0);
344
                CF_CHECK_GTE(BN_cmp(bn[1].GetPtr(), zero.GetPtr()), 0);
345
                CF_CHECK_LT(BN_cmp(bn[0].GetPtr(), bn[2].GetPtr()), 0);
346
                CF_CHECK_LT(BN_cmp(bn[1].GetPtr(), bn[2].GetPtr()), 0);
347
                CF_CHECK_EQ(BN_mod_sub_quick(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr()), 1);
348
            }
349
        default:
350
            goto end;
351
            break;
352
    }
353
354
    ret = true;
355
356
end:
357
    return ret;
358
}
359
#endif
360
361
41
bool MulMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
362
41
    bool ret = false;
363
364
41
    switch ( ds.Get<uint8_t>() ) {
365
31
        case    0:
366
31
            CF_CHECK_EQ(BN_mod_mul(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1);
367
30
            break;
368
8
        default:
369
8
            goto end;
370
8
            break;
371
41
    }
372
373
30
    ret = true;
374
375
39
end:
376
39
    return ret;
377
30
}
378
379
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
380
bool SqrMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
381
    bool ret = false;
382
383
    switch ( ds.Get<uint8_t>() ) {
384
        case    0:
385
            CF_CHECK_EQ(BN_mod_sqr(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
386
            break;
387
        default:
388
            goto end;
389
            break;
390
    }
391
392
    ret = true;
393
394
end:
395
    return ret;
396
}
397
#endif
398
399
416
bool InvMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
400
416
    bool ret = false;
401
402
416
    switch ( ds.Get<uint8_t>() ) {
403
397
        case    0:
404
397
            CF_CHECK_NE(BN_mod_inverse(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), nullptr);
405
311
            break;
406
#if defined(CRYPTOFUZZ_BORINGSSL)
407
        case    1:
408
            {
409
                int out_no_inverse;
410
                CF_CHECK_LT(BN_cmp(bn[0].GetPtr(), bn[1].GetPtr()), 0);
411
                CF_CHECK_EQ(BN_is_odd(bn[1].GetPtr()), 1);
412
                CF_CHECK_EQ(BN_mod_inverse_odd(res.GetDestPtr(), &out_no_inverse, bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
413
            }
414
            break;
415
#endif
416
12
        default:
417
12
            goto end;
418
12
            break;
419
416
    }
420
421
311
    ret = true;
422
423
409
end:
424
409
    return ret;
425
311
}
426
427
31
bool Cmp::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
428
31
    (void)ds;
429
31
    (void)ctx;
430
31
    bool ret = false;
431
432
31
    int cmpRes;
433
434
31
    switch ( ds.Get<uint8_t>() ) {
435
27
        case    0:
436
27
            cmpRes = BN_cmp(bn[0].GetPtr(), bn[1].GetPtr());
437
27
            break;
438
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
439
        case    1:
440
            CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0);
441
            CF_CHECK_EQ(BN_is_negative(bn[1].GetPtr()), 0);
442
            cmpRes = BN_ucmp(bn[0].GetPtr(), bn[1].GetPtr());
443
            break;
444
#endif
445
#if defined(CRYPTOFUZZ_BORINGSSL)
446
        case    2:
447
            {
448
                auto val = bn[1].AsBN_ULONG();
449
                CF_CHECK_NE(val, std::nullopt);
450
                cmpRes = BN_cmp_word(bn[0].GetPtr(), *val);
451
            }
452
            break;
453
#endif
454
2
        default:
455
2
            goto end;
456
2
            break;
457
31
    }
458
459
27
    if ( cmpRes > 0 ) {
460
11
        cmpRes = 1;
461
16
    } else if ( cmpRes < 0 ) {
462
9
        cmpRes = -1;
463
9
    }
464
465
27
#if defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
466
    /* wolfCrypt's OpenSSL API cannot set negative numbers */
467
27
    if ( cmpRes == -1 ) {
468
9
        goto end;
469
9
    }
470
18
#endif
471
18
    res.Set( std::to_string(cmpRes) );
472
473
18
    ret = true;
474
475
29
end:
476
29
    return ret;
477
18
}
478
479
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
480
bool Div::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
481
    (void)ds;
482
    (void)ctx;
483
    bool ret = false;
484
485
    switch ( ds.Get<uint8_t>() ) {
486
        case    0:
487
            CF_CHECK_EQ(BN_div(res.GetDestPtr(), nullptr, bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
488
            break;
489
#if defined(CRYPTOFUZZ_BORINGSSL)
490
        case    1:
491
            CF_CHECK_EQ(bn_div_consttime(res.GetDestPtr(), nullptr, bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
492
            break;
493
#endif
494
        case    2:
495
            {
496
                const auto val = bn[1].AsBN_ULONG();
497
                CF_CHECK_NE(val, std::nullopt);
498
499
                CF_CHECK_NE(BN_div_word(bn.GetDestPtr(0), *val), (BN_ULONG)-1);
500
                CF_CHECK_EQ(res.Set(bn[0]), true);
501
            }
502
            break;
503
        default:
504
            goto end;
505
            break;
506
    }
507
508
    ret = true;
509
510
end:
511
    return ret;
512
}
513
#endif
514
515
3
bool IsPrime::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
516
3
    (void)ds;
517
3
    (void)ctx;
518
519
#if defined(CRYPTOFUZZ_BORINGSSL) || defined(CRYPTOFUZZ_LIBRESSL)
520
    const int ret = BN_is_prime_ex(bn[0].GetPtr(), 0, nullptr, nullptr);
521
    if ( ret == -1 ) {
522
        return false;
523
    }
524
525
    res.Set( std::to_string(ret) );
526
527
    return true;
528
#else
529
3
    (void)res;
530
3
    (void)bn;
531
3
    return false;
532
3
#endif
533
3
}
534
535
3
bool Sqrt::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
536
3
    (void)ds;
537
3
    bool ret = false;
538
539
#if defined(CRYPTOFUZZ_BORINGSSL)
540
    CF_CHECK_EQ(BN_sqrt(res.GetDestPtr(), bn[0].GetPtr(), ctx.GetPtr()), 1);
541
542
    ret = true;
543
544
end:
545
#else
546
3
    (void)res;
547
3
    (void)bn;
548
3
    (void)ctx;
549
550
3
#endif
551
3
    return ret;
552
3
}
553
554
10
bool IsNeg::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
555
10
    (void)ds;
556
10
    (void)ctx;
557
558
10
    res.Set( std::to_string(BN_is_negative(bn[0].GetPtr())) );
559
560
10
    return true;
561
10
}
562
563
6
bool IsEq::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
564
6
    (void)ds;
565
6
    (void)ctx;
566
567
#if defined(CRYPTOFUZZ_BORINGSSL)
568
    bool ret = false;
569
570
    switch ( ds.Get<uint8_t>() ) {
571
        case    0:
572
            res.Set( std::to_string(BN_equal_consttime(bn[0].GetPtr(), bn[1].GetPtr())) );
573
            break;
574
        case    1:
575
            {
576
                auto val = bn[1].AsBN_ULONG();
577
                CF_CHECK_NE(val, std::nullopt);
578
                res.Set( std::to_string(BN_is_word(bn[0].GetPtr(), *val)) );
579
            }
580
            break;
581
        default:
582
            goto end;
583
    }
584
585
    ret = true;
586
587
end:
588
589
    return ret;
590
#else
591
6
    (void)res;
592
6
    (void)bn;
593
6
    return false;
594
6
#endif
595
6
}
596
597
18
bool IsEven::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
598
18
    (void)ds;
599
18
    (void)ctx;
600
601
18
    res.Set( std::to_string(!BN_is_odd(bn[0].GetPtr())) );
602
603
18
    return true;
604
18
}
605
606
14
bool IsOdd::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
607
14
    (void)ds;
608
14
    (void)ctx;
609
610
14
    res.Set( std::to_string(BN_is_odd(bn[0].GetPtr())) );
611
612
14
    return true;
613
14
}
614
615
23
bool IsZero::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
616
23
    (void)ds;
617
23
    (void)ctx;
618
619
23
    res.Set( std::to_string(BN_is_zero(bn[0].GetPtr())) );
620
621
23
    return true;
622
23
}
623
624
66
bool IsOne::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
625
66
    (void)ds;
626
66
    (void)ctx;
627
628
66
    res.Set( std::to_string(BN_is_one(bn[0].GetPtr())) );
629
630
66
    return true;
631
66
}
632
633
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
634
bool Jacobi::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
635
    (void)ds;
636
    bool ret = false;
637
638
#if !defined(CRYPTOFUZZ_BORINGSSL)
639
    const int jacobi = BN_kronecker(bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr());
640
#else
641
    const int jacobi = bn_jacobi(bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr());
642
#endif
643
644
    CF_CHECK_NE(jacobi, -2);
645
646
    res.Set( std::to_string(jacobi) );
647
648
    ret = true;
649
end:
650
651
    return ret;
652
}
653
#endif
654
655
#if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
656
bool Mod_NIST_192::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
657
    (void)ds;
658
    bool ret = false;
659
660
    CF_CHECK_EQ(BN_nist_mod_192(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
661
662
    ret = true;
663
664
end:
665
    return ret;
666
}
667
668
bool Mod_NIST_224::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
669
    (void)ds;
670
    bool ret = false;
671
672
    CF_CHECK_EQ(BN_nist_mod_224(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
673
674
    ret = true;
675
676
end:
677
    return ret;
678
}
679
680
bool Mod_NIST_256::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
681
    (void)ds;
682
    bool ret = false;
683
684
    CF_CHECK_EQ(BN_nist_mod_256(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
685
686
    ret = true;
687
688
end:
689
    return ret;
690
}
691
692
bool Mod_NIST_384::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
693
    (void)ds;
694
    bool ret = false;
695
696
    CF_CHECK_EQ(BN_nist_mod_384(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
697
698
    ret = true;
699
700
end:
701
    return ret;
702
}
703
704
bool Mod_NIST_521::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
705
    (void)ds;
706
    bool ret = false;
707
708
    CF_CHECK_EQ(BN_nist_mod_521(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
709
710
    ret = true;
711
712
end:
713
    return ret;
714
}
715
#endif
716
717
7
bool SqrtMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
718
    /* Disabled due to slowness of primality testing */
719
#if 0
720
    (void)ds;
721
    bool ret = false;
722
723
    /* Third parameter to BN_mod_sqrt must be prime */
724
    CF_CHECK_EQ(BN_is_prime_ex(bn[1].GetPtr(), 64, ctx.GetPtr(), nullptr), 1);
725
    CF_CHECK_NE(BN_mod_sqrt(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), nullptr);
726
727
    ret = true;
728
729
end:
730
    return ret;
731
#else
732
7
    (void)ds;
733
7
    (void)res;
734
7
    (void)bn;
735
7
    (void)ctx;
736
7
    return false;
737
7
#endif
738
7
}
739
740
#if defined(CRYPTOFUZZ_BORINGSSL)
741
bool LCM::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
742
    (void)ds;
743
    bool ret = false;
744
745
    CF_CHECK_EQ(bn_lcm_consttime(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
746
747
    ret = true;
748
749
end:
750
    return ret;
751
}
752
#endif
753
754
10
bool Exp::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
755
10
    (void)ds;
756
10
    bool ret = false;
757
758
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
759
    CF_CHECK_EQ(BN_exp(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1);
760
761
    ret = true;
762
763
end:
764
#else
765
10
    (void)res;
766
10
    (void)bn;
767
10
    (void)ctx;
768
769
10
    return ret;
770
10
#endif
771
10
}
772
773
/* BN_copy doesn't work in wolfCrypt's OpenSSL API */
774
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
775
bool Abs::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
776
    (void)ds;
777
    (void)ctx;
778
    bool ret = false;
779
780
    if ( BN_is_negative(bn[0].GetPtr()) ) {
781
        Bignum zero(ds);
782
        CF_CHECK_EQ(zero.New(), true);
783
784
        switch ( ds.Get<uint8_t>() ) {
785
            case    0:
786
                CF_CHECK_EQ(BN_sub(res.GetDestPtr(), zero.GetPtr(), bn[0].GetPtr()), 1);
787
                break;
788
            case    1:
789
                CF_CHECK_EQ(BN_sub(res.GetDestPtr(), bn[0].GetPtr(), bn[0].GetPtr()), 1);
790
                CF_CHECK_EQ(BN_sub(res.GetDestPtr(), res.GetDestPtr(), bn[0].GetPtr()), 1);
791
                break;
792
            default:
793
                goto end;
794
                break;
795
        }
796
    } else {
797
        CF_CHECK_NE(BN_copy(res.GetDestPtr(), bn[0].GetPtr()), nullptr);
798
    }
799
800
    ret = true;
801
802
end:
803
    return ret;
804
}
805
#endif
806
807
32
bool RShift::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
808
32
    (void)ctx;
809
32
    bool ret = false;
810
32
    std::optional<int> places;
811
812
32
    CF_CHECK_NE(places = bn[1].AsInt(), std::nullopt);
813
814
0
    switch ( ds.Get<uint8_t>() ) {
815
0
        case    0:
816
0
            CF_CHECK_EQ(BN_rshift(res.GetDestPtr(), bn[0].GetPtr(), *places), 1);
817
0
            break;
818
0
        case    1:
819
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
820
            if ( *places != 1 ) {
821
                goto end;
822
            }
823
            CF_CHECK_EQ(BN_rshift1(res.GetDestPtr(), bn[0].GetPtr()), 1);
824
            break;
825
#endif
826
0
        default:
827
0
            goto end;
828
0
    }
829
830
0
    ret = true;
831
832
32
end:
833
32
    return ret;
834
0
}
835
836
1
bool LShift1::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
837
1
    (void)ctx;
838
1
    (void)ds;
839
1
    bool ret = false;
840
841
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
842
    CF_CHECK_EQ(BN_lshift1(res.GetDestPtr(), bn[0].GetPtr()), 1);
843
844
    ret = true;
845
846
end:
847
#else
848
1
    (void)res;
849
1
    (void)bn;
850
1
#endif
851
1
    return ret;
852
1
}
853
854
15
bool SetBit::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
855
15
    (void)ctx;
856
15
    (void)ds;
857
15
    bool ret = false;
858
15
    std::optional<uint64_t> pos;
859
860
15
    CF_CHECK_NE(pos = bn[1].AsInt(), std::nullopt);
861
862
0
    CF_CHECK_EQ(BN_set_bit(bn.GetDestPtr(0), *pos), 1);
863
0
    CF_CHECK_NE(BN_copy(res.GetDestPtr(), bn[0].GetPtr()), nullptr);
864
865
0
    ret = true;
866
867
15
end:
868
15
    return ret;
869
0
}
870
871
6
bool ClearBit::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
872
6
    (void)ctx;
873
6
    (void)ds;
874
6
    bool ret = false;
875
6
    std::optional<int> pos;
876
877
6
    CF_CHECK_NE(pos = bn[1].AsInt(), std::nullopt);
878
879
0
    CF_CHECK_EQ(BN_clear_bit(bn.GetDestPtr(0), *pos), 1);
880
0
    CF_CHECK_NE(BN_copy(res.GetDestPtr(), bn[0].GetPtr()), nullptr);
881
882
0
    ret = true;
883
884
6
end:
885
6
    return ret;
886
0
}
887
888
8
bool Bit::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
889
8
    (void)ctx;
890
8
    (void)ds;
891
8
    bool ret = false;
892
8
    std::optional<int> pos;
893
894
8
    CF_CHECK_NE(pos = bn[1].AsInt(), std::nullopt);
895
896
0
    res.Set( std::to_string(BN_is_bit_set(bn[0].GetPtr(), *pos)) );
897
898
0
    ret = true;
899
900
8
end:
901
8
    return ret;
902
0
}
903
904
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
905
bool CmpAbs::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
906
    (void)ctx;
907
    (void)ds;
908
909
    int cmpRes = BN_ucmp(bn[0].GetPtr(), bn[1].GetPtr());
910
911
    if ( cmpRes > 0 ) {
912
        cmpRes = 1;
913
    } else if ( cmpRes < 0 ) {
914
        cmpRes = -1;
915
    }
916
917
    res.Set( std::to_string(cmpRes) );
918
919
    return true;
920
}
921
#endif
922
923
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
924
bool ModLShift::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
925
    (void)ctx;
926
    (void)ds;
927
    bool ret = false;
928
    std::optional<uint64_t> places;
929
930
    CF_CHECK_NE(places = bn[1].AsInt(), std::nullopt);
931
932
    switch ( ds.Get<uint8_t>() ) {
933
        case    0:
934
            CF_CHECK_EQ(BN_mod_lshift(res.GetDestPtr(), bn[0].GetPtr(), *places, bn[2].GetPtr(), ctx.GetPtr()), 1);
935
            break;
936
        case    1:
937
            /* BN_mod_lshift_quick acts like BN_mod_lshift but requires that a be non-negative and less than m. */
938
            CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0);
939
            CF_CHECK_LT(BN_cmp(bn[0].GetPtr(), bn[2].GetPtr()), 0);
940
            CF_CHECK_EQ(BN_mod_lshift_quick(res.GetDestPtr(), bn[0].GetPtr(), *places, bn[2].GetPtr()), 1);
941
            break;
942
        case    2:
943
            CF_CHECK_EQ(*places, 1);
944
            CF_CHECK_EQ(BN_mod_lshift1(res.GetDestPtr(), bn[0].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1);
945
            break;
946
        case    3:
947
            CF_CHECK_EQ(*places, 1);
948
            /* BN_mod_lshift1_quick acts like BN_mod_lshift1 but requires that a be non-negative and less than m. */
949
            CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0);
950
            CF_CHECK_LT(BN_cmp(bn[0].GetPtr(), bn[2].GetPtr()), 0);
951
            CF_CHECK_EQ(BN_mod_lshift1_quick(res.GetDestPtr(), bn[0].GetPtr(), bn[2].GetPtr()), 1);
952
            break;
953
        default:
954
            goto end;
955
    }
956
957
    ret = true;
958
959
end:
960
    return ret;
961
}
962
#endif
963
964
4
bool IsPow2::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
965
4
    (void)ctx;
966
4
    (void)ds;
967
968
#if defined(CRYPTOFUZZ_BORINGSSL)
969
    res.Set( std::to_string(BN_is_pow2(bn[0].GetPtr())) );
970
971
    return true;
972
#else
973
4
    (void)res;
974
4
    (void)bn;
975
976
4
    return false;
977
4
#endif
978
4
}
979
980
8
bool Mask::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const {
981
8
    (void)ctx;
982
8
    (void)ds;
983
8
    bool ret = false;
984
985
8
    std::optional<uint64_t> places;
986
987
8
    CF_CHECK_NE(places = bn[1].AsInt(), std::nullopt);
988
0
    CF_CHECK_EQ(BN_mask_bits(bn[0].GetDestPtr(), *places), 1);
989
0
    CF_CHECK_EQ(res.Set(bn[0]), true);
990
991
0
    ret = true;
992
993
8
end:
994
8
    return ret;
995
0
}
996
997
} /* namespace OpenSSL_bignum */
998
} /* namespace module */
999
} /* namespace cryptofuzz */