Coverage Report

Created: 2026-04-05 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptofuzz-openssl-api/modules/wolfcrypt-openssl/module.cpp
Line
Count
Source
1
#include "module.h"
2
#include <cryptofuzz/util.h>
3
#include <cryptofuzz/repository.h>
4
#include <fuzzing/datasource/id.hpp>
5
#include "bn_ops.h"
6
extern "C" {
7
#include <wolfssl/openssl/hmac.h>
8
}
9
#if defined(HMAC)
10
#undef HMAC
11
#endif
12
#include "module_internal.h"
13
14
namespace cryptofuzz {
15
namespace module {
16
17
wolfCrypt_OpenSSL::wolfCrypt_OpenSSL(void) :
18
2
    Module("wolfCrypt-OpenSSL") {
19
2
}
20
21
namespace wolfCrypt_OpenSSL_detail {
22
3.26k
    const EVP_MD* toEVPMD(const component::DigestType& digestType) {
23
3.26k
        using fuzzing::datasource::ID;
24
25
3.26k
        static const std::map<uint64_t, const EVP_MD*> LUT = {
26
#if defined(CRYPTOFUZZ_BORINGSSL)
27
            { CF_DIGEST("SHA1"), EVP_sha1() },
28
            { CF_DIGEST("SHA224"), EVP_sha224() },
29
            { CF_DIGEST("SHA256"), EVP_sha256() },
30
            { CF_DIGEST("SHA384"), EVP_sha384() },
31
            { CF_DIGEST("SHA512"), EVP_sha512() },
32
            { CF_DIGEST("MD4"), EVP_md4() },
33
            { CF_DIGEST("MD5"), EVP_md5() },
34
            { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() },
35
            { CF_DIGEST("SHA512-256"), EVP_sha512_256() },
36
#elif defined(CRYPTOFUZZ_LIBRESSL)
37
            { CF_DIGEST("SHA1"), EVP_sha1() },
38
            { CF_DIGEST("SHA224"), EVP_sha224() },
39
            { CF_DIGEST("SHA256"), EVP_sha256() },
40
            { CF_DIGEST("SHA384"), EVP_sha384() },
41
            { CF_DIGEST("SHA512"), EVP_sha512() },
42
            { CF_DIGEST("MD4"), EVP_md4() },
43
            { CF_DIGEST("MD5"), EVP_md5() },
44
            { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() },
45
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
46
            { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() },
47
            { CF_DIGEST("SM3"), EVP_sm3() },
48
            { CF_DIGEST("GOST-R-34.11-94"), EVP_gostr341194() },
49
            { CF_DIGEST("GOST-28147-89"), EVP_gost2814789imit() },
50
            { CF_DIGEST("STREEBOG-256"), EVP_streebog256() },
51
            { CF_DIGEST("STREEBOG-512"), EVP_streebog512() },
52
#elif defined(CRYPTOFUZZ_OPENSSL_102)
53
            { CF_DIGEST("SHA1"), EVP_sha1() },
54
            { CF_DIGEST("SHA224"), EVP_sha224() },
55
            { CF_DIGEST("SHA256"), EVP_sha256() },
56
            { CF_DIGEST("SHA384"), EVP_sha384() },
57
            { CF_DIGEST("SHA512"), EVP_sha512() },
58
            { CF_DIGEST("MD2"), EVP_md2() },
59
            { CF_DIGEST("MD4"), EVP_md4() },
60
            { CF_DIGEST("MD5"), EVP_md5() },
61
            { CF_DIGEST("MDC2"), EVP_mdc2() },
62
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
63
            { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() },
64
#elif defined(CRYPTOFUZZ_OPENSSL_110)
65
            { CF_DIGEST("SHA1"), EVP_sha1() },
66
            { CF_DIGEST("SHA224"), EVP_sha224() },
67
            { CF_DIGEST("SHA256"), EVP_sha256() },
68
            { CF_DIGEST("SHA384"), EVP_sha384() },
69
            { CF_DIGEST("SHA512"), EVP_sha512() },
70
            { CF_DIGEST("MD2"), EVP_md2() },
71
            { CF_DIGEST("MD4"), EVP_md4() },
72
            { CF_DIGEST("MD5"), EVP_md5() },
73
            { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() },
74
            { CF_DIGEST("MDC2"), EVP_mdc2() },
75
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
76
            { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() },
77
            { CF_DIGEST("BLAKE2B512"), EVP_blake2b512() },
78
            { CF_DIGEST("BLAKE2S256"), EVP_blake2s256() },
79
#elif defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
80
3.26k
            { CF_DIGEST("SHA1"), EVP_sha1() },
81
3.26k
            { CF_DIGEST("MDC2"), EVP_mdc2() },
82
3.26k
            { CF_DIGEST("MD4"), EVP_md4() },
83
3.26k
            { CF_DIGEST("MD5"), EVP_md5() },
84
3.26k
            { CF_DIGEST("SHA224"), EVP_sha224() },
85
3.26k
            { CF_DIGEST("SHA256"), EVP_sha256() },
86
3.26k
            { CF_DIGEST("SHA384"), EVP_sha384() },
87
3.26k
            { CF_DIGEST("SHA512"), EVP_sha512() },
88
3.26k
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
89
#if 0
90
            { CF_DIGEST("MDC2"), EVP_mdc2() },
91
            { CF_DIGEST("MD4"), EVP_md4() },
92
            { CF_DIGEST("MD5"), EVP_md5() },
93
            { CF_DIGEST("SHA1"), EVP_sha1() },
94
            { CF_DIGEST("SHA224"), EVP_sha224() },
95
            { CF_DIGEST("SHA256"), EVP_sha256() },
96
            { CF_DIGEST("SHA384"), EVP_sha384() },
97
            { CF_DIGEST("SHA512"), EVP_sha512() },
98
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
99
            { CF_DIGEST("SHA3-224"), EVP_sha3_224() },
100
            { CF_DIGEST("SHA3-256"), EVP_sha3_256() },
101
            { CF_DIGEST("SHA3-384"), EVP_sha3_384() },
102
            { CF_DIGEST("SHA3-512"), EVP_sha3_512() },
103
#endif
104
#else
105
            { CF_DIGEST("SHA1"), EVP_sha1() },
106
            { CF_DIGEST("SHA224"), EVP_sha224() },
107
            { CF_DIGEST("SHA256"), EVP_sha256() },
108
            { CF_DIGEST("SHA384"), EVP_sha384() },
109
            { CF_DIGEST("SHA512"), EVP_sha512() },
110
            { CF_DIGEST("MD2"), EVP_md2() },
111
            { CF_DIGEST("MD4"), EVP_md4() },
112
            { CF_DIGEST("MD5"), EVP_md5() },
113
            { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() },
114
            { CF_DIGEST("MDC2"), EVP_mdc2() },
115
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
116
            { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() },
117
            { CF_DIGEST("SM3"), EVP_sm3() },
118
            { CF_DIGEST("BLAKE2B512"), EVP_blake2b512() },
119
            { CF_DIGEST("BLAKE2S256"), EVP_blake2s256() },
120
            { CF_DIGEST("SHAKE128"), EVP_shake128() },
121
            { CF_DIGEST("SHAKE256"), EVP_shake256() },
122
            { CF_DIGEST("SHA3-224"), EVP_sha3_224() },
123
            { CF_DIGEST("SHA3-256"), EVP_sha3_256() },
124
            { CF_DIGEST("SHA3-384"), EVP_sha3_384() },
125
            { CF_DIGEST("SHA3-512"), EVP_sha3_512() },
126
            { CF_DIGEST("SHA512-224"), EVP_sha512_224() },
127
            { CF_DIGEST("SHA512-256"), EVP_sha512_256() },
128
#endif
129
3.26k
        };
130
131
3.26k
        if ( LUT.find(digestType.Get()) == LUT.end() ) {
132
642
            return nullptr;
133
642
        }
134
135
2.62k
        return LUT.at(digestType.Get());
136
3.26k
    }
137
}
138
139
997
std::optional<component::Digest> wolfCrypt_OpenSSL::OpDigest(operation::Digest& op) {
140
997
    std::optional<component::Digest> ret = std::nullopt;
141
997
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
142
143
997
    util::Multipart parts;
144
145
997
    CF_EVP_MD_CTX ctx(ds);
146
997
    const EVP_MD* md = nullptr;
147
148
    /* Initialize */
149
997
    {
150
997
        parts = util::ToParts(ds, op.cleartext);
151
997
        CF_CHECK_NE(md = wolfCrypt_OpenSSL_detail::toEVPMD(op.digestType), nullptr);
152
761
        CF_CHECK_EQ(EVP_DigestInit_ex(ctx.GetPtr(), md, nullptr), 1);
153
761
    }
154
155
    /* Process */
156
42.0k
    for (const auto& part : parts) {
157
42.0k
        CF_CHECK_EQ(EVP_DigestUpdate(ctx.GetPtr(), part.first, part.second), 1);
158
42.0k
    }
159
160
    /* Finalize */
161
761
    {
162
761
        unsigned int len = -1;
163
761
        unsigned char md[EVP_MAX_MD_SIZE];
164
761
        CF_CHECK_EQ(EVP_DigestFinal_ex(ctx.GetPtr(), md, &len), 1);
165
166
761
        ret = component::Digest(md, len);
167
761
    }
168
169
997
end:
170
997
    return ret;
171
761
}
172
173
namespace wolfCrypt_OpenSSL_detail {
174
723
std::optional<component::MAC> OpHMAC_EVP(operation::HMAC& op, Datasource& ds) {
175
723
    std::optional<component::MAC> ret = std::nullopt;
176
177
723
    util::Multipart parts;
178
179
723
    CF_EVP_MD_CTX ctx(ds);
180
723
    const EVP_MD* md = nullptr;
181
723
    EVP_PKEY *pkey = nullptr;
182
183
    /* Initialize */
184
723
    {
185
723
        parts = util::ToParts(ds, op.cleartext);
186
187
723
        CF_CHECK_NE(md = wolfCrypt_OpenSSL_detail::toEVPMD(op.digestType), nullptr);
188
517
        CF_CHECK_NE(pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, op.cipher.key.GetPtr(), op.cipher.key.GetSize()), nullptr);
189
517
        CF_CHECK_EQ(EVP_DigestSignInit(ctx.GetPtr(), nullptr, md, nullptr, pkey), 1);
190
482
    }
191
192
    /* Process */
193
5.24k
    for (const auto& part : parts) {
194
5.24k
        CF_CHECK_EQ(EVP_DigestSignUpdate(ctx.GetPtr(), part.first, part.second), 1);
195
5.05k
    }
196
197
    /* Finalize */
198
292
    {
199
292
        size_t len = -1;
200
292
        uint8_t out[EVP_MAX_MD_SIZE];
201
292
        CF_CHECK_EQ(EVP_DigestSignFinal(ctx.GetPtr(), out, &len), 1);
202
203
292
        ret = component::MAC(out, len);
204
292
    }
205
206
723
end:
207
723
    EVP_PKEY_free(pkey);
208
209
723
    return ret;
210
292
}
211
212
143
std::optional<component::MAC> OpHMAC_HMAC(operation::HMAC& op, Datasource& ds) {
213
143
    std::optional<component::MAC> ret = std::nullopt;
214
215
143
    util::Multipart parts;
216
217
143
    CF_HMAC_CTX ctx(ds);
218
143
    const EVP_MD* md = nullptr;
219
220
    /* Initialize */
221
143
    {
222
143
        parts = util::ToParts(ds, op.cleartext);
223
        /* TODO remove ? */
224
143
        HMAC_CTX_reset(ctx.GetPtr());
225
143
        CF_CHECK_NE(md = toEVPMD(op.digestType), nullptr);
226
119
        CF_CHECK_EQ(HMAC_Init_ex(ctx.GetPtr(), op.cipher.key.GetPtr(), op.cipher.key.GetSize(), md, nullptr), 1);
227
95
    }
228
229
    /* Process */
230
1.44k
    for (const auto& part : parts) {
231
1.44k
        CF_CHECK_EQ(HMAC_Update(ctx.GetPtr(), part.first, part.second), 1);
232
1.44k
    }
233
234
    /* Finalize */
235
95
    {
236
95
        unsigned int len = -1;
237
95
        uint8_t out[EVP_MAX_MD_SIZE];
238
95
        CF_CHECK_EQ(HMAC_Final(ctx.GetPtr(), out, &len), 1);
239
240
95
        ret = component::MAC(out, len);
241
95
    }
242
243
143
end:
244
143
    return ret;
245
95
}
246
}
247
248
866
std::optional<component::MAC> wolfCrypt_OpenSSL::OpHMAC(operation::HMAC& op) {
249
866
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
250
251
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
252
    if (    op.digestType.Get() == CF_DIGEST("SIPHASH64") ||
253
            op.digestType.Get() == CF_DIGEST("SIPHASH128") ) {
254
        /* Not HMAC but invoking SipHash here anyway due to convenience. */
255
        return OpenSSL_detail::SipHash(op);
256
    }
257
#endif
258
259
866
    bool useEVP = true;
260
866
    try {
261
866
        useEVP = ds.Get<bool>();
262
866
    } catch ( fuzzing::datasource::Datasource::OutOfData ) {
263
432
    }
264
265
866
    if ( useEVP == true ) {
266
723
#if !defined(CRYPTOFUZZ_BORINGSSL)
267
723
        return wolfCrypt_OpenSSL_detail::OpHMAC_EVP(op, ds);
268
#else
269
        return wolfCrypt_OpenSSL_detail::OpHMAC_HMAC(op, ds);
270
#endif
271
723
    } else {
272
143
#if !defined(CRYPTOFUZZ_OPENSSL_102)
273
143
        return wolfCrypt_OpenSSL_detail::OpHMAC_HMAC(op, ds);
274
#else
275
        return wolfCrypt_OpenSSL_detail::OpHMAC_EVP(op, ds);
276
#endif
277
143
    }
278
279
0
    return {};
280
866
}
281
282
namespace wolfCrypt_OpenSSL_detail {
283
284
8.36k
const EVP_CIPHER* toEVPCIPHER(const component::SymmetricCipherType cipherType) {
285
8.36k
    using fuzzing::datasource::ID;
286
287
8.36k
    switch ( cipherType.Get() ) {
288
316
        case CF_CIPHER("AES_128_CBC"):
289
316
            return EVP_aes_128_cbc();
290
149
        case CF_CIPHER("AES_128_CFB1"):
291
149
            return EVP_aes_128_cfb1();
292
188
        case CF_CIPHER("AES_128_CFB8"):
293
188
            return EVP_aes_128_cfb8();
294
78
        case CF_CIPHER("AES_128_CTR"):
295
78
            return EVP_aes_128_ctr();
296
104
        case CF_CIPHER("AES_128_ECB"):
297
104
            return EVP_aes_128_ecb();
298
512
        case CF_CIPHER("AES_128_GCM"):
299
512
            return EVP_aes_128_gcm();
300
231
        case CF_CIPHER("AES_128_OFB"):
301
231
            return EVP_aes_128_ofb();
302
456
        case CF_CIPHER("AES_128_XTS"):
303
456
            return EVP_aes_128_xts();
304
149
        case CF_CIPHER("AES_192_CBC"):
305
149
            return EVP_aes_192_cbc();
306
47
        case CF_CIPHER("AES_192_CFB1"):
307
47
            return EVP_aes_192_cfb1();
308
124
        case CF_CIPHER("AES_192_CFB8"):
309
124
            return EVP_aes_192_cfb8();
310
440
        case CF_CIPHER("AES_192_CTR"):
311
440
            return EVP_aes_192_ctr();
312
119
        case CF_CIPHER("AES_192_ECB"):
313
119
            return EVP_aes_192_ecb();
314
178
        case CF_CIPHER("AES_192_GCM"):
315
178
            return EVP_aes_192_gcm();
316
127
        case CF_CIPHER("AES_192_OFB"):
317
127
            return EVP_aes_192_ofb();
318
142
        case CF_CIPHER("AES_256_CBC"):
319
142
            return EVP_aes_256_cbc();
320
171
        case CF_CIPHER("AES_256_CFB1"):
321
171
            return EVP_aes_256_cfb1();
322
147
        case CF_CIPHER("AES_256_CFB8"):
323
147
            return EVP_aes_256_cfb8();
324
83
        case CF_CIPHER("AES_256_CTR"):
325
83
            return EVP_aes_256_ctr();
326
63
        case CF_CIPHER("AES_256_ECB"):
327
63
            return EVP_aes_256_ecb();
328
483
        case CF_CIPHER("AES_256_GCM"):
329
483
            return EVP_aes_256_gcm();
330
279
        case CF_CIPHER("AES_256_OFB"):
331
279
            return EVP_aes_256_ofb();
332
106
        case CF_CIPHER("AES_256_XTS"):
333
106
            return EVP_aes_256_xts();
334
220
        case CF_CIPHER("DES_CBC"):
335
220
            return EVP_des_cbc();
336
446
        case CF_CIPHER("DES_ECB"):
337
446
            return EVP_des_ecb();
338
248
        case CF_CIPHER("DES_EDE3_CBC"):
339
248
            return EVP_des_ede3_cbc();
340
66
        case CF_CIPHER("RC4"):
341
66
            return EVP_rc4();
342
2.69k
        default:
343
2.69k
            return nullptr;
344
8.36k
    }
345
8.36k
}
346
347
1.19k
inline bool isAEAD(const EVP_CIPHER* ctx) {
348
1.19k
    return (EVP_CIPHER_flags(ctx) & EVP_CIPH_GCM_MODE) == EVP_CIPH_GCM_MODE;
349
1.19k
}
350
351
5.05k
bool checkSetIVLength(const uint64_t cipherType, const EVP_CIPHER* cipher, EVP_CIPHER_CTX* ctx, const size_t inputIvLength) {
352
5.05k
    bool ret = false;
353
354
5.05k
    const size_t ivLength = EVP_CIPHER_iv_length(cipher);
355
5.05k
    const bool ivLengthMismatch = ivLength != inputIvLength;
356
357
5.05k
    return !ivLengthMismatch;
358
0
    if ( isAEAD(cipher) == false ) {
359
        /* Return true (success) if input IV length is expected IV length */
360
0
        return !ivLengthMismatch;
361
0
    }
362
363
0
    const bool isCCM = repository::IsCCM( cipherType );
364
365
    /* Only AEAD ciphers past this point */
366
367
    /* EVP_CIPHER_iv_length may return the wrong default IV length for CCM ciphers.
368
     * Eg. EVP_CIPHER_iv_length returns 12 for EVP_aes_128_ccm() even though the
369
     * IV length is actually.
370
     *
371
     * Hence, with CCM ciphers set the desired IV length always.
372
     */
373
374
0
    if ( isCCM || ivLengthMismatch ) {
375
0
        CF_CHECK_EQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, inputIvLength, nullptr), 1);
376
0
    }
377
378
0
    ret = true;
379
0
end:
380
381
0
    return ret;
382
0
}
383
384
4.60k
bool checkSetKeyLength(const EVP_CIPHER* cipher, EVP_CIPHER_CTX* ctx, const size_t inputKeyLength) {
385
4.60k
    (void)ctx;
386
387
4.60k
    bool ret = false;
388
389
4.60k
    const size_t keyLength = EVP_CIPHER_key_length(cipher);
390
4.60k
    if ( keyLength != inputKeyLength ) {
391
197
        return false;
392
0
        CF_CHECK_EQ(EVP_CIPHER_CTX_set_key_length(ctx, inputKeyLength), 1);
393
0
    }
394
395
4.41k
    ret = true;
396
397
4.41k
end:
398
4.41k
    return ret;
399
4.41k
}
400
401
3.98k
std::optional<component::Ciphertext> OpSymmetricEncrypt_EVP(operation::SymmetricEncrypt& op, Datasource& ds) {
402
3.98k
    std::optional<component::Ciphertext> ret = std::nullopt;
403
404
3.98k
    util::Multipart partsCleartext, partsAAD;
405
406
3.98k
    const EVP_CIPHER* cipher = nullptr;
407
3.98k
    CF_EVP_CIPHER_CTX ctx(ds);
408
409
3.98k
    size_t out_size = op.ciphertextSize;
410
3.98k
    size_t outIdx = 0;
411
3.98k
    uint8_t* out = util::malloc(out_size);
412
3.98k
    uint8_t* outTag = op.tagSize != std::nullopt ? util::malloc(*op.tagSize) : nullptr;
413
414
    /* Initialize */
415
3.98k
    {
416
3.98k
        CF_CHECK_NE(cipher = wolfCrypt_OpenSSL_detail::toEVPCIPHER(op.cipher.cipherType), nullptr);
417
2.62k
        if ( op.tagSize != std::nullopt || op.aad != std::nullopt ) {
418
            /* Trying to treat non-AEAD with AEAD-specific features (tag, aad)
419
             * leads to all kinds of gnarly memory bugs in OpenSSL.
420
             * It is quite arguably misuse of the OpenSSL API, so don't do this.
421
             */
422
664
            CF_CHECK_EQ(isAEAD(cipher), true);
423
566
        }
424
425
2.53k
        CF_CHECK_EQ(EVP_EncryptInit_ex(ctx.GetPtr(), cipher, nullptr, nullptr, nullptr), 1);
426
427
        /* Must be a multiple of the block size of this cipher */
428
        //CF_CHECK_EQ(op.cleartext.GetSize() % EVP_CIPHER_block_size(cipher), 0);
429
430
        /* Convert cleartext to parts */
431
2.53k
        partsCleartext = util::CipherInputTransform(ds, op.cipher.cipherType, out, out_size, op.cleartext.GetPtr(), op.cleartext.GetSize());
432
433
2.53k
        if ( op.aad != std::nullopt ) {
434
258
            if ( repository::IsCCM( op.cipher.cipherType.Get() ) ) {
435
                /* CCM does not support chunked AAD updating.
436
                 * See: https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Encryption_using_CCM_mode
437
                 */
438
0
                partsAAD = { {op.aad->GetPtr(), op.aad->GetSize()} };
439
258
            } else {
440
258
                partsAAD = util::ToParts(ds, *(op.aad));
441
258
            }
442
258
        }
443
444
2.53k
        if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) {
445
2.53k
            CF_CHECK_EQ(checkSetIVLength(op.cipher.cipherType.Get(), cipher, ctx.GetPtr(), op.cipher.iv.GetSize()), true);
446
2.30k
        } else {
447
0
            CF_CHECK_EQ(op.cipher.iv.GetSize(), 12);
448
0
        }
449
2.30k
        CF_CHECK_EQ(checkSetKeyLength(cipher, ctx.GetPtr(), op.cipher.key.GetSize()), true);
450
451
2.19k
        if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) {
452
2.19k
            CF_CHECK_EQ(EVP_EncryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), op.cipher.iv.GetPtr()), 1);
