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