Coverage Report

Created: 2026-02-18 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/cryptofuzz/modules/botan/module.cpp
Line
Count
Source
1
#include "module.h"
2
#include <cryptofuzz/util.h>
3
#include <cryptofuzz/repository.h>
4
#include <botan/aead.h>
5
#include <botan/ber_dec.h>
6
#include <botan/bigint.h>
7
#include <botan/cipher_mode.h>
8
#include <botan/curve25519.h>
9
#include <botan/dh.h>
10
#include <botan/dl_group.h>
11
#include <botan/dsa.h>
12
#include <botan/ecdsa.h>
13
#include <botan/ecgdsa.h>
14
#include <botan/ed25519.h>
15
#include <botan/hash.h>
16
#include <botan/kdf.h>
17
#include <botan/mac.h>
18
#include <botan/pubkey.h>
19
#include <botan/pwdhash.h>
20
#include <botan/system_rng.h>
21
#include "bn_ops.h"
22
23
namespace cryptofuzz {
24
namespace module {
25
26
Botan::Botan(void) :
27
2
    Module("Botan") {
28
2
    if ( setenv("BOTAN_MLOCK_POOL_SIZE", "0", 1) != 0 ) {
29
0
        abort();
30
0
    }
31
32
    /* Add a few curves */
33
34
2
    {
35
2
        const ::Botan::OID secp112r1_oid("1.3.132.0.6");
36
2
        const ::Botan::EC_Group secp112r1(
37
2
                ::Botan::BigInt::from_string("4451685225093714772084598273548427"),
38
2
                ::Botan::BigInt::from_string("4451685225093714772084598273548424"),
39
2
                ::Botan::BigInt::from_string("2061118396808653202902996166388514"),
40
2
                ::Botan::BigInt::from_string("188281465057972534892223778713752"),
41
2
                ::Botan::BigInt::from_string("3419875491033170827167861896082688"),
42
2
                ::Botan::BigInt::from_string("4451685225093714776491891542548933"),
43
2
                1,
44
2
                secp112r1_oid);
45
2
        ::Botan::OID::register_oid(secp112r1_oid, "secp112r1");
46
2
    }
47
48
2
    {
49
2
        const ::Botan::OID secp112r2_oid("1.3.132.0.7");
50
2
        const ::Botan::EC_Group secp112r2(
51
2
                ::Botan::BigInt::from_string("4451685225093714772084598273548427"),
52
2
                ::Botan::BigInt::from_string("1970543761890640310119143205433388"),
53
2
                ::Botan::BigInt::from_string("1660538572255285715897238774208265"),
54
2
                ::Botan::BigInt::from_string("1534098225527667214992304222930499"),
55
2
                ::Botan::BigInt::from_string("3525120595527770847583704454622871"),
56
2
                ::Botan::BigInt::from_string("1112921306273428674967732714786891"),
57
2
                4,
58
2
                secp112r2_oid);
59
2
        ::Botan::OID::register_oid(secp112r2_oid, "secp112r2");
60
2
    }
61
62
2
    {
63
2
        const ::Botan::OID secp128r1_oid("1.3.132.0.28");
64
2
        const ::Botan::EC_Group secp128r1(
65
2
                ::Botan::BigInt::from_string("340282366762482138434845932244680310783"),
66
2
                ::Botan::BigInt::from_string("340282366762482138434845932244680310780"),
67
2
                ::Botan::BigInt::from_string("308990863222245658030922601041482374867"),
68
2
                ::Botan::BigInt::from_string("29408993404948928992877151431649155974"),
69
2
                ::Botan::BigInt::from_string("275621562871047521857442314737465260675"),
70
2
                ::Botan::BigInt::from_string("340282366762482138443322565580356624661"),
71
2
                1,
72
2
                secp128r1_oid);
73
2
        ::Botan::OID::register_oid(secp128r1_oid, "secp128r1");
74
2
    }
75
76
2
    {
77
2
        const ::Botan::OID secp128r2_oid("1.3.132.0.29");
78
2
        const ::Botan::EC_Group secp128r2(
79
2
                ::Botan::BigInt::from_string("340282366762482138434845932244680310783"),
80
2
                ::Botan::BigInt::from_string("284470887156368047300405921324061011681"),
81
2
                ::Botan::BigInt::from_string("126188322377389722996253562430093625949"),
82
2
                ::Botan::BigInt::from_string("164048790688614013222215505581242564928"),
83
2
                ::Botan::BigInt::from_string("52787839253935625605232456597451787076"),
84
2
                ::Botan::BigInt::from_string("85070591690620534603955721926813660579"),
85
2
                4,
86
2
                secp128r2_oid);
87
2
        ::Botan::OID::register_oid(secp128r2_oid, "secp128r2");
88
2
    }
89
2
}
90
91
#if !defined(CRYPTOFUZZ_BOTAN_IS_ORACLE)
92
4.28k
 #define BOTAN_FUZZER_RNG Botan_detail::Fuzzer_RNG rng(ds);
93
#else
94
 #define BOTAN_FUZZER_RNG ::Botan::System_RNG rng;
95
#endif /* CRYPTOFUZZ_BOTAN_IS_ORACLE */
96
97
#if !defined(CRYPTOFUZZ_BOTAN_IS_ORACLE)
98
4.59k
 #define BOTAN_SET_GLOBAL_DS CF_NORET(util::SetGlobalDs(&ds));
99
4.59k
 #define BOTAN_UNSET_GLOBAL_DS CF_NORET(util::UnsetGlobalDs());
100
#else
101
 #define BOTAN_SET_GLOBAL_DS
102
 #define BOTAN_UNSET_GLOBAL_DS
103
#endif
104
105
namespace Botan_detail {
106
107
#if !defined(CRYPTOFUZZ_BOTAN_IS_ORACLE)
108
    class Fuzzer_RNG final : public ::Botan::RandomNumberGenerator {
109
        private:
110
            Datasource& ds;
111
        public:
112
            Fuzzer_RNG(Datasource& ds) :
113
4.28k
                ds(ds)
114
4.28k
            { }
115
116
8.82k
            bool is_seeded() const override { return true; }
117
118
0
            bool accepts_input() const override { return false; }
119
120
0
            void clear() override {}
121
122
            virtual void fill_bytes_with_input(
123
                    std::span<uint8_t> output,
124
31.6k
                    std::span<const uint8_t> input) override {
125
31.6k
                (void)input;
126
127
31.6k
                if ( output.empty() ) {
128
0
                    return;
129
0
                }
130
131
31.6k
                const auto data = ds.GetData(0, output.size(), output.size());
132
133
31.6k
                std::copy(data.begin(), data.end(), output.begin());
134
31.6k
            }
135
136
0
            std::string name() const override { return "Fuzzer_RNG"; }
137
    };
138
#endif /* CRYPTOFUZZ_BOTAN_IS_ORACLE */
139
140
2.48k
    const std::string parenthesize(const std::string parent, const std::string child) {
141
2.48k
        static const std::string pOpen("(");
142
2.48k
        static const std::string pClose(")");
143
144
2.48k
        return parent + pOpen + child + pClose;
145
2.48k
    }
146
147
3.83k
    std::optional<std::string> DigestIDToString(const uint64_t digestType, const bool altShake = false, const bool isHmac = false) {
148
3.83k
#include "digest_string_lut.h"
149
3.83k
        std::optional<std::string> ret = std::nullopt;
150
151
3.83k
        CF_CHECK_NE(LUT.find(digestType), LUT.end());
152
153
3.59k
        if ( isHmac == false ) {
154
3.37k
            if (    digestType == CF_DIGEST("SIPHASH64") ||
155
3.37k
                    digestType == CF_DIGEST("SIPHASH128") ) {
156
1
                return std::nullopt;
157
1
            }
158
3.37k
        }
159
3.59k
        if ( altShake == true && digestType == CF_DIGEST("SHAKE128") ) {
160
15
            ret = "SHAKE-128(256)";
161
3.58k
        } else if ( altShake == true && digestType == CF_DIGEST("SHAKE256") ) {
162
13
            ret = "SHAKE-256(512)";
163
3.57k
        } else if ( altShake == true && digestType == CF_DIGEST("SHAKE256_114") ) {
164
0
            ret = "SHAKE-256(912)"; /* 114 bytes * 8 = 912 bits */
165
3.57k
        } else {
166
3.57k
            ret = LUT.at(digestType);
167
3.57k
        }
168
3.83k
end:
169
3.83k
        return ret;
170
3.59k
    }
171
172
} /* namespace Botan_detail */
173
174
440
std::optional<component::Digest> Botan::OpDigest(operation::Digest& op) {
175
440
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
176
440
    std::optional<component::Digest> ret = std::nullopt;
177
440
    std::unique_ptr<::Botan::HashFunction> hash = nullptr;
178
440
    util::Multipart parts;
179
440
    size_t numClears = 0;
180
181
    /* Initialize */
182
440
    {
183
440
        BOTAN_SET_GLOBAL_DS
184
185
440
        std::optional<std::string> algoString;
186
440
        CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get()), std::nullopt);
187
374
        CF_CHECK_NE(hash = ::Botan::HashFunction::create(*algoString), nullptr);
188
189
374
        parts = util::ToParts(ds, op.cleartext);
190
374
    }
191
192
512
again:
193
    /* Process */
194
41.3k
    for (const auto& part : parts) {
195
41.3k
        hash->update(part.first, part.second);
196
41.3k
        bool clear = false;
197
198
41.3k
        if ( numClears < 3 ) {
199
41.3k
            try {
200
41.3k
#if !defined(CRYPTOFUZZ_BOTAN_IS_ORACLE)
201
41.3k
                clear = ds.Get<bool>();
202
41.3k
#endif /* CRYPTOFUZZ_BOTAN_IS_ORACLE */
203
41.3k
            } catch ( ... ) { }
204
41.3k
        }
205
206
41.3k
        if ( clear == true ) {
207
138
            hash->clear();
208
138
            numClears++;
209
138
            goto again;
210
138
        }
211
41.3k
    }
212
213
    /* Finalize */
214
374
    {
215
374
        const auto res = hash->final();
216
374
        ret = component::Digest(res.data(), res.size());
217
374
    }
218
219
440
end:
220
440
    BOTAN_UNSET_GLOBAL_DS
221
222
440
    return ret;
223
374
}
224
225
264
std::optional<component::MAC> Botan::OpHMAC(operation::HMAC& op) {
226
264
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
227
264
    std::optional<component::MAC> ret = std::nullopt;
228
264
    std::unique_ptr<::Botan::MessageAuthenticationCode> hmac = nullptr;
229
264
    util::Multipart parts;
230
231
264
    try {
232
        /* Initialize */
233
264
        {
234
264
            BOTAN_SET_GLOBAL_DS
235
236
264
            std::optional<std::string> algoString;
237
264
            CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get(), true, true), std::nullopt);
238
239
222
            std::string hmacString;
240
222
            if (
241
222
                    op.digestType.Is(CF_DIGEST("SIPHASH64")) ||
242
185
                    op.digestType.Is(CF_DIGEST("BLAKE2B_MAC")) ) {
243
48
                hmacString = *algoString;
244
174
            } else {
245
174
                hmacString = Botan_detail::parenthesize("HMAC", *algoString);
246
174
            }
247
248
222
            CF_CHECK_NE(hmac = ::Botan::MessageAuthenticationCode::create(hmacString), nullptr);
249
250
222
            try {
251
222
                hmac->set_key(op.cipher.key.GetPtr(), op.cipher.key.GetSize());
252
222
            } catch ( ... ) {
253
7
                goto end;
254
7
            }
255
256
214
            parts = util::ToParts(ds, op.cleartext);
257
214
        }
258
259
        /* Process */
260
5.87k
        for (const auto& part : parts) {
261
5.87k
            hmac->update(part.first, part.second);
262
5.87k
        }
263
264
        /* Finalize */
265
214
        {
266
214
            const auto res = hmac->final();
267
214
            ret = component::MAC(res.data(), res.size());
268
214
        }
269
270
214
    } catch ( ... ) { }
271
272
264
end:
273
264
    BOTAN_UNSET_GLOBAL_DS
274
275
264
    return ret;
