Coverage Report

Created: 2022-08-24 06:37

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