Coverage Report

Created: 2022-08-24 06:37

/src/cryptofuzz-openssl-api/modules/wolfcrypt-openssl/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 <fuzzing/datasource/id.hpp>
5
#include "bn_ops.h"
6
extern "C" {
7
#include <wolfssl/openssl/hmac.h>
8
}
9
#include "module_internal.h"
10
11
namespace cryptofuzz {
12
namespace module {
13
14
wolfCrypt_OpenSSL::wolfCrypt_OpenSSL(void) :
15
2
    Module("wolfCrypt-OpenSSL") {
16
2
}
17
18
namespace wolfCrypt_OpenSSL_detail {
19
1.42k
    const EVP_MD* toEVPMD(const component::DigestType& digestType) {
20
1.42k
        using fuzzing::datasource::ID;
21
22
1.42k
        static const std::map<uint64_t, const EVP_MD*> LUT = {
23
#if defined(CRYPTOFUZZ_BORINGSSL)
24
            { CF_DIGEST("SHA1"), EVP_sha1() },
25
            { CF_DIGEST("SHA224"), EVP_sha224() },
26
            { CF_DIGEST("SHA256"), EVP_sha256() },
27
            { CF_DIGEST("SHA384"), EVP_sha384() },
28
            { CF_DIGEST("SHA512"), EVP_sha512() },
29
            { CF_DIGEST("MD4"), EVP_md4() },
30
            { CF_DIGEST("MD5"), EVP_md5() },
31
            { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() },
32
            { CF_DIGEST("SHA512-256"), EVP_sha512_256() },
33
#elif defined(CRYPTOFUZZ_LIBRESSL)
34
            { CF_DIGEST("SHA1"), EVP_sha1() },
35
            { CF_DIGEST("SHA224"), EVP_sha224() },
36
            { CF_DIGEST("SHA256"), EVP_sha256() },
37
            { CF_DIGEST("SHA384"), EVP_sha384() },
38
            { CF_DIGEST("SHA512"), EVP_sha512() },
39
            { CF_DIGEST("MD4"), EVP_md4() },
40
            { CF_DIGEST("MD5"), EVP_md5() },
41
            { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() },
42
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
43
            { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() },
44
            { CF_DIGEST("SM3"), EVP_sm3() },
45
            { CF_DIGEST("GOST-R-34.11-94"), EVP_gostr341194() },
46
            { CF_DIGEST("GOST-28147-89"), EVP_gost2814789imit() },
47
            { CF_DIGEST("STREEBOG-256"), EVP_streebog256() },
48
            { CF_DIGEST("STREEBOG-512"), EVP_streebog512() },
49
#elif defined(CRYPTOFUZZ_OPENSSL_102)
50
            { CF_DIGEST("SHA1"), EVP_sha1() },
51
            { CF_DIGEST("SHA224"), EVP_sha224() },
52
            { CF_DIGEST("SHA256"), EVP_sha256() },
53
            { CF_DIGEST("SHA384"), EVP_sha384() },
54
            { CF_DIGEST("SHA512"), EVP_sha512() },
55
            { CF_DIGEST("MD2"), EVP_md2() },
56
            { CF_DIGEST("MD4"), EVP_md4() },
57
            { CF_DIGEST("MD5"), EVP_md5() },
58
            { CF_DIGEST("MDC2"), EVP_mdc2() },
59
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
60
            { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() },
61
#elif defined(CRYPTOFUZZ_OPENSSL_110)
62
            { CF_DIGEST("SHA1"), EVP_sha1() },
63
            { CF_DIGEST("SHA224"), EVP_sha224() },
64
            { CF_DIGEST("SHA256"), EVP_sha256() },
65
            { CF_DIGEST("SHA384"), EVP_sha384() },
66
            { CF_DIGEST("SHA512"), EVP_sha512() },
67
            { CF_DIGEST("MD2"), EVP_md2() },
68
            { CF_DIGEST("MD4"), EVP_md4() },
69
            { CF_DIGEST("MD5"), EVP_md5() },
70
            { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() },
71
            { CF_DIGEST("MDC2"), EVP_mdc2() },
72
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
73
            { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() },
74
            { CF_DIGEST("BLAKE2B512"), EVP_blake2b512() },
75
            { CF_DIGEST("BLAKE2S256"), EVP_blake2s256() },
76
#elif defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
77
1.42k
            { CF_DIGEST("SHA1"), EVP_sha1() },
78
1.42k
            { CF_DIGEST("MDC2"), EVP_mdc2() },
79
1.42k
            { CF_DIGEST("MD4"), EVP_md4() },
80
1.42k
            { CF_DIGEST("MD5"), EVP_md5() },
81
1.42k
            { CF_DIGEST("SHA224"), EVP_sha224() },
82
1.42k
            { CF_DIGEST("SHA256"), EVP_sha256() },
83
1.42k
            { CF_DIGEST("SHA384"), EVP_sha384() },
84
1.42k
            { CF_DIGEST("SHA512"), EVP_sha512() },
85
1.42k
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
86
#if 0
87
            { CF_DIGEST("MDC2"), EVP_mdc2() },
88
            { CF_DIGEST("MD4"), EVP_md4() },
89
            { CF_DIGEST("MD5"), EVP_md5() },
90
            { CF_DIGEST("SHA1"), EVP_sha1() },
91
            { CF_DIGEST("SHA224"), EVP_sha224() },
92
            { CF_DIGEST("SHA256"), EVP_sha256() },
93
            { CF_DIGEST("SHA384"), EVP_sha384() },
94
            { CF_DIGEST("SHA512"), EVP_sha512() },
95
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
96
            { CF_DIGEST("SHA3-224"), EVP_sha3_224() },
97
            { CF_DIGEST("SHA3-256"), EVP_sha3_256() },
98
            { CF_DIGEST("SHA3-384"), EVP_sha3_384() },
99
            { CF_DIGEST("SHA3-512"), EVP_sha3_512() },
100
#endif
101
#else
102
            { CF_DIGEST("SHA1"), EVP_sha1() },
103
            { CF_DIGEST("SHA224"), EVP_sha224() },
104
            { CF_DIGEST("SHA256"), EVP_sha256() },
105
            { CF_DIGEST("SHA384"), EVP_sha384() },
106
            { CF_DIGEST("SHA512"), EVP_sha512() },
107
            { CF_DIGEST("MD2"), EVP_md2() },
108
            { CF_DIGEST("MD4"), EVP_md4() },
109
            { CF_DIGEST("MD5"), EVP_md5() },
110
            { CF_DIGEST("MD5_SHA1"), EVP_md5_sha1() },
111
            { CF_DIGEST("MDC2"), EVP_mdc2() },
112
            { CF_DIGEST("RIPEMD160"), EVP_ripemd160() },
113
            { CF_DIGEST("WHIRLPOOL"), EVP_whirlpool() },
114
            { CF_DIGEST("SM3"), EVP_sm3() },
115
            { CF_DIGEST("BLAKE2B512"), EVP_blake2b512() },
116
            { CF_DIGEST("BLAKE2S256"), EVP_blake2s256() },
117
            { CF_DIGEST("SHAKE128"), EVP_shake128() },
118
            { CF_DIGEST("SHAKE256"), EVP_shake256() },
119
            { CF_DIGEST("SHA3-224"), EVP_sha3_224() },
120
            { CF_DIGEST("SHA3-256"), EVP_sha3_256() },
121
            { CF_DIGEST("SHA3-384"), EVP_sha3_384() },
122
            { CF_DIGEST("SHA3-512"), EVP_sha3_512() },
123
            { CF_DIGEST("SHA512-224"), EVP_sha512_224() },
124
            { CF_DIGEST("SHA512-256"), EVP_sha512_256() },
125
#endif
126
1.42k
        };
127
128
1.42k
        if ( LUT.find(digestType.Get()) == LUT.end() ) {
129
318
            return nullptr;
130
318
        }
131
132
1.10k
        return LUT.at(digestType.Get());
133
1.42k
    }
134
}
135
136
778
std::optional<component::Digest> wolfCrypt_OpenSSL::OpDigest(operation::Digest& op) {
137
778
    std::optional<component::Digest> ret = std::nullopt;
138
778
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
139
140
778
    util::Multipart parts;
141
142
778
    CF_EVP_MD_CTX ctx(ds);
143
778
    const EVP_MD* md = nullptr;
144
145
    /* Initialize */
146
778
    {
147
778
        parts = util::ToParts(ds, op.cleartext);
148
778
        CF_CHECK_NE(md = wolfCrypt_OpenSSL_detail::toEVPMD(op.digestType), nullptr);
149
542
        CF_CHECK_EQ(EVP_DigestInit_ex(ctx.GetPtr(), md, nullptr), 1);
150
542
    }
151
152
    /* Process */
153
14.3k
    for (const auto& part : parts) {
154
14.3k
        CF_CHECK_EQ(EVP_DigestUpdate(ctx.GetPtr(), part.first, part.second), 1);
155
14.3k
    }
156
157
    /* Finalize */
158
542
    {
159
542
        unsigned int len = -1;
160
542
        unsigned char md[EVP_MAX_MD_SIZE];
161
542
        CF_CHECK_EQ(EVP_DigestFinal_ex(ctx.GetPtr(), md, &len), 1);
162
163
542
        ret = component::Digest(md, len);
164
542
    }
165
166
778
end:
167
778
    return ret;
168
542
}
169
170
namespace wolfCrypt_OpenSSL_detail {
171
514
std::optional<component::MAC> OpHMAC_EVP(operation::HMAC& op, Datasource& ds) {
172
514
    std::optional<component::MAC> ret = std::nullopt;
173
174
514
    util::Multipart parts;
175
176
514
    CF_EVP_MD_CTX ctx(ds);
177
514
    const EVP_MD* md = nullptr;
178
514
    EVP_PKEY *pkey = nullptr;
179
180
    /* Initialize */
181
514
    {
182
514
        parts = util::ToParts(ds, op.cleartext);
183
184
514
        CF_CHECK_NE(md = wolfCrypt_OpenSSL_detail::toEVPMD(op.digestType), nullptr);
185
432
        CF_CHECK_NE(pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, op.cipher.key.GetPtr(), op.cipher.key.GetSize()), nullptr);
186
432
        CF_CHECK_EQ(EVP_DigestSignInit(ctx.GetPtr(), nullptr, md, nullptr, pkey), 1);
187
429
    }
188
189
    /* Process */
190
748
    for (const auto& part : parts) {
191
748
        CF_CHECK_EQ(EVP_DigestSignUpdate(ctx.GetPtr(), part.first, part.second), 1);
192
568
    }
193
194
    /* Finalize */
195
249
    {
196
249
        size_t len = -1;
197
249
        uint8_t out[EVP_MAX_MD_SIZE];
198
249
        CF_CHECK_EQ(EVP_DigestSignFinal(ctx.GetPtr(), out, &len), 1);
199
200
249
        ret = component::MAC(out, len);
201
249
    }
202
203
514
end:
204
514
    EVP_PKEY_free(pkey);
205
206
514
    return ret;
207
249
}
208
209
129
std::optional<component::MAC> OpHMAC_HMAC(operation::HMAC& op, Datasource& ds) {
210
129
    std::optional<component::MAC> ret = std::nullopt;
211
212
129
    util::Multipart parts;
213
214
129
    CF_HMAC_CTX ctx(ds);
215
129
    const EVP_MD* md = nullptr;
216
217
    /* Initialize */
218
129
    {
219
129
        parts = util::ToParts(ds, op.cleartext);
220
        /* TODO remove ? */
221
129
        HMAC_CTX_reset(ctx.GetPtr());
222
129
        CF_CHECK_NE(md = toEVPMD(op.digestType), nullptr);
223
118
        CF_CHECK_EQ(HMAC_Init_ex(ctx.GetPtr(), op.cipher.key.GetPtr(), op.cipher.key.GetSize(), md, nullptr), 1);
224
106
    }
225
226
    /* Process */
227
621
    for (const auto& part : parts) {
228
621
        CF_CHECK_EQ(HMAC_Update(ctx.GetPtr(), part.first, part.second), 1);
229
621
    }
230
231
    /* Finalize */
232
106
    {
233
106
        unsigned int len = -1;
234
106
        uint8_t out[EVP_MAX_MD_SIZE];
235
106
        CF_CHECK_EQ(HMAC_Final(ctx.GetPtr(), out, &len), 1);
236
237
106
        ret = component::MAC(out, len);
238
106
    }
239
240
129
end:
241
129
    return ret;
242
106
}
243
}
244
245
643
std::optional<component::MAC> wolfCrypt_OpenSSL::OpHMAC(operation::HMAC& op) {
246
643
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
247
248
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
249
    if (    op.digestType.Get() == CF_DIGEST("SIPHASH64") ||
250
            op.digestType.Get() == CF_DIGEST("SIPHASH128") ) {
251
        /* Not HMAC but invoking SipHash here anyway due to convenience. */
252
        return OpenSSL_detail::SipHash(op);
253
    }
254
#endif
255
256
643
    bool useEVP = true;
257
643
    try {
258
643
        useEVP = ds.Get<bool>();
259
643
    } catch ( fuzzing::datasource::Datasource::OutOfData ) {
260
264
    }
261
262
643
    if ( useEVP == true ) {
263
514
#if !defined(CRYPTOFUZZ_BORINGSSL)
264
514
        return wolfCrypt_OpenSSL_detail::OpHMAC_EVP(op, ds);
265
#else
266
        return wolfCrypt_OpenSSL_detail::OpHMAC_HMAC(op, ds);
267
#endif
268
514
    } else {
269
129
#if !defined(CRYPTOFUZZ_OPENSSL_102)
270
129
        return wolfCrypt_OpenSSL_detail::OpHMAC_HMAC(op, ds);
271
#else
272
        return wolfCrypt_OpenSSL_detail::OpHMAC_EVP(op, ds);
273
#endif
274
129
    }
275
276
0
    return {};
277
643
}
278
279
namespace wolfCrypt_OpenSSL_detail {
280
281
1.92k
const EVP_CIPHER* toEVPCIPHER(const component::SymmetricCipherType cipherType) {
282
1.92k
    using fuzzing::datasource::ID;
283
284
1.92k
    switch ( cipherType.Get() ) {
285
121
        case CF_CIPHER("AES_128_CBC"):
286
121
            return EVP_aes_128_cbc();
287
141
        case CF_CIPHER("AES_128_CFB1"):
288
141
            return EVP_aes_128_cfb1();
289
74
        case CF_CIPHER("AES_128_CFB8"):
290
74
            return EVP_aes_128_cfb8();
291
14
        case CF_CIPHER("AES_128_CTR"):
292
14
            return EVP_aes_128_ctr();
293
42
        case CF_CIPHER("AES_128_ECB"):
294
42
            return EVP_aes_128_ecb();
295
46
        case CF_CIPHER("AES_128_GCM"):
296
46
            return EVP_aes_128_gcm();
297
78
        case CF_CIPHER("AES_128_OFB"):
298
78
            return EVP_aes_128_ofb();
299
147
        case CF_CIPHER("AES_128_XTS"):
300
147
            return EVP_aes_128_xts();
301
14
        case CF_CIPHER("AES_192_CBC"):
302
14
            return EVP_aes_192_cbc();
303
21
        case CF_CIPHER("AES_192_CFB1"):
304
21
            return EVP_aes_192_cfb1();
305
18
        case CF_CIPHER("AES_192_CFB8"):
306
18
            return EVP_aes_192_cfb8();
307
28
        case CF_CIPHER("AES_192_CTR"):
308
28
            return EVP_aes_192_ctr();
309
16
        case CF_CIPHER("AES_192_ECB"):
310
16
            return EVP_aes_192_ecb();
311
183
        case CF_CIPHER("AES_192_GCM"):
312
183
            return EVP_aes_192_gcm();
313
26
        case CF_CIPHER("AES_192_OFB"):
314
26
            return EVP_aes_192_ofb();
315
36
        case CF_CIPHER("AES_256_CBC"):
316
36
            return EVP_aes_256_cbc();
317
28
        case CF_CIPHER("AES_256_CFB1"):
318
28
            return EVP_aes_256_cfb1();
319
21
        case CF_CIPHER("AES_256_CFB8"):
320
21
            return EVP_aes_256_cfb8();
321
23
        case CF_CIPHER("AES_256_CTR"):
322
23
            return EVP_aes_256_ctr();
323
17
        case CF_CIPHER("AES_256_ECB"):
324
17
            return EVP_aes_256_ecb();
325
76
        case CF_CIPHER("AES_256_GCM"):
326
76
            return EVP_aes_256_gcm();
327
17
        case CF_CIPHER("AES_256_OFB"):
328
17
            return EVP_aes_256_ofb();
329
45
        case CF_CIPHER("AES_256_XTS"):
330
45
            return EVP_aes_256_xts();
331
182
        case CF_CIPHER("DES_CBC"):
332
182
            return EVP_des_cbc();
333
74
        case CF_CIPHER("DES_ECB"):
334
74
            return EVP_des_ecb();
335
23
        case CF_CIPHER("DES_EDE3_CBC"):
336
23
            return EVP_des_ede3_cbc();
337
43
        case CF_CIPHER("RC4"):
338
43
            return EVP_rc4();
339
371
        default:
340
371
            return nullptr;
341
1.92k
    }
342
1.92k
}
343
344
335
inline bool isAEAD(const EVP_CIPHER* ctx) {
345
335
    return (EVP_CIPHER_flags(ctx) & EVP_CIPH_GCM_MODE) == EVP_CIPH_GCM_MODE;
346
335
}
347
348
1.42k
bool checkSetIVLength(const uint64_t cipherType, const EVP_CIPHER* cipher, EVP_CIPHER_CTX* ctx, const size_t inputIvLength) {
349
1.42k
    bool ret = false;
350
351
1.42k
    const size_t ivLength = EVP_CIPHER_iv_length(cipher);
352
1.42k
    const bool ivLengthMismatch = ivLength != inputIvLength;
353
354
1.42k
    return !ivLengthMismatch;
355
0
    if ( isAEAD(cipher) == false ) {
356
        /* Return true (success) if input IV length is expected IV length */
357
0
        return !ivLengthMismatch;
358
0
    }
359
360
0
    const bool isCCM = repository::IsCCM( cipherType );
361
362
    /* Only AEAD ciphers past this point */
363
364
    /* EVP_CIPHER_iv_length may return the wrong default IV length for CCM ciphers.
365
     * Eg. EVP_CIPHER_iv_length returns 12 for EVP_aes_128_ccm() even though the
366
     * IV length is actually.
367
     *
368
     * Hence, with CCM ciphers set the desired IV length always.
369
     */
370
371
0
    if ( isCCM || ivLengthMismatch ) {
372
0
        CF_CHECK_EQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, inputIvLength, nullptr), 1);
373
0
    }
374
375
0
    ret = true;
376
0
end:
377
378
0
    return ret;
379
0
}
380
381
1.19k
bool checkSetKeyLength(const EVP_CIPHER* cipher, EVP_CIPHER_CTX* ctx, const size_t inputKeyLength) {
382
1.19k
    (void)ctx;
383
384
1.19k
    bool ret = false;
385
386
1.19k
    const size_t keyLength = EVP_CIPHER_key_length(cipher);
387
1.19k
    if ( keyLength != inputKeyLength ) {
388
78
        return false;
389
0
        CF_CHECK_EQ(EVP_CIPHER_CTX_set_key_length(ctx, inputKeyLength), 1);
390
0
    }
391
392
1.12k
    ret = true;
393
394
1.12k
end:
395
1.12k
    return ret;
396
1.12k
}
397
398
791
std::optional<component::Ciphertext> OpSymmetricEncrypt_EVP(operation::SymmetricEncrypt& op, Datasource& ds) {
399
791
    std::optional<component::Ciphertext> ret = std::nullopt;
400
401
791
    util::Multipart partsCleartext, partsAAD;
402
403
791
    const EVP_CIPHER* cipher = nullptr;
404
791
    CF_EVP_CIPHER_CTX ctx(ds);
405
406
791
    size_t out_size = op.ciphertextSize;
407
791
    size_t outIdx = 0;
408
791
    uint8_t* out = util::malloc(out_size);
409
791
    uint8_t* outTag = op.tagSize != std::nullopt ? util::malloc(*op.tagSize) : nullptr;
410
411
    /* Initialize */
412
791
    {
413
791
        CF_CHECK_NE(cipher = wolfCrypt_OpenSSL_detail::toEVPCIPHER(op.cipher.cipherType), nullptr);
414
596
        if ( op.tagSize != std::nullopt || op.aad != std::nullopt ) {
415
            /* Trying to treat non-AEAD with AEAD-specific features (tag, aad)
416
             * leads to all kinds of gnarly memory bugs in OpenSSL.
417
             * It is quite arguably misuse of the OpenSSL API, so don't do this.
418
             */
419
129
            CF_CHECK_EQ(isAEAD(cipher), true);
420
76
        }
421
422
543
        CF_CHECK_EQ(EVP_EncryptInit_ex(ctx.GetPtr(), cipher, nullptr, nullptr, nullptr), 1);
423
424
        /* Must be a multiple of the block size of this cipher */
425
        //CF_CHECK_EQ(op.cleartext.GetSize() % EVP_CIPHER_block_size(cipher), 0);
426
427
        /* Convert cleartext to parts */
428
543
        partsCleartext = util::CipherInputTransform(ds, op.cipher.cipherType, out, out_size, op.cleartext.GetPtr(), op.cleartext.GetSize());
429
430
543
        if ( op.aad != std::nullopt ) {
431
45
            if ( repository::IsCCM( op.cipher.cipherType.Get() ) ) {
432
                /* CCM does not support chunked AAD updating.
433
                 * See: https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Encryption_using_CCM_mode
434
                 */
435
0
                partsAAD = { {op.aad->GetPtr(), op.aad->GetSize()} };
436
45
            } else {
437
45
                partsAAD = util::ToParts(ds, *(op.aad));
438
45
            }
439
45
        }
440
441
543
        if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) {
442
543
            CF_CHECK_EQ(checkSetIVLength(op.cipher.cipherType.Get(), cipher, ctx.GetPtr(), op.cipher.iv.GetSize()), true);
443
467
        } else {
444
0
            CF_CHECK_EQ(op.cipher.iv.GetSize(), 12);
445
0
        }
446
467
        CF_CHECK_EQ(checkSetKeyLength(cipher, ctx.GetPtr(), op.cipher.key.GetSize()), true);
447
448
414
        if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) {
449
414
            CF_CHECK_EQ(EVP_EncryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), op.cipher.iv.GetPtr()), 1);
