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