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