450
414
        } else {
451
            /* Prepend the 32 bit counter (which is 0) to the iv */
452
0
            uint8_t cc20IV[16];
453
0
            memset(cc20IV, 0, 4);
454
0
            memcpy(cc20IV + 4, op.cipher.iv.GetPtr(), op.cipher.iv.GetSize());
455
0
            CF_CHECK_EQ(EVP_EncryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), cc20IV), 1);
456
0
        }
457
458
        /* Disable ECB padding for consistency with mbed TLS */
459
414
        if ( repository::IsECB(op.cipher.cipherType.Get()) ) {
460
50
            CF_CHECK_EQ(EVP_CIPHER_CTX_set_padding(ctx.GetPtr(), 0), 1);
461
50
        }
462
414
    }
463
464
    /* Process */
465
414
    {
466
        /* If the cipher is CCM, the total cleartext size needs to be indicated explicitly
467
         * https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
468
         */
469
414
        if ( repository::IsCCM(op.cipher.cipherType.Get()) == true ) {
470
0
            int len;
471
0
            CF_CHECK_EQ(EVP_EncryptUpdate(ctx.GetPtr(), nullptr, &len, nullptr, op.cleartext.GetSize()), 1);
472
0
        }
473
474
        /* Set AAD */
475
414
        if ( op.aad != std::nullopt ) {
476
92
            for (const auto& part : partsAAD) {
477
92
                int len;
478
92
                CF_CHECK_EQ(EVP_EncryptUpdate(ctx.GetPtr(), nullptr, &len, part.first, part.second), 1);
479
92
            }
480
33
        }
481
482
793
        for (const auto& part : partsCleartext) {
483
            /* "the amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1)" */
484
793
            CF_CHECK_GTE(out_size, part.second + EVP_CIPHER_block_size(cipher) - 1);
485
486
713
            int len = -1;
487
713
            CF_CHECK_EQ(EVP_EncryptUpdate(ctx.GetPtr(), out + outIdx, &len, part.first, part.second), 1);
488
704
            outIdx += len;
489
704
            out_size -= len;
490
704
        }
491
414
    }