276
264
}
277
278
namespace Botan_detail {
279
280
1.22k
    std::optional<std::string> CipherIDToString(const uint64_t digestType, const bool withMode = true) {
281
1.22k
#include "cipher_string_lut.h"
282
1.22k
        std::optional<std::string> ret = std::nullopt;
283
284
1.22k
        CF_CHECK_NE(LUT.find(digestType), LUT.end());
285
994
        ret = withMode ? LUT.at(digestType).first : LUT.at(digestType).second;
286
1.22k
end:
287
1.22k
        return ret;
288
994
    }
289
290
    template <class OperationType>
291
    const uint8_t* GetInPtr(const OperationType& op);
292
293
    template <>
294
523
    const uint8_t* GetInPtr(const operation::SymmetricEncrypt& op) {
295
523
        return op.cleartext.GetPtr();
296
523
    }
297
298
    template <>
299
544
    const uint8_t* GetInPtr(const operation::SymmetricDecrypt& op) {
300
544
        return op.ciphertext.GetPtr();
301
544
    }
302
303
    template <class OperationType>
304
    size_t GetInSize(const OperationType& op);
305
306
    template <>
307
523
    size_t GetInSize(const operation::SymmetricEncrypt& op) {
308
523
        return op.cleartext.GetSize();
309
523
    }
310
311
    template <>
312
727
    size_t GetInSize(const operation::SymmetricDecrypt& op) {
313
727
        return op.ciphertext.GetSize();
314
727
    }
315
316
    template <class OperationType>
317
    ::Botan::Cipher_Dir GetCryptType(void);
318
319
    template <>
320
780
    ::Botan::Cipher_Dir GetCryptType<operation::SymmetricEncrypt>(void) {
321
780
        return ::Botan::Cipher_Dir::Encryption;
322
780
    }
323
324
    template <>
325
896
    ::Botan::Cipher_Dir GetCryptType<operation::SymmetricDecrypt>(void) {
326
896
        return ::Botan::Cipher_Dir::Decryption;
327
896
    }
328
329
    template <class OperationType>
330
    std::optional<size_t> GetTagSize(const OperationType& op);
331
332
    template <>
333
810
    std::optional<size_t> GetTagSize<>(const operation::SymmetricEncrypt& op) {
334
810
        if ( op.tagSize == std::nullopt ) {
335
584
            return std::nullopt;
336
584
        }
337
338
226
        return *op.tagSize;
339
810
    }
340
341
    template <>
342
1.29k
    std::optional<size_t> GetTagSize<>(const operation::SymmetricDecrypt& op) {
343
1.29k
        if ( op.tag == std::nullopt ) {
344
878
            return std::nullopt;
345
878
        }
346
347
414
        return op.tag->GetSize();
348
1.29k
    }
349
350
    template <class OperationType>
351
    const uint8_t* GetTagPtr(const OperationType& op);
352
353
    template <>
354
0
    const uint8_t* GetTagPtr<>(const operation::SymmetricEncrypt& op) {
355
0
        (void)op;
356
357
0
        return nullptr;
358
0
    }
359
360
    template <>
361
183
    const uint8_t* GetTagPtr<>(const operation::SymmetricDecrypt& op) {
362
183
        if ( op.tag == std::nullopt ) {
363
0
            return nullptr;
364
0
        }
365
366
183
        return op.tag->GetPtr();
367
183
    }
368
369
    template <class CryptClass>
370
    void SetAAD(std::shared_ptr<CryptClass> crypt, const std::optional<component::AAD>& aad);
371
372
    template <>
373
239
    void SetAAD<>(std::shared_ptr<::Botan::AEAD_Mode> crypt, const std::optional<component::AAD>& aad) {
374
239
        if ( aad != std::nullopt ) {
375
127
            crypt->set_associated_data(aad->Get());
376
127
        }
377
239
    }
378
379
    template <>
380
223
    void SetAAD<>(std::shared_ptr<::Botan::Cipher_Mode> crypt, const std::optional<component::AAD>& aad) {
381
223
        (void)crypt;
382
223
        (void)aad;
383
223
    }
384
385
    template <class OperationType>
386
948
    ::Botan::secure_vector<uint8_t> GetInData(const OperationType& op) {
387
948
        const auto inPtr = GetInPtr(op);
388
948
        ::Botan::secure_vector<uint8_t> ret(inPtr, inPtr + GetInSize(op));
389
390
948
        if ( GetCryptType<OperationType>() == ::Botan::Cipher_Dir::Encryption ) {
391
458
            return ret;
392
458
        }
393
394
490
        const auto tagSize = GetTagSize(op);
395
396
490
        if ( tagSize == std::nullopt || *tagSize == 0 ) {
397
307
            return ret;
398
307
        }
399
400
        /* Append the tag */
401
402
183
        ret.resize(ret.size() + *tagSize);
403
404
183
        memcpy(ret.data() + GetInSize(op), GetTagPtr(op), *tagSize);
405
406
183
        return ret;
407
490
    }
std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > cryptofuzz::module::Botan_detail::GetInData<cryptofuzz::operation::SymmetricEncrypt>(cryptofuzz::operation::SymmetricEncrypt const&)
Line
Count
Source
386
458
    ::Botan::secure_vector<uint8_t> GetInData(const OperationType& op) {
387
458
        const auto inPtr = GetInPtr(op);
388
458
        ::Botan::secure_vector<uint8_t> ret(inPtr, inPtr + GetInSize(op));
389
390
458
        if ( GetCryptType<OperationType>() == ::Botan::Cipher_Dir::Encryption ) {
391
458
            return ret;
392
458
        }
393
394
0
        const auto tagSize = GetTagSize(op);
395
396
0
        if ( tagSize == std::nullopt || *tagSize == 0 ) {
397
0
            return ret;
398
0
        }
399
400
        /* Append the tag */
401
402
0
        ret.resize(ret.size() + *tagSize);
403
404
0
        memcpy(ret.data() + GetInSize(op), GetTagPtr(op), *tagSize);
405
406
0
        return ret;
407
0
    }
std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > cryptofuzz::module::Botan_detail::GetInData<cryptofuzz::operation::SymmetricDecrypt>(cryptofuzz::operation::SymmetricDecrypt const&)
Line
Count
Source
386
490
    ::Botan::secure_vector<uint8_t> GetInData(const OperationType& op) {
387
490
        const auto inPtr = GetInPtr(op);
388
490
        ::Botan::secure_vector<uint8_t> ret(inPtr, inPtr + GetInSize(op));
389
390
490
        if ( GetCryptType<OperationType>() == ::Botan::Cipher_Dir::Encryption ) {
391
0
            return ret;
392
0
        }
393
394
490
        const auto tagSize = GetTagSize(op);
395
396
490
        if ( tagSize == std::nullopt || *tagSize == 0 ) {
397
307
            return ret;
398
307
        }
399
400
        /* Append the tag */
401
402
183
        ret.resize(ret.size() + *tagSize);
403
404
183
        memcpy(ret.data() + GetInSize(op), GetTagPtr(op), *tagSize);
405
406
183
        return ret;
407
490
    }
408
409
    template <class ReturnType>
410
    ReturnType ToReturnType(const ::Botan::secure_vector<uint8_t>& data, std::optional<size_t> tagSize);
411
412
    template <>
413
158
    component::Ciphertext ToReturnType(const ::Botan::secure_vector<uint8_t>& data, std::optional<size_t> tagSize) {
414
158
        if ( tagSize == std::nullopt ) {
415
69
            return component::Ciphertext(Buffer(data.data(), data.size()));
416
69
        }
417
418
89
        const size_t ciphertextSize = data.size() - *tagSize;
419
420
89
        return component::Ciphertext(Buffer(data.data(), ciphertextSize), Buffer(data.data() + ciphertextSize, *tagSize));
421
158
    }
422
423
    template <>
424
220
    component::Cleartext ToReturnType(const ::Botan::secure_vector<uint8_t>& data, std::optional<size_t> tagSize) {
425
220
        (void)tagSize;
426
427
220
        return component::Cleartext(Buffer(data.data(), data.size()));
428
220
    }
429
430
    template <class ReturnType, class OperationType, class CryptClass>
431
1.19k
        std::optional<ReturnType> Crypt(OperationType& op, Datasource& ds) {
432
1.19k
            std::optional<ReturnType> ret = std::nullopt;
433
434
1.19k
            if ( typeid(CryptClass) == typeid(::Botan::Cipher_Mode) ) {
435
812
                if ( op.aad != std::nullopt ) {
436
148
                    return std::nullopt;
437
148
                }
438
664
                if ( GetTagSize(op) != std::nullopt ) {
439
100
                    return std::nullopt;
440
100
                }
441
664
            }
442
443
948
            std::shared_ptr<CryptClass> crypt = nullptr;
444
948
            const ::Botan::SymmetricKey key(op.cipher.key.GetPtr(), op.cipher.key.GetSize());
445
948
            const ::Botan::InitializationVector iv(op.cipher.iv.GetPtr(), op.cipher.iv.GetSize());
446
948
            ::Botan::secure_vector<uint8_t> in = GetInData(op);
447
948
            ::Botan::secure_vector<uint8_t> out;
448
948
            bool useOneShot = true;
449
948
            util::Multipart parts;
450
451
948
            const std::optional<size_t> tagSize = GetTagSize(op);
452
453
948
            try {
454
                /* Initialize */
455
948
                {
456
948
                    std::optional<std::string> _algoString;
457
948
                    CF_CHECK_NE(_algoString = Botan_detail::CipherIDToString(op.cipher.cipherType.Get()), std::nullopt);
458
728
                    std::string algoString;
459
728
                    if ( tagSize == std::nullopt ) {
460
388
                        algoString = Botan_detail::parenthesize(*_algoString, std::to_string(0));
461
388
                    } else {
462
340
                        algoString = Botan_detail::parenthesize(*_algoString, std::to_string(*tagSize));
463
340
                    }
464
465
728
                    CF_CHECK_NE(crypt = CryptClass::create(algoString, GetCryptType<OperationType>()), nullptr);
466
615
                    crypt->set_key(key);
467
468
615
                    SetAAD(crypt, op.aad);
469
470
615
                    crypt->start(iv.bits_of());
471
615
                    if ( crypt->update_granularity() == 1 ) {
472
280
                        try {
473
280
                            useOneShot = ds.Get<bool>();
474
280
                        } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
475
280
                    }
476
615
                    if ( useOneShot == false ) {
477
119
                        parts = util::ToParts(ds, GetInPtr(op), GetInSize(op));
478
119
                    }
479
615
                }
480
481
                /* Process */
482
0
                {
483
615
                    if ( useOneShot == true ) {
484
317
                        crypt->finish(in);
485
317
                    } else {
486
5.52k
                        for (const auto& part : parts) {
487
5.52k
                            std::vector<uint8_t> tmp(part.first, part.first + part.second);
488
5.52k
                            const auto num = crypt->process(tmp.data(), tmp.size());
489
5.52k
                            out.insert(out.end(), tmp.begin(), tmp.begin() + num);
490
5.52k
                        }
491
298
                        crypt->finish(out, out.size());
492
298
                    }
493
615
                }
494
495
                /* Finalize */
496
615
                {
497
                    /* TODO take max output size in consideration */
498
499
615
                    if ( useOneShot == true ) {
500
296
                        ret = ToReturnType<ReturnType>(in, tagSize);
501
319
                    } else {
502
319
                        ret = ToReturnType<ReturnType>(::Botan::secure_vector<uint8_t>(out.data(), out.data() + out.size()), tagSize);
503
319
                    }
504
615
                }
505
615
            } catch ( ... ) { }
506
948
end:
507
508
948
            return ret;
509
948
        }
std::__1::optional<cryptofuzz::component::Ciphertext> cryptofuzz::module::Botan_detail::Crypt<cryptofuzz::component::Ciphertext, cryptofuzz::operation::SymmetricEncrypt, Botan::AEAD_Mode>(cryptofuzz::operation::SymmetricEncrypt&, fuzzing::datasource::Datasource&)
Line
Count
Source
431
176
        std::optional<ReturnType> Crypt(OperationType& op, Datasource& ds) {
432
176
            std::optional<ReturnType> ret = std::nullopt;
433
434
176
            if ( typeid(CryptClass) == typeid(::Botan::Cipher_Mode) ) {
435
0
                if ( op.aad != std::nullopt ) {
436
0
                    return std::nullopt;
437
0
                }
438
0
                if ( GetTagSize(op) != std::nullopt ) {
439
0
                    return std::nullopt;
440
0
                }
441
0
            }
442
443
176
            std::shared_ptr<CryptClass> crypt = nullptr;
444
176
            const ::Botan::SymmetricKey key(op.cipher.key.GetPtr(), op.cipher.key.GetSize());
445
176
            const ::Botan::InitializationVector iv(op.cipher.iv.GetPtr(), op.cipher.iv.GetSize());
446
176
            ::Botan::secure_vector<uint8_t> in = GetInData(op);
447
176
            ::Botan::secure_vector<uint8_t> out;
448
176
            bool useOneShot = true;
449
176
            util::Multipart parts;
450
451
176
            const std::optional<size_t> tagSize = GetTagSize(op);
452
453
176
            try {
454
                /* Initialize */
455
176
                {
456
176
                    std::optional<std::string> _algoString;
457
176
                    CF_CHECK_NE(_algoString = Botan_detail::CipherIDToString(op.cipher.cipherType.Get()), std::nullopt);
458
172
                    std::string algoString;
459
172
                    if ( tagSize == std::nullopt ) {
460
16
                        algoString = Botan_detail::parenthesize(*_algoString, std::to_string(0));
461
156
                    } else {
462
156
                        algoString = Botan_detail::parenthesize(*_algoString, std::to_string(*tagSize));
463
156
                    }
464
465
172
                    CF_CHECK_NE(crypt = CryptClass::create(algoString, GetCryptType<OperationType>()), nullptr);
466
147
                    crypt->set_key(key);
467
468
147
                    SetAAD(crypt, op.aad);
469
470
147
                    crypt->start(iv.bits_of());
471
147
                    if ( crypt->update_granularity() == 1 ) {
472
89
                        try {
473
89
                            useOneShot = ds.Get<bool>();
474
89
                        } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
475
89
                    }
476
147
                    if ( useOneShot == false ) {
477
54
                        parts = util::ToParts(ds, GetInPtr(op), GetInSize(op));
478
54
                    }
479
147
                }
480
481
                /* Process */
482
0
                {
483
147
                    if ( useOneShot == true ) {
484
35
                        crypt->finish(in);
485
112
                    } else {
486
2.57k
                        for (const auto& part : parts) {
487
2.57k
                            std::vector<uint8_t> tmp(part.first, part.first + part.second);
488
2.57k
                            const auto num = crypt->process(tmp.data(), tmp.size());
489
2.57k
                            out.insert(out.end(), tmp.begin(), tmp.begin() + num);
490
2.57k
                        }
491
112
                        crypt->finish(out, out.size());
492
112
                    }
493
147
                }
494
495
                /* Finalize */
496
147
                {
497
                    /* TODO take max output size in consideration */
498
499
147
                    if ( useOneShot == true ) {
500
35
                        ret = ToReturnType<ReturnType>(in, tagSize);
501
112
                    } else {
502
112
                        ret = ToReturnType<ReturnType>(::Botan::secure_vector<uint8_t>(out.data(), out.data() + out.size()), tagSize);
503
112
                    }
504
147
                }
505
147
            } catch ( ... ) { }
506
176
end:
507
508
176
            return ret;
509
176
        }
std::__1::optional<cryptofuzz::component::Ciphertext> cryptofuzz::module::Botan_detail::Crypt<cryptofuzz::component::Ciphertext, cryptofuzz::operation::SymmetricEncrypt, Botan::Cipher_Mode>(cryptofuzz::operation::SymmetricEncrypt&, fuzzing::datasource::Datasource&)
Line
Count
Source
431
436
        std::optional<ReturnType> Crypt(OperationType& op, Datasource& ds) {
432
436
            std::optional<ReturnType> ret = std::nullopt;
433
434
436
            if ( typeid(CryptClass) == typeid(::Botan::Cipher_Mode) ) {
435
436
                if ( op.aad != std::nullopt ) {
436
84
                    return std::nullopt;
437
84
                }
438
352
                if ( GetTagSize(op) != std::nullopt ) {
439
70
                    return std::nullopt;
440
70
                }
441
352
            }
442
443
282
            std::shared_ptr<CryptClass> crypt = nullptr;
444
282
            const ::Botan::SymmetricKey key(op.cipher.key.GetPtr(), op.cipher.key.GetSize());
445
282
            const ::Botan::InitializationVector iv(op.cipher.iv.GetPtr(), op.cipher.iv.GetSize());
446
282
            ::Botan::secure_vector<uint8_t> in = GetInData(op);
447
282
            ::Botan::secure_vector<uint8_t> out;
448
282
            bool useOneShot = true;
449
282
            util::Multipart parts;
450
451
282
            const std::optional<size_t> tagSize = GetTagSize(op);
452
453
282
            try {
454
                /* Initialize */
455
282
                {
456
282
                    std::optional<std::string> _algoString;
457
282
                    CF_CHECK_NE(_algoString = Botan_detail::CipherIDToString(op.cipher.cipherType.Get()), std::nullopt);
458
150
                    std::string algoString;
459
150
                    if ( tagSize == std::nullopt ) {
460
150
                        algoString = Botan_detail::parenthesize(*_algoString, std::to_string(0));
461
150
                    } else {
462
0
                        algoString = Botan_detail::parenthesize(*_algoString, std::to_string(*tagSize));
463
0
                    }
464
465
150
                    CF_CHECK_NE(crypt = CryptClass::create(algoString, GetCryptType<OperationType>()), nullptr);
466
124
                    crypt->set_key(key);
467
468
124
                    SetAAD(crypt, op.aad);
469
470
124
                    crypt->start(iv.bits_of());
471
124
                    if ( crypt->update_granularity() == 1 ) {
472
14
                        try {
473
14
                            useOneShot = ds.Get<bool>();
474
14
                        } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
475
14
                    }
476
124
                    if ( useOneShot == false ) {
477
11
                        parts = util::ToParts(ds, GetInPtr(op), GetInSize(op));
478
11
                    }
479
124
                }
480
481
                /* Process */
482
0
                {
483
124
                    if ( useOneShot == true ) {
484
60
                        crypt->finish(in);
485
64
                    } else {
486
292
                        for (const auto& part : parts) {
487
292
                            std::vector<uint8_t> tmp(part.first, part.first + part.second);
488
292
                            const auto num = crypt->process(tmp.data(), tmp.size());
489
292
                            out.insert(out.end(), tmp.begin(), tmp.begin() + num);
490
292
                        }
491
64
                        crypt->finish(out, out.size());
492
64
                    }
493
124
                }
494
495
                /* Finalize */
496
124
                {
497
                    /* TODO take max output size in consideration */
498
499
124
                    if ( useOneShot == true ) {
500
58
                        ret = ToReturnType<ReturnType>(in, tagSize);
501
66
                    } else {
502
66
                        ret = ToReturnType<ReturnType>(::Botan::secure_vector<uint8_t>(out.data(), out.data() + out.size()), tagSize);
503
66
                    }
504
124
                }
505
124
            } catch ( ... ) { }
506
282
end:
507
508
282
            return ret;
509
282
        }
std::__1::optional<cryptofuzz::Buffer> cryptofuzz::module::Botan_detail::Crypt<cryptofuzz::Buffer, cryptofuzz::operation::SymmetricDecrypt, Botan::AEAD_Mode>(cryptofuzz::operation::SymmetricDecrypt&, fuzzing::datasource::Datasource&)
Line
Count
Source
431
208
        std::optional<ReturnType> Crypt(OperationType& op, Datasource& ds) {
432
208
            std::optional<ReturnType> ret = std::nullopt;
433
434
208
            if ( typeid(CryptClass) == typeid(::Botan::Cipher_Mode) ) {
435
0
                if ( op.aad != std::nullopt ) {
436
0
                    return std::nullopt;
437
0
                }
438
0
                if ( GetTagSize(op) != std::nullopt ) {
439
0
                    return std::nullopt;
440
0
                }
441
0
            }
442
443
208
            std::shared_ptr<CryptClass> crypt = nullptr;
444
208
            const ::Botan::SymmetricKey key(op.cipher.key.GetPtr(), op.cipher.key.GetSize());
445
208
            const ::Botan::InitializationVector iv(op.cipher.iv.GetPtr(), op.cipher.iv.GetSize());
446
208
            ::Botan::secure_vector<uint8_t> in = GetInData(op);
447
208
            ::Botan::secure_vector<uint8_t> out;
448
208
            bool useOneShot = true;
449
208
            util::Multipart parts;
450
451
208
            const std::optional<size_t> tagSize = GetTagSize(op);
452
453
208
            try {
454
                /* Initialize */
455
208
                {
456
208
                    std::optional<std::string> _algoString;
457
208
                    CF_CHECK_NE(_algoString = Botan_detail::CipherIDToString(op.cipher.cipherType.Get()), std::nullopt);
458
196
                    std::string algoString;
459
196
                    if ( tagSize == std::nullopt ) {
460
12
                        algoString = Botan_detail::parenthesize(*_algoString, std::to_string(0));
461
184
                    } else {
462
184
                        algoString = Botan_detail::parenthesize(*_algoString, std::to_string(*tagSize));
463
184
                    }
464
465
196
                    CF_CHECK_NE(crypt = CryptClass::create(algoString, GetCryptType<OperationType>()), nullptr);
466
172
                    crypt->set_key(key);
467
468
172
                    SetAAD(crypt, op.aad);
469
470
172
                    crypt->start(iv.bits_of());
471
172
                    if ( crypt->update_granularity() == 1 ) {
472
144
                        try {
473
144
                            useOneShot = ds.Get<bool>();
474
144
                        } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
475
144
                    }
476
172
                    if ( useOneShot == false ) {
477
37
                        parts = util::ToParts(ds, GetInPtr(op), GetInSize(op));
478
37
                    }
479
172
                }
480
481
                /* Process */
482
0
                {
483
172
                    if ( useOneShot == true ) {
484
107
                        crypt->finish(in);
485
107
                    } else {
486
1.79k
                        for (const auto& part : parts) {
487
1.79k
                            std::vector<uint8_t> tmp(part.first, part.first + part.second);
488
1.79k
                            const auto num = crypt->process(tmp.data(), tmp.size());
489
1.79k
                            out.insert(out.end(), tmp.begin(), tmp.begin() + num);
490
1.79k
                        }
491
65
                        crypt->finish(out, out.size());
492
65
                    }
493
172
                }
494
495
                /* Finalize */
496
172
                {
497
                    /* TODO take max output size in consideration */
498
499
172
                    if ( useOneShot == true ) {
500
89
                        ret = ToReturnType<ReturnType>(in, tagSize);
501
89
                    } else {
502
83
                        ret = ToReturnType<ReturnType>(::Botan::secure_vector<uint8_t>(out.data(), out.data() + out.size()), tagSize);
503
83
                    }
504
172
                }
505
172
            } catch ( ... ) { }
506
208
end:
507
508
208
            return ret;
509
208
        }
std::__1::optional<cryptofuzz::Buffer> cryptofuzz::module::Botan_detail::Crypt<cryptofuzz::Buffer, cryptofuzz::operation::SymmetricDecrypt, Botan::Cipher_Mode>(cryptofuzz::operation::SymmetricDecrypt&, fuzzing::datasource::Datasource&)
Line
Count
Source
431
376
        std::optional<ReturnType> Crypt(OperationType& op, Datasource& ds) {
432
376
            std::optional<ReturnType> ret = std::nullopt;
433
434
376
            if ( typeid(CryptClass) == typeid(::Botan::Cipher_Mode) ) {
435
376
                if ( op.aad != std::nullopt ) {
436
64
                    return std::nullopt;
437
64
                }
438
312
                if ( GetTagSize(op) != std::nullopt ) {
439
30
                    return std::nullopt;
440
30
                }
441
312
            }
442
443
282
            std::shared_ptr<CryptClass> crypt = nullptr;
444
282
            const ::Botan::SymmetricKey key(op.cipher.key.GetPtr(), op.cipher.key.GetSize());
445
282
            const ::Botan::InitializationVector iv(op.cipher.iv.GetPtr(), op.cipher.iv.GetSize());
446
282
            ::Botan::secure_vector<uint8_t> in = GetInData(op);
447
282
            ::Botan::secure_vector<uint8_t> out;
448
282
            bool useOneShot = true;
449
282
            util::Multipart parts;
450
451
282
            const std::optional<size_t> tagSize = GetTagSize(op);
452
453
282
            try {
454
                /* Initialize */
455
282
                {
456
282
                    std::optional<std::string> _algoString;
457
282
                    CF_CHECK_NE(_algoString = Botan_detail::CipherIDToString(op.cipher.cipherType.Get()), std::nullopt);
458
210
                    std::string algoString;
459
210
                    if ( tagSize == std::nullopt ) {
460
210
                        algoString = Botan_detail::parenthesize(*_algoString, std::to_string(0));
461
210
                    } else {
462
0
                        algoString = Botan_detail::parenthesize(*_algoString, std::to_string(*tagSize));
463
0
                    }
464
465
210
                    CF_CHECK_NE(crypt = CryptClass::create(algoString, GetCryptType<OperationType>()), nullptr);
466
172
                    crypt->set_key(key);
467
468
172
                    SetAAD(crypt, op.aad);
469
470
172
                    crypt->start(iv.bits_of());
471
172
                    if ( crypt->update_granularity() == 1 ) {
472
33
                        try {
473
33
                            useOneShot = ds.Get<bool>();
474
33
                        } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
475
33
                    }
476
172
                    if ( useOneShot == false ) {
477
17
                        parts = util::ToParts(ds, GetInPtr(op), GetInSize(op));
478
17
                    }
479
172
                }
480
481
                /* Process */
482
0
                {
483
172
                    if ( useOneShot == true ) {
484
115
                        crypt->finish(in);
485
115
                    } else {
486
862
                        for (const auto& part : parts) {
487
862
                            std::vector<uint8_t> tmp(part.first, part.first + part.second);
488
862
                            const auto num = crypt->process(tmp.data(), tmp.size());
489
862
                            out.insert(out.end(), tmp.begin(), tmp.begin() + num);
490
862
                        }
491
57
                        crypt->finish(out, out.size());
492
57
                    }
493
172
                }
494
495
                /* Finalize */
496
172
                {
497
                    /* TODO take max output size in consideration */
498
499
172
                    if ( useOneShot == true ) {
500
114
                        ret = ToReturnType<ReturnType>(in, tagSize);
501
114
                    } else {
502
58
                        ret = ToReturnType<ReturnType>(::Botan::secure_vector<uint8_t>(out.data(), out.data() + out.size()), tagSize);
503
58
                    }
504
172
                }
505
172
            } catch ( ... ) { }
506
282
end:
507
508
282
            return ret;
509
282
        }
510
511
} /* namespace Botan_detail */
512
513
333
std::optional<component::MAC> Botan::OpCMAC(operation::CMAC& op) {
514
333
    if ( !repository::IsCBC(op.cipher.cipherType.Get()) ) {
515
59
        return std::nullopt;
516
59
    }
517
274
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
518
274
    std::optional<component::MAC> ret = std::nullopt;
519
274
    std::unique_ptr<::Botan::MessageAuthenticationCode> cmac = nullptr;
520
274
    util::Multipart parts;
521
522
274
    try {
523
        /* Initialize */
524
274
        {
525
274
            BOTAN_SET_GLOBAL_DS
526
527
274
            std::optional<std::string> algoString;
528
274
            CF_CHECK_NE(algoString = Botan_detail::CipherIDToString(op.cipher.cipherType.Get(), false), std::nullopt);
529
530
266
            const std::string cmacString = Botan_detail::parenthesize("CMAC", *algoString);
531
532
266
            CF_CHECK_NE(cmac = ::Botan::MessageAuthenticationCode::create(cmacString), nullptr);
533
534
266
            try {
535
266
                cmac->set_key(op.cipher.key.GetPtr(), op.cipher.key.GetSize());
536
266
            } catch ( ... ) {
537
21
                goto end;
538
21
            }
539
540
245
            parts = util::ToParts(ds, op.cleartext);
541
245
        }
542
543
        /* Process */
544
16.5k
        for (const auto& part : parts) {
545
16.5k
            cmac->update(part.first, part.second);
546
16.5k
        }
547
548
        /* Finalize */
549
245
        {
550
245
            const auto res = cmac->final();
551
245
            ret = component::MAC(res.data(), res.size());
552
245
        }
553
554
245
    } catch ( ... ) { }
555
556
274
end:
557
274
    BOTAN_UNSET_GLOBAL_DS
558
559
274
    return ret;
560
274
}
561
562
613
std::optional<component::Ciphertext> Botan::OpSymmetricEncrypt(operation::SymmetricEncrypt& op) {
563
613
    if ( op.cipher.cipherType.Is(CF_CIPHER("CHACHA20_POLY1305")) && op.cipher.iv.GetSize() == 24 ) {
564
        /* Botan interpretes CHACHA20_POLY1305 + 192 bits IV as XCHACHA20_POLY1305 */
565
1
        return std::nullopt;
566
1
    }
567
568
612
    std::optional<component::Ciphertext> ret = std::nullopt;
569
570
612
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
571
612
    BOTAN_SET_GLOBAL_DS
572
573
612
    if ( cryptofuzz::repository::IsAEAD(op.cipher.cipherType.Get()) ) {
574
176
        ret = Botan_detail::Crypt<component::Ciphertext, operation::SymmetricEncrypt, ::Botan::AEAD_Mode>(op, ds);
575
436
    } else {
576
436
        ret = Botan_detail::Crypt<component::Ciphertext, operation::SymmetricEncrypt, ::Botan::Cipher_Mode>(op, ds);
577
436
    }
578
579
612
    BOTAN_UNSET_GLOBAL_DS
580
581
612
    return ret;
582
613
}
583
584
593
std::optional<component::Cleartext> Botan::OpSymmetricDecrypt(operation::SymmetricDecrypt& op) {
585
593
    if ( op.cipher.cipherType.Is(CF_CIPHER("CHACHA20_POLY1305")) && op.cipher.iv.GetSize() == 24 ) {
586
9
        return std::nullopt;
587
9
    }
588
589
584
    std::optional<component::Cleartext> ret = std::nullopt;
590
591
584
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
592
584
    BOTAN_SET_GLOBAL_DS
593
594
584
    if ( cryptofuzz::repository::IsAEAD(op.cipher.cipherType.Get()) ) {
595
208
        ret = Botan_detail::Crypt<component::Cleartext, operation::SymmetricDecrypt, ::Botan::AEAD_Mode>(op, ds);
596
376
    } else {
597
376
        ret = Botan_detail::Crypt<component::Cleartext, operation::SymmetricDecrypt, ::Botan::Cipher_Mode>(op, ds);
598
376
    }
599
600
584
    BOTAN_UNSET_GLOBAL_DS
601
602
584
    return ret;
603
593
}
604
605
56
std::optional<component::Key> Botan::OpKDF_SCRYPT(operation::KDF_SCRYPT& op) {
606
56
    std::optional<component::Key> ret = std::nullopt;
607
56
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
608
56
    std::unique_ptr<::Botan::PasswordHashFamily> pwdhash_fam = nullptr;
609
56
    std::unique_ptr<::Botan::PasswordHash> pwdhash = nullptr;
610
56
    uint8_t* out = util::malloc(op.keySize);
611
612
56
    try {
613
        /* Initialize */
614
56
        {
615
56
            BOTAN_SET_GLOBAL_DS
616
617
56
            CF_CHECK_NE(pwdhash_fam = ::Botan::PasswordHashFamily::create("Scrypt"), nullptr);
618
56
            CF_CHECK_NE(pwdhash = pwdhash_fam->from_params(op.N, op.r, op.p), nullptr);
619
620
56
        }
621
622
        /* Process */
623
0
        {
624
56
            pwdhash->derive_key(
625
56
                    out,
626
56
                    op.keySize,
627
56
                    (const char*)op.password.GetPtr(),
628
56
                    op.password.GetSize(),
629
56
                    op.salt.GetPtr(),
630
56
                    op.salt.GetSize());
631
56
        }
632
633
        /* Finalize */
634
56
        {
635
56
            ret = component::Key(out, op.keySize);
636
56
        }
637
56
    } catch ( ... ) { }
638
639
56
end:
640
56
    util::free(out);
641
642
56
    BOTAN_UNSET_GLOBAL_DS
643
644
56
    return ret;
645
56
}
646
647
378
std::optional<component::Key> Botan::OpKDF_HKDF(operation::KDF_HKDF& op) {
648
378
    std::optional<component::Key> ret = std::nullopt;
649
378
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
650
378
    std::unique_ptr<::Botan::KDF> hkdf = nullptr;
651
652
378
    try {
653
378
        {
654
378
            BOTAN_SET_GLOBAL_DS
655
656
378
            std::optional<std::string> algoString;
657
378
            CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get(), true), std::nullopt);
658
659
324
            const std::string hkdfString = Botan_detail::parenthesize("HKDF", *algoString);
660
324
            hkdf = ::Botan::KDF::create(hkdfString);
661
324
        }
