/src/cryptofuzz-sp-math-all/modules/wolfcrypt/bn_ops.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include <cryptofuzz/util.h> |
2 | | #include <cryptofuzz/repository.h> |
3 | | #include <fuzzing/datasource/id.hpp> |
4 | | #include <type_traits> |
5 | | |
6 | | #include "bn_ops.h" |
7 | | |
8 | 19.1k | #define GET_WHICH(max) uint8_t which = 0; try { which = ds.Get<uint8_t>(); which %= ((max)+1); } catch ( ... ) { } |
9 | | #define GET_OPTIONAL_BN() (ds.Get<bool>() ? bn.GetDestPtr(3) : nullptr) |
10 | | |
11 | | namespace cryptofuzz { |
12 | | namespace module { |
13 | | |
14 | | namespace wolfCrypt_detail { |
15 | | WC_RNG* GetRNG(void); |
16 | | } |
17 | | |
18 | | namespace wolfCrypt_bignum { |
19 | | |
20 | | namespace wolfCrypt_bignum_detail { |
21 | | |
22 | | template <class ReturnType> |
23 | 29.3k | static ReturnType assertRet(const ReturnType ret) { |
24 | 29.3k | static_assert(std::is_same<ReturnType, int>()); |
25 | | |
26 | 29.3k | if ( ret > 0 ) { |
27 | 0 | CF_ASSERT(0, "Result of mp_* function is not negative or zero"); |
28 | 0 | } |
29 | | |
30 | 29.3k | return ret; |
31 | 29.3k | } |
32 | 25.2k | #define MP_CHECK_EQ(expr, res) CF_CHECK_EQ(::cryptofuzz::module::wolfCrypt_bignum::wolfCrypt_bignum_detail::assertRet(expr), res); |
33 | | |
34 | 3.47k | static int compare(Bignum& A, Bignum& B, Datasource& ds) { |
35 | 3.47k | util::HintBignumOpt(A.ToDecString()); |
36 | 3.47k | util::HintBignumOpt(B.ToDecString()); |
37 | | |
38 | 3.47k | bool swap = false; |
39 | 3.47k | try { |
40 | 3.47k | swap = ds.Get<bool>(); |
41 | 3.47k | } catch ( ... ) { } |
42 | | |
43 | 3.47k | if ( swap == false ) { |
44 | 2.61k | return mp_cmp(A.GetPtr(), B.GetPtr()); |
45 | 2.61k | } else { |
46 | 854 | const auto ret = mp_cmp(B.GetPtr(), A.GetPtr()); |
47 | | |
48 | | /* Because the operands were swapped, invert the result */ |
49 | 854 | if ( ret == MP_LT ) { |
50 | 294 | return MP_GT; |
51 | 560 | } else if ( ret == MP_GT ) { |
52 | 378 | return MP_LT; |
53 | 378 | } else { |
54 | 182 | return ret; |
55 | 182 | } |
56 | 854 | } |
57 | 3.47k | } |
58 | | |
59 | | #if !defined(WOLFSSL_SP_MATH) && (!defined(USE_FAST_MATH) || defined(WOLFSSL_SP_MATH_ALL)) |
60 | 392 | static std::optional<int> isPowerOf2(Bignum& A, Datasource& ds) { |
61 | 392 | std::optional<int> ret = std::nullopt; |
62 | 392 | wolfCrypt_bignum::Bignum tmp(ds); |
63 | | |
64 | 392 | auto numBits = mp_count_bits(A.GetPtr()); |
65 | 392 | CF_CHECK_GTE(numBits, 1); |
66 | 347 | numBits--; |
67 | 347 | MP_CHECK_EQ(mp_copy(A.GetPtr(), tmp.GetPtr()), MP_OKAY); |
68 | 347 | CF_NORET(mp_rshb(tmp.GetPtr(), numBits)); |
69 | 347 | MP_CHECK_EQ(mp_mul_2d(tmp.GetPtr(), numBits, tmp.GetPtr()), MP_OKAY); |
70 | | |
71 | 344 | { |
72 | | /* Use the nearest exponent of 2 as a hint for the mutator */ |
73 | 344 | const auto s = tmp.ToDecString(); |
74 | | |
75 | 344 | util::HintBignumOpt(s); |
76 | 344 | } |
77 | | |
78 | 344 | CF_CHECK_EQ(compare(A, tmp, ds), MP_EQ); |
79 | | |
80 | 185 | ret = numBits; |
81 | 392 | end: |
82 | 392 | return ret; |
83 | 185 | } |
84 | | #endif |
85 | | } |
86 | | |
87 | 1.40k | bool Add::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
88 | 1.40k | bool ret = false; |
89 | | |
90 | 1.40k | GET_WHICH(1); |
91 | 1.40k | switch ( which ) { |
92 | 754 | case 0: |
93 | 754 | MP_CHECK_EQ(mp_add(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
94 | 748 | ret = true; |
95 | 748 | break; |
96 | 647 | case 1: |
97 | 647 | { |
98 | 647 | const auto op = bn[1].AsUnsigned<mp_digit>(); |
99 | 647 | CF_CHECK_NE(op, std::nullopt); |
100 | 546 | MP_CHECK_EQ(mp_add_d(bn[0].GetPtr(), *op, res.GetPtr()), MP_OKAY); |
101 | 546 | ret = true; |
102 | 546 | } |
103 | 0 | break; |
104 | 1.40k | } |
105 | | |
106 | 1.40k | end: |
107 | 1.40k | return ret; |
108 | 1.40k | } |
109 | | |
110 | 1.63k | bool Sub::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
111 | 1.63k | bool ret = false; |
112 | | |
113 | 1.63k | #if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) |
114 | | /* SP math cannot represent negative numbers, so ensure the result |
115 | | * of the subtracton is always >= 0. |
116 | | * |
117 | | * Still run the subtraction operation to see if this can cause |
118 | | * memory errors, but don't return the result. |
119 | | */ |
120 | 1.63k | bool negative = false; |
121 | 1.63k | if ( wolfCrypt_bignum_detail::compare(bn[0], bn[1], ds) == MP_LT) { |
122 | 577 | negative = true; |
123 | 577 | } |
124 | 1.63k | #endif |
125 | | |
126 | 1.63k | GET_WHICH(1); |
127 | 1.63k | switch ( which ) { |
128 | 847 | case 0: |
129 | 847 | MP_CHECK_EQ(mp_sub(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
130 | 847 | ret = true; |
131 | 847 | break; |
132 | 790 | case 1: |
133 | 790 | { |
134 | 790 | const auto op = bn[1].AsUnsigned<mp_digit>(); |
135 | 790 | CF_CHECK_NE(op, std::nullopt); |
136 | 700 | MP_CHECK_EQ(mp_sub_d(bn[0].GetPtr(), *op, res.GetPtr()), MP_OKAY); |
137 | 700 | ret = true; |
138 | 700 | } |
139 | 0 | break; |
140 | 1.63k | } |
141 | | |
142 | 1.63k | end: |
143 | 1.63k | #if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) |
144 | 1.63k | if ( negative == true ) { |
145 | 577 | return false; |
146 | 577 | } |
147 | 1.06k | #endif |
148 | 1.06k | return ret; |
149 | 1.63k | } |
150 | | |
151 | 1.11k | bool Mul::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
152 | 1.11k | bool ret = false; |
153 | | |
154 | 1.11k | GET_WHICH(3); |
155 | 1.11k | switch ( which ) { |
156 | 518 | case 0: |
157 | 518 | MP_CHECK_EQ(mp_mul(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
158 | 492 | ret = true; |
159 | 492 | break; |
160 | 455 | case 1: |
161 | 455 | { |
162 | 455 | const auto op = bn[1].AsUnsigned<mp_digit>(); |
163 | 455 | CF_CHECK_NE(op, std::nullopt); |
164 | 357 | MP_CHECK_EQ(mp_mul_d(bn[0].GetPtr(), *op, res.GetPtr()), MP_OKAY); |
165 | 357 | ret = true; |
166 | 357 | } |
167 | 0 | break; |
168 | 0 | #if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH) |
169 | 52 | case 2: |
170 | 52 | util::HintBignum("2"); |
171 | 52 | CF_CHECK_EQ(mp_cmp_d(bn[1].GetPtr(), 2), MP_EQ); |
172 | 4 | MP_CHECK_EQ(mp_mul_2(bn[0].GetPtr(), res.GetPtr()), MP_OKAY); |
173 | 4 | ret = true; |
174 | 4 | break; |
175 | 0 | #endif |
176 | 91 | case 3: |
177 | 91 | { |
178 | 91 | const auto numBits = mp_cnt_lsb(bn[1].GetPtr()); |
179 | 91 | CF_CHECK_GTE(numBits, DIGIT_BIT); |
180 | 38 | CF_CHECK_EQ(numBits % DIGIT_BIT, 0); |
181 | | |
182 | 27 | wolfCrypt_bignum::Bignum multiplier(ds); |
183 | 27 | MP_CHECK_EQ(mp_2expt(multiplier.GetPtr(), numBits), MP_OKAY); |
184 | 27 | CF_CHECK_EQ(wolfCrypt_bignum_detail::compare(bn[1], multiplier, ds), MP_EQ); |
185 | | |
186 | 7 | MP_CHECK_EQ(mp_lshd(bn.GetDestPtr(0), numBits / DIGIT_BIT), MP_OKAY); |
187 | 7 | MP_CHECK_EQ(mp_copy(bn[0].GetPtr(), res.GetPtr()), MP_OKAY); |
188 | 7 | ret = true; |
189 | 7 | } |
190 | 0 | break; |
191 | 1.11k | } |
192 | | |
193 | 1.11k | end: |
194 | 1.11k | return ret; |
195 | 1.11k | } |
196 | | |
197 | 731 | bool Div::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
198 | 731 | (void)ds; |
199 | 731 | bool ret = false; |
200 | | |
201 | | #if defined(WOLFSSL_SP_MATH) |
202 | | (void)res; |
203 | | (void)bn; |
204 | | #else |
205 | | |
206 | 731 | GET_WHICH(3); |
207 | 731 | switch ( which ) { |
208 | 318 | case 0: |
209 | 318 | MP_CHECK_EQ(mp_div(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr(), GET_OPTIONAL_BN()), MP_OKAY); |
210 | 287 | break; |
211 | 83 | case 1: |
212 | 83 | util::HintBignum("2"); |
213 | 83 | CF_CHECK_EQ(mp_cmp_d(bn[1].GetPtr(), 2), MP_EQ); |
214 | 48 | MP_CHECK_EQ(mp_div_2(bn[0].GetPtr(), res.GetPtr()), MP_OKAY); |
215 | 48 | break; |
216 | 0 | #if !defined(USE_FAST_MATH) |
217 | 63 | case 2: |
218 | 63 | { |
219 | 63 | mp_digit remainder; |
220 | 63 | util::HintBignum("3"); |
221 | 63 | CF_CHECK_EQ(mp_cmp_d(bn[1].GetPtr(), 3), MP_EQ); |
222 | 29 | MP_CHECK_EQ(mp_div_3(bn[0].GetPtr(), res.GetPtr(), ds.Get<bool>() ? &remainder : nullptr), MP_OKAY); |
223 | 29 | } |
224 | 0 | break; |
225 | 0 | #endif |
226 | 0 | #if defined(WOLFSSL_SP_MATH_ALL) |
227 | 267 | case 3: |
228 | 267 | { |
229 | 267 | const auto divisor = bn[1].AsUnsigned<mp_digit>(); |
230 | 267 | mp_digit remainder; |
231 | 267 | CF_CHECK_NE(divisor, std::nullopt); |
232 | 231 | MP_CHECK_EQ(mp_div_d(bn[0].GetPtr(), *divisor, res.GetPtr(), ds.Get<bool>() ? &remainder : nullptr), MP_OKAY); |
233 | 208 | } |
234 | 0 | #endif |
235 | 208 | default: |
236 | 208 | goto end; |
237 | 731 | } |
238 | | |
239 | | /* wolfCrypt uses different rounding logic with negative divisior. |
240 | | * The result is still computed, but don't return it |
241 | | */ |
242 | 136 | CF_CHECK_EQ(mp_isneg(bn[0].GetPtr()), 0); |
243 | | |
244 | 133 | ret = true; |
245 | | |
246 | 496 | end: |
247 | 496 | #endif |
248 | 496 | return ret; |
249 | 133 | } |
250 | | |
251 | 2.69k | bool ExpMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
252 | 2.69k | bool ret = false; |
253 | | |
254 | 2.69k | try { |
255 | 2.69k | switch ( ds.Get<uint8_t>() % 5 ) { |
256 | 240 | case 0: |
257 | 240 | { |
258 | 240 | auto data = ds.GetData(0, 1024 / 8, 1024 / 8); |
259 | | /* Odd */ |
260 | 240 | data[1024 / 8 - 1] |= 1; |
261 | 240 | util::HintBignum(util::BinToDec(data)); |
262 | 240 | } |
263 | 240 | break; |
264 | 523 | case 1: |
265 | 523 | { |
266 | 523 | auto data = ds.GetData(0, 1536 / 8, 1536 / 8); |
267 | 523 | data[1536 / 8 - 1] |= 1; |
268 | 523 | util::HintBignum(util::BinToDec(data)); |
269 | 523 | } |
270 | 523 | break; |
271 | 154 | case 2: |
272 | 154 | { |
273 | 154 | auto data = ds.GetData(0, 2048 / 8, 2048 / 8); |
274 | 154 | data[2048 / 8 - 1] |= 1; |
275 | 154 | util::HintBignum(util::BinToDec(data)); |
276 | 154 | } |
277 | 154 | break; |
278 | 79 | case 3: |
279 | 79 | { |
280 | 79 | auto data = ds.GetData(0, 3072 / 8, 3072 / 8); |
281 | 79 | data[3072 / 8 - 1] |= 1; |
282 | 79 | util::HintBignum(util::BinToDec(data)); |
283 | 79 | } |
284 | 79 | break; |
285 | 141 | case 4: |
286 | 141 | { |
287 | 141 | auto data = ds.GetData(0, 4096 / 8, 4096 / 8); |
288 | 141 | data[4096 / 8 - 1] |= 1; |
289 | 141 | util::HintBignum(util::BinToDec(data)); |
290 | 141 | } |
291 | 141 | break; |
292 | 2.69k | } |
293 | 2.69k | } catch ( fuzzing::datasource::Datasource::OutOfData ) { |
294 | 2.49k | } |
295 | | |
296 | 2.69k | GET_WHICH(9); |
297 | 2.69k | switch ( which ) { |
298 | 1.76k | case 0: |
299 | 1.76k | MP_CHECK_EQ(mp_exptmod(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
300 | 1.51k | break; |
301 | 0 | #if defined(WOLFSSL_SP_MATH_ALL) |
302 | 668 | case 1: |
303 | 668 | MP_CHECK_EQ(mp_exptmod_nct(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
304 | 491 | break; |
305 | 0 | #endif |
306 | 84 | case 2: |
307 | 84 | MP_CHECK_EQ(mp_exptmod_ex(bn[0].GetPtr(), bn[1].GetPtr(), bn[1].GetPtr()->used, bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
308 | 32 | break; |
309 | | #if defined(WOLFSSL_SP_MATH) |
310 | | case 3: |
311 | | MP_CHECK_EQ(sp_ModExp_1024(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
312 | | break; |
313 | | case 4: |
314 | | MP_CHECK_EQ(sp_ModExp_1536(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
315 | | break; |
316 | | case 5: |
317 | | MP_CHECK_EQ(sp_ModExp_2048(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
318 | | break; |
319 | | case 6: |
320 | | MP_CHECK_EQ(sp_ModExp_3072(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
321 | | break; |
322 | | #if !defined(__i386__) |
323 | | case 7: |
324 | | MP_CHECK_EQ(sp_ModExp_4096(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
325 | | break; |
326 | | #endif |
327 | | #endif |
328 | | #if !defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL) && !defined(USE_FAST_MATH) |
329 | | case 8: |
330 | | MP_CHECK_EQ(mp_exptmod_fast(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr(), 0), MP_OKAY); |
331 | | break; |
332 | | #endif |
333 | | #if !defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL) && !defined(USE_FAST_MATH) |
334 | | case 9: |
335 | | { |
336 | | util::HintBignum("2"); |
337 | | CF_CHECK_EQ(mp_cmp_d(bn[0].GetPtr(), 2), MP_EQ); |
338 | | MP_CHECK_EQ(mp_exptmod_base_2(bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
339 | | } |
340 | | break; |
341 | | #endif |
342 | 179 | default: |
343 | 179 | goto end; |
344 | 2.69k | } |
345 | | |
346 | | #if defined(WOLFSSL_SP_MATH) |
347 | | ret = true; |
348 | | #else |
349 | 2.03k | if ( |
350 | 2.03k | !mp_iszero(bn[1].GetPtr()) && |
351 | 2.03k | !mp_isneg(bn[0].GetPtr()) && |
352 | 2.03k | !mp_isneg(bn[1].GetPtr()) && |
353 | 2.03k | !mp_isneg(bn[2].GetPtr()) ) { |
354 | 1.51k | ret = true; |
355 | 1.51k | } |
356 | 2.03k | #endif |
357 | | |
358 | 2.69k | end: |
359 | 2.69k | return ret; |
360 | 2.03k | } |
361 | | |
362 | 1.16k | bool Sqr::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
363 | 1.16k | (void)ds; |
364 | | |
365 | 1.16k | bool ret = false; |
366 | | |
367 | 1.16k | MP_CHECK_EQ(mp_sqr(bn[0].GetPtr(), res.GetPtr()), MP_OKAY); |
368 | | |
369 | 1.05k | ret = true; |
370 | | |
371 | 1.16k | end: |
372 | 1.16k | return ret; |
373 | 1.05k | } |
374 | | |
375 | 2.35k | bool GCD::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
376 | 2.35k | (void)ds; |
377 | 2.35k | (void)res; |
378 | 2.35k | (void)bn; |
379 | | |
380 | 2.35k | bool ret = false; |
381 | | |
382 | | /* mp_gcd does not support negative numbers */ |
383 | 2.35k | CF_CHECK_NE(mp_cmp_d(bn[0].GetPtr(), 0), MP_LT); |
384 | 2.31k | CF_CHECK_NE(mp_cmp_d(bn[1].GetPtr(), 0), MP_LT); |
385 | | |
386 | 2.26k | MP_CHECK_EQ(mp_gcd(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
387 | | |
388 | 2.11k | ret = true; |
389 | | |
390 | 2.35k | end: |
391 | 2.35k | return ret; |
392 | 2.11k | } |
393 | | |
394 | 3.08k | bool InvMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
395 | 3.08k | (void)ds; |
396 | | |
397 | 3.08k | bool ret = false; |
398 | | |
399 | 3.08k | GET_WHICH(0); |
400 | 3.08k | switch ( which ) { |
401 | 3.08k | case 0: |
402 | 3.08k | MP_CHECK_EQ(mp_invmod(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
403 | 2.07k | break; |
404 | 0 | #if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH) |
405 | | #if 0 |
406 | | case 1: |
407 | | MP_CHECK_EQ(mp_invmod_slow(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
408 | | break; |
409 | | #endif |
410 | 0 | #endif |
411 | 0 | default: |
412 | 0 | goto end; |
413 | 3.08k | } |
414 | | |
415 | 2.07k | ret = true; |
416 | | |
417 | 3.08k | end: |
418 | 3.08k | return ret; |
419 | 2.07k | } |
420 | | |
421 | 491 | bool Cmp::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
422 | 491 | bool ret = false; |
423 | | |
424 | 491 | int cmpRes = 0; |
425 | 491 | GET_WHICH(1); |
426 | 491 | switch ( which ) { |
427 | 335 | case 0: |
428 | 335 | cmpRes = wolfCrypt_bignum_detail::compare(bn[0], bn[1], ds); |
429 | 335 | break; |
430 | 156 | case 1: |
431 | 156 | { |
432 | 156 | const auto op = bn[1].AsUnsigned<mp_digit>(); |
433 | 156 | CF_CHECK_NE(op, std::nullopt); |
434 | 108 | cmpRes = mp_cmp_d(bn[0].GetPtr(), *op); |
435 | 108 | } |
436 | 0 | break; |
437 | 0 | default: |
438 | 0 | goto end; |
439 | 491 | } |
440 | | |
441 | 443 | switch ( cmpRes ) { |
442 | 130 | case MP_GT: |
443 | 130 | CF_CHECK_EQ( res.Set("1"), true); |
444 | 130 | break; |
445 | 216 | case MP_LT: |
446 | 216 | CF_CHECK_EQ( res.Set("-1"), true); |
447 | 90 | break; |
448 | 97 | case MP_EQ: |
449 | 97 | CF_CHECK_EQ( res.Set("0"), true); |
450 | 97 | break; |
451 | 0 | default: |
452 | 0 | CF_ASSERT(0, "Compare result is not one of (MP_GT, MP_LT, MP_EQ)"); |
453 | 443 | } |
454 | | |
455 | 317 | ret = true; |
456 | | |
457 | 491 | end: |
458 | 491 | return ret; |
459 | 317 | } |
460 | | |
461 | 81 | bool Abs::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
462 | 81 | (void)ds; |
463 | | |
464 | 81 | bool ret = false; |
465 | | |
466 | 81 | MP_CHECK_EQ(mp_abs(bn[0].GetPtr(), res.GetPtr()), MP_OKAY); |
467 | | |
468 | 81 | ret = true; |
469 | | |
470 | 81 | end: |
471 | 81 | return ret; |
472 | 81 | } |
473 | | |
474 | 111 | bool Neg::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
475 | 111 | (void)ds; |
476 | 111 | bool ret = false; |
477 | | |
478 | 111 | #if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) |
479 | 111 | (void)res; |
480 | 111 | (void)bn; |
481 | | #else |
482 | | CF_CHECK_EQ(res.Set("0"), true); |
483 | | MP_CHECK_EQ(mp_sub(res.GetPtr(), bn[0].GetPtr(), res.GetPtr()), MP_OKAY); |
484 | | |
485 | | ret = true; |
486 | | |
487 | | end: |
488 | | #endif |
489 | | |
490 | 111 | return ret; |
491 | 111 | } |
492 | | |
493 | 1.78k | bool RShift::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
494 | 1.78k | bool ret = false; |
495 | | |
496 | 1.78k | std::optional<uint64_t> _numBits; |
497 | 1.78k | int numBits; |
498 | | |
499 | 1.78k | GET_WHICH(2); |
500 | 1.78k | CF_CHECK_NE(_numBits = bn[1].AsUint64(), std::nullopt); |
501 | 1.74k | CF_CHECK_LTE(_numBits, 2147483647); |
502 | | |
503 | 1.48k | numBits = *_numBits; |
504 | | |
505 | 1.48k | switch ( which ) { |
506 | 672 | case 0: |
507 | 672 | MP_CHECK_EQ(mp_copy(bn[0].GetPtr(), res.GetPtr()), MP_OKAY); |
508 | 672 | CF_NORET(mp_rshb(res.GetPtr(), numBits)); |
509 | 672 | ret = true; |
510 | 672 | break; |
511 | 0 | #if !defined(WOLFSSL_SP_MATH) |
512 | 644 | case 1: |
513 | 644 | MP_CHECK_EQ(mp_div_2d(bn[0].GetPtr(), numBits, res.GetPtr(), GET_OPTIONAL_BN()), MP_OKAY); |
514 | 644 | ret = true; |
515 | 644 | break; |
516 | 0 | #endif |
517 | 172 | case 2: |
518 | 172 | { |
519 | | /* Check if number of bits to shift is a multiple of a full digit */ |
520 | 172 | CF_CHECK_EQ(numBits % (sizeof(mp_digit) * 8), 0); |
521 | | |
522 | 148 | MP_CHECK_EQ(mp_copy(bn[0].GetPtr(), res.GetPtr()), MP_OKAY); |
523 | | |
524 | 148 | const auto numDigits = numBits / (sizeof(mp_digit) * 8); |
525 | 148 | CF_NORET(mp_rshd(res.GetPtr(), numDigits)); |
526 | | |
527 | 148 | ret = true; |
528 | 148 | } |
529 | 0 | break; |
530 | 1.48k | } |
531 | | |
532 | 1.73k | end: |
533 | | |
534 | 1.73k | return ret; |
535 | 1.48k | } |
536 | | |
537 | 298 | bool LShift1::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
538 | 298 | (void)ds; |
539 | | |
540 | 298 | bool ret = false; |
541 | | |
542 | | #if defined(WOLFSSL_SP_MATH) |
543 | | (void)res; |
544 | | (void)bn; |
545 | | #else |
546 | 298 | MP_CHECK_EQ(mp_mul_2d(bn[0].GetPtr(), 1, res.GetPtr()), MP_OKAY); |
547 | | |
548 | 298 | ret = true; |
549 | | |
550 | 298 | end: |
551 | 298 | #endif |
552 | | |
553 | 298 | return ret; |
554 | 298 | } |
555 | | |
556 | 50 | bool IsNeg::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
557 | 50 | (void)ds; |
558 | | |
559 | 50 | bool ret = false; |
560 | | |
561 | 50 | #if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) |
562 | 50 | (void)res; |
563 | 50 | (void)bn; |
564 | | #else |
565 | | CF_CHECK_EQ( res.Set( std::to_string(mp_isneg(bn[0].GetPtr()) ? 1 : 0) ), true); |
566 | | |
567 | | ret = true; |
568 | | |
569 | | end: |
570 | | #endif |
571 | 50 | return ret; |
572 | 50 | } |
573 | | |
574 | 178 | bool IsEq::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
575 | 178 | bool ret = false; |
576 | | |
577 | 178 | const bool isEq = wolfCrypt_bignum_detail::compare(bn[0], bn[1], ds) == MP_EQ; |
578 | 178 | CF_CHECK_EQ( res.Set( std::to_string(isEq ? 1 : 0) ), true); |
579 | | |
580 | 178 | ret = true; |
581 | | |
582 | 178 | end: |
583 | 178 | return ret; |
584 | 178 | } |
585 | | |
586 | 137 | bool IsZero::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
587 | 137 | (void)ds; |
588 | | |
589 | 137 | bool ret = false; |
590 | | |
591 | 137 | CF_CHECK_EQ( res.Set( std::to_string(mp_iszero(bn[0].GetPtr()) ? 1 : 0) ), true); |
592 | | |
593 | 137 | ret = true; |
594 | | |
595 | 137 | end: |
596 | 137 | return ret; |
597 | 137 | } |
598 | | |
599 | 168 | bool IsOne::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
600 | 168 | (void)ds; |
601 | | |
602 | 168 | bool ret = false; |
603 | | |
604 | 168 | CF_CHECK_EQ( res.Set( std::to_string(mp_isone(bn[0].GetPtr()) ? 1 : 0) ), true); |
605 | | |
606 | 168 | ret = true; |
607 | | |
608 | 168 | end: |
609 | 168 | return ret; |
610 | 168 | } |
611 | | |
612 | 199 | bool MulMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
613 | 199 | (void)ds; |
614 | | |
615 | 199 | bool ret = false; |
616 | | |
617 | 199 | MP_CHECK_EQ(mp_mulmod(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
618 | | |
619 | 131 | ret = true; |
620 | | |
621 | 199 | end: |
622 | 199 | return ret; |
623 | 131 | } |
624 | | |
625 | 484 | bool AddMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
626 | 484 | bool ret = false; |
627 | | |
628 | | #if defined(WOLFSSL_SP_MATH) |
629 | | (void)ds; |
630 | | (void)res; |
631 | | (void)bn; |
632 | | #else |
633 | 484 | GET_WHICH(1); |
634 | 484 | switch ( which ) { |
635 | 268 | case 0: |
636 | 268 | MP_CHECK_EQ(mp_addmod(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
637 | 146 | break; |
638 | 216 | case 1: |
639 | | /* mp_addmod_ct does not support negative numbers */ |
640 | 216 | CF_CHECK_NE(mp_cmp_d(bn[0].GetPtr(), 0), MP_LT); |
641 | 204 | CF_CHECK_NE(mp_cmp_d(bn[1].GetPtr(), 0), MP_LT); |
642 | 188 | CF_CHECK_NE(mp_cmp_d(bn[2].GetPtr(), 0), MP_LT); |
643 | | |
644 | 168 | CF_CHECK_EQ(wolfCrypt_bignum_detail::compare(bn[0], bn[1], ds), MP_LT) |
645 | 114 | CF_CHECK_EQ(wolfCrypt_bignum_detail::compare(bn[1], bn[2], ds), MP_LT) |
646 | 114 | MP_CHECK_EQ(mp_addmod_ct(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
647 | 65 | break; |
648 | 0 | default: |
649 | 0 | goto end; |
650 | 484 | } |
651 | | |
652 | 211 | ret = true; |
653 | | |
654 | 484 | end: |
655 | 484 | #endif |
656 | 484 | return ret; |
657 | 211 | } |
658 | | |
659 | 1.23k | bool SubMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
660 | 1.23k | bool ret = false; |
661 | | |
662 | | #if defined(WOLFSSL_SP_MATH) |
663 | | (void)ds; |
664 | | (void)res; |
665 | | (void)bn; |
666 | | #else |
667 | 1.23k | GET_WHICH(1); |
668 | 1.23k | switch ( which ) { |
669 | 896 | case 0: |
670 | 896 | MP_CHECK_EQ(mp_submod(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
671 | 814 | break; |
672 | 342 | case 1: |
673 | | /* mp_submod_ct does not support negative numbers */ |
674 | 342 | CF_CHECK_NE(mp_cmp_d(bn[0].GetPtr(), 0), MP_LT); |
675 | 326 | CF_CHECK_NE(mp_cmp_d(bn[1].GetPtr(), 0), MP_LT); |
676 | 306 | CF_CHECK_NE(mp_cmp_d(bn[2].GetPtr(), 0), MP_LT); |
677 | | |
678 | | /* mp_submod_ct documentation states that: |
679 | | * |
680 | | * A < modulo |
681 | | * B < modulo |
682 | | */ |
683 | 286 | CF_CHECK_EQ(wolfCrypt_bignum_detail::compare(bn[0], bn[2], ds), MP_LT) |
684 | 233 | CF_CHECK_EQ(wolfCrypt_bignum_detail::compare(bn[1], bn[2], ds), MP_LT) |
685 | | |
686 | 233 | MP_CHECK_EQ(mp_submod_ct(bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), res.GetPtr()), MP_OKAY); |
687 | 182 | break; |
688 | 0 | default: |
689 | 0 | goto end; |
690 | 1.23k | } |
691 | | |
692 | 996 | ret = true; |
693 | | |
694 | 1.23k | end: |
695 | 1.23k | #endif |
696 | 1.23k | return ret; |
697 | 996 | } |
698 | | |
699 | 304 | bool SqrMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
700 | 304 | (void)ds; |
701 | | |
702 | 304 | bool ret = false; |
703 | | |
704 | 304 | MP_CHECK_EQ(mp_sqrmod(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
705 | | |
706 | 189 | ret = true; |
707 | | |
708 | 304 | end: |
709 | 304 | return ret; |
710 | 189 | } |
711 | | |
712 | 518 | bool Bit::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
713 | 518 | (void)ds; |
714 | 518 | bool ret = false; |
715 | | |
716 | | #if defined(WOLFSSL_SP_MATH) |
717 | | (void)res; |
718 | | (void)bn; |
719 | | #else |
720 | 518 | std::optional<uint64_t> _bitPos; |
721 | 518 | #if defined(WOLFSSL_SP_MATH_ALL) |
722 | 518 | unsigned int bitPos; |
723 | | #else |
724 | | mp_digit bitPos; |
725 | | #endif |
726 | 518 | int isBitSet; |
727 | | |
728 | 518 | CF_CHECK_NE(_bitPos = bn[1].AsUint64(), std::nullopt); |
729 | | |
730 | 456 | bitPos = *_bitPos; |
731 | | /* Ensure no truncation has occurred */ |
732 | 456 | CF_CHECK_EQ(bitPos, *_bitPos); |
733 | | |
734 | 278 | CF_CHECK_GTE(isBitSet = mp_is_bit_set(bn[0].GetPtr(), bitPos), 0); |
735 | 278 | CF_CHECK_EQ( res.Set(isBitSet ? "1" : "0"), true); |
736 | | |
737 | 278 | ret = true; |
738 | | |
739 | 518 | end: |
740 | 518 | #endif |
741 | 518 | return ret; |
742 | 278 | } |
743 | | |
744 | 69 | bool CmpAbs::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
745 | 69 | (void)ds; |
746 | 69 | (void)res; |
747 | 69 | (void)bn; |
748 | | |
749 | | /* TODO */ |
750 | | |
751 | 69 | bool ret = false; |
752 | | |
753 | 69 | return ret; |
754 | 69 | } |
755 | | |
756 | 354 | bool SetBit::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
757 | 354 | (void)ds; |
758 | 354 | bool ret = false; |
759 | | |
760 | 354 | std::optional<uint64_t> _bitPos; |
761 | 354 | mp_digit bitPos; |
762 | | |
763 | 354 | CF_CHECK_NE(_bitPos = bn[1].AsUint64(), std::nullopt); |
764 | | |
765 | 334 | bitPos = *_bitPos; |
766 | | /* Ensure no truncation has occurred */ |
767 | 334 | CF_CHECK_EQ(bitPos, *_bitPos); |
768 | | |
769 | 311 | MP_CHECK_EQ(mp_copy(bn[0].GetPtr(), res.GetPtr()), MP_OKAY); |
770 | 311 | MP_CHECK_EQ(mp_set_bit(res.GetPtr(), bitPos), MP_OKAY); |
771 | | |
772 | 260 | ret = true; |
773 | | |
774 | 354 | end: |
775 | 354 | return ret; |
776 | 260 | } |
777 | | |
778 | 810 | bool LCM::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
779 | 810 | #if \ |
780 | 810 | defined(WOLFSSL_SP_MATH) || \ |
781 | 810 | (defined(WOLFSSL_SP_MATH_ALL) && \ |
782 | 810 | !(!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && !defined(WC_RSA_BLINDING)) \ |
783 | 810 | ) |
784 | 810 | (void)ds; |
785 | 810 | (void)res; |
786 | 810 | (void)bn; |
787 | 810 | return false; |
788 | | #else |
789 | | (void)ds; |
790 | | |
791 | | bool ret = false; |
792 | | |
793 | | /* mp_lcm does not support negative numbers */ |
794 | | CF_CHECK_NE(mp_cmp_d(bn[0].GetPtr(), 0), MP_LT); |
795 | | CF_CHECK_NE(mp_cmp_d(bn[1].GetPtr(), 0), MP_LT); |
796 | | |
797 | | MP_CHECK_EQ(mp_lcm(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
798 | | |
799 | | ret = true; |
800 | | |
801 | | end: |
802 | | return ret; |
803 | | #endif |
804 | 810 | } |
805 | | |
806 | 1.51k | bool Mod::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
807 | 1.51k | bool ret = false; |
808 | | |
809 | 1.51k | GET_WHICH(4); |
810 | 1.51k | switch ( which ) { |
811 | 460 | case 0: |
812 | 460 | MP_CHECK_EQ(mp_mod(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
813 | 361 | break; |
814 | 0 | #if !defined(WOLFSSL_SP_MATH) |
815 | 319 | case 1: |
816 | 319 | { |
817 | | /* Input must not be negative */ |
818 | 319 | CF_CHECK_NE(mp_cmp_d(bn[0].GetPtr(), 0), MP_LT); |
819 | | |
820 | 308 | const auto op = bn[1].AsUnsigned<mp_digit>(); |
821 | 308 | CF_CHECK_NE(op, std::nullopt); |
822 | 226 | mp_digit modResult; |
823 | 226 | MP_CHECK_EQ(mp_mod_d(bn[0].GetPtr(), *op, &modResult), MP_OKAY); |
824 | 184 | CF_CHECK_EQ(res.Set(std::to_string(modResult)), true); |
825 | 184 | } |
826 | 0 | break; |
827 | 168 | case 2: |
828 | 168 | { |
829 | | /* mp_div_2_mod_ct does not support negative numbers */ |
830 | 168 | CF_CHECK_NE(mp_cmp_d(bn[0].GetPtr(), 0), MP_LT); |
831 | 148 | CF_CHECK_NE(mp_cmp_d(bn[0].GetPtr(), 0), MP_LT); |
832 | | |
833 | | /* bn[0] *= 2 */ |
834 | 148 | MP_CHECK_EQ(mp_mul_d(bn[0].GetPtr(), 2, bn.GetDestPtr(0)), MP_OKAY); |
835 | | |
836 | 144 | CF_CHECK_EQ(wolfCrypt_bignum_detail::compare(bn[0], bn[1], ds), MP_LT) |
837 | 144 | MP_CHECK_EQ(mp_div_2_mod_ct(bn[0].GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
838 | 82 | } |
839 | 0 | break; |
840 | 160 | case 3: |
841 | 160 | { |
842 | 160 | mp_digit mp; |
843 | 160 | wolfCrypt_bignum::Bignum tmp(ds); |
844 | | |
845 | 160 | MP_CHECK_EQ(mp_montgomery_setup(bn[1].GetPtr(), &mp), MP_OKAY); |
846 | 70 | MP_CHECK_EQ(mp_montgomery_calc_normalization(tmp.GetPtr(), bn[1].GetPtr()), MP_OKAY); |
847 | 70 | MP_CHECK_EQ(mp_mulmod(bn[0].GetPtr(), tmp.GetPtr(), bn[1].GetPtr(), res.GetPtr()), MP_OKAY); |
848 | 64 | MP_CHECK_EQ(mp_montgomery_reduce(res.GetPtr(), bn[1].GetPtr(), mp), MP_OKAY); |
849 | 53 | } |
850 | 0 | break; |
851 | 0 | #endif |
852 | 0 | #if !defined(WOLFSSL_SP_MATH) && (!defined(USE_FAST_MATH) || defined(WOLFSSL_SP_MATH_ALL)) |
853 | 404 | case 4: |
854 | 404 | { |
855 | 404 | std::optional<int> exponent = std::nullopt; |
856 | | |
857 | | /* Negative modulo not supported */ |
858 | 404 | CF_CHECK_NE(mp_cmp_d(bn[1].GetPtr(), 0), MP_LT); |
859 | | |
860 | 392 | CF_CHECK_NE(exponent = wolfCrypt_bignum_detail::isPowerOf2(bn[1], ds), std::nullopt); |
861 | | |
862 | 185 | MP_CHECK_EQ(mp_mod_2d(bn[0].GetPtr(), *exponent, res.GetPtr()), MP_OKAY); |
863 | 185 | } |
864 | 0 | break; |
865 | 0 | #endif |
866 | 0 | default: |
867 | 0 | goto end; |
868 | 1.51k | } |
869 | | |
870 | 865 | ret = true; |
871 | | |
872 | 1.51k | end: |
873 | 1.51k | return ret; |
874 | 865 | } |
875 | | |
876 | 104 | bool IsEven::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
877 | 104 | (void)ds; |
878 | | |
879 | 104 | bool ret = false; |
880 | | |
881 | 104 | CF_CHECK_EQ(mp_iszero(bn[0].GetPtr()), false); |
882 | | |
883 | 51 | CF_CHECK_EQ( res.Set( std::to_string(mp_iseven(bn[0].GetPtr()) ? 1 : 0) ), true); |
884 | | |
885 | 51 | ret = true; |
886 | | |
887 | 104 | end: |
888 | | |
889 | 104 | return ret; |
890 | 51 | } |
891 | | |
892 | 117 | bool IsOdd::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
893 | 117 | (void)ds; |
894 | | |
895 | 117 | bool ret = false; |
896 | | |
897 | 117 | CF_CHECK_EQ( res.Set( std::to_string(mp_isodd(bn[0].GetPtr()) ? 1 : 0) ), true); |
898 | | |
899 | 117 | ret = true; |
900 | | |
901 | 117 | end: |
902 | | |
903 | 117 | return ret; |
904 | 117 | } |
905 | | |
906 | 135 | bool MSB::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
907 | 135 | (void)ds; |
908 | | |
909 | 135 | bool ret = false; |
910 | | |
911 | 135 | const int bit = mp_leading_bit(bn[0].GetPtr()); |
912 | | |
913 | 135 | CF_ASSERT(bit == 0 || bit == 1, "mp_leading_bit result is not one of (0, 1)"); |
914 | | |
915 | 135 | CF_CHECK_EQ( res.Set( std::to_string(bit) ), true); |
916 | | |
917 | 135 | ret = true; |
918 | | |
919 | 135 | end: |
920 | | |
921 | 135 | return ret; |
922 | 135 | } |
923 | | |
924 | 108 | bool NumBits::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
925 | 108 | (void)ds; |
926 | | |
927 | 108 | bool ret = false; |
928 | | |
929 | 108 | const auto numBits = mp_count_bits(bn[0].GetPtr()); |
930 | | |
931 | 108 | CF_ASSERT(numBits >= 0, "mp_count_bits result is negative"); |
932 | | |
933 | 108 | CF_CHECK_EQ( res.Set( std::to_string(numBits) ), true); |
934 | | |
935 | 108 | ret = true; |
936 | | |
937 | 108 | end: |
938 | 108 | return ret; |
939 | 108 | } |
940 | | |
941 | 621 | bool Set::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
942 | 621 | bool ret = false; |
943 | | |
944 | 621 | GET_WHICH(3); |
945 | 621 | switch ( which ) { |
946 | 100 | case 0: |
947 | 100 | MP_CHECK_EQ(mp_copy(bn[0].GetPtr(), res.GetPtr()), MP_OKAY); |
948 | 100 | ret = true; |
949 | 100 | break; |
950 | 226 | case 1: |
951 | 226 | { |
952 | 226 | const auto op = bn[0].AsUnsigned<mp_digit>(); |
953 | 226 | CF_CHECK_NE(op, std::nullopt); |
954 | 143 | MP_CHECK_EQ(mp_set(res.GetPtr(), *op), MP_OKAY); |
955 | 143 | ret = true; |
956 | 143 | } |
957 | 0 | break; |
958 | 129 | case 2: |
959 | 129 | { |
960 | | /* mp_exch alters the value of bn[0], so invalidate the cache. */ |
961 | 129 | bn.InvalidateCache(); |
962 | | |
963 | | /* mp_exch always returns a value */ |
964 | 129 | MP_CHECK_EQ(mp_exch(res.GetPtr(), bn[0].GetPtr()), MP_OKAY); |
965 | | |
966 | 96 | ret = true; |
967 | 96 | } |
968 | 0 | break; |
969 | 166 | case 3: |
970 | 166 | { |
971 | 166 | const auto op = bn[0].AsUnsigned<unsigned long>(); |
972 | 166 | CF_CHECK_NE(op, std::nullopt); |
973 | 116 | MP_CHECK_EQ(mp_set_int(res.GetPtr(), *op), MP_OKAY); |
974 | 116 | ret = true; |
975 | 116 | } |
976 | 0 | break; |
977 | 621 | } |
978 | | |
979 | 621 | end: |
980 | 621 | return ret; |
981 | 621 | } |
982 | | |
983 | | #if defined(HAVE_COMP_KEY) && !defined(WOLFSSL_SP_MATH) |
984 | | #define HAVE_MP_JACOBI 1 |
985 | | #endif |
986 | | |
987 | | #if defined(HAVE_MP_JACOBI) |
988 | | extern "C" { |
989 | | int mp_jacobi(mp_int* a, mp_int* n, int* c); |
990 | | } |
991 | | #endif |
992 | | |
993 | 1.67k | bool Jacobi::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
994 | 1.67k | bool ret = false; |
995 | | |
996 | 1.67k | (void)ds; |
997 | | |
998 | | #if !defined(HAVE_MP_JACOBI) |
999 | | (void)res; |
1000 | | (void)bn; |
1001 | | #else |
1002 | 1.67k | if ( mp_isodd(bn[1].GetPtr()) ) { |
1003 | 1.58k | int jacobi; |
1004 | 1.58k | MP_CHECK_EQ(mp_jacobi(bn[0].GetPtr(), bn[1].GetPtr(), &jacobi), MP_OKAY); |
1005 | | |
1006 | 1.29k | switch ( jacobi ) { |
1007 | 432 | case 1: |
1008 | 432 | CF_CHECK_EQ( res.Set("1"), true); |
1009 | 432 | break; |
1010 | 401 | case -1: |
1011 | 401 | CF_CHECK_EQ( res.Set("-1"), true); |
1012 | 207 | break; |
1013 | 458 | case 0: |
1014 | 458 | CF_CHECK_EQ( res.Set("0"), true); |
1015 | 458 | break; |
1016 | 0 | default: |
1017 | 0 | CF_ASSERT(0, "mp_jacobi result is not one of (-1, 0, 1)"); |
1018 | 1.29k | } |
1019 | | |
1020 | 1.09k | ret = true; |
1021 | 1.09k | } |
1022 | | |
1023 | 1.67k | end: |
1024 | 1.67k | #endif |
1025 | | |
1026 | 1.67k | return ret; |
1027 | 1.67k | } |
1028 | | |
1029 | 453 | bool Exp2::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
1030 | 453 | (void)ds; |
1031 | | |
1032 | 453 | bool ret = false; |
1033 | | |
1034 | 453 | const auto exponent = bn[0].AsUnsigned<unsigned int>(); |
1035 | 453 | CF_CHECK_NE(exponent, std::nullopt); |
1036 | | #if defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL) |
1037 | | CF_CHECK_LT(*exponent / DIGIT_BIT, FP_SIZE); |
1038 | | #endif |
1039 | 433 | MP_CHECK_EQ(mp_2expt(res.GetPtr(), *exponent), MP_OKAY); |
1040 | | |
1041 | 349 | ret = true; |
1042 | | |
1043 | 453 | end: |
1044 | | |
1045 | 453 | return ret; |
1046 | 349 | } |
1047 | | |
1048 | 447 | bool NumLSZeroBits::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
1049 | 447 | (void)ds; |
1050 | | |
1051 | 447 | bool ret = false; |
1052 | | |
1053 | | #if (defined(USE_FAST_MATH) && !defined(HAVE_COMP_KEY)) |
1054 | | (void)res; |
1055 | | (void)bn; |
1056 | | #else |
1057 | 447 | const auto numBits = mp_cnt_lsb(bn[0].GetPtr()); |
1058 | | |
1059 | 447 | CF_ASSERT(numBits >= 0, "mp_cnt_lsb result is negative"); |
1060 | | |
1061 | 447 | CF_CHECK_EQ( res.Set( std::to_string(numBits) ), true); |
1062 | | |
1063 | 447 | ret = true; |
1064 | | |
1065 | 447 | end: |
1066 | 447 | #endif |
1067 | | |
1068 | 447 | return ret; |
1069 | 447 | } |
1070 | | |
1071 | 697 | bool MulAdd::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
1072 | 697 | bool ret = false; |
1073 | | |
1074 | 697 | std::optional<std::string> mulRes, toAdd; |
1075 | | |
1076 | 697 | auto mul = std::make_unique<Mul>(); |
1077 | 697 | auto add = std::make_unique<Add>(); |
1078 | | |
1079 | 697 | CF_CHECK_NE(toAdd = bn[2].ToDecString(), std::nullopt); |
1080 | | |
1081 | 655 | CF_CHECK_EQ(mul->Run(ds, res, bn), true); |
1082 | | |
1083 | 553 | CF_CHECK_NE(mulRes = res.ToDecString(), std::nullopt); |
1084 | | |
1085 | | /* bn[0] and bn[1] are altered, so invalidate the cache. */ |
1086 | 522 | bn.InvalidateCache(); |
1087 | | |
1088 | 522 | CF_CHECK_EQ(bn.Set(0, *mulRes), true); |
1089 | | |
1090 | 502 | CF_CHECK_EQ(bn.Set(1, *toAdd), true); |
1091 | 499 | CF_CHECK_EQ(add->Run(ds, res, bn), true); |
1092 | | |
1093 | 451 | ret = true; |
1094 | | |
1095 | 697 | end: |
1096 | 697 | return ret; |
1097 | 451 | } |
1098 | | |
1099 | 362 | bool CondSet::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
1100 | 362 | (void)ds; |
1101 | | |
1102 | 362 | bool ret = false; |
1103 | | |
1104 | 362 | const int doCopy = mp_iszero(bn[1].GetPtr()) ? 0 : 1; |
1105 | 362 | CF_CHECK_EQ(res.Set("0"), true); |
1106 | 362 | MP_CHECK_EQ(mp_cond_copy(bn[0].GetPtr(), doCopy, res.GetPtr()), MP_OKAY); |
1107 | | |
1108 | 358 | ret = true; |
1109 | | |
1110 | 362 | end: |
1111 | 362 | return ret; |
1112 | 358 | } |
1113 | | |
1114 | 2.37k | bool Rand::Run(Datasource& ds, Bignum& res, BignumCluster& bn) const { |
1115 | 2.37k | (void)ds; |
1116 | 2.37k | (void)bn; |
1117 | | |
1118 | 2.37k | bool ret = false; |
1119 | | |
1120 | 2.37k | GET_WHICH(1); |
1121 | 2.37k | switch ( which ) { |
1122 | 448 | case 0: |
1123 | 448 | { |
1124 | 448 | const auto len = ds.Get<uint16_t>() % 512; |
1125 | 448 | MP_CHECK_EQ(mp_rand(res.GetPtr(), len, wolfCrypt_detail::GetRNG()), MP_OKAY); |
1126 | 316 | ret = true; |
1127 | 316 | } |
1128 | 0 | break; |
1129 | 1.93k | case 1: |
1130 | 1.93k | { |
1131 | 1.93k | const auto len = ds.Get<uint16_t>() % 100; |
1132 | 1.93k | MP_CHECK_EQ(mp_rand_prime(res.GetPtr(), len, wolfCrypt_detail::GetRNG(), nullptr), MP_OKAY); |
1133 | 1.31k | ret = true; |
1134 | 1.31k | } |
1135 | 0 | break; |
1136 | 2.37k | } |
1137 | | |
1138 | 2.22k | end: |
1139 | 2.22k | return ret; |
1140 | 2.37k | } |
1141 | | |
1142 | | } /* namespace wolfCrypt_bignum */ |
1143 | | } /* namespace module */ |
1144 | | } /* namespace cryptofuzz */ |