492
493
    /* Finalize */
494
325
    {
495
325
        CF_CHECK_GTE(out_size, static_cast<size_t>(EVP_CIPHER_block_size(cipher)));
496
497
321
        int len = -1;
498
321
        CF_CHECK_EQ(EVP_EncryptFinal_ex(ctx.GetPtr(), out + outIdx, &len), 1);
499
320
        outIdx += len;
500
501
320
        if ( op.tagSize != std::nullopt ) {
502
            /* Get tag.
503
             *
504
             * See comments around EVP_CTRL_AEAD_SET_TAG in OpSymmetricDecrypt_EVP for reasons
505
             * as to why this is disabled for LibreSSL.
506
             */
507
47
            CF_CHECK_EQ(EVP_CIPHER_CTX_ctrl(ctx.GetPtr(), EVP_CTRL_AEAD_GET_TAG, *op.tagSize, outTag), 1);
508
14
            ret = component::Ciphertext(Buffer(out, outIdx), Buffer(outTag, *op.tagSize));
509
273
        } else {
510
273
            ret = component::Ciphertext(Buffer(out, outIdx));
511
273
        }
512
320
    }
513
514
791
end:
515
516
791
    util::free(out);
517
791
    util::free(outTag);
518
519
791
    return ret;
520
320
}
521
522
}
523
524
791
std::optional<component::Ciphertext> wolfCrypt_OpenSSL::OpSymmetricEncrypt(operation::SymmetricEncrypt& op) {
525
791
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
526
791
    return wolfCrypt_OpenSSL_detail::OpSymmetricEncrypt_EVP(op, ds);
527
791
}
528
529
namespace wolfCrypt_OpenSSL_detail {
530
531
1.13k
std::optional<component::Cleartext> OpSymmetricDecrypt_EVP(operation::SymmetricDecrypt& op, Datasource& ds) {
532
1.13k
    std::optional<component::Cleartext> ret = std::nullopt;
533
534
1.13k
    util::Multipart partsCiphertext, partsAAD;
535
536
1.13k
    const EVP_CIPHER* cipher = nullptr;
537
1.13k
    CF_EVP_CIPHER_CTX ctx(ds);
538
539
1.13k
    size_t out_size = op.cleartextSize;
540
1.13k
    size_t outIdx = 0;
541
1.13k
    uint8_t* out = util::malloc(out_size);
542
543
    /* Initialize */
544
1.13k
    {
545
1.13k
        CF_CHECK_NE(cipher = toEVPCIPHER(op.cipher.cipherType), nullptr);
546
958
        if ( op.tag != std::nullopt || op.aad != std::nullopt ) {
547
            /* Trying to treat non-AEAD with AEAD-specific features (tag, aad)
548
             * leads to all kinds of gnarly memory bugs in OpenSSL.
549
             * It is quite arguably misuse of the OpenSSL API, so don't do this.
550
             */
551
206
            CF_CHECK_EQ(isAEAD(cipher), true);
552
134
        }
553
886
        CF_CHECK_EQ(EVP_DecryptInit_ex(ctx.GetPtr(), cipher, nullptr, nullptr, nullptr), 1);
554
555
        /* Must be a multiple of the block size of this cipher */
556
        //CF_CHECK_EQ(op.ciphertext.GetSize() % EVP_CIPHER_block_size(cipher), 0);
557
558
        /* Convert ciphertext to parts */
559
        //partsCiphertext = util::CipherInputTransform(ds, op.cipher.cipherType, out, out_size, op.ciphertext.GetPtr(), op.ciphertext.GetSize());
560
886
        partsCiphertext = { {op.ciphertext.GetPtr(), op.ciphertext.GetSize()} };
561
562
886
        if ( op.aad != std::nullopt ) {
563
104
            if ( repository::IsCCM( op.cipher.cipherType.Get() ) ) {
564
                /* CCM does not support chunked AAD updating.
565
                 * See: https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Encryption_using_CCM_mode
566
                 */
567
0
                partsAAD = { {op.aad->GetPtr(), op.aad->GetSize()} };
568
104
            } else {
569
104
                partsAAD = util::ToParts(ds, *(op.aad));
570
104
            }
571
104
        }
572
573
886
        if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) {
574
886
            CF_CHECK_EQ(checkSetIVLength(op.cipher.cipherType.Get(), cipher, ctx.GetPtr(), op.cipher.iv.GetSize()), true);
575
731
        } else {
576
0
            CF_CHECK_EQ(op.cipher.iv.GetSize(), 12);
577
0
        }
578
731
        CF_CHECK_EQ(checkSetKeyLength(cipher, ctx.GetPtr(), op.cipher.key.GetSize()), true);
579
580
706
        if ( op.cipher.cipherType.Get() != CF_CIPHER("CHACHA20") ) {
581
706
            CF_CHECK_EQ(EVP_DecryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), op.cipher.iv.GetPtr()), 1);
582
706
        } else {
583
            /* Prepend the 32 bit counter (which is 0) to the iv */
584
0
            uint8_t cc20IV[16];
585
0
            memset(cc20IV, 0, 4);
586
0
            memcpy(cc20IV + 4, op.cipher.iv.GetPtr(), op.cipher.iv.GetSize());
587
0
            CF_CHECK_EQ(EVP_DecryptInit_ex(ctx.GetPtr(), nullptr, nullptr, op.cipher.key.GetPtr(), cc20IV), 1);
588
0
        }
