Coverage Report

Created: 2023-09-25 06:34

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