Coverage Report

Created: 2026-04-01 07:25

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