662
663
0
        {
664
324
            auto derived = hkdf->derive_key(op.keySize, op.password.Get(), op.salt.Get(), op.info.Get());
665
666
324
            ret = component::Key(derived.data(), derived.size());
667
324
        }
668
324
    } catch ( ... ) { }
669
670
378
end:
671
378
    BOTAN_UNSET_GLOBAL_DS
672
673
378
    return ret;
674
378
}
675
676
428
std::optional<component::Key> Botan::OpKDF_PBKDF2(operation::KDF_PBKDF2& op) {
677
428
    std::optional<component::Key> ret = std::nullopt;
678
428
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
679
428
    std::unique_ptr<::Botan::PasswordHashFamily> pwdhash_fam = nullptr;
680
428
    std::unique_ptr<::Botan::PasswordHash> pwdhash = nullptr;
681
428
    uint8_t* out = util::malloc(op.keySize);
682
683
428
    try {
684
        /* Initialize */
685
428
        {
686
428
            BOTAN_SET_GLOBAL_DS
687
688
428
            std::optional<std::string> algoString;
689
428
            CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get(), true), std::nullopt);
690
691
397
            const std::string pbkdf2String = Botan_detail::parenthesize("PBKDF2", *algoString);
692
397
            CF_CHECK_NE(pwdhash_fam = ::Botan::PasswordHashFamily::create(pbkdf2String), nullptr);
693
694
397
            CF_CHECK_NE(pwdhash = pwdhash_fam->from_params(op.iterations), nullptr);
695
696
397
        }
697
698
        /* Process */