453
2.19k
        } else {
454
            /* Prepend the 32 bit counter (which is 0) to the iv */
455
0
            uint8_t cc20IV[16];
456
0
            memset(cc20IV, 0, 4);
457
0
            memcpy(cc20IV + 4, op.cipher.iv.GetPtr(), op.cipher.iv.GetSize());
458
0
            CF_CHECK_EQ(EVP_EncryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), cc20IV), 1);
459
0
        }
460
461
        /* Disable ECB padding for consistency with mbed TLS */
462
2.19k
        if ( repository::IsECB(op.cipher.cipherType.Get()) ) {
463
338
            CF_CHECK_EQ(EVP_CIPHER_CTX_set_padding(ctx.GetPtr(), 0), 1);
464
338
        }
465
2.19k
    }
466
467
    /* Process */
468
2.19k
    {
469
        /* If the cipher is CCM, the total cleartext size needs to be indicated explicitly
470
         * https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
471
         */
472
2.19k
        if ( repository::IsCCM(op.cipher.cipherType.Get()) == true ) {
473
0
            int len;
474
0
            CF_CHECK_EQ(EVP_EncryptUpdate(ctx.GetPtr(), nullptr, &len, nullptr, op.cleartext.GetSize()), 1);
475
0
        }
476
477
        /* Set AAD */
478
2.19k
        if ( op.aad != std::nullopt ) {
479
193
            for (const auto& part : partsAAD) {
480
193
                int len;
481
193
                CF_CHECK_EQ(EVP_EncryptUpdate(ctx.GetPtr(), nullptr, &len, part.first, part.second), 1);
482
193
            }
483
180
        }
484
485
24.4k
        for (const auto& part : partsCleartext) {
486
            /* "the amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1)" */
487
24.4k
            CF_CHECK_GTE(out_size, part.second + EVP_CIPHER_block_size(cipher) - 1);
488
489
24.2k
            int len = -1;
490
24.2k
            CF_CHECK_EQ(EVP_EncryptUpdate(ctx.GetPtr(), out + outIdx, &len, part.first, part.second), 1);
491
24.2k
            outIdx += len;
492
24.2k
            out_size -= len;
493
24.2k
        }
494
2.19k
    }