589
590
        /* Disable ECB padding for consistency with mbed TLS */
591
706
        if ( repository::IsECB(op.cipher.cipherType.Get()) ) {
592
46
            CF_CHECK_EQ(EVP_CIPHER_CTX_set_padding(ctx.GetPtr(), 0), 1);
593
46
        }
594
706
    }
595
596
    /* Process */
597
706
    {
598
        /* If the cipher is CCM, the total cleartext size needs to be indicated explicitly
599
         * https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
600
         */
601
706
        if ( repository::IsCCM(op.cipher.cipherType.Get()) == true ) {
602
0
            int len;
603
0
            CF_CHECK_EQ(EVP_DecryptUpdate(ctx.GetPtr(), nullptr, &len, nullptr, op.ciphertext.GetSize()), 1);
604
0
        }
605
606
        /* Set AAD */
607
706
        if ( op.aad != std::nullopt ) {
608
586
            for (const auto& part : partsAAD) {
609
586
                int len;
610
586
                CF_CHECK_EQ(EVP_DecryptUpdate(ctx.GetPtr(), nullptr, &len, part.first, part.second), 1);
611
586
            }
612
64
        }
613
614
        /* Set ciphertext */
615
706
        for (const auto& part : partsCiphertext) {
616
706
            CF_CHECK_GTE(out_size, part.second + EVP_CIPHER_block_size(cipher));
617
618
677
            int len = -1;
619
677
            CF_CHECK_EQ(EVP_DecryptUpdate(ctx.GetPtr(), out + outIdx, &len, part.first, part.second), 1);
620
621
677
            outIdx += len;
622
677
            out_size -= len;
623
677
        }
624
625
677
        if ( op.tag != std::nullopt ) {
626
26
            CF_CHECK_EQ(EVP_CIPHER_CTX_ctrl(ctx.GetPtr(), EVP_CTRL_AEAD_SET_TAG, op.tag->GetSize(), (void*)op.tag->GetPtr()), 1);
627
18
        }
628
677
    }
