Coverage Report

Created: 2025-12-31 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptofuzz-openssl-api/modules/wolfcrypt-openssl/bn_ops.h
Line
Count
Source
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
26.3k
            ds(ds)
26
26.3k
    { }
27
28
38.4k
        ~Bignum() {
29
38.4k
            if ( noFree == false ) {
30
36.8k
                BN_free(bn);
31
36.8k
            }
32
38.4k
        }
33
34
1.61k
        void Lock(void) {
35
1.61k
            locked = true;
36
1.61k
        }
37
38
1.57k
        void DisableFree(void) {
39
1.57k
            noFree = true;
40
1.57k
        }
41
42
1.57k
        void ReleaseOwnership(void) {
43
1.57k
            Lock();
44
1.57k
            DisableFree();
45
1.57k
        }
46
47
18.2k
        bool New(void) {
48
18.2k
            if ( locked == true ) {
49
0
                printf("Cannot renew locked Bignum\n");
50
0
                abort();
51
0
            }
52
53
18.2k
            BN_free(bn);
54
18.2k
            bn = BN_new();
55
56
18.2k
            return bn != nullptr;
57
18.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
22.0k
        bool Set(const std::string s) {
70
22.0k
            if ( locked == true ) {
71
0
                printf("Cannot set locked Bignum\n");
72
0
                abort();
73
0
            }
74
75
22.0k
            bool ret = false;
76
77
22.0k
#if defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
78
22.0k
            const auto asHex = util::DecToHex(s);
79
22.0k
            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
21.8k
            ret = true;
85
22.0k
end:
86
22.0k
            return ret;
87
21.8k
        }
88
89
99
        std::optional<uint64_t> AsUint64(void) const {
90
99
            std::optional<uint64_t> ret = std::nullopt;
91
99
            try {
92
99
                switch ( ds.Get<uint8_t>() ) {
93
6
                    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
6
                        break;
122
2
                    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
2
                        break;
137
30
                    default:
138
30
                        break;
139
140
99
                }
141
99
            } catch ( ... ) { }
142
143
            /* Silence compiler */
144
99
            goto end;
145
99
end:
146
99
            return ret;
147
99
        }
148
149
93
        std::optional<int> AsInt(void) const {
150
93
            std::optional<int> ret = std::nullopt;
151
93
            const auto u64 = AsUint64();
152
153
93
            CF_CHECK_NE(u64, std::nullopt);
154
0
            CF_CHECK_LTE(*u64, 2147483647);
155
156
0
            ret = *u64;
157
93
end:
158
93
            return ret;
159
0
        }
160
161
6
        std::optional<BN_ULONG> AsBN_ULONG(void) const {
162
6
            std::optional<BN_ULONG> ret;
163
6
            std::optional<uint64_t> v64;
164
165
            /* Convert bn[1] to uint64_t if possible */
166
6
            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
6
end:
174
6
            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
16.3k
        BIGNUM* GetDestPtr(const bool allowDup = true) {
191
16.3k
            if ( locked == false ) {
192
16.3k
                try {
193
16.3k
                    {
194
16.3k
                        const bool changeConstness = ds.Get<bool>();
195
16.3k
                        if ( changeConstness == true ) {
196
1.42k
#if !defined(CRYPTOFUZZ_BORINGSSL)
197
1.42k
                            const bool constness = ds.Get<bool>();
198
199
1.42k
                            if ( constness == true ) {
200
748
                                /* noret */ BN_set_flags(bn, BN_FLG_CONSTTIME);
201
748
                            } else {
202
679
                                /* noret */ BN_set_flags(bn, 0);
203
679
                            }
204
1.42k
#endif
205
1.42k
                        }
206
16.3k
                    }
207
208
16.3k
                    {
209
16.3k
                        if ( allowDup == true ) {
210
2.96k
                            const bool dup = ds.Get<bool>();
211
212
2.96k
                            if ( dup == true ) {
213
1.30k
                                BIGNUM* tmp = BN_dup(bn);
214
1.30k
                                if ( tmp != nullptr ) {
215
1.30k
                                    BN_free(bn);
216
1.30k
                                    bn = tmp;
217
1.30k
                                }
218
1.30k
                            }
219
2.96k
                        }
220
16.3k
                    }
221
222
16.3k
                    {
223
16.3k
                        if ( allowDup == true ) {
224
2.76k
                            const bool asn1Convert = ds.Get<bool>();
225
226
2.76k
                            if ( asn1Convert == true ) {
227
1.19k
                                ASN1_INTEGER* asn1 = BN_to_ASN1_INTEGER(bn, nullptr);
228
229
1.19k
                                if ( asn1 != nullptr ) {
230
1.19k
                                    BIGNUM* tmp = ASN1_INTEGER_to_BN(asn1, nullptr);
231
232
1.19k
                                    if ( tmp != nullptr ) {
233
1.19k
                                        BN_free(bn);
234
1.19k
                                        bn = tmp;
235
1.19k
                                    }
236
237
1.19k
                                    ASN1_INTEGER_free(asn1);
238
1.19k
                                }
239
1.19k
                            }
240
2.76k
                        }
241
16.3k
                    }
242
243
16.3k
                    {
244
16.3k
                        if ( allowDup == true ) {
245
2.50k
                            const bool asn1Convert = ds.Get<bool>();
246
247
2.50k
                            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.05k
                            }
263
2.50k
                        }
264
16.3k
                    }
265
16.3k
                } catch ( ... ) { }
266
16.3k
            }
267
268
16.3k
            return bn;
269
16.3k
        }
270
271
332
        BIGNUM* GetPtrConst(void) const {
272
332
            return bn;
273
332
        }
274
275
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
276
        const BIGNUM* GetPtr(const bool allowDup = true) {
277
#else
278
11.2k
        BIGNUM* GetPtr(const bool allowDup = true) {
279
11.2k
#endif
280
11.2k
            return GetDestPtr(allowDup);
281
11.2k
        }
282
283
489
        std::optional<component::Bignum> ToComponentBignum(void) {
284
489
            std::optional<component::Bignum> ret = std::nullopt;
285
286
489
            char* str = nullptr;
287
489
            CF_CHECK_NE(str = BN_bn2dec(GetPtr()), nullptr);
288
289
489
            ret = { std::string(str) };
290
489
end:
291
489
            OPENSSL_free(str);
292
293
489
            return ret;
294
489
        }
295
296
166
        inline bool operator==(const Bignum& rhs) const {
297
166
            return BN_cmp(GetPtrConst(), rhs.GetPtrConst()) == 0;
298
166
        }
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.02k
            ds(ds),
308
3.02k
            bn({bn0, bn1, bn2, bn3})
309
3.02k
        { }
310
311
1.36k
        Bignum& operator[](const size_t index) {
312
1.36k
            if ( index >= bn.size() ) {
313
0
                abort();
314
0
            }
315
316
1.36k
            try {
317
                /* Rewire? */
318
1.36k
                if ( ds.Get<bool>() == true ) {
319
                    /* Pick a random bignum */
320
185
                    const size_t newIndex = ds.Get<uint8_t>() % 4;
321
322
                    /* Same value? */
323
185
                    if ( bn[newIndex] == bn[index] ) {
324
                        /* Then return reference to other bignum */
325
326
68
                        if ( newIndex != index ) {
327
32
                            bn[newIndex].Lock();
328
32
                        }
329
330
68
                        return bn[newIndex];
331
68
                    }
332
333
                    /* Fall through */
334
185
                }
335
1.36k
            } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
336
337
1.29k
            return bn[index];
338
1.36k
        }
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
12.1k
        bool New(const size_t index) {
353
12.1k
            if ( index >= bn.size() ) {
354
0
                abort();
355
0
            }
356
357
12.1k
            return bn[index].New();
358
12.1k
        }
359
360
12.0k
        bool Set(const size_t index, const std::string s) {
361
12.0k
            if ( index >= bn.size() ) {
362
0
                abort();
363
0
            }
364
365
12.0k
            return bn[index].Set(s);
366
12.0k
        }
367
};
368
369
class BN_CTX {
370
    private:
371
        ::BN_CTX* ctx = nullptr;
372
    public:
373
        BN_CTX(Datasource& ds) :
374
3.16k
            ctx(BN_CTX_new())
375
3.16k
        {
376
3.16k
            (void)ds;
377
3.16k
            if ( ctx == nullptr ) {
378
0
                abort();
379
0
            }
380
3.16k
        }
381
382
550
        ::BN_CTX* GetPtr() {
383
550
            return ctx;
384
550
        }
385
386
3.16k
        ~BN_CTX() {
387
3.16k
            BN_CTX_free(ctx);
388
3.16k
        }
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
867
        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 */