Coverage Report

Created: 2026-10-06 06:17

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