629
630
    /* Finalize */
631
669
    {
632
669
        CF_CHECK_GTE(out_size, static_cast<size_t>(EVP_CIPHER_block_size(cipher)));
633
634
669
        int len = -1;
635
669
        CF_CHECK_EQ(EVP_DecryptFinal_ex(ctx.GetPtr(), out + outIdx, &len), 1);
636
443
        outIdx += len;
637
638
443
        ret = component::Cleartext(out, outIdx);
639
443
    }
640
641
1.13k
end:
642
643
1.13k
    util::free(out);
644
645
1.13k
    return ret;
646
443
}
647
648
}
649
650
1.13k
std::optional<component::Cleartext> wolfCrypt_OpenSSL::OpSymmetricDecrypt(operation::SymmetricDecrypt& op) {
651
1.13k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
652
1.13k
    return wolfCrypt_OpenSSL_detail::OpSymmetricDecrypt_EVP(op, ds);
653
1.13k
}
654
655
2.25k
std::optional<component::Bignum> wolfCrypt_OpenSSL::OpBignumCalc(operation::BignumCalc& op) {
656
2.25k
    std::optional<component::Bignum> ret = std::nullopt;
657
2.25k
    Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize());
658
659
2.25k
    OpenSSL_bignum::BN_CTX ctx(ds);
