Coverage Report

Created: 2025-03-09 06:52

/src/cryptofuzz/modules/openssl/module_internal.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include "bn_ops.h"
4
#include <iostream>
5
6
namespace cryptofuzz {
7
namespace module {
8
9
template <class T>
10
class CTX_Copier {
11
    private:
12
        T* ctx = nullptr;
13
        Datasource& ds;
14
15
        T* newCTX(void) const;
16
        int copyCTX(T* dest, T* src) const;
17
        void freeCTX(T* ctx) const;
18
19
128k
        T* copy(void) {
20
128k
            bool doCopyCTX = true;
21
128k
            try {
22
128k
                doCopyCTX = ds.Get<bool>();
23
128k
            } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
24
25
128k
            if ( doCopyCTX == true ) {
26
128k
                T* tmpCtx = newCTX();
27
128k
                if ( tmpCtx != nullptr ) {
28
128k
                    if ( copyCTX(tmpCtx, ctx) == 1 ) {
29
                        /* Copy succeeded, free the old ctx */
30
121k
                        freeCTX(ctx);
31
32
                        /* Use the copied ctx */
33
121k
                        ctx = tmpCtx;
34
121k
                    } else {
35
6.17k
                        freeCTX(tmpCtx);
36
6.17k
                    }
37
128k
                }
38
128k
            }
39
40
128k
            return ctx;
41
128k
        }
cryptofuzz::module::CTX_Copier<evp_md_ctx_st>::copy()
Line
Count
Source
19
55.4k
        T* copy(void) {
20
55.4k
            bool doCopyCTX = true;
21
55.4k
            try {
22
55.4k
                doCopyCTX = ds.Get<bool>();
23
55.4k
            } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
24
25
55.4k
            if ( doCopyCTX == true ) {
26
55.3k
                T* tmpCtx = newCTX();
27
55.3k
                if ( tmpCtx != nullptr ) {
28
55.3k
                    if ( copyCTX(tmpCtx, ctx) == 1 ) {
29
                        /* Copy succeeded, free the old ctx */
30
54.0k
                        freeCTX(ctx);
31
32
                        /* Use the copied ctx */
33
54.0k
                        ctx = tmpCtx;
34
54.0k
                    } else {
35
1.29k
                        freeCTX(tmpCtx);
36
1.29k
                    }
37
55.3k
                }
38
55.3k
            }
39
40
55.4k
            return ctx;
41
55.4k
        }
cryptofuzz::module::CTX_Copier<hmac_ctx_st>::copy()
Line
Count
Source
19
5.48k
        T* copy(void) {
20
5.48k
            bool doCopyCTX = true;
21
5.48k
            try {
22
5.48k
                doCopyCTX = ds.Get<bool>();
23
5.48k
            } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
24
25
5.48k
            if ( doCopyCTX == true ) {
26
5.29k
                T* tmpCtx = newCTX();
27
5.29k
                if ( tmpCtx != nullptr ) {
28
5.29k
                    if ( copyCTX(tmpCtx, ctx) == 1 ) {
29
                        /* Copy succeeded, free the old ctx */
30
5.07k
                        freeCTX(ctx);
31
32
                        /* Use the copied ctx */
33
5.07k
                        ctx = tmpCtx;
34
5.07k
                    } else {
35
224
                        freeCTX(tmpCtx);
36
224
                    }
37
5.29k
                }
38
5.29k
            }
39
40
5.48k
            return ctx;
41
5.48k
        }
cryptofuzz::module::CTX_Copier<evp_cipher_ctx_st>::copy()
Line
Count
Source
19
46.6k
        T* copy(void) {
20
46.6k
            bool doCopyCTX = true;
21
46.6k
            try {
22
46.6k
                doCopyCTX = ds.Get<bool>();
23
46.6k
            } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
24
25
46.6k
            if ( doCopyCTX == true ) {
26
46.5k
                T* tmpCtx = newCTX();
27
46.5k
                if ( tmpCtx != nullptr ) {
28
46.5k
                    if ( copyCTX(tmpCtx, ctx) == 1 ) {
29
                        /* Copy succeeded, free the old ctx */
30
44.2k
                        freeCTX(ctx);
31
32
                        /* Use the copied ctx */
33
44.2k
                        ctx = tmpCtx;
34
44.2k
                    } else {
35
2.21k
                        freeCTX(tmpCtx);
36
2.21k
                    }
37
46.5k
                }
38
46.5k
            }
39
40
46.6k
            return ctx;
41
46.6k
        }
cryptofuzz::module::CTX_Copier<CMAC_CTX_st>::copy()
Line
Count
Source
19
17.9k
        T* copy(void) {
20
17.9k
            bool doCopyCTX = true;
21
17.9k
            try {
22
17.9k
                doCopyCTX = ds.Get<bool>();
23
17.9k
            } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
24
25
17.9k
            if ( doCopyCTX == true ) {
26
17.9k
                T* tmpCtx = newCTX();
27
17.9k
                if ( tmpCtx != nullptr ) {
28
17.9k
                    if ( copyCTX(tmpCtx, ctx) == 1 ) {
29
                        /* Copy succeeded, free the old ctx */
30
15.5k
                        freeCTX(ctx);
31
32
                        /* Use the copied ctx */
33
15.5k
                        ctx = tmpCtx;
34
15.5k
                    } else {
35
2.44k
                        freeCTX(tmpCtx);
36
2.44k
                    }
37
17.9k
                }
38
17.9k
            }
39
40
17.9k
            return ctx;
41
17.9k
        }
cryptofuzz::module::CTX_Copier<ec_key_st>::copy()
Line
Count
Source
19
3.39k
        T* copy(void) {
20
3.39k
            bool doCopyCTX = true;
21
3.39k
            try {
22
3.39k
                doCopyCTX = ds.Get<bool>();
23
3.39k
            } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
24
25
3.39k
            if ( doCopyCTX == true ) {
26
2.92k
                T* tmpCtx = newCTX();
27
2.92k
                if ( tmpCtx != nullptr ) {
28
2.92k
                    if ( copyCTX(tmpCtx, ctx) == 1 ) {
29
                        /* Copy succeeded, free the old ctx */
30
2.92k
                        freeCTX(ctx);
31
32
                        /* Use the copied ctx */
33
2.92k
                        ctx = tmpCtx;
34
2.92k
                    } else {
35
0
                        freeCTX(tmpCtx);
36
0
                    }
37
2.92k
                }
38
2.92k
            }
39
40
3.39k
            return ctx;
41
3.39k
        }
42
43
    public:
44
        CTX_Copier(Datasource& ds) :
45
10.0k
            ds(ds) {
46
10.0k
            ctx = newCTX();
47
48
10.0k
            CF_ASSERT(ctx != nullptr, "Cannot create ctx");
49
10.0k
        }
cryptofuzz::module::CTX_Copier<evp_md_ctx_st>::CTX_Copier(fuzzing::datasource::Datasource&)
Line
Count
Source
45
1.84k
            ds(ds) {
46
1.84k
            ctx = newCTX();
47
48
1.84k
            CF_ASSERT(ctx != nullptr, "Cannot create ctx");
49
1.84k
        }
cryptofuzz::module::CTX_Copier<hmac_ctx_st>::CTX_Copier(fuzzing::datasource::Datasource&)
Line
Count
Source
45
202
            ds(ds) {
46
202
            ctx = newCTX();
47
48
202
            CF_ASSERT(ctx != nullptr, "Cannot create ctx");
49
202
        }
cryptofuzz::module::CTX_Copier<evp_cipher_ctx_st>::CTX_Copier(fuzzing::datasource::Datasource&)
Line
Count
Source
45
3.18k
            ds(ds) {
46
3.18k
            ctx = newCTX();
47
48
3.18k
            CF_ASSERT(ctx != nullptr, "Cannot create ctx");
49
3.18k
        }
cryptofuzz::module::CTX_Copier<CMAC_CTX_st>::CTX_Copier(fuzzing::datasource::Datasource&)
Line
Count
Source
45
2.72k
            ds(ds) {
46
2.72k
            ctx = newCTX();
47
48
2.72k
            CF_ASSERT(ctx != nullptr, "Cannot create ctx");
49
2.72k
        }
cryptofuzz::module::CTX_Copier<ec_key_st>::CTX_Copier(fuzzing::datasource::Datasource&)
Line
Count
Source
45
2.09k
            ds(ds) {
46
2.09k
            ctx = newCTX();
47
48
2.09k
            CF_ASSERT(ctx != nullptr, "Cannot create ctx");
49
2.09k
        }
50
51
128k
        T* GetPtr(void) {
52
128k
            return copy();
53
128k
        }
cryptofuzz::module::CTX_Copier<evp_md_ctx_st>::GetPtr()
Line
Count
Source
51
55.4k
        T* GetPtr(void) {
52
55.4k
            return copy();
53
55.4k
        }
cryptofuzz::module::CTX_Copier<hmac_ctx_st>::GetPtr()
Line
Count
Source
51
5.48k
        T* GetPtr(void) {
52
5.48k
            return copy();
53
5.48k
        }
cryptofuzz::module::CTX_Copier<evp_cipher_ctx_st>::GetPtr()
Line
Count
Source
51
46.6k
        T* GetPtr(void) {
52
46.6k
            return copy();
53
46.6k
        }
cryptofuzz::module::CTX_Copier<CMAC_CTX_st>::GetPtr()
Line
Count
Source
51
17.9k
        T* GetPtr(void) {
52
17.9k
            return copy();
53
17.9k
        }
cryptofuzz::module::CTX_Copier<ec_key_st>::GetPtr()
Line
Count
Source
51
3.39k
        T* GetPtr(void) {
52
3.39k
            return copy();
53
3.39k
        }
54
55
10.0k
        ~CTX_Copier() {
56
10.0k
            freeCTX(ctx);
57
10.0k
        }
cryptofuzz::module::CTX_Copier<evp_md_ctx_st>::~CTX_Copier()
Line
Count
Source
55
1.84k
        ~CTX_Copier() {
56
1.84k
            freeCTX(ctx);
57
1.84k
        }
cryptofuzz::module::CTX_Copier<hmac_ctx_st>::~CTX_Copier()
Line
Count
Source
55
202
        ~CTX_Copier() {
56
202
            freeCTX(ctx);
57
202
        }
cryptofuzz::module::CTX_Copier<evp_cipher_ctx_st>::~CTX_Copier()
Line
Count
Source
55
3.18k
        ~CTX_Copier() {
56
3.18k
            freeCTX(ctx);
57
3.18k
        }
cryptofuzz::module::CTX_Copier<CMAC_CTX_st>::~CTX_Copier()
Line
Count
Source
55
2.72k
        ~CTX_Copier() {
56
2.72k
            freeCTX(ctx);
57
2.72k
        }
cryptofuzz::module::CTX_Copier<ec_key_st>::~CTX_Copier()
Line
Count
Source
55
2.09k
        ~CTX_Copier() {
56
2.09k
            freeCTX(ctx);
57
2.09k
        }
58
};
59
60
class EC_GROUP_Copier {
61
    private:
62
        bool locked = false;
63
        const int curveNID;
64
        EC_GROUP* group = nullptr;
65
        Datasource& ds;
66
67
2.21k
        EC_GROUP* newGroup(void) {
68
2.21k
            return EC_GROUP_new_by_curve_name(curveNID);
69
2.21k
        }
70
71
#if !defined(CRYPTOFUZZ_BORINGSSL)
72
0
        int copyGroup(EC_GROUP* dest, EC_GROUP* src) {
73
0
            return EC_GROUP_copy(dest, src);
74
0
        }
75
#endif
76
2.21k
        void freeGroup(EC_GROUP* group) {
77
2.21k
            /* noret */ EC_GROUP_free(group);
78
2.21k
        }
79
80
0
        EC_GROUP* copy(void) {
81
0
            bool doCopyGroup = true;
82
0
            try {
83
0
                doCopyGroup = ds.Get<bool>();
84
0
            } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
85
86
0
            if ( doCopyGroup == true ) {
87
0
#if !defined(CRYPTOFUZZ_BORINGSSL)
88
0
                EC_GROUP* tmpGroup = newGroup();
89
0
                if ( tmpGroup != nullptr ) {
90
0
                    if ( copyGroup(tmpGroup, group) == 1 ) {
91
                        /* Copy succeeded, free the old group */
92
0
                        freeGroup(group);
93
94
                        /* Use the copied group */
95
0
                        group = tmpGroup;
96
0
                    } else {
97
0
                        freeGroup(tmpGroup);
98
0
                    }
99
0
                }
100
0
#endif
101
0
            }
102
103
0
            return group;
104
0
        }
105
106
    public:
107
        EC_GROUP_Copier(Datasource& ds, const int curveNID) :
108
2.21k
            curveNID(curveNID), ds(ds) {
109
2.21k
            group = newGroup();
110
2.21k
        }
111
112
2.21k
        void Lock(void) {
113
2.21k
            locked = true;
114
2.21k
        }
115
116
11.5k
        EC_GROUP* GetPtr(void) {
117
11.5k
            if ( locked == true ) {
118
11.5k
                return group;
119
11.5k
            } else {
120
0
                return copy();
121
0
            }
122
11.5k
        }
123
124
2.21k
        ~EC_GROUP_Copier() {
125
2.21k
            freeGroup(group);
126
2.21k
        }
127
};
128
129
class EC_POINT_Copier {
130
    private:
131
        std::shared_ptr<EC_GROUP_Copier> group;
132
        EC_POINT* point = nullptr;
133
        Datasource& ds;
134
        const uint64_t curveType;
135
        bool projective = false;
136
137
5.07k
        EC_POINT* newPoint(void) {
138
5.07k
            return EC_POINT_new(group->GetPtr());
139
5.07k
        }
140
141
2.96k
        int copyPoint(EC_POINT* dest, EC_POINT* src) {
142
2.96k
            return EC_POINT_copy(dest, src);
143
2.96k
        }
144
5.07k
        void freePoint(EC_POINT* point) {
145
5.07k
            /* noret */ EC_POINT_free(point);
146
5.07k
        }
147
148
149
0
        point_conversion_form_t GetForm(void) {
150
0
            uint8_t form = 0;
151
0
            try {
152
0
                form = ds.Get<uint8_t>() % 3;
153
0
            } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
154
0
155
0
            if ( form == 0 ) {
156
0
                return POINT_CONVERSION_COMPRESSED;
157
0
            } else if ( form == 1 ) {
158
0
                return POINT_CONVERSION_UNCOMPRESSED;
159
0
            } else if ( form == 2 ) {
160
0
                return POINT_CONVERSION_HYBRID;
161
0
            } else {
162
0
                CF_UNREACHABLE();
163
0
            }
164
0
        }
165
166
167
3.62k
        EC_POINT* copy(void) {
168
3.62k
            {
169
3.62k
                bool doCopyPoint = true;
170
3.62k
                try {
171
3.62k
                    doCopyPoint = ds.Get<bool>();
172
3.62k
                } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
173
174
3.62k
                if ( doCopyPoint == true ) {
175
2.96k
                    EC_POINT* tmpPoint = newPoint();
176
2.96k
                    if ( tmpPoint != nullptr ) {
177
2.96k
                        if ( copyPoint(tmpPoint, point) == 1 ) {
178
                            /* Copy succeeded, free the old point */
179
2.96k
                            freePoint(point);
180
181
                            /* Use the copied point */
182
2.96k
                            point = tmpPoint;
183
2.96k
                        } else {
184
0
                            freePoint(tmpPoint);
185
0
                        }
186
2.96k
                    }
187
2.96k
                }
188
3.62k
            }
189
190
3.62k
            return point;
191
3.62k
        }
192
193
1.30k
        bool set(OpenSSL_bignum::Bignum& pub_x, OpenSSL_bignum::Bignum& pub_y, const bool allowProjective = true) {
194
1.30k
            bool ret = false;
195
196
1.30k
            char* x_str = nullptr;
197
1.30k
            char* y_str = nullptr;
198
199
#if defined(CRYPTOFUZZ_BORINGSSL)
200
            (void)allowProjective;
201
            const bool projective = false;
202
#else
203
1.30k
            bool projective = false;
204
1.30k
            if ( allowProjective == true ) {
205
1.28k
                try {
206
1.28k
                    projective = ds.Get<bool>();
207
1.28k
                } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
208
1.28k
            }
209
210
1.30k
            if ( projective ) {
211
394
                if ( (x_str = BN_bn2dec(pub_x.GetPtr())) == nullptr ) {
212
0
                    projective = false;
213
0
                }
214
394
                if ( projective && (y_str = BN_bn2dec(pub_y.GetPtr())) == nullptr ) {
215
0
                    projective = false;
216
0
                }
217
394
            }
218
1.30k
#endif
219
1.30k
            if ( projective == false ) {
220
#if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_LIBRESSL) && !defined(CRYPTOFUZZ_OPENSSL_102) && !defined(CRYPTOFUZZ_OPENSSL_110) && !defined(CRYPTOFUZZ_OPENSSL_098)
221
                CF_CHECK_NE(EC_POINT_set_affine_coordinates(group->GetPtr(), GetPtr(), pub_x.GetPtr(), pub_y.GetPtr(), nullptr), 0);
222
#else
223
907
                CF_CHECK_NE(EC_POINT_set_affine_coordinates_GFp(group->GetPtr(), GetPtr(), pub_x.GetPtr(), pub_y.GetPtr(), nullptr), 0);
224
712
#endif
225
712
            } else {
226
#if defined(CRYPTOFUZZ_BORINGSSL)
227
                CF_UNREACHABLE();
228
#else
229
394
                OpenSSL_bignum::Bignum x(ds);
230
394
                CF_CHECK_TRUE(x.New());
231
394
                OpenSSL_bignum::Bignum y(ds);
232
394
                CF_CHECK_TRUE(y.New());
233
394
                OpenSSL_bignum::Bignum z(ds);
234
394
                CF_CHECK_TRUE(z.New());
235
236
394
                const auto proj = util::ToRandomProjective(
237
394
                        ds,
238
394
                        std::string(x_str),
239
394
                        std::string(y_str),
240
394
                        curveType);
241
394
                CF_CHECK_TRUE(x.Set(proj[0]));
242
394
                CF_CHECK_TRUE(y.Set(proj[1]));
243
394
                CF_CHECK_TRUE(z.Set(proj[2]));
244
394
                CF_CHECK_NE(EC_POINT_set_Jprojective_coordinates_GFp(group->GetPtr(), GetPtr(), x.GetPtr(), y.GetPtr(), z.GetPtr(), nullptr), 0);
245
0
                this->projective = true;
246
247
#if !defined(CRYPTOFUZZ_LIBRESSL)
248
                /* OpenSSL does not and will not check if a point set using
249
                 * EC_POINT_set_Jprojective_coordinates_GFp is on the curve.
250
                 *
251
                 * https://github.com/openssl/openssl/issues/21228#issuecomment-1604229793
252
                 */
253
                CF_CHECK_EQ(EC_POINT_is_on_curve(group->GetPtr(), GetPtr(), nullptr), 1);
254
#endif
255
256
0
#endif
257
0
            }
258
259
712
            ret = true;
260
1.30k
end:
261
1.30k
            OPENSSL_free(x_str);
262
1.30k
            OPENSSL_free(y_str);
263
1.30k
            return ret;
264
712
        }
265
266
0
        bool set_compressed(OpenSSL_bignum::Bignum& pub_x, OpenSSL_bignum::Bignum& pub_y) {
267
0
            bool ret = false;
268
269
0
            const bool is_prime_curve =
270
0
#if defined(CRYPTOFUZZ_LIBRESSL) || defined(CRYPTOFUZZ_BORINGSSL) || defined(CRYPTOFUZZ_OPENSSL_102) || defined(CRYPTOFUZZ_OPENSSL_098)
271
0
                EC_METHOD_get_field_type(EC_GROUP_method_of(group->GetPtr()))
272
#else
273
                EC_GROUP_get_field_type(group->GetPtr())
274
#endif
275
0
                == NID_X9_62_prime_field;
276
277
#if defined(CRYPTOFUZZ_BORINGSSL)
278
            if ( is_prime_curve ) {
279
                return set(pub_x, pub_y);
280
            }
281
#endif
282
283
0
#if defined(CRYPTOFUZZ_LIBRESSL)
284
0
            if ( !is_prime_curve ) {
285
                /* LibreSSL doesn't have BN_GF2m_mod_div */
286
0
                return set(pub_x, pub_y);
287
0
            }
288
0
#endif
289
290
0
            OpenSSL_bignum::Bignum field(ds);
291
0
            CF_CHECK_TRUE(field.New());
292
0
            int y_bit;
293
294
            /* Reduction of Y is necessary in order to correctly determine y_bit */
295
0
            {
296
0
                OpenSSL_bignum::BN_CTX ctx(ds);
297
0
                BIGNUM* y = pub_y.GetDestPtr();
298
299
0
#if defined(CRYPTOFUZZ_LIBRESSL) || defined(CRYPTOFUZZ_BORINGSSL) || defined(CRYPTOFUZZ_OPENSSL_102) || defined(CRYPTOFUZZ_OPENSSL_098)
300
                /* LibreSSL and BoringSSL don't have EC_GROUP_get0_field(),
301
                 * so try to retrieve the prime from the repository
302
                 */
303
0
                const auto prime = cryptofuzz::repository::ECC_CurveToPrime(curveType);
304
0
                CF_CHECK_NE(prime, std::nullopt);
305
0
                CF_CHECK_EQ(field.Set(*prime), true);
306
#else
307
                (void)curveType;
308
309
                const BIGNUM* _field;
310
                CF_ASSERT(
311
                        (_field = EC_GROUP_get0_field(group->GetPtr())) != nullptr,
312
                        "EC_GROUP_get0_field returned NULL");
313
                CF_CHECK_NE(BN_copy(field.GetDestPtr(), _field), nullptr);
314
#endif
315
316
0
                CF_CHECK_EQ(BN_mod(y, y, field.GetPtr(), ctx.GetPtr()), 1);
317
0
            }
318
319
0
            if ( is_prime_curve == true ) {
320
0
                y_bit = BN_is_bit_set(pub_y.GetPtr(), 0);
321
0
            } else {
322
                /* Binary curve */
323
0
#if defined(CRYPTOFUZZ_BORINGSSL) || defined(CRYPTOFUZZ_LIBRESSL)
324
0
                CF_UNREACHABLE();
325
#else
326
                if ( BN_is_zero(pub_x.GetPtr()) ) {
327
                    y_bit = 0;
328
                } else {
329
                    OpenSSL_bignum::BN_CTX ctx(ds);
330
                    OpenSSL_bignum::Bignum div(ds);
331
332
                    CF_CHECK_TRUE(div.New());
333
                    CF_CHECK_EQ(BN_GF2m_mod_div(div.GetDestPtr(), pub_y.GetPtr(), pub_x.GetPtr(), field.GetPtr(), ctx.GetPtr()), 1);
334
335
                    y_bit = BN_is_bit_set(div.GetPtr(), 0);
336
                }
337
#endif
338
0
            }
339
340
#if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_LIBRESSL) && !defined(CRYPTOFUZZ_OPENSSL_102) && !defined(CRYPTOFUZZ_OPENSSL_110) && !defined(CRYPTOFUZZ_OPENSSL_098)
341
            CF_CHECK_NE(EC_POINT_set_compressed_coordinates(group->GetPtr(), GetPtr(), pub_x.GetPtr(), y_bit, nullptr), 0);
342
#else
343
0
            CF_CHECK_NE(EC_POINT_set_compressed_coordinates_GFp(group->GetPtr(), GetPtr(), pub_x.GetPtr(), y_bit, nullptr), 0);
344
0
#endif
345
346
0
            CF_ASSERT(
347
0
                    EC_POINT_is_on_curve(group->GetPtr(), GetPtr(), nullptr) == 1,
348
0
                    "Decompressed point not on curve")
349
350
0
            ret = true;
351
0
end:
352
0
            return ret;
353
0
        }
354
355
    public:
356
        EC_POINT_Copier(Datasource& ds, std::shared_ptr<EC_GROUP_Copier> group, const uint64_t curveType) :
357
2.10k
            group(group), ds(ds), curveType(curveType) {
358
2.10k
            point = newPoint();
359
360
2.10k
            CF_ASSERT(point != nullptr, "Cannot create EC_POINT");
361
2.10k
        }
362
363
3.62k
        EC_POINT* GetPtr(void) {
364
3.62k
            return copy();
365
3.62k
        }
366
367
2.10k
        ~EC_POINT_Copier() {
368
2.10k
            freePoint(point);
369
2.10k
        }
370
371
        bool Set(
372
                OpenSSL_bignum::Bignum& pub_x,
373
                OpenSSL_bignum::Bignum& pub_y,
374
                const bool allowCompressed = true,
375
1.30k
                const bool allowProjective = true) {
376
1.30k
            bool compressed = false;
377
1.30k
            try {
378
1.30k
                compressed = ds.Get<bool>();
379
1.30k
            } catch ( fuzzing::datasource::Datasource::OutOfData& ) { }
380
381
1.30k
            if ( allowCompressed == false ) {
382
795
                compressed = false;
383
795
            }
384
385
            /* Currently disabled because it leads to spurious discrepancies */
386
1.30k
            compressed = false;
387
388
1.30k
            return compressed ?
389
0
                set_compressed(pub_x, pub_y) :
390
1.30k
                set(pub_x, pub_y, allowProjective);
391
1.30k
        }
392
393
        bool Set(
394
                const component::Bignum& pub_x,
395
                const component::Bignum& pub_y,
396
                const bool allowCompressed = true,
397
1.30k
                const bool allowProjective = true) {
398
1.30k
            bool ret = false;
399
400
1.30k
            OpenSSL_bignum::Bignum _pub_x(ds), _pub_y(ds);
401
402
1.30k
            CF_CHECK_EQ(_pub_x.Set(pub_x.ToString(ds)), true);
403
1.30k
            CF_CHECK_EQ(_pub_y.Set(pub_y.ToString(ds)), true);
404
405
1.30k
            CF_CHECK_TRUE(Set(_pub_x, _pub_y, allowCompressed, allowProjective));
406
407
712
            ret = true;
408
1.30k
end:
409
1.30k
            return ret;
410
712
        }
411
412
37
        bool Get(OpenSSL_bignum::Bignum& pub_x, OpenSSL_bignum::Bignum& pub_y) {
413
37
            bool ret = false;
414
415
#if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_LIBRESSL) && !defined(CRYPTOFUZZ_OPENSSL_102) && !defined(CRYPTOFUZZ_OPENSSL_110) && !defined(CRYPTOFUZZ_OPENSSL_098)
416
            CF_CHECK_NE(EC_POINT_get_affine_coordinates(group->GetPtr(), GetPtr(), pub_x.GetDestPtr(), pub_y.GetDestPtr(), nullptr), 0);
417
#else
418
37
            CF_CHECK_NE(EC_POINT_get_affine_coordinates_GFp(group->GetPtr(), GetPtr(), pub_x.GetDestPtr(), pub_y.GetDestPtr(), nullptr), 0);
419
35
#endif
420
421
35
            ret = true;
422
37
end:
423
37
            return ret;
424
35
        }
425
426
37
        std::optional<component::ECC_Point> Get(void) {
427
37
            std::optional<component::ECC_Point> ret = std::nullopt;
428
429
37
            char* x_str = nullptr;
430
37
            char* y_str = nullptr;
431
432
37
            OpenSSL_bignum::Bignum x(ds);
433
37
            OpenSSL_bignum::Bignum y(ds);
434
435
37
            CF_CHECK_EQ(x.New(), true);
436
37
            CF_CHECK_EQ(y.New(), true);
437
438
37
            CF_CHECK_TRUE(Get(x, y));
439
440
35
            CF_CHECK_NE(x_str = BN_bn2dec(x.GetPtr()), nullptr);
441
35
            CF_CHECK_NE(y_str = BN_bn2dec(y.GetPtr()), nullptr);
442
443
35
            ret = { std::string(x_str), std::string(y_str) };
444
445
37
end:
446
37
            OPENSSL_free(x_str);
447
37
            OPENSSL_free(y_str);
448
449
37
            return ret;
450
35
        }
451
452
99
        bool IsProjective(void) const {
453
99
            return projective;
454
99
        }
455
};
456
457
#if !defined(CRYPTOFUZZ_OPENSSL_102) && !defined(CRYPTOFUZZ_OPENSSL_098)
458
57.2k
template<> EVP_MD_CTX* CTX_Copier<EVP_MD_CTX>::newCTX(void) const { return EVP_MD_CTX_new(); }
459
#else
460
template<> EVP_MD_CTX* CTX_Copier<EVP_MD_CTX>::newCTX(void) const {
461
    EVP_MD_CTX* ret = (EVP_MD_CTX*)malloc(sizeof(*ret));
462
    EVP_MD_CTX_init(ret);
463
    return ret;
464
}
465
#endif
466
467
55.3k
template<> int CTX_Copier<EVP_MD_CTX>::copyCTX(EVP_MD_CTX* dest, EVP_MD_CTX* src) const { return EVP_MD_CTX_copy(dest, src); }
468
469
#if !defined(CRYPTOFUZZ_OPENSSL_102) && !defined(CRYPTOFUZZ_OPENSSL_098)
470
57.2k
template<> void CTX_Copier<EVP_MD_CTX>::freeCTX(EVP_MD_CTX* ctx) const { EVP_MD_CTX_free(ctx); }
471
#else
472
template<> void CTX_Copier<EVP_MD_CTX>::freeCTX(EVP_MD_CTX* ctx) const { EVP_MD_CTX_cleanup(ctx); free(ctx); }
473
#endif
474
475
49.6k
template<> EVP_CIPHER_CTX* CTX_Copier<EVP_CIPHER_CTX>::newCTX(void) const { return EVP_CIPHER_CTX_new(); }
476
#if !defined(CRYPTOFUZZ_OPENSSL_098)
477
46.5k
template<> int CTX_Copier<EVP_CIPHER_CTX>::copyCTX(EVP_CIPHER_CTX* dest, EVP_CIPHER_CTX* src) const { return EVP_CIPHER_CTX_copy(dest, src); }
478
#else
479
template<> int CTX_Copier<EVP_CIPHER_CTX>::copyCTX(EVP_CIPHER_CTX* dest, EVP_CIPHER_CTX* src) const { (void)dest; (void)src; return 0; }
480
#endif
481
49.6k
template<> void CTX_Copier<EVP_CIPHER_CTX>::freeCTX(EVP_CIPHER_CTX* ctx) const { return EVP_CIPHER_CTX_free(ctx); }
482
483
#if !defined(CRYPTOFUZZ_OPENSSL_102) && !defined(CRYPTOFUZZ_OPENSSL_098)
484
5.50k
template<> HMAC_CTX* CTX_Copier<HMAC_CTX>::newCTX(void) const { return HMAC_CTX_new(); }
485
5.29k
template<> int CTX_Copier<HMAC_CTX>::copyCTX(HMAC_CTX* dest, HMAC_CTX* src) const { return HMAC_CTX_copy(dest, src); }
486
5.50k
template<> void CTX_Copier<HMAC_CTX>::freeCTX(HMAC_CTX* ctx) const { return HMAC_CTX_free(ctx); }
487
#endif
488
489
#if !defined(CRYPTOFUZZ_OPENSSL_098)
490
20.6k
template<> CMAC_CTX* CTX_Copier<CMAC_CTX>::newCTX(void) const { return CMAC_CTX_new(); }
491
17.9k
template<> int CTX_Copier<CMAC_CTX>::copyCTX(CMAC_CTX* dest, CMAC_CTX* src) const { return CMAC_CTX_copy(dest, src); }
492
20.6k
template<> void CTX_Copier<CMAC_CTX>::freeCTX(CMAC_CTX* ctx) const { return CMAC_CTX_free(ctx); }
493
#endif
494
495
5.02k
template<> EC_KEY* CTX_Copier<EC_KEY>::newCTX(void) const { return EC_KEY_new(); }
496
2.92k
template<> int CTX_Copier<EC_KEY>::copyCTX(EC_KEY* dest, EC_KEY* src) const {
497
2.92k
#if !defined(CRYPTOFUZZ_BORINGSSL)
498
2.92k
    return EC_KEY_copy(dest, src) == nullptr ? 0 : 1;
499
#else
500
    (void)dest;
501
    (void)src;
502
    return 0;
503
#endif
504
2.92k
}
505
5.02k
template<> void CTX_Copier<EC_KEY>::freeCTX(EC_KEY* ctx) const { return EC_KEY_free(ctx); }
506
507
using CF_EVP_MD_CTX = CTX_Copier<EVP_MD_CTX>;
508
using CF_EVP_CIPHER_CTX = CTX_Copier<EVP_CIPHER_CTX>;
509
using CF_HMAC_CTX = CTX_Copier<HMAC_CTX>;
510
using CF_CMAC_CTX = CTX_Copier<CMAC_CTX>;
511
using CF_EC_KEY = CTX_Copier<EC_KEY>;
512
using CF_EC_POINT = EC_POINT_Copier;
513
using CF_EC_GROUP = EC_GROUP_Copier;
514
} /* namespace module */
515
} /* namespace cryptofuzz */