699
0
        {
700
397
            pwdhash->derive_key(
701
397
                    out,
702
397
                    op.keySize,
703
397
                    (const char*)op.password.GetPtr(),
704
397
                    op.password.GetSize(),
705
397
                    op.salt.GetPtr(),
706
397
                    op.salt.GetSize());
707
397
        }
708
709
        /* Finalize */
710
397
        {
711
397
            ret = component::Key(out, op.keySize);
712
397
        }
713
397
    } catch ( ... ) { }
714
715
428
end:
716
428
    util::free(out);
717
718
428
    BOTAN_UNSET_GLOBAL_DS
719
720
428
    return ret;
721
428
}
722
723
165
std::optional<component::Key> Botan::OpKDF_ARGON2(operation::KDF_ARGON2& op) {
724
165
    std::optional<component::Key> ret = std::nullopt;
725
165
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
726
165
    std::unique_ptr<::Botan::PasswordHashFamily> pwdhash_fam = nullptr;
727
165
    std::unique_ptr<::Botan::PasswordHash> pwdhash = nullptr;
728
165
    uint8_t* out = util::malloc(op.keySize);
729
730
165
    try {
731
        /* Initialize */
732
165
        {
733
165
            BOTAN_SET_GLOBAL_DS
734
735
165
            std::string argon2String;
736
737
165
            switch ( op.type ) {
738
46
                case    0:
739
46
                    argon2String = "Argon2d";
740
46
                    break;
741
52
                case    1:
742
52
                    argon2String = "Argon2i";
743
52
                    break;
744
66
                case    2:
745
66
                    argon2String = "Argon2id";
746
66
                    break;
747
1
                default:
748
1
                    goto end;
749
165
            }
750
164
            CF_CHECK_NE(pwdhash_fam = ::Botan::PasswordHashFamily::create(argon2String), nullptr);
751
752
164
            CF_CHECK_NE(pwdhash = pwdhash_fam->from_params(
753
164
                        op.memory,
754
164
                        op.iterations,
755
164
                        op.threads), nullptr);
756
164
        }
757
758
        /* Process */
759
0
        {
760
164
            pwdhash->derive_key(
761
164
                    out,
762
164
                    op.keySize,
763
164
                    (const char*)op.password.GetPtr(),
764
164
                    op.password.GetSize(),
765
164
                    op.salt.GetPtr(),
766
164
                    op.salt.GetSize());
767
164
        }
768
769
        /* Finalize */
770
164
        {
771
164
            ret = component::Key(out, op.keySize);
772
164
        }
773
164
    } catch ( ... ) { }
774
775
165
end:
776
165
    util::free(out);
777
778
165
    BOTAN_UNSET_GLOBAL_DS
779
780
165
    return ret;
781
165
}
782
783
228
std::optional<component::Key> Botan::OpKDF_SP_800_108(operation::KDF_SP_800_108& op) {
784
228
    std::optional<component::Key> ret = std::nullopt;
785
228
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
786
228
    uint8_t* out = util::malloc(op.keySize);
787
228
    std::unique_ptr<::Botan::KDF> sp_800_108 = nullptr;
788
789
228
    try {
790
228
        BOTAN_SET_GLOBAL_DS
791
792
228
        std::optional<std::string> algoString;
793
228
        CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.mech.type.Get(), true), std::nullopt);
794
795
210
        const std::string hmacString = Botan_detail::parenthesize("HMAC", *algoString);
796
210
        std::string sp_800_108_string;
797
210
        switch ( op.mode ) {
798
65
            case    0:
799
65
                sp_800_108_string = Botan_detail::parenthesize("SP800-108-Counter", hmacString);
800
65
                break;
801
66
            case    1:
802
66
                sp_800_108_string = Botan_detail::parenthesize("SP800-108-Feedback", hmacString);
803
66
                break;
804
77
            case    2:
805
77
                sp_800_108_string = Botan_detail::parenthesize("SP800-108-Pipeline", hmacString);
806
77
                break;
807
2
            default:
808
2
                goto end;
809
210
        }
810
811
208
        sp_800_108 = ::Botan::KDF::create(sp_800_108_string);
812
813
208
        {
814
208
            auto derived = sp_800_108->derive_key(op.keySize, op.secret.Get(), op.salt.Get(), op.label.Get());
815
816
208
            ret = component::Key(derived.data(), derived.size());
817
208
        }
818
208
    } catch ( ... ) { }
819
820
228
end:
821
228
    util::free(out);
822
823
228
    BOTAN_UNSET_GLOBAL_DS
824
825
228
    return ret;
826
228
}
827
828
74
std::optional<component::Key> Botan::OpKDF_TLS1_PRF(operation::KDF_TLS1_PRF& op) {
829
74
    std::optional<component::Key> ret = std::nullopt;
830
74
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
831
74
    std::unique_ptr<::Botan::KDF> tlsprf = nullptr;
832
833
74
    try {
834
74
        BOTAN_SET_GLOBAL_DS
835
836
74
        {
837
74
            CF_CHECK_EQ(op.digestType.Get(), CF_DIGEST("MD5_SHA1"));
838
60
            CF_CHECK_NE(tlsprf = ::Botan::KDF::create("TLS-PRF()"), nullptr);
839
0
        }
840
841
0
        {
842
0
            const auto derived = tlsprf->derive_key(op.keySize, op.secret.Get(), op.seed.Get(), std::vector<uint8_t>{});
843
844
0
            ret = component::Key(derived.data(), derived.size());
845
0
        }
846
0
    } catch ( ... ) { }
847
848
74
end:
849
74
    BOTAN_UNSET_GLOBAL_DS
850
851
74
    return ret;
852
74
}
853
854
25
std::optional<component::Key> Botan::OpKDF_BCRYPT(operation::KDF_BCRYPT& op) {
855
25
    std::optional<component::Key> ret = std::nullopt;
856
25
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
857
25
    std::unique_ptr<::Botan::PasswordHashFamily> pwdhash_fam = nullptr;
858
25
    std::unique_ptr<::Botan::PasswordHash> pwdhash = nullptr;
859
25
    uint8_t* out = util::malloc(op.keySize);
860
861
25
    try {
862
25
        BOTAN_SET_GLOBAL_DS
863
864
        /* Initialize */
865
25
        {
866
25
            CF_CHECK_EQ(op.digestType.Get(), CF_DIGEST("SHA512"));
867
20
            CF_CHECK_NE(pwdhash_fam = ::Botan::PasswordHashFamily::create("Bcrypt-PBKDF"), nullptr);
868
20
            CF_CHECK_NE(pwdhash = pwdhash_fam->from_params(op.iterations), nullptr);
869
870
20
        }
871
872
        /* Process */
873
0
        {
874
20
            pwdhash->derive_key(
875
20
                    out,
876
20
                    op.keySize,
877
20
                    (const char*)op.secret.GetPtr(),
878
20
                    op.secret.GetSize(),
879
20
                    op.salt.GetPtr(),
880
20
                    op.salt.GetSize());
881
20
        }
882
883
        /* Finalize */
884
20
        {
885
20
            ret = component::Key(out, op.keySize);
886
20
        }
887
20
    } catch ( ... ) { }
888
889
25
end:
890
25
    util::free(out);
891
892
25
    BOTAN_UNSET_GLOBAL_DS
893
894
25
    return ret;
895
25
}
896
897
namespace Botan_detail {
898
5.73k
    std::optional<std::string> CurveIDToString(const uint64_t curveID) {
899
5.73k
#include "curve_string_lut.h"
900
5.73k
        std::optional<std::string> ret = std::nullopt;
901
902
5.73k
        CF_CHECK_NE(LUT.find(curveID), LUT.end());
903
5.49k
        ret = LUT.at(curveID);
904
5.73k
end:
905
5.73k
        return ret;
906
5.49k
    }
907
} /* namespace Botan_detail */
908
909
1.03k
std::optional<component::ECC_KeyPair> Botan::OpECC_GenerateKeyPair(operation::ECC_GenerateKeyPair& op) {
910
1.03k
    std::optional<component::ECC_KeyPair> ret = std::nullopt;
911
1.03k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
912
913
1.03k
    std::optional<std::string> curveString;
914
1.03k
    BOTAN_FUZZER_RNG;
915
916
1.03k
    CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
917
918
997
    try {
919
997
        ::Botan::EC_Group group(*curveString);
920
997
        auto priv = ::Botan::ECDSA_PrivateKey(rng, group);
921
922
997
        const auto public_point = ::Botan::EC_AffinePoint::deserialize(group, priv.raw_public_key_bits());
923
997
        const auto pub_x = ::Botan::BigInt::from_bytes(public_point->x_bytes());
924
997
        const auto pub_y = ::Botan::BigInt::from_bytes(public_point->y_bytes());
925
926
997
        {
927
997
            const auto pub = priv.public_key();
928
997
            CF_ASSERT(pub->check_key(rng, true) == true, "Generated pubkey fails validation");
929
997
        }
930
931
0
        ret = { priv.private_value().to_dec_string(), { pub_x.to_dec_string(), pub_y.to_dec_string() } };
932
933
      /* Catch exception thrown from Botan_detail::Fuzzer_RNG::randomize */
934
997
    } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
935
936
1.03k
end:
937
1.03k
    return ret;
938
997
}
939
940
398
std::optional<bool> Botan::OpECC_ValidatePubkey(operation::ECC_ValidatePubkey& op) {
941
398
    std::optional<bool> ret = std::nullopt;
942
398
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
943
944
398
    BOTAN_FUZZER_RNG;
945
398
    std::unique_ptr<::Botan::Public_Key> pub = nullptr;
946
947
398
    try {
948
398
        std::optional<std::string> curveString;
949
398
        CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
950
951
387
        ::Botan::EC_Group group(*curveString);
952
387
        const auto pub_x = ::Botan::BigInt::from_string(op.pub.first.ToString(ds));
953
387
        const auto pub_y = ::Botan::BigInt::from_string(op.pub.second.ToString(ds));
954
387
        std::optional<::Botan::EC_AffinePoint> public_point;
955
387
        CF_CHECK_NE(public_point = ::Botan::EC_AffinePoint::from_bigint_xy(group, pub_x, pub_y), std::nullopt);
956
266
        pub = std::make_unique<::Botan::ECDSA_PublicKey>(::Botan::ECDSA_PublicKey(group, *public_point));
957
958
266
        ret = pub->check_key(rng, true);
959
266
    } catch ( ... ) { }
960
961
398
end:
962
398
    return ret;
963
398
}
964
965
827
std::optional<component::ECC_PublicKey> Botan::OpECC_PrivateToPublic(operation::ECC_PrivateToPublic& op) {
966
827
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
967
827
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
968
969
827
    BOTAN_FUZZER_RNG;
970
971
827
    try {
972
827
        std::optional<std::string> curveString;
973
974
827
        if ( op.curveType.Get() == CF_ECC_CURVE("x25519") ) {
975
10
            uint8_t priv_bytes[32];
976
977
10
            const ::Botan::BigInt priv_bigint(op.priv.ToString(ds));
978
10
            CF_CHECK_GT(priv_bigint, 0);
979
980
9
            priv_bigint.binary_encode(priv_bytes, sizeof(priv_bytes));
981
9
            priv_bytes[0] &= 248;
982
9
            priv_bytes[31] &= 127;
983
9
            priv_bytes[31] |= 64;
984
9
            const ::Botan::secure_vector<uint8_t> priv_vec(priv_bytes, priv_bytes + sizeof(priv_bytes));
985
986
9
            auto priv = ::Botan::X25519_PrivateKey(priv_vec);
987
988
9
            ::Botan::BigInt pub;
989
9
            pub.binary_decode(priv.public_value());
990
991
9
            ret = { pub.to_dec_string(), "0" };
992
817
        } else {
993
817
            CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
994
745
            ::Botan::EC_Group group(*curveString);
995
996
745
            const ::Botan::BigInt priv_bn(op.priv.ToString(ds));
997
745
            CF_CHECK_GT(priv_bn, 0);
998
999
734
            auto priv = std::make_unique<::Botan::ECDSA_PrivateKey>(::Botan::ECDSA_PrivateKey(rng, group, priv_bn));
1000
1001
734
            const auto public_point = ::Botan::EC_AffinePoint::deserialize(group, priv->raw_public_key_bits());
1002
734
            const auto pub_x = ::Botan::BigInt::from_bytes(public_point->x_bytes());
1003
734
            const auto pub_y = ::Botan::BigInt::from_bytes(public_point->y_bytes());
1004
1005
734
            ret = { pub_x.to_dec_string(), pub_y.to_dec_string() };
1006
734
        }
1007
827
    } catch ( ... ) { }
1008
1009
827
end:
1010
827
    return ret;
1011
827
}
1012
1013
namespace Botan_detail {
1014
    template <class PrivkeyType, class Operation, bool RFC6979 = true>
1015
339
        std::optional<component::ECDSA_Signature> ECxDSA_Sign(Operation& op) {
1016
339
            std::optional<component::ECDSA_Signature> ret = std::nullopt;
1017
339
            Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1018
1019
339
            std::unique_ptr<PrivkeyType> priv = nullptr;
1020
339
            std::unique_ptr<::Botan::Public_Key> pub = nullptr;
1021
339
            std::unique_ptr<::Botan::PK_Signer> signer;
1022
1023
339
            BOTAN_FUZZER_RNG;
1024
1025
339
            BOTAN_SET_GLOBAL_DS
1026
1027
339
            if ( RFC6979 == true ) {
1028
236
                CF_CHECK_EQ(op.UseRFC6979Nonce(), true);
1029
120
            } else {
1030
103
                CF_CHECK_EQ(op.UseRandomNonce(), true);
1031
91
            }
1032
1033
211
            CF_CHECK_EQ(op.digestType.Get(), CF_DIGEST("SHA256"));
1034
1035
199
            try {
1036
                /* Initialize */
1037
199
                {
1038
1039
199
                    std::optional<std::string> curveString, algoString;
1040
1041
199
                    CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1042
197
                    ::Botan::EC_Group group(*curveString);
1043
1044
                    /* Private key */
1045
197
                    {
1046
197
                        const ::Botan::BigInt priv_bn(op.priv.ToString(ds));
1047
1048
                        /* Botan appears to generate a new key if the input key is 0,
1049
                         * so don't do this */
1050
197
                        CF_CHECK_NE(priv_bn, 0);
1051
1052
195
                        priv = std::make_unique<PrivkeyType>(PrivkeyType(rng, group, priv_bn));
1053
195
                    }
1054
1055
                    /* Prepare signer */
1056
195
                    CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get()), std::nullopt);
1057
1058
195
                    const std::string emsa1String = Botan_detail::parenthesize("EMSA1", *algoString);
1059
195
                    signer.reset(new ::Botan::PK_Signer(*priv, rng, emsa1String, ::Botan::Signature_Format::DerSequence));
1060
195
                }
1061
1062
                /* Process */
1063
0
                {
1064
195
                    const auto signature = signer->sign_message(op.cleartext.Get(), rng);
1065
1066
                    /* Retrieve R and S */
1067
195
                    {
1068
195
                        ::Botan::BER_Decoder decoder(signature);
1069
195
                        ::Botan::BER_Decoder ber_sig = decoder.start_sequence();
1070
1071
195
                        size_t count = 0;
1072
1073
195
                        ::Botan::BigInt R;
1074
195
                        ::Botan::BigInt S;
1075
425
                        while(ber_sig.more_items())
1076
230
                        {
1077
230
                            switch ( count ) {
1078
115
                                case    0:
1079
115
                                    ber_sig.decode(R);
1080
115
                                    break;
1081
115
                                case    1:
1082
115
                                    ber_sig.decode(S);
1083
115
                                    break;
1084
0
                                default:
1085
0
                                    printf("Error: Too many parts in signature BER\n");
1086
0
                                    abort();
1087
230
                            }
1088
1089
230
                            ++count;
1090
230
                        }
1091
1092
195
                        if ( op.curveType.Get() == CF_ECC_CURVE("secp256k1") ) {
1093
                            /* For compatibility with the secp256k1 library.
1094
                             * See: https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#low-s-values-in-signatures
1095
                             */
1096
6
                            if (S > ::Botan::BigInt::from_string("57896044618658097711785492504343953926418782139537452191302581570759080747168")) {
1097
3
                                S = ::Botan::BigInt::from_string("115792089237316195423570985008687907852837564279074904382605163141518161494337") - S;
1098
3
                            }
1099
189
                        } else if ( op.curveType.Get() == CF_ECC_CURVE("secp256r1") ) {
1100
                            /* Similar ECDSA signature malleability adjustment for compatibility with trezor-firmware */
1101
8
                            if (S > ::Botan::BigInt::from_string("57896044605178124381348723474703786764998477612067880171211129530534256022184")) {
1102
2
                                S = ::Botan::BigInt::from_string("115792089210356248762697446949407573529996955224135760342422259061068512044369") - S;
1103
2
                            }
1104
8
                        }
1105
1106
195
                        const auto public_point = ::Botan::EC_AffinePoint::deserialize(priv->domain(), priv->raw_public_key_bits());
1107
195
                        const auto pub_x = ::Botan::BigInt::from_bytes(public_point->x_bytes()).to_dec_string();
1108
195
                        const auto pub_y = ::Botan::BigInt::from_bytes(public_point->y_bytes()).to_dec_string();
1109
1110
195
                        const auto R_str = R.to_dec_string();
1111
195
                        const auto S_str = S.to_dec_string();
1112
1113
195
                        ret = component::ECDSA_Signature({ R_str, S_str }, { pub_x, pub_y });
1114
195
                    }
1115
195
                }
1116
195
            } catch ( ... ) { }