660
2.25k
    OpenSSL_bignum::BignumCluster bn(ds,
661
2.25k
        OpenSSL_bignum::Bignum(ds),
662
2.25k
        OpenSSL_bignum::Bignum(ds),
663
2.25k
        OpenSSL_bignum::Bignum(ds),
664
2.25k
        OpenSSL_bignum::Bignum(ds));
665
2.25k
    OpenSSL_bignum::Bignum res(ds);
666
2.25k
    std::unique_ptr<OpenSSL_bignum::Operation> opRunner = nullptr;
667
668
2.25k
    CF_CHECK_EQ(res.New(), true);
669
2.25k
    CF_CHECK_EQ(bn.New(0), true);
670
2.25k
    CF_CHECK_EQ(bn.New(1), true);
671
2.25k
    CF_CHECK_EQ(bn.New(2), true);
672
2.25k
    CF_CHECK_EQ(bn.New(3), true);
673
674
2.25k
    CF_CHECK_EQ(res.Set("0"), true);
675
2.25k
    CF_CHECK_EQ(bn.Set(0, op.bn0.ToString(ds)), true);
676
2.21k
    CF_CHECK_EQ(bn.Set(1, op.bn1.ToString(ds)), true);
677
2.17k
    CF_CHECK_EQ(bn.Set(2, op.bn2.ToString(ds)), true);
