Coverage Report

Created: 2024-11-21 07:00

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