/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 */  |