495
496
    /* Finalize */
497
2.05k
    {
498
2.05k
        CF_CHECK_GTE(out_size, static_cast<size_t>(EVP_CIPHER_block_size(cipher)));
499
500
2.01k
        int len = -1;
501
2.01k
        CF_CHECK_EQ(EVP_EncryptFinal_ex(ctx.GetPtr(), out + outIdx, &len), 1);
502
1.91k
        outIdx += len;
503
504
1.91k
        if ( op.tagSize != std::nullopt ) {
505
            /* Get tag.
506
             *
507
             * See comments around EVP_CTRL_AEAD_SET_TAG in OpSymmetricDecrypt_EVP for reasons
508
             * as to why this is disabled for LibreSSL.
509
             */
510
471
            CF_CHECK_EQ(EVP_CIPHER_CTX_ctrl(ctx.GetPtr(), EVP_CTRL_AEAD_GET_TAG, *op.tagSize, outTag), 1);
511
254
            ret = component::Ciphertext(Buffer(out, outIdx), Buffer(outTag, *op.tagSize));
512
1.44k
        } else {
513
1.44k
            ret = component::Ciphertext(Buffer(out, outIdx));
514
1.44k
        }
515
1.91k
    }
516
517
3.98k
end:
518
519
3.98k
    util::free(out);
520
3.98k
    util::free(outTag);
521
522
3.98k
    return ret;
