/src/cryptofuzz-sp-math/modules/wolfcrypt/ecdsa_generic.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include "ecdsa_generic.h" |
2 | | #include "module_internal.h" |
3 | | #include "shared.h" |
4 | | #include "bn_ops.h" |
5 | | #include <cryptofuzz/util.h> |
6 | | #include <iostream> |
7 | | |
8 | | namespace cryptofuzz { |
9 | | namespace module { |
10 | | namespace wolfCrypt_detail { |
11 | | |
12 | | #if !defined(WOLFSSL_SP_MATH) |
13 | | #include "custom_curves.h" |
14 | | #endif |
15 | | |
16 | | #if defined(CRYPTOFUZZ_WOLFCRYPT_ALLOCATION_FAILURES) |
17 | | extern bool haveAllocFailure; |
18 | | #endif |
19 | | |
20 | | WC_RNG* GetRNG(void); |
21 | | |
22 | | ECCKey::ECCKey(Datasource& ds) : |
23 | 29.7k | ds(ds) { |
24 | 29.7k | if ( (key = wc_ecc_key_new(nullptr)) == nullptr ) { |
25 | 1.86k | throw std::exception(); |
26 | 1.86k | } |
27 | 29.7k | } |
28 | | |
29 | 27.8k | ECCKey::~ECCKey() { |
30 | 27.8k | CF_NORET(wc_ecc_key_free(key)); |
31 | 27.8k | } |
32 | | |
33 | 72.2k | ecc_key* ECCKey::GetPtr(void) { |
34 | 72.2k | uint8_t* x963 = nullptr; |
35 | 72.2k | ecc_key* newKey = nullptr; |
36 | | |
37 | 72.2k | bool exportToX963 = false; |
38 | 72.2k | try { |
39 | 72.2k | exportToX963 = ds.Get<bool>(); |
40 | 72.2k | } catch ( ... ) { } |
41 | | |
42 | 72.2k | if ( exportToX963 == true ) { |
43 | 5.47k | CF_CHECK_NE(newKey = wc_ecc_key_new(nullptr), nullptr); |
44 | | |
45 | 3.53k | word32 outLen = 0; |
46 | | |
47 | 3.53k | bool compressed = false; |
48 | 3.53k | try { compressed = ds.Get<bool>();} catch ( ... ) { } |
49 | | |
50 | 6.32k | WC_CHECK_EQ(wc_ecc_export_x963_ex(key, nullptr, &outLen, compressed), LENGTH_ONLY_E); |
51 | 6.32k | x963 = util::malloc(outLen); |
52 | 6.32k | WC_CHECK_EQ(wc_ecc_export_x963_ex(key, x963, &outLen, compressed), 0);; |
53 | | |
54 | | /* Get the curve id of the old key */ |
55 | 1.11k | int curveID; |
56 | 1.11k | CF_CHECK_NE(curveID = wc_ecc_get_curve_id(key->idx), ECC_CURVE_INVALID); |
57 | | |
58 | 1.11k | const bool valid = wc_ecc_check_key(key) == 0; |
59 | | |
60 | 1.11k | haveAllocFailure = false; |
61 | 1.11k | if ( wc_ecc_import_x963_ex(x963, outLen, newKey, curveID) != 0 ) { |
62 | | /* Allowed to fail if either: |
63 | | * |
64 | | * - Compression is used and the input key is invalid |
65 | | * - An allocation failure occured during wc_ecc_import_x963_ex |
66 | | */ |
67 | 326 | CF_ASSERT((compressed && !valid) || haveAllocFailure, "Cannot import X963-exported ECC key"); |
68 | 326 | goto end; |
69 | 326 | } |
70 | | |
71 | 788 | if ( compressed ) { |
72 | 184 | CF_CHECK_TRUE(valid); |
73 | 38 | } |
74 | | |
75 | 642 | CF_NORET(wc_ecc_key_free(key)); |
76 | 642 | key = newKey; |
77 | 642 | newKey = nullptr; |
78 | 642 | } |
79 | | |
80 | 72.2k | end: |
81 | 72.2k | util::free(x963); |
82 | 72.2k | CF_NORET(wc_ecc_key_free(newKey)); |
83 | | |
84 | 72.2k | return key; |
85 | 72.2k | } |
86 | | |
87 | 3.15k | bool ECCKey::SetCurve(const Type& curveType) { |
88 | 3.15k | bool ret = false; |
89 | | |
90 | | #if !defined(WOLFSSL_SP_MATH) |
91 | | bool useCustomCurve = false; |
92 | | |
93 | | try { |
94 | | useCustomCurve = ds.Get<uint8_t>(); |
95 | | } catch ( fuzzing::datasource::Datasource::OutOfData ) { } |
96 | | useCustomCurve = false; |
97 | | |
98 | | if ( useCustomCurve == false ) |
99 | | #endif |
100 | 3.15k | { |
101 | | #if defined(CRYPTOFUZZ_WOLFCRYPT_DEBUG) |
102 | | std::cout << "Using native curve" << std::endl; |
103 | | #endif |
104 | 3.15k | std::optional<int> curveID; |
105 | | |
106 | 3.15k | CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(curveType), std::nullopt); |
107 | 2.61k | this->curveID = *curveID; |
108 | | |
109 | 2.61k | WC_CHECK_EQ(wc_ecc_set_curve(GetPtr(), 0, *curveID), 0); |
110 | 2.36k | } |
111 | | #if !defined(WOLFSSL_SP_MATH) |
112 | | else { |
113 | | #if defined(CRYPTOFUZZ_WOLFCRYPT_DEBUG) |
114 | | std::cout << "Using custom curve" << std::endl; |
115 | | #endif |
116 | | const ecc_set_type* curveSpec; |
117 | | CF_CHECK_NE(curveSpec = GetCustomCurve(curveType.Get()), nullptr); |
118 | | WC_CHECK_EQ(wc_ecc_set_custom_curve(GetPtr(), curveSpec), 0); |
119 | | this->curveID = ECC_CURVE_CUSTOM; |
120 | | } |
121 | | #endif |
122 | | |
123 | 0 | ret = true; |
124 | | |
125 | 3.15k | end: |
126 | 3.15k | return ret; |
127 | 2.36k | } |
128 | | |
129 | 9.48k | bool ECCKey::LoadPrivateKey(const component::Bignum& priv) { |
130 | 9.48k | bool ret = false; |
131 | 9.48k | std::optional<std::vector<uint8_t>> priv_bytes; |
132 | | |
133 | 9.48k | CF_CHECK_NE(priv_bytes = wolfCrypt_bignum::Bignum::ToBin(ds, priv), std::nullopt); |
134 | | |
135 | 9.11k | WC_CHECK_EQ(wc_ecc_import_private_key_ex(priv_bytes->data(), priv_bytes->size(), nullptr, 0, GetPtr(), *curveID), 0); |
136 | | |
137 | 8.72k | ret = true; |
138 | | |
139 | 9.48k | end: |
140 | 9.48k | return ret; |
141 | 8.72k | } |
142 | | |
143 | 6.42k | std::optional<ECCPoint> ECCKey::MakePub(void) { |
144 | 6.42k | std::optional<ECCPoint> ret = std::nullopt; |
145 | | |
146 | 6.42k | ECCPoint pub(ds, *curveID); |
147 | 6.42k | WC_CHECK_EQ(wc_ecc_make_pub(GetPtr(), pub.GetPtr()), 0); |
148 | 6.05k | pub.SetInitialized(); |
149 | | |
150 | 6.05k | return pub; |
151 | | |
152 | 363 | end: |
153 | 363 | return ret; |
154 | 6.42k | } |
155 | | |
156 | 3.59k | bool ECCKey::SetRNG(void) { |
157 | 3.59k | bool ret = false; |
158 | | |
159 | 3.59k | WC_CHECK_EQ(wc_ecc_set_rng(GetPtr(), wolfCrypt_detail::GetRNG()), 0); |
160 | | |
161 | 3.59k | ret = true; |
162 | 3.59k | end: |
163 | 3.59k | return ret; |
164 | 3.59k | } |
165 | | |
166 | | ECCPoint::ECCPoint(Datasource& ds, const int curveID) : |
167 | | ds(ds), |
168 | 22.4k | curveID(curveID) { |
169 | 22.4k | if ( (point = wc_ecc_new_point_h(nullptr)) == nullptr ) { |
170 | 687 | throw std::exception(); |
171 | 687 | } |
172 | 22.4k | } |
173 | | |
174 | | /* Copy constructor */ |
175 | | ECCPoint::ECCPoint(const ECCPoint& other) : |
176 | | ds(other.ds), |
177 | | curveID(other.curveID), |
178 | | locked(other.locked), |
179 | | initialized(other.initialized) |
180 | 5.96k | { |
181 | 5.96k | if ( (point = wc_ecc_new_point_h(nullptr)) == nullptr ) { |
182 | 9 | throw std::exception(); |
183 | 9 | } |
184 | | |
185 | 5.95k | if ( wc_ecc_copy_point(other.point, point) != 0 ) { |
186 | 0 | CF_NORET(wc_ecc_del_point(point)); |
187 | 0 | throw std::exception(); |
188 | 0 | } |
189 | 5.95k | } |
190 | | |
191 | 27.6k | ECCPoint::~ECCPoint() { |
192 | 27.6k | CF_NORET(wc_ecc_del_point(point)); |
193 | 27.6k | } |
194 | | |
195 | 40.1k | ecc_point* ECCPoint::GetPtr() { |
196 | 40.1k | uint8_t* out = nullptr; |
197 | 40.1k | ecc_point* newPoint = nullptr; |
198 | | |
199 | 40.1k | if ( locked == false && initialized == true ) { |
200 | 11.3k | bool exportToDER = false; |
201 | | |
202 | 11.3k | try { |
203 | 11.3k | exportToDER = ds.Get<bool>(); |
204 | 11.3k | } catch ( ... ) { } |
205 | | |
206 | 11.3k | if ( exportToDER == true ) { |
207 | 821 | bool compressed = false; |
208 | 821 | try { |
209 | 821 | compressed = ds.Get<bool>(); |
210 | 821 | } catch ( ... ) { } |
211 | | |
212 | 821 | const int curveIdx = wc_ecc_get_curve_idx(curveID); |
213 | 821 | CF_CHECK_NE(newPoint = wc_ecc_new_point_h(nullptr), nullptr); |
214 | | |
215 | 605 | word32 outSz = 0xFFFF; |
216 | 605 | try { outSz = ds.Get<word32>() & 0xFFFF; } catch ( ... ) { } |
217 | | |
218 | 605 | out = util::malloc(outSz); |
219 | | |
220 | 605 | if ( compressed == false ) { |
221 | 266 | WC_CHECK_EQ(wc_ecc_export_point_der(curveIdx, point, out, &outSz), 0); |
222 | 339 | } else { |
223 | 339 | WC_CHECK_EQ(wc_ecc_export_point_der(curveIdx, point, out, &outSz), 0); |
224 | | //WC_CHECK_EQ(wc_ecc_export_point_der_compressed(curveIdx, point, out, &outSz), 0); |
225 | 110 | } |
226 | | |
227 | 214 | { |
228 | 214 | haveAllocFailure = false; |
229 | 214 | const bool success = wc_ecc_import_point_der(out, outSz, curveIdx, newPoint) == 0; |
230 | | |
231 | 214 | if ( success ) { |
232 | | /* Point imported. Replace old point with new point. */ |
233 | | |
234 | 214 | CF_NORET(wc_ecc_del_point(point)); |
235 | 214 | point = newPoint; |
236 | 214 | newPoint = nullptr; |
237 | 214 | } else { |
238 | | /* Failure */ |
239 | |
|
240 | 0 | if ( haveAllocFailure == false ) { |
241 | | /* Failure is only acceptable if an allocation failure occured, crash otherwise */ |
242 | 0 | CF_ASSERT(0, "Cannot import DER-exported ECC point"); |
243 | 0 | } |
244 | 0 | } |
245 | 214 | } |
246 | 214 | } |
247 | 11.3k | } |
248 | | |
249 | 40.1k | end: |
250 | 40.1k | util::free(out); |
251 | 40.1k | CF_NORET(wc_ecc_del_point(newPoint)); |
252 | | |
253 | 40.1k | return point; |
254 | 40.1k | } |
255 | | |
256 | 8.70k | bool ECCPoint::Set(const component::BignumPair& xy, const bool pointCheck) { |
257 | 8.70k | bool ret = false; |
258 | | |
259 | 8.70k | wolfCrypt_bignum::Bignum x(ds), y(ds), z(ds); |
260 | | |
261 | 8.70k | CF_CHECK_TRUE(x.Set(xy.first)); |
262 | 8.54k | CF_CHECK_TRUE(y.Set(xy.second)); |
263 | 8.44k | CF_CHECK_TRUE(z.Set("1")); |
264 | | |
265 | 8.44k | WC_CHECK_EQ(mp_copy(x.GetPtr(), point->x), MP_OKAY); |
266 | 8.44k | WC_CHECK_EQ(mp_copy(y.GetPtr(), point->y), MP_OKAY); |
267 | 8.44k | WC_CHECK_EQ(mp_copy(z.GetPtr(), point->z), MP_OKAY); |
268 | | |
269 | 8.44k | if ( pointCheck ) { |
270 | 0 | CF_CHECK_TRUE(CurveCheck()); |
271 | 0 | } |
272 | | |
273 | 8.44k | SetInitialized(); |
274 | | |
275 | 8.44k | ret = true; |
276 | | |
277 | 8.70k | end: |
278 | 8.70k | return ret; |
279 | 8.44k | } |
280 | | |
281 | 4.49k | bool ECCPoint::ToProjective(wolfCrypt_bignum::Bignum& prime) { |
282 | 4.49k | bool ret = false; |
283 | | |
284 | 4.49k | wolfCrypt_bignum::Bignum mu(ds); |
285 | | |
286 | 4.49k | WC_CHECK_EQ(mp_montgomery_calc_normalization(mu.GetPtr(), prime.GetPtr()), MP_OKAY); |
287 | | |
288 | 4.49k | if ( mp_cmp_d(mu.GetPtr(), 1) != MP_EQ ) { |
289 | 3.12k | WC_CHECK_EQ(mp_mulmod(point->x, mu.GetPtr(), prime.GetPtr(), point->x), MP_OKAY); |
290 | 3.06k | WC_CHECK_EQ(mp_mulmod(point->y, mu.GetPtr(), prime.GetPtr(), point->y), MP_OKAY); |
291 | 2.99k | WC_CHECK_EQ(mp_mulmod(point->z, mu.GetPtr(), prime.GetPtr(), point->z), MP_OKAY); |
292 | 2.95k | } |
293 | | |
294 | | /* Lock so it isn't attempted to export/import the projective point in GetPtr(), |
295 | | * which will lead to incorrect results |
296 | | */ |
297 | 4.33k | Lock(); |
298 | | |
299 | 4.33k | ret = true; |
300 | | |
301 | 4.49k | end: |
302 | 4.49k | return ret; |
303 | 4.33k | } |
304 | | |
305 | 6.58k | bool ECCPoint::CurveCheck(void) const { |
306 | 6.58k | const int curveIdx = wc_ecc_get_curve_idx(curveID); |
307 | 6.58k | return wc_ecc_point_is_on_curve(point, curveIdx) == 0; |
308 | 6.58k | } |
309 | | |
310 | 12.0k | void ECCPoint::Lock(void) { |
311 | 12.0k | locked = true; |
312 | 12.0k | } |
313 | | |
314 | 14.4k | void ECCPoint::SetInitialized(void) { |
315 | 14.4k | initialized = true; |
316 | 14.4k | } |
317 | | |
318 | 5.85k | std::optional<component::BignumPair> ECCPoint::ToBignumPair(void) { |
319 | 5.85k | std::optional<component::BignumPair> ret = std::nullopt; |
320 | | |
321 | 5.85k | wolfCrypt_bignum::Bignum pub_x(GetPtr()->x, ds); |
322 | | |
323 | | /* Pointer is stored in pub_x; lock to prevent UAF */ |
324 | 5.85k | Lock(); |
325 | | |
326 | 5.85k | wolfCrypt_bignum::Bignum pub_y(GetPtr()->y, ds); |
327 | | |
328 | 5.85k | std::optional<std::string> pub_x_str, pub_y_str; |
329 | 5.85k | CF_CHECK_NE(pub_x_str = pub_x.ToDecString(), std::nullopt); |
330 | 5.85k | CF_CHECK_NE(pub_y_str = pub_y.ToDecString(), std::nullopt); |
331 | | |
332 | 5.84k | ret = { *pub_x_str, *pub_y_str }; |
333 | 5.85k | end: |
334 | | |
335 | 5.85k | return ret; |
336 | 5.84k | } |
337 | | |
338 | 2.13k | int ECCPoint::Compare(ECCPoint& other) { |
339 | 2.13k | return wc_ecc_cmp_point(GetPtr(), other.GetPtr()); |
340 | 2.13k | } |
341 | | |
342 | 2.29k | std::optional<bool> ECCPoint::IsNeg(ECCPoint& other, wolfCrypt_bignum::Bignum& prime) { |
343 | 2.29k | std::optional<bool> ret = std::nullopt; |
344 | | |
345 | 2.29k | wolfCrypt_bignum::Bignum neg(ds); |
346 | 2.29k | if ( mp_sub(prime.GetPtr(), other.GetPtr()->y, neg.GetPtr()) == MP_OKAY) { |
347 | 2.29k | ret = static_cast<bool>(mp_cmp(point->y, neg.GetPtr()) == MP_EQ); |
348 | 2.29k | } |
349 | | |
350 | 2.29k | return ret; |
351 | 2.29k | } |
352 | | |
353 | 4.82k | std::optional<component::ECC_PublicKey> OpECC_PrivateToPublic_Generic(operation::ECC_PrivateToPublic& op) { |
354 | 4.82k | std::optional<component::ECC_PublicKey> ret = std::nullopt; |
355 | 4.82k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
356 | 4.82k | wolfCrypt_detail::SetGlobalDs(&ds); |
357 | | |
358 | 4.82k | try { |
359 | 4.82k | ECCKey key(ds); |
360 | | |
361 | | /* Initialize */ |
362 | 4.82k | { |
363 | 4.82k | CF_CHECK_EQ(key.SetCurve(op.curveType), true); |
364 | 2.65k | CF_CHECK_EQ(key.LoadPrivateKey(op.priv), true); |
365 | 2.18k | } |
366 | | |
367 | | /* Process/Finalize */ |
368 | 0 | { |
369 | 2.18k | auto pub = key.MakePub(); |
370 | 2.18k | CF_CHECK_NE(pub, std::nullopt); |
371 | | |
372 | 1.95k | ret = pub->ToBignumPair(); |
373 | 1.95k | } |
374 | 1.95k | } catch ( ... ) { } |
375 | | |
376 | 4.82k | end: |
377 | | |
378 | 4.82k | wolfCrypt_detail::UnsetGlobalDs(); |
379 | 4.82k | return ret; |
380 | 4.82k | } |
381 | | |
382 | 5.73k | std::optional<bool> OpECC_ValidatePubkey_Generic(operation::ECC_ValidatePubkey& op) { |
383 | 5.73k | std::optional<bool> ret = std::nullopt; |
384 | 5.73k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
385 | 5.73k | wolfCrypt_detail::SetGlobalDs(&ds); |
386 | | |
387 | 5.73k | std::optional<int> curveID; |
388 | | |
389 | 5.73k | try { |
390 | 5.73k | ECCKey key(ds); |
391 | 5.73k | { |
392 | 5.73k | const char* name = nullptr; |
393 | | |
394 | 5.73k | CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt); |
395 | | |
396 | 4.09k | CF_CHECK_NE(name = wc_ecc_get_name(*curveID), nullptr); |
397 | | |
398 | 3.86k | WC_CHECK_EQ(wc_ecc_import_raw( |
399 | 3.40k | key.GetPtr(), |
400 | 3.40k | util::DecToHex(op.pub.first.ToTrimmedString()).c_str(), |
401 | 3.40k | util::DecToHex(op.pub.second.ToTrimmedString()).c_str(), |
402 | 3.40k | nullptr, |
403 | 3.40k | name), 0); |
404 | 3.40k | haveAllocFailure = false; |
405 | 3.40k | ret = wc_ecc_check_key(key.GetPtr()) == 0; |
406 | 3.40k | if ( *ret == false && haveAllocFailure == true ) { |
407 | 620 | ret = std::nullopt; |
408 | 620 | } |
409 | 3.40k | } |
410 | 3.40k | } catch ( ... ) { } |
411 | | |
412 | 5.73k | end: |
413 | | |
414 | 5.73k | wolfCrypt_detail::UnsetGlobalDs(); |
415 | 5.73k | return ret; |
416 | 5.73k | } |
417 | | |
418 | 6.92k | std::optional<bool> OpECDSA_Verify_Generic(operation::ECDSA_Verify& op) { |
419 | 6.92k | std::optional<bool> ret = std::nullopt; |
420 | 6.92k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
421 | 6.92k | wolfCrypt_detail::SetGlobalDs(&ds); |
422 | | |
423 | 6.92k | std::optional<int> curveID; |
424 | 6.92k | uint8_t* sig = nullptr; |
425 | 6.92k | uint8_t* hash = nullptr; |
426 | 6.92k | word32 sigSz = ECC_MAX_SIG_SIZE; |
427 | 6.92k | int verify; |
428 | | |
429 | 6.92k | { |
430 | 6.92k | try { |
431 | 6.92k | sigSz = ds.Get<uint8_t>(); |
432 | 6.92k | } catch ( fuzzing::datasource::Datasource::OutOfData ) { } |
433 | | |
434 | 6.92k | sig = util::malloc(sigSz); |
435 | 6.92k | } |
436 | | |
437 | 6.92k | try { |
438 | 6.92k | ECCKey key(ds); |
439 | 6.92k | { |
440 | 6.92k | const char* name = nullptr; |
441 | | |
442 | 6.92k | CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt); |
443 | | |
444 | 6.25k | CF_CHECK_NE(name = wc_ecc_get_name(*curveID), nullptr); |
445 | | |
446 | 5.89k | WC_CHECK_EQ(wc_ecc_import_raw( |
447 | 5.63k | key.GetPtr(), |
448 | 5.63k | util::DecToHex(op.signature.pub.first.ToTrimmedString()).c_str(), |
449 | 5.63k | util::DecToHex(op.signature.pub.second.ToTrimmedString()).c_str(), |
450 | 5.63k | nullptr, |
451 | 5.63k | name), 0); |
452 | 5.63k | WC_CHECK_EQ(wc_ecc_check_key(key.GetPtr()), 0); |
453 | 5.19k | } |
454 | | |
455 | 5.19k | WC_CHECK_EQ(wc_ecc_rs_to_sig( |
456 | 4.83k | util::DecToHex(op.signature.signature.first.ToTrimmedString()).c_str(), |
457 | 4.83k | util::DecToHex(op.signature.signature.second.ToTrimmedString()).c_str(), |
458 | 4.83k | sig, &sigSz), 0); |
459 | | |
460 | 4.83k | if ( op.digestType.Get() == CF_DIGEST("NULL") ) { |
461 | 4.54k | const auto CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType); |
462 | 4.54k | WC_CHECK_EQ(wc_ecc_verify_hash(sig, sigSz, CT.GetPtr(), CT.GetSize(), &verify, key.GetPtr()), 0); |
463 | 4.09k | } else { |
464 | 298 | std::optional<wc_HashType> hashType; |
465 | 298 | CF_CHECK_NE(hashType = wolfCrypt_detail::toHashType(op.digestType), std::nullopt); |
466 | | |
467 | 298 | const auto hashSize = wc_HashGetDigestSize(*hashType); |
468 | 298 | hash = util::malloc(hashSize); |
469 | | |
470 | 298 | WC_CHECK_EQ(wc_Hash(*hashType, op.cleartext.GetPtr(), op.cleartext.GetSize(), hash, hashSize), 0); |
471 | | |
472 | 298 | const auto CT = Buffer(hash, hashSize).ECDSA_RandomPad(ds, op.curveType); |
473 | 298 | WC_CHECK_EQ(wc_ecc_verify_hash(sig, sigSz, CT.GetPtr(), CT.GetSize(), &verify, key.GetPtr()), 0); |
474 | 298 | } |
475 | | |
476 | 4.39k | ret = verify ? true : false; |
477 | 4.39k | } catch ( ... ) { } |
478 | | |
479 | 6.92k | end: |
480 | | |
481 | 6.92k | util::free(sig); |
482 | 6.92k | util::free(hash); |
483 | | |
484 | 6.92k | wolfCrypt_detail::UnsetGlobalDs(); |
485 | | |
486 | 6.92k | return ret; |
487 | 6.92k | } |
488 | | |
489 | 6.07k | std::optional<component::ECDSA_Signature> OpECDSA_Sign_Generic(operation::ECDSA_Sign& op) { |
490 | 6.07k | std::optional<component::ECDSA_Signature> ret = std::nullopt; |
491 | 6.07k | if ( op.UseRandomNonce() == false && op.UseSpecifiedNonce() == false ) { |
492 | 326 | return ret; |
493 | 326 | } |
494 | | |
495 | 5.74k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
496 | 5.74k | wolfCrypt_detail::SetGlobalDs(&ds); |
497 | | |
498 | 5.74k | uint8_t* sig = nullptr; |
499 | 5.74k | word32 sigSz = ECC_MAX_SIG_SIZE; |
500 | 5.74k | Buffer CT; |
501 | 5.74k | uint8_t* hash = nullptr; |
502 | 5.74k | size_t hashSize = 0; |
503 | 5.74k | uint8_t* nonce_bytes = nullptr; |
504 | 5.74k | wolfCrypt_bignum::Bignum nonce(ds), r(ds), s(ds); |
505 | | |
506 | 5.74k | CF_CHECK_NE(op.priv.ToTrimmedString(), "0"); |
507 | | |
508 | 5.39k | { |
509 | 5.39k | try { |
510 | 5.39k | sigSz = ds.Get<uint8_t>(); |
511 | 5.39k | } catch ( fuzzing::datasource::Datasource::OutOfData ) { } |
512 | | |
513 | 5.39k | sig = util::malloc(sigSz); |
514 | 5.39k | } |
515 | | |
516 | 5.39k | try { |
517 | 5.39k | ECCKey key(ds); |
518 | 5.39k | CF_CHECK_EQ(key.SetCurve(op.curveType), true); |
519 | 5.04k | CF_CHECK_EQ(key.LoadPrivateKey(op.priv), true); |
520 | 4.95k | key.GetPtr()->type = ECC_PRIVATEKEY_ONLY; |
521 | | |
522 | 4.95k | if ( op.UseSpecifiedNonce() == true ) { |
523 | 2.36k | CF_CHECK_EQ(nonce.Set(op.nonce.ToString(ds)), true); |
524 | | |
525 | 2.32k | const size_t nonce_bytes_size = mp_unsigned_bin_size(nonce.GetPtr()); |
526 | | |
527 | | /* Convert nonce to byte array */ |
528 | 2.32k | nonce_bytes = util::malloc(nonce_bytes_size); |
529 | 2.32k | CF_CHECK_EQ(mp_to_unsigned_bin(nonce.GetPtr(), nonce_bytes), 0); |
530 | | |
531 | | /* Set nonce */ |
532 | 2.27k | WC_CHECK_EQ(wc_ecc_sign_set_k(nonce_bytes, nonce_bytes_size, key.GetPtr()), 0); |
533 | 2.17k | } |
534 | | |
535 | 4.76k | auto pub = key.MakePub(); |
536 | 4.76k | CF_CHECK_NE(pub, std::nullopt); |
537 | | |
538 | 4.63k | if ( op.digestType.Get() == CF_DIGEST("NULL") ) { |
539 | 4.29k | CT = op.cleartext.ECDSA_RandomPad(ds, op.curveType); |
540 | 4.29k | } else { |
541 | 334 | std::optional<wc_HashType> hashType; |
542 | 334 | CF_CHECK_NE(hashType = wolfCrypt_detail::toHashType(op.digestType), std::nullopt); |
543 | | |
544 | 334 | hashSize = wc_HashGetDigestSize(*hashType); |
545 | 334 | hash = util::malloc(hashSize); |
546 | | |
547 | 334 | WC_CHECK_EQ(wc_Hash(*hashType, op.cleartext.GetPtr(), op.cleartext.GetSize(), hash, hashSize), 0); |
548 | | |
549 | 334 | CT = Buffer(hash, hashSize).ECDSA_RandomPad(ds, op.curveType); |
550 | 334 | } |
551 | | |
552 | | /* Sign */ |
553 | 8.64k | WC_CHECK_EQ(wc_ecc_sign_hash(CT.GetPtr(), CT.GetSize(), sig, &sigSz, wolfCrypt_detail::GetRNG(), key.GetPtr()), 0); |
554 | | |
555 | | /* Verify */ |
556 | 8.64k | { |
557 | 8.64k | int verify; |
558 | 8.64k | haveAllocFailure = false; |
559 | 8.64k | if ( wc_ecc_verify_hash(sig, sigSz, CT.GetPtr(), CT.GetSize(), &verify, key.GetPtr()) == 0 && haveAllocFailure == false ) { |
560 | 3.57k | CF_ASSERT(verify, "Cannot verify generated signature"); |
561 | 3.57k | } |
562 | 8.64k | } |
563 | | |
564 | 4.00k | CF_CHECK_EQ(DecodeECC_DSA_Sig(sig, sigSz, r.GetPtr(), s.GetPtr()), 0); |
565 | 4.00k | { |
566 | 4.00k | std::optional<std::string> r_str, s_str; |
567 | | |
568 | 4.00k | if ( op.curveType.Get() == CF_ECC_CURVE("secp256k1") ) { |
569 | 287 | wolfCrypt_bignum::Bignum SMax(ds); |
570 | 287 | CF_CHECK_EQ(SMax.Set("57896044618658097711785492504343953926418782139537452191302581570759080747168"), true); |
571 | 287 | if ( mp_cmp(s.GetPtr(), SMax.GetPtr()) == 1 ) { |
572 | 154 | wolfCrypt_bignum::Bignum SSub(ds); |
573 | 154 | CF_CHECK_EQ(SSub.Set("115792089237316195423570985008687907852837564279074904382605163141518161494337"), true); |
574 | 154 | CF_CHECK_EQ(mp_sub(SSub.GetPtr(), s.GetPtr(), s.GetPtr()), 0); |
575 | 154 | } |
576 | 3.72k | } else if ( op.curveType.Get() == CF_ECC_CURVE("secp256r1") ) { |
577 | 1.10k | wolfCrypt_bignum::Bignum SMax(ds); |
578 | 1.10k | CF_CHECK_EQ(SMax.Set("57896044605178124381348723474703786764998477612067880171211129530534256022184"), true); |
579 | 1.10k | if ( mp_cmp(s.GetPtr(), SMax.GetPtr()) == 1 ) { |
580 | 595 | wolfCrypt_bignum::Bignum SSub(ds); |
581 | 595 | CF_CHECK_EQ(SSub.Set("115792089210356248762697446949407573529996955224135760342422259061068512044369"), true); |
582 | 595 | CF_CHECK_EQ(mp_sub(SSub.GetPtr(), s.GetPtr(), s.GetPtr()), 0); |
583 | 595 | } |
584 | 1.10k | } |
585 | | |
586 | 4.00k | CF_CHECK_NE(r_str = r.ToDecString(), std::nullopt); |
587 | 4.00k | CF_CHECK_NE(s_str = s.ToDecString(), std::nullopt); |
588 | | |
589 | 4.00k | const auto pub2 = pub->ToBignumPair(); |
590 | 4.00k | CF_CHECK_NE(pub2, std::nullopt); |
591 | | |
592 | 3.99k | ret = component::ECDSA_Signature({*r_str, *s_str}, *pub2); |
593 | 3.99k | } |
594 | 3.99k | } catch ( ... ) { } |
595 | 5.74k | end: |
596 | | |
597 | 5.74k | util::free(sig); |
598 | 5.74k | util::free(hash); |
599 | 5.74k | util::free(nonce_bytes); |
600 | | |
601 | 5.74k | wolfCrypt_detail::UnsetGlobalDs(); |
602 | | |
603 | 5.74k | return ret; |
604 | 5.39k | } |
605 | | |
606 | 2.00k | std::optional<component::Ciphertext> OpECIES_Encrypt_Generic(operation::ECIES_Encrypt& op) { |
607 | 2.00k | std::optional<component::Ciphertext> ret = std::nullopt; |
608 | | #if !defined(HAVE_ECC_ENCRYPT) |
609 | | (void)op; |
610 | | #else |
611 | 2.00k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
612 | 2.00k | wolfCrypt_detail::SetGlobalDs(&ds); |
613 | 2.00k | uint8_t* out = nullptr; |
614 | | |
615 | 2.00k | CF_CHECK_TRUE(op.cipherType.Is(CF_CIPHER("AES_128_CBC"))); |
616 | 1.55k | CF_CHECK_EQ(op.iv, std::nullopt); |
617 | | |
618 | 1.50k | try { |
619 | 1.50k | ECCKey priv(ds), pub(ds); |
620 | 1.50k | word32 outSz = ds.Get<uint32_t>() % 0xFFFFFF; |
621 | | |
622 | | /* Initialize private key */ |
623 | 1.50k | { |
624 | 1.50k | CF_CHECK_TRUE(priv.SetCurve(op.curveType)); |
625 | 1.43k | CF_CHECK_TRUE(priv.LoadPrivateKey(op.priv)); |
626 | 1.36k | CF_CHECK_TRUE(priv.SetRNG()); |
627 | 1.36k | } |
628 | | |
629 | | /* Initialize public key */ |
630 | 0 | { |
631 | 1.36k | std::optional<int> curveID; |
632 | 1.36k | const char* name = nullptr; |
633 | | |
634 | 1.36k | CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt); |
635 | | |
636 | 1.36k | CF_CHECK_NE(name = wc_ecc_get_name(*curveID), nullptr); |
637 | | |
638 | 1.36k | WC_CHECK_EQ(wc_ecc_import_raw( |
639 | 1.30k | pub.GetPtr(), |
640 | 1.30k | util::DecToHex(op.pub.first.ToTrimmedString()).c_str(), |
641 | 1.30k | util::DecToHex(op.pub.second.ToTrimmedString()).c_str(), |
642 | 1.30k | nullptr, |
643 | 1.30k | name), 0); |
644 | | |
645 | 1.30k | CF_CHECK_TRUE(pub.SetRNG()); |
646 | 1.30k | } |
647 | | |
648 | 0 | out = util::malloc(outSz); |
649 | | |
650 | 1.30k | WC_CHECK_EQ(wc_ecc_encrypt(priv.GetPtr(), pub.GetPtr(), op.cleartext.GetPtr(), op.cleartext.GetSize(), out, &outSz, nullptr), 0); |
651 | | |
652 | 704 | ret = component::Ciphertext(Buffer(out, outSz)); |
653 | 704 | } catch ( ... ) { } |
654 | | |
655 | 2.00k | end: |
656 | 2.00k | util::free(out); |
657 | | |
658 | 2.00k | wolfCrypt_detail::UnsetGlobalDs(); |
659 | 2.00k | #endif |
660 | 2.00k | return ret; |
661 | 1.50k | } |
662 | | |
663 | 1.56k | std::optional<component::Cleartext> OpECIES_Decrypt_Generic(operation::ECIES_Decrypt& op) { |
664 | 1.56k | std::optional<component::Cleartext> ret = std::nullopt; |
665 | | #if !defined(HAVE_ECC_ENCRYPT) |
666 | | (void)op; |
667 | | #else |
668 | 1.56k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
669 | 1.56k | wolfCrypt_detail::SetGlobalDs(&ds); |
670 | 1.56k | uint8_t* out = nullptr; |
671 | | |
672 | 1.56k | CF_CHECK_TRUE(op.cipherType.Is(CF_CIPHER("AES_128_CBC"))); |
673 | 1.14k | CF_CHECK_EQ(op.iv, std::nullopt); |
674 | | |
675 | 1.09k | try { |
676 | 1.09k | ECCKey priv(ds), pub(ds); |
677 | 1.09k | word32 outSz = ds.Get<uint32_t>() % 0xFFFFFF; |
678 | | |
679 | | /* Initialize private key */ |
680 | 1.09k | { |
681 | 1.09k | CF_CHECK_TRUE(priv.SetCurve(op.curveType)); |
682 | 1.02k | CF_CHECK_TRUE(priv.LoadPrivateKey(op.priv)); |
683 | 956 | CF_CHECK_TRUE(priv.SetRNG()); |
684 | 956 | } |
685 | | |
686 | | /* Initialize public key */ |
687 | 0 | { |
688 | 956 | std::optional<int> curveID; |
689 | 956 | const char* name = nullptr; |
690 | | |
691 | 956 | CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt); |
692 | | |
693 | 956 | CF_CHECK_NE(name = wc_ecc_get_name(*curveID), nullptr); |
694 | | |
695 | 956 | WC_CHECK_EQ(wc_ecc_import_raw( |
696 | 905 | pub.GetPtr(), |
697 | 905 | util::DecToHex(op.pub.first.ToTrimmedString()).c_str(), |
698 | 905 | util::DecToHex(op.pub.second.ToTrimmedString()).c_str(), |
699 | 905 | nullptr, |
700 | 905 | name), 0); |
701 | | |
702 | 905 | CF_CHECK_TRUE(pub.SetRNG()); |
703 | 905 | } |
704 | | |
705 | 0 | out = util::malloc(outSz); |
706 | | |
707 | 905 | WC_CHECK_EQ(wc_ecc_decrypt(priv.GetPtr(), pub.GetPtr(), op.ciphertext.GetPtr(), op.ciphertext.GetSize(), out, &outSz, nullptr), 0); |
708 | | |
709 | 326 | ret = component::Cleartext(Buffer(out, outSz)); |
710 | 326 | } catch ( ... ) { } |
711 | | |
712 | 1.56k | end: |
713 | 1.56k | util::free(out); |
714 | | |
715 | 1.56k | wolfCrypt_detail::UnsetGlobalDs(); |
716 | 1.56k | #endif |
717 | 1.56k | return ret; |
718 | 1.09k | } |
719 | | |
720 | 1.13k | std::optional<component::Secret> OpECDH_Derive(operation::ECDH_Derive& op) { |
721 | 1.13k | std::optional<component::Secret> ret = std::nullopt; |
722 | 1.13k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
723 | 1.13k | wolfCrypt_detail::SetGlobalDs(&ds); |
724 | | |
725 | | /* try/catch because ECCKey constructor may throw if allocation fails */ |
726 | 1.13k | try { |
727 | | /* TODO dynamic size */ |
728 | 1.13k | uint8_t out[1024]; |
729 | 1.13k | word32 outlen = sizeof(out); |
730 | 1.13k | ECCKey priv(ds), pub(ds); |
731 | | |
732 | | /* Initialize private key */ |
733 | 1.13k | { |
734 | 1.13k | CF_CHECK_TRUE(priv.SetCurve(op.curveType)); |
735 | 887 | CF_CHECK_TRUE(priv.LoadPrivateKey(op.priv)); |
736 | 818 | CF_CHECK_TRUE(priv.SetRNG()); |
737 | 818 | } |
738 | | |
739 | | /* Initialize public key */ |
740 | 0 | { |
741 | 818 | std::optional<int> curveID; |
742 | 818 | const char* name = nullptr; |
743 | | |
744 | 818 | CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt); |
745 | | |
746 | 818 | CF_CHECK_NE(name = wc_ecc_get_name(*curveID), nullptr); |
747 | | |
748 | 818 | WC_CHECK_EQ(wc_ecc_import_raw( |
749 | 729 | pub.GetPtr(), |
750 | 729 | util::DecToHex(op.pub.first.ToTrimmedString()).c_str(), |
751 | 729 | util::DecToHex(op.pub.second.ToTrimmedString()).c_str(), |
752 | 729 | nullptr, |
753 | 729 | name), 0); |
754 | 729 | WC_CHECK_EQ(wc_ecc_check_key(pub.GetPtr()), 0); |
755 | 585 | } |
756 | | |
757 | 585 | WC_CHECK_EQ(wc_ecc_shared_secret(priv.GetPtr(), pub.GetPtr(), out, &outlen), 0); |
758 | | |
759 | 514 | ret = component::Secret(Buffer(out, outlen)); |
760 | 514 | } catch ( ... ) { } |
761 | | |
762 | 1.13k | end: |
763 | 1.13k | wolfCrypt_detail::UnsetGlobalDs(); |
764 | | |
765 | 1.13k | return ret; |
766 | 1.13k | } |
767 | | |
768 | 1.05k | std::optional<component::ECC_Point> OpECC_Point_Add(operation::ECC_Point_Add& op) { |
769 | 1.05k | std::optional<component::ECC_Point> ret = std::nullopt; |
770 | 1.05k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
771 | 1.05k | wolfCrypt_detail::SetGlobalDs(&ds); |
772 | | |
773 | 1.05k | std::optional<int> curveID; |
774 | 1.05k | int curveIdx; |
775 | 1.05k | const ecc_set_type* curve = nullptr; |
776 | | |
777 | 1.05k | CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt); |
778 | | |
779 | 1.00k | CF_CHECK_NE(curveIdx = wc_ecc_get_curve_idx(*curveID), ECC_CURVE_INVALID); |
780 | 952 | CF_CHECK_NE(curve = wc_ecc_get_curve_params(curveIdx), nullptr); |
781 | | |
782 | | /* try/catch because ECCPoint constructor may throw if allocation fails */ |
783 | 952 | try { |
784 | 952 | ECCPoint res(ds, *curveID), a(ds, *curveID), b(ds, *curveID); |
785 | 952 | wolfCrypt_bignum::Bignum Af(ds), prime(ds), mu(ds); |
786 | 952 | mp_digit mp; |
787 | 952 | bool valid = false; |
788 | 952 | std::optional<bool> is_neg = std::nullopt; |
789 | | |
790 | | /* Set points */ |
791 | 952 | CF_CHECK_TRUE(a.Set(op.a)); |
792 | 939 | CF_CHECK_TRUE(b.Set(op.b)); |
793 | | |
794 | 928 | valid = a.CurveCheck() && b.CurveCheck(); |
795 | | |
796 | | /* Retrieve curve parameter */ |
797 | 928 | CF_CHECK_EQ(Af.Set(util::HexToDec(curve->Af)), true); |
798 | 928 | CF_CHECK_EQ(prime.Set(util::HexToDec(curve->prime)), true); |
799 | | |
800 | 928 | is_neg = a.IsNeg(b, prime); |
801 | | |
802 | 928 | CF_CHECK_TRUE(a.ToProjective(prime)); |
803 | 911 | CF_CHECK_TRUE(b.ToProjective(prime)); |
804 | | |
805 | 897 | WC_CHECK_EQ(mp_montgomery_setup(prime.GetPtr(), &mp), MP_OKAY); |
806 | | |
807 | | #if defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_PUBLIC_ECC_ADD_DBL) |
808 | | goto end; |
809 | | #else |
810 | 897 | { |
811 | 897 | bool dbl = false; |
812 | 897 | bool safe = false; |
813 | | |
814 | 897 | if ( a.Compare(b) == MP_EQ ) { |
815 | 89 | try { dbl = ds.Get<bool>(); } catch ( ... ) { } |
816 | 89 | } |
817 | | |
818 | | #if !(defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_PUBLIC_ECC_ADD_DBL)) |
819 | | try { safe = ds.Get<bool>(); } catch ( ... ) { } |
820 | | #endif |
821 | | |
822 | 897 | if ( safe ) { |
823 | 0 | #if defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_PUBLIC_ECC_ADD_DBL) |
824 | 0 | CF_UNREACHABLE(); |
825 | | #else |
826 | | int infinity; |
827 | | |
828 | | if ( dbl == true ) { |
829 | | WC_CHECK_EQ(ecc_projective_dbl_point_safe(a.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp), 0); |
830 | | } else { |
831 | | WC_CHECK_EQ(ecc_projective_add_point_safe(a.GetPtr(), b.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp, &infinity), 0); |
832 | | } |
833 | | #endif |
834 | 897 | } else { |
835 | 897 | if ( dbl == true ) { |
836 | 18 | WC_CHECK_EQ(ecc_projective_dbl_point(a.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp), 0); |
837 | 879 | } else { |
838 | 879 | WC_CHECK_EQ(ecc_projective_add_point(a.GetPtr(), b.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp), 0); |
839 | | |
840 | | /* Do not return result if inputs are negations of the same point */ |
841 | 820 | CF_CHECK_FALSE(is_neg && *is_neg); |
842 | 818 | } |
843 | 897 | } |
844 | | |
845 | | /* Lock to prevent exporting the projective point */ |
846 | 826 | res.Lock(); |
847 | 826 | } |
848 | 0 | #endif |
849 | | |
850 | | /* To affine */ |
851 | 826 | WC_CHECK_EQ(ecc_map(res.GetPtr(), prime.GetPtr(), mp), MP_OKAY); |
852 | | |
853 | | /* Only return the result if the input points are valid */ |
854 | 816 | CF_CHECK_TRUE(valid); |
855 | | |
856 | | /* Only return the result if the output point is valid */ |
857 | 93 | CF_CHECK_TRUE(res.CurveCheck()); |
858 | | |
859 | 92 | ret = res.ToBignumPair(); |
860 | 92 | } catch ( ... ) { } |
861 | | |
862 | 1.05k | end: |
863 | 1.05k | wolfCrypt_detail::UnsetGlobalDs(); |
864 | | |
865 | 1.05k | return ret; |
866 | 952 | } |
867 | | |
868 | 4.97k | std::optional<component::ECC_Point> OpECC_Point_Mul(operation::ECC_Point_Mul& op) { |
869 | 4.97k | std::optional<component::ECC_Point> ret = std::nullopt; |
870 | 4.97k | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
871 | 4.97k | wolfCrypt_detail::SetGlobalDs(&ds); |
872 | | |
873 | 4.97k | std::optional<int> curveID; |
874 | 4.97k | int curveIdx; |
875 | 4.97k | const ecc_set_type* curve = nullptr; |
876 | | |
877 | 4.97k | CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt); |
878 | | |
879 | 4.60k | CF_CHECK_NE(curveIdx = wc_ecc_get_curve_idx(*curveID), ECC_CURVE_INVALID); |
880 | 4.21k | CF_CHECK_NE(curve = wc_ecc_get_curve_params(curveIdx), nullptr); |
881 | | |
882 | | /* try/catch because ECCPoint constructor may throw if allocation fails */ |
883 | 4.21k | try { |
884 | 4.21k | ECCPoint res(ds, *curveID), a(ds, *curveID); |
885 | 4.21k | wolfCrypt_bignum::Bignum b(ds), Af(ds), prime(ds); |
886 | 4.21k | bool valid = false; |
887 | | |
888 | | /* Set point */ |
889 | 4.21k | CF_CHECK_TRUE(a.Set(op.a)); |
890 | 4.09k | valid = a.CurveCheck(); |
891 | | |
892 | | /* Set multiplier */ |
893 | 4.09k | CF_CHECK_EQ(b.Set(op.b.ToString(ds)), true); |
894 | | |
895 | | /* Retrieve curve parameters */ |
896 | 4.03k | CF_CHECK_EQ(Af.Set(util::HexToDec(curve->Af)), true); |
897 | 4.03k | CF_CHECK_EQ(prime.Set(util::HexToDec(curve->prime)), true); |
898 | | |
899 | | /* Multiply */ |
900 | 4.03k | WC_CHECK_EQ(wc_ecc_mulmod_ex(b.GetPtr(), a.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), 1, nullptr), 0); |
901 | | |
902 | | /* Only return the result if the input point is valid */ |
903 | 3.11k | CF_CHECK_TRUE(valid); |
904 | | |
905 | 690 | ret = res.ToBignumPair(); |
906 | 690 | } catch ( ... ) { } |
907 | | |
908 | 4.97k | end: |
909 | 4.97k | wolfCrypt_detail::UnsetGlobalDs(); |
910 | | |
911 | 4.97k | return ret; |
912 | 4.21k | } |
913 | | |
914 | 0 | std::optional<component::ECC_Point> OpECC_Point_Dbl(operation::ECC_Point_Dbl& op) { |
915 | 0 | std::optional<component::ECC_Point> ret = std::nullopt; |
916 | 0 | Datasource ds(op.modifier.GetPtr(), op.modifier.GetSize()); |
917 | 0 | wolfCrypt_detail::SetGlobalDs(&ds); |
918 | |
|
919 | 0 | std::optional<int> curveID; |
920 | 0 | int curveIdx; |
921 | 0 | const ecc_set_type* curve = nullptr; |
922 | |
|
923 | 0 | CF_CHECK_NE(curveID = wolfCrypt_detail::toCurveID(op.curveType), std::nullopt); |
924 | |
|
925 | 0 | CF_CHECK_NE(curveIdx = wc_ecc_get_curve_idx(*curveID), ECC_CURVE_INVALID); |
926 | 0 | CF_CHECK_NE(curve = wc_ecc_get_curve_params(curveIdx), nullptr); |
927 | | |
928 | | /* try/catch because ECCPoint constructor may throw if allocation fails */ |
929 | 0 | try { |
930 | 0 | ECCPoint res(ds, *curveID), a(ds, *curveID); |
931 | 0 | wolfCrypt_bignum::Bignum Af(ds), prime(ds), mu(ds); |
932 | 0 | mp_digit mp; |
933 | 0 | bool valid = false; |
934 | | |
935 | | /* Set points */ |
936 | 0 | CF_CHECK_TRUE(a.Set(op.a)); |
937 | |
|
938 | 0 | valid = a.CurveCheck(); |
939 | | |
940 | | /* Retrieve curve parameter */ |
941 | 0 | CF_CHECK_EQ(Af.Set(util::HexToDec(curve->Af)), true); |
942 | 0 | CF_CHECK_EQ(prime.Set(util::HexToDec(curve->prime)), true); |
943 | |
|
944 | 0 | CF_CHECK_TRUE(a.ToProjective(prime)); |
945 | |
|
946 | 0 | WC_CHECK_EQ(mp_montgomery_setup(prime.GetPtr(), &mp), MP_OKAY); |
947 | |
|
948 | | #if defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_PUBLIC_ECC_ADD_DBL) |
949 | | goto end; |
950 | | #else |
951 | 0 | { |
952 | 0 | bool safe = false; |
953 | |
|
954 | | #if !(defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_PUBLIC_ECC_ADD_DBL)) |
955 | | try { safe = ds.Get<bool>(); } catch ( ... ) { } |
956 | | #endif |
957 | |
|
958 | 0 | if ( safe ) { |
959 | 0 | #if defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_PUBLIC_ECC_ADD_DBL) |
960 | 0 | CF_UNREACHABLE(); |
961 | | #else |
962 | | WC_CHECK_EQ(ecc_projective_dbl_point_safe(a.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp), 0); |
963 | | #endif |
964 | 0 | } else { |
965 | 0 | WC_CHECK_EQ(ecc_projective_dbl_point(a.GetPtr(), res.GetPtr(), Af.GetPtr(), prime.GetPtr(), mp), 0); |
966 | 0 | } |
967 | | |
968 | | /* Lock to prevent exporting the projective point */ |
969 | 0 | res.Lock(); |
970 | 0 | } |
971 | 0 | #endif |
972 | | |
973 | | /* To affine */ |
974 | 0 | WC_CHECK_EQ(ecc_map(res.GetPtr(), prime.GetPtr(), mp), MP_OKAY); |
975 | | |
976 | | /* Only return the result if the input points are valid */ |
977 | 0 | CF_CHECK_TRUE(valid); |
978 | | |
979 | | /* Only return the result if the output point is valid */ |
980 | 0 | CF_CHECK_TRUE(res.CurveCheck()); |
981 | |
|
982 | 0 | ret = res.ToBignumPair(); |
983 | 0 | } catch ( ... ) { } |
984 | | |
985 | 0 | end: |
986 | 0 | wolfCrypt_detail::UnsetGlobalDs(); |
987 | |
|
988 | 0 | return ret; |
989 | 0 | } |
990 | | |
991 | | } /* namespace wolfCrypt_detail */ |
992 | | } /* namespace module */ |
993 | | } /* namespace cryptofuzz */ |