Coverage Report

Created: 2024-02-25 06:16

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