523
1.91k
}
524
525
}
526
527
3.98k
std::optional<component::Ciphertext> wolfCrypt_OpenSSL::OpSymmetricEncrypt(operation::SymmetricEncrypt& op) {
528
3.98k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
529
3.98k
    return wolfCrypt_OpenSSL_detail::OpSymmetricEncrypt_EVP(op, ds);
530
3.98k
}
531
532
namespace wolfCrypt_OpenSSL_detail {
533
534
3.23k
std::optional<component::Cleartext> OpSymmetricDecrypt_EVP(operation::SymmetricDecrypt& op, Datasource& ds) {
535
3.23k
    std::optional<component::Cleartext> ret = std::nullopt;
536
537
3.23k
    util::Multipart partsCiphertext, partsAAD;
538
539
3.23k
    const EVP_CIPHER* cipher = nullptr;
540
3.23k
    CF_EVP_CIPHER_CTX ctx(ds);
541
542
3.23k
    size_t out_size = op.cleartextSize;
543
3.23k
    size_t outIdx = 0;
544
3.23k
    uint8_t* out = util::malloc(out_size);
545
546
    /* Initialize */
547
3.23k
    {
548
3.23k
        CF_CHECK_NE(cipher = toEVPCIPHER(op.cipher.cipherType), nullptr);
549
2.56k
        if ( op.tag != std::nullopt || op.aad != std::nullopt ) {
550
            /* Trying to treat non-AEAD with AEAD-specific features (tag, aad)
551
             * leads to all kinds of gnarly memory bugs in OpenSSL.
552
             * It is quite arguably misuse of the OpenSSL API, so don't do this.
553
             */
554
529
            CF_CHECK_EQ(isAEAD(cipher), true);
555
482
        }
556
2.51k
        CF_CHECK_EQ(EVP_DecryptInit_ex(ctx.GetPtr(), cipher, nullptr, nullptr, nullptr), 1);
557
558
        /* Must be a multiple of the block size of this cipher */
559
        //CF_CHECK_EQ(op.ciphertext.GetSize() % EVP_CIPHER_block_size(cipher), 0);
560
561
        /* Convert ciphertext to parts */
562
        //partsCiphertext = util::CipherInputTransform(ds, op.cipher.cipherType, out, out_size, op.ciphertext.GetPtr(), op.ciphertext.GetSize());
563
2.51k
        partsCiphertext = { {op.ciphertext.GetPtr(), op.ciphertext.GetSize()} };
564
565
2.51k
        if ( op.aad != std::nullopt ) {
566
258
            if ( repository::IsCCM( op.cipher.cipherType.Get() ) ) {
567
                /* CCM does not support chunked AAD updating.
568
                 * See: https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Encryption_using_CCM_mode
569
                 */
570
0
                partsAAD = { {op.aad->GetPtr(), op.aad->GetSize()} };
571
258
            } else {
572
258
                partsAAD = util::ToParts(ds, *(op.aad));
573
258
            }
574
258
        }
575
576
2.51k
        if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) {
577
2.51k
            CF_CHECK_EQ(checkSetIVLength(op.cipher.cipherType.Get(), cipher, ctx.GetPtr(), op.cipher.iv.GetSize()), true);
578
2.30k
        } else {
579
0
            CF_CHECK_EQ(op.cipher.iv.GetSize(), 12);
580
0
        }
581
2.30k
        CF_CHECK_EQ(checkSetKeyLength(cipher, ctx.GetPtr(), op.cipher.key.GetSize()), true);
582
583
2.21k
        if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) {
584
2.21k
            CF_CHECK_EQ(EVP_DecryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), op.cipher.iv.GetPtr()), 1);
585
2.21k
        } else {
586
            /* Prepend the 32 bit counter (which is 0) to the iv */
587
0
            uint8_t cc20IV[16];
588
0
            memset(cc20IV, 0, 4);
589
0
            memcpy(cc20IV + 4, op.cipher.iv.GetPtr(), op.cipher.iv.GetSize());
590
0
            CF_CHECK_EQ(EVP_DecryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), cc20IV), 1);
591
0
        }
592
593
        /* Disable ECB padding for consistency with mbed TLS */
594
2.21k
        if ( repository::IsECB(op.cipher.cipherType.Get()) ) {
595
222
            CF_CHECK_EQ(EVP_CIPHER_CTX_set_padding(ctx.GetPtr(), 0), 1);
596
222
        }
597
2.21k
    }
598
599
    /* Process */
600
2.21k
    {
601
        /* If the cipher is CCM, the total cleartext size needs to be indicated explicitly
602
         * https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
603
         */
604
2.21k
        if ( repository::IsCCM(op.cipher.cipherType.Get()) == true ) {
605
0
            int len;
606
0
            CF_CHECK_EQ(EVP_DecryptUpdate(ctx.GetPtr(), nullptr, &len, nullptr, op.ciphertext.GetSize()), 1);
607
0
        }
608
609
        /* Set AAD */
610
2.21k
        if ( op.aad != std::nullopt ) {
611
1.78k
            for (const auto& part : partsAAD) {
612
1.78k
                int len;
613
1.78k
                CF_CHECK_EQ(EVP_DecryptUpdate(ctx.GetPtr(), nullptr, &len, part.first, part.second), 1);
614
1.78k
            }
615
185
        }
616
617
        /* Set ciphertext */
618
2.21k
        for (const auto& part : partsCiphertext) {
619
2.21k
            CF_CHECK_GTE(out_size, part.second + EVP_CIPHER_block_size(cipher));
620
621
2.17k
            int len = -1;
622
2.17k
            CF_CHECK_EQ(EVP_DecryptUpdate(ctx.GetPtr(), out + outIdx, &len, part.first, part.second), 1);
623
624
2.17k
            outIdx += len;
625
2.17k
            out_size -= len;
626
2.17k
        }
627
628
2.17k
        if ( op.tag != std::nullopt ) {
629
297
            CF_CHECK_EQ(EVP_CIPHER_CTX_ctrl(ctx.GetPtr(), EVP_CTRL_AEAD_SET_TAG, op.tag->GetSize(), (void*)op.tag->GetPtr()), 1);
630
267
        }
631
2.17k
    }
632
633
    /* Finalize */
634
2.14k
    {
635
2.14k
        CF_CHECK_GTE(out_size, static_cast<size_t>(EVP_CIPHER_block_size(cipher)));
636
637
2.14k
        int len = -1;
638
2.14k
        CF_CHECK_EQ(EVP_DecryptFinal_ex(ctx.GetPtr(), out + outIdx, &len), 1);
639
1.90k
        outIdx += len;
640
641
1.90k
        ret = component::Cleartext(out, outIdx);
642
1.90k
    }
643
644
3.23k
end:
645
646
3.23k
    util::free(out);
647
648
3.23k
    return ret;
649
1.90k
}
650
651
}
652
653
3.23k
std::optional<component::Cleartext> wolfCrypt_OpenSSL::OpSymmetricDecrypt(operation::SymmetricDecrypt& op) {
654
3.23k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
655
3.23k
    return wolfCrypt_OpenSSL_detail::OpSymmetricDecrypt_EVP(op, ds);
656
3.23k
}
657
658
1.14k
std::optional<component::MAC> wolfCrypt_OpenSSL::OpCMAC(operation::CMAC& op) {
659
1.14k
    std::optional<component::MAC> ret = std::nullopt;
660
1.14k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
661
662
1.14k
    util::Multipart parts;
663
664
1.14k
    CF_CMAC_CTX ctx(ds);
665
1.14k
    const EVP_CIPHER* cipher = nullptr;
666
667
    /* Initialize */
668
1.14k
    {
669
1.14k
        parts = util::ToParts(ds, op.cleartext);
670
671
1.14k
        CF_CHECK_NE(cipher = wolfCrypt_OpenSSL_detail::toEVPCIPHER(op.cipher.cipherType), nullptr);
672
477
        CF_CHECK_EQ(CMAC_Init(ctx.GetPtr(), op.cipher.key.GetPtr(), op.cipher.key.GetSize(), cipher, nullptr), 1);
673
245
    }
674
675
    /* Process */
676
2.06k
    for (const auto& part : parts) {
677
2.06k
        CF_CHECK_EQ(CMAC_Update(ctx.GetPtr(), part.first, part.second), 1);
678
2.06k
    }
679
680
    /* Finalize */
681
245
    {
682
245
        size_t len = 0;
683
245
        uint8_t out[EVP_MAX_MD_SIZE];
684
245
        CF_CHECK_EQ(CMAC_Final(ctx.GetPtr(), out, &len), 1);
685
245
        ret = component::MAC(out, len);
686
245
    }
687
688
1.14k
end:
689
1.14k
    return ret;
690
245
}
691
692
799
std::optional<component::Key> wolfCrypt_OpenSSL::OpKDF_HKDF(operation::KDF_HKDF& op) {
693
799
    std::optional<component::Key> ret = std::nullopt;
694
799
    EVP_PKEY_CTX* pctx = nullptr;
695
799
    const EVP_MD* md = nullptr;
696
697
799
    size_t out_size = op.keySize;
698
799
    uint8_t* out = util::malloc(out_size);
699
700
    /* Initialize */
701
799
    {
702
799
        CF_CHECK_NE(md = wolfCrypt_OpenSSL_detail::toEVPMD(op.digestType), nullptr);
703
689
        CF_CHECK_NE(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr), nullptr);
704
689
        CF_CHECK_EQ(EVP_PKEY_derive_init(pctx), 1);
705
689
        CF_CHECK_EQ(EVP_PKEY_CTX_set_hkdf_md(pctx, md), 1);
706
689
        CF_CHECK_EQ(EVP_PKEY_CTX_set1_hkdf_key(pctx, op.password.GetPtr(), op.password.GetSize()), 1);
707
568
        CF_CHECK_EQ(EVP_PKEY_CTX_set1_hkdf_salt(pctx, op.salt.GetPtr(), op.salt.GetSize()), 1);
708
568
        CF_CHECK_EQ(EVP_PKEY_CTX_add1_hkdf_info(pctx, op.info.GetPtr(), op.info.GetSize()), 1);
709
568
    }