678
2.14k
    CF_CHECK_EQ(bn.Set(3, op.bn3.ToString(ds)), true);
679
680
2.13k
    switch ( op.calcOp.Get() ) {
681
16
        case    CF_CALCOP("Add(A,B)"):
682
16
            opRunner = std::make_unique<OpenSSL_bignum::Add>();
683
16
            break;
684
17
        case    CF_CALCOP("Sub(A,B)"):
685
17
            opRunner = std::make_unique<OpenSSL_bignum::Sub>();
686
17
            break;
687
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
688
        case    CF_CALCOP("Mul(A,B)"):
689
            opRunner = std::make_unique<OpenSSL_bignum::Mul>();
690
            break;
691
#endif
692
18
        case    CF_CALCOP("Mod(A,B)"):
693
18
            opRunner = std::make_unique<OpenSSL_bignum::Mod>();
694
18
            break;
695
393
        case    CF_CALCOP("ExpMod(A,B,C)"):
696
393
            opRunner = std::make_unique<OpenSSL_bignum::ExpMod>();
697
393
            break;
698
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
699
        case    CF_CALCOP("Sqr(A)"):
700
            opRunner = std::make_unique<OpenSSL_bignum::Sqr>();
701
            break;
702
#endif
703
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
704
        case    CF_CALCOP("GCD(A,B)"):
705
            opRunner = std::make_unique<OpenSSL_bignum::GCD>();
706
            break;
707
#endif
708
38
        case    CF_CALCOP("AddMod(A,B,C)"):
709
38
            opRunner = std::make_unique<OpenSSL_bignum::AddMod>();
710
38
            break;
711
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
712
        case    CF_CALCOP("SubMod(A,B,C)"):
713
            opRunner = std::make_unique<OpenSSL_bignum::SubMod>();
714
            break;
715
#endif
716
41
        case    CF_CALCOP("MulMod(A,B,C)"):
717
41
            opRunner = std::make_unique<OpenSSL_bignum::MulMod>();
718
41
            break;
719
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
720
        case    CF_CALCOP("SqrMod(A,B)"):
721
            opRunner = std::make_unique<OpenSSL_bignum::SqrMod>();
722
            break;
723
#endif
724
416
        case    CF_CALCOP("InvMod(A,B)"):
725
416
            opRunner = std::make_unique<OpenSSL_bignum::InvMod>();
726
416
            break;
727
31
        case    CF_CALCOP("Cmp(A,B)"):
728
31
            opRunner = std::make_unique<OpenSSL_bignum::Cmp>();
729
31
            break;
730
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
731
        case    CF_CALCOP("Div(A,B)"):
732
            opRunner = std::make_unique<OpenSSL_bignum::Div>();
733
            break;
734
#endif
735
3
        case    CF_CALCOP("IsPrime(A)"):
736
3
            opRunner = std::make_unique<OpenSSL_bignum::IsPrime>();
737
3
            break;
738
3
        case    CF_CALCOP("Sqrt(A)"):
739
3
            opRunner = std::make_unique<OpenSSL_bignum::Sqrt>();
740
3
            break;
741
10
        case    CF_CALCOP("IsNeg(A)"):
742
10
            opRunner = std::make_unique<OpenSSL_bignum::IsNeg>();
743
10
            break;
744
6
        case    CF_CALCOP("IsEq(A,B)"):
745
6
            opRunner = std::make_unique<OpenSSL_bignum::IsEq>();
746
6
            break;
747
18
        case    CF_CALCOP("IsEven(A)"):
748
18
            opRunner = std::make_unique<OpenSSL_bignum::IsEven>();
749
18
            break;
750
14
        case    CF_CALCOP("IsOdd(A)"):
751
14
            opRunner = std::make_unique<OpenSSL_bignum::IsOdd>();
752
14
            break;
753
23
        case    CF_CALCOP("IsZero(A)"):
754
23
            opRunner = std::make_unique<OpenSSL_bignum::IsZero>();
755
23
            break;
756
66
        case    CF_CALCOP("IsOne(A)"):
757
66
            opRunner = std::make_unique<OpenSSL_bignum::IsOne>();
758
66
            break;
759
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
760
        case    CF_CALCOP("Jacobi(A,B)"):
761
            opRunner = std::make_unique<OpenSSL_bignum::Jacobi>();
762
            break;
763
#endif
764
#if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
765
        case    CF_CALCOP("Mod_NIST_192(A)"):
766
            opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_192>();
767
            break;
768
        case    CF_CALCOP("Mod_NIST_224(A)"):
769
            opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_224>();
770
            break;
771
        case    CF_CALCOP("Mod_NIST_256(A)"):
772
            opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_256>();
773
            break;
774
        case    CF_CALCOP("Mod_NIST_384(A)"):
775
            opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_384>();
776
            break;
777
        case    CF_CALCOP("Mod_NIST_521(A)"):
778
            opRunner = std::make_unique<OpenSSL_bignum::Mod_NIST_521>();
779
            break;
780
#endif
781
7
        case    CF_CALCOP("SqrtMod(A,B)"):
782
7
            opRunner = std::make_unique<OpenSSL_bignum::SqrtMod>();
783
7
            break;
784
#if defined(CRYPTOFUZZ_BORINGSSL)
785
        case    CF_CALCOP("LCM(A,B)"):
786
            opRunner = std::make_unique<OpenSSL_bignum::LCM>();
787
            break;
788
#endif
789
10
        case    CF_CALCOP("Exp(A,B)"):
790
10
            opRunner = std::make_unique<OpenSSL_bignum::Exp>();
791
10
            break;
792
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
793
        case    CF_CALCOP("Abs(A)"):
794
            opRunner = std::make_unique<OpenSSL_bignum::Abs>();
795
            break;
796
#endif
797
32
        case    CF_CALCOP("RShift(A,B)"):
798
32
            opRunner = std::make_unique<OpenSSL_bignum::RShift>();
799
32
            break;
800
1
        case    CF_CALCOP("LShift1(A)"):
801
1
            opRunner = std::make_unique<OpenSSL_bignum::LShift1>();
802
1
            break;
803
15
        case    CF_CALCOP("SetBit(A,B)"):
804
15
            opRunner = std::make_unique<OpenSSL_bignum::SetBit>();
805
15
            break;
806
6
        case    CF_CALCOP("ClearBit(A,B)"):
807
6
            opRunner = std::make_unique<OpenSSL_bignum::ClearBit>();
808
6
            break;
809
8
        case    CF_CALCOP("Bit(A,B)"):
810
8
            opRunner = std::make_unique<OpenSSL_bignum::Bit>();
811
8
            break;
812
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
813
        case    CF_CALCOP("CmpAbs(A,B)"):
814
            opRunner = std::make_unique<OpenSSL_bignum::CmpAbs>();
815
            break;
816
#endif
817
#if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL)
818
        case    CF_CALCOP("ModLShift(A,B,C)"):
819
            opRunner = std::make_unique<OpenSSL_bignum::ModLShift>();
820
            break;
821
#endif
822
4
        case    CF_CALCOP("IsPow2(A)"):
823
4
            opRunner = std::make_unique<OpenSSL_bignum::IsPow2>();
824
4
            break;
825
8
        case    CF_CALCOP("Mask(A,B)"):
826
8
            opRunner = std::make_unique<OpenSSL_bignum::Mask>();
827
8
            break;
828
2.13k
    }
829
830
2.13k
    CF_CHECK_NE(opRunner, nullptr);
831
1.20k
    CF_CHECK_EQ(opRunner->Run(ds, res, bn, ctx), true);
832
833
922
    ret = res.ToComponentBignum();
834
835
2.22k
end:
836
2.22k
    return ret;
837
922
}
838
839
} /* namespace module */
840
} /* namespace cryptofuzz */