/src/cryptofuzz-openssl-api/modules/wolfcrypt-openssl/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 | | |
5 | | #include "bn_ops.h" |
6 | | |
7 | | /* Not included in public headers */ |
8 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
9 | | extern "C" { |
10 | | int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); |
11 | | int bn_div_consttime(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator, const BIGNUM *divisor, BN_CTX *ctx); |
12 | | int bn_lcm_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); |
13 | | uint16_t bn_mod_u16_consttime(const BIGNUM *bn, uint16_t d); |
14 | | int bn_abs_sub_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); |
15 | | } |
16 | | #endif |
17 | | |
18 | | /* Not included in public headers */ |
19 | | #if defined(CRYPTOFUZZ_LIBRESSL) |
20 | | extern "C" { |
21 | | int BN_gcd_ct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx); |
22 | | } |
23 | | #endif |
24 | | |
25 | | namespace cryptofuzz { |
26 | | namespace module { |
27 | | namespace OpenSSL_bignum { |
28 | | |
29 | 16 | bool Add::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
30 | 16 | (void)ctx; |
31 | 16 | bool ret = false; |
32 | | |
33 | 16 | switch ( ds.Get<uint8_t>() ) { |
34 | 9 | case 0: |
35 | 9 | CF_CHECK_EQ(BN_add(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr()), 1); |
36 | 9 | break; |
37 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
38 | | case 1: |
39 | | CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0); |
40 | | CF_CHECK_EQ(BN_is_negative(bn[1].GetPtr()), 0); |
41 | | CF_CHECK_EQ(BN_uadd(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr()), 1); |
42 | | break; |
43 | | #endif |
44 | 0 | case 2: |
45 | 0 | { |
46 | 0 | const auto val = bn[1].AsBN_ULONG(); |
47 | 0 | CF_CHECK_NE(val, std::nullopt); |
48 | |
|
49 | 0 | CF_CHECK_EQ(BN_add_word(bn.GetDestPtr(0), *val), 1); |
50 | |
|
51 | 0 | CF_CHECK_EQ(res.Set(bn[0]), true); |
52 | 0 | } |
53 | 0 | break; |
54 | 7 | default: |
55 | 7 | goto end; |
56 | 7 | break; |
57 | 16 | } |
58 | | |
59 | 9 | ret = true; |
60 | | |
61 | 16 | end: |
62 | 16 | return ret; |
63 | 9 | } |
64 | | |
65 | 17 | bool Sub::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
66 | 17 | (void)ctx; |
67 | 17 | bool ret = false; |
68 | | |
69 | 17 | switch ( ds.Get<uint8_t>() ) { |
70 | 11 | case 0: |
71 | 11 | CF_CHECK_EQ(BN_sub(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr()), 1); |
72 | 11 | break; |
73 | | |
74 | | /* OpenSSL and LibreSSL return a positive value for BN_usub(A,B) |
75 | | * where A > B |
76 | | */ |
77 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
78 | | case 1: |
79 | | CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0); |
80 | | CF_CHECK_EQ(BN_is_negative(bn[1].GetPtr()), 0); |
81 | | CF_CHECK_EQ(BN_usub(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr()), 1); |
82 | | break; |
83 | | #endif |
84 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
85 | | case 2: |
86 | | { |
87 | | const auto val = bn[1].AsBN_ULONG(); |
88 | | CF_CHECK_NE(val, std::nullopt); |
89 | | |
90 | | CF_CHECK_EQ(BN_sub_word(bn.GetDestPtr(0), *val), 1); |
91 | | |
92 | | CF_CHECK_EQ(res.Set(bn[0]), true); |
93 | | } |
94 | | break; |
95 | | #endif |
96 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
97 | | case 3: |
98 | | CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0); |
99 | | CF_CHECK_EQ(BN_is_negative(bn[1].GetPtr()), 0); |
100 | | CF_CHECK_GTE(BN_cmp(bn[0].GetPtr(), bn[1].GetPtr()), 0); |
101 | | CF_CHECK_EQ(bn_abs_sub_consttime(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
102 | | break; |
103 | | #endif |
104 | 3 | default: |
105 | 3 | goto end; |
106 | 3 | break; |
107 | 17 | } |
108 | | |
109 | 11 | ret = true; |
110 | | |
111 | 14 | end: |
112 | 14 | return ret; |
113 | 11 | } |
114 | | |
115 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
116 | | bool Mul::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
117 | | (void)ds; |
118 | | (void)ctx; |
119 | | bool ret = false; |
120 | | |
121 | | switch ( ds.Get<uint8_t>() ) { |
122 | | case 0: |
123 | | { |
124 | | CF_CHECK_EQ(BN_mul(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
125 | | } |
126 | | break; |
127 | | case 1: |
128 | | { |
129 | | const auto val = bn[1].AsBN_ULONG(); |
130 | | CF_CHECK_NE(val, std::nullopt); |
131 | | |
132 | | CF_CHECK_EQ(BN_mul_word(bn.GetDestPtr(0), *val), 1); |
133 | | |
134 | | CF_CHECK_EQ(res.Set(bn[0]), true); |
135 | | } |
136 | | break; |
137 | | default: |
138 | | goto end; |
139 | | break; |
140 | | } |
141 | | |
142 | | ret = true; |
143 | | |
144 | | end: |
145 | | return ret; |
146 | | } |
147 | | #endif |
148 | | |
149 | 18 | bool Mod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
150 | 18 | (void)ctx; |
151 | 18 | bool ret = false; |
152 | | |
153 | 18 | switch ( ds.Get<uint8_t>() ) { |
154 | 5 | case 0: |
155 | 5 | CF_CHECK_EQ(BN_mod(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
156 | 3 | break; |
157 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
158 | | case 1: |
159 | | /* "BN_mod() corresponds to BN_div() with dv set to NULL" */ |
160 | | CF_CHECK_EQ(BN_div(nullptr, res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
161 | | break; |
162 | | #endif |
163 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
164 | | case 2: |
165 | | CF_CHECK_EQ(bn_div_consttime(nullptr, res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
166 | | break; |
167 | | case 3: |
168 | | CF_CHECK_EQ(BN_is_pow2(bn[1].GetPtr()), 1); |
169 | | CF_CHECK_EQ(BN_mod_pow2(res.GetDestPtr(), bn[0].GetPtr(), BN_num_bits(bn[1].GetPtr()) - 1), 1); |
170 | | break; |
171 | | case 4: |
172 | | { |
173 | | std::optional<uint64_t> v64; |
174 | | |
175 | | /* Convert bn[1] to uint64_t if possible */ |
176 | | CF_CHECK_NE(v64 = bn[1].AsUint64(), std::nullopt); |
177 | | |
178 | | /* Try to convert the uint64_t to uint16_t */ |
179 | | uint16_t v16; |
180 | | CF_CHECK_EQ(v16 = *v64, *v64); |
181 | | |
182 | | CF_CHECK_GT(v16, 1); |
183 | | |
184 | | /* This condition is imposed by bn_mod_u16_consttime, which |
185 | | * triggers an assert failure otherwise |
186 | | */ |
187 | | CF_CHECK_LTE(BN_num_bits_word(v16 - 1), 16); |
188 | | |
189 | | /* ret = bn[0] MOD v16 (which is bn[1]) */ |
190 | | const auto ret = bn_mod_u16_consttime(bn[0].GetPtr(), v16); |
191 | | res.SetUint32(ret); |
192 | | } |
193 | | break; |
194 | | #endif |
195 | 1 | case 5: |
196 | 1 | { |
197 | 1 | const auto val = bn[1].AsBN_ULONG(); |
198 | 1 | CF_CHECK_NE(val, std::nullopt); |
199 | 0 | CF_CHECK_NE(*val, 0); |
200 | |
|
201 | 0 | const auto ret = BN_mod_word(bn[0].GetPtr(), *val); |
202 | | |
203 | | /* Try to convert the BN_ULONG to uint32_t */ |
204 | 0 | uint32_t ret32; |
205 | 0 | CF_CHECK_EQ(ret32 = ret, ret); |
206 | |
|
207 | 0 | res.SetUint32(ret32); |
208 | 0 | } |
209 | 0 | break; |
210 | 11 | default: |
211 | 11 | goto end; |
212 | 11 | break; |
213 | 18 | } |
214 | | |
215 | 3 | ret = true; |
216 | | |
217 | 17 | end: |
218 | 17 | return ret; |
219 | 3 | } |
220 | | |
221 | 393 | bool ExpMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
222 | 393 | (void)ctx; |
223 | 393 | bool ret = false; |
224 | | |
225 | 393 | switch ( ds.Get<uint8_t>() ) { |
226 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
227 | | case 0: |
228 | | CF_CHECK_EQ(BN_mod_exp_mont_consttime(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr(), nullptr), 1); |
229 | | break; |
230 | | case 1: |
231 | | CF_CHECK_EQ(BN_mod_exp_mont(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr(), nullptr), 1); |
232 | | break; |
233 | | #endif |
234 | 373 | case 2: |
235 | 373 | CF_CHECK_EQ(BN_mod_exp(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1); |
236 | 364 | break; |
237 | 4 | case 3: |
238 | | #if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
239 | | CF_CHECK_EQ(BN_mod_exp_simple(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1); |
240 | | #else |
241 | 4 | goto end; |
242 | 0 | #endif |
243 | 0 | break; |
244 | 9 | default: |
245 | 9 | goto end; |
246 | 9 | break; |
247 | | |
248 | 393 | } |
249 | | |
250 | 364 | ret = true; |
251 | | |
252 | 386 | end: |
253 | 386 | return ret; |
254 | 364 | } |
255 | | |
256 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
257 | | bool Sqr::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
258 | | (void)ds; |
259 | | bool ret = false; |
260 | | |
261 | | CF_CHECK_EQ(BN_sqr(res.GetDestPtr(), bn[0].GetPtr(), ctx.GetPtr()), 1); |
262 | | |
263 | | ret = true; |
264 | | |
265 | | end: |
266 | | |
267 | | return ret; |
268 | | } |
269 | | #endif |
270 | | |
271 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
272 | | bool GCD::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
273 | | (void)ds; |
274 | | bool ret = false; |
275 | | |
276 | | switch ( ds.Get<uint8_t>() ) { |
277 | | case 0: |
278 | | CF_CHECK_EQ(BN_gcd(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
279 | | break; |
280 | | #if defined(CRYPTOFUZZ_LIBRESSL) |
281 | | case 1: |
282 | | CF_CHECK_EQ(BN_gcd_ct(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
283 | | break; |
284 | | #endif |
285 | | default: |
286 | | goto end; |
287 | | } |
288 | | |
289 | | ret = true; |
290 | | |
291 | | end: |
292 | | return ret; |
293 | | } |
294 | | #endif |
295 | | |
296 | 38 | bool AddMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
297 | 38 | bool ret = false; |
298 | | |
299 | 38 | switch ( ds.Get<uint8_t>() ) { |
300 | 31 | case 0: |
301 | 31 | CF_CHECK_EQ(BN_mod_add(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1); |
302 | 20 | break; |
303 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
304 | | case 1: |
305 | | { |
306 | | Bignum zero(ds); |
307 | | CF_CHECK_EQ(zero.New(), true); |
308 | | |
309 | | /* "... may be used if both a and b are non-negative and less than m" */ |
310 | | CF_CHECK_GTE(BN_cmp(bn[0].GetPtr(), zero.GetPtr()), 0); |
311 | | CF_CHECK_GTE(BN_cmp(bn[1].GetPtr(), zero.GetPtr()), 0); |
312 | | CF_CHECK_LT(BN_cmp(bn[0].GetPtr(), bn[2].GetPtr()), 0); |
313 | | CF_CHECK_LT(BN_cmp(bn[1].GetPtr(), bn[2].GetPtr()), 0); |
314 | | CF_CHECK_EQ(BN_mod_add_quick(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr()), 1); |
315 | | } |
316 | | break; |
317 | | #endif |
318 | 4 | default: |
319 | 4 | goto end; |
320 | 4 | break; |
321 | 38 | } |
322 | | |
323 | 20 | ret = true; |
324 | | |
325 | 35 | end: |
326 | 35 | return ret; |
327 | 20 | } |
328 | | |
329 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
330 | | bool SubMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
331 | | bool ret = false; |
332 | | |
333 | | switch ( ds.Get<uint8_t>() ) { |
334 | | case 0: |
335 | | CF_CHECK_EQ(BN_mod_sub(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1); |
336 | | break; |
337 | | case 1: |
338 | | { |
339 | | Bignum zero(ds); |
340 | | CF_CHECK_EQ(zero.New(), true); |
341 | | |
342 | | /* "... may be used if both a and b are non-negative and less than m" */ |
343 | | CF_CHECK_GTE(BN_cmp(bn[0].GetPtr(), zero.GetPtr()), 0); |
344 | | CF_CHECK_GTE(BN_cmp(bn[1].GetPtr(), zero.GetPtr()), 0); |
345 | | CF_CHECK_LT(BN_cmp(bn[0].GetPtr(), bn[2].GetPtr()), 0); |
346 | | CF_CHECK_LT(BN_cmp(bn[1].GetPtr(), bn[2].GetPtr()), 0); |
347 | | CF_CHECK_EQ(BN_mod_sub_quick(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr()), 1); |
348 | | } |
349 | | default: |
350 | | goto end; |
351 | | break; |
352 | | } |
353 | | |
354 | | ret = true; |
355 | | |
356 | | end: |
357 | | return ret; |
358 | | } |
359 | | #endif |
360 | | |
361 | 41 | bool MulMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
362 | 41 | bool ret = false; |
363 | | |
364 | 41 | switch ( ds.Get<uint8_t>() ) { |
365 | 31 | case 0: |
366 | 31 | CF_CHECK_EQ(BN_mod_mul(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1); |
367 | 30 | break; |
368 | 8 | default: |
369 | 8 | goto end; |
370 | 8 | break; |
371 | 41 | } |
372 | | |
373 | 30 | ret = true; |
374 | | |
375 | 39 | end: |
376 | 39 | return ret; |
377 | 30 | } |
378 | | |
379 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
380 | | bool SqrMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
381 | | bool ret = false; |
382 | | |
383 | | switch ( ds.Get<uint8_t>() ) { |
384 | | case 0: |
385 | | CF_CHECK_EQ(BN_mod_sqr(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
386 | | break; |
387 | | default: |
388 | | goto end; |
389 | | break; |
390 | | } |
391 | | |
392 | | ret = true; |
393 | | |
394 | | end: |
395 | | return ret; |
396 | | } |
397 | | #endif |
398 | | |
399 | 416 | bool InvMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
400 | 416 | bool ret = false; |
401 | | |
402 | 416 | switch ( ds.Get<uint8_t>() ) { |
403 | 397 | case 0: |
404 | 397 | CF_CHECK_NE(BN_mod_inverse(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), nullptr); |
405 | 311 | break; |
406 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
407 | | case 1: |
408 | | { |
409 | | int out_no_inverse; |
410 | | CF_CHECK_LT(BN_cmp(bn[0].GetPtr(), bn[1].GetPtr()), 0); |
411 | | CF_CHECK_EQ(BN_is_odd(bn[1].GetPtr()), 1); |
412 | | CF_CHECK_EQ(BN_mod_inverse_odd(res.GetDestPtr(), &out_no_inverse, bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
413 | | } |
414 | | break; |
415 | | #endif |
416 | 12 | default: |
417 | 12 | goto end; |
418 | 12 | break; |
419 | 416 | } |
420 | | |
421 | 311 | ret = true; |
422 | | |
423 | 409 | end: |
424 | 409 | return ret; |
425 | 311 | } |
426 | | |
427 | 31 | bool Cmp::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
428 | 31 | (void)ds; |
429 | 31 | (void)ctx; |
430 | 31 | bool ret = false; |
431 | | |
432 | 31 | int cmpRes; |
433 | | |
434 | 31 | switch ( ds.Get<uint8_t>() ) { |
435 | 27 | case 0: |
436 | 27 | cmpRes = BN_cmp(bn[0].GetPtr(), bn[1].GetPtr()); |
437 | 27 | break; |
438 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
439 | | case 1: |
440 | | CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0); |
441 | | CF_CHECK_EQ(BN_is_negative(bn[1].GetPtr()), 0); |
442 | | cmpRes = BN_ucmp(bn[0].GetPtr(), bn[1].GetPtr()); |
443 | | break; |
444 | | #endif |
445 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
446 | | case 2: |
447 | | { |
448 | | auto val = bn[1].AsBN_ULONG(); |
449 | | CF_CHECK_NE(val, std::nullopt); |
450 | | cmpRes = BN_cmp_word(bn[0].GetPtr(), *val); |
451 | | } |
452 | | break; |
453 | | #endif |
454 | 2 | default: |
455 | 2 | goto end; |
456 | 2 | break; |
457 | 31 | } |
458 | | |
459 | 27 | if ( cmpRes > 0 ) { |
460 | 11 | cmpRes = 1; |
461 | 16 | } else if ( cmpRes < 0 ) { |
462 | 9 | cmpRes = -1; |
463 | 9 | } |
464 | | |
465 | 27 | #if defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
466 | | /* wolfCrypt's OpenSSL API cannot set negative numbers */ |
467 | 27 | if ( cmpRes == -1 ) { |
468 | 9 | goto end; |
469 | 9 | } |
470 | 18 | #endif |
471 | 18 | res.Set( std::to_string(cmpRes) ); |
472 | | |
473 | 18 | ret = true; |
474 | | |
475 | 29 | end: |
476 | 29 | return ret; |
477 | 18 | } |
478 | | |
479 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
480 | | bool Div::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
481 | | (void)ds; |
482 | | (void)ctx; |
483 | | bool ret = false; |
484 | | |
485 | | switch ( ds.Get<uint8_t>() ) { |
486 | | case 0: |
487 | | CF_CHECK_EQ(BN_div(res.GetDestPtr(), nullptr, bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
488 | | break; |
489 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
490 | | case 1: |
491 | | CF_CHECK_EQ(bn_div_consttime(res.GetDestPtr(), nullptr, bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
492 | | break; |
493 | | #endif |
494 | | case 2: |
495 | | { |
496 | | const auto val = bn[1].AsBN_ULONG(); |
497 | | CF_CHECK_NE(val, std::nullopt); |
498 | | |
499 | | CF_CHECK_NE(BN_div_word(bn.GetDestPtr(0), *val), (BN_ULONG)-1); |
500 | | CF_CHECK_EQ(res.Set(bn[0]), true); |
501 | | } |
502 | | break; |
503 | | default: |
504 | | goto end; |
505 | | break; |
506 | | } |
507 | | |
508 | | ret = true; |
509 | | |
510 | | end: |
511 | | return ret; |
512 | | } |
513 | | #endif |
514 | | |
515 | 3 | bool IsPrime::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
516 | 3 | (void)ds; |
517 | 3 | (void)ctx; |
518 | | |
519 | | #if defined(CRYPTOFUZZ_BORINGSSL) || defined(CRYPTOFUZZ_LIBRESSL) |
520 | | const int ret = BN_is_prime_ex(bn[0].GetPtr(), 0, nullptr, nullptr); |
521 | | if ( ret == -1 ) { |
522 | | return false; |
523 | | } |
524 | | |
525 | | res.Set( std::to_string(ret) ); |
526 | | |
527 | | return true; |
528 | | #else |
529 | 3 | (void)res; |
530 | 3 | (void)bn; |
531 | 3 | return false; |
532 | 3 | #endif |
533 | 3 | } |
534 | | |
535 | 3 | bool Sqrt::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
536 | 3 | (void)ds; |
537 | 3 | bool ret = false; |
538 | | |
539 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
540 | | CF_CHECK_EQ(BN_sqrt(res.GetDestPtr(), bn[0].GetPtr(), ctx.GetPtr()), 1); |
541 | | |
542 | | ret = true; |
543 | | |
544 | | end: |
545 | | #else |
546 | 3 | (void)res; |
547 | 3 | (void)bn; |
548 | 3 | (void)ctx; |
549 | | |
550 | 3 | #endif |
551 | 3 | return ret; |
552 | 3 | } |
553 | | |
554 | 10 | bool IsNeg::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
555 | 10 | (void)ds; |
556 | 10 | (void)ctx; |
557 | | |
558 | 10 | res.Set( std::to_string(BN_is_negative(bn[0].GetPtr())) ); |
559 | | |
560 | 10 | return true; |
561 | 10 | } |
562 | | |
563 | 6 | bool IsEq::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
564 | 6 | (void)ds; |
565 | 6 | (void)ctx; |
566 | | |
567 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
568 | | bool ret = false; |
569 | | |
570 | | switch ( ds.Get<uint8_t>() ) { |
571 | | case 0: |
572 | | res.Set( std::to_string(BN_equal_consttime(bn[0].GetPtr(), bn[1].GetPtr())) ); |
573 | | break; |
574 | | case 1: |
575 | | { |
576 | | auto val = bn[1].AsBN_ULONG(); |
577 | | CF_CHECK_NE(val, std::nullopt); |
578 | | res.Set( std::to_string(BN_is_word(bn[0].GetPtr(), *val)) ); |
579 | | } |
580 | | break; |
581 | | default: |
582 | | goto end; |
583 | | } |
584 | | |
585 | | ret = true; |
586 | | |
587 | | end: |
588 | | |
589 | | return ret; |
590 | | #else |
591 | 6 | (void)res; |
592 | 6 | (void)bn; |
593 | 6 | return false; |
594 | 6 | #endif |
595 | 6 | } |
596 | | |
597 | 18 | bool IsEven::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
598 | 18 | (void)ds; |
599 | 18 | (void)ctx; |
600 | | |
601 | 18 | res.Set( std::to_string(!BN_is_odd(bn[0].GetPtr())) ); |
602 | | |
603 | 18 | return true; |
604 | 18 | } |
605 | | |
606 | 14 | bool IsOdd::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
607 | 14 | (void)ds; |
608 | 14 | (void)ctx; |
609 | | |
610 | 14 | res.Set( std::to_string(BN_is_odd(bn[0].GetPtr())) ); |
611 | | |
612 | 14 | return true; |
613 | 14 | } |
614 | | |
615 | 23 | bool IsZero::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
616 | 23 | (void)ds; |
617 | 23 | (void)ctx; |
618 | | |
619 | 23 | res.Set( std::to_string(BN_is_zero(bn[0].GetPtr())) ); |
620 | | |
621 | 23 | return true; |
622 | 23 | } |
623 | | |
624 | 66 | bool IsOne::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
625 | 66 | (void)ds; |
626 | 66 | (void)ctx; |
627 | | |
628 | 66 | res.Set( std::to_string(BN_is_one(bn[0].GetPtr())) ); |
629 | | |
630 | 66 | return true; |
631 | 66 | } |
632 | | |
633 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
634 | | bool Jacobi::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
635 | | (void)ds; |
636 | | bool ret = false; |
637 | | |
638 | | #if !defined(CRYPTOFUZZ_BORINGSSL) |
639 | | const int jacobi = BN_kronecker(bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()); |
640 | | #else |
641 | | const int jacobi = bn_jacobi(bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()); |
642 | | #endif |
643 | | |
644 | | CF_CHECK_NE(jacobi, -2); |
645 | | |
646 | | res.Set( std::to_string(jacobi) ); |
647 | | |
648 | | ret = true; |
649 | | end: |
650 | | |
651 | | return ret; |
652 | | } |
653 | | #endif |
654 | | |
655 | | #if !defined(CRYPTOFUZZ_BORINGSSL) && !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
656 | | bool Mod_NIST_192::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
657 | | (void)ds; |
658 | | bool ret = false; |
659 | | |
660 | | CF_CHECK_EQ(BN_nist_mod_192(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
661 | | |
662 | | ret = true; |
663 | | |
664 | | end: |
665 | | return ret; |
666 | | } |
667 | | |
668 | | bool Mod_NIST_224::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
669 | | (void)ds; |
670 | | bool ret = false; |
671 | | |
672 | | CF_CHECK_EQ(BN_nist_mod_224(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
673 | | |
674 | | ret = true; |
675 | | |
676 | | end: |
677 | | return ret; |
678 | | } |
679 | | |
680 | | bool Mod_NIST_256::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
681 | | (void)ds; |
682 | | bool ret = false; |
683 | | |
684 | | CF_CHECK_EQ(BN_nist_mod_256(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
685 | | |
686 | | ret = true; |
687 | | |
688 | | end: |
689 | | return ret; |
690 | | } |
691 | | |
692 | | bool Mod_NIST_384::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
693 | | (void)ds; |
694 | | bool ret = false; |
695 | | |
696 | | CF_CHECK_EQ(BN_nist_mod_384(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
697 | | |
698 | | ret = true; |
699 | | |
700 | | end: |
701 | | return ret; |
702 | | } |
703 | | |
704 | | bool Mod_NIST_521::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
705 | | (void)ds; |
706 | | bool ret = false; |
707 | | |
708 | | CF_CHECK_EQ(BN_nist_mod_521(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
709 | | |
710 | | ret = true; |
711 | | |
712 | | end: |
713 | | return ret; |
714 | | } |
715 | | #endif |
716 | | |
717 | 7 | bool SqrtMod::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
718 | | /* Disabled due to slowness of primality testing */ |
719 | | #if 0 |
720 | | (void)ds; |
721 | | bool ret = false; |
722 | | |
723 | | /* Third parameter to BN_mod_sqrt must be prime */ |
724 | | CF_CHECK_EQ(BN_is_prime_ex(bn[1].GetPtr(), 64, ctx.GetPtr(), nullptr), 1); |
725 | | CF_CHECK_NE(BN_mod_sqrt(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), nullptr); |
726 | | |
727 | | ret = true; |
728 | | |
729 | | end: |
730 | | return ret; |
731 | | #else |
732 | 7 | (void)ds; |
733 | 7 | (void)res; |
734 | 7 | (void)bn; |
735 | 7 | (void)ctx; |
736 | 7 | return false; |
737 | 7 | #endif |
738 | 7 | } |
739 | | |
740 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
741 | | bool LCM::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
742 | | (void)ds; |
743 | | bool ret = false; |
744 | | |
745 | | CF_CHECK_EQ(bn_lcm_consttime(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
746 | | |
747 | | ret = true; |
748 | | |
749 | | end: |
750 | | return ret; |
751 | | } |
752 | | #endif |
753 | | |
754 | 10 | bool Exp::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
755 | 10 | (void)ds; |
756 | 10 | bool ret = false; |
757 | | |
758 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
759 | | CF_CHECK_EQ(BN_exp(res.GetDestPtr(), bn[0].GetPtr(), bn[1].GetPtr(), ctx.GetPtr()), 1); |
760 | | |
761 | | ret = true; |
762 | | |
763 | | end: |
764 | | #else |
765 | 10 | (void)res; |
766 | 10 | (void)bn; |
767 | 10 | (void)ctx; |
768 | | |
769 | 10 | return ret; |
770 | 10 | #endif |
771 | 10 | } |
772 | | |
773 | | /* BN_copy doesn't work in wolfCrypt's OpenSSL API */ |
774 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
775 | | bool Abs::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
776 | | (void)ds; |
777 | | (void)ctx; |
778 | | bool ret = false; |
779 | | |
780 | | if ( BN_is_negative(bn[0].GetPtr()) ) { |
781 | | Bignum zero(ds); |
782 | | CF_CHECK_EQ(zero.New(), true); |
783 | | |
784 | | switch ( ds.Get<uint8_t>() ) { |
785 | | case 0: |
786 | | CF_CHECK_EQ(BN_sub(res.GetDestPtr(), zero.GetPtr(), bn[0].GetPtr()), 1); |
787 | | break; |
788 | | case 1: |
789 | | CF_CHECK_EQ(BN_sub(res.GetDestPtr(), bn[0].GetPtr(), bn[0].GetPtr()), 1); |
790 | | CF_CHECK_EQ(BN_sub(res.GetDestPtr(), res.GetDestPtr(), bn[0].GetPtr()), 1); |
791 | | break; |
792 | | default: |
793 | | goto end; |
794 | | break; |
795 | | } |
796 | | } else { |
797 | | CF_CHECK_NE(BN_copy(res.GetDestPtr(), bn[0].GetPtr()), nullptr); |
798 | | } |
799 | | |
800 | | ret = true; |
801 | | |
802 | | end: |
803 | | return ret; |
804 | | } |
805 | | #endif |
806 | | |
807 | 32 | bool RShift::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
808 | 32 | (void)ctx; |
809 | 32 | bool ret = false; |
810 | 32 | std::optional<int> places; |
811 | | |
812 | 32 | CF_CHECK_NE(places = bn[1].AsInt(), std::nullopt); |
813 | |
|
814 | 0 | switch ( ds.Get<uint8_t>() ) { |
815 | 0 | case 0: |
816 | 0 | CF_CHECK_EQ(BN_rshift(res.GetDestPtr(), bn[0].GetPtr(), *places), 1); |
817 | 0 | break; |
818 | 0 | case 1: |
819 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
820 | | if ( *places != 1 ) { |
821 | | goto end; |
822 | | } |
823 | | CF_CHECK_EQ(BN_rshift1(res.GetDestPtr(), bn[0].GetPtr()), 1); |
824 | | break; |
825 | | #endif |
826 | 0 | default: |
827 | 0 | goto end; |
828 | 0 | } |
829 | | |
830 | 0 | ret = true; |
831 | |
|
832 | 32 | end: |
833 | 32 | return ret; |
834 | 0 | } |
835 | | |
836 | 1 | bool LShift1::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
837 | 1 | (void)ctx; |
838 | 1 | (void)ds; |
839 | 1 | bool ret = false; |
840 | | |
841 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
842 | | CF_CHECK_EQ(BN_lshift1(res.GetDestPtr(), bn[0].GetPtr()), 1); |
843 | | |
844 | | ret = true; |
845 | | |
846 | | end: |
847 | | #else |
848 | 1 | (void)res; |
849 | 1 | (void)bn; |
850 | 1 | #endif |
851 | 1 | return ret; |
852 | 1 | } |
853 | | |
854 | 15 | bool SetBit::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
855 | 15 | (void)ctx; |
856 | 15 | (void)ds; |
857 | 15 | bool ret = false; |
858 | 15 | std::optional<uint64_t> pos; |
859 | | |
860 | 15 | CF_CHECK_NE(pos = bn[1].AsInt(), std::nullopt); |
861 | |
|
862 | 0 | CF_CHECK_EQ(BN_set_bit(bn.GetDestPtr(0), *pos), 1); |
863 | 0 | CF_CHECK_NE(BN_copy(res.GetDestPtr(), bn[0].GetPtr()), nullptr); |
864 | |
|
865 | 0 | ret = true; |
866 | |
|
867 | 15 | end: |
868 | 15 | return ret; |
869 | 0 | } |
870 | | |
871 | 6 | bool ClearBit::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
872 | 6 | (void)ctx; |
873 | 6 | (void)ds; |
874 | 6 | bool ret = false; |
875 | 6 | std::optional<int> pos; |
876 | | |
877 | 6 | CF_CHECK_NE(pos = bn[1].AsInt(), std::nullopt); |
878 | |
|
879 | 0 | CF_CHECK_EQ(BN_clear_bit(bn.GetDestPtr(0), *pos), 1); |
880 | 0 | CF_CHECK_NE(BN_copy(res.GetDestPtr(), bn[0].GetPtr()), nullptr); |
881 | |
|
882 | 0 | ret = true; |
883 | |
|
884 | 6 | end: |
885 | 6 | return ret; |
886 | 0 | } |
887 | | |
888 | 8 | bool Bit::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
889 | 8 | (void)ctx; |
890 | 8 | (void)ds; |
891 | 8 | bool ret = false; |
892 | 8 | std::optional<int> pos; |
893 | | |
894 | 8 | CF_CHECK_NE(pos = bn[1].AsInt(), std::nullopt); |
895 | |
|
896 | 0 | res.Set( std::to_string(BN_is_bit_set(bn[0].GetPtr(), *pos)) ); |
897 | |
|
898 | 0 | ret = true; |
899 | |
|
900 | 8 | end: |
901 | 8 | return ret; |
902 | 0 | } |
903 | | |
904 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
905 | | bool CmpAbs::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
906 | | (void)ctx; |
907 | | (void)ds; |
908 | | |
909 | | int cmpRes = BN_ucmp(bn[0].GetPtr(), bn[1].GetPtr()); |
910 | | |
911 | | if ( cmpRes > 0 ) { |
912 | | cmpRes = 1; |
913 | | } else if ( cmpRes < 0 ) { |
914 | | cmpRes = -1; |
915 | | } |
916 | | |
917 | | res.Set( std::to_string(cmpRes) ); |
918 | | |
919 | | return true; |
920 | | } |
921 | | #endif |
922 | | |
923 | | #if !defined(CRYPTOFUZZ_WOLFCRYPT_OPENSSL) |
924 | | bool ModLShift::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
925 | | (void)ctx; |
926 | | (void)ds; |
927 | | bool ret = false; |
928 | | std::optional<uint64_t> places; |
929 | | |
930 | | CF_CHECK_NE(places = bn[1].AsInt(), std::nullopt); |
931 | | |
932 | | switch ( ds.Get<uint8_t>() ) { |
933 | | case 0: |
934 | | CF_CHECK_EQ(BN_mod_lshift(res.GetDestPtr(), bn[0].GetPtr(), *places, bn[2].GetPtr(), ctx.GetPtr()), 1); |
935 | | break; |
936 | | case 1: |
937 | | /* BN_mod_lshift_quick acts like BN_mod_lshift but requires that a be non-negative and less than m. */ |
938 | | CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0); |
939 | | CF_CHECK_LT(BN_cmp(bn[0].GetPtr(), bn[2].GetPtr()), 0); |
940 | | CF_CHECK_EQ(BN_mod_lshift_quick(res.GetDestPtr(), bn[0].GetPtr(), *places, bn[2].GetPtr()), 1); |
941 | | break; |
942 | | case 2: |
943 | | CF_CHECK_EQ(*places, 1); |
944 | | CF_CHECK_EQ(BN_mod_lshift1(res.GetDestPtr(), bn[0].GetPtr(), bn[2].GetPtr(), ctx.GetPtr()), 1); |
945 | | break; |
946 | | case 3: |
947 | | CF_CHECK_EQ(*places, 1); |
948 | | /* BN_mod_lshift1_quick acts like BN_mod_lshift1 but requires that a be non-negative and less than m. */ |
949 | | CF_CHECK_EQ(BN_is_negative(bn[0].GetPtr()), 0); |
950 | | CF_CHECK_LT(BN_cmp(bn[0].GetPtr(), bn[2].GetPtr()), 0); |
951 | | CF_CHECK_EQ(BN_mod_lshift1_quick(res.GetDestPtr(), bn[0].GetPtr(), bn[2].GetPtr()), 1); |
952 | | break; |
953 | | default: |
954 | | goto end; |
955 | | } |
956 | | |
957 | | ret = true; |
958 | | |
959 | | end: |
960 | | return ret; |
961 | | } |
962 | | #endif |
963 | | |
964 | 4 | bool IsPow2::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
965 | 4 | (void)ctx; |
966 | 4 | (void)ds; |
967 | | |
968 | | #if defined(CRYPTOFUZZ_BORINGSSL) |
969 | | res.Set( std::to_string(BN_is_pow2(bn[0].GetPtr())) ); |
970 | | |
971 | | return true; |
972 | | #else |
973 | 4 | (void)res; |
974 | 4 | (void)bn; |
975 | | |
976 | 4 | return false; |
977 | 4 | #endif |
978 | 4 | } |
979 | | |
980 | 8 | bool Mask::Run(Datasource& ds, Bignum& res, BignumCluster& bn, BN_CTX& ctx) const { |
981 | 8 | (void)ctx; |
982 | 8 | (void)ds; |
983 | 8 | bool ret = false; |
984 | | |
985 | 8 | std::optional<uint64_t> places; |
986 | | |
987 | 8 | CF_CHECK_NE(places = bn[1].AsInt(), std::nullopt); |
988 | 0 | CF_CHECK_EQ(BN_mask_bits(bn[0].GetDestPtr(), *places), 1); |
989 | 0 | CF_CHECK_EQ(res.Set(bn[0]), true); |
990 | |
|
991 | 0 | ret = true; |
992 | |
|
993 | 8 | end: |
994 | 8 | return ret; |
995 | 0 | } |
996 | | |
997 | | } /* namespace OpenSSL_bignum */ |
998 | | } /* namespace module */ |
999 | | } /* namespace cryptofuzz */ |