Coverage Report

Created: 2025-07-23 06:59

/src/cryptofuzz-openssl-api/modules/wolfcrypt-openssl/bn_ops.h
Line
Count
Source (jump to first uncovered line)
1
#include <cryptofuzz/components.h>
2
#include <cryptofuzz/operations.h>
3
extern "C" {
4
#include <wolfssl/options.h>
5
#include <wolfssl/openssl/bn.h>
6
#include <wolfssl/openssl/asn1.h>
7
}
8
#if defined(CRYPTOFUZZ_BORINGSSL)
9
#include <openssl/mem.h>
10
#endif
11
#include <array>
12
13
namespace cryptofuzz {
14
namespace module {
15
namespace OpenSSL_bignum {
16
17
class Bignum {
18
    private:
19
        BIGNUM* bn = nullptr;
20
        Datasource& ds;
21
        bool locked = false;
22
        bool noFree = false;
23
    public:
24
        Bignum(Datasource& ds) :
25
30.7k
            ds(ds)
26
30.7k
    { }
27
28
45.0k
        ~Bignum() {
29
45.0k
            if ( noFree == false ) {
30
43.0k
                BN_free(bn);
31
43.0k
            }
32
45.0k
        }
33
34
2.10k
        void Lock(void) {
35
2.10k
            locked = true;
36
2.10k
        }
37
38
2.06k
        void DisableFree(void) {
39
2.06k
            noFree = true;
40
2.06k
        }
41
42
2.06k
        void ReleaseOwnership(void) {
43
2.06k
            Lock();
44
2.06k
            DisableFree();
45
2.06k
        }
46
47
21.2k
        bool New(void) {
48
21.2k
            if ( locked == true ) {
49
0
                printf("Cannot renew locked Bignum\n");
50
0
                abort();
51
0
            }
52
53
21.2k
            BN_free(bn);
54
21.2k
            bn = BN_new();
55
56
21.2k
            return bn != nullptr;
57
21.2k
        }
58
59
0
        bool Set(Bignum& other) {
60
0
            bool ret = false;
61
62
0
            CF_CHECK_NE(BN_copy(bn, other.GetPtr()), NULL);
63
64
0
            ret = true;
65
0
end:
66
0
            return ret;
67
0
        }
68
69
25.9k
        bool Set(const std::string s) {
70
25.9k
            if ( locked == true ) {
71
0
                printf("Cannot set locked Bignum\n");
72
0
                abort();
73
0
            }
74
75
25.9k
            bool ret = false;
76
77
25.9k
#if defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
78
25.9k
            const auto asHex = util::DecToHex(s);
79
25.9k
            CF_CHECK_NE(BN_hex2bn(&bn, asHex.c_str()), 0);
80
#else
81
            CF_CHECK_NE(BN_dec2bn(&bn, s.c_str()), 0);
82
#endif
83
84
25.8k
            ret = true;
85
25.9k
end:
86
25.9k
            return ret;
87
25.8k
        }
88
89
90
        std::optional<uint64_t> AsUint64(void) const {
90
90
            std::optional<uint64_t> ret = std::nullopt;
91
90
            try {
92
90
                switch ( ds.Get<uint8_t>() ) {
93
2
                    case    0:
94
#if !defined(CRYPTOFUZZ_LIBRESSL) && !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
95
                        {
96
                            /* BN_bn2binpad is not supported by LibreSSL */
97
98
                            uint64_t v;
99
100
                            CF_CHECK_LTE(BN_num_bytes(bn), (int)sizeof(uint64_t));
101
                            CF_CHECK_NE(BN_bn2binpad(bn, (unsigned char*)&v, sizeof(v)), -1);
102
103
                            /* Manual reversing is required because
104
                             * BN_bn2lebinpad is not supported by BoringSSL.
105
                             *
106
                             * TODO This must be omitted on big-endian platforms.
107
                             */
108
                            v =
109
                                ((v & 0xFF00000000000000) >> 56) |
110
                                ((v & 0x00FF000000000000) >> 40) |
111
                                ((v & 0x0000FF0000000000) >> 24) |
112
                                ((v & 0x000000FF00000000) >>  8) |
113
                                ((v & 0x00000000FF000000) <<  8) |
114
                                ((v & 0x0000000000FF0000) << 24) |
115
                                ((v & 0x000000000000FF00) << 40) |
116
                                ((v & 0x00000000000000FF) << 56);
117
118
                            ret = v;
119
                        }
120
#endif
121
2
                        break;
122
7
                    case    1:
123
#if !defined(CRYPTOFUZZ_LIBRESSL) && !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
124
                        {
125
                            ASN1_INTEGER* asn1 = nullptr;
126
                            uint64_t v;
127
128
                            CF_CHECK_NE( (asn1 = BN_to_ASN1_INTEGER(bn, nullptr)), nullptr);
129
                            const auto r = ASN1_INTEGER_get_uint64(&v, asn1);
130
                            ASN1_INTEGER_free(asn1);
131
                            CF_CHECK_EQ(r, 1);
132
133
                            ret = v;
134
                        }
135
#endif
136
7
                        break;
137
31
                    default:
138
31
                        break;
139
140
90
                }
141
90
            } catch ( ... ) { }
142
143
            /* Silence compiler */
144
90
            goto end;
145
90
end:
146
90
            return ret;
147
90
        }
148
149
86
        std::optional<int> AsInt(void) const {
150
86
            std::optional<int> ret = std::nullopt;
151
86
            const auto u64 = AsUint64();
152
153
86
            CF_CHECK_NE(u64, std::nullopt);
154
0
            CF_CHECK_LTE(*u64, 2147483647);
155
156
0
            ret = *u64;
157
86
end:
158
86
            return ret;
159
0
        }
160
161
4
        std::optional<BN_ULONG> AsBN_ULONG(void) const {
162
4
            std::optional<BN_ULONG> ret;
163
4
            std::optional<uint64_t> v64;
164
165
            /* Convert bn[1] to uint64_t if possible */
166
4
            CF_CHECK_NE(v64 = AsUint64(), std::nullopt);
167
168
            /* Try to convert the uint64_t to BN_ULONG */
169
0
            BN_ULONG vul;
170
0
            CF_CHECK_EQ(vul = *v64, *v64);
171
172
0
            ret = vul;
173
4
end:
174
4
            return ret;
175
0
        }
176
177
0
        void SetUint32(const uint32_t v) {
178
            /* Gnarly but it works for now */
179
180
0
            char s[1024];
181
0
            if ( sprintf(s, "%u", v) < 0 ) {
182
0
                abort();
183
0
            }
184
185
0
            if ( Set(s) == false ) {
186
0
                abort();
187
0
            }
188
0
        }
189
190
19.6k
        BIGNUM* GetDestPtr(const bool allowDup = true) {
191
19.6k
            if ( locked == false ) {
192
19.6k
                try {
193
19.6k
                    {
194
19.6k
                        const bool changeConstness = ds.Get<bool>();
195
19.6k
                        if ( changeConstness == true ) {
196
2.38k
#if !defined(CRYPTOFUZZ_BORINGSSL)
197
2.38k
                            const bool constness = ds.Get<bool>();
198
199
2.38k
                            if ( constness == true ) {
200
1.36k
                                /* noret */ BN_set_flags(bn, BN_FLG_CONSTTIME);
201
1.36k
                            } else {
202
1.01k
                                /* noret */ BN_set_flags(bn, 0);
203
1.01k
                            }
204
2.38k
#endif
205
2.38k
                        }
206
19.6k
                    }
207
208
19.6k
                    {
209
19.6k
                        if ( allowDup == true ) {
210
3.94k
                            const bool dup = ds.Get<bool>();
211
212
3.94k
                            if ( dup == true ) {
213
1.98k
                                BIGNUM* tmp = BN_dup(bn);
214
1.98k
                                if ( tmp != nullptr ) {
215
1.98k
                                    BN_free(bn);
216
1.98k
                                    bn = tmp;
217
1.98k
                                }
218
1.98k
                            }
219
3.94k
                        }
220
19.6k
                    }
221
222
19.6k
                    {
223
19.6k
                        if ( allowDup == true ) {
224
3.71k
                            const bool asn1Convert = ds.Get<bool>();
225
226
3.71k
                            if ( asn1Convert == true ) {
227
2.03k
                                ASN1_INTEGER* asn1 = BN_to_ASN1_INTEGER(bn, nullptr);
228
229
2.03k
                                if ( asn1 != nullptr ) {
230
2.03k
                                    BIGNUM* tmp = ASN1_INTEGER_to_BN(asn1, nullptr);
231
232
2.03k
                                    if ( tmp != nullptr ) {
233
2.03k
                                        BN_free(bn);
234
2.03k
                                        bn = tmp;
235
2.03k
                                    }
236
237
2.03k
                                    ASN1_INTEGER_free(asn1);
238
2.03k
                                }
239
2.03k
                            }
240
3.71k
                        }
241
19.6k
                    }
242
243
19.6k
                    {
244
19.6k
                        if ( allowDup == true ) {
245
3.37k
                            const bool asn1Convert = ds.Get<bool>();
246
247
3.37k
                            if ( asn1Convert == true ) {
248
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
249
                                ASN1_ENUMERATED* asn1 = BN_to_ASN1_ENUMERATED(bn, nullptr);
250
251
                                if ( asn1 != nullptr ) {
252
                                    BIGNUM* tmp = ASN1_ENUMERATED_to_BN(asn1, nullptr);
253
254
                                    if ( tmp != nullptr ) {
255
                                        BN_free(bn);
256
                                        bn = tmp;
257
                                    }
258
259
                                    ASN1_ENUMERATED_free(asn1);
260
                                }
261
#endif
262
1.70k
                            }
263
3.37k
                        }
264
19.6k
                    }
265
19.6k
                } catch ( ... ) { }
266
19.6k
            }
267
268
19.6k
            return bn;
269
19.6k
        }
270
271
610
        BIGNUM* GetPtrConst(void) const {
272
610
            return bn;
273
610
        }
274
275
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
276
        const BIGNUM* GetPtr(const bool allowDup = true) {
277
#else
278
13.4k
        BIGNUM* GetPtr(const bool allowDup = true) {
279
13.4k
#endif
280
13.4k
            return GetDestPtr(allowDup);
281
13.4k
        }
282
283
713
        std::optional<component::Bignum> ToComponentBignum(void) {
284
713
            std::optional<component::Bignum> ret = std::nullopt;
285
286
713
            char* str = nullptr;
287
713
            CF_CHECK_NE(str = BN_bn2dec(GetPtr()), nullptr);
288
289
713
            ret = { std::string(str) };
290
713
end:
291
713
            OPENSSL_free(str);
292
293
713
            return ret;
294
713
        }
295
296
305
        inline bool operator==(const Bignum& rhs) const {
297
305
            return BN_cmp(GetPtrConst(), rhs.GetPtrConst()) == 0;
298
305
        }
299
};
300
301
class BignumCluster {
302
    private:
303
        Datasource& ds;
304
        std::array<Bignum, 4> bn;
305
    public:
306
        BignumCluster(Datasource& ds, Bignum bn0, Bignum bn1, Bignum bn2, Bignum bn3) :
307
3.57k
            ds(ds),
308
3.57k
            bn({bn0, bn1, bn2, bn3})
309
3.57k
        { }
310
311
2.13k
        Bignum& operator[](const size_t index) {
312
2.13k
            if ( index >= bn.size() ) {
313
0
                abort();
314
0
            }
315
316
2.13k
            try {
317
                /* Rewire? */
318
2.13k
                if ( ds.Get<bool>() == true ) {
319
                    /* Pick a random bignum */
320
334
                    const size_t newIndex = ds.Get<uint8_t>() % 4;
321
322
                    /* Same value? */
323
334
                    if ( bn[newIndex] == bn[index] ) {
324
                        /* Then return reference to other bignum */
325
326
115
                        if ( newIndex != index ) {
327
38
                            bn[newIndex].Lock();
328
38
                        }
329
330
115
                        return bn[newIndex];
331
115
                    }
332
333
                    /* Fall through */
334
334
                }
335
2.13k
            } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
336
337
2.02k
            return bn[index];
338
2.13k
        }
339
340
0
        Bignum& Get(const size_t index) {
341
0
            if ( index >= bn.size() ) {
342
0
                abort();
343
0
            }
344
345
0
            return bn[index];
346
0
        }
347
348
0
        BIGNUM* GetDestPtr(const size_t index) {
349
0
            return Get(index).GetDestPtr();
350
0
        }
351
352
14.2k
        bool New(const size_t index) {
353
14.2k
            if ( index >= bn.size() ) {
354
0
                abort();
355
0
            }
356
357
14.2k
            return bn[index].New();
358
14.2k
        }
359
360
14.1k
        bool Set(const size_t index, const std::string s) {
361
14.1k
            if ( index >= bn.size() ) {
362
0
                abort();
363
0
            }
364
365
14.1k
            return bn[index].Set(s);
366
14.1k
        }
367
};
368
369
class BN_CTX {
370
    private:
371
        ::BN_CTX* ctx = nullptr;
372
    public:
373
        BN_CTX(Datasource& ds) :
374
3.71k
            ctx(BN_CTX_new())
375
3.71k
        {
376
3.71k
            (void)ds;
377
3.71k
            if ( ctx == nullptr ) {
378
0
                abort();
379
0
            }
380
3.71k
        }
381
382
858
        ::BN_CTX* GetPtr() {
383
858
            return ctx;
384
858
        }
385
386
3.71k
        ~BN_CTX() {
387
3.71k
            BN_CTX_free(ctx);
388
3.71k
        }
389
};
390
391
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
392
class BN_MONT_CTX {
393
    private:
394
        ::BN_MONT_CTX* ctx = nullptr;
395
    public:
396
        BN_MONT_CTX(Datasource& ds) :
397
            ctx(BN_MONT_CTX_new())
398
        {
399
            (void)ds;
400
            if ( ctx == nullptr ) {
401
                abort();
402
            }
403
        }
404
405
        ::BN_MONT_CTX* GetPtr() {
406
            return ctx;
407
        }
408
409
        ~BN_MONT_CTX() {
410
            BN_MONT_CTX_free(ctx);
411
        }
412
};
413
#endif
414
415
class Operation {
416
    public:
417
        virtual bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const = 0;
418
1.19k
        virtual ~Operation() { }
419
};
420
421
class Add : public Operation {
422
    public:
423
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
424
};
425
426
class Sub : public Operation {
427
    public:
428
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
429
};
430
431
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
432
class Mul : public Operation {
433
    public:
434
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
435
};
436
#endif
437
438
class Mod : public Operation {
439
    public:
440
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
441
};
442
443
class ExpMod : public Operation {
444
    public:
445
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
446
};
447
448
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
449
class Sqr : public Operation {
450
    public:
451
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
452
};
453
#endif
454
455
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
456
class GCD : public Operation {
457
    public:
458
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
459
};
460
#endif
461
462
class AddMod : public Operation {
463
    public:
464
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
465
};
466
467
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
468
class SubMod : public Operation {
469
    public:
470
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
471
};
472
#endif
473
474
class MulMod : public Operation {
475
    public:
476
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
477
};
478
479
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
480
class SqrMod : public Operation {
481
    public:
482
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
483
};
484
#endif
485
486
class InvMod : public Operation {
487
    public:
488
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
489
};
490
491
class Cmp : public Operation {
492
    public:
493
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
494
};
495
496
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
497
class Div : public Operation {
498
    public:
499
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
500
};
501
#endif
502
503
class IsPrime : public Operation {
504
    public:
505
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
506
};
507
508
class Sqrt : public Operation {
509
    public:
510
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
511
};
512
513
class IsNeg : public Operation {
514
    public:
515
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
516
};
517
518
class IsEq : public Operation {
519
    public:
520
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
521
};
522
523
class IsEven : public Operation {
524
    public:
525
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
526
};
527
528
class IsOdd : public Operation {
529
    public:
530
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
531
};
532
533
class IsZero : public Operation {
534
    public:
535
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
536
};
537
538
class IsOne : public Operation {
539
    public:
540
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
541
};
542
543
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
544
class Jacobi : public Operation {
545
    public:
546
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
547
};
548
#endif
549
550
#if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
551
class Mod_NIST_192 : public Operation {
552
    public:
553
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
554
};
555
556
class Mod_NIST_224 : public Operation {
557
    public:
558
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
559
};
560
561
class Mod_NIST_256 : public Operation {
562
    public:
563
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
564
};
565
566
class Mod_NIST_384 : public Operation {
567
    public:
568
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
569
};
570
571
class Mod_NIST_521 : public Operation {
572
    public:
573
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
574
};
575
#endif
576
577
class SqrtMod : public Operation {
578
    public:
579
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
580
};
581
582
#if defined(CRYPTOFUZZ_BORINGSSL)
583
class LCM : public Operation {
584
    public:
585
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
586
};
587
#endif
588
589
class Exp : public Operation {
590
    public:
591
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
592
};
593
594
#if defined(CRYPTOFUZZ_BORINGSSL)
595
class Abs : public Operation {
596
    public:
597
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
598
};
599
#endif
600
601
class RShift : public Operation {
602
    public:
603
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
604
};
605
606
class LShift1 : public Operation {
607
    public:
608
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
609
};
610
611
class SetBit : public Operation {
612
    public:
613
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
614
};
615
616
class ClearBit : public Operation {
617
    public:
618
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
619
};
620
621
class Bit : public Operation {
622
    public:
623
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
624
};
625
626
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
627
class CmpAbs : public Operation {
628
    public:
629
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
630
};
631
#endif
632
633
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
634
class ModLShift : public Operation {
635
    public:
636
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
637
};
638
#endif
639
640
class IsPow2 : public Operation {
641
    public:
642
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
643
};
644
645
class Mask : public Operation {
646
    public:
647
        bool Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const override;
648
};
649
650
} /* namespace OpenSSL_bignum */
651
} /* namespace module */
652
} /* namespace cryptofuzz */