710
711
    /* Process/finalize */
712
0
    {
713
568
        CF_CHECK_EQ(EVP_PKEY_derive(pctx, out, &out_size) , 1);
714
715
340
        CF_CHECK_NE(out, nullptr);
716
717
340
        ret = component::Key(out, out_size);
718
340
    }
719
720
799
end:
721
799
    EVP_PKEY_CTX_free(pctx);
722
723
799
    util::free(out);
724
725
799
    return ret;
726
340
}
727
728
601
std::optional<component::Key> wolfCrypt_OpenSSL::OpKDF_PBKDF2(operation::KDF_PBKDF2& op) {
729
601
    std::optional<component::Key> ret = std::nullopt;
730
601
    const EVP_MD* md = nullptr;
731
732
601
    const size_t outSize = op.keySize;
733
601
    uint8_t* out = util::malloc(outSize);
734
735
601
    CF_CHECK_NE(md = wolfCrypt_OpenSSL_detail::toEVPMD(op.digestType), nullptr);
736
504
    CF_CHECK_EQ(PKCS5_PBKDF2_HMAC(
737
504
                (const char*)(op.password.GetPtr()),
738
504
                op.password.GetSize(),
739
504
                op.salt.GetPtr(),
740
504
                op.salt.GetSize(),
741
504
                op.iterations,
742
504
                md,
743
504
                outSize,
744
504
                out), 1);
745
746
432
    ret = component::Key(out, outSize);
747
601
end:
748
601
    util::free(out);
749
750
601
    return ret;
751
432
}
752
753
3.99k
static std::optional<int> toCurveNID(const component::CurveType& curveType) {
754
3.99k
    static const std::map<uint64_t, int> LUT = {
755
3.99k
        { CF_ECC_CURVE("secp192r1"), NID_X9_62_prime192v1 },
756
3.99k
        { CF_ECC_CURVE("x962_p192v2"), NID_X9_62_prime192v2 },
757
3.99k
        { CF_ECC_CURVE("x962_p192v3"), NID_X9_62_prime192v3 },
758
3.99k
        { CF_ECC_CURVE("x962_p239v1"), NID_X9_62_prime239v1 },
759
3.99k
        { CF_ECC_CURVE("x962_p239v2"), NID_X9_62_prime239v2 },
760
3.99k
        { CF_ECC_CURVE("x962_p239v3"), NID_X9_62_prime239v3 },
761
3.99k
        { CF_ECC_CURVE("secp256r1"), NID_X9_62_prime256v1 },
762
3.99k
        { CF_ECC_CURVE("brainpool160r1"), NID_brainpoolP160r1 },
763
3.99k
        { CF_ECC_CURVE("brainpool192r1"), NID_brainpoolP192r1 },
764
3.99k
        { CF_ECC_CURVE("brainpool224r1"), NID_brainpoolP224r1 },
765
3.99k
        { CF_ECC_CURVE("brainpool256r1"), NID_brainpoolP256r1 },
766
3.99k
        { CF_ECC_CURVE("brainpool320r1"), NID_brainpoolP320r1 },
767
3.99k
        { CF_ECC_CURVE("brainpool384r1"), NID_brainpoolP384r1 },
768
3.99k
        { CF_ECC_CURVE("brainpool512r1"), NID_brainpoolP512r1 },
769
3.99k
        { CF_ECC_CURVE("secp112r1"), NID_secp112r1 },
770
3.99k
        { CF_ECC_CURVE("secp112r2"), NID_secp112r2 },
771
3.99k
        { CF_ECC_CURVE("secp128r1"), NID_secp128r1 },
772
3.99k
        { CF_ECC_CURVE("secp128r2"), NID_secp128r2 },
773
3.99k
        { CF_ECC_CURVE("secp160k1"), NID_secp160k1 },
774
3.99k
        { CF_ECC_CURVE("secp160r1"), NID_secp160r1 },
775
3.99k
        { CF_ECC_CURVE("secp160r2"), NID_secp160r2 },
776
3.99k
        { CF_ECC_CURVE("secp192k1"), NID_secp192k1 },
777
3.99k
        { CF_ECC_CURVE("secp224k1"), NID_secp224k1 },
778
3.99k
        { CF_ECC_CURVE("secp224r1"), NID_secp224r1 },
779
3.99k
        { CF_ECC_CURVE("secp256k1"), NID_secp256k1 },
780
3.99k
        { CF_ECC_CURVE("secp384r1"), NID_secp384r1 },
781
3.99k
        { CF_ECC_CURVE("secp521r1"), NID_secp521r1 },
782
3.99k
    };
783
784
3.99k
    if ( LUT.find(curveType.Get()) == LUT.end() ) {
785
353
        return std::nullopt;
786
353
    }
787
788
3.64k
    return LUT.at(curveType.Get());
789
3.99k
}
790
791
235
std::optional<bool> wolfCrypt_OpenSSL::OpECC_ValidatePubkey(operation::ECC_ValidatePubkey& op) {
792
235
    std::optional<bool> ret = std::nullopt;
793
235
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
794
795
235
    CF_EC_KEY key(ds);
796
235
    std::shared_ptr<CF_EC_GROUP> group = nullptr;
797
798
235
    std::unique_ptr<CF_EC_POINT> pub = nullptr;
799
800
235
    {
801
235
        std::optional<int> curveNID;
802
235
        CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt);
803
168
        CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr);
804
168
        group->Lock();
805
168
        CF_CHECK_NE(group->GetPtr(), nullptr);
806
168
    }
807
808
168
    CF_CHECK_EQ(EC_KEY_set_group(key.GetPtr(), group->GetPtr()), 1);
809
810
    /* Construct key */
811
168
    CF_CHECK_NE(pub = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
812
168
    CF_CHECK_TRUE(pub->Set(op.pub.first, op.pub.second));
813
814
    /* Reject oversized pubkeys until it is fixed in OpenSSL
815
     * https://github.com/openssl/openssl/issues/17590
816
     */
817
#if 0
818
    {
819
        const auto order = cryptofuzz::repository::ECC_CurveToOrder(op.curveType.Get());
820
        CF_CHECK_NE(order, std::nullopt);
821
        CF_CHECK_TRUE(op.pub.first.IsLessThan(*order));
822
        CF_CHECK_TRUE(op.pub.second.IsLessThan(*order));
823
    }
824
#endif
825
826
15
    ret = EC_KEY_set_public_key(key.GetPtr(), pub->GetPtr()) == 1;
827
235
end:
828
235
    return ret;
829
15
}
830
831
814
std::optional<component::ECC_PublicKey> wolfCrypt_OpenSSL::OpECC_PrivateToPublic(operation::ECC_PrivateToPublic& op) {
832
814
    std::optional<component::ECC_PublicKey> ret = std::nullopt;
833
814
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
834
835
814
    char* pub_x_str = nullptr;
836
814
    char* pub_y_str = nullptr;
837
838
814
    try {
839
814
        CF_EC_KEY key(ds);
840
814
        std::shared_ptr<CF_EC_GROUP> group = nullptr;
841
814
        OpenSSL_bignum::Bignum prv(ds);
842
814
        std::unique_ptr<CF_EC_POINT> pub = nullptr;
843
814
        OpenSSL_bignum::Bignum pub_x(ds);
844
814
        OpenSSL_bignum::Bignum pub_y(ds);
845
846
814
        {
847
814
            std::optional<int> curveNID;
848
814
            CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt);
849
718
            CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr);
850
718
            group->Lock();
851
718
            CF_CHECK_NE(group->GetPtr(), nullptr);
852
718
        }
853
854
718
        CF_CHECK_EQ(EC_KEY_set_group(key.GetPtr(), group->GetPtr()), 1);
855
856
        /* Load private key */
857
718
        CF_CHECK_EQ(prv.Set(op.priv.ToString(ds)), true);
858
859
        /* Set private key */
860
697
        CF_CHECK_EQ(EC_KEY_set_private_key(key.GetPtr(), prv.GetPtr()), 1);
861
862
        /* Compute public key */
863
635
        CF_CHECK_NE(pub = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
864
635
        CF_CHECK_EQ(EC_POINT_mul(group->GetPtr(), pub->GetPtr(), prv.GetPtr(), nullptr, nullptr, nullptr), 1);
865
866
603
        CF_CHECK_EQ(pub_x.New(), true);
867
603
        CF_CHECK_EQ(pub_y.New(), true);
868
869
603
        CF_CHECK_NE(EC_POINT_get_affine_coordinates(group->GetPtr(), pub->GetPtr(), pub_x.GetDestPtr(), pub_y.GetDestPtr(), nullptr), 0);
870
871
        /* Convert bignum x/y to strings */
872
570
        CF_CHECK_NE(pub_x_str = BN_bn2dec(pub_x.GetPtr()), nullptr);
873
570
        CF_CHECK_NE(pub_y_str = BN_bn2dec(pub_y.GetPtr()), nullptr);
874
875
        /* Save bignum x/y */
876
570
        ret = { std::string(pub_x_str), std::string(pub_y_str) };
877
570
    } catch ( ... ) { }
878
879
814
end:
880
814
    OPENSSL_free(pub_x_str);
881
814
    OPENSSL_free(pub_y_str);
882
883
814
    return ret;
884
814
}
885
886
195
std::optional<component::ECC_Point> wolfCrypt_OpenSSL::OpECC_Point_Add(operation::ECC_Point_Add& op) {
887
195
    std::optional<component::ECC_Point> ret = std::nullopt;
888
195
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
889
890
195
    std::shared_ptr<CF_EC_GROUP> group = nullptr;
891
195
    std::unique_ptr<CF_EC_POINT> a = nullptr, b = nullptr, res = nullptr;
892
195
    char* x_str = nullptr;
893
195
    char* y_str = nullptr;
894
895
195
    {
896
195
        std::optional<int> curveNID;
897
195
        CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt);
898
161
        CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr);
899
161
        group->Lock();
900
161
        CF_CHECK_NE(group->GetPtr(), nullptr);
901
161
    }
902
903
161
    CF_CHECK_NE(a = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
904
161
    CF_CHECK_TRUE(a->Set(op.a.first, op.a.second));
905
906
100
    CF_CHECK_NE(b = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
907
100
    CF_CHECK_TRUE(b->Set(op.b.first, op.b.second));
908
909
77
    CF_CHECK_NE(res = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
910
911
77
    CF_CHECK_NE(EC_POINT_add(group->GetPtr(), res->GetPtr(), a->GetPtr(), b->GetPtr(), nullptr), 0);
912
913
77
    {
914
77
        OpenSSL_bignum::Bignum x(ds);
915
77
        OpenSSL_bignum::Bignum y(ds);
916
917
77
        CF_CHECK_EQ(x.New(), true);
918
77
        CF_CHECK_EQ(y.New(), true);
919
920
77
        CF_CHECK_NE(EC_POINT_get_affine_coordinates(group->GetPtr(), res->GetPtr(), x.GetDestPtr(), y.GetDestPtr(), nullptr), 0);
921
922
        /* Convert bignum x/y to strings */
923
71
        CF_CHECK_NE(x_str = BN_bn2dec(x.GetPtr()), nullptr);
924
71
        CF_CHECK_NE(y_str = BN_bn2dec(y.GetPtr()), nullptr);
925
926
71
        ret = { std::string(x_str), std::string(y_str) };
927
71
    }
928
929
195
end:
930
195
    OPENSSL_free(x_str);
931
195
    OPENSSL_free(y_str);
932
933
195
    return ret;
934
71
}
935
936
233
std::optional<component::ECC_Point> wolfCrypt_OpenSSL::OpECC_Point_Mul(operation::ECC_Point_Mul& op) {
937
233
    std::optional<component::ECC_Point> ret = std::nullopt;
938
233
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
939
940
233
    std::shared_ptr<CF_EC_GROUP> group = nullptr;
941
233
    std::unique_ptr<CF_EC_POINT> a = nullptr, res = nullptr;
942
233
    OpenSSL_bignum::Bignum b(ds);
943
233
    char* x_str = nullptr;
944
233
    char* y_str = nullptr;
945
946
233
    {
947
233
        std::optional<int> curveNID;
948
233
        CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt);
949
202
        CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr);
950
202
        group->Lock();
951
202
        CF_CHECK_NE(group->GetPtr(), nullptr);
952
202
    }
953
954
202
    CF_CHECK_NE(a = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
955
202
    CF_CHECK_TRUE(a->Set(op.a.first, op.a.second));
956
957
158
    CF_CHECK_NE(res = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
958
959
158
    CF_CHECK_EQ(b.Set(op.b.ToString(ds)), true);
960
961
143
    CF_CHECK_NE(EC_POINT_mul(group->GetPtr(), res->GetPtr(), nullptr, a->GetPtr(), b.GetPtr(), nullptr), 0);
962
963
128
    if ( op.b.ToTrimmedString() == "0" ) {
964
10
        CF_ASSERT(
965
10
                EC_POINT_is_at_infinity(group->GetPtr(), res->GetPtr()) == 1,
966
10
                "Point multiplication by 0 does not yield point at infinity");
967
10
    }
968
969
128
    {
970
128
        OpenSSL_bignum::BN_CTX ctx(ds);
971
972
128
        if ( !EC_POINT_is_on_curve(group->GetPtr(), a->GetPtr(), ctx.GetPtr()) ) {
973
0
            CF_ASSERT(
974
0
                    EC_POINT_is_on_curve(group->GetPtr(), res->GetPtr(), ctx.GetPtr()) == 0,
975
0
                    "Point multiplication of invalid point yields valid point");
976
0
        }
977
128
    }
978
979
128
    ret = res->Get();
980
981
233
end:
982
233
    OPENSSL_free(x_str);
983
233
    OPENSSL_free(y_str);
984
985
233
    return ret;
986
128
}
987
988
289
std::optional<component::ECC_Point> wolfCrypt_OpenSSL::OpECC_Point_Neg(operation::ECC_Point_Neg& op) {
989
289
    std::optional<component::ECC_Point> ret = std::nullopt;
990
289
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
991
992
289
    std::shared_ptr<CF_EC_GROUP> group = nullptr;
993
289
    std::unique_ptr<CF_EC_POINT> a = nullptr, res = nullptr;
994
289
    char* x_str = nullptr;
995
289
    char* y_str = nullptr;
996
997
289
    {
998
289
        std::optional<int> curveNID;
999
289
        CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt);
1000
246
        CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr);
1001
246
        group->Lock();
1002
246
        CF_CHECK_NE(group->GetPtr(), nullptr);
1003
246
    }
1004
1005
246
    CF_CHECK_NE(a = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
1006
246
    CF_CHECK_TRUE(a->Set(op.a.first, op.a.second));
1007
1008
48
    CF_CHECK_NE(EC_POINT_invert(group->GetPtr(), a->GetPtr(), nullptr), 0);
1009
1010
48
    {
1011
48
        OpenSSL_bignum::Bignum x(ds);
1012
48
        OpenSSL_bignum::Bignum y(ds);
1013
1014
48
        CF_CHECK_EQ(x.New(), true);
1015
48
        CF_CHECK_EQ(y.New(), true);
1016
1017
48
        CF_CHECK_NE(EC_POINT_get_affine_coordinates(group->GetPtr(), a->GetPtr(), x.GetDestPtr(), y.GetDestPtr(), nullptr), 0);
1018
1019
        /* Convert bignum x/y to strings */
1020
48
        CF_CHECK_NE(x_str = BN_bn2dec(x.GetPtr()), nullptr);
1021
48
        CF_CHECK_NE(y_str = BN_bn2dec(y.GetPtr()), nullptr);
1022
1023
48
        ret = { std::string(x_str), std::string(y_str) };
1024
48
    }
1025
1026
289
end:
1027
289
    OPENSSL_free(x_str);
1028
289
    OPENSSL_free(y_str);
1029
1030
289
    return ret;
1031
48
}
1032
1033
142
std::optional<bool> wolfCrypt_OpenSSL::OpECC_Point_Cmp(operation::ECC_Point_Cmp& op) {
1034
142
    std::optional<bool> ret = std::nullopt;
1035
142
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1036
1037
142
    std::shared_ptr<CF_EC_GROUP> group = nullptr;
1038
142
    std::unique_ptr<CF_EC_POINT> a = nullptr, b = nullptr;
1039
1040
142
    {
1041
142
        std::optional<int> curveNID;
1042
142
        CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt);
1043
106
        CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr);
1044
106
        group->Lock();
1045
106
        CF_CHECK_NE(group->GetPtr(), nullptr);
1046
106
    }
1047
1048
106
    CF_CHECK_NE(a = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
1049
106
    CF_CHECK_TRUE(a->Set(op.a.first, op.a.second));
1050
1051
57
    CF_CHECK_NE(b = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
1052
57
    CF_CHECK_TRUE(b->Set(op.b.first, op.b.second));
1053
1054
43
    ret = EC_POINT_cmp(group->GetPtr(), a->GetPtr(), b->GetPtr(), nullptr) == 0;
1055
1056
142
end:
1057
1058
142
    return ret;
1059
43
}
1060
1061
1.10k
std::optional<bool> wolfCrypt_OpenSSL::OpECDSA_Verify(operation::ECDSA_Verify& op) {
1062
1.10k
    std::optional<bool> ret = std::nullopt;
1063
1.10k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1064
1065
1.10k
    ECDSA_SIG* signature = nullptr;
1066
1067
1.10k
    try {
1068
1.10k
        CF_EC_KEY key(ds);
1069
1.10k
        std::shared_ptr<CF_EC_GROUP> group = nullptr;
1070
1071
1.10k
        std::unique_ptr<CF_EC_POINT> pub = nullptr;
1072
1073
1.10k
        OpenSSL_bignum::Bignum sig_s(ds);
1074
1.10k
        OpenSSL_bignum::Bignum sig_r(ds);
1075
1076
        /* Initialize */
1077
1.10k
        {
1078
1.10k
            {
1079
1.10k
                std::optional<int> curveNID;
1080
1.10k
                CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt);
1081
1.07k
                CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr);
1082
1.07k
                group->Lock();
1083
1.07k
                CF_CHECK_NE(group->GetPtr(), nullptr);
1084
1.07k
            }
1085
1.07k
            CF_CHECK_EQ(EC_KEY_set_group(key.GetPtr(), group->GetPtr()), 1);
1086
1087
            /* Construct signature */
1088
1.07k
            CF_CHECK_EQ(sig_r.Set(op.signature.signature.first.ToString(ds)), true);
1089
1.06k
            CF_CHECK_EQ(sig_s.Set(op.signature.signature.second.ToString(ds)), true);
1090
1.05k
            CF_CHECK_NE(signature = ECDSA_SIG_new(), nullptr);
1091
1.05k
            CF_CHECK_EQ(ECDSA_SIG_set0(signature, sig_r.GetDestPtr(false), sig_s.GetDestPtr(false)), 1);
1092
            /* 'signature' now has ownership, and the BIGNUMs will be freed by ECDSA_SIG_free */
1093
1.05k
            sig_r.ReleaseOwnership();
1094
1.05k
            sig_s.ReleaseOwnership();
1095
1096
            /* Construct key */
1097
1.05k
            CF_CHECK_NE(pub = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
1098
1.05k
            CF_CHECK_TRUE(pub->Set(op.signature.pub.first, op.signature.pub.second));
1099
1.03k
            CF_CHECK_EQ(EC_KEY_set_public_key(key.GetPtr(), pub->GetPtr()), 1);
1100
1.03k
        }
1101
1102
        /* Process */
1103
0
        {
1104
1.03k
            int res;
1105
1.03k
            if ( op.digestType.Get() == CF_DIGEST("NULL") ) {
1106
                //const auto CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType);
1107
941
                const auto CT = op.cleartext;
1108
941
                res = ECDSA_do_verify(CT.GetPtr(), CT.GetSize(), signature, key.GetPtr());
1109
941
            } else if ( op.digestType.Get() == CF_DIGEST("SHA256") ) {
1110
47
                uint8_t CT[32];
1111
47
                SHA256(op.cleartext.GetPtr(), op.cleartext.GetSize(), CT);
1112
47
                res = ECDSA_do_verify(CT, sizeof(CT), signature, key.GetPtr());
1113
49
            } else {
1114
                /* TODO other digests */
1115
49
                goto end;
1116
49
            }
1117
1118
988
            if ( res == 0 ) {
1119
76
                ret = false;
1120
912
            } else if ( res == 1 ) {
1121
848
                ret = true;
1122
848
            } else {
1123
                /* ECDSA_do_verify failed -- don't set ret */
1124
64
            }
1125
1126
988
        }
1127
988
    } catch ( ... ) { }
1128
1129
1.10k
end:
1130
1.10k
    if ( signature != nullptr ) {
1131
1.05k
        ECDSA_SIG_free(signature);
1132
1.05k
    }
1133
1134
1.10k
    return ret;
1135
1.10k
}
1136
1137
1.08k
std::optional<component::ECDSA_Signature> wolfCrypt_OpenSSL::OpECDSA_Sign(operation::ECDSA_Sign& op) {
1138
1.08k
    std::optional<component::ECDSA_Signature> ret = std::nullopt;
1139
1.08k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1140
1141
1.08k
    ECDSA_SIG* signature = nullptr;
1142
1.08k
    char* pub_x_str = nullptr;
1143
1.08k
    char* pub_y_str = nullptr;
1144
1.08k
    char* sig_r_str = nullptr;
1145
1.08k
    char* sig_s_str = nullptr;
1146
1147
1.08k
    try {
1148
1.08k
        CF_EC_KEY key(ds);
1149
1.08k
        std::shared_ptr<CF_EC_GROUP> group = nullptr;
1150
1.08k
        OpenSSL_bignum::Bignum prv(ds);
1151
1.08k
        std::unique_ptr<CF_EC_POINT> pub = nullptr;
1152
1.08k
        OpenSSL_bignum::Bignum pub_x(ds);
1153
1.08k
        OpenSSL_bignum::Bignum pub_y(ds);
1154
1.08k
        const BIGNUM *R = nullptr, *S = nullptr;
1155
1156
1.08k
        CF_CHECK_TRUE(op.UseRandomNonce());
1157
1.05k
        CF_CHECK_TRUE(op.digestType.Is(CF_DIGEST("NULL")));
1158
1159
980
        {
1160
980
            std::optional<int> curveNID;
1161
980
            CF_CHECK_NE(curveNID = toCurveNID(op.curveType), std::nullopt);
1162
964
            CF_CHECK_NE(group = std::make_shared<CF_EC_GROUP>(ds, *curveNID), nullptr);
1163
964
            group->Lock();
1164
964
            CF_CHECK_NE(group->GetPtr(), nullptr);
1165
964
        }
1166
1167
964
        CF_CHECK_EQ(EC_KEY_set_group(key.GetPtr(), group->GetPtr()), 1);
1168
1169
        /* Load private key */
1170
964
        CF_CHECK_EQ(prv.Set(op.priv.ToString(ds)), true);
1171
1172
        /* Set private key */
1173
954
        CF_CHECK_EQ(EC_KEY_set_private_key(key.GetPtr(), prv.GetPtr()), 1);
1174
1175
        /* Compute public key */
1176
939
        CF_CHECK_NE(pub = std::make_unique<CF_EC_POINT>(ds, group), nullptr);
1177
939
        CF_CHECK_EQ(EC_POINT_mul(group->GetPtr(), pub->GetPtr(), prv.GetPtr(), nullptr, nullptr, nullptr), 1);
1178
1179
929
        CF_CHECK_EQ(pub_x.New(), true);
1180
929
        CF_CHECK_EQ(pub_y.New(), true);
1181
1182
929
        CF_CHECK_NE(EC_POINT_get_affine_coordinates(group->GetPtr(), pub->GetPtr(), pub_x.GetDestPtr(), pub_y.GetDestPtr(), nullptr), 0);
1183
1184
915
        CF_CHECK_NE(pub_x_str = BN_bn2dec(pub_x.GetPtr()), nullptr);
1185
915
        CF_CHECK_NE(pub_y_str = BN_bn2dec(pub_y.GetPtr()), nullptr);
1186
1187
915
        const auto CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType);
1188
1189
915
        CF_CHECK_NE(signature = ECDSA_do_sign(CT.GetPtr(), CT.GetSize(), key.GetPtr()), nullptr);
1190
1191
817
        /* noret */ ECDSA_SIG_get0(signature, &R, &S);
1192
817
        CF_CHECK_NE(R, nullptr);
1193
817
        CF_CHECK_NE(S, nullptr);
1194
1195
        /* Convert bignum x/y to strings */
1196
817
        CF_CHECK_NE(sig_r_str = BN_bn2dec(R), nullptr);
1197
817
        CF_CHECK_NE(sig_s_str = BN_bn2dec(S), nullptr);
1198
1199
1200
817
        component::Bignum S_corrected{std::string(sig_s_str)};
1201
817
        CF_NORET(util::AdjustECDSASignature(op.curveType.Get(), S_corrected));
1202
1203
817
        ret = { {sig_r_str, S_corrected.ToTrimmedString()}, {pub_x_str, pub_y_str} };
1204
817
    } catch ( ... ) { }
1205
1206
1.08k
end:
1207
1.08k
    if ( signature != nullptr ) {
1208
817
        ECDSA_SIG_free(signature);
1209
817
    }
1210
1.08k
    OPENSSL_free(pub_x_str);
1211
1.08k
    OPENSSL_free(pub_y_str);
1212
1.08k
    OPENSSL_free(sig_r_str);
1213
1.08k
    OPENSSL_free(sig_s_str);
1214
1215
1.08k
    return ret;
1216
1.08k
}
1217
1218
2.92k
std::optional<component::Bignum> wolfCrypt_OpenSSL::OpBignumCalc(operation::BignumCalc& op) {
1219
2.92k
    std::optional<component::Bignum> ret = std::nullopt;
1220
2.92k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
1221
1222
2.92k
    OpenSSL_bignum::BN_CTX ctx(ds);
1223
2.92k
    OpenSSL_bignum::BignumCluster bn(ds,
1224
2.92k
        OpenSSL_bignum::Bignum(ds),
1225
2.92k
        OpenSSL_bignum::Bignum(ds),
1226
2.92k
        OpenSSL_bignum::Bignum(ds),
1227
2.92k
        OpenSSL_bignum::Bignum(ds));
1228
2.92k
    OpenSSL_bignum::Bignum res(ds);
1229
2.92k
    std::unique_ptr<OpenSSL_bignum::Operation> opRunner = nullptr;
1230
1231
2.92k
    CF_CHECK_EQ(res.New(), true);
1232
2.92k
    CF_CHECK_EQ(bn.New(0), true);
1233
2.92k
    CF_CHECK_EQ(bn.New(1), true);
1234
2.92k
    CF_CHECK_EQ(bn.New(2), true);
1235
2.92k
    CF_CHECK_EQ(bn.New(3), true);
1236
1237
2.92k
    CF_CHECK_EQ(res.Set("0"), true);
1238
2.92k
    CF_CHECK_EQ(bn.Set(0, op.bn0.ToString(ds)), true);
1239
2.91k
    CF_CHECK_EQ(bn.Set(1, op.bn1.ToString(ds)), true);
1240
2.90k
    CF_CHECK_EQ(bn.Set(2, op.bn2.ToString(ds)), true);
1241
2.88k
    CF_CHECK_EQ(bn.Set(3, op.bn3.ToString(ds)), true);
1242
1243
2.88k
    switch ( op.calcOp.Get() ) {
1244
27
        case    CF_CALCOP("Add(A,B)"):
1245
27
            opRunner = std::make_unique<OpenSSL_bignum::Add>();
1246
27
            break;
1247
26
        case    CF_CALCOP("Sub(A,B)"):
1248
26
            opRunner = std::make_unique<OpenSSL_bignum::Sub>();
1249
26
            break;
1250
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1251
        case    CF_CALCOP("Mul(A,B)"):
1252
            opRunner = std::make_unique<OpenSSL_bignum::Mul>();
1253
            break;
1254
#endif
1255
34
        case    CF_CALCOP("Mod(A,B)"):
1256
34
            opRunner = std::make_unique<OpenSSL_bignum::Mod>();
1257
34
            break;
1258
230
        case    CF_CALCOP("ExpMod(A,B,C)"):
1259
230
            opRunner = std::make_unique<OpenSSL_bignum::ExpMod>();
1260
230
            break;
1261
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1262
        case    CF_CALCOP("Sqr(A)"):
1263
            opRunner = std::make_unique<OpenSSL_bignum::Sqr>();
1264
            break;
1265
#endif
1266
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1267
        case    CF_CALCOP("GCD(A,B)"):
1268
            opRunner = std::make_unique<OpenSSL_bignum::GCD>();
1269
            break;
1270
#endif
1271
48
        case    CF_CALCOP("AddMod(A,B,C)"):
1272
48
            opRunner = std::make_unique<OpenSSL_bignum::AddMod>();
1273
48
            break;
1274
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1275
        case    CF_CALCOP("SubMod(A,B,C)"):
1276
            opRunner = std::make_unique<OpenSSL_bignum::SubMod>();
1277
            break;
1278
#endif
1279
50
        case    CF_CALCOP("MulMod(A,B,C)"):
1280
50
            opRunner = std::make_unique<OpenSSL_bignum::MulMod>();
1281
50
            break;
1282
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1283
        case    CF_CALCOP("SqrMod(A,B)"):
1284
            opRunner = std::make_unique<OpenSSL_bignum::SqrMod>();
1285
            break;
1286
#endif
1287
203
        case    CF_CALCOP("InvMod(A,B)"):
1288
203
            opRunner = std::make_unique<OpenSSL_bignum::InvMod>();
1289
203
            break;
1290
33
        case    CF_CALCOP("Cmp(A,B)"):
1291
33
            opRunner = std::make_unique<OpenSSL_bignum::Cmp>();
1292
33
            break;
1293
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1294
        case    CF_CALCOP("Div(A,B)"):
1295
            opRunner = std::make_unique<OpenSSL_bignum::Div>();
1296
            break;
1297
#endif
1298
15
        case    CF_CALCOP("IsPrime(A)"):
1299
15
            opRunner = std::make_unique<OpenSSL_bignum::IsPrime>();
1300
15
            break;
1301
10
        case    CF_CALCOP("Sqrt(A)"):
1302
10
            opRunner = std::make_unique<OpenSSL_bignum::Sqrt>();
1303
10
            break;
1304
10
        case    CF_CALCOP("IsNeg(A)"):
1305
10
            opRunner = std::make_unique<OpenSSL_bignum::IsNeg>();
1306
10
            break;
1307
12
        case    CF_CALCOP("IsEq(A,B)"):
1308
12
            opRunner = std::make_unique<OpenSSL_bignum::IsEq>();
1309
12
            break;
1310
8
        case    CF_CALCOP("IsEven(A)"):
1311
8
            opRunner = std::make_unique<OpenSSL_bignum::IsEven>();
1312
8
            break;
1313
21
        case    CF_CALCOP("IsOdd(A)"):
1314
21
            opRunner = std::make_unique<OpenSSL_bignum::IsOdd>();
1315
21
            break;
1316
40
        case    CF_CALCOP("IsZero(A)"):
1317
40
            opRunner = std::make_unique<OpenSSL_bignum::IsZero>();
1318
40
            break;
1319
41
        case    CF_CALCOP("IsOne(A)"):
1320
41
            opRunner = std::make_unique<OpenSSL_bignum::IsOne>();
1321
41
            break;
1322
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1323
        case    CF_CALCOP("Jacobi(A,B)"):
1324
            opRunner = std::make_unique<OpenSSL_bignum::Jacobi>();
1325
            break;
1326
#endif
1327
#if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1328
        case    CF_CALCOP("Mod_NIST_192(A)"):
1329
            opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_192>();
1330
            break;
1331
        case    CF_CALCOP("Mod_NIST_224(A)"):
1332
            opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_224>();
1333
            break;
1334
        case    CF_CALCOP("Mod_NIST_256(A)"):
1335
            opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_256>();
1336
            break;
1337
        case    CF_CALCOP("Mod_NIST_384(A)"):
1338
            opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_384>();
1339
            break;
1340
        case    CF_CALCOP("Mod_NIST_521(A)"):
1341
            opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_521>();
1342
            break;
1343
#endif
1344
10
        case    CF_CALCOP("SqrtMod(A,B)"):
1345
10
            opRunner = std::make_unique<OpenSSL_bignum::SqrtMod>();
1346
10
            break;
1347
#if defined(CRYPTOFUZZ_BORINGSSL)
1348
        case    CF_CALCOP("LCM(A,B)"):
1349
            opRunner = std::make_unique<OpenSSL_bignum::LCM>();
1350
            break;
1351
#endif
1352
3
        case    CF_CALCOP("Exp(A,B)"):
1353
3
            opRunner = std::make_unique<OpenSSL_bignum::Exp>();
1354
3
            break;
1355
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1356
        case    CF_CALCOP("Abs(A)"):
1357
            opRunner = std::make_unique<OpenSSL_bignum::Abs>();
1358
            break;
1359
#endif
1360
19
        case    CF_CALCOP("RShift(A,B)"):
1361
19
            opRunner = std::make_unique<OpenSSL_bignum::RShift>();
1362
19
            break;
1363
10
        case    CF_CALCOP("LShift1(A)"):
1364
10
            opRunner = std::make_unique<OpenSSL_bignum::LShift1>();
1365
10
            break;
1366
16
        case    CF_CALCOP("SetBit(A,B)"):
1367
16
            opRunner = std::make_unique<OpenSSL_bignum::SetBit>();
1368
16
            break;
1369
28
        case    CF_CALCOP("ClearBit(A,B)"):
1370
28
            opRunner = std::make_unique<OpenSSL_bignum::ClearBit>();
1371
28
            break;
1372
13
        case    CF_CALCOP("Bit(A,B)"):
1373
13
            opRunner = std::make_unique<OpenSSL_bignum::Bit>();
1374
13
            break;
1375
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1376
        case    CF_CALCOP("CmpAbs(A,B)"):
1377
            opRunner = std::make_unique<OpenSSL_bignum::CmpAbs>();
1378
            break;
1379
#endif
1380
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
1381
        case    CF_CALCOP("ModLShift(A,B,C)"):
1382
            opRunner = std::make_unique<OpenSSL_bignum::ModLShift>();
1383
            break;
1384
#endif
1385
10
        case    CF_CALCOP("IsPow2(A)"):
1386
10
            opRunner = std::make_unique<OpenSSL_bignum::IsPow2>();
1387
10
            break;
1388
14
        case    CF_CALCOP("Mask(A,B)"):
1389
14
            opRunner = std::make_unique<OpenSSL_bignum::Mask>();
1390
14
            break;
1391
2.88k
    }
1392
1393
2.88k
    CF_CHECK_NE(opRunner, nullptr);
1394
931
    CF_CHECK_EQ(opRunner->Run(ds, res, bn, ctx), true);
1395
1396
555
    ret = res.ToComponentBignum();
1397
1398
2.90k
end:
1399
2.90k
    return ret;
1400
555
}
1401
1402
} /* namespace module */
1403
} /* namespace cryptofuzz */