/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 */ |