1117
1118
339
end:
1119
339
            BOTAN_UNSET_GLOBAL_DS
1120
1121
339
            return ret;
1122
199
        }
std::__1::optional<cryptofuzz::component::ECDSA_Signature> cryptofuzz::module::Botan_detail::ECxDSA_Sign<Botan::ECDSA_PrivateKey, cryptofuzz::operation::ECDSA_Sign, true>(cryptofuzz::operation::ECDSA_Sign&)
Line
Count
Source
1015
236
        std::optional<component::ECDSA_Signature> ECxDSA_Sign(Operation& op) {
1016
236
            std::optional<component::ECDSA_Signature> ret = std::nullopt;
1017
236
            Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1018
1019
236
            std::unique_ptr<PrivkeyType> priv = nullptr;
1020
236
            std::unique_ptr<::Botan::Public_Key> pub = nullptr;
1021
236
            std::unique_ptr<::Botan::PK_Signer> signer;
1022
1023
236
            BOTAN_FUZZER_RNG;
1024
1025
236
            BOTAN_SET_GLOBAL_DS
1026
1027
236
            if ( RFC6979 == true ) {
1028
236
                CF_CHECK_EQ(op.UseRFC6979Nonce(), true);
1029
120
            } else {
1030
0
                CF_CHECK_EQ(op.UseRandomNonce(), true);
1031
0
            }
1032
1033
120
            CF_CHECK_EQ(op.digestType.Get(), CF_DIGEST("SHA256"));
1034
1035
114
            try {
1036
                /* Initialize */
1037
114
                {
1038
1039
114
                    std::optional<std::string> curveString, algoString;
1040
1041
114
                    CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1042
113
                    ::Botan::EC_Group group(*curveString);
1043
1044
                    /* Private key */
1045
113
                    {
1046
113
                        const ::Botan::BigInt priv_bn(op.priv.ToString(ds));
1047
1048
                        /* Botan appears to generate a new key if the input key is 0,
1049
                         * so don't do this */
1050
113
                        CF_CHECK_NE(priv_bn, 0);
1051
1052
112
                        priv = std::make_unique<PrivkeyType>(PrivkeyType(rng, group, priv_bn));
1053
112
                    }
1054
1055
                    /* Prepare signer */
1056
112
                    CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get()), std::nullopt);
1057
1058
112
                    const std::string emsa1String = Botan_detail::parenthesize("EMSA1", *algoString);
1059
112
                    signer.reset(new ::Botan::PK_Signer(*priv, rng, emsa1String, ::Botan::Signature_Format::DerSequence));
1060
112
                }
1061
1062
                /* Process */
1063
0
                {
1064
112
                    const auto signature = signer->sign_message(op.cleartext.Get(), rng);
1065
1066
                    /* Retrieve R and S */
1067
112
                    {
1068
112
                        ::Botan::BER_Decoder decoder(signature);
1069
112
                        ::Botan::BER_Decoder ber_sig = decoder.start_sequence();
1070
1071
112
                        size_t count = 0;
1072
1073
112
                        ::Botan::BigInt R;
1074
112
                        ::Botan::BigInt S;
1075
278
                        while(ber_sig.more_items())
1076
166
                        {
1077
166
                            switch ( count ) {
1078
83
                                case    0:
1079
83
                                    ber_sig.decode(R);
1080
83
                                    break;
1081
83
                                case    1:
1082
83
                                    ber_sig.decode(S);
1083
83
                                    break;
1084
0
                                default:
1085
0
                                    printf("Error: Too many parts in signature BER\n");
1086
0
                                    abort();
1087
166
                            }
1088
1089
166
                            ++count;
1090
166
                        }
1091
1092
112
                        if ( op.curveType.Get() == CF_ECC_CURVE("secp256k1") ) {
1093
                            /* For compatibility with the secp256k1 library.
1094
                             * See: https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#low-s-values-in-signatures
1095
                             */
1096
3
                            if (S > ::Botan::BigInt::from_string("57896044618658097711785492504343953926418782139537452191302581570759080747168")) {
1097
1
                                S = ::Botan::BigInt::from_string("115792089237316195423570985008687907852837564279074904382605163141518161494337") - S;
1098
1
                            }
1099
109
                        } else if ( op.curveType.Get() == CF_ECC_CURVE("secp256r1") ) {
1100
                            /* Similar ECDSA signature malleability adjustment for compatibility with trezor-firmware */
1101
4
                            if (S > ::Botan::BigInt::from_string("57896044605178124381348723474703786764998477612067880171211129530534256022184")) {
1102
1
                                S = ::Botan::BigInt::from_string("115792089210356248762697446949407573529996955224135760342422259061068512044369") - S;
1103
1
                            }
1104
4
                        }
1105
1106
112
                        const auto public_point = ::Botan::EC_AffinePoint::deserialize(priv->domain(), priv->raw_public_key_bits());
1107
112
                        const auto pub_x = ::Botan::BigInt::from_bytes(public_point->x_bytes()).to_dec_string();
1108
112
                        const auto pub_y = ::Botan::BigInt::from_bytes(public_point->y_bytes()).to_dec_string();
1109
1110
112
                        const auto R_str = R.to_dec_string();
1111
112
                        const auto S_str = S.to_dec_string();
1112
1113
112
                        ret = component::ECDSA_Signature({ R_str, S_str }, { pub_x, pub_y });
1114
112
                    }
1115
112
                }
1116
112
            } catch ( ... ) { }
1117
1118
236
end:
1119
236
            BOTAN_UNSET_GLOBAL_DS
1120
1121
236
            return ret;
1122
114
        }
std::__1::optional<cryptofuzz::component::ECDSA_Signature> cryptofuzz::module::Botan_detail::ECxDSA_Sign<Botan::ECGDSA_PrivateKey, cryptofuzz::operation::ECGDSA_Sign, false>(cryptofuzz::operation::ECGDSA_Sign&)
Line
Count
Source
1015
103
        std::optional<component::ECDSA_Signature> ECxDSA_Sign(Operation& op) {
1016
103
            std::optional<component::ECDSA_Signature> ret = std::nullopt;
1017
103
            Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1018
1019
103
            std::unique_ptr<PrivkeyType> priv = nullptr;
1020
103
            std::unique_ptr<::Botan::Public_Key> pub = nullptr;
1021
103
            std::unique_ptr<::Botan::PK_Signer> signer;
1022
1023
103
            BOTAN_FUZZER_RNG;
1024
1025
103
            BOTAN_SET_GLOBAL_DS
1026
1027
103
            if ( RFC6979 == true ) {
1028
0
                CF_CHECK_EQ(op.UseRFC6979Nonce(), true);
1029
103
            } else {
1030
103
                CF_CHECK_EQ(op.UseRandomNonce(), true);
1031
91
            }
1032
1033
91
            CF_CHECK_EQ(op.digestType.Get(), CF_DIGEST("SHA256"));
1034
1035
85
            try {
1036
                /* Initialize */
1037
85
                {
1038
1039
85
                    std::optional<std::string> curveString, algoString;
1040
1041
85
                    CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1042
84
                    ::Botan::EC_Group group(*curveString);
1043
1044
                    /* Private key */
1045
84
                    {
1046
84
                        const ::Botan::BigInt priv_bn(op.priv.ToString(ds));
1047
1048
                        /* Botan appears to generate a new key if the input key is 0,
1049
                         * so don't do this */
1050
84
                        CF_CHECK_NE(priv_bn, 0);
1051
1052
83
                        priv = std::make_unique<PrivkeyType>(PrivkeyType(rng, group, priv_bn));
1053
83
                    }
1054
1055
                    /* Prepare signer */
1056
83
                    CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get()), std::nullopt);
1057
1058
83
                    const std::string emsa1String = Botan_detail::parenthesize("EMSA1", *algoString);
1059
83
                    signer.reset(new ::Botan::PK_Signer(*priv, rng, emsa1String, ::Botan::Signature_Format::DerSequence));
1060
83
                }
1061
1062
                /* Process */
1063
0
                {
1064
83
                    const auto signature = signer->sign_message(op.cleartext.Get(), rng);
1065
1066
                    /* Retrieve R and S */
1067
83
                    {
1068
83
                        ::Botan::BER_Decoder decoder(signature);
1069
83
                        ::Botan::BER_Decoder ber_sig = decoder.start_sequence();
1070
1071
83
                        size_t count = 0;
1072
1073
83
                        ::Botan::BigInt R;
1074
83
                        ::Botan::BigInt S;
1075
147
                        while(ber_sig.more_items())
1076
64
                        {
1077
64
                            switch ( count ) {
1078
32
                                case    0:
1079
32
                                    ber_sig.decode(R);
1080
32
                                    break;
1081
32
                                case    1:
1082
32
                                    ber_sig.decode(S);
1083
32
                                    break;
1084
0
                                default:
1085
0
                                    printf("Error: Too many parts in signature BER\n");
1086
0
                                    abort();
1087
64
                            }
1088
1089
64
                            ++count;
1090
64
                        }
1091
1092
83
                        if ( op.curveType.Get() == CF_ECC_CURVE("secp256k1") ) {
1093
                            /* For compatibility with the secp256k1 library.
1094
                             * See: https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#low-s-values-in-signatures
1095
                             */
1096
3
                            if (S > ::Botan::BigInt::from_string("57896044618658097711785492504343953926418782139537452191302581570759080747168")) {
1097
2
                                S = ::Botan::BigInt::from_string("115792089237316195423570985008687907852837564279074904382605163141518161494337") - S;
1098
2
                            }
1099
80
                        } else if ( op.curveType.Get() == CF_ECC_CURVE("secp256r1") ) {
1100
                            /* Similar ECDSA signature malleability adjustment for compatibility with trezor-firmware */
1101
4
                            if (S > ::Botan::BigInt::from_string("57896044605178124381348723474703786764998477612067880171211129530534256022184")) {
1102
1
                                S = ::Botan::BigInt::from_string("115792089210356248762697446949407573529996955224135760342422259061068512044369") - S;
1103
1
                            }
1104
4
                        }
1105
1106
83
                        const auto public_point = ::Botan::EC_AffinePoint::deserialize(priv->domain(), priv->raw_public_key_bits());
1107
83
                        const auto pub_x = ::Botan::BigInt::from_bytes(public_point->x_bytes()).to_dec_string();
1108
83
                        const auto pub_y = ::Botan::BigInt::from_bytes(public_point->y_bytes()).to_dec_string();
1109
1110
83
                        const auto R_str = R.to_dec_string();
1111
83
                        const auto S_str = S.to_dec_string();
1112
1113
83
                        ret = component::ECDSA_Signature({ R_str, S_str }, { pub_x, pub_y });
1114
83
                    }
1115
83
                }
1116
83
            } catch ( ... ) { }
1117
1118
103
end:
1119
103
            BOTAN_UNSET_GLOBAL_DS
1120
1121
103
            return ret;
1122
85
        }
1123
} /* namespace Botan_detail */
1124
1125
277
std::optional<component::ECDSA_Signature> Botan::OpECDSA_Sign(operation::ECDSA_Sign& op) {
1126
277
    if ( op.curveType.Is(CF_ECC_CURVE("ed25519")) ) {
1127
41
        const auto _priv_bytes = util::DecToBin(op.priv.ToTrimmedString(), 32);
1128
41
        if ( _priv_bytes == std::nullopt ) {
1129
2
            return std::nullopt;
1130
2
        }
1131
1132
39
        const ::Botan::secure_vector<uint8_t> priv_bytes(_priv_bytes->data(), _priv_bytes->data() + _priv_bytes->size());
1133
1134
39
        const auto priv = std::make_unique<::Botan::Ed25519_PrivateKey>(priv_bytes);
1135
1136
39
        std::unique_ptr<::Botan::PK_Signer> signer;
1137
1138
39
        Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1139
39
        BOTAN_FUZZER_RNG;
1140
1141
39
        signer.reset(new ::Botan::PK_Signer(*priv, rng, "Pure", ::Botan::Signature_Format::Standard));
1142
1143
39
        const auto signature = signer->sign_message(op.cleartext.Get(), rng);
1144
39
        CF_ASSERT(signature.size() == 64, "ed25519 signature is not 64 bytes");
1145
1146
39
        const auto pub = priv->get_public_key();
1147
39
        CF_ASSERT(pub.size() == 32, "ed25519 pubkey is not 32 bytes");
1148
1149
39
        const auto ret = component::ECDSA_Signature(
1150
39
                { util::BinToDec(signature.data(), 32), util::BinToDec(signature.data() + 32, 32) },
1151
39
                { util::BinToDec(pub.data(), 32), "0"}
1152
39
        );
1153
1154
39
        return ret;
1155
39
    }
1156
1157
236
    return Botan_detail::ECxDSA_Sign<::Botan::ECDSA_PrivateKey, operation::ECDSA_Sign>(op);
1158
277
}
1159
1160
103
std::optional<component::ECGDSA_Signature> Botan::OpECGDSA_Sign(operation::ECGDSA_Sign& op) {
1161
103
    return Botan_detail::ECxDSA_Sign<::Botan::ECGDSA_PrivateKey, operation::ECGDSA_Sign, false>(op);
1162
103
}
1163
1164
namespace Botan_detail {
1165
    template <class PubkeyType, class Operation>
1166
724
        std::optional<bool> ECxDSA_Verify(Operation& op) {
1167
724
            try {
1168
724
                std::optional<bool> ret = std::nullopt;
1169
724
                Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1170
1171
724
                ::Botan::secure_vector<uint8_t> sig;
1172
724
                std::unique_ptr<::Botan::Public_Key> pub = nullptr;
1173
724
                std::unique_ptr<::Botan::EC_Group> group = nullptr;
1174
724
                Buffer CT;
1175
1176
724
                {
1177
724
                    BOTAN_SET_GLOBAL_DS;
1178
1179
724
                    std::optional<std::string> curveString;
1180
724
                    CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1181
697
                    group = std::make_unique<::Botan::EC_Group>(*curveString);
1182
697
                }
1183
1184
                /* Construct signature */
1185
0
                {
1186
697
                    const ::Botan::BigInt R(op.signature.signature.first.ToString(ds));
1187
697
                    const ::Botan::BigInt S(op.signature.signature.second.ToString(ds));
1188
697
                    sig = ::Botan::BigInt::encode_fixed_length_int_pair(R, S, group->get_order_bytes());
1189
697
                }
1190
1191
                /* Construct pubkey */
1192
697
                {
1193
697
                    const auto pub_x = ::Botan::BigInt::from_string(op.signature.pub.first.ToString(ds));
1194
697
                    const auto pub_y = ::Botan::BigInt::from_string(op.signature.pub.second.ToString(ds));
1195
697
                    std::optional<::Botan::EC_AffinePoint> public_point;
1196
697
                    CF_CHECK_NE(public_point = ::Botan::EC_AffinePoint::from_bigint_xy(*group, pub_x, pub_y), std::nullopt);
1197
657
                    pub = std::make_unique<PubkeyType>(PubkeyType(*group, *public_point));
1198
657
                }
1199
1200
                /* Construct input */
1201
0
                {
1202
657
                    if ( op.digestType.Get() == CF_DIGEST("NULL") ) {
1203
43
                        CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType);
1204
614
                    } else {
1205
614
                        std::optional<std::string> algoString;
1206
614
                        CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get()), std::nullopt);
1207
1208
591
                        auto hash = ::Botan::HashFunction::create(*algoString);
1209
591
                        hash->update(op.cleartext.GetPtr(), op.cleartext.GetSize());
1210
591
                        const auto _CT = hash->final();
1211
591
                        CT = Buffer(_CT.data(), _CT.size()).ECDSA_RandomPad(ds, op.curveType);
1212
591
                    }
1213
657
                }
1214
1215
634
                ret = ::Botan::PK_Verifier(*pub, "Raw").verify_message(CT.Get(), sig);
1216
1217
714
end:
1218
714
                BOTAN_UNSET_GLOBAL_DS;
1219
1220
714
                return ret;
1221
634
            } catch (::Botan::Internal_Error& e) {
1222
0
                throw e;
1223
10
            } catch (::Botan::Exception& e) {
1224
10
                BOTAN_UNSET_GLOBAL_DS;
1225
10
                return false;
1226
10
            }
1227
724
        }
std::__1::optional<bool> cryptofuzz::module::Botan_detail::ECxDSA_Verify<Botan::ECDSA_PublicKey, cryptofuzz::operation::ECDSA_Verify>(cryptofuzz::operation::ECDSA_Verify&)
Line
Count
Source
1166
375
        std::optional<bool> ECxDSA_Verify(Operation& op) {
1167
375
            try {
1168
375
                std::optional<bool> ret = std::nullopt;
1169
375
                Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1170
1171
375
                ::Botan::secure_vector<uint8_t> sig;
1172
375
                std::unique_ptr<::Botan::Public_Key> pub = nullptr;
1173
375
                std::unique_ptr<::Botan::EC_Group> group = nullptr;
1174
375
                Buffer CT;
1175
1176
375
                {
1177
375
                    BOTAN_SET_GLOBAL_DS;
1178
1179
375
                    std::optional<std::string> curveString;
1180
375
                    CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1181
363
                    group = std::make_unique<::Botan::EC_Group>(*curveString);
1182
363
                }
1183
1184
                /* Construct signature */
1185
0
                {
1186
363
                    const ::Botan::BigInt R(op.signature.signature.first.ToString(ds));
1187
363
                    const ::Botan::BigInt S(op.signature.signature.second.ToString(ds));
1188
363
                    sig = ::Botan::BigInt::encode_fixed_length_int_pair(R, S, group->get_order_bytes());
1189
363
                }
1190
1191
                /* Construct pubkey */
1192
363
                {
1193
363
                    const auto pub_x = ::Botan::BigInt::from_string(op.signature.pub.first.ToString(ds));
1194
363
                    const auto pub_y = ::Botan::BigInt::from_string(op.signature.pub.second.ToString(ds));
1195
363
                    std::optional<::Botan::EC_AffinePoint> public_point;
1196
363
                    CF_CHECK_NE(public_point = ::Botan::EC_AffinePoint::from_bigint_xy(*group, pub_x, pub_y), std::nullopt);
1197
336
                    pub = std::make_unique<PubkeyType>(PubkeyType(*group, *public_point));
1198
336
                }
1199
1200
                /* Construct input */
1201
0
                {
1202
336
                    if ( op.digestType.Get() == CF_DIGEST("NULL") ) {
1203
40
                        CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType);
1204
296
                    } else {
1205
296
                        std::optional<std::string> algoString;
1206
296
                        CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get()), std::nullopt);
1207
1208
292
                        auto hash = ::Botan::HashFunction::create(*algoString);
1209
292
                        hash->update(op.cleartext.GetPtr(), op.cleartext.GetSize());
1210
292
                        const auto _CT = hash->final();
1211
292
                        CT = Buffer(_CT.data(), _CT.size()).ECDSA_RandomPad(ds, op.curveType);
1212
292
                    }
1213
336
                }
1214
1215
332
                ret = ::Botan::PK_Verifier(*pub, "Raw").verify_message(CT.Get(), sig);
1216
1217
367
end:
1218
367
                BOTAN_UNSET_GLOBAL_DS;
1219
1220
367
                return ret;
1221
332
            } catch (::Botan::Internal_Error& e) {
1222
0
                throw e;
1223
8
            } catch (::Botan::Exception& e) {
1224
8
                BOTAN_UNSET_GLOBAL_DS;
1225
8
                return false;
1226
8
            }
1227
375
        }
std::__1::optional<bool> cryptofuzz::module::Botan_detail::ECxDSA_Verify<Botan::ECGDSA_PublicKey, cryptofuzz::operation::ECGDSA_Verify>(cryptofuzz::operation::ECGDSA_Verify&)
Line
Count
Source
1166
349
        std::optional<bool> ECxDSA_Verify(Operation& op) {
1167
349
            try {
1168
349
                std::optional<bool> ret = std::nullopt;
1169
349
                Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1170
1171
349
                ::Botan::secure_vector<uint8_t> sig;
1172
349
                std::unique_ptr<::Botan::Public_Key> pub = nullptr;
1173
349
                std::unique_ptr<::Botan::EC_Group> group = nullptr;
1174
349
                Buffer CT;
1175
1176
349
                {
1177
349
                    BOTAN_SET_GLOBAL_DS;
1178
1179
349
                    std::optional<std::string> curveString;
1180
349
                    CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1181
334
                    group = std::make_unique<::Botan::EC_Group>(*curveString);
1182
334
                }
1183
1184
                /* Construct signature */
1185
0
                {
1186
334
                    const ::Botan::BigInt R(op.signature.signature.first.ToString(ds));
1187
334
                    const ::Botan::BigInt S(op.signature.signature.second.ToString(ds));
1188
334
                    sig = ::Botan::BigInt::encode_fixed_length_int_pair(R, S, group->get_order_bytes());
1189
334
                }
1190
1191
                /* Construct pubkey */
1192
334
                {
1193
334
                    const auto pub_x = ::Botan::BigInt::from_string(op.signature.pub.first.ToString(ds));
1194
334
                    const auto pub_y = ::Botan::BigInt::from_string(op.signature.pub.second.ToString(ds));
1195
334
                    std::optional<::Botan::EC_AffinePoint> public_point;
1196
334
                    CF_CHECK_NE(public_point = ::Botan::EC_AffinePoint::from_bigint_xy(*group, pub_x, pub_y), std::nullopt);
1197
321
                    pub = std::make_unique<PubkeyType>(PubkeyType(*group, *public_point));
1198
321
                }
1199
1200
                /* Construct input */
1201
0
                {
1202
321
                    if ( op.digestType.Get() == CF_DIGEST("NULL") ) {
1203
3
                        CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType);
1204
318
                    } else {
1205
318
                        std::optional<std::string> algoString;
1206
318
                        CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get()), std::nullopt);
1207
1208
299
                        auto hash = ::Botan::HashFunction::create(*algoString);
1209
299
                        hash->update(op.cleartext.GetPtr(), op.cleartext.GetSize());
1210
299
                        const auto _CT = hash->final();
1211
299
                        CT = Buffer(_CT.data(), _CT.size()).ECDSA_RandomPad(ds, op.curveType);
1212
299
                    }
1213
321
                }
1214
1215
302
                ret = ::Botan::PK_Verifier(*pub, "Raw").verify_message(CT.Get(), sig);
1216
1217
347
end:
1218
347
                BOTAN_UNSET_GLOBAL_DS;
1219
1220
347
                return ret;
1221
302
            } catch (::Botan::Internal_Error& e) {
1222
0
                throw e;
1223
2
            } catch (::Botan::Exception& e) {
1224
2
                BOTAN_UNSET_GLOBAL_DS;
1225
2
                return false;
1226
2
            }
1227
349
        }
1228
} /* namespace Botan_detail */
1229
1230
449
std::optional<bool> Botan::OpECDSA_Verify(operation::ECDSA_Verify& op) {
1231
449
    if ( op.curveType.Is(CF_ECC_CURVE("ed25519")) ) {
1232
74
        const auto pub_bytes = util::DecToBin(op.signature.pub.first.ToTrimmedString(), 32);
1233
74
        if ( pub_bytes == std::nullopt ) {
1234
1
            return std::nullopt;
1235
1
        }
1236
73
        const auto pub = std::make_unique<::Botan::Ed25519_PublicKey>(*pub_bytes);
1237
1238
73
        const auto sig_r = util::DecToBin(op.signature.signature.first.ToTrimmedString(), 32);
1239
73
        if ( sig_r == std::nullopt ) {
1240
1
            return std::nullopt;
1241
1
        }
1242
1243
72
        const auto sig_s = util::DecToBin(op.signature.signature.second.ToTrimmedString(), 32);
1244
72
        if ( sig_s == std::nullopt ) {
1245
1
            return std::nullopt;
1246
1
        }
1247
1248
71
        std::vector<uint8_t> sig_bytes(64);
1249
71
        memcpy(sig_bytes.data(), sig_r->data(), 32);
1250
71
        memcpy(sig_bytes.data() + 32, sig_s->data(), 32);
1251
1252
71
        const bool ret = ::Botan::PK_Verifier(*pub, "Pure").verify_message(op.cleartext.Get(), sig_bytes);
1253
71
        return ret;
1254
1255
375
    } else {
1256
375
        return Botan_detail::ECxDSA_Verify<::Botan::ECDSA_PublicKey, operation::ECDSA_Verify>(op);
1257
375
    }
1258
449
}
1259
1260
349
std::optional<bool> Botan::OpECGDSA_Verify(operation::ECGDSA_Verify& op) {
1261
349
    return Botan_detail::ECxDSA_Verify<::Botan::ECGDSA_PublicKey, operation::ECGDSA_Verify>(op);
1262
349
}
1263
1264
1.47k
std::optional<component::ECC_PublicKey> Botan::OpECDSA_Recover(operation::ECDSA_Recover& op) {
1265
1.47k
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
1266
1.47k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1267
1268
1.47k
    std::unique_ptr<::Botan::EC_Group> group = nullptr;
1269
1.47k
    Buffer CT;
1270
1271
1.47k
    {
1272
1.47k
        std::optional<std::string> curveString;
1273
1.47k
        CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1274
1.45k
        group = std::make_unique<::Botan::EC_Group>(*curveString);
1275
1.45k
    }
1276
1277
    /* Construct input */
1278
0
    {
1279
1.45k
        if ( op.digestType.Get() == CF_DIGEST("NULL") ) {
1280
141
            CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType);
1281
1.31k
        } else {
1282
1.31k
            std::optional<std::string> algoString;
1283
1.31k
            CF_CHECK_NE(algoString = Botan_detail::DigestIDToString(op.digestType.Get()), std::nullopt);
1284
1285
1.31k
            auto hash = ::Botan::HashFunction::create(*algoString);
1286
1.31k
            hash->update(op.cleartext.GetPtr(), op.cleartext.GetSize());
1287
1.31k
            const auto _CT = hash->final();
1288
1.31k
            CT = Buffer(_CT.data(), _CT.size()).ECDSA_RandomPad(ds, op.curveType);
1289
1.31k
        }
1290
1.45k
    }
1291
1292
1.45k
    {
1293
1.45k
        const ::Botan::BigInt R(op.signature.first.ToString(ds));
1294
1.45k
        const ::Botan::BigInt S(op.signature.second.ToString(ds));
1295
1296
1.45k
        std::unique_ptr<::Botan::ECDSA_PublicKey> pub = nullptr;
1297
1.45k
        try {
1298
1.45k
            pub = std::make_unique<::Botan::ECDSA_PublicKey>(*group, CT.Get(), R, S, op.id);
1299
1.45k
            const auto public_point = ::Botan::EC_AffinePoint::deserialize(*group, pub->raw_public_key_bits());
1300
1301
1.45k
            ret = {
1302
1.45k
                ::Botan::BigInt::from_bytes(public_point->x_bytes()).to_dec_string(),
1303
1.45k
                ::Botan::BigInt::from_bytes(public_point->y_bytes()).to_dec_string()
1304
1.45k
            };
1305
1.45k
        } catch ( ::Botan::Invalid_State& e ) {
1306
49
        } catch ( ::Botan::Decoding_Error& ) {
1307
49
        } catch ( ::Botan::Invalid_Argument& ) {
1308
            //ret = {"0", "0"};
1309
12
        }
1310
1311
1.45k
    }
1312
1313
1.47k
end:
1314
1.47k
    return ret;
1315
1.45k
}
1316
1317
765
std::optional<component::Bignum> Botan::OpDH_Derive(operation::DH_Derive& op) {
1318
765
    std::optional<component::Bignum> ret = std::nullopt;
1319
765
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1320
1321
765
    BOTAN_FUZZER_RNG;
1322
1323
765
    try {
1324
765
        CF_CHECK_NE(op.priv.ToTrimmedString(), "0");
1325
1326
714
        const ::Botan::BigInt g(op.base.ToString(ds));
1327
714
        const ::Botan::BigInt p(op.prime.ToString(ds));
1328
714
        const ::Botan::DL_Group grp(p, g);
1329
1330
714
        const ::Botan::BigInt _priv(op.priv.ToString(ds));
1331
1332
        /* Prevent time-out */
1333
714
        CF_CHECK_LT(g.bytes(), 80);
1334
706
        CF_CHECK_LT(p.bytes(), 80);
1335
623
        CF_CHECK_LT(_priv.bytes(), 80);
1336
1337
614
        std::unique_ptr<::Botan::Private_Key> priv(new ::Botan::DH_PrivateKey(grp, _priv));
1338
1339
614
        const ::Botan::BigInt _pub(op.pub.ToString(ds));
1340
614
        ::Botan::DH_PublicKey pub(grp, _pub);
1341
1342
614
        std::unique_ptr<::Botan::PK_Key_Agreement> kas(new ::Botan::PK_Key_Agreement(*priv, rng, "Raw"));
1343
614
        const auto derived_key = kas->derive_key(0, pub.public_value());
1344
1345
614
        const auto derived_str = ::Botan::BigInt::from_bytes(derived_key.bits_of()).to_dec_string();
1346
614
        if ( derived_str != "0" ) {
1347
29
            ret = derived_str;
1348
29
        }
1349
614
    } catch ( ... ) { }
1350
1351
765
end:
1352
765
    return ret;
1353
765
}
1354
1355
51
std::optional<component::ECC_Point> Botan::OpECC_Point_Add(operation::ECC_Point_Add& op) {
1356
51
    std::optional<component::ECC_Point> ret = std::nullopt;
1357
51
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1358
1359
51
    BOTAN_FUZZER_RNG;
1360
1361
51
    std::unique_ptr<::Botan::EC_Group> group = nullptr;
1362
51
    std::unique_ptr<::Botan::EC_AffinePoint> a, b;
1363
1364
51
    try {
1365
51
        {
1366
51
            std::optional<std::string> curveString;
1367
51
            CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1368
37
            group = std::make_unique<::Botan::EC_Group>(*curveString);
1369
37
        }
1370
1371
0
        {
1372
            /* A */
1373
37
            {
1374
37
                const auto a_x = ::Botan::BigInt::from_string(op.a.first.ToString(ds));
1375
37
                CF_CHECK_GTE(a_x, 0);
1376
1377
37
                const auto a_y = ::Botan::BigInt::from_string(op.a.second.ToString(ds));
1378
37
                CF_CHECK_GTE(a_y, 0);
1379
1380
37
                try {
1381
37
                    std::optional<::Botan::EC_AffinePoint> a_point;
1382
37
                    CF_CHECK_NE(a_point = ::Botan::EC_AffinePoint::from_bigint_xy(*group, a_x, a_y), std::nullopt);
1383
22
                    a = std::make_unique<::Botan::EC_AffinePoint>(*a_point);
1384
22
                } catch ( ::Botan::Invalid_Argument ) {
1385
0
                    goto end;
1386
0
                }
1387
37
            }
1388
1389
            /* B */
1390
22
            {
1391
22
                const auto b_x = ::Botan::BigInt::from_string(op.b.first.ToString(ds));
1392
22
                CF_CHECK_GTE(b_x, 0);
1393
1394
22
                const auto b_y = ::Botan::BigInt::from_string(op.b.second.ToString(ds));
1395
22
                CF_CHECK_GTE(b_y, 0);
1396
1397
22
                try {
1398
22
                    std::optional<::Botan::EC_AffinePoint> b_point;
1399
22
                    CF_CHECK_NE(b_point = ::Botan::EC_AffinePoint::from_bigint_xy(*group, b_x, b_y), std::nullopt);
1400
15
                    b = std::make_unique<::Botan::EC_AffinePoint>(*b_point);
1401
15
                } catch ( ::Botan::Invalid_Argument ) {
1402
0
                    goto end;
1403
0
                }
1404
22
            }
1405
1406
15
            const bool is_negation = *a == b->negate();
1407
1408
15
            ::Botan::EC_AffinePoint _res = a->add(*b);
1409
1410
15
            const bool is_zero = _res.is_identity();
1411
1412
            /* If A is a negation of B, then addition of both should result in point at infinity */
1413
            /* Otherwise, it should result in non-infinity. */
1414
15
            CF_ASSERT(is_zero == is_negation, "Unexpected point addition result");
1415
15
            CF_CHECK_FALSE(is_zero);
1416
1417
13
            const auto x = ::Botan::BigInt::from_bytes(_res.x_bytes());
1418
13
            const auto y = ::Botan::BigInt::from_bytes(_res.y_bytes());
1419
1420
13
            ret = {
1421
13
                util::HexToDec(x.to_hex_string()),
1422
13
                util::HexToDec(y.to_hex_string()),
1423
13
            };
1424
1425
13
        }
1426
13
    } catch (::Botan::Internal_Error& e) {
1427
0
        throw e;
1428
0
    } catch (::Botan::Exception& e) {
1429
0
    }
1430
1431
51
end:
1432
51
    return ret;
1433
51
}
1434
1435
52
std::optional<component::ECC_Point> Botan::OpECC_Point_Sub(operation::ECC_Point_Sub& op) {
1436
52
    std::optional<component::ECC_Point> ret = std::nullopt;
1437
52
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1438
1439
52
    BOTAN_FUZZER_RNG;
1440
1441
52
    std::unique_ptr<::Botan::EC_Group> group = nullptr;
1442
52
    std::unique_ptr<::Botan::EC_AffinePoint> a, b;
1443
1444
52
    try {
1445
52
        {
1446
52
            std::optional<std::string> curveString;
1447
52
            CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1448
40
            group = std::make_unique<::Botan::EC_Group>(*curveString);
1449
40
        }
1450
1451
0
        {
1452
            /* A */
1453
40
            {
1454
40
                const auto a_x = ::Botan::BigInt::from_string(op.a.first.ToString(ds));
1455
40
                CF_CHECK_GTE(a_x, 0);
1456
1457
40
                const auto a_y = ::Botan::BigInt::from_string(op.a.second.ToString(ds));
1458
40
                CF_CHECK_GTE(a_y, 0);
1459
1460
40
                try {
1461
40
                    std::optional<::Botan::EC_AffinePoint> a_point;
1462
40
                    CF_CHECK_NE(a_point = ::Botan::EC_AffinePoint::from_bigint_xy(*group, a_x, a_y), std::nullopt);
1463
26
                    a = std::make_unique<::Botan::EC_AffinePoint>(*a_point);
1464
26
                } catch ( ::Botan::Invalid_Argument ) {
1465
0
                    goto end;
1466
0
                }
1467
40
            }
1468
1469
            /* B */
1470
26
            {
1471
26
                const auto b_x = ::Botan::BigInt::from_string(op.b.first.ToString(ds));
1472
26
                CF_CHECK_GTE(b_x, 0);
1473
1474
26
                const auto b_y = ::Botan::BigInt::from_string(op.b.second.ToString(ds));
1475
26
                CF_CHECK_GTE(b_y, 0);
1476
1477
26
                try {
1478
26
                    std::optional<::Botan::EC_AffinePoint> b_point;
1479
26
                    CF_CHECK_NE(b_point = ::Botan::EC_AffinePoint::from_bigint_xy(*group, b_x, b_y), std::nullopt);
1480
20
                    b = std::make_unique<::Botan::EC_AffinePoint>(*b_point);
1481
20
                } catch ( ::Botan::Invalid_Argument ) {
1482
0
                    goto end;
1483
0
                }
1484
26
            }
1485
1486
20
            const bool is_eq = *a == *b;
1487
1488
20
            ::Botan::EC_AffinePoint _res = a->add(b->negate());
1489
1490
20
            const bool is_zero = _res.is_identity();
1491
1492
            /* If A equals B, then subtraction of both should result in point at infinity */
1493
            /* Otherwise, it should result in non-infinity. */
1494
20
            CF_ASSERT(is_zero == is_eq, "Unexpected point subtraction result");
1495
20
            CF_CHECK_FALSE(is_zero);
1496
1497
12
            const auto x = ::Botan::BigInt::from_bytes(_res.x_bytes());
1498
12
            const auto y = ::Botan::BigInt::from_bytes(_res.y_bytes());
1499
1500
12
            ret = {
1501
12
                util::HexToDec(x.to_hex_string()),
1502
12
                util::HexToDec(y.to_hex_string()),
1503
12
            };
1504
1505
12
        }
1506
12
    } catch (::Botan::Internal_Error& e) {
1507
0
        throw e;
1508
0
    } catch (::Botan::Exception& e) {
1509
0
    }
1510
1511
52
end:
1512
52
    return ret;
1513
52
}
1514
1515
644
std::optional<component::ECC_Point> Botan::OpECC_Point_Mul(operation::ECC_Point_Mul& op) {
1516
644
    std::optional<component::ECC_Point> ret = std::nullopt;
1517
644
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1518
1519
644
    BOTAN_FUZZER_RNG;
1520
1521
644
    std::unique_ptr<::Botan::EC_Group> group = nullptr;
1522
1523
644
    {
1524
644
        std::optional<std::string> curveString;
1525
644
        CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1526
633
        group = std::make_unique<::Botan::EC_Group>(*curveString);
1527
633
    }
1528
1529
633
    try {
1530
633
        const auto a_x = ::Botan::BigInt::from_string(op.a.first.ToString(ds));
1531
633
        CF_CHECK_GTE(a_x, 0);
1532
1533
633
        const auto a_y = ::Botan::BigInt::from_string(op.a.second.ToString(ds));
1534
633
        CF_CHECK_GTE(a_y, 0);
1535
1536
633
        std::optional<::Botan::EC_AffinePoint> a;
1537
633
        CF_CHECK_NE(a = ::Botan::EC_AffinePoint::from_bigint_xy(*group, a_x, a_y), std::nullopt);
1538
1539
611
        const auto b = ::Botan::BigInt::from_string(op.b.ToString(ds));
1540
611
        CF_CHECK_GTE(b, 0);
1541
1542
611
        const auto k = ::Botan::EC_Scalar::from_bigint(*group, b);
1543
1544
611
        bool useBlinding = false;
1545
#if defined(CRYPTOFUZZ_BOTAN_IS_ORACLE)
1546
        try {
1547
            useBlinding = ds.Get<bool>();
1548
        } catch ( fuzzing::datasource::Datasource::OutOfData ) { }
1549
#endif
1550
1551
611
        std::unique_ptr<::Botan::EC_AffinePoint> _res;
1552
1553
611
        if ( useBlinding == false ) {
1554
605
            _res = std::make_unique<::Botan::EC_AffinePoint>(a->mul(k, rng));
1555
605
        } else {
1556
6
            _res = std::make_unique<::Botan::EC_AffinePoint>(a->mul(k, rng));
1557
6
        }
1558
1559
611
        const auto x = ::Botan::BigInt::from_bytes(_res->x_bytes());
1560
611
        const auto y = ::Botan::BigInt::from_bytes(_res->y_bytes());
1561
1562
611
        ret = {
1563
611
            util::HexToDec(x.to_hex_string()),
1564
611
            util::HexToDec(y.to_hex_string()),
1565
611
        };
1566
611
    } catch (::Botan::Internal_Error& e) {
1567
0
        throw e;
1568
6
    } catch (::Botan::Exception& e) {
1569
6
    }
1570
1571
282
end:
1572
282
    return ret;
1573
633
}
1574
1575
181
std::optional<component::ECC_Point> Botan::OpECC_Point_Neg(operation::ECC_Point_Neg& op) {
1576
181
    std::optional<component::ECC_Point> ret = std::nullopt;
1577
181
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1578
1579
181
    std::unique_ptr<::Botan::EC_Group> group = nullptr;
1580
1581
181
    {
1582
181
        std::optional<std::string> curveString;
1583
181
        CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1584
169
        group = std::make_unique<::Botan::EC_Group>(*curveString);
1585
169
    }
1586
1587
169
    try {
1588
169
        const auto a_x = ::Botan::BigInt::from_string(op.a.first.ToString(ds));
1589
169
        CF_CHECK_GTE(a_x, 0);
1590
1591
169
        const auto a_y = ::Botan::BigInt::from_string(op.a.second.ToString(ds));
1592
169
        CF_CHECK_GTE(a_y, 0);
1593
1594
169
        std::optional<::Botan::EC_AffinePoint> a;
1595
169
        CF_CHECK_NE(a = ::Botan::EC_AffinePoint::from_bigint_xy(*group, a_x, a_y), std::nullopt);
1596
1597
108
        const ::Botan::EC_AffinePoint _res = a->negate();
1598
1599
108
        const auto x = ::Botan::BigInt::from_bytes(_res.x_bytes());
1600
108
        const auto y = ::Botan::BigInt::from_bytes(_res.y_bytes());
1601
1602
108
        ret = {
1603
108
            util::HexToDec(x.to_hex_string()),
1604
108
            util::HexToDec(y.to_hex_string()),
1605
108
        };
1606
1607
108
    } catch (::Botan::Internal_Error& e) {
1608
0
        throw e;
1609
0
    } catch (::Botan::Exception& e) {
1610
0
    }
1611
1612
181
end:
1613
181
    return ret;
1614
169
}
1615
1616
128
std::optional<component::ECC_Point> Botan::OpECC_Point_Dbl(operation::ECC_Point_Dbl& op) {
1617
128
    std::optional<component::ECC_Point> ret = std::nullopt;
1618
128
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1619
1620
128
    std::unique_ptr<::Botan::EC_Group> group = nullptr;
1621
1622
128
    {
1623
128
        std::optional<std::string> curveString;
1624
128
        CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1625
113
        group = std::make_unique<::Botan::EC_Group>(*curveString);
1626
113
    }
1627
1628
113
    try {
1629
113
        const auto a_x = ::Botan::BigInt::from_string(op.a.first.ToString(ds));
1630
113
        CF_CHECK_GTE(a_x, 0);
1631
1632
113
        const auto a_y = ::Botan::BigInt::from_string(op.a.second.ToString(ds));
1633
113
        CF_CHECK_GTE(a_y, 0);
1634
1635
113
        std::optional<::Botan::EC_AffinePoint> a;
1636
113
        CF_CHECK_NE(a = ::Botan::EC_AffinePoint::from_bigint_xy(*group, a_x, a_y), std::nullopt);
1637
1638
48
        const ::Botan::EC_AffinePoint _res = a->add(*a);
1639
1640
48
        const auto x = ::Botan::BigInt::from_bytes(_res.x_bytes());
1641
48
        const auto y = ::Botan::BigInt::from_bytes(_res.y_bytes());
1642
1643
48
        ret = {
1644
48
            util::HexToDec(x.to_hex_string()),
1645
48
            util::HexToDec(y.to_hex_string()),
1646
48
        };
1647
1648
48
    } catch (::Botan::Internal_Error& e) {
1649
0
        throw e;
1650
0
    } catch (::Botan::Exception& e) {
1651
0
    }
1652
1653
128
end:
1654
128
    return ret;
1655
113
}
1656
1657
35
std::optional<bool> Botan::OpECC_Point_Cmp(operation::ECC_Point_Cmp& op) {
1658
35
    std::optional<bool> ret = std::nullopt;
1659
35
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1660
1661
35
    BOTAN_FUZZER_RNG;
1662
1663
35
    std::unique_ptr<::Botan::EC_Group> group = nullptr;
1664
35
    std::unique_ptr<::Botan::EC_AffinePoint> a, b;
1665
1666
35
    try {
1667
35
        {
1668
35
            std::optional<std::string> curveString;
1669
35
            CF_CHECK_NE(curveString = Botan_detail::CurveIDToString(op.curveType.Get()), std::nullopt);
1670
23
            group = std::make_unique<::Botan::EC_Group>(*curveString);
1671
23
        }
1672
1673
0
        {
1674
            /* A */
1675
23
            {
1676
23
                const auto a_x = ::Botan::BigInt::from_string(op.a.first.ToString(ds));
1677
23
                CF_CHECK_GTE(a_x, 0);
1678
1679
23
                const auto a_y = ::Botan::BigInt::from_string(op.a.second.ToString(ds));
1680
23
                CF_CHECK_GTE(a_y, 0);
1681
1682
23
                try {
1683
23
                    std::optional<::Botan::EC_AffinePoint> a_point;
1684
23
                    CF_CHECK_NE(a_point = ::Botan::EC_AffinePoint::from_bigint_xy(*group, a_x, a_y), std::nullopt);
1685
6
                    a = std::make_unique<::Botan::EC_AffinePoint>(*a_point);
1686
6
                } catch ( ::Botan::Invalid_Argument ) {
1687
0
                    goto end;
1688
0
                }
1689
23
            }
1690
1691
            /* B */
1692
6
            {
1693
6
                const auto b_x = ::Botan::BigInt::from_string(op.b.first.ToString(ds));
1694
6
                CF_CHECK_GTE(b_x, 0);
1695
1696
6
                const auto b_y = ::Botan::BigInt::from_string(op.b.second.ToString(ds));
1697
6
                CF_CHECK_GTE(b_y, 0);
1698
1699
6
                try {
1700
6
                    std::optional<::Botan::EC_AffinePoint> b_point;
1701
6
                    CF_CHECK_NE(b_point = ::Botan::EC_AffinePoint::from_bigint_xy(*group, b_x, b_y), std::nullopt);
1702
3
                    b = std::make_unique<::Botan::EC_AffinePoint>(*b_point);
1703
3
                } catch ( ... ) {
1704
0
                    goto end;
1705
0
                }
1706
6
            }
1707
1708
3
            ret = *a == *b;
1709
3
        }
1710
3
    } catch (::Botan::Internal_Error& e) {
1711
0
        throw e;
1712
0
    } catch (::Botan::Exception& e) {
1713
0
    }
1714
1715
35
end:
1716
35
    return ret;
1717
35
}
1718
1719
107
std::optional<bool> Botan::OpDSA_Verify(operation::DSA_Verify& op) {
1720
107
    std::optional<bool> ret = std::nullopt;
1721
107
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1722
1723
107
    BOTAN_FUZZER_RNG;
1724
1725
107
    try {
1726
107
        const auto p = ::Botan::BigInt::from_string(op.parameters.p.ToString(ds));
1727
        /* Avoid time-outs */
1728
107
        CF_CHECK_LTE(p.bytes(), 300);
1729
106
        const auto q = ::Botan::BigInt::from_string(op.parameters.q.ToString(ds));
1730
106
        const auto g = ::Botan::BigInt::from_string(op.parameters.g.ToString(ds));
1731
1732
        /* Botan can verify signatures with g = 0.
1733
         * Avoid discrepancies with OpenSSL
1734
         */
1735
106
        CF_CHECK_NE(g, 0);
1736
1737
99
        const ::Botan::DL_Group group(p, q, g);
1738
99
        CF_CHECK_TRUE(group.verify_group(rng));
1739
1740
53
        const auto y = ::Botan::BigInt::from_string(op.pub.ToString(ds));
1741
53
        const auto pub = std::make_unique<::Botan::DSA_PublicKey>(group, y);
1742
1743
53
        const auto r = ::Botan::BigInt::from_string(op.signature.first.ToString(ds));
1744
53
        const auto s = ::Botan::BigInt::from_string(op.signature.second.ToString(ds));
1745
1746
53
        const auto sig = ::Botan::BigInt::encode_fixed_length_int_pair(
1747
53
                r, s, q.bytes());
1748
53
        auto verifier = ::Botan::PK_Verifier(*pub, "Raw");
1749
53
        verifier.update(op.cleartext.Get());
1750
53
        ret = verifier.check_signature(sig);
1751
53
    } catch ( ... ) {
1752
51
    }
1753
1754
107
end:
1755
107
    return ret;
1756
107
}
1757
1758
4.13k
std::optional<component::Bignum> Botan::OpBignumCalc(operation::BignumCalc& op) {
1759
4.13k
    std::optional<component::Bignum> ret = std::nullopt;
1760
1761
4.13k
    if ( op.modulo ) {
1762
719
        switch ( op.calcOp.Get() ) {
1763
8
            case    CF_CALCOP("Add(A,B)"):
1764
60
            case    CF_CALCOP("Bit(A,B)"):
1765
98
            case    CF_CALCOP("CondSet(A,B)"):
1766
104
            case    CF_CALCOP("Exp(A,B)"):
1767
114
            case    CF_CALCOP("InvMod(A,B)"):
1768
132
            case    CF_CALCOP("IsEq(A,B)"):
1769
133
            case    CF_CALCOP("IsEven(A)"):
1770
134
            case    CF_CALCOP("IsOdd(A)"):
1771
144
            case    CF_CALCOP("IsOne(A)"):
1772
148
            case    CF_CALCOP("IsZero(A)"):
1773
152
            case    CF_CALCOP("LShift1(A)"):
1774
180
            case    CF_CALCOP("Mul(A,B)"):
1775
197
            case    CF_CALCOP("Not(A)"):
1776
205
            case    CF_CALCOP("NumBits(A)"):
1777
266
            case    CF_CALCOP("RShift(A,B)"):
1778
271
            case    CF_CALCOP("Set(A)"):
1779
296
            case    CF_CALCOP("Sqr(A)"):
1780
383
            case    CF_CALCOP("Sqrt(A)"):
1781
403
            case    CF_CALCOP("Sub(A,B)"):
1782
403
                break;
1783
316
            default:
1784
316
                return ret;
1785
719
        }
1786
719
    }
1787
3.81k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1788
1789
3.81k
    Botan_bignum::Bignum res(&ds, "0");
1790
3.81k
    std::vector<Botan_bignum::Bignum> bn{
1791
3.81k
        Botan_bignum::Bignum(&ds, op.bn0.ToString(ds)),
1792
3.81k
        Botan_bignum::Bignum(&ds, op.bn1.ToString(ds)),
1793
3.81k
        Botan_bignum::Bignum(&ds, op.bn2.ToString(ds)),
1794
3.81k
        Botan_bignum::Bignum(&ds, op.bn3.ToString(ds))
1795
3.81k
    };
1796
3.81k
    std::unique_ptr<Botan_bignum::Operation> opRunner = nullptr;
1797
1798
3.81k
    switch ( op.calcOp.Get() ) {
1799
12
        case    CF_CALCOP("Add(A,B)"):
1800
12
            opRunner = std::make_unique<Botan_bignum::Add>();
1801
12
            break;
1802
28
        case    CF_CALCOP("Sub(A,B)"):
1803
28
            opRunner = std::make_unique<Botan_bignum::Sub>();
1804
28
            break;
1805
45
        case    CF_CALCOP("Mul(A,B)"):
1806
45
            opRunner = std::make_unique<Botan_bignum::Mul>();
1807
45
            break;
1808
41
        case    CF_CALCOP("Div(A,B)"):
1809
41
            opRunner = std::make_unique<Botan_bignum::Div>();
1810
41
            break;
1811
47
        case    CF_CALCOP("Mod(A,B)"):
1812
47
            opRunner = std::make_unique<Botan_bignum::Mod>();
1813
47
            break;
1814
425
        case    CF_CALCOP("ExpMod(A,B,C)"):
1815
            /* Too slow with larger values */
1816
425
            CF_CHECK_LT(op.bn0.GetSize(), 1000);
1817
417
            CF_CHECK_LT(op.bn1.GetSize(), 1000);
1818
409
            CF_CHECK_LT(op.bn2.GetSize(), 1000);
1819
1820
404
            opRunner = std::make_unique<Botan_bignum::ExpMod>();
1821
404
            break;
1822
48
        case    CF_CALCOP("Exp(A,B)"):
1823
48
            opRunner = std::make_unique<Botan_bignum::Exp>();
1824
48
            break;
1825
53
        case    CF_CALCOP("Sqr(A)"):
1826
53
            opRunner = std::make_unique<Botan_bignum::Sqr>();
1827
53
            break;
1828
72
        case    CF_CALCOP("GCD(A,B)"):
1829
72
            opRunner = std::make_unique<Botan_bignum::GCD>();
1830
72
            break;
1831
36
        case    CF_CALCOP("SqrMod(A,B)"):
1832
36
            opRunner = std::make_unique<Botan_bignum::SqrMod>();
1833
36
            break;
1834
348
        case    CF_CALCOP("InvMod(A,B)"):
1835
348
            opRunner = std::make_unique<Botan_bignum::InvMod>();
1836
348
            break;
1837
11
        case    CF_CALCOP("Cmp(A,B)"):
1838
11
            opRunner = std::make_unique<Botan_bignum::Cmp>();
1839
11
            break;
1840
316
        case    CF_CALCOP("LCM(A,B)"):
1841
316
            opRunner = std::make_unique<Botan_bignum::LCM>();
1842
316
            break;
1843
5
        case    CF_CALCOP("Abs(A)"):
1844
5
            opRunner = std::make_unique<Botan_bignum::Abs>();
1845
5
            break;
1846
26
        case    CF_CALCOP("Jacobi(A,B)"):
1847
26
            opRunner = std::make_unique<Botan_bignum::Jacobi>();
1848
26
            break;
1849
29
        case    CF_CALCOP("Neg(A)"):
1850
29
            opRunner = std::make_unique<Botan_bignum::Neg>();
1851
29
            break;
1852
78
        case    CF_CALCOP("IsPrime(A)"):
1853
78
            opRunner = std::make_unique<Botan_bignum::IsPrime>();
1854
78
            break;
1855
69
        case    CF_CALCOP("RShift(A,B)"):
1856
69
            opRunner = std::make_unique<Botan_bignum::RShift>();
1857
69
            break;
1858
7
        case    CF_CALCOP("LShift1(A)"):
1859
7
            opRunner = std::make_unique<Botan_bignum::LShift1>();
1860
7
            break;
1861
1
        case    CF_CALCOP("IsNeg(A)"):
1862
1
            opRunner = std::make_unique<Botan_bignum::IsNeg>();
1863
1
            break;
1864
22
        case    CF_CALCOP("IsEq(A,B)"):
1865
22
            opRunner = std::make_unique<Botan_bignum::IsEq>();
1866
22
            break;
1867
1
        case    CF_CALCOP("IsGt(A,B)"):
1868
1
            opRunner = std::make_unique<Botan_bignum::IsGt>();
1869
1
            break;
1870
2
        case    CF_CALCOP("IsGte(A,B)"):
1871
2
            opRunner = std::make_unique<Botan_bignum::IsGte>();
1872
2
            break;
1873
1
        case    CF_CALCOP("IsLt(A,B)"):
1874
1
            opRunner = std::make_unique<Botan_bignum::IsLt>();
1875
1
            break;
1876
1
        case    CF_CALCOP("IsLte(A,B)"):
1877
1
            opRunner = std::make_unique<Botan_bignum::IsLte>();
1878
1
            break;
1879
5
        case    CF_CALCOP("IsEven(A)"):
1880
5
            opRunner = std::make_unique<Botan_bignum::IsEven>();
1881
5
            break;
1882
8
        case    CF_CALCOP("IsOdd(A)"):
1883
8
            opRunner = std::make_unique<Botan_bignum::IsOdd>();
1884
8
            break;
1885
5
        case    CF_CALCOP("IsZero(A)"):
1886
5
            opRunner = std::make_unique<Botan_bignum::IsZero>();
1887
5
            break;
1888
1
        case    CF_CALCOP("IsNotZero(A)"):
1889
1
            opRunner = std::make_unique<Botan_bignum::IsNotZero>();
1890
1
            break;
1891
11
        case    CF_CALCOP("IsOne(A)"):
1892
11
            opRunner = std::make_unique<Botan_bignum::IsOne>();
1893
11
            break;
1894
20
        case    CF_CALCOP("MulMod(A,B,C)"):
1895
20
            opRunner = std::make_unique<Botan_bignum::MulMod>();
1896
20
            break;
1897
59
        case    CF_CALCOP("Bit(A,B)"):
1898
59
            opRunner = std::make_unique<Botan_bignum::Bit>();
1899
59
            break;
1900
2
        case    CF_CALCOP("CmpAbs(A,B)"):
1901
2
            opRunner = std::make_unique<Botan_bignum::CmpAbs>();
1902
2
            break;
1903
5
        case    CF_CALCOP("SetBit(A,B)"):
1904
5
            opRunner = std::make_unique<Botan_bignum::SetBit>();
1905
5
            break;
1906
5
        case    CF_CALCOP("ClearBit(A,B)"):
1907
5
            opRunner = std::make_unique<Botan_bignum::ClearBit>();
1908
5
            break;
1909
5
        case    CF_CALCOP("MulAdd(A,B,C)"):
1910
5
            opRunner = std::make_unique<Botan_bignum::MulAdd>();
1911
5
            break;
1912
6
        case    CF_CALCOP("MulDiv(A,B,C)"):
1913
6
            opRunner = std::make_unique<Botan_bignum::MulDiv>();
1914
6
            break;
1915
35
        case    CF_CALCOP("MulDivCeil(A,B,C)"):
1916
35
            opRunner = std::make_unique<Botan_bignum::MulDivCeil>();
1917
35
            break;
1918
9
        case    CF_CALCOP("Exp2(A)"):
1919
9
            opRunner = std::make_unique<Botan_bignum::Exp2>();
1920
9
            break;
1921
6
        case    CF_CALCOP("NumLSZeroBits(A)"):
1922
6
            opRunner = std::make_unique<Botan_bignum::NumLSZeroBits>();
1923
6
            break;
1924
123
        case    CF_CALCOP("Sqrt(A)"):
1925
123
            if ( op.modulo == std::nullopt ) {
1926
36
                opRunner = std::make_unique<Botan_bignum::Sqrt>();
1927
87
            } else {
1928
87
                opRunner = std::make_unique<Botan_bignum::Ressol>();
1929
87
            }
1930
123
            break;
1931
24
        case    CF_CALCOP("AddMod(A,B,C)"):
1932
24
            opRunner = std::make_unique<Botan_bignum::AddMod>();
1933
24
            break;
1934
28
        case    CF_CALCOP("SubMod(A,B,C)"):
1935
28
            opRunner = std::make_unique<Botan_bignum::SubMod>();
1936
28
            break;
1937
9
        case    CF_CALCOP("NumBits(A)"):
1938
9
            opRunner = std::make_unique<Botan_bignum::NumBits>();
1939
9
            break;
1940
6
        case    CF_CALCOP("Set(A)"):
1941
6
            opRunner = std::make_unique<Botan_bignum::Set>();
1942
6
            break;
1943
39
        case    CF_CALCOP("CondSet(A,B)"):
1944
39
            opRunner = std::make_unique<Botan_bignum::CondSet>();
1945
39
            break;
1946
        /*
1947
        case    CF_CALCOP("Ressol(A,B)"):
1948
            opRunner = std::make_unique<Botan_bignum::Ressol>();
1949
            break;
1950
        */
1951
27
        case    CF_CALCOP("Not(A)"):
1952
27
            opRunner = std::make_unique<Botan_bignum::Not>();
1953
27
            break;
1954
141
        case    CF_CALCOP("Prime()"):
1955
141
            opRunner = std::make_unique<Botan_bignum::Prime>();
1956
141
            break;
1957
5
        case    CF_CALCOP("RandRange(A,B)"):
1958
5
            opRunner = std::make_unique<Botan_bignum::RandRange>();
1959
5
            break;
1960
17
        case    CF_CALCOP("IsSquare(A)"):
1961
17
            opRunner = std::make_unique<Botan_bignum::IsSquare>();
1962
17
            break;
1963
3.81k
    }
1964
1965
3.79k
    CF_CHECK_NE(opRunner, nullptr);
1966
1967
#if defined(CRYPTOFUZZ_BOTAN_IS_ORACLE)
1968
    try {
1969
#endif
1970
2.30k
        CF_CHECK_EQ(opRunner->Run(
1971
2.30k
                    ds,
1972
2.30k
                    res,
1973
2.30k
                    bn,
1974
2.30k
                    op.modulo ?
1975
2.30k
                        std::optional<Botan_bignum::Bignum>(Botan_bignum::Bignum(op.modulo->ToTrimmedString())) :
1976
2.30k
                        std::nullopt), true);
1977
#if defined(CRYPTOFUZZ_BOTAN_IS_ORACLE)
1978
    } catch ( ... ) {
1979
        goto end;
1980
    }
1981
#endif
1982
1983
2.06k
    ret = { util::HexToDec(res.Ref().to_hex_string()) };
1984
1985
3.81k
end:
1986
3.81k
    return ret;
1987
2.06k
}
1988
1989
731
bool Botan::SupportsModularBignumCalc(void) const {
1990
731
    return true;
1991
731
}
1992
1993
} /* namespace module */
1994
} /* namespace cryptofuzz */