1 /* Start: bn_cutoffs.c */
2 #include "tommath_private.h"
3 #ifdef BN_CUTOFFS_C
4 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5 /* SPDX-License-Identifier: Unlicense */
6
7 #ifndef MP_FIXED_CUTOFFS
8 #include "tommath_cutoffs.h"
9 int KARATSUBA_MUL_CUTOFF = MP_DEFAULT_KARATSUBA_MUL_CUTOFF,
10 KARATSUBA_SQR_CUTOFF = MP_DEFAULT_KARATSUBA_SQR_CUTOFF,
11 TOOM_MUL_CUTOFF = MP_DEFAULT_TOOM_MUL_CUTOFF,
12 TOOM_SQR_CUTOFF = MP_DEFAULT_TOOM_SQR_CUTOFF;
13 #endif
14
15 #endif
16
17 /* End: bn_cutoffs.c */
18
19 /* Start: bn_deprecated.c */
20 #include "tommath_private.h"
21 #ifdef BN_DEPRECATED_C
22 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
23 /* SPDX-License-Identifier: Unlicense */
24
25 #ifdef BN_MP_GET_BIT_C
mp_get_bit(const mp_int * a,int b)26 int mp_get_bit(const mp_int *a, int b)
27 {
28 if (b < 0) {
29 return MP_VAL;
30 }
31 return (s_mp_get_bit(a, (unsigned int)b) == MP_YES) ? MP_YES : MP_NO;
32 }
33 #endif
34 #ifdef BN_MP_JACOBI_C
mp_jacobi(const mp_int * a,const mp_int * n,int * c)35 mp_err mp_jacobi(const mp_int *a, const mp_int *n, int *c)
36 {
37 if (a->sign == MP_NEG) {
38 return MP_VAL;
39 }
40 if (mp_cmp_d(n, 0uL) != MP_GT) {
41 return MP_VAL;
42 }
43 return mp_kronecker(a, n, c);
44 }
45 #endif
46 #ifdef BN_MP_PRIME_RANDOM_EX_C
mp_prime_random_ex(mp_int * a,int t,int size,int flags,private_mp_prime_callback cb,void * dat)47 mp_err mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat)
48 {
49 return s_mp_prime_random_ex(a, t, size, flags, cb, dat);
50 }
51 #endif
52 #ifdef BN_MP_RAND_DIGIT_C
mp_rand_digit(mp_digit * r)53 mp_err mp_rand_digit(mp_digit *r)
54 {
55 mp_err err = s_mp_rand_source(r, sizeof(mp_digit));
56 *r &= MP_MASK;
57 return err;
58 }
59 #endif
60 #ifdef BN_FAST_MP_INVMOD_C
fast_mp_invmod(const mp_int * a,const mp_int * b,mp_int * c)61 mp_err fast_mp_invmod(const mp_int *a, const mp_int *b, mp_int *c)
62 {
63 return s_mp_invmod_fast(a, b, c);
64 }
65 #endif
66 #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
fast_mp_montgomery_reduce(mp_int * x,const mp_int * n,mp_digit rho)67 mp_err fast_mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho)
68 {
69 return s_mp_montgomery_reduce_fast(x, n, rho);
70 }
71 #endif
72 #ifdef BN_FAST_S_MP_MUL_DIGS_C
fast_s_mp_mul_digs(const mp_int * a,const mp_int * b,mp_int * c,int digs)73 mp_err fast_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs)
74 {
75 return s_mp_mul_digs_fast(a, b, c, digs);
76 }
77 #endif
78 #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
fast_s_mp_mul_high_digs(const mp_int * a,const mp_int * b,mp_int * c,int digs)79 mp_err fast_s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs)
80 {
81 return s_mp_mul_high_digs_fast(a, b, c, digs);
82 }
83 #endif
84 #ifdef BN_FAST_S_MP_SQR_C
fast_s_mp_sqr(const mp_int * a,mp_int * b)85 mp_err fast_s_mp_sqr(const mp_int *a, mp_int *b)
86 {
87 return s_mp_sqr_fast(a, b);
88 }
89 #endif
90 #ifdef BN_MP_BALANCE_MUL_C
mp_balance_mul(const mp_int * a,const mp_int * b,mp_int * c)91 mp_err mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c)
92 {
93 return s_mp_balance_mul(a, b, c);
94 }
95 #endif
96 #ifdef BN_MP_EXPTMOD_FAST_C
mp_exptmod_fast(const mp_int * G,const mp_int * X,const mp_int * P,mp_int * Y,int redmode)97 mp_err mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode)
98 {
99 return s_mp_exptmod_fast(G, X, P, Y, redmode);
100 }
101 #endif
102 #ifdef BN_MP_INVMOD_SLOW_C
mp_invmod_slow(const mp_int * a,const mp_int * b,mp_int * c)103 mp_err mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c)
104 {
105 return s_mp_invmod_slow(a, b, c);
106 }
107 #endif
108 #ifdef BN_MP_KARATSUBA_MUL_C
mp_karatsuba_mul(const mp_int * a,const mp_int * b,mp_int * c)109 mp_err mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c)
110 {
111 return s_mp_karatsuba_mul(a, b, c);
112 }
113 #endif
114 #ifdef BN_MP_KARATSUBA_SQR_C
mp_karatsuba_sqr(const mp_int * a,mp_int * b)115 mp_err mp_karatsuba_sqr(const mp_int *a, mp_int *b)
116 {
117 return s_mp_karatsuba_sqr(a, b);
118 }
119 #endif
120 #ifdef BN_MP_TOOM_MUL_C
mp_toom_mul(const mp_int * a,const mp_int * b,mp_int * c)121 mp_err mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c)
122 {
123 return s_mp_toom_mul(a, b, c);
124 }
125 #endif
126 #ifdef BN_MP_TOOM_SQR_C
mp_toom_sqr(const mp_int * a,mp_int * b)127 mp_err mp_toom_sqr(const mp_int *a, mp_int *b)
128 {
129 return s_mp_toom_sqr(a, b);
130 }
131 #endif
132 #ifdef S_MP_REVERSE_C
bn_reverse(unsigned char * s,int len)133 void bn_reverse(unsigned char *s, int len)
134 {
135 if (len > 0) {
136 s_mp_reverse(s, (size_t)len);
137 }
138 }
139 #endif
140 #ifdef BN_MP_TC_AND_C
mp_tc_and(const mp_int * a,const mp_int * b,mp_int * c)141 mp_err mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c)
142 {
143 return mp_and(a, b, c);
144 }
145 #endif
146 #ifdef BN_MP_TC_OR_C
mp_tc_or(const mp_int * a,const mp_int * b,mp_int * c)147 mp_err mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c)
148 {
149 return mp_or(a, b, c);
150 }
151 #endif
152 #ifdef BN_MP_TC_XOR_C
mp_tc_xor(const mp_int * a,const mp_int * b,mp_int * c)153 mp_err mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c)
154 {
155 return mp_xor(a, b, c);
156 }
157 #endif
158 #ifdef BN_MP_TC_DIV_2D_C
mp_tc_div_2d(const mp_int * a,int b,mp_int * c)159 mp_err mp_tc_div_2d(const mp_int *a, int b, mp_int *c)
160 {
161 return mp_signed_rsh(a, b, c);
162 }
163 #endif
164 #ifdef BN_MP_INIT_SET_INT_C
mp_init_set_int(mp_int * a,unsigned long b)165 mp_err mp_init_set_int(mp_int *a, unsigned long b)
166 {
167 return mp_init_u32(a, (uint32_t)b);
168 }
169 #endif
170 #ifdef BN_MP_SET_INT_C
mp_set_int(mp_int * a,unsigned long b)171 mp_err mp_set_int(mp_int *a, unsigned long b)
172 {
173 mp_set_u32(a, (uint32_t)b);
174 return MP_OKAY;
175 }
176 #endif
177 #ifdef BN_MP_SET_LONG_C
mp_set_long(mp_int * a,unsigned long b)178 mp_err mp_set_long(mp_int *a, unsigned long b)
179 {
180 mp_set_u64(a, b);
181 return MP_OKAY;
182 }
183 #endif
184 #ifdef BN_MP_SET_LONG_LONG_C
mp_set_long_long(mp_int * a,unsigned long long b)185 mp_err mp_set_long_long(mp_int *a, unsigned long long b)
186 {
187 mp_set_u64(a, b);
188 return MP_OKAY;
189 }
190 #endif
191 #ifdef BN_MP_GET_INT_C
mp_get_int(const mp_int * a)192 unsigned long mp_get_int(const mp_int *a)
193 {
194 return (unsigned long)mp_get_mag_u32(a);
195 }
196 #endif
197 #ifdef BN_MP_GET_LONG_C
mp_get_long(const mp_int * a)198 unsigned long mp_get_long(const mp_int *a)
199 {
200 return (unsigned long)mp_get_mag_ul(a);
201 }
202 #endif
203 #ifdef BN_MP_GET_LONG_LONG_C
mp_get_long_long(const mp_int * a)204 unsigned long long mp_get_long_long(const mp_int *a)
205 {
206 return mp_get_mag_ull(a);
207 }
208 #endif
209 #ifdef BN_MP_PRIME_IS_DIVISIBLE_C
mp_prime_is_divisible(const mp_int * a,mp_bool * result)210 mp_err mp_prime_is_divisible(const mp_int *a, mp_bool *result)
211 {
212 return s_mp_prime_is_divisible(a, result);
213 }
214 #endif
215 #ifdef BN_MP_EXPT_D_EX_C
mp_expt_d_ex(const mp_int * a,mp_digit b,mp_int * c,int fast)216 mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
217 {
218 (void)fast;
219 if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) {
220 return MP_VAL;
221 }
222 return mp_expt_u32(a, (uint32_t)b, c);
223 }
224 #endif
225 #ifdef BN_MP_EXPT_D_C
mp_expt_d(const mp_int * a,mp_digit b,mp_int * c)226 mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c)
227 {
228 if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) {
229 return MP_VAL;
230 }
231 return mp_expt_u32(a, (uint32_t)b, c);
232 }
233 #endif
234 #ifdef BN_MP_N_ROOT_EX_C
mp_n_root_ex(const mp_int * a,mp_digit b,mp_int * c,int fast)235 mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast)
236 {
237 (void)fast;
238 if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) {
239 return MP_VAL;
240 }
241 return mp_root_u32(a, (uint32_t)b, c);
242 }
243 #endif
244 #ifdef BN_MP_N_ROOT_C
mp_n_root(const mp_int * a,mp_digit b,mp_int * c)245 mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c)
246 {
247 if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) {
248 return MP_VAL;
249 }
250 return mp_root_u32(a, (uint32_t)b, c);
251 }
252 #endif
253 #ifdef BN_MP_UNSIGNED_BIN_SIZE_C
mp_unsigned_bin_size(const mp_int * a)254 int mp_unsigned_bin_size(const mp_int *a)
255 {
256 return (int)mp_ubin_size(a);
257 }
258 #endif
259 #ifdef BN_MP_READ_UNSIGNED_BIN_C
mp_read_unsigned_bin(mp_int * a,const unsigned char * b,int c)260 mp_err mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c)
261 {
262 return mp_from_ubin(a, b, (size_t) c);
263 }
264 #endif
265 #ifdef BN_MP_TO_UNSIGNED_BIN_C
mp_to_unsigned_bin(const mp_int * a,unsigned char * b)266 mp_err mp_to_unsigned_bin(const mp_int *a, unsigned char *b)
267 {
268 return mp_to_ubin(a, b, SIZE_MAX, NULL);
269 }
270 #endif
271 #ifdef BN_MP_TO_UNSIGNED_BIN_N_C
mp_to_unsigned_bin_n(const mp_int * a,unsigned char * b,unsigned long * outlen)272 mp_err mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen)
273 {
274 size_t n = mp_ubin_size(a);
275 if (*outlen < (unsigned long)n) {
276 return MP_VAL;
277 }
278 *outlen = (unsigned long)n;
279 return mp_to_ubin(a, b, n, NULL);
280 }
281 #endif
282 #ifdef BN_MP_SIGNED_BIN_SIZE_C
mp_signed_bin_size(const mp_int * a)283 int mp_signed_bin_size(const mp_int *a)
284 {
285 return (int)mp_sbin_size(a);
286 }
287 #endif
288 #ifdef BN_MP_READ_SIGNED_BIN_C
mp_read_signed_bin(mp_int * a,const unsigned char * b,int c)289 mp_err mp_read_signed_bin(mp_int *a, const unsigned char *b, int c)
290 {
291 return mp_from_sbin(a, b, (size_t) c);
292 }
293 #endif
294 #ifdef BN_MP_TO_SIGNED_BIN_C
mp_to_signed_bin(const mp_int * a,unsigned char * b)295 mp_err mp_to_signed_bin(const mp_int *a, unsigned char *b)
296 {
297 return mp_to_sbin(a, b, SIZE_MAX, NULL);
298 }
299 #endif
300 #ifdef BN_MP_TO_SIGNED_BIN_N_C
mp_to_signed_bin_n(const mp_int * a,unsigned char * b,unsigned long * outlen)301 mp_err mp_to_signed_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen)
302 {
303 size_t n = mp_sbin_size(a);
304 if (*outlen < (unsigned long)n) {
305 return MP_VAL;
306 }
307 *outlen = (unsigned long)n;
308 return mp_to_sbin(a, b, n, NULL);
309 }
310 #endif
311 #ifdef BN_MP_TORADIX_N_C
mp_toradix_n(const mp_int * a,char * str,int radix,int maxlen)312 mp_err mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen)
313 {
314 if (maxlen < 0) {
315 return MP_VAL;
316 }
317 return mp_to_radix(a, str, (size_t)maxlen, NULL, radix);
318 }
319 #endif
320 #ifdef BN_MP_TORADIX_C
mp_toradix(const mp_int * a,char * str,int radix)321 mp_err mp_toradix(const mp_int *a, char *str, int radix)
322 {
323 return mp_to_radix(a, str, SIZE_MAX, NULL, radix);
324 }
325 #endif
326 #ifdef BN_MP_IMPORT_C
mp_import(mp_int * rop,size_t count,int order,size_t size,int endian,size_t nails,const void * op)327 mp_err mp_import(mp_int *rop, size_t count, int order, size_t size, int endian, size_t nails,
328 const void *op)
329 {
330 return mp_unpack(rop, count, order, size, endian, nails, op);
331 }
332 #endif
333 #ifdef BN_MP_EXPORT_C
mp_export(void * rop,size_t * countp,int order,size_t size,int endian,size_t nails,const mp_int * op)334 mp_err mp_export(void *rop, size_t *countp, int order, size_t size,
335 int endian, size_t nails, const mp_int *op)
336 {
337 return mp_pack(rop, SIZE_MAX, countp, order, size, endian, nails, op);
338 }
339 #endif
340 #endif
341
342 /* End: bn_deprecated.c */
343
344 /* Start: bn_mp_2expt.c */
345 #include "tommath_private.h"
346 #ifdef BN_MP_2EXPT_C
347 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
348 /* SPDX-License-Identifier: Unlicense */
349
350 /* computes a = 2**b
351 *
352 * Simple algorithm which zeroes the int, grows it then just sets one bit
353 * as required.
354 */
mp_2expt(mp_int * a,int b)355 mp_err mp_2expt(mp_int *a, int b)
356 {
357 mp_err err;
358
359 /* zero a as per default */
360 mp_zero(a);
361
362 /* grow a to accomodate the single bit */
363 if ((err = mp_grow(a, (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) {
364 return err;
365 }
366
367 /* set the used count of where the bit will go */
368 a->used = (b / MP_DIGIT_BIT) + 1;
369
370 /* put the single bit in its place */
371 a->dp[b / MP_DIGIT_BIT] = (mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT);
372
373 return MP_OKAY;
374 }
375 #endif
376
377 /* End: bn_mp_2expt.c */
378
379 /* Start: bn_mp_abs.c */
380 #include "tommath_private.h"
381 #ifdef BN_MP_ABS_C
382 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
383 /* SPDX-License-Identifier: Unlicense */
384
385 /* b = |a|
386 *
387 * Simple function copies the input and fixes the sign to positive
388 */
mp_abs(const mp_int * a,mp_int * b)389 mp_err mp_abs(const mp_int *a, mp_int *b)
390 {
391 mp_err err;
392
393 /* copy a to b */
394 if (a != b) {
395 if ((err = mp_copy(a, b)) != MP_OKAY) {
396 return err;
397 }
398 }
399
400 /* force the sign of b to positive */
401 b->sign = MP_ZPOS;
402
403 return MP_OKAY;
404 }
405 #endif
406
407 /* End: bn_mp_abs.c */
408
409 /* Start: bn_mp_add.c */
410 #include "tommath_private.h"
411 #ifdef BN_MP_ADD_C
412 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
413 /* SPDX-License-Identifier: Unlicense */
414
415 /* high level addition (handles signs) */
mp_add(const mp_int * a,const mp_int * b,mp_int * c)416 mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c)
417 {
418 mp_sign sa, sb;
419 mp_err err;
420
421 /* get sign of both inputs */
422 sa = a->sign;
423 sb = b->sign;
424
425 /* handle two cases, not four */
426 if (sa == sb) {
427 /* both positive or both negative */
428 /* add their magnitudes, copy the sign */
429 c->sign = sa;
430 err = s_mp_add(a, b, c);
431 } else {
432 /* one positive, the other negative */
433 /* subtract the one with the greater magnitude from */
434 /* the one of the lesser magnitude. The result gets */
435 /* the sign of the one with the greater magnitude. */
436 if (mp_cmp_mag(a, b) == MP_LT) {
437 c->sign = sb;
438 err = s_mp_sub(b, a, c);
439 } else {
440 c->sign = sa;
441 err = s_mp_sub(a, b, c);
442 }
443 }
444 return err;
445 }
446
447 #endif
448
449 /* End: bn_mp_add.c */
450
451 /* Start: bn_mp_add_d.c */
452 #include "tommath_private.h"
453 #ifdef BN_MP_ADD_D_C
454 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
455 /* SPDX-License-Identifier: Unlicense */
456
457 /* single digit addition */
mp_add_d(const mp_int * a,mp_digit b,mp_int * c)458 mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c)
459 {
460 mp_err err;
461 int ix, oldused;
462 mp_digit *tmpa, *tmpc;
463
464 /* grow c as required */
465 if (c->alloc < (a->used + 1)) {
466 if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) {
467 return err;
468 }
469 }
470
471 /* if a is negative and |a| >= b, call c = |a| - b */
472 if ((a->sign == MP_NEG) && ((a->used > 1) || (a->dp[0] >= b))) {
473 mp_int a_ = *a;
474 /* temporarily fix sign of a */
475 a_.sign = MP_ZPOS;
476
477 /* c = |a| - b */
478 err = mp_sub_d(&a_, b, c);
479
480 /* fix sign */
481 c->sign = MP_NEG;
482
483 /* clamp */
484 mp_clamp(c);
485
486 return err;
487 }
488
489 /* old number of used digits in c */
490 oldused = c->used;
491
492 /* source alias */
493 tmpa = a->dp;
494
495 /* destination alias */
496 tmpc = c->dp;
497
498 /* if a is positive */
499 if (a->sign == MP_ZPOS) {
500 /* add digits, mu is carry */
501 mp_digit mu = b;
502 for (ix = 0; ix < a->used; ix++) {
503 *tmpc = *tmpa++ + mu;
504 mu = *tmpc >> MP_DIGIT_BIT;
505 *tmpc++ &= MP_MASK;
506 }
507 /* set final carry */
508 ix++;
509 *tmpc++ = mu;
510
511 /* setup size */
512 c->used = a->used + 1;
513 } else {
514 /* a was negative and |a| < b */
515 c->used = 1;
516
517 /* the result is a single digit */
518 if (a->used == 1) {
519 *tmpc++ = b - a->dp[0];
520 } else {
521 *tmpc++ = b;
522 }
523
524 /* setup count so the clearing of oldused
525 * can fall through correctly
526 */
527 ix = 1;
528 }
529
530 /* sign always positive */
531 c->sign = MP_ZPOS;
532
533 /* now zero to oldused */
534 MP_ZERO_DIGITS(tmpc, oldused - ix);
535 mp_clamp(c);
536
537 return MP_OKAY;
538 }
539
540 #endif
541
542 /* End: bn_mp_add_d.c */
543
544 /* Start: bn_mp_addmod.c */
545 #include "tommath_private.h"
546 #ifdef BN_MP_ADDMOD_C
547 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
548 /* SPDX-License-Identifier: Unlicense */
549
550 /* d = a + b (mod c) */
mp_addmod(const mp_int * a,const mp_int * b,const mp_int * c,mp_int * d)551 mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d)
552 {
553 mp_err err;
554 mp_int t;
555
556 if ((err = mp_init(&t)) != MP_OKAY) {
557 return err;
558 }
559
560 if ((err = mp_add(a, b, &t)) != MP_OKAY) {
561 goto LBL_ERR;
562 }
563 err = mp_mod(&t, c, d);
564
565 LBL_ERR:
566 mp_clear(&t);
567 return err;
568 }
569 #endif
570
571 /* End: bn_mp_addmod.c */
572
573 /* Start: bn_mp_and.c */
574 #include "tommath_private.h"
575 #ifdef BN_MP_AND_C
576 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
577 /* SPDX-License-Identifier: Unlicense */
578
579 /* two complement and */
mp_and(const mp_int * a,const mp_int * b,mp_int * c)580 mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c)
581 {
582 int used = MP_MAX(a->used, b->used) + 1, i;
583 mp_err err;
584 mp_digit ac = 1, bc = 1, cc = 1;
585 mp_sign csign = ((a->sign == MP_NEG) && (b->sign == MP_NEG)) ? MP_NEG : MP_ZPOS;
586
587 if (c->alloc < used) {
588 if ((err = mp_grow(c, used)) != MP_OKAY) {
589 return err;
590 }
591 }
592
593 for (i = 0; i < used; i++) {
594 mp_digit x, y;
595
596 /* convert to two complement if negative */
597 if (a->sign == MP_NEG) {
598 ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK);
599 x = ac & MP_MASK;
600 ac >>= MP_DIGIT_BIT;
601 } else {
602 x = (i >= a->used) ? 0uL : a->dp[i];
603 }
604
605 /* convert to two complement if negative */
606 if (b->sign == MP_NEG) {
607 bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK);
608 y = bc & MP_MASK;
609 bc >>= MP_DIGIT_BIT;
610 } else {
611 y = (i >= b->used) ? 0uL : b->dp[i];
612 }
613
614 c->dp[i] = x & y;
615
616 /* convert to to sign-magnitude if negative */
617 if (csign == MP_NEG) {
618 cc += ~c->dp[i] & MP_MASK;
619 c->dp[i] = cc & MP_MASK;
620 cc >>= MP_DIGIT_BIT;
621 }
622 }
623
624 c->used = used;
625 c->sign = csign;
626 mp_clamp(c);
627 return MP_OKAY;
628 }
629 #endif
630
631 /* End: bn_mp_and.c */
632
633 /* Start: bn_mp_clamp.c */
634 #include "tommath_private.h"
635 #ifdef BN_MP_CLAMP_C
636 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
637 /* SPDX-License-Identifier: Unlicense */
638
639 /* trim unused digits
640 *
641 * This is used to ensure that leading zero digits are
642 * trimed and the leading "used" digit will be non-zero
643 * Typically very fast. Also fixes the sign if there
644 * are no more leading digits
645 */
mp_clamp(mp_int * a)646 void mp_clamp(mp_int *a)
647 {
648 /* decrease used while the most significant digit is
649 * zero.
650 */
651 while ((a->used > 0) && (a->dp[a->used - 1] == 0u)) {
652 --(a->used);
653 }
654
655 /* reset the sign flag if used == 0 */
656 if (a->used == 0) {
657 a->sign = MP_ZPOS;
658 }
659 }
660 #endif
661
662 /* End: bn_mp_clamp.c */
663
664 /* Start: bn_mp_clear.c */
665 #include "tommath_private.h"
666 #ifdef BN_MP_CLEAR_C
667 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
668 /* SPDX-License-Identifier: Unlicense */
669
670 /* clear one (frees) */
mp_clear(mp_int * a)671 void mp_clear(mp_int *a)
672 {
673 /* only do anything if a hasn't been freed previously */
674 if (a->dp != NULL) {
675 /* free ram */
676 MP_FREE_DIGITS(a->dp, a->alloc);
677
678 /* reset members to make debugging easier */
679 a->dp = NULL;
680 a->alloc = a->used = 0;
681 a->sign = MP_ZPOS;
682 }
683 }
684 #endif
685
686 /* End: bn_mp_clear.c */
687
688 /* Start: bn_mp_clear_multi.c */
689 #include "tommath_private.h"
690 #ifdef BN_MP_CLEAR_MULTI_C
691 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
692 /* SPDX-License-Identifier: Unlicense */
693
694 #include <stdarg.h>
695
mp_clear_multi(mp_int * mp,...)696 void mp_clear_multi(mp_int *mp, ...)
697 {
698 mp_int *next_mp = mp;
699 va_list args;
700 va_start(args, mp);
701 while (next_mp != NULL) {
702 mp_clear(next_mp);
703 next_mp = va_arg(args, mp_int *);
704 }
705 va_end(args);
706 }
707 #endif
708
709 /* End: bn_mp_clear_multi.c */
710
711 /* Start: bn_mp_cmp.c */
712 #include "tommath_private.h"
713 #ifdef BN_MP_CMP_C
714 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
715 /* SPDX-License-Identifier: Unlicense */
716
717 /* compare two ints (signed)*/
mp_cmp(const mp_int * a,const mp_int * b)718 mp_ord mp_cmp(const mp_int *a, const mp_int *b)
719 {
720 /* compare based on sign */
721 if (a->sign != b->sign) {
722 if (a->sign == MP_NEG) {
723 return MP_LT;
724 } else {
725 return MP_GT;
726 }
727 }
728
729 /* compare digits */
730 if (a->sign == MP_NEG) {
731 /* if negative compare opposite direction */
732 return mp_cmp_mag(b, a);
733 } else {
734 return mp_cmp_mag(a, b);
735 }
736 }
737 #endif
738
739 /* End: bn_mp_cmp.c */
740
741 /* Start: bn_mp_cmp_d.c */
742 #include "tommath_private.h"
743 #ifdef BN_MP_CMP_D_C
744 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
745 /* SPDX-License-Identifier: Unlicense */
746
747 /* compare a digit */
mp_cmp_d(const mp_int * a,mp_digit b)748 mp_ord mp_cmp_d(const mp_int *a, mp_digit b)
749 {
750 /* compare based on sign */
751 if (a->sign == MP_NEG) {
752 return MP_LT;
753 }
754
755 /* compare based on magnitude */
756 if (a->used > 1) {
757 return MP_GT;
758 }
759
760 /* compare the only digit of a to b */
761 if (a->dp[0] > b) {
762 return MP_GT;
763 } else if (a->dp[0] < b) {
764 return MP_LT;
765 } else {
766 return MP_EQ;
767 }
768 }
769 #endif
770
771 /* End: bn_mp_cmp_d.c */
772
773 /* Start: bn_mp_cmp_mag.c */
774 #include "tommath_private.h"
775 #ifdef BN_MP_CMP_MAG_C
776 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
777 /* SPDX-License-Identifier: Unlicense */
778
779 /* compare maginitude of two ints (unsigned) */
mp_cmp_mag(const mp_int * a,const mp_int * b)780 mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b)
781 {
782 int n;
783 const mp_digit *tmpa, *tmpb;
784
785 /* compare based on # of non-zero digits */
786 if (a->used > b->used) {
787 return MP_GT;
788 }
789
790 if (a->used < b->used) {
791 return MP_LT;
792 }
793
794 /* alias for a */
795 tmpa = a->dp + (a->used - 1);
796
797 /* alias for b */
798 tmpb = b->dp + (a->used - 1);
799
800 /* compare based on digits */
801 for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
802 if (*tmpa > *tmpb) {
803 return MP_GT;
804 }
805
806 if (*tmpa < *tmpb) {
807 return MP_LT;
808 }
809 }
810 return MP_EQ;
811 }
812 #endif
813
814 /* End: bn_mp_cmp_mag.c */
815
816 /* Start: bn_mp_cnt_lsb.c */
817 #include "tommath_private.h"
818 #ifdef BN_MP_CNT_LSB_C
819 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
820 /* SPDX-License-Identifier: Unlicense */
821
822 static const int lnz[16] = {
823 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
824 };
825
826 /* Counts the number of lsbs which are zero before the first zero bit */
mp_cnt_lsb(const mp_int * a)827 int mp_cnt_lsb(const mp_int *a)
828 {
829 int x;
830 mp_digit q, qq;
831
832 /* easy out */
833 if (MP_IS_ZERO(a)) {
834 return 0;
835 }
836
837 /* scan lower digits until non-zero */
838 for (x = 0; (x < a->used) && (a->dp[x] == 0u); x++) {}
839 q = a->dp[x];
840 x *= MP_DIGIT_BIT;
841
842 /* now scan this digit until a 1 is found */
843 if ((q & 1u) == 0u) {
844 do {
845 qq = q & 15u;
846 x += lnz[qq];
847 q >>= 4;
848 } while (qq == 0u);
849 }
850 return x;
851 }
852
853 #endif
854
855 /* End: bn_mp_cnt_lsb.c */
856
857 /* Start: bn_mp_complement.c */
858 #include "tommath_private.h"
859 #ifdef BN_MP_COMPLEMENT_C
860 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
861 /* SPDX-License-Identifier: Unlicense */
862
863 /* b = ~a */
mp_complement(const mp_int * a,mp_int * b)864 mp_err mp_complement(const mp_int *a, mp_int *b)
865 {
866 mp_err err = mp_neg(a, b);
867 return (err == MP_OKAY) ? mp_sub_d(b, 1uL, b) : err;
868 }
869 #endif
870
871 /* End: bn_mp_complement.c */
872
873 /* Start: bn_mp_copy.c */
874 #include "tommath_private.h"
875 #ifdef BN_MP_COPY_C
876 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
877 /* SPDX-License-Identifier: Unlicense */
878
879 /* copy, b = a */
mp_copy(const mp_int * a,mp_int * b)880 mp_err mp_copy(const mp_int *a, mp_int *b)
881 {
882 int n;
883 mp_digit *tmpa, *tmpb;
884 mp_err err;
885
886 /* if dst == src do nothing */
887 if (a == b) {
888 return MP_OKAY;
889 }
890
891 /* grow dest */
892 if (b->alloc < a->used) {
893 if ((err = mp_grow(b, a->used)) != MP_OKAY) {
894 return err;
895 }
896 }
897
898 /* zero b and copy the parameters over */
899 /* pointer aliases */
900
901 /* source */
902 tmpa = a->dp;
903
904 /* destination */
905 tmpb = b->dp;
906
907 /* copy all the digits */
908 for (n = 0; n < a->used; n++) {
909 *tmpb++ = *tmpa++;
910 }
911
912 /* clear high digits */
913 MP_ZERO_DIGITS(tmpb, b->used - n);
914
915 /* copy used count and sign */
916 b->used = a->used;
917 b->sign = a->sign;
918 return MP_OKAY;
919 }
920 #endif
921
922 /* End: bn_mp_copy.c */
923
924 /* Start: bn_mp_count_bits.c */
925 #include "tommath_private.h"
926 #ifdef BN_MP_COUNT_BITS_C
927 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
928 /* SPDX-License-Identifier: Unlicense */
929
930 /* returns the number of bits in an int */
mp_count_bits(const mp_int * a)931 int mp_count_bits(const mp_int *a)
932 {
933 int r;
934 mp_digit q;
935
936 /* shortcut */
937 if (MP_IS_ZERO(a)) {
938 return 0;
939 }
940
941 /* get number of digits and add that */
942 r = (a->used - 1) * MP_DIGIT_BIT;
943
944 /* take the last digit and count the bits in it */
945 q = a->dp[a->used - 1];
946 while (q > 0u) {
947 ++r;
948 q >>= 1u;
949 }
950 return r;
951 }
952 #endif
953
954 /* End: bn_mp_count_bits.c */
955
956 /* Start: bn_mp_decr.c */
957 #include "tommath_private.h"
958 #ifdef BN_MP_DECR_C
959 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
960 /* SPDX-License-Identifier: Unlicense */
961
962 /* Decrement "a" by one like "a--". Changes input! */
mp_decr(mp_int * a)963 mp_err mp_decr(mp_int *a)
964 {
965 if (MP_IS_ZERO(a)) {
966 mp_set(a,1uL);
967 a->sign = MP_NEG;
968 return MP_OKAY;
969 } else if (a->sign == MP_NEG) {
970 mp_err err;
971 a->sign = MP_ZPOS;
972 if ((err = mp_incr(a)) != MP_OKAY) {
973 return err;
974 }
975 /* There is no -0 in LTM */
976 if (!MP_IS_ZERO(a)) {
977 a->sign = MP_NEG;
978 }
979 return MP_OKAY;
980 } else if (a->dp[0] > 1uL) {
981 a->dp[0]--;
982 if (a->dp[0] == 0u) {
983 mp_zero(a);
984 }
985 return MP_OKAY;
986 } else {
987 return mp_sub_d(a, 1uL,a);
988 }
989 }
990 #endif
991
992 /* End: bn_mp_decr.c */
993
994 /* Start: bn_mp_div.c */
995 #include "tommath_private.h"
996 #ifdef BN_MP_DIV_C
997 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
998 /* SPDX-License-Identifier: Unlicense */
999
1000 #ifdef BN_MP_DIV_SMALL
1001
1002 /* slower bit-bang division... also smaller */
mp_div(const mp_int * a,const mp_int * b,mp_int * c,mp_int * d)1003 mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d)
1004 {
1005 mp_int ta, tb, tq, q;
1006 int n, n2;
1007 mp_err err;
1008
1009 /* is divisor zero ? */
1010 if (MP_IS_ZERO(b)) {
1011 return MP_VAL;
1012 }
1013
1014 /* if a < b then q=0, r = a */
1015 if (mp_cmp_mag(a, b) == MP_LT) {
1016 if (d != NULL) {
1017 err = mp_copy(a, d);
1018 } else {
1019 err = MP_OKAY;
1020 }
1021 if (c != NULL) {
1022 mp_zero(c);
1023 }
1024 return err;
1025 }
1026
1027 /* init our temps */
1028 if ((err = mp_init_multi(&ta, &tb, &tq, &q, NULL)) != MP_OKAY) {
1029 return err;
1030 }
1031
1032
1033 mp_set(&tq, 1uL);
1034 n = mp_count_bits(a) - mp_count_bits(b);
1035 if ((err = mp_abs(a, &ta)) != MP_OKAY) goto LBL_ERR;
1036 if ((err = mp_abs(b, &tb)) != MP_OKAY) goto LBL_ERR;
1037 if ((err = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) goto LBL_ERR;
1038 if ((err = mp_mul_2d(&tq, n, &tq)) != MP_OKAY) goto LBL_ERR;
1039
1040 while (n-- >= 0) {
1041 if (mp_cmp(&tb, &ta) != MP_GT) {
1042 if ((err = mp_sub(&ta, &tb, &ta)) != MP_OKAY) goto LBL_ERR;
1043 if ((err = mp_add(&q, &tq, &q)) != MP_OKAY) goto LBL_ERR;
1044 }
1045 if ((err = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) goto LBL_ERR;
1046 if ((err = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY) goto LBL_ERR;
1047 }
1048
1049 /* now q == quotient and ta == remainder */
1050 n = a->sign;
1051 n2 = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
1052 if (c != NULL) {
1053 mp_exch(c, &q);
1054 c->sign = MP_IS_ZERO(c) ? MP_ZPOS : n2;
1055 }
1056 if (d != NULL) {
1057 mp_exch(d, &ta);
1058 d->sign = MP_IS_ZERO(d) ? MP_ZPOS : n;
1059 }
1060 LBL_ERR:
1061 mp_clear_multi(&ta, &tb, &tq, &q, NULL);
1062 return err;
1063 }
1064
1065 #else
1066
1067 /* integer signed division.
1068 * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
1069 * HAC pp.598 Algorithm 14.20
1070 *
1071 * Note that the description in HAC is horribly
1072 * incomplete. For example, it doesn't consider
1073 * the case where digits are removed from 'x' in
1074 * the inner loop. It also doesn't consider the
1075 * case that y has fewer than three digits, etc..
1076 *
1077 * The overall algorithm is as described as
1078 * 14.20 from HAC but fixed to treat these cases.
1079 */
mp_div(const mp_int * a,const mp_int * b,mp_int * c,mp_int * d)1080 mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d)
1081 {
1082 mp_int q, x, y, t1, t2;
1083 int n, t, i, norm;
1084 mp_sign neg;
1085 mp_err err;
1086
1087 /* is divisor zero ? */
1088 if (MP_IS_ZERO(b)) {
1089 return MP_VAL;
1090 }
1091
1092 /* if a < b then q=0, r = a */
1093 if (mp_cmp_mag(a, b) == MP_LT) {
1094 if (d != NULL) {
1095 err = mp_copy(a, d);
1096 } else {
1097 err = MP_OKAY;
1098 }
1099 if (c != NULL) {
1100 mp_zero(c);
1101 }
1102 return err;
1103 }
1104
1105 if ((err = mp_init_size(&q, a->used + 2)) != MP_OKAY) {
1106 return err;
1107 }
1108 q.used = a->used + 2;
1109
1110 if ((err = mp_init(&t1)) != MP_OKAY) goto LBL_Q;
1111
1112 if ((err = mp_init(&t2)) != MP_OKAY) goto LBL_T1;
1113
1114 if ((err = mp_init_copy(&x, a)) != MP_OKAY) goto LBL_T2;
1115
1116 if ((err = mp_init_copy(&y, b)) != MP_OKAY) goto LBL_X;
1117
1118 /* fix the sign */
1119 neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
1120 x.sign = y.sign = MP_ZPOS;
1121
1122 /* normalize both x and y, ensure that y >= b/2, [b == 2**MP_DIGIT_BIT] */
1123 norm = mp_count_bits(&y) % MP_DIGIT_BIT;
1124 if (norm < (MP_DIGIT_BIT - 1)) {
1125 norm = (MP_DIGIT_BIT - 1) - norm;
1126 if ((err = mp_mul_2d(&x, norm, &x)) != MP_OKAY) goto LBL_Y;
1127 if ((err = mp_mul_2d(&y, norm, &y)) != MP_OKAY) goto LBL_Y;
1128 } else {
1129 norm = 0;
1130 }
1131
1132 /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
1133 n = x.used - 1;
1134 t = y.used - 1;
1135
1136 /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
1137 /* y = y*b**{n-t} */
1138 if ((err = mp_lshd(&y, n - t)) != MP_OKAY) goto LBL_Y;
1139
1140 while (mp_cmp(&x, &y) != MP_LT) {
1141 ++(q.dp[n - t]);
1142 if ((err = mp_sub(&x, &y, &x)) != MP_OKAY) goto LBL_Y;
1143 }
1144
1145 /* reset y by shifting it back down */
1146 mp_rshd(&y, n - t);
1147
1148 /* step 3. for i from n down to (t + 1) */
1149 for (i = n; i >= (t + 1); i--) {
1150 if (i > x.used) {
1151 continue;
1152 }
1153
1154 /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
1155 * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
1156 if (x.dp[i] == y.dp[t]) {
1157 q.dp[(i - t) - 1] = ((mp_digit)1 << (mp_digit)MP_DIGIT_BIT) - (mp_digit)1;
1158 } else {
1159 mp_word tmp;
1160 tmp = (mp_word)x.dp[i] << (mp_word)MP_DIGIT_BIT;
1161 tmp |= (mp_word)x.dp[i - 1];
1162 tmp /= (mp_word)y.dp[t];
1163 if (tmp > (mp_word)MP_MASK) {
1164 tmp = MP_MASK;
1165 }
1166 q.dp[(i - t) - 1] = (mp_digit)(tmp & (mp_word)MP_MASK);
1167 }
1168
1169 /* while (q{i-t-1} * (yt * b + y{t-1})) >
1170 xi * b**2 + xi-1 * b + xi-2
1171
1172 do q{i-t-1} -= 1;
1173 */
1174 q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] + 1uL) & (mp_digit)MP_MASK;
1175 do {
1176 q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & (mp_digit)MP_MASK;
1177
1178 /* find left hand */
1179 mp_zero(&t1);
1180 t1.dp[0] = ((t - 1) < 0) ? 0u : y.dp[t - 1];
1181 t1.dp[1] = y.dp[t];
1182 t1.used = 2;
1183 if ((err = mp_mul_d(&t1, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y;
1184
1185 /* find right hand */
1186 t2.dp[0] = ((i - 2) < 0) ? 0u : x.dp[i - 2];
1187 t2.dp[1] = x.dp[i - 1]; /* i >= 1 always holds */
1188 t2.dp[2] = x.dp[i];
1189 t2.used = 3;
1190 } while (mp_cmp_mag(&t1, &t2) == MP_GT);
1191
1192 /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
1193 if ((err = mp_mul_d(&y, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y;
1194
1195 if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y;
1196
1197 if ((err = mp_sub(&x, &t1, &x)) != MP_OKAY) goto LBL_Y;
1198
1199 /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
1200 if (x.sign == MP_NEG) {
1201 if ((err = mp_copy(&y, &t1)) != MP_OKAY) goto LBL_Y;
1202 if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y;
1203 if ((err = mp_add(&x, &t1, &x)) != MP_OKAY) goto LBL_Y;
1204
1205 q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & MP_MASK;
1206 }
1207 }
1208
1209 /* now q is the quotient and x is the remainder
1210 * [which we have to normalize]
1211 */
1212
1213 /* get sign before writing to c */
1214 x.sign = (x.used == 0) ? MP_ZPOS : a->sign;
1215
1216 if (c != NULL) {
1217 mp_clamp(&q);
1218 mp_exch(&q, c);
1219 c->sign = neg;
1220 }
1221
1222 if (d != NULL) {
1223 if ((err = mp_div_2d(&x, norm, &x, NULL)) != MP_OKAY) goto LBL_Y;
1224 mp_exch(&x, d);
1225 }
1226
1227 err = MP_OKAY;
1228
1229 LBL_Y:
1230 mp_clear(&y);
1231 LBL_X:
1232 mp_clear(&x);
1233 LBL_T2:
1234 mp_clear(&t2);
1235 LBL_T1:
1236 mp_clear(&t1);
1237 LBL_Q:
1238 mp_clear(&q);
1239 return err;
1240 }
1241
1242 #endif
1243
1244 #endif
1245
1246 /* End: bn_mp_div.c */
1247
1248 /* Start: bn_mp_div_2.c */
1249 #include "tommath_private.h"
1250 #ifdef BN_MP_DIV_2_C
1251 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1252 /* SPDX-License-Identifier: Unlicense */
1253
1254 /* b = a/2 */
mp_div_2(const mp_int * a,mp_int * b)1255 mp_err mp_div_2(const mp_int *a, mp_int *b)
1256 {
1257 int x, oldused;
1258 mp_digit r, rr, *tmpa, *tmpb;
1259 mp_err err;
1260
1261 /* copy */
1262 if (b->alloc < a->used) {
1263 if ((err = mp_grow(b, a->used)) != MP_OKAY) {
1264 return err;
1265 }
1266 }
1267
1268 oldused = b->used;
1269 b->used = a->used;
1270
1271 /* source alias */
1272 tmpa = a->dp + b->used - 1;
1273
1274 /* dest alias */
1275 tmpb = b->dp + b->used - 1;
1276
1277 /* carry */
1278 r = 0;
1279 for (x = b->used - 1; x >= 0; x--) {
1280 /* get the carry for the next iteration */
1281 rr = *tmpa & 1u;
1282
1283 /* shift the current digit, add in carry and store */
1284 *tmpb-- = (*tmpa-- >> 1) | (r << (MP_DIGIT_BIT - 1));
1285
1286 /* forward carry to next iteration */
1287 r = rr;
1288 }
1289
1290 /* zero excess digits */
1291 MP_ZERO_DIGITS(b->dp + b->used, oldused - b->used);
1292
1293 b->sign = a->sign;
1294 mp_clamp(b);
1295 return MP_OKAY;
1296 }
1297 #endif
1298
1299 /* End: bn_mp_div_2.c */
1300
1301 /* Start: bn_mp_div_2d.c */
1302 #include "tommath_private.h"
1303 #ifdef BN_MP_DIV_2D_C
1304 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1305 /* SPDX-License-Identifier: Unlicense */
1306
1307 /* shift right by a certain bit count (store quotient in c, optional remainder in d) */
mp_div_2d(const mp_int * a,int b,mp_int * c,mp_int * d)1308 mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d)
1309 {
1310 mp_digit D, r, rr;
1311 int x;
1312 mp_err err;
1313
1314 /* if the shift count is <= 0 then we do no work */
1315 if (b <= 0) {
1316 err = mp_copy(a, c);
1317 if (d != NULL) {
1318 mp_zero(d);
1319 }
1320 return err;
1321 }
1322
1323 /* copy */
1324 if ((err = mp_copy(a, c)) != MP_OKAY) {
1325 return err;
1326 }
1327 /* 'a' should not be used after here - it might be the same as d */
1328
1329 /* get the remainder */
1330 if (d != NULL) {
1331 if ((err = mp_mod_2d(a, b, d)) != MP_OKAY) {
1332 return err;
1333 }
1334 }
1335
1336 /* shift by as many digits in the bit count */
1337 if (b >= MP_DIGIT_BIT) {
1338 mp_rshd(c, b / MP_DIGIT_BIT);
1339 }
1340
1341 /* shift any bit count < MP_DIGIT_BIT */
1342 D = (mp_digit)(b % MP_DIGIT_BIT);
1343 if (D != 0u) {
1344 mp_digit *tmpc, mask, shift;
1345
1346 /* mask */
1347 mask = ((mp_digit)1 << D) - 1uL;
1348
1349 /* shift for lsb */
1350 shift = (mp_digit)MP_DIGIT_BIT - D;
1351
1352 /* alias */
1353 tmpc = c->dp + (c->used - 1);
1354
1355 /* carry */
1356 r = 0;
1357 for (x = c->used - 1; x >= 0; x--) {
1358 /* get the lower bits of this word in a temp */
1359 rr = *tmpc & mask;
1360
1361 /* shift the current word and mix in the carry bits from the previous word */
1362 *tmpc = (*tmpc >> D) | (r << shift);
1363 --tmpc;
1364
1365 /* set the carry to the carry bits of the current word found above */
1366 r = rr;
1367 }
1368 }
1369 mp_clamp(c);
1370 return MP_OKAY;
1371 }
1372 #endif
1373
1374 /* End: bn_mp_div_2d.c */
1375
1376 /* Start: bn_mp_div_3.c */
1377 #include "tommath_private.h"
1378 #ifdef BN_MP_DIV_3_C
1379 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1380 /* SPDX-License-Identifier: Unlicense */
1381
1382 /* divide by three (based on routine from MPI and the GMP manual) */
mp_div_3(const mp_int * a,mp_int * c,mp_digit * d)1383 mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d)
1384 {
1385 mp_int q;
1386 mp_word w, t;
1387 mp_digit b;
1388 mp_err err;
1389 int ix;
1390
1391 /* b = 2**MP_DIGIT_BIT / 3 */
1392 b = ((mp_word)1 << (mp_word)MP_DIGIT_BIT) / (mp_word)3;
1393
1394 if ((err = mp_init_size(&q, a->used)) != MP_OKAY) {
1395 return err;
1396 }
1397
1398 q.used = a->used;
1399 q.sign = a->sign;
1400 w = 0;
1401 for (ix = a->used - 1; ix >= 0; ix--) {
1402 w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix];
1403
1404 if (w >= 3u) {
1405 /* multiply w by [1/3] */
1406 t = (w * (mp_word)b) >> (mp_word)MP_DIGIT_BIT;
1407
1408 /* now subtract 3 * [w/3] from w, to get the remainder */
1409 w -= t+t+t;
1410
1411 /* fixup the remainder as required since
1412 * the optimization is not exact.
1413 */
1414 while (w >= 3u) {
1415 t += 1u;
1416 w -= 3u;
1417 }
1418 } else {
1419 t = 0;
1420 }
1421 q.dp[ix] = (mp_digit)t;
1422 }
1423
1424 /* [optional] store the remainder */
1425 if (d != NULL) {
1426 *d = (mp_digit)w;
1427 }
1428
1429 /* [optional] store the quotient */
1430 if (c != NULL) {
1431 mp_clamp(&q);
1432 mp_exch(&q, c);
1433 }
1434 mp_clear(&q);
1435
1436 return err;
1437 }
1438
1439 #endif
1440
1441 /* End: bn_mp_div_3.c */
1442
1443 /* Start: bn_mp_div_d.c */
1444 #include "tommath_private.h"
1445 #ifdef BN_MP_DIV_D_C
1446 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1447 /* SPDX-License-Identifier: Unlicense */
1448
1449 /* single digit division (based on routine from MPI) */
mp_div_d(const mp_int * a,mp_digit b,mp_int * c,mp_digit * d)1450 mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
1451 {
1452 mp_int q;
1453 mp_word w;
1454 mp_digit t;
1455 mp_err err;
1456 int ix;
1457
1458 /* cannot divide by zero */
1459 if (b == 0u) {
1460 return MP_VAL;
1461 }
1462
1463 /* quick outs */
1464 if ((b == 1u) || MP_IS_ZERO(a)) {
1465 if (d != NULL) {
1466 *d = 0;
1467 }
1468 if (c != NULL) {
1469 return mp_copy(a, c);
1470 }
1471 return MP_OKAY;
1472 }
1473
1474 /* power of two ? */
1475 if ((b & (b - 1u)) == 0u) {
1476 ix = 1;
1477 while ((ix < MP_DIGIT_BIT) && (b != (((mp_digit)1)<<ix))) {
1478 ix++;
1479 }
1480 if (d != NULL) {
1481 *d = a->dp[0] & (((mp_digit)1<<(mp_digit)ix) - 1uL);
1482 }
1483 if (c != NULL) {
1484 return mp_div_2d(a, ix, c, NULL);
1485 }
1486 return MP_OKAY;
1487 }
1488
1489 /* three? */
1490 if (MP_HAS(MP_DIV_3) && (b == 3u)) {
1491 return mp_div_3(a, c, d);
1492 }
1493
1494 /* no easy answer [c'est la vie]. Just division */
1495 if ((err = mp_init_size(&q, a->used)) != MP_OKAY) {
1496 return err;
1497 }
1498
1499 q.used = a->used;
1500 q.sign = a->sign;
1501 w = 0;
1502 for (ix = a->used - 1; ix >= 0; ix--) {
1503 w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix];
1504
1505 if (w >= b) {
1506 t = (mp_digit)(w / b);
1507 w -= (mp_word)t * (mp_word)b;
1508 } else {
1509 t = 0;
1510 }
1511 q.dp[ix] = t;
1512 }
1513
1514 if (d != NULL) {
1515 *d = (mp_digit)w;
1516 }
1517
1518 if (c != NULL) {
1519 mp_clamp(&q);
1520 mp_exch(&q, c);
1521 }
1522 mp_clear(&q);
1523
1524 return err;
1525 }
1526
1527 #endif
1528
1529 /* End: bn_mp_div_d.c */
1530
1531 /* Start: bn_mp_dr_is_modulus.c */
1532 #include "tommath_private.h"
1533 #ifdef BN_MP_DR_IS_MODULUS_C
1534 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1535 /* SPDX-License-Identifier: Unlicense */
1536
1537 /* determines if a number is a valid DR modulus */
mp_dr_is_modulus(const mp_int * a)1538 mp_bool mp_dr_is_modulus(const mp_int *a)
1539 {
1540 int ix;
1541
1542 /* must be at least two digits */
1543 if (a->used < 2) {
1544 return MP_NO;
1545 }
1546
1547 /* must be of the form b**k - a [a <= b] so all
1548 * but the first digit must be equal to -1 (mod b).
1549 */
1550 for (ix = 1; ix < a->used; ix++) {
1551 if (a->dp[ix] != MP_MASK) {
1552 return MP_NO;
1553 }
1554 }
1555 return MP_YES;
1556 }
1557
1558 #endif
1559
1560 /* End: bn_mp_dr_is_modulus.c */
1561
1562 /* Start: bn_mp_dr_reduce.c */
1563 #include "tommath_private.h"
1564 #ifdef BN_MP_DR_REDUCE_C
1565 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1566 /* SPDX-License-Identifier: Unlicense */
1567
1568 /* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
1569 *
1570 * Based on algorithm from the paper
1571 *
1572 * "Generating Efficient Primes for Discrete Log Cryptosystems"
1573 * Chae Hoon Lim, Pil Joong Lee,
1574 * POSTECH Information Research Laboratories
1575 *
1576 * The modulus must be of a special format [see manual]
1577 *
1578 * Has been modified to use algorithm 7.10 from the LTM book instead
1579 *
1580 * Input x must be in the range 0 <= x <= (n-1)**2
1581 */
mp_dr_reduce(mp_int * x,const mp_int * n,mp_digit k)1582 mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k)
1583 {
1584 mp_err err;
1585 int i, m;
1586 mp_word r;
1587 mp_digit mu, *tmpx1, *tmpx2;
1588
1589 /* m = digits in modulus */
1590 m = n->used;
1591
1592 /* ensure that "x" has at least 2m digits */
1593 if (x->alloc < (m + m)) {
1594 if ((err = mp_grow(x, m + m)) != MP_OKAY) {
1595 return err;
1596 }
1597 }
1598
1599 /* top of loop, this is where the code resumes if
1600 * another reduction pass is required.
1601 */
1602 top:
1603 /* aliases for digits */
1604 /* alias for lower half of x */
1605 tmpx1 = x->dp;
1606
1607 /* alias for upper half of x, or x/B**m */
1608 tmpx2 = x->dp + m;
1609
1610 /* set carry to zero */
1611 mu = 0;
1612
1613 /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
1614 for (i = 0; i < m; i++) {
1615 r = ((mp_word)*tmpx2++ * (mp_word)k) + *tmpx1 + mu;
1616 *tmpx1++ = (mp_digit)(r & MP_MASK);
1617 mu = (mp_digit)(r >> ((mp_word)MP_DIGIT_BIT));
1618 }
1619
1620 /* set final carry */
1621 *tmpx1++ = mu;
1622
1623 /* zero words above m */
1624 MP_ZERO_DIGITS(tmpx1, (x->used - m) - 1);
1625
1626 /* clamp, sub and return */
1627 mp_clamp(x);
1628
1629 /* if x >= n then subtract and reduce again
1630 * Each successive "recursion" makes the input smaller and smaller.
1631 */
1632 if (mp_cmp_mag(x, n) != MP_LT) {
1633 if ((err = s_mp_sub(x, n, x)) != MP_OKAY) {
1634 return err;
1635 }
1636 goto top;
1637 }
1638 return MP_OKAY;
1639 }
1640 #endif
1641
1642 /* End: bn_mp_dr_reduce.c */
1643
1644 /* Start: bn_mp_dr_setup.c */
1645 #include "tommath_private.h"
1646 #ifdef BN_MP_DR_SETUP_C
1647 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1648 /* SPDX-License-Identifier: Unlicense */
1649
1650 /* determines the setup value */
mp_dr_setup(const mp_int * a,mp_digit * d)1651 void mp_dr_setup(const mp_int *a, mp_digit *d)
1652 {
1653 /* the casts are required if MP_DIGIT_BIT is one less than
1654 * the number of bits in a mp_digit [e.g. MP_DIGIT_BIT==31]
1655 */
1656 *d = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - (mp_word)a->dp[0]);
1657 }
1658
1659 #endif
1660
1661 /* End: bn_mp_dr_setup.c */
1662
1663 /* Start: bn_mp_error_to_string.c */
1664 #include "tommath_private.h"
1665 #ifdef BN_MP_ERROR_TO_STRING_C
1666 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1667 /* SPDX-License-Identifier: Unlicense */
1668
1669 /* return a char * string for a given code */
mp_error_to_string(mp_err code)1670 const char *mp_error_to_string(mp_err code)
1671 {
1672 switch (code) {
1673 case MP_OKAY:
1674 return "Successful";
1675 case MP_ERR:
1676 return "Unknown error";
1677 case MP_MEM:
1678 return "Out of heap";
1679 case MP_VAL:
1680 return "Value out of range";
1681 case MP_ITER:
1682 return "Max. iterations reached";
1683 case MP_BUF:
1684 return "Buffer overflow";
1685 default:
1686 return "Invalid error code";
1687 }
1688 }
1689
1690 #endif
1691
1692 /* End: bn_mp_error_to_string.c */
1693
1694 /* Start: bn_mp_exch.c */
1695 #include "tommath_private.h"
1696 #ifdef BN_MP_EXCH_C
1697 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1698 /* SPDX-License-Identifier: Unlicense */
1699
1700 /* swap the elements of two integers, for cases where you can't simply swap the
1701 * mp_int pointers around
1702 */
mp_exch(mp_int * a,mp_int * b)1703 void mp_exch(mp_int *a, mp_int *b)
1704 {
1705 mp_int t;
1706
1707 t = *a;
1708 *a = *b;
1709 *b = t;
1710 }
1711 #endif
1712
1713 /* End: bn_mp_exch.c */
1714
1715 /* Start: bn_mp_expt_u32.c */
1716 #include "tommath_private.h"
1717 #ifdef BN_MP_EXPT_U32_C
1718 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1719 /* SPDX-License-Identifier: Unlicense */
1720
1721 /* calculate c = a**b using a square-multiply algorithm */
mp_expt_u32(const mp_int * a,uint32_t b,mp_int * c)1722 mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c)
1723 {
1724 mp_err err;
1725
1726 mp_int g;
1727
1728 if ((err = mp_init_copy(&g, a)) != MP_OKAY) {
1729 return err;
1730 }
1731
1732 /* set initial result */
1733 mp_set(c, 1uL);
1734
1735 while (b > 0u) {
1736 /* if the bit is set multiply */
1737 if ((b & 1u) != 0u) {
1738 if ((err = mp_mul(c, &g, c)) != MP_OKAY) {
1739 goto LBL_ERR;
1740 }
1741 }
1742
1743 /* square */
1744 if (b > 1u) {
1745 if ((err = mp_sqr(&g, &g)) != MP_OKAY) {
1746 goto LBL_ERR;
1747 }
1748 }
1749
1750 /* shift to next bit */
1751 b >>= 1;
1752 }
1753
1754 err = MP_OKAY;
1755
1756 LBL_ERR:
1757 mp_clear(&g);
1758 return err;
1759 }
1760
1761 #endif
1762
1763 /* End: bn_mp_expt_u32.c */
1764
1765 /* Start: bn_mp_exptmod.c */
1766 #include "tommath_private.h"
1767 #ifdef BN_MP_EXPTMOD_C
1768 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1769 /* SPDX-License-Identifier: Unlicense */
1770
1771 /* this is a shell function that calls either the normal or Montgomery
1772 * exptmod functions. Originally the call to the montgomery code was
1773 * embedded in the normal function but that wasted alot of stack space
1774 * for nothing (since 99% of the time the Montgomery code would be called)
1775 */
mp_exptmod(const mp_int * G,const mp_int * X,const mp_int * P,mp_int * Y)1776 mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y)
1777 {
1778 int dr;
1779
1780 /* modulus P must be positive */
1781 if (P->sign == MP_NEG) {
1782 return MP_VAL;
1783 }
1784
1785 /* if exponent X is negative we have to recurse */
1786 if (X->sign == MP_NEG) {
1787 mp_int tmpG, tmpX;
1788 mp_err err;
1789
1790 if (!MP_HAS(MP_INVMOD)) {
1791 return MP_VAL;
1792 }
1793
1794 if ((err = mp_init_multi(&tmpG, &tmpX, NULL)) != MP_OKAY) {
1795 return err;
1796 }
1797
1798 /* first compute 1/G mod P */
1799 if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
1800 goto LBL_ERR;
1801 }
1802
1803 /* now get |X| */
1804 if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
1805 goto LBL_ERR;
1806 }
1807
1808 /* and now compute (1/G)**|X| instead of G**X [X < 0] */
1809 err = mp_exptmod(&tmpG, &tmpX, P, Y);
1810 LBL_ERR:
1811 mp_clear_multi(&tmpG, &tmpX, NULL);
1812 return err;
1813 }
1814
1815 /* modified diminished radix reduction */
1816 if (MP_HAS(MP_REDUCE_IS_2K_L) && MP_HAS(MP_REDUCE_2K_L) && MP_HAS(S_MP_EXPTMOD) &&
1817 (mp_reduce_is_2k_l(P) == MP_YES)) {
1818 return s_mp_exptmod(G, X, P, Y, 1);
1819 }
1820
1821 /* is it a DR modulus? default to no */
1822 dr = (MP_HAS(MP_DR_IS_MODULUS) && (mp_dr_is_modulus(P) == MP_YES)) ? 1 : 0;
1823
1824 /* if not, is it a unrestricted DR modulus? */
1825 if (MP_HAS(MP_REDUCE_IS_2K) && (dr == 0)) {
1826 dr = (mp_reduce_is_2k(P) == MP_YES) ? 2 : 0;
1827 }
1828
1829 /* if the modulus is odd or dr != 0 use the montgomery method */
1830 if (MP_HAS(S_MP_EXPTMOD_FAST) && (MP_IS_ODD(P) || (dr != 0))) {
1831 return s_mp_exptmod_fast(G, X, P, Y, dr);
1832 } else if (MP_HAS(S_MP_EXPTMOD)) {
1833 /* otherwise use the generic Barrett reduction technique */
1834 return s_mp_exptmod(G, X, P, Y, 0);
1835 } else {
1836 /* no exptmod for evens */
1837 return MP_VAL;
1838 }
1839 }
1840
1841 #endif
1842
1843 /* End: bn_mp_exptmod.c */
1844
1845 /* Start: bn_mp_exteuclid.c */
1846 #include "tommath_private.h"
1847 #ifdef BN_MP_EXTEUCLID_C
1848 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1849 /* SPDX-License-Identifier: Unlicense */
1850
1851 /* Extended euclidean algorithm of (a, b) produces
1852 a*u1 + b*u2 = u3
1853 */
mp_exteuclid(const mp_int * a,const mp_int * b,mp_int * U1,mp_int * U2,mp_int * U3)1854 mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
1855 {
1856 mp_int u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp;
1857 mp_err err;
1858
1859 if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
1860 return err;
1861 }
1862
1863 /* initialize, (u1,u2,u3) = (1,0,a) */
1864 mp_set(&u1, 1uL);
1865 if ((err = mp_copy(a, &u3)) != MP_OKAY) goto LBL_ERR;
1866
1867 /* initialize, (v1,v2,v3) = (0,1,b) */
1868 mp_set(&v2, 1uL);
1869 if ((err = mp_copy(b, &v3)) != MP_OKAY) goto LBL_ERR;
1870
1871 /* loop while v3 != 0 */
1872 while (!MP_IS_ZERO(&v3)) {
1873 /* q = u3/v3 */
1874 if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) goto LBL_ERR;
1875
1876 /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
1877 if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) goto LBL_ERR;
1878 if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) goto LBL_ERR;
1879 if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) goto LBL_ERR;
1880 if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) goto LBL_ERR;
1881 if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) goto LBL_ERR;
1882 if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) goto LBL_ERR;
1883
1884 /* (u1,u2,u3) = (v1,v2,v3) */
1885 if ((err = mp_copy(&v1, &u1)) != MP_OKAY) goto LBL_ERR;
1886 if ((err = mp_copy(&v2, &u2)) != MP_OKAY) goto LBL_ERR;
1887 if ((err = mp_copy(&v3, &u3)) != MP_OKAY) goto LBL_ERR;
1888
1889 /* (v1,v2,v3) = (t1,t2,t3) */
1890 if ((err = mp_copy(&t1, &v1)) != MP_OKAY) goto LBL_ERR;
1891 if ((err = mp_copy(&t2, &v2)) != MP_OKAY) goto LBL_ERR;
1892 if ((err = mp_copy(&t3, &v3)) != MP_OKAY) goto LBL_ERR;
1893 }
1894
1895 /* make sure U3 >= 0 */
1896 if (u3.sign == MP_NEG) {
1897 if ((err = mp_neg(&u1, &u1)) != MP_OKAY) goto LBL_ERR;
1898 if ((err = mp_neg(&u2, &u2)) != MP_OKAY) goto LBL_ERR;
1899 if ((err = mp_neg(&u3, &u3)) != MP_OKAY) goto LBL_ERR;
1900 }
1901
1902 /* copy result out */
1903 if (U1 != NULL) {
1904 mp_exch(U1, &u1);
1905 }
1906 if (U2 != NULL) {
1907 mp_exch(U2, &u2);
1908 }
1909 if (U3 != NULL) {
1910 mp_exch(U3, &u3);
1911 }
1912
1913 err = MP_OKAY;
1914 LBL_ERR:
1915 mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
1916 return err;
1917 }
1918 #endif
1919
1920 /* End: bn_mp_exteuclid.c */
1921
1922 /* Start: bn_mp_fread.c */
1923 #include "tommath_private.h"
1924 #ifdef BN_MP_FREAD_C
1925 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1926 /* SPDX-License-Identifier: Unlicense */
1927
1928 #ifndef MP_NO_FILE
1929 /* read a bigint from a file stream in ASCII */
mp_fread(mp_int * a,int radix,FILE * stream)1930 mp_err mp_fread(mp_int *a, int radix, FILE *stream)
1931 {
1932 mp_err err;
1933 mp_sign neg;
1934
1935 /* if first digit is - then set negative */
1936 int ch = fgetc(stream);
1937 if (ch == (int)'-') {
1938 neg = MP_NEG;
1939 ch = fgetc(stream);
1940 } else {
1941 neg = MP_ZPOS;
1942 }
1943
1944 /* no digits, return error */
1945 if (ch == EOF) {
1946 return MP_ERR;
1947 }
1948
1949 /* clear a */
1950 mp_zero(a);
1951
1952 do {
1953 int y;
1954 unsigned pos = (unsigned)(ch - (int)'(');
1955 if (mp_s_rmap_reverse_sz < pos) {
1956 break;
1957 }
1958
1959 y = (int)mp_s_rmap_reverse[pos];
1960
1961 if ((y == 0xff) || (y >= radix)) {
1962 break;
1963 }
1964
1965 /* shift up and add */
1966 if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) {
1967 return err;
1968 }
1969 if ((err = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) {
1970 return err;
1971 }
1972 } while ((ch = fgetc(stream)) != EOF);
1973
1974 if (a->used != 0) {
1975 a->sign = neg;
1976 }
1977
1978 return MP_OKAY;
1979 }
1980 #endif
1981
1982 #endif
1983
1984 /* End: bn_mp_fread.c */
1985
1986 /* Start: bn_mp_from_sbin.c */
1987 #include "tommath_private.h"
1988 #ifdef BN_MP_FROM_SBIN_C
1989 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
1990 /* SPDX-License-Identifier: Unlicense */
1991
1992 /* read signed bin, big endian, first byte is 0==positive or 1==negative */
mp_from_sbin(mp_int * a,const unsigned char * buf,size_t size)1993 mp_err mp_from_sbin(mp_int *a, const unsigned char *buf, size_t size)
1994 {
1995 mp_err err;
1996
1997 /* read magnitude */
1998 if ((err = mp_from_ubin(a, buf + 1, size - 1u)) != MP_OKAY) {
1999 return err;
2000 }
2001
2002 /* first byte is 0 for positive, non-zero for negative */
2003 if (buf[0] == (unsigned char)0) {
2004 a->sign = MP_ZPOS;
2005 } else {
2006 a->sign = MP_NEG;
2007 }
2008
2009 return MP_OKAY;
2010 }
2011 #endif
2012
2013 /* End: bn_mp_from_sbin.c */
2014
2015 /* Start: bn_mp_from_ubin.c */
2016 #include "tommath_private.h"
2017 #ifdef BN_MP_FROM_UBIN_C
2018 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2019 /* SPDX-License-Identifier: Unlicense */
2020
2021 /* reads a unsigned char array, assumes the msb is stored first [big endian] */
mp_from_ubin(mp_int * a,const unsigned char * buf,size_t size)2022 mp_err mp_from_ubin(mp_int *a, const unsigned char *buf, size_t size)
2023 {
2024 mp_err err;
2025
2026 /* make sure there are at least two digits */
2027 if (a->alloc < 2) {
2028 if ((err = mp_grow(a, 2)) != MP_OKAY) {
2029 return err;
2030 }
2031 }
2032
2033 /* zero the int */
2034 mp_zero(a);
2035
2036 /* read the bytes in */
2037 while (size-- > 0u) {
2038 if ((err = mp_mul_2d(a, 8, a)) != MP_OKAY) {
2039 return err;
2040 }
2041
2042 #ifndef MP_8BIT
2043 a->dp[0] |= *buf++;
2044 a->used += 1;
2045 #else
2046 a->dp[0] = (*buf & MP_MASK);
2047 a->dp[1] |= ((*buf++ >> 7) & 1u);
2048 a->used += 2;
2049 #endif
2050 }
2051 mp_clamp(a);
2052 return MP_OKAY;
2053 }
2054 #endif
2055
2056 /* End: bn_mp_from_ubin.c */
2057
2058 /* Start: bn_mp_fwrite.c */
2059 #include "tommath_private.h"
2060 #ifdef BN_MP_FWRITE_C
2061 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2062 /* SPDX-License-Identifier: Unlicense */
2063
2064 #ifndef MP_NO_FILE
mp_fwrite(const mp_int * a,int radix,FILE * stream)2065 mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream)
2066 {
2067 char *buf;
2068 mp_err err;
2069 int len;
2070 size_t written;
2071
2072 /* TODO: this function is not in this PR */
2073 if (MP_HAS(MP_RADIX_SIZE_OVERESTIMATE)) {
2074 /* if ((err = mp_radix_size_overestimate(&t, base, &len)) != MP_OKAY) goto LBL_ERR; */
2075 } else {
2076 if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
2077 return err;
2078 }
2079 }
2080
2081 buf = (char *) MP_MALLOC((size_t)len);
2082 if (buf == NULL) {
2083 return MP_MEM;
2084 }
2085
2086 if ((err = mp_to_radix(a, buf, (size_t)len, &written, radix)) != MP_OKAY) {
2087 goto LBL_ERR;
2088 }
2089
2090 if (fwrite(buf, written, 1uL, stream) != 1uL) {
2091 err = MP_ERR;
2092 goto LBL_ERR;
2093 }
2094 err = MP_OKAY;
2095
2096
2097 LBL_ERR:
2098 MP_FREE_BUFFER(buf, (size_t)len);
2099 return err;
2100 }
2101 #endif
2102
2103 #endif
2104
2105 /* End: bn_mp_fwrite.c */
2106
2107 /* Start: bn_mp_gcd.c */
2108 #include "tommath_private.h"
2109 #ifdef BN_MP_GCD_C
2110 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2111 /* SPDX-License-Identifier: Unlicense */
2112
2113 /* Greatest Common Divisor using the binary method */
mp_gcd(const mp_int * a,const mp_int * b,mp_int * c)2114 mp_err mp_gcd(const mp_int *a, const mp_int *b, mp_int *c)
2115 {
2116 mp_int u, v;
2117 int k, u_lsb, v_lsb;
2118 mp_err err;
2119
2120 /* either zero than gcd is the largest */
2121 if (MP_IS_ZERO(a)) {
2122 return mp_abs(b, c);
2123 }
2124 if (MP_IS_ZERO(b)) {
2125 return mp_abs(a, c);
2126 }
2127
2128 /* get copies of a and b we can modify */
2129 if ((err = mp_init_copy(&u, a)) != MP_OKAY) {
2130 return err;
2131 }
2132
2133 if ((err = mp_init_copy(&v, b)) != MP_OKAY) {
2134 goto LBL_U;
2135 }
2136
2137 /* must be positive for the remainder of the algorithm */
2138 u.sign = v.sign = MP_ZPOS;
2139
2140 /* B1. Find the common power of two for u and v */
2141 u_lsb = mp_cnt_lsb(&u);
2142 v_lsb = mp_cnt_lsb(&v);
2143 k = MP_MIN(u_lsb, v_lsb);
2144
2145 if (k > 0) {
2146 /* divide the power of two out */
2147 if ((err = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
2148 goto LBL_V;
2149 }
2150
2151 if ((err = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
2152 goto LBL_V;
2153 }
2154 }
2155
2156 /* divide any remaining factors of two out */
2157 if (u_lsb != k) {
2158 if ((err = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
2159 goto LBL_V;
2160 }
2161 }
2162
2163 if (v_lsb != k) {
2164 if ((err = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
2165 goto LBL_V;
2166 }
2167 }
2168
2169 while (!MP_IS_ZERO(&v)) {
2170 /* make sure v is the largest */
2171 if (mp_cmp_mag(&u, &v) == MP_GT) {
2172 /* swap u and v to make sure v is >= u */
2173 mp_exch(&u, &v);
2174 }
2175
2176 /* subtract smallest from largest */
2177 if ((err = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
2178 goto LBL_V;
2179 }
2180
2181 /* Divide out all factors of two */
2182 if ((err = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
2183 goto LBL_V;
2184 }
2185 }
2186
2187 /* multiply by 2**k which we divided out at the beginning */
2188 if ((err = mp_mul_2d(&u, k, c)) != MP_OKAY) {
2189 goto LBL_V;
2190 }
2191 c->sign = MP_ZPOS;
2192 err = MP_OKAY;
2193 LBL_V:
2194 mp_clear(&u);
2195 LBL_U:
2196 mp_clear(&v);
2197 return err;
2198 }
2199 #endif
2200
2201 /* End: bn_mp_gcd.c */
2202
2203 /* Start: bn_mp_get_double.c */
2204 #include "tommath_private.h"
2205 #ifdef BN_MP_GET_DOUBLE_C
2206 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2207 /* SPDX-License-Identifier: Unlicense */
2208
mp_get_double(const mp_int * a)2209 double mp_get_double(const mp_int *a)
2210 {
2211 int i;
2212 double d = 0.0, fac = 1.0;
2213 for (i = 0; i < MP_DIGIT_BIT; ++i) {
2214 fac *= 2.0;
2215 }
2216 for (i = a->used; i --> 0;) {
2217 d = (d * fac) + (double)a->dp[i];
2218 }
2219 return (a->sign == MP_NEG) ? -d : d;
2220 }
2221 #endif
2222
2223 /* End: bn_mp_get_double.c */
2224
2225 /* Start: bn_mp_get_i32.c */
2226 #include "tommath_private.h"
2227 #ifdef BN_MP_GET_I32_C
2228 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2229 /* SPDX-License-Identifier: Unlicense */
2230
MP_GET_SIGNED(mp_get_i32,mp_get_mag_u32,int32_t,uint32_t)2231 MP_GET_SIGNED(mp_get_i32, mp_get_mag_u32, int32_t, uint32_t)
2232 #endif
2233
2234 /* End: bn_mp_get_i32.c */
2235
2236 /* Start: bn_mp_get_i64.c */
2237 #include "tommath_private.h"
2238 #ifdef BN_MP_GET_I64_C
2239 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2240 /* SPDX-License-Identifier: Unlicense */
2241
2242 MP_GET_SIGNED(mp_get_i64, mp_get_mag_u64, int64_t, uint64_t)
2243 #endif
2244
2245 /* End: bn_mp_get_i64.c */
2246
2247 /* Start: bn_mp_get_l.c */
2248 #include "tommath_private.h"
2249 #ifdef BN_MP_GET_L_C
2250 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2251 /* SPDX-License-Identifier: Unlicense */
2252
2253 MP_GET_SIGNED(mp_get_l, mp_get_mag_ul, long, unsigned long)
2254 #endif
2255
2256 /* End: bn_mp_get_l.c */
2257
2258 /* Start: bn_mp_get_ll.c */
2259 #include "tommath_private.h"
2260 #ifdef BN_MP_GET_LL_C
2261 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2262 /* SPDX-License-Identifier: Unlicense */
2263
2264 MP_GET_SIGNED(mp_get_ll, mp_get_mag_ull, long long, unsigned long long)
2265 #endif
2266
2267 /* End: bn_mp_get_ll.c */
2268
2269 /* Start: bn_mp_get_mag_u32.c */
2270 #include "tommath_private.h"
2271 #ifdef BN_MP_GET_MAG_U32_C
2272 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2273 /* SPDX-License-Identifier: Unlicense */
2274
2275 MP_GET_MAG(mp_get_mag_u32, uint32_t)
2276 #endif
2277
2278 /* End: bn_mp_get_mag_u32.c */
2279
2280 /* Start: bn_mp_get_mag_u64.c */
2281 #include "tommath_private.h"
2282 #ifdef BN_MP_GET_MAG_U64_C
2283 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2284 /* SPDX-License-Identifier: Unlicense */
2285
2286 MP_GET_MAG(mp_get_mag_u64, uint64_t)
2287 #endif
2288
2289 /* End: bn_mp_get_mag_u64.c */
2290
2291 /* Start: bn_mp_get_mag_ul.c */
2292 #include "tommath_private.h"
2293 #ifdef BN_MP_GET_MAG_UL_C
2294 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2295 /* SPDX-License-Identifier: Unlicense */
2296
2297 MP_GET_MAG(mp_get_mag_ul, unsigned long)
2298 #endif
2299
2300 /* End: bn_mp_get_mag_ul.c */
2301
2302 /* Start: bn_mp_get_mag_ull.c */
2303 #include "tommath_private.h"
2304 #ifdef BN_MP_GET_MAG_ULL_C
2305 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2306 /* SPDX-License-Identifier: Unlicense */
2307
2308 MP_GET_MAG(mp_get_mag_ull, unsigned long long)
2309 #endif
2310
2311 /* End: bn_mp_get_mag_ull.c */
2312
2313 /* Start: bn_mp_grow.c */
2314 #include "tommath_private.h"
2315 #ifdef BN_MP_GROW_C
2316 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2317 /* SPDX-License-Identifier: Unlicense */
2318
2319 /* grow as required */
2320 mp_err mp_grow(mp_int *a, int size)
2321 {
2322 int i;
2323 mp_digit *tmp;
2324
2325 /* if the alloc size is smaller alloc more ram */
2326 if (a->alloc < size) {
2327 /* reallocate the array a->dp
2328 *
2329 * We store the return in a temporary variable
2330 * in case the operation failed we don't want
2331 * to overwrite the dp member of a.
2332 */
2333 tmp = (mp_digit *) MP_REALLOC(a->dp,
2334 (size_t)a->alloc * sizeof(mp_digit),
2335 (size_t)size * sizeof(mp_digit));
2336 if (tmp == NULL) {
2337 /* reallocation failed but "a" is still valid [can be freed] */
2338 return MP_MEM;
2339 }
2340
2341 /* reallocation succeeded so set a->dp */
2342 a->dp = tmp;
2343
2344 /* zero excess digits */
2345 i = a->alloc;
2346 a->alloc = size;
2347 MP_ZERO_DIGITS(a->dp + i, a->alloc - i);
2348 }
2349 return MP_OKAY;
2350 }
2351 #endif
2352
2353 /* End: bn_mp_grow.c */
2354
2355 /* Start: bn_mp_incr.c */
2356 #include "tommath_private.h"
2357 #ifdef BN_MP_INCR_C
2358 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2359 /* SPDX-License-Identifier: Unlicense */
2360
2361 /* Increment "a" by one like "a++". Changes input! */
mp_incr(mp_int * a)2362 mp_err mp_incr(mp_int *a)
2363 {
2364 if (MP_IS_ZERO(a)) {
2365 mp_set(a,1uL);
2366 return MP_OKAY;
2367 } else if (a->sign == MP_NEG) {
2368 mp_err err;
2369 a->sign = MP_ZPOS;
2370 if ((err = mp_decr(a)) != MP_OKAY) {
2371 return err;
2372 }
2373 /* There is no -0 in LTM */
2374 if (!MP_IS_ZERO(a)) {
2375 a->sign = MP_NEG;
2376 }
2377 return MP_OKAY;
2378 } else if (a->dp[0] < MP_DIGIT_MAX) {
2379 a->dp[0]++;
2380 return MP_OKAY;
2381 } else {
2382 return mp_add_d(a, 1uL,a);
2383 }
2384 }
2385 #endif
2386
2387 /* End: bn_mp_incr.c */
2388
2389 /* Start: bn_mp_init.c */
2390 #include "tommath_private.h"
2391 #ifdef BN_MP_INIT_C
2392 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2393 /* SPDX-License-Identifier: Unlicense */
2394
2395 /* init a new mp_int */
mp_init(mp_int * a)2396 mp_err mp_init(mp_int *a)
2397 {
2398 /* allocate memory required and clear it */
2399 a->dp = (mp_digit *) MP_CALLOC((size_t)MP_PREC, sizeof(mp_digit));
2400 if (a->dp == NULL) {
2401 return MP_MEM;
2402 }
2403
2404 /* set the used to zero, allocated digits to the default precision
2405 * and sign to positive */
2406 a->used = 0;
2407 a->alloc = MP_PREC;
2408 a->sign = MP_ZPOS;
2409
2410 return MP_OKAY;
2411 }
2412 #endif
2413
2414 /* End: bn_mp_init.c */
2415
2416 /* Start: bn_mp_init_copy.c */
2417 #include "tommath_private.h"
2418 #ifdef BN_MP_INIT_COPY_C
2419 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2420 /* SPDX-License-Identifier: Unlicense */
2421
2422 /* creates "a" then copies b into it */
mp_init_copy(mp_int * a,const mp_int * b)2423 mp_err mp_init_copy(mp_int *a, const mp_int *b)
2424 {
2425 mp_err err;
2426
2427 if ((err = mp_init_size(a, b->used)) != MP_OKAY) {
2428 return err;
2429 }
2430
2431 if ((err = mp_copy(b, a)) != MP_OKAY) {
2432 mp_clear(a);
2433 }
2434
2435 return err;
2436 }
2437 #endif
2438
2439 /* End: bn_mp_init_copy.c */
2440
2441 /* Start: bn_mp_init_i32.c */
2442 #include "tommath_private.h"
2443 #ifdef BN_MP_INIT_I32_C
2444 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2445 /* SPDX-License-Identifier: Unlicense */
2446
MP_INIT_INT(mp_init_i32,mp_set_i32,int32_t)2447 MP_INIT_INT(mp_init_i32, mp_set_i32, int32_t)
2448 #endif
2449
2450 /* End: bn_mp_init_i32.c */
2451
2452 /* Start: bn_mp_init_i64.c */
2453 #include "tommath_private.h"
2454 #ifdef BN_MP_INIT_I64_C
2455 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2456 /* SPDX-License-Identifier: Unlicense */
2457
2458 MP_INIT_INT(mp_init_i64, mp_set_i64, int64_t)
2459 #endif
2460
2461 /* End: bn_mp_init_i64.c */
2462
2463 /* Start: bn_mp_init_l.c */
2464 #include "tommath_private.h"
2465 #ifdef BN_MP_INIT_L_C
2466 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2467 /* SPDX-License-Identifier: Unlicense */
2468
2469 MP_INIT_INT(mp_init_l, mp_set_l, long)
2470 #endif
2471
2472 /* End: bn_mp_init_l.c */
2473
2474 /* Start: bn_mp_init_ll.c */
2475 #include "tommath_private.h"
2476 #ifdef BN_MP_INIT_LL_C
2477 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2478 /* SPDX-License-Identifier: Unlicense */
2479
2480 MP_INIT_INT(mp_init_ll, mp_set_ll, long long)
2481 #endif
2482
2483 /* End: bn_mp_init_ll.c */
2484
2485 /* Start: bn_mp_init_multi.c */
2486 #include "tommath_private.h"
2487 #ifdef BN_MP_INIT_MULTI_C
2488 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2489 /* SPDX-License-Identifier: Unlicense */
2490
2491 #include <stdarg.h>
2492
2493 mp_err mp_init_multi(mp_int *mp, ...)
2494 {
2495 mp_err err = MP_OKAY; /* Assume ok until proven otherwise */
2496 int n = 0; /* Number of ok inits */
2497 mp_int *cur_arg = mp;
2498 va_list args;
2499
2500 va_start(args, mp); /* init args to next argument from caller */
2501 while (cur_arg != NULL) {
2502 if (mp_init(cur_arg) != MP_OKAY) {
2503 /* Oops - error! Back-track and mp_clear what we already
2504 succeeded in init-ing, then return error.
2505 */
2506 va_list clean_args;
2507
2508 /* now start cleaning up */
2509 cur_arg = mp;
2510 va_start(clean_args, mp);
2511 while (n-- != 0) {
2512 mp_clear(cur_arg);
2513 cur_arg = va_arg(clean_args, mp_int *);
2514 }
2515 va_end(clean_args);
2516 err = MP_MEM;
2517 break;
2518 }
2519 n++;
2520 cur_arg = va_arg(args, mp_int *);
2521 }
2522 va_end(args);
2523 return err; /* Assumed ok, if error flagged above. */
2524 }
2525
2526 #endif
2527
2528 /* End: bn_mp_init_multi.c */
2529
2530 /* Start: bn_mp_init_set.c */
2531 #include "tommath_private.h"
2532 #ifdef BN_MP_INIT_SET_C
2533 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2534 /* SPDX-License-Identifier: Unlicense */
2535
2536 /* initialize and set a digit */
mp_init_set(mp_int * a,mp_digit b)2537 mp_err mp_init_set(mp_int *a, mp_digit b)
2538 {
2539 mp_err err;
2540 if ((err = mp_init(a)) != MP_OKAY) {
2541 return err;
2542 }
2543 mp_set(a, b);
2544 return err;
2545 }
2546 #endif
2547
2548 /* End: bn_mp_init_set.c */
2549
2550 /* Start: bn_mp_init_size.c */
2551 #include "tommath_private.h"
2552 #ifdef BN_MP_INIT_SIZE_C
2553 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2554 /* SPDX-License-Identifier: Unlicense */
2555
2556 /* init an mp_init for a given size */
mp_init_size(mp_int * a,int size)2557 mp_err mp_init_size(mp_int *a, int size)
2558 {
2559 size = MP_MAX(MP_MIN_PREC, size);
2560
2561 /* alloc mem */
2562 a->dp = (mp_digit *) MP_CALLOC((size_t)size, sizeof(mp_digit));
2563 if (a->dp == NULL) {
2564 return MP_MEM;
2565 }
2566
2567 /* set the members */
2568 a->used = 0;
2569 a->alloc = size;
2570 a->sign = MP_ZPOS;
2571
2572 return MP_OKAY;
2573 }
2574 #endif
2575
2576 /* End: bn_mp_init_size.c */
2577
2578 /* Start: bn_mp_init_u32.c */
2579 #include "tommath_private.h"
2580 #ifdef BN_MP_INIT_U32_C
2581 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2582 /* SPDX-License-Identifier: Unlicense */
2583
MP_INIT_INT(mp_init_u32,mp_set_u32,uint32_t)2584 MP_INIT_INT(mp_init_u32, mp_set_u32, uint32_t)
2585 #endif
2586
2587 /* End: bn_mp_init_u32.c */
2588
2589 /* Start: bn_mp_init_u64.c */
2590 #include "tommath_private.h"
2591 #ifdef BN_MP_INIT_U64_C
2592 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2593 /* SPDX-License-Identifier: Unlicense */
2594
2595 MP_INIT_INT(mp_init_u64, mp_set_u64, uint64_t)
2596 #endif
2597
2598 /* End: bn_mp_init_u64.c */
2599
2600 /* Start: bn_mp_init_ul.c */
2601 #include "tommath_private.h"
2602 #ifdef BN_MP_INIT_UL_C
2603 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2604 /* SPDX-License-Identifier: Unlicense */
2605
2606 MP_INIT_INT(mp_init_ul, mp_set_ul, unsigned long)
2607 #endif
2608
2609 /* End: bn_mp_init_ul.c */
2610
2611 /* Start: bn_mp_init_ull.c */
2612 #include "tommath_private.h"
2613 #ifdef BN_MP_INIT_ULL_C
2614 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2615 /* SPDX-License-Identifier: Unlicense */
2616
2617 MP_INIT_INT(mp_init_ull, mp_set_ull, unsigned long long)
2618 #endif
2619
2620 /* End: bn_mp_init_ull.c */
2621
2622 /* Start: bn_mp_invmod.c */
2623 #include "tommath_private.h"
2624 #ifdef BN_MP_INVMOD_C
2625 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2626 /* SPDX-License-Identifier: Unlicense */
2627
2628 /* hac 14.61, pp608 */
2629 mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c)
2630 {
2631 /* b cannot be negative and has to be >1 */
2632 if ((b->sign == MP_NEG) || (mp_cmp_d(b, 1uL) != MP_GT)) {
2633 return MP_VAL;
2634 }
2635
2636 /* if the modulus is odd we can use a faster routine instead */
2637 if (MP_HAS(S_MP_INVMOD_FAST) && MP_IS_ODD(b)) {
2638 return s_mp_invmod_fast(a, b, c);
2639 }
2640
2641 return MP_HAS(S_MP_INVMOD_SLOW)
2642 ? s_mp_invmod_slow(a, b, c)
2643 : MP_VAL;
2644 }
2645 #endif
2646
2647 /* End: bn_mp_invmod.c */
2648
2649 /* Start: bn_mp_is_square.c */
2650 #include "tommath_private.h"
2651 #ifdef BN_MP_IS_SQUARE_C
2652 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2653 /* SPDX-License-Identifier: Unlicense */
2654
2655 /* Check if remainders are possible squares - fast exclude non-squares */
2656 static const char rem_128[128] = {
2657 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
2658 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
2659 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
2660 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
2661 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
2662 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
2663 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
2664 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
2665 };
2666
2667 static const char rem_105[105] = {
2668 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
2669 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
2670 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
2671 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
2672 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
2673 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
2674 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
2675 };
2676
2677 /* Store non-zero to ret if arg is square, and zero if not */
mp_is_square(const mp_int * arg,mp_bool * ret)2678 mp_err mp_is_square(const mp_int *arg, mp_bool *ret)
2679 {
2680 mp_err err;
2681 mp_digit c;
2682 mp_int t;
2683 unsigned long r;
2684
2685 /* Default to Non-square :) */
2686 *ret = MP_NO;
2687
2688 if (arg->sign == MP_NEG) {
2689 return MP_VAL;
2690 }
2691
2692 if (MP_IS_ZERO(arg)) {
2693 return MP_OKAY;
2694 }
2695
2696 /* First check mod 128 (suppose that MP_DIGIT_BIT is at least 7) */
2697 if (rem_128[127u & arg->dp[0]] == (char)1) {
2698 return MP_OKAY;
2699 }
2700
2701 /* Next check mod 105 (3*5*7) */
2702 if ((err = mp_mod_d(arg, 105uL, &c)) != MP_OKAY) {
2703 return err;
2704 }
2705 if (rem_105[c] == (char)1) {
2706 return MP_OKAY;
2707 }
2708
2709
2710 if ((err = mp_init_u32(&t, 11u*13u*17u*19u*23u*29u*31u)) != MP_OKAY) {
2711 return err;
2712 }
2713 if ((err = mp_mod(arg, &t, &t)) != MP_OKAY) {
2714 goto LBL_ERR;
2715 }
2716 r = mp_get_u32(&t);
2717 /* Check for other prime modules, note it's not an ERROR but we must
2718 * free "t" so the easiest way is to goto LBL_ERR. We know that err
2719 * is already equal to MP_OKAY from the mp_mod call
2720 */
2721 if (((1uL<<(r%11uL)) & 0x5C4uL) != 0uL) goto LBL_ERR;
2722 if (((1uL<<(r%13uL)) & 0x9E4uL) != 0uL) goto LBL_ERR;
2723 if (((1uL<<(r%17uL)) & 0x5CE8uL) != 0uL) goto LBL_ERR;
2724 if (((1uL<<(r%19uL)) & 0x4F50CuL) != 0uL) goto LBL_ERR;
2725 if (((1uL<<(r%23uL)) & 0x7ACCA0uL) != 0uL) goto LBL_ERR;
2726 if (((1uL<<(r%29uL)) & 0xC2EDD0CuL) != 0uL) goto LBL_ERR;
2727 if (((1uL<<(r%31uL)) & 0x6DE2B848uL) != 0uL) goto LBL_ERR;
2728
2729 /* Final check - is sqr(sqrt(arg)) == arg ? */
2730 if ((err = mp_sqrt(arg, &t)) != MP_OKAY) {
2731 goto LBL_ERR;
2732 }
2733 if ((err = mp_sqr(&t, &t)) != MP_OKAY) {
2734 goto LBL_ERR;
2735 }
2736
2737 *ret = (mp_cmp_mag(&t, arg) == MP_EQ) ? MP_YES : MP_NO;
2738 LBL_ERR:
2739 mp_clear(&t);
2740 return err;
2741 }
2742 #endif
2743
2744 /* End: bn_mp_is_square.c */
2745
2746 /* Start: bn_mp_iseven.c */
2747 #include "tommath_private.h"
2748 #ifdef BN_MP_ISEVEN_C
2749 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2750 /* SPDX-License-Identifier: Unlicense */
2751
mp_iseven(const mp_int * a)2752 mp_bool mp_iseven(const mp_int *a)
2753 {
2754 return MP_IS_EVEN(a) ? MP_YES : MP_NO;
2755 }
2756 #endif
2757
2758 /* End: bn_mp_iseven.c */
2759
2760 /* Start: bn_mp_isodd.c */
2761 #include "tommath_private.h"
2762 #ifdef BN_MP_ISODD_C
2763 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2764 /* SPDX-License-Identifier: Unlicense */
2765
mp_isodd(const mp_int * a)2766 mp_bool mp_isodd(const mp_int *a)
2767 {
2768 return MP_IS_ODD(a) ? MP_YES : MP_NO;
2769 }
2770 #endif
2771
2772 /* End: bn_mp_isodd.c */
2773
2774 /* Start: bn_mp_kronecker.c */
2775 #include "tommath_private.h"
2776 #ifdef BN_MP_KRONECKER_C
2777
2778 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2779 /* SPDX-License-Identifier: Unlicense */
2780
2781 /*
2782 Kronecker symbol (a|p)
2783 Straightforward implementation of algorithm 1.4.10 in
2784 Henri Cohen: "A Course in Computational Algebraic Number Theory"
2785
2786 @book{cohen2013course,
2787 title={A course in computational algebraic number theory},
2788 author={Cohen, Henri},
2789 volume={138},
2790 year={2013},
2791 publisher={Springer Science \& Business Media}
2792 }
2793 */
mp_kronecker(const mp_int * a,const mp_int * p,int * c)2794 mp_err mp_kronecker(const mp_int *a, const mp_int *p, int *c)
2795 {
2796 mp_int a1, p1, r;
2797 mp_err err;
2798 int v, k;
2799
2800 static const int table[8] = {0, 1, 0, -1, 0, -1, 0, 1};
2801
2802 if (MP_IS_ZERO(p)) {
2803 if ((a->used == 1) && (a->dp[0] == 1u)) {
2804 *c = 1;
2805 } else {
2806 *c = 0;
2807 }
2808 return MP_OKAY;
2809 }
2810
2811 if (MP_IS_EVEN(a) && MP_IS_EVEN(p)) {
2812 *c = 0;
2813 return MP_OKAY;
2814 }
2815
2816 if ((err = mp_init_copy(&a1, a)) != MP_OKAY) {
2817 return err;
2818 }
2819 if ((err = mp_init_copy(&p1, p)) != MP_OKAY) {
2820 goto LBL_KRON_0;
2821 }
2822
2823 v = mp_cnt_lsb(&p1);
2824 if ((err = mp_div_2d(&p1, v, &p1, NULL)) != MP_OKAY) {
2825 goto LBL_KRON_1;
2826 }
2827
2828 if ((v & 1) == 0) {
2829 k = 1;
2830 } else {
2831 k = table[a->dp[0] & 7u];
2832 }
2833
2834 if (p1.sign == MP_NEG) {
2835 p1.sign = MP_ZPOS;
2836 if (a1.sign == MP_NEG) {
2837 k = -k;
2838 }
2839 }
2840
2841 if ((err = mp_init(&r)) != MP_OKAY) {
2842 goto LBL_KRON_1;
2843 }
2844
2845 for (;;) {
2846 if (MP_IS_ZERO(&a1)) {
2847 if (mp_cmp_d(&p1, 1uL) == MP_EQ) {
2848 *c = k;
2849 goto LBL_KRON;
2850 } else {
2851 *c = 0;
2852 goto LBL_KRON;
2853 }
2854 }
2855
2856 v = mp_cnt_lsb(&a1);
2857 if ((err = mp_div_2d(&a1, v, &a1, NULL)) != MP_OKAY) {
2858 goto LBL_KRON;
2859 }
2860
2861 if ((v & 1) == 1) {
2862 k = k * table[p1.dp[0] & 7u];
2863 }
2864
2865 if (a1.sign == MP_NEG) {
2866 /*
2867 * Compute k = (-1)^((a1)*(p1-1)/4) * k
2868 * a1.dp[0] + 1 cannot overflow because the MSB
2869 * of the type mp_digit is not set by definition
2870 */
2871 if (((a1.dp[0] + 1u) & p1.dp[0] & 2u) != 0u) {
2872 k = -k;
2873 }
2874 } else {
2875 /* compute k = (-1)^((a1-1)*(p1-1)/4) * k */
2876 if ((a1.dp[0] & p1.dp[0] & 2u) != 0u) {
2877 k = -k;
2878 }
2879 }
2880
2881 if ((err = mp_copy(&a1, &r)) != MP_OKAY) {
2882 goto LBL_KRON;
2883 }
2884 r.sign = MP_ZPOS;
2885 if ((err = mp_mod(&p1, &r, &a1)) != MP_OKAY) {
2886 goto LBL_KRON;
2887 }
2888 if ((err = mp_copy(&r, &p1)) != MP_OKAY) {
2889 goto LBL_KRON;
2890 }
2891 }
2892
2893 LBL_KRON:
2894 mp_clear(&r);
2895 LBL_KRON_1:
2896 mp_clear(&p1);
2897 LBL_KRON_0:
2898 mp_clear(&a1);
2899
2900 return err;
2901 }
2902
2903 #endif
2904
2905 /* End: bn_mp_kronecker.c */
2906
2907 /* Start: bn_mp_lcm.c */
2908 #include "tommath_private.h"
2909 #ifdef BN_MP_LCM_C
2910 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2911 /* SPDX-License-Identifier: Unlicense */
2912
2913 /* computes least common multiple as |a*b|/(a, b) */
mp_lcm(const mp_int * a,const mp_int * b,mp_int * c)2914 mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c)
2915 {
2916 mp_err err;
2917 mp_int t1, t2;
2918
2919
2920 if ((err = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) {
2921 return err;
2922 }
2923
2924 /* t1 = get the GCD of the two inputs */
2925 if ((err = mp_gcd(a, b, &t1)) != MP_OKAY) {
2926 goto LBL_T;
2927 }
2928
2929 /* divide the smallest by the GCD */
2930 if (mp_cmp_mag(a, b) == MP_LT) {
2931 /* store quotient in t2 such that t2 * b is the LCM */
2932 if ((err = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
2933 goto LBL_T;
2934 }
2935 err = mp_mul(b, &t2, c);
2936 } else {
2937 /* store quotient in t2 such that t2 * a is the LCM */
2938 if ((err = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
2939 goto LBL_T;
2940 }
2941 err = mp_mul(a, &t2, c);
2942 }
2943
2944 /* fix the sign to positive */
2945 c->sign = MP_ZPOS;
2946
2947 LBL_T:
2948 mp_clear_multi(&t1, &t2, NULL);
2949 return err;
2950 }
2951 #endif
2952
2953 /* End: bn_mp_lcm.c */
2954
2955 /* Start: bn_mp_log_u32.c */
2956 #include "tommath_private.h"
2957 #ifdef BN_MP_LOG_U32_C
2958 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
2959 /* SPDX-License-Identifier: Unlicense */
2960
2961 /* Compute log_{base}(a) */
s_pow(mp_word base,mp_word exponent)2962 static mp_word s_pow(mp_word base, mp_word exponent)
2963 {
2964 mp_word result = 1uLL;
2965 while (exponent != 0u) {
2966 if ((exponent & 1u) == 1u) {
2967 result *= base;
2968 }
2969 exponent >>= 1;
2970 base *= base;
2971 }
2972
2973 return result;
2974 }
2975
s_digit_ilogb(mp_digit base,mp_digit n)2976 static mp_digit s_digit_ilogb(mp_digit base, mp_digit n)
2977 {
2978 mp_word bracket_low = 1uLL, bracket_mid, bracket_high, N;
2979 mp_digit ret, high = 1uL, low = 0uL, mid;
2980
2981 if (n < base) {
2982 return 0uL;
2983 }
2984 if (n == base) {
2985 return 1uL;
2986 }
2987
2988 bracket_high = (mp_word) base ;
2989 N = (mp_word) n;
2990
2991 while (bracket_high < N) {
2992 low = high;
2993 bracket_low = bracket_high;
2994 high <<= 1;
2995 bracket_high *= bracket_high;
2996 }
2997
2998 while (((mp_digit)(high - low)) > 1uL) {
2999 mid = (low + high) >> 1;
3000 bracket_mid = bracket_low * s_pow(base, (mp_word)(mid - low));
3001
3002 if (N < bracket_mid) {
3003 high = mid ;
3004 bracket_high = bracket_mid ;
3005 }
3006 if (N > bracket_mid) {
3007 low = mid ;
3008 bracket_low = bracket_mid ;
3009 }
3010 if (N == bracket_mid) {
3011 return (mp_digit) mid;
3012 }
3013 }
3014
3015 if (bracket_high == N) {
3016 ret = high;
3017 } else {
3018 ret = low;
3019 }
3020
3021 return ret;
3022 }
3023
3024 /* TODO: output could be "int" because the output of mp_radix_size is int, too,
3025 as is the output of mp_bitcount.
3026 With the same problem: max size is INT_MAX * MP_DIGIT not INT_MAX only!
3027 */
mp_log_u32(const mp_int * a,uint32_t base,uint32_t * c)3028 mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c)
3029 {
3030 mp_err err;
3031 mp_ord cmp;
3032 uint32_t high, low, mid;
3033 mp_int bracket_low, bracket_high, bracket_mid, t, bi_base;
3034
3035 err = MP_OKAY;
3036
3037 if (a->sign == MP_NEG) {
3038 return MP_VAL;
3039 }
3040
3041 if (MP_IS_ZERO(a)) {
3042 return MP_VAL;
3043 }
3044
3045 if (base < 2u) {
3046 return MP_VAL;
3047 }
3048
3049 /* A small shortcut for bases that are powers of two. */
3050 if ((base & (base - 1u)) == 0u) {
3051 int y, bit_count;
3052 for (y=0; (y < 7) && ((base & 1u) == 0u); y++) {
3053 base >>= 1;
3054 }
3055 bit_count = mp_count_bits(a) - 1;
3056 *c = (uint32_t)(bit_count/y);
3057 return MP_OKAY;
3058 }
3059
3060 if (a->used == 1) {
3061 *c = (uint32_t)s_digit_ilogb(base, a->dp[0]);
3062 return err;
3063 }
3064
3065 cmp = mp_cmp_d(a, base);
3066 if ((cmp == MP_LT) || (cmp == MP_EQ)) {
3067 *c = cmp == MP_EQ;
3068 return err;
3069 }
3070
3071 if ((err =
3072 mp_init_multi(&bracket_low, &bracket_high,
3073 &bracket_mid, &t, &bi_base, NULL)) != MP_OKAY) {
3074 return err;
3075 }
3076
3077 low = 0u;
3078 mp_set(&bracket_low, 1uL);
3079 high = 1u;
3080
3081 mp_set(&bracket_high, base);
3082
3083 /*
3084 A kind of Giant-step/baby-step algorithm.
3085 Idea shamelessly stolen from https://programmingpraxis.com/2010/05/07/integer-logarithms/2/
3086 The effect is asymptotic, hence needs benchmarks to test if the Giant-step should be skipped
3087 for small n.
3088 */
3089 while (mp_cmp(&bracket_high, a) == MP_LT) {
3090 low = high;
3091 if ((err = mp_copy(&bracket_high, &bracket_low)) != MP_OKAY) {
3092 goto LBL_ERR;
3093 }
3094 high <<= 1;
3095 if ((err = mp_sqr(&bracket_high, &bracket_high)) != MP_OKAY) {
3096 goto LBL_ERR;
3097 }
3098 }
3099 mp_set(&bi_base, base);
3100
3101 while ((high - low) > 1u) {
3102 mid = (high + low) >> 1;
3103
3104 if ((err = mp_expt_u32(&bi_base, (uint32_t)(mid - low), &t)) != MP_OKAY) {
3105 goto LBL_ERR;
3106 }
3107 if ((err = mp_mul(&bracket_low, &t, &bracket_mid)) != MP_OKAY) {
3108 goto LBL_ERR;
3109 }
3110 cmp = mp_cmp(a, &bracket_mid);
3111 if (cmp == MP_LT) {
3112 high = mid;
3113 mp_exch(&bracket_mid, &bracket_high);
3114 }
3115 if (cmp == MP_GT) {
3116 low = mid;
3117 mp_exch(&bracket_mid, &bracket_low);
3118 }
3119 if (cmp == MP_EQ) {
3120 *c = mid;
3121 goto LBL_END;
3122 }
3123 }
3124
3125 *c = (mp_cmp(&bracket_high, a) == MP_EQ) ? high : low;
3126
3127 LBL_END:
3128 LBL_ERR:
3129 mp_clear_multi(&bracket_low, &bracket_high, &bracket_mid,
3130 &t, &bi_base, NULL);
3131 return err;
3132 }
3133
3134
3135 #endif
3136
3137 /* End: bn_mp_log_u32.c */
3138
3139 /* Start: bn_mp_lshd.c */
3140 #include "tommath_private.h"
3141 #ifdef BN_MP_LSHD_C
3142 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3143 /* SPDX-License-Identifier: Unlicense */
3144
3145 /* shift left a certain amount of digits */
mp_lshd(mp_int * a,int b)3146 mp_err mp_lshd(mp_int *a, int b)
3147 {
3148 int x;
3149 mp_err err;
3150 mp_digit *top, *bottom;
3151
3152 /* if its less than zero return */
3153 if (b <= 0) {
3154 return MP_OKAY;
3155 }
3156 /* no need to shift 0 around */
3157 if (MP_IS_ZERO(a)) {
3158 return MP_OKAY;
3159 }
3160
3161 /* grow to fit the new digits */
3162 if (a->alloc < (a->used + b)) {
3163 if ((err = mp_grow(a, a->used + b)) != MP_OKAY) {
3164 return err;
3165 }
3166 }
3167
3168 /* increment the used by the shift amount then copy upwards */
3169 a->used += b;
3170
3171 /* top */
3172 top = a->dp + a->used - 1;
3173
3174 /* base */
3175 bottom = (a->dp + a->used - 1) - b;
3176
3177 /* much like mp_rshd this is implemented using a sliding window
3178 * except the window goes the otherway around. Copying from
3179 * the bottom to the top. see bn_mp_rshd.c for more info.
3180 */
3181 for (x = a->used - 1; x >= b; x--) {
3182 *top-- = *bottom--;
3183 }
3184
3185 /* zero the lower digits */
3186 MP_ZERO_DIGITS(a->dp, b);
3187
3188 return MP_OKAY;
3189 }
3190 #endif
3191
3192 /* End: bn_mp_lshd.c */
3193
3194 /* Start: bn_mp_mod.c */
3195 #include "tommath_private.h"
3196 #ifdef BN_MP_MOD_C
3197 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3198 /* SPDX-License-Identifier: Unlicense */
3199
3200 /* c = a mod b, 0 <= c < b if b > 0, b < c <= 0 if b < 0 */
mp_mod(const mp_int * a,const mp_int * b,mp_int * c)3201 mp_err mp_mod(const mp_int *a, const mp_int *b, mp_int *c)
3202 {
3203 mp_int t;
3204 mp_err err;
3205
3206 if ((err = mp_init_size(&t, b->used)) != MP_OKAY) {
3207 return err;
3208 }
3209
3210 if ((err = mp_div(a, b, NULL, &t)) != MP_OKAY) {
3211 goto LBL_ERR;
3212 }
3213
3214 if (MP_IS_ZERO(&t) || (t.sign == b->sign)) {
3215 err = MP_OKAY;
3216 mp_exch(&t, c);
3217 } else {
3218 err = mp_add(b, &t, c);
3219 }
3220
3221 LBL_ERR:
3222 mp_clear(&t);
3223 return err;
3224 }
3225 #endif
3226
3227 /* End: bn_mp_mod.c */
3228
3229 /* Start: bn_mp_mod_2d.c */
3230 #include "tommath_private.h"
3231 #ifdef BN_MP_MOD_2D_C
3232 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3233 /* SPDX-License-Identifier: Unlicense */
3234
3235 /* calc a value mod 2**b */
mp_mod_2d(const mp_int * a,int b,mp_int * c)3236 mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c)
3237 {
3238 int x;
3239 mp_err err;
3240
3241 /* if b is <= 0 then zero the int */
3242 if (b <= 0) {
3243 mp_zero(c);
3244 return MP_OKAY;
3245 }
3246
3247 /* if the modulus is larger than the value than return */
3248 if (b >= (a->used * MP_DIGIT_BIT)) {
3249 return mp_copy(a, c);
3250 }
3251
3252 /* copy */
3253 if ((err = mp_copy(a, c)) != MP_OKAY) {
3254 return err;
3255 }
3256
3257 /* zero digits above the last digit of the modulus */
3258 x = (b / MP_DIGIT_BIT) + (((b % MP_DIGIT_BIT) == 0) ? 0 : 1);
3259 MP_ZERO_DIGITS(c->dp + x, c->used - x);
3260
3261 /* clear the digit that is not completely outside/inside the modulus */
3262 c->dp[b / MP_DIGIT_BIT] &=
3263 ((mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT)) - (mp_digit)1;
3264 mp_clamp(c);
3265 return MP_OKAY;
3266 }
3267 #endif
3268
3269 /* End: bn_mp_mod_2d.c */
3270
3271 /* Start: bn_mp_mod_d.c */
3272 #include "tommath_private.h"
3273 #ifdef BN_MP_MOD_D_C
3274 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3275 /* SPDX-License-Identifier: Unlicense */
3276
mp_mod_d(const mp_int * a,mp_digit b,mp_digit * c)3277 mp_err mp_mod_d(const mp_int *a, mp_digit b, mp_digit *c)
3278 {
3279 return mp_div_d(a, b, NULL, c);
3280 }
3281 #endif
3282
3283 /* End: bn_mp_mod_d.c */
3284
3285 /* Start: bn_mp_montgomery_calc_normalization.c */
3286 #include "tommath_private.h"
3287 #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
3288 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3289 /* SPDX-License-Identifier: Unlicense */
3290
3291 /*
3292 * shifts with subtractions when the result is greater than b.
3293 *
3294 * The method is slightly modified to shift B unconditionally upto just under
3295 * the leading bit of b. This saves alot of multiple precision shifting.
3296 */
mp_montgomery_calc_normalization(mp_int * a,const mp_int * b)3297 mp_err mp_montgomery_calc_normalization(mp_int *a, const mp_int *b)
3298 {
3299 int x, bits;
3300 mp_err err;
3301
3302 /* how many bits of last digit does b use */
3303 bits = mp_count_bits(b) % MP_DIGIT_BIT;
3304
3305 if (b->used > 1) {
3306 if ((err = mp_2expt(a, ((b->used - 1) * MP_DIGIT_BIT) + bits - 1)) != MP_OKAY) {
3307 return err;
3308 }
3309 } else {
3310 mp_set(a, 1uL);
3311 bits = 1;
3312 }
3313
3314
3315 /* now compute C = A * B mod b */
3316 for (x = bits - 1; x < (int)MP_DIGIT_BIT; x++) {
3317 if ((err = mp_mul_2(a, a)) != MP_OKAY) {
3318 return err;
3319 }
3320 if (mp_cmp_mag(a, b) != MP_LT) {
3321 if ((err = s_mp_sub(a, b, a)) != MP_OKAY) {
3322 return err;
3323 }
3324 }
3325 }
3326
3327 return MP_OKAY;
3328 }
3329 #endif
3330
3331 /* End: bn_mp_montgomery_calc_normalization.c */
3332
3333 /* Start: bn_mp_montgomery_reduce.c */
3334 #include "tommath_private.h"
3335 #ifdef BN_MP_MONTGOMERY_REDUCE_C
3336 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3337 /* SPDX-License-Identifier: Unlicense */
3338
3339 /* computes xR**-1 == x (mod N) via Montgomery Reduction */
mp_montgomery_reduce(mp_int * x,const mp_int * n,mp_digit rho)3340 mp_err mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho)
3341 {
3342 int ix, digs;
3343 mp_err err;
3344 mp_digit mu;
3345
3346 /* can the fast reduction [comba] method be used?
3347 *
3348 * Note that unlike in mul you're safely allowed *less*
3349 * than the available columns [255 per default] since carries
3350 * are fixed up in the inner loop.
3351 */
3352 digs = (n->used * 2) + 1;
3353 if ((digs < MP_WARRAY) &&
3354 (x->used <= MP_WARRAY) &&
3355 (n->used < MP_MAXFAST)) {
3356 return s_mp_montgomery_reduce_fast(x, n, rho);
3357 }
3358
3359 /* grow the input as required */
3360 if (x->alloc < digs) {
3361 if ((err = mp_grow(x, digs)) != MP_OKAY) {
3362 return err;
3363 }
3364 }
3365 x->used = digs;
3366
3367 for (ix = 0; ix < n->used; ix++) {
3368 /* mu = ai * rho mod b
3369 *
3370 * The value of rho must be precalculated via
3371 * montgomery_setup() such that
3372 * it equals -1/n0 mod b this allows the
3373 * following inner loop to reduce the
3374 * input one digit at a time
3375 */
3376 mu = (mp_digit)(((mp_word)x->dp[ix] * (mp_word)rho) & MP_MASK);
3377
3378 /* a = a + mu * m * b**i */
3379 {
3380 int iy;
3381 mp_digit *tmpn, *tmpx, u;
3382 mp_word r;
3383
3384 /* alias for digits of the modulus */
3385 tmpn = n->dp;
3386
3387 /* alias for the digits of x [the input] */
3388 tmpx = x->dp + ix;
3389
3390 /* set the carry to zero */
3391 u = 0;
3392
3393 /* Multiply and add in place */
3394 for (iy = 0; iy < n->used; iy++) {
3395 /* compute product and sum */
3396 r = ((mp_word)mu * (mp_word)*tmpn++) +
3397 (mp_word)u + (mp_word)*tmpx;
3398
3399 /* get carry */
3400 u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
3401
3402 /* fix digit */
3403 *tmpx++ = (mp_digit)(r & (mp_word)MP_MASK);
3404 }
3405 /* At this point the ix'th digit of x should be zero */
3406
3407
3408 /* propagate carries upwards as required*/
3409 while (u != 0u) {
3410 *tmpx += u;
3411 u = *tmpx >> MP_DIGIT_BIT;
3412 *tmpx++ &= MP_MASK;
3413 }
3414 }
3415 }
3416
3417 /* at this point the n.used'th least
3418 * significant digits of x are all zero
3419 * which means we can shift x to the
3420 * right by n.used digits and the
3421 * residue is unchanged.
3422 */
3423
3424 /* x = x/b**n.used */
3425 mp_clamp(x);
3426 mp_rshd(x, n->used);
3427
3428 /* if x >= n then x = x - n */
3429 if (mp_cmp_mag(x, n) != MP_LT) {
3430 return s_mp_sub(x, n, x);
3431 }
3432
3433 return MP_OKAY;
3434 }
3435 #endif
3436
3437 /* End: bn_mp_montgomery_reduce.c */
3438
3439 /* Start: bn_mp_montgomery_setup.c */
3440 #include "tommath_private.h"
3441 #ifdef BN_MP_MONTGOMERY_SETUP_C
3442 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3443 /* SPDX-License-Identifier: Unlicense */
3444
3445 /* setups the montgomery reduction stuff */
mp_montgomery_setup(const mp_int * n,mp_digit * rho)3446 mp_err mp_montgomery_setup(const mp_int *n, mp_digit *rho)
3447 {
3448 mp_digit x, b;
3449
3450 /* fast inversion mod 2**k
3451 *
3452 * Based on the fact that
3453 *
3454 * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
3455 * => 2*X*A - X*X*A*A = 1
3456 * => 2*(1) - (1) = 1
3457 */
3458 b = n->dp[0];
3459
3460 if ((b & 1u) == 0u) {
3461 return MP_VAL;
3462 }
3463
3464 x = (((b + 2u) & 4u) << 1) + b; /* here x*a==1 mod 2**4 */
3465 x *= 2u - (b * x); /* here x*a==1 mod 2**8 */
3466 #if !defined(MP_8BIT)
3467 x *= 2u - (b * x); /* here x*a==1 mod 2**16 */
3468 #endif
3469 #if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
3470 x *= 2u - (b * x); /* here x*a==1 mod 2**32 */
3471 #endif
3472 #ifdef MP_64BIT
3473 x *= 2u - (b * x); /* here x*a==1 mod 2**64 */
3474 #endif
3475
3476 /* rho = -1/m mod b */
3477 *rho = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - x) & MP_MASK;
3478
3479 return MP_OKAY;
3480 }
3481 #endif
3482
3483 /* End: bn_mp_montgomery_setup.c */
3484
3485 /* Start: bn_mp_mul.c */
3486 #include "tommath_private.h"
3487 #ifdef BN_MP_MUL_C
3488 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3489 /* SPDX-License-Identifier: Unlicense */
3490
3491 /* high level multiplication (handles sign) */
mp_mul(const mp_int * a,const mp_int * b,mp_int * c)3492 mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
3493 {
3494 mp_err err;
3495 int min_len = MP_MIN(a->used, b->used),
3496 max_len = MP_MAX(a->used, b->used),
3497 digs = a->used + b->used + 1;
3498 mp_sign neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
3499
3500 if (MP_HAS(S_MP_BALANCE_MUL) &&
3501 /* Check sizes. The smaller one needs to be larger than the Karatsuba cut-off.
3502 * The bigger one needs to be at least about one MP_KARATSUBA_MUL_CUTOFF bigger
3503 * to make some sense, but it depends on architecture, OS, position of the
3504 * stars... so YMMV.
3505 * Using it to cut the input into slices small enough for fast_s_mp_mul_digs
3506 * was actually slower on the author's machine, but YMMV.
3507 */
3508 (min_len >= MP_KARATSUBA_MUL_CUTOFF) &&
3509 ((max_len / 2) >= MP_KARATSUBA_MUL_CUTOFF) &&
3510 /* Not much effect was observed below a ratio of 1:2, but again: YMMV. */
3511 (max_len >= (2 * min_len))) {
3512 err = s_mp_balance_mul(a,b,c);
3513 } else if (MP_HAS(S_MP_TOOM_MUL) &&
3514 (min_len >= MP_TOOM_MUL_CUTOFF)) {
3515 err = s_mp_toom_mul(a, b, c);
3516 } else if (MP_HAS(S_MP_KARATSUBA_MUL) &&
3517 (min_len >= MP_KARATSUBA_MUL_CUTOFF)) {
3518 err = s_mp_karatsuba_mul(a, b, c);
3519 } else if (MP_HAS(S_MP_MUL_DIGS_FAST) &&
3520 /* can we use the fast multiplier?
3521 *
3522 * The fast multiplier can be used if the output will
3523 * have less than MP_WARRAY digits and the number of
3524 * digits won't affect carry propagation
3525 */
3526 (digs < MP_WARRAY) &&
3527 (min_len <= MP_MAXFAST)) {
3528 err = s_mp_mul_digs_fast(a, b, c, digs);
3529 } else if (MP_HAS(S_MP_MUL_DIGS)) {
3530 err = s_mp_mul_digs(a, b, c, digs);
3531 } else {
3532 err = MP_VAL;
3533 }
3534 c->sign = (c->used > 0) ? neg : MP_ZPOS;
3535 return err;
3536 }
3537 #endif
3538
3539 /* End: bn_mp_mul.c */
3540
3541 /* Start: bn_mp_mul_2.c */
3542 #include "tommath_private.h"
3543 #ifdef BN_MP_MUL_2_C
3544 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3545 /* SPDX-License-Identifier: Unlicense */
3546
3547 /* b = a*2 */
mp_mul_2(const mp_int * a,mp_int * b)3548 mp_err mp_mul_2(const mp_int *a, mp_int *b)
3549 {
3550 int x, oldused;
3551 mp_err err;
3552
3553 /* grow to accomodate result */
3554 if (b->alloc < (a->used + 1)) {
3555 if ((err = mp_grow(b, a->used + 1)) != MP_OKAY) {
3556 return err;
3557 }
3558 }
3559
3560 oldused = b->used;
3561 b->used = a->used;
3562
3563 {
3564 mp_digit r, rr, *tmpa, *tmpb;
3565
3566 /* alias for source */
3567 tmpa = a->dp;
3568
3569 /* alias for dest */
3570 tmpb = b->dp;
3571
3572 /* carry */
3573 r = 0;
3574 for (x = 0; x < a->used; x++) {
3575
3576 /* get what will be the *next* carry bit from the
3577 * MSB of the current digit
3578 */
3579 rr = *tmpa >> (mp_digit)(MP_DIGIT_BIT - 1);
3580
3581 /* now shift up this digit, add in the carry [from the previous] */
3582 *tmpb++ = ((*tmpa++ << 1uL) | r) & MP_MASK;
3583
3584 /* copy the carry that would be from the source
3585 * digit into the next iteration
3586 */
3587 r = rr;
3588 }
3589
3590 /* new leading digit? */
3591 if (r != 0u) {
3592 /* add a MSB which is always 1 at this point */
3593 *tmpb = 1;
3594 ++(b->used);
3595 }
3596
3597 /* now zero any excess digits on the destination
3598 * that we didn't write to
3599 */
3600 MP_ZERO_DIGITS(b->dp + b->used, oldused - b->used);
3601 }
3602 b->sign = a->sign;
3603 return MP_OKAY;
3604 }
3605 #endif
3606
3607 /* End: bn_mp_mul_2.c */
3608
3609 /* Start: bn_mp_mul_2d.c */
3610 #include "tommath_private.h"
3611 #ifdef BN_MP_MUL_2D_C
3612 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3613 /* SPDX-License-Identifier: Unlicense */
3614
3615 /* shift left by a certain bit count */
mp_mul_2d(const mp_int * a,int b,mp_int * c)3616 mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c)
3617 {
3618 mp_digit d;
3619 mp_err err;
3620
3621 /* copy */
3622 if (a != c) {
3623 if ((err = mp_copy(a, c)) != MP_OKAY) {
3624 return err;
3625 }
3626 }
3627
3628 if (c->alloc < (c->used + (b / MP_DIGIT_BIT) + 1)) {
3629 if ((err = mp_grow(c, c->used + (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) {
3630 return err;
3631 }
3632 }
3633
3634 /* shift by as many digits in the bit count */
3635 if (b >= MP_DIGIT_BIT) {
3636 if ((err = mp_lshd(c, b / MP_DIGIT_BIT)) != MP_OKAY) {
3637 return err;
3638 }
3639 }
3640
3641 /* shift any bit count < MP_DIGIT_BIT */
3642 d = (mp_digit)(b % MP_DIGIT_BIT);
3643 if (d != 0u) {
3644 mp_digit *tmpc, shift, mask, r, rr;
3645 int x;
3646
3647 /* bitmask for carries */
3648 mask = ((mp_digit)1 << d) - (mp_digit)1;
3649
3650 /* shift for msbs */
3651 shift = (mp_digit)MP_DIGIT_BIT - d;
3652
3653 /* alias */
3654 tmpc = c->dp;
3655
3656 /* carry */
3657 r = 0;
3658 for (x = 0; x < c->used; x++) {
3659 /* get the higher bits of the current word */
3660 rr = (*tmpc >> shift) & mask;
3661
3662 /* shift the current word and OR in the carry */
3663 *tmpc = ((*tmpc << d) | r) & MP_MASK;
3664 ++tmpc;
3665
3666 /* set the carry to the carry bits of the current word */
3667 r = rr;
3668 }
3669
3670 /* set final carry */
3671 if (r != 0u) {
3672 c->dp[(c->used)++] = r;
3673 }
3674 }
3675 mp_clamp(c);
3676 return MP_OKAY;
3677 }
3678 #endif
3679
3680 /* End: bn_mp_mul_2d.c */
3681
3682 /* Start: bn_mp_mul_d.c */
3683 #include "tommath_private.h"
3684 #ifdef BN_MP_MUL_D_C
3685 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3686 /* SPDX-License-Identifier: Unlicense */
3687
3688 /* multiply by a digit */
mp_mul_d(const mp_int * a,mp_digit b,mp_int * c)3689 mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c)
3690 {
3691 mp_digit u, *tmpa, *tmpc;
3692 mp_word r;
3693 mp_err err;
3694 int ix, olduse;
3695
3696 /* make sure c is big enough to hold a*b */
3697 if (c->alloc < (a->used + 1)) {
3698 if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) {
3699 return err;
3700 }
3701 }
3702
3703 /* get the original destinations used count */
3704 olduse = c->used;
3705
3706 /* set the sign */
3707 c->sign = a->sign;
3708
3709 /* alias for a->dp [source] */
3710 tmpa = a->dp;
3711
3712 /* alias for c->dp [dest] */
3713 tmpc = c->dp;
3714
3715 /* zero carry */
3716 u = 0;
3717
3718 /* compute columns */
3719 for (ix = 0; ix < a->used; ix++) {
3720 /* compute product and carry sum for this term */
3721 r = (mp_word)u + ((mp_word)*tmpa++ * (mp_word)b);
3722
3723 /* mask off higher bits to get a single digit */
3724 *tmpc++ = (mp_digit)(r & (mp_word)MP_MASK);
3725
3726 /* send carry into next iteration */
3727 u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
3728 }
3729
3730 /* store final carry [if any] and increment ix offset */
3731 *tmpc++ = u;
3732 ++ix;
3733
3734 /* now zero digits above the top */
3735 MP_ZERO_DIGITS(tmpc, olduse - ix);
3736
3737 /* set used count */
3738 c->used = a->used + 1;
3739 mp_clamp(c);
3740
3741 return MP_OKAY;
3742 }
3743 #endif
3744
3745 /* End: bn_mp_mul_d.c */
3746
3747 /* Start: bn_mp_mulmod.c */
3748 #include "tommath_private.h"
3749 #ifdef BN_MP_MULMOD_C
3750 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3751 /* SPDX-License-Identifier: Unlicense */
3752
3753 /* d = a * b (mod c) */
mp_mulmod(const mp_int * a,const mp_int * b,const mp_int * c,mp_int * d)3754 mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d)
3755 {
3756 mp_err err;
3757 mp_int t;
3758
3759 if ((err = mp_init_size(&t, c->used)) != MP_OKAY) {
3760 return err;
3761 }
3762
3763 if ((err = mp_mul(a, b, &t)) != MP_OKAY) {
3764 goto LBL_ERR;
3765 }
3766 err = mp_mod(&t, c, d);
3767
3768 LBL_ERR:
3769 mp_clear(&t);
3770 return err;
3771 }
3772 #endif
3773
3774 /* End: bn_mp_mulmod.c */
3775
3776 /* Start: bn_mp_neg.c */
3777 #include "tommath_private.h"
3778 #ifdef BN_MP_NEG_C
3779 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3780 /* SPDX-License-Identifier: Unlicense */
3781
3782 /* b = -a */
mp_neg(const mp_int * a,mp_int * b)3783 mp_err mp_neg(const mp_int *a, mp_int *b)
3784 {
3785 mp_err err;
3786 if (a != b) {
3787 if ((err = mp_copy(a, b)) != MP_OKAY) {
3788 return err;
3789 }
3790 }
3791
3792 if (!MP_IS_ZERO(b)) {
3793 b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
3794 } else {
3795 b->sign = MP_ZPOS;
3796 }
3797
3798 return MP_OKAY;
3799 }
3800 #endif
3801
3802 /* End: bn_mp_neg.c */
3803
3804 /* Start: bn_mp_or.c */
3805 #include "tommath_private.h"
3806 #ifdef BN_MP_OR_C
3807 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3808 /* SPDX-License-Identifier: Unlicense */
3809
3810 /* two complement or */
mp_or(const mp_int * a,const mp_int * b,mp_int * c)3811 mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c)
3812 {
3813 int used = MP_MAX(a->used, b->used) + 1, i;
3814 mp_err err;
3815 mp_digit ac = 1, bc = 1, cc = 1;
3816 mp_sign csign = ((a->sign == MP_NEG) || (b->sign == MP_NEG)) ? MP_NEG : MP_ZPOS;
3817
3818 if (c->alloc < used) {
3819 if ((err = mp_grow(c, used)) != MP_OKAY) {
3820 return err;
3821 }
3822 }
3823
3824 for (i = 0; i < used; i++) {
3825 mp_digit x, y;
3826
3827 /* convert to two complement if negative */
3828 if (a->sign == MP_NEG) {
3829 ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK);
3830 x = ac & MP_MASK;
3831 ac >>= MP_DIGIT_BIT;
3832 } else {
3833 x = (i >= a->used) ? 0uL : a->dp[i];
3834 }
3835
3836 /* convert to two complement if negative */
3837 if (b->sign == MP_NEG) {
3838 bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK);
3839 y = bc & MP_MASK;
3840 bc >>= MP_DIGIT_BIT;
3841 } else {
3842 y = (i >= b->used) ? 0uL : b->dp[i];
3843 }
3844
3845 c->dp[i] = x | y;
3846
3847 /* convert to to sign-magnitude if negative */
3848 if (csign == MP_NEG) {
3849 cc += ~c->dp[i] & MP_MASK;
3850 c->dp[i] = cc & MP_MASK;
3851 cc >>= MP_DIGIT_BIT;
3852 }
3853 }
3854
3855 c->used = used;
3856 c->sign = csign;
3857 mp_clamp(c);
3858 return MP_OKAY;
3859 }
3860 #endif
3861
3862 /* End: bn_mp_or.c */
3863
3864 /* Start: bn_mp_pack.c */
3865 #include "tommath_private.h"
3866 #ifdef BN_MP_PACK_C
3867 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3868 /* SPDX-License-Identifier: Unlicense */
3869
3870 /* based on gmp's mpz_export.
3871 * see http://gmplib.org/manual/Integer-Import-and-Export.html
3872 */
mp_pack(void * rop,size_t maxcount,size_t * written,mp_order order,size_t size,mp_endian endian,size_t nails,const mp_int * op)3873 mp_err mp_pack(void *rop, size_t maxcount, size_t *written, mp_order order, size_t size,
3874 mp_endian endian, size_t nails, const mp_int *op)
3875 {
3876 mp_err err;
3877 size_t odd_nails, nail_bytes, i, j, count;
3878 unsigned char odd_nail_mask;
3879
3880 mp_int t;
3881
3882 count = mp_pack_count(op, nails, size);
3883
3884 if (count > maxcount) {
3885 return MP_BUF;
3886 }
3887
3888 if ((err = mp_init_copy(&t, op)) != MP_OKAY) {
3889 return err;
3890 }
3891
3892 if (endian == MP_NATIVE_ENDIAN) {
3893 MP_GET_ENDIANNESS(endian);
3894 }
3895
3896 odd_nails = (nails % 8u);
3897 odd_nail_mask = 0xff;
3898 for (i = 0u; i < odd_nails; ++i) {
3899 odd_nail_mask ^= (unsigned char)(1u << (7u - i));
3900 }
3901 nail_bytes = nails / 8u;
3902
3903 for (i = 0u; i < count; ++i) {
3904 for (j = 0u; j < size; ++j) {
3905 unsigned char *byte = (unsigned char *)rop +
3906 (((order == MP_LSB_FIRST) ? i : ((count - 1u) - i)) * size) +
3907 ((endian == MP_LITTLE_ENDIAN) ? j : ((size - 1u) - j));
3908
3909 if (j >= (size - nail_bytes)) {
3910 *byte = 0;
3911 continue;
3912 }
3913
3914 *byte = (unsigned char)((j == ((size - nail_bytes) - 1u)) ? (t.dp[0] & odd_nail_mask) : (t.dp[0] & 0xFFuL));
3915
3916 if ((err = mp_div_2d(&t, (j == ((size - nail_bytes) - 1u)) ? (int)(8u - odd_nails) : 8, &t, NULL)) != MP_OKAY) {
3917 goto LBL_ERR;
3918 }
3919
3920 }
3921 }
3922
3923 if (written != NULL) {
3924 *written = count;
3925 }
3926 err = MP_OKAY;
3927
3928 LBL_ERR:
3929 mp_clear(&t);
3930 return err;
3931 }
3932
3933 #endif
3934
3935 /* End: bn_mp_pack.c */
3936
3937 /* Start: bn_mp_pack_count.c */
3938 #include "tommath_private.h"
3939 #ifdef BN_MP_PACK_COUNT_C
3940 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3941 /* SPDX-License-Identifier: Unlicense */
3942
mp_pack_count(const mp_int * a,size_t nails,size_t size)3943 size_t mp_pack_count(const mp_int *a, size_t nails, size_t size)
3944 {
3945 size_t bits = (size_t)mp_count_bits(a);
3946 return ((bits / ((size * 8u) - nails)) + (((bits % ((size * 8u) - nails)) != 0u) ? 1u : 0u));
3947 }
3948
3949 #endif
3950
3951 /* End: bn_mp_pack_count.c */
3952
3953 /* Start: bn_mp_prime_fermat.c */
3954 #include "tommath_private.h"
3955 #ifdef BN_MP_PRIME_FERMAT_C
3956 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
3957 /* SPDX-License-Identifier: Unlicense */
3958
3959 /* performs one Fermat test.
3960 *
3961 * If "a" were prime then b**a == b (mod a) since the order of
3962 * the multiplicative sub-group would be phi(a) = a-1. That means
3963 * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
3964 *
3965 * Sets result to 1 if the congruence holds, or zero otherwise.
3966 */
mp_prime_fermat(const mp_int * a,const mp_int * b,mp_bool * result)3967 mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, mp_bool *result)
3968 {
3969 mp_int t;
3970 mp_err err;
3971
3972 /* default to composite */
3973 *result = MP_NO;
3974
3975 /* ensure b > 1 */
3976 if (mp_cmp_d(b, 1uL) != MP_GT) {
3977 return MP_VAL;
3978 }
3979
3980 /* init t */
3981 if ((err = mp_init(&t)) != MP_OKAY) {
3982 return err;
3983 }
3984
3985 /* compute t = b**a mod a */
3986 if ((err = mp_exptmod(b, a, a, &t)) != MP_OKAY) {
3987 goto LBL_T;
3988 }
3989
3990 /* is it equal to b? */
3991 if (mp_cmp(&t, b) == MP_EQ) {
3992 *result = MP_YES;
3993 }
3994
3995 err = MP_OKAY;
3996 LBL_T:
3997 mp_clear(&t);
3998 return err;
3999 }
4000 #endif
4001
4002 /* End: bn_mp_prime_fermat.c */
4003
4004 /* Start: bn_mp_prime_frobenius_underwood.c */
4005 #include "tommath_private.h"
4006 #ifdef BN_MP_PRIME_FROBENIUS_UNDERWOOD_C
4007
4008 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4009 /* SPDX-License-Identifier: Unlicense */
4010
4011 /*
4012 * See file bn_mp_prime_is_prime.c or the documentation in doc/bn.tex for the details
4013 */
4014 #ifndef LTM_USE_ONLY_MR
4015
4016 #ifdef MP_8BIT
4017 /*
4018 * floor of positive solution of
4019 * (2^16)-1 = (a+4)*(2*a+5)
4020 * TODO: Both values are smaller than N^(1/4), would have to use a bigint
4021 * for a instead but any a biger than about 120 are already so rare that
4022 * it is possible to ignore them and still get enough pseudoprimes.
4023 * But it is still a restriction of the set of available pseudoprimes
4024 * which makes this implementation less secure if used stand-alone.
4025 */
4026 #define LTM_FROBENIUS_UNDERWOOD_A 177
4027 #else
4028 #define LTM_FROBENIUS_UNDERWOOD_A 32764
4029 #endif
mp_prime_frobenius_underwood(const mp_int * N,mp_bool * result)4030 mp_err mp_prime_frobenius_underwood(const mp_int *N, mp_bool *result)
4031 {
4032 mp_int T1z, T2z, Np1z, sz, tz;
4033
4034 int a, ap2, length, i, j;
4035 mp_err err;
4036
4037 *result = MP_NO;
4038
4039 if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, NULL)) != MP_OKAY) {
4040 return err;
4041 }
4042
4043 for (a = 0; a < LTM_FROBENIUS_UNDERWOOD_A; a++) {
4044 /* TODO: That's ugly! No, really, it is! */
4045 if ((a==2) || (a==4) || (a==7) || (a==8) || (a==10) ||
4046 (a==14) || (a==18) || (a==23) || (a==26) || (a==28)) {
4047 continue;
4048 }
4049 /* (32764^2 - 4) < 2^31, no bigint for >MP_8BIT needed) */
4050 mp_set_u32(&T1z, (uint32_t)a);
4051
4052 if ((err = mp_sqr(&T1z, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
4053
4054 if ((err = mp_sub_d(&T1z, 4uL, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
4055
4056 if ((err = mp_kronecker(&T1z, N, &j)) != MP_OKAY) goto LBL_FU_ERR;
4057
4058 if (j == -1) {
4059 break;
4060 }
4061
4062 if (j == 0) {
4063 /* composite */
4064 goto LBL_FU_ERR;
4065 }
4066 }
4067 /* Tell it a composite and set return value accordingly */
4068 if (a >= LTM_FROBENIUS_UNDERWOOD_A) {
4069 err = MP_ITER;
4070 goto LBL_FU_ERR;
4071 }
4072 /* Composite if N and (a+4)*(2*a+5) are not coprime */
4073 mp_set_u32(&T1z, (uint32_t)((a+4)*((2*a)+5)));
4074
4075 if ((err = mp_gcd(N, &T1z, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
4076
4077 if (!((T1z.used == 1) && (T1z.dp[0] == 1u))) goto LBL_FU_ERR;
4078
4079 ap2 = a + 2;
4080 if ((err = mp_add_d(N, 1uL, &Np1z)) != MP_OKAY) goto LBL_FU_ERR;
4081
4082 mp_set(&sz, 1uL);
4083 mp_set(&tz, 2uL);
4084 length = mp_count_bits(&Np1z);
4085
4086 for (i = length - 2; i >= 0; i--) {
4087 /*
4088 * temp = (sz*(a*sz+2*tz))%N;
4089 * tz = ((tz-sz)*(tz+sz))%N;
4090 * sz = temp;
4091 */
4092 if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_FU_ERR;
4093
4094 /* a = 0 at about 50% of the cases (non-square and odd input) */
4095 if (a != 0) {
4096 if ((err = mp_mul_d(&sz, (mp_digit)a, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
4097 if ((err = mp_add(&T1z, &T2z, &T2z)) != MP_OKAY) goto LBL_FU_ERR;
4098 }
4099
4100 if ((err = mp_mul(&T2z, &sz, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
4101 if ((err = mp_sub(&tz, &sz, &T2z)) != MP_OKAY) goto LBL_FU_ERR;
4102 if ((err = mp_add(&sz, &tz, &sz)) != MP_OKAY) goto LBL_FU_ERR;
4103 if ((err = mp_mul(&sz, &T2z, &tz)) != MP_OKAY) goto LBL_FU_ERR;
4104 if ((err = mp_mod(&tz, N, &tz)) != MP_OKAY) goto LBL_FU_ERR;
4105 if ((err = mp_mod(&T1z, N, &sz)) != MP_OKAY) goto LBL_FU_ERR;
4106 if (s_mp_get_bit(&Np1z, (unsigned int)i) == MP_YES) {
4107 /*
4108 * temp = (a+2) * sz + tz
4109 * tz = 2 * tz - sz
4110 * sz = temp
4111 */
4112 if (a == 0) {
4113 if ((err = mp_mul_2(&sz, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
4114 } else {
4115 if ((err = mp_mul_d(&sz, (mp_digit)ap2, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
4116 }
4117 if ((err = mp_add(&T1z, &tz, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
4118 if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_FU_ERR;
4119 if ((err = mp_sub(&T2z, &sz, &tz)) != MP_OKAY) goto LBL_FU_ERR;
4120 mp_exch(&sz, &T1z);
4121 }
4122 }
4123
4124 mp_set_u32(&T1z, (uint32_t)((2 * a) + 5));
4125 if ((err = mp_mod(&T1z, N, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
4126 if (MP_IS_ZERO(&sz) && (mp_cmp(&tz, &T1z) == MP_EQ)) {
4127 *result = MP_YES;
4128 }
4129
4130 LBL_FU_ERR:
4131 mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, NULL);
4132 return err;
4133 }
4134
4135 #endif
4136 #endif
4137
4138 /* End: bn_mp_prime_frobenius_underwood.c */
4139
4140 /* Start: bn_mp_prime_is_prime.c */
4141 #include "tommath_private.h"
4142 #ifdef BN_MP_PRIME_IS_PRIME_C
4143 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4144 /* SPDX-License-Identifier: Unlicense */
4145
4146 /* portable integer log of two with small footprint */
s_floor_ilog2(int value)4147 static unsigned int s_floor_ilog2(int value)
4148 {
4149 unsigned int r = 0;
4150 while ((value >>= 1) != 0) {
4151 r++;
4152 }
4153 return r;
4154 }
4155
4156
mp_prime_is_prime(const mp_int * a,int t,mp_bool * result)4157 mp_err mp_prime_is_prime(const mp_int *a, int t, mp_bool *result)
4158 {
4159 mp_int b;
4160 int ix, p_max = 0, size_a, len;
4161 mp_bool res;
4162 mp_err err;
4163 unsigned int fips_rand, mask;
4164
4165 /* default to no */
4166 *result = MP_NO;
4167
4168 /* Some shortcuts */
4169 /* N > 3 */
4170 if (a->used == 1) {
4171 if ((a->dp[0] == 0u) || (a->dp[0] == 1u)) {
4172 *result = MP_NO;
4173 return MP_OKAY;
4174 }
4175 if (a->dp[0] == 2u) {
4176 *result = MP_YES;
4177 return MP_OKAY;
4178 }
4179 }
4180
4181 /* N must be odd */
4182 if (MP_IS_EVEN(a)) {
4183 return MP_OKAY;
4184 }
4185 /* N is not a perfect square: floor(sqrt(N))^2 != N */
4186 if ((err = mp_is_square(a, &res)) != MP_OKAY) {
4187 return err;
4188 }
4189 if (res != MP_NO) {
4190 return MP_OKAY;
4191 }
4192
4193 /* is the input equal to one of the primes in the table? */
4194 for (ix = 0; ix < PRIVATE_MP_PRIME_TAB_SIZE; ix++) {
4195 if (mp_cmp_d(a, s_mp_prime_tab[ix]) == MP_EQ) {
4196 *result = MP_YES;
4197 return MP_OKAY;
4198 }
4199 }
4200 #ifdef MP_8BIT
4201 /* The search in the loop above was exhaustive in this case */
4202 if ((a->used == 1) && (PRIVATE_MP_PRIME_TAB_SIZE >= 31)) {
4203 return MP_OKAY;
4204 }
4205 #endif
4206
4207 /* first perform trial division */
4208 if ((err = s_mp_prime_is_divisible(a, &res)) != MP_OKAY) {
4209 return err;
4210 }
4211
4212 /* return if it was trivially divisible */
4213 if (res == MP_YES) {
4214 return MP_OKAY;
4215 }
4216
4217 /*
4218 Run the Miller-Rabin test with base 2 for the BPSW test.
4219 */
4220 if ((err = mp_init_set(&b, 2uL)) != MP_OKAY) {
4221 return err;
4222 }
4223
4224 if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
4225 goto LBL_B;
4226 }
4227 if (res == MP_NO) {
4228 goto LBL_B;
4229 }
4230 /*
4231 Rumours have it that Mathematica does a second M-R test with base 3.
4232 Other rumours have it that their strong L-S test is slightly different.
4233 It does not hurt, though, beside a bit of extra runtime.
4234 */
4235 b.dp[0]++;
4236 if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
4237 goto LBL_B;
4238 }
4239 if (res == MP_NO) {
4240 goto LBL_B;
4241 }
4242
4243 /*
4244 * Both, the Frobenius-Underwood test and the the Lucas-Selfridge test are quite
4245 * slow so if speed is an issue, define LTM_USE_ONLY_MR to use M-R tests with
4246 * bases 2, 3 and t random bases.
4247 */
4248 #ifndef LTM_USE_ONLY_MR
4249 if (t >= 0) {
4250 /*
4251 * Use a Frobenius-Underwood test instead of the Lucas-Selfridge test for
4252 * MP_8BIT (It is unknown if the Lucas-Selfridge test works with 16-bit
4253 * integers but the necesssary analysis is on the todo-list).
4254 */
4255 #if defined (MP_8BIT) || defined (LTM_USE_FROBENIUS_TEST)
4256 err = mp_prime_frobenius_underwood(a, &res);
4257 if ((err != MP_OKAY) && (err != MP_ITER)) {
4258 goto LBL_B;
4259 }
4260 if (res == MP_NO) {
4261 goto LBL_B;
4262 }
4263 #else
4264 if ((err = mp_prime_strong_lucas_selfridge(a, &res)) != MP_OKAY) {
4265 goto LBL_B;
4266 }
4267 if (res == MP_NO) {
4268 goto LBL_B;
4269 }
4270 #endif
4271 }
4272 #endif
4273
4274 /* run at least one Miller-Rabin test with a random base */
4275 if (t == 0) {
4276 t = 1;
4277 }
4278
4279 /*
4280 Only recommended if the input range is known to be < 3317044064679887385961981
4281
4282 It uses the bases necessary for a deterministic M-R test if the input is
4283 smaller than 3317044064679887385961981
4284 The caller has to check the size.
4285 TODO: can be made a bit finer grained but comparing is not free.
4286 */
4287 if (t < 0) {
4288 /*
4289 Sorenson, Jonathan; Webster, Jonathan (2015).
4290 "Strong Pseudoprimes to Twelve Prime Bases".
4291 */
4292 /* 0x437ae92817f9fc85b7e5 = 318665857834031151167461 */
4293 if ((err = mp_read_radix(&b, "437ae92817f9fc85b7e5", 16)) != MP_OKAY) {
4294 goto LBL_B;
4295 }
4296
4297 if (mp_cmp(a, &b) == MP_LT) {
4298 p_max = 12;
4299 } else {
4300 /* 0x2be6951adc5b22410a5fd = 3317044064679887385961981 */
4301 if ((err = mp_read_radix(&b, "2be6951adc5b22410a5fd", 16)) != MP_OKAY) {
4302 goto LBL_B;
4303 }
4304
4305 if (mp_cmp(a, &b) == MP_LT) {
4306 p_max = 13;
4307 } else {
4308 err = MP_VAL;
4309 goto LBL_B;
4310 }
4311 }
4312
4313 /* we did bases 2 and 3 already, skip them */
4314 for (ix = 2; ix < p_max; ix++) {
4315 mp_set(&b, s_mp_prime_tab[ix]);
4316 if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
4317 goto LBL_B;
4318 }
4319 if (res == MP_NO) {
4320 goto LBL_B;
4321 }
4322 }
4323 }
4324 /*
4325 Do "t" M-R tests with random bases between 3 and "a".
4326 See Fips 186.4 p. 126ff
4327 */
4328 else if (t > 0) {
4329 /*
4330 * The mp_digit's have a defined bit-size but the size of the
4331 * array a.dp is a simple 'int' and this library can not assume full
4332 * compliance to the current C-standard (ISO/IEC 9899:2011) because
4333 * it gets used for small embeded processors, too. Some of those MCUs
4334 * have compilers that one cannot call standard compliant by any means.
4335 * Hence the ugly type-fiddling in the following code.
4336 */
4337 size_a = mp_count_bits(a);
4338 mask = (1u << s_floor_ilog2(size_a)) - 1u;
4339 /*
4340 Assuming the General Rieman hypothesis (never thought to write that in a
4341 comment) the upper bound can be lowered to 2*(log a)^2.
4342 E. Bach, "Explicit bounds for primality testing and related problems,"
4343 Math. Comp. 55 (1990), 355-380.
4344
4345 size_a = (size_a/10) * 7;
4346 len = 2 * (size_a * size_a);
4347
4348 E.g.: a number of size 2^2048 would be reduced to the upper limit
4349
4350 floor(2048/10)*7 = 1428
4351 2 * 1428^2 = 4078368
4352
4353 (would have been ~4030331.9962 with floats and natural log instead)
4354 That number is smaller than 2^28, the default bit-size of mp_digit.
4355 */
4356
4357 /*
4358 How many tests, you might ask? Dana Jacobsen of Math::Prime::Util fame
4359 does exactly 1. In words: one. Look at the end of _GMP_is_prime() in
4360 Math-Prime-Util-GMP-0.50/primality.c if you do not believe it.
4361
4362 The function mp_rand() goes to some length to use a cryptographically
4363 good PRNG. That also means that the chance to always get the same base
4364 in the loop is non-zero, although very low.
4365 If the BPSW test and/or the addtional Frobenious test have been
4366 performed instead of just the Miller-Rabin test with the bases 2 and 3,
4367 a single extra test should suffice, so such a very unlikely event
4368 will not do much harm.
4369
4370 To preemptivly answer the dangling question: no, a witness does not
4371 need to be prime.
4372 */
4373 for (ix = 0; ix < t; ix++) {
4374 /* mp_rand() guarantees the first digit to be non-zero */
4375 if ((err = mp_rand(&b, 1)) != MP_OKAY) {
4376 goto LBL_B;
4377 }
4378 /*
4379 * Reduce digit before casting because mp_digit might be bigger than
4380 * an unsigned int and "mask" on the other side is most probably not.
4381 */
4382 fips_rand = (unsigned int)(b.dp[0] & (mp_digit) mask);
4383 #ifdef MP_8BIT
4384 /*
4385 * One 8-bit digit is too small, so concatenate two if the size of
4386 * unsigned int allows for it.
4387 */
4388 if ((MP_SIZEOF_BITS(unsigned int)/2) >= MP_SIZEOF_BITS(mp_digit)) {
4389 if ((err = mp_rand(&b, 1)) != MP_OKAY) {
4390 goto LBL_B;
4391 }
4392 fips_rand <<= MP_SIZEOF_BITS(mp_digit);
4393 fips_rand |= (unsigned int) b.dp[0];
4394 fips_rand &= mask;
4395 }
4396 #endif
4397 if (fips_rand > (unsigned int)(INT_MAX - MP_DIGIT_BIT)) {
4398 len = INT_MAX / MP_DIGIT_BIT;
4399 } else {
4400 len = (((int)fips_rand + MP_DIGIT_BIT) / MP_DIGIT_BIT);
4401 }
4402 /* Unlikely. */
4403 if (len < 0) {
4404 ix--;
4405 continue;
4406 }
4407 /*
4408 * As mentioned above, one 8-bit digit is too small and
4409 * although it can only happen in the unlikely case that
4410 * an "unsigned int" is smaller than 16 bit a simple test
4411 * is cheap and the correction even cheaper.
4412 */
4413 #ifdef MP_8BIT
4414 /* All "a" < 2^8 have been caught before */
4415 if (len == 1) {
4416 len++;
4417 }
4418 #endif
4419 if ((err = mp_rand(&b, len)) != MP_OKAY) {
4420 goto LBL_B;
4421 }
4422 /*
4423 * That number might got too big and the witness has to be
4424 * smaller than "a"
4425 */
4426 len = mp_count_bits(&b);
4427 if (len >= size_a) {
4428 len = (len - size_a) + 1;
4429 if ((err = mp_div_2d(&b, len, &b, NULL)) != MP_OKAY) {
4430 goto LBL_B;
4431 }
4432 }
4433 /* Although the chance for b <= 3 is miniscule, try again. */
4434 if (mp_cmp_d(&b, 3uL) != MP_GT) {
4435 ix--;
4436 continue;
4437 }
4438 if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
4439 goto LBL_B;
4440 }
4441 if (res == MP_NO) {
4442 goto LBL_B;
4443 }
4444 }
4445 }
4446
4447 /* passed the test */
4448 *result = MP_YES;
4449 LBL_B:
4450 mp_clear(&b);
4451 return err;
4452 }
4453
4454 #endif
4455
4456 /* End: bn_mp_prime_is_prime.c */
4457
4458 /* Start: bn_mp_prime_miller_rabin.c */
4459 #include "tommath_private.h"
4460 #ifdef BN_MP_PRIME_MILLER_RABIN_C
4461 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4462 /* SPDX-License-Identifier: Unlicense */
4463
4464 /* Miller-Rabin test of "a" to the base of "b" as described in
4465 * HAC pp. 139 Algorithm 4.24
4466 *
4467 * Sets result to 0 if definitely composite or 1 if probably prime.
4468 * Randomly the chance of error is no more than 1/4 and often
4469 * very much lower.
4470 */
mp_prime_miller_rabin(const mp_int * a,const mp_int * b,mp_bool * result)4471 mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, mp_bool *result)
4472 {
4473 mp_int n1, y, r;
4474 mp_err err;
4475 int s, j;
4476
4477 /* default */
4478 *result = MP_NO;
4479
4480 /* ensure b > 1 */
4481 if (mp_cmp_d(b, 1uL) != MP_GT) {
4482 return MP_VAL;
4483 }
4484
4485 /* get n1 = a - 1 */
4486 if ((err = mp_init_copy(&n1, a)) != MP_OKAY) {
4487 return err;
4488 }
4489 if ((err = mp_sub_d(&n1, 1uL, &n1)) != MP_OKAY) {
4490 goto LBL_N1;
4491 }
4492
4493 /* set 2**s * r = n1 */
4494 if ((err = mp_init_copy(&r, &n1)) != MP_OKAY) {
4495 goto LBL_N1;
4496 }
4497
4498 /* count the number of least significant bits
4499 * which are zero
4500 */
4501 s = mp_cnt_lsb(&r);
4502
4503 /* now divide n - 1 by 2**s */
4504 if ((err = mp_div_2d(&r, s, &r, NULL)) != MP_OKAY) {
4505 goto LBL_R;
4506 }
4507
4508 /* compute y = b**r mod a */
4509 if ((err = mp_init(&y)) != MP_OKAY) {
4510 goto LBL_R;
4511 }
4512 if ((err = mp_exptmod(b, &r, a, &y)) != MP_OKAY) {
4513 goto LBL_Y;
4514 }
4515
4516 /* if y != 1 and y != n1 do */
4517 if ((mp_cmp_d(&y, 1uL) != MP_EQ) && (mp_cmp(&y, &n1) != MP_EQ)) {
4518 j = 1;
4519 /* while j <= s-1 and y != n1 */
4520 while ((j <= (s - 1)) && (mp_cmp(&y, &n1) != MP_EQ)) {
4521 if ((err = mp_sqrmod(&y, a, &y)) != MP_OKAY) {
4522 goto LBL_Y;
4523 }
4524
4525 /* if y == 1 then composite */
4526 if (mp_cmp_d(&y, 1uL) == MP_EQ) {
4527 goto LBL_Y;
4528 }
4529
4530 ++j;
4531 }
4532
4533 /* if y != n1 then composite */
4534 if (mp_cmp(&y, &n1) != MP_EQ) {
4535 goto LBL_Y;
4536 }
4537 }
4538
4539 /* probably prime now */
4540 *result = MP_YES;
4541 LBL_Y:
4542 mp_clear(&y);
4543 LBL_R:
4544 mp_clear(&r);
4545 LBL_N1:
4546 mp_clear(&n1);
4547 return err;
4548 }
4549 #endif
4550
4551 /* End: bn_mp_prime_miller_rabin.c */
4552
4553 /* Start: bn_mp_prime_next_prime.c */
4554 #include "tommath_private.h"
4555 #ifdef BN_MP_PRIME_NEXT_PRIME_C
4556 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4557 /* SPDX-License-Identifier: Unlicense */
4558
4559 /* finds the next prime after the number "a" using "t" trials
4560 * of Miller-Rabin.
4561 *
4562 * bbs_style = 1 means the prime must be congruent to 3 mod 4
4563 */
mp_prime_next_prime(mp_int * a,int t,int bbs_style)4564 mp_err mp_prime_next_prime(mp_int *a, int t, int bbs_style)
4565 {
4566 int x, y;
4567 mp_ord cmp;
4568 mp_err err;
4569 mp_bool res = MP_NO;
4570 mp_digit res_tab[PRIVATE_MP_PRIME_TAB_SIZE], step, kstep;
4571 mp_int b;
4572
4573 /* force positive */
4574 a->sign = MP_ZPOS;
4575
4576 /* simple algo if a is less than the largest prime in the table */
4577 if (mp_cmp_d(a, s_mp_prime_tab[PRIVATE_MP_PRIME_TAB_SIZE-1]) == MP_LT) {
4578 /* find which prime it is bigger than "a" */
4579 for (x = 0; x < PRIVATE_MP_PRIME_TAB_SIZE; x++) {
4580 cmp = mp_cmp_d(a, s_mp_prime_tab[x]);
4581 if (cmp == MP_EQ) {
4582 continue;
4583 }
4584 if (cmp != MP_GT) {
4585 if ((bbs_style == 1) && ((s_mp_prime_tab[x] & 3u) != 3u)) {
4586 /* try again until we get a prime congruent to 3 mod 4 */
4587 continue;
4588 } else {
4589 mp_set(a, s_mp_prime_tab[x]);
4590 return MP_OKAY;
4591 }
4592 }
4593 }
4594 /* fall through to the sieve */
4595 }
4596
4597 /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
4598 if (bbs_style == 1) {
4599 kstep = 4;
4600 } else {
4601 kstep = 2;
4602 }
4603
4604 /* at this point we will use a combination of a sieve and Miller-Rabin */
4605
4606 if (bbs_style == 1) {
4607 /* if a mod 4 != 3 subtract the correct value to make it so */
4608 if ((a->dp[0] & 3u) != 3u) {
4609 if ((err = mp_sub_d(a, (a->dp[0] & 3u) + 1u, a)) != MP_OKAY) {
4610 return err;
4611 }
4612 }
4613 } else {
4614 if (MP_IS_EVEN(a)) {
4615 /* force odd */
4616 if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) {
4617 return err;
4618 }
4619 }
4620 }
4621
4622 /* generate the restable */
4623 for (x = 1; x < PRIVATE_MP_PRIME_TAB_SIZE; x++) {
4624 if ((err = mp_mod_d(a, s_mp_prime_tab[x], res_tab + x)) != MP_OKAY) {
4625 return err;
4626 }
4627 }
4628
4629 /* init temp used for Miller-Rabin Testing */
4630 if ((err = mp_init(&b)) != MP_OKAY) {
4631 return err;
4632 }
4633
4634 for (;;) {
4635 /* skip to the next non-trivially divisible candidate */
4636 step = 0;
4637 do {
4638 /* y == 1 if any residue was zero [e.g. cannot be prime] */
4639 y = 0;
4640
4641 /* increase step to next candidate */
4642 step += kstep;
4643
4644 /* compute the new residue without using division */
4645 for (x = 1; x < PRIVATE_MP_PRIME_TAB_SIZE; x++) {
4646 /* add the step to each residue */
4647 res_tab[x] += kstep;
4648
4649 /* subtract the modulus [instead of using division] */
4650 if (res_tab[x] >= s_mp_prime_tab[x]) {
4651 res_tab[x] -= s_mp_prime_tab[x];
4652 }
4653
4654 /* set flag if zero */
4655 if (res_tab[x] == 0u) {
4656 y = 1;
4657 }
4658 }
4659 } while ((y == 1) && (step < (((mp_digit)1 << MP_DIGIT_BIT) - kstep)));
4660
4661 /* add the step */
4662 if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
4663 goto LBL_ERR;
4664 }
4665
4666 /* if didn't pass sieve and step == MP_MAX then skip test */
4667 if ((y == 1) && (step >= (((mp_digit)1 << MP_DIGIT_BIT) - kstep))) {
4668 continue;
4669 }
4670
4671 if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
4672 goto LBL_ERR;
4673 }
4674 if (res == MP_YES) {
4675 break;
4676 }
4677 }
4678
4679 err = MP_OKAY;
4680 LBL_ERR:
4681 mp_clear(&b);
4682 return err;
4683 }
4684
4685 #endif
4686
4687 /* End: bn_mp_prime_next_prime.c */
4688
4689 /* Start: bn_mp_prime_rabin_miller_trials.c */
4690 #include "tommath_private.h"
4691 #ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
4692 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4693 /* SPDX-License-Identifier: Unlicense */
4694
4695 static const struct {
4696 int k, t;
4697 } sizes[] = {
4698 { 80, -1 }, /* Use deterministic algorithm for size <= 80 bits */
4699 { 81, 37 }, /* max. error = 2^(-96)*/
4700 { 96, 32 }, /* max. error = 2^(-96)*/
4701 { 128, 40 }, /* max. error = 2^(-112)*/
4702 { 160, 35 }, /* max. error = 2^(-112)*/
4703 { 256, 27 }, /* max. error = 2^(-128)*/
4704 { 384, 16 }, /* max. error = 2^(-128)*/
4705 { 512, 18 }, /* max. error = 2^(-160)*/
4706 { 768, 11 }, /* max. error = 2^(-160)*/
4707 { 896, 10 }, /* max. error = 2^(-160)*/
4708 { 1024, 12 }, /* max. error = 2^(-192)*/
4709 { 1536, 8 }, /* max. error = 2^(-192)*/
4710 { 2048, 6 }, /* max. error = 2^(-192)*/
4711 { 3072, 4 }, /* max. error = 2^(-192)*/
4712 { 4096, 5 }, /* max. error = 2^(-256)*/
4713 { 5120, 4 }, /* max. error = 2^(-256)*/
4714 { 6144, 4 }, /* max. error = 2^(-256)*/
4715 { 8192, 3 }, /* max. error = 2^(-256)*/
4716 { 9216, 3 }, /* max. error = 2^(-256)*/
4717 { 10240, 2 } /* For bigger keysizes use always at least 2 Rounds */
4718 };
4719
4720 /* returns # of RM trials required for a given bit size */
mp_prime_rabin_miller_trials(int size)4721 int mp_prime_rabin_miller_trials(int size)
4722 {
4723 int x;
4724
4725 for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
4726 if (sizes[x].k == size) {
4727 return sizes[x].t;
4728 } else if (sizes[x].k > size) {
4729 return (x == 0) ? sizes[0].t : sizes[x - 1].t;
4730 }
4731 }
4732 return sizes[x-1].t;
4733 }
4734
4735
4736 #endif
4737
4738 /* End: bn_mp_prime_rabin_miller_trials.c */
4739
4740 /* Start: bn_mp_prime_rand.c */
4741 #include "tommath_private.h"
4742 #ifdef BN_MP_PRIME_RAND_C
4743 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4744 /* SPDX-License-Identifier: Unlicense */
4745
4746 /* makes a truly random prime of a given size (bits),
4747 *
4748 * Flags are as follows:
4749 *
4750 * MP_PRIME_BBS - make prime congruent to 3 mod 4
4751 * MP_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS)
4752 * MP_PRIME_2MSB_ON - make the 2nd highest bit one
4753 *
4754 * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
4755 * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
4756 * so it can be NULL
4757 *
4758 */
4759
4760 /* This is possibly the mother of all prime generation functions, muahahahahaha! */
s_mp_prime_random_ex(mp_int * a,int t,int size,int flags,private_mp_prime_callback cb,void * dat)4761 mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat)
4762 {
4763 unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
4764 int bsize, maskOR_msb_offset;
4765 mp_bool res;
4766 mp_err err;
4767
4768 /* sanity check the input */
4769 if ((size <= 1) || (t <= 0)) {
4770 return MP_VAL;
4771 }
4772
4773 /* MP_PRIME_SAFE implies MP_PRIME_BBS */
4774 if ((flags & MP_PRIME_SAFE) != 0) {
4775 flags |= MP_PRIME_BBS;
4776 }
4777
4778 /* calc the byte size */
4779 bsize = (size>>3) + ((size&7)?1:0);
4780
4781 /* we need a buffer of bsize bytes */
4782 tmp = (unsigned char *) MP_MALLOC((size_t)bsize);
4783 if (tmp == NULL) {
4784 return MP_MEM;
4785 }
4786
4787 /* calc the maskAND value for the MSbyte*/
4788 maskAND = ((size&7) == 0) ? 0xFFu : (unsigned char)(0xFFu >> (8 - (size & 7)));
4789
4790 /* calc the maskOR_msb */
4791 maskOR_msb = 0;
4792 maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
4793 if ((flags & MP_PRIME_2MSB_ON) != 0) {
4794 maskOR_msb |= (unsigned char)(0x80 >> ((9 - size) & 7));
4795 }
4796
4797 /* get the maskOR_lsb */
4798 maskOR_lsb = 1u;
4799 if ((flags & MP_PRIME_BBS) != 0) {
4800 maskOR_lsb |= 3u;
4801 }
4802
4803 do {
4804 /* read the bytes */
4805 if (cb(tmp, bsize, dat) != bsize) {
4806 err = MP_VAL;
4807 goto error;
4808 }
4809
4810 /* work over the MSbyte */
4811 tmp[0] &= maskAND;
4812 tmp[0] |= (unsigned char)(1 << ((size - 1) & 7));
4813
4814 /* mix in the maskORs */
4815 tmp[maskOR_msb_offset] |= maskOR_msb;
4816 tmp[bsize-1] |= maskOR_lsb;
4817
4818 /* read it in */
4819 /* TODO: casting only for now until all lengths have been changed to the type "size_t"*/
4820 if ((err = mp_from_ubin(a, tmp, (size_t)bsize)) != MP_OKAY) {
4821 goto error;
4822 }
4823
4824 /* is it prime? */
4825 if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
4826 goto error;
4827 }
4828 if (res == MP_NO) {
4829 continue;
4830 }
4831
4832 if ((flags & MP_PRIME_SAFE) != 0) {
4833 /* see if (a-1)/2 is prime */
4834 if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) {
4835 goto error;
4836 }
4837 if ((err = mp_div_2(a, a)) != MP_OKAY) {
4838 goto error;
4839 }
4840
4841 /* is it prime? */
4842 if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
4843 goto error;
4844 }
4845 }
4846 } while (res == MP_NO);
4847
4848 if ((flags & MP_PRIME_SAFE) != 0) {
4849 /* restore a to the original value */
4850 if ((err = mp_mul_2(a, a)) != MP_OKAY) {
4851 goto error;
4852 }
4853 if ((err = mp_add_d(a, 1uL, a)) != MP_OKAY) {
4854 goto error;
4855 }
4856 }
4857
4858 err = MP_OKAY;
4859 error:
4860 MP_FREE_BUFFER(tmp, (size_t)bsize);
4861 return err;
4862 }
4863
s_mp_rand_cb(unsigned char * dst,int len,void * dat)4864 static int s_mp_rand_cb(unsigned char *dst, int len, void *dat)
4865 {
4866 (void)dat;
4867 if (len <= 0) {
4868 return len;
4869 }
4870 if (s_mp_rand_source(dst, (size_t)len) != MP_OKAY) {
4871 return 0;
4872 }
4873 return len;
4874 }
4875
mp_prime_rand(mp_int * a,int t,int size,int flags)4876 mp_err mp_prime_rand(mp_int *a, int t, int size, int flags)
4877 {
4878 return s_mp_prime_random_ex(a, t, size, flags, s_mp_rand_cb, NULL);
4879 }
4880
4881 #endif
4882
4883 /* End: bn_mp_prime_rand.c */
4884
4885 /* Start: bn_mp_prime_strong_lucas_selfridge.c */
4886 #include "tommath_private.h"
4887 #ifdef BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_C
4888
4889 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4890 /* SPDX-License-Identifier: Unlicense */
4891
4892 /*
4893 * See file bn_mp_prime_is_prime.c or the documentation in doc/bn.tex for the details
4894 */
4895 #ifndef LTM_USE_ONLY_MR
4896
4897 /*
4898 * 8-bit is just too small. You can try the Frobenius test
4899 * but that frobenius test can fail, too, for the same reason.
4900 */
4901 #ifndef MP_8BIT
4902
4903 /*
4904 * multiply bigint a with int d and put the result in c
4905 * Like mp_mul_d() but with a signed long as the small input
4906 */
s_mp_mul_si(const mp_int * a,int32_t d,mp_int * c)4907 static mp_err s_mp_mul_si(const mp_int *a, int32_t d, mp_int *c)
4908 {
4909 mp_int t;
4910 mp_err err;
4911
4912 if ((err = mp_init(&t)) != MP_OKAY) {
4913 return err;
4914 }
4915
4916 /*
4917 * mp_digit might be smaller than a long, which excludes
4918 * the use of mp_mul_d() here.
4919 */
4920 mp_set_i32(&t, d);
4921 err = mp_mul(a, &t, c);
4922 mp_clear(&t);
4923 return err;
4924 }
4925 /*
4926 Strong Lucas-Selfridge test.
4927 returns MP_YES if it is a strong L-S prime, MP_NO if it is composite
4928
4929 Code ported from Thomas Ray Nicely's implementation of the BPSW test
4930 at http://www.trnicely.net/misc/bpsw.html
4931
4932 Freeware copyright (C) 2016 Thomas R. Nicely <http://www.trnicely.net>.
4933 Released into the public domain by the author, who disclaims any legal
4934 liability arising from its use
4935
4936 The multi-line comments are made by Thomas R. Nicely and are copied verbatim.
4937 Additional comments marked "CZ" (without the quotes) are by the code-portist.
4938
4939 (If that name sounds familiar, he is the guy who found the fdiv bug in the
4940 Pentium (P5x, I think) Intel processor)
4941 */
mp_prime_strong_lucas_selfridge(const mp_int * a,mp_bool * result)4942 mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, mp_bool *result)
4943 {
4944 /* CZ TODO: choose better variable names! */
4945 mp_int Dz, gcd, Np1, Uz, Vz, U2mz, V2mz, Qmz, Q2mz, Qkdz, T1z, T2z, T3z, T4z, Q2kdz;
4946 /* CZ TODO: Some of them need the full 32 bit, hence the (temporary) exclusion of MP_8BIT */
4947 int32_t D, Ds, J, sign, P, Q, r, s, u, Nbits;
4948 mp_err err;
4949 mp_bool oddness;
4950
4951 *result = MP_NO;
4952 /*
4953 Find the first element D in the sequence {5, -7, 9, -11, 13, ...}
4954 such that Jacobi(D,N) = -1 (Selfridge's algorithm). Theory
4955 indicates that, if N is not a perfect square, D will "nearly
4956 always" be "small." Just in case, an overflow trap for D is
4957 included.
4958 */
4959
4960 if ((err = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz,
4961 NULL)) != MP_OKAY) {
4962 return err;
4963 }
4964
4965 D = 5;
4966 sign = 1;
4967
4968 for (;;) {
4969 Ds = sign * D;
4970 sign = -sign;
4971 mp_set_u32(&Dz, (uint32_t)D);
4972 if ((err = mp_gcd(a, &Dz, &gcd)) != MP_OKAY) goto LBL_LS_ERR;
4973
4974 /* if 1 < GCD < N then N is composite with factor "D", and
4975 Jacobi(D,N) is technically undefined (but often returned
4976 as zero). */
4977 if ((mp_cmp_d(&gcd, 1uL) == MP_GT) && (mp_cmp(&gcd, a) == MP_LT)) {
4978 goto LBL_LS_ERR;
4979 }
4980 if (Ds < 0) {
4981 Dz.sign = MP_NEG;
4982 }
4983 if ((err = mp_kronecker(&Dz, a, &J)) != MP_OKAY) goto LBL_LS_ERR;
4984
4985 if (J == -1) {
4986 break;
4987 }
4988 D += 2;
4989
4990 if (D > (INT_MAX - 2)) {
4991 err = MP_VAL;
4992 goto LBL_LS_ERR;
4993 }
4994 }
4995
4996
4997
4998 P = 1; /* Selfridge's choice */
4999 Q = (1 - Ds) / 4; /* Required so D = P*P - 4*Q */
5000
5001 /* NOTE: The conditions (a) N does not divide Q, and
5002 (b) D is square-free or not a perfect square, are included by
5003 some authors; e.g., "Prime numbers and computer methods for
5004 factorization," Hans Riesel (2nd ed., 1994, Birkhauser, Boston),
5005 p. 130. For this particular application of Lucas sequences,
5006 these conditions were found to be immaterial. */
5007
5008 /* Now calculate N - Jacobi(D,N) = N + 1 (even), and calculate the
5009 odd positive integer d and positive integer s for which
5010 N + 1 = 2^s*d (similar to the step for N - 1 in Miller's test).
5011 The strong Lucas-Selfridge test then returns N as a strong
5012 Lucas probable prime (slprp) if any of the following
5013 conditions is met: U_d=0, V_d=0, V_2d=0, V_4d=0, V_8d=0,
5014 V_16d=0, ..., etc., ending with V_{2^(s-1)*d}=V_{(N+1)/2}=0
5015 (all equalities mod N). Thus d is the highest index of U that
5016 must be computed (since V_2m is independent of U), compared
5017 to U_{N+1} for the standard Lucas-Selfridge test; and no
5018 index of V beyond (N+1)/2 is required, just as in the
5019 standard Lucas-Selfridge test. However, the quantity Q^d must
5020 be computed for use (if necessary) in the latter stages of
5021 the test. The result is that the strong Lucas-Selfridge test
5022 has a running time only slightly greater (order of 10 %) than
5023 that of the standard Lucas-Selfridge test, while producing
5024 only (roughly) 30 % as many pseudoprimes (and every strong
5025 Lucas pseudoprime is also a standard Lucas pseudoprime). Thus
5026 the evidence indicates that the strong Lucas-Selfridge test is
5027 more effective than the standard Lucas-Selfridge test, and a
5028 Baillie-PSW test based on the strong Lucas-Selfridge test
5029 should be more reliable. */
5030
5031 if ((err = mp_add_d(a, 1uL, &Np1)) != MP_OKAY) goto LBL_LS_ERR;
5032 s = mp_cnt_lsb(&Np1);
5033
5034 /* CZ
5035 * This should round towards zero because
5036 * Thomas R. Nicely used GMP's mpz_tdiv_q_2exp()
5037 * and mp_div_2d() is equivalent. Additionally:
5038 * dividing an even number by two does not produce
5039 * any leftovers.
5040 */
5041 if ((err = mp_div_2d(&Np1, s, &Dz, NULL)) != MP_OKAY) goto LBL_LS_ERR;
5042 /* We must now compute U_d and V_d. Since d is odd, the accumulated
5043 values U and V are initialized to U_1 and V_1 (if the target
5044 index were even, U and V would be initialized instead to U_0=0
5045 and V_0=2). The values of U_2m and V_2m are also initialized to
5046 U_1 and V_1; the FOR loop calculates in succession U_2 and V_2,
5047 U_4 and V_4, U_8 and V_8, etc. If the corresponding bits
5048 (1, 2, 3, ...) of t are on (the zero bit having been accounted
5049 for in the initialization of U and V), these values are then
5050 combined with the previous totals for U and V, using the
5051 composition formulas for addition of indices. */
5052
5053 mp_set(&Uz, 1uL); /* U=U_1 */
5054 mp_set(&Vz, (mp_digit)P); /* V=V_1 */
5055 mp_set(&U2mz, 1uL); /* U_1 */
5056 mp_set(&V2mz, (mp_digit)P); /* V_1 */
5057
5058 mp_set_i32(&Qmz, Q);
5059 if ((err = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) goto LBL_LS_ERR;
5060 /* Initializes calculation of Q^d */
5061 mp_set_i32(&Qkdz, Q);
5062
5063 Nbits = mp_count_bits(&Dz);
5064
5065 for (u = 1; u < Nbits; u++) { /* zero bit off, already accounted for */
5066 /* Formulas for doubling of indices (carried out mod N). Note that
5067 * the indices denoted as "2m" are actually powers of 2, specifically
5068 * 2^(ul-1) beginning each loop and 2^ul ending each loop.
5069 *
5070 * U_2m = U_m*V_m
5071 * V_2m = V_m*V_m - 2*Q^m
5072 */
5073
5074 if ((err = mp_mul(&U2mz, &V2mz, &U2mz)) != MP_OKAY) goto LBL_LS_ERR;
5075 if ((err = mp_mod(&U2mz, a, &U2mz)) != MP_OKAY) goto LBL_LS_ERR;
5076 if ((err = mp_sqr(&V2mz, &V2mz)) != MP_OKAY) goto LBL_LS_ERR;
5077 if ((err = mp_sub(&V2mz, &Q2mz, &V2mz)) != MP_OKAY) goto LBL_LS_ERR;
5078 if ((err = mp_mod(&V2mz, a, &V2mz)) != MP_OKAY) goto LBL_LS_ERR;
5079
5080 /* Must calculate powers of Q for use in V_2m, also for Q^d later */
5081 if ((err = mp_sqr(&Qmz, &Qmz)) != MP_OKAY) goto LBL_LS_ERR;
5082
5083 /* prevents overflow */ /* CZ still necessary without a fixed prealloc'd mem.? */
5084 if ((err = mp_mod(&Qmz, a, &Qmz)) != MP_OKAY) goto LBL_LS_ERR;
5085 if ((err = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) goto LBL_LS_ERR;
5086
5087 if (s_mp_get_bit(&Dz, (unsigned int)u) == MP_YES) {
5088 /* Formulas for addition of indices (carried out mod N);
5089 *
5090 * U_(m+n) = (U_m*V_n + U_n*V_m)/2
5091 * V_(m+n) = (V_m*V_n + D*U_m*U_n)/2
5092 *
5093 * Be careful with division by 2 (mod N)!
5094 */
5095 if ((err = mp_mul(&U2mz, &Vz, &T1z)) != MP_OKAY) goto LBL_LS_ERR;
5096 if ((err = mp_mul(&Uz, &V2mz, &T2z)) != MP_OKAY) goto LBL_LS_ERR;
5097 if ((err = mp_mul(&V2mz, &Vz, &T3z)) != MP_OKAY) goto LBL_LS_ERR;
5098 if ((err = mp_mul(&U2mz, &Uz, &T4z)) != MP_OKAY) goto LBL_LS_ERR;
5099 if ((err = s_mp_mul_si(&T4z, Ds, &T4z)) != MP_OKAY) goto LBL_LS_ERR;
5100 if ((err = mp_add(&T1z, &T2z, &Uz)) != MP_OKAY) goto LBL_LS_ERR;
5101 if (MP_IS_ODD(&Uz)) {
5102 if ((err = mp_add(&Uz, a, &Uz)) != MP_OKAY) goto LBL_LS_ERR;
5103 }
5104 /* CZ
5105 * This should round towards negative infinity because
5106 * Thomas R. Nicely used GMP's mpz_fdiv_q_2exp().
5107 * But mp_div_2() does not do so, it is truncating instead.
5108 */
5109 oddness = MP_IS_ODD(&Uz) ? MP_YES : MP_NO;
5110 if ((err = mp_div_2(&Uz, &Uz)) != MP_OKAY) goto LBL_LS_ERR;
5111 if ((Uz.sign == MP_NEG) && (oddness != MP_NO)) {
5112 if ((err = mp_sub_d(&Uz, 1uL, &Uz)) != MP_OKAY) goto LBL_LS_ERR;
5113 }
5114 if ((err = mp_add(&T3z, &T4z, &Vz)) != MP_OKAY) goto LBL_LS_ERR;
5115 if (MP_IS_ODD(&Vz)) {
5116 if ((err = mp_add(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR;
5117 }
5118 oddness = MP_IS_ODD(&Vz) ? MP_YES : MP_NO;
5119 if ((err = mp_div_2(&Vz, &Vz)) != MP_OKAY) goto LBL_LS_ERR;
5120 if ((Vz.sign == MP_NEG) && (oddness != MP_NO)) {
5121 if ((err = mp_sub_d(&Vz, 1uL, &Vz)) != MP_OKAY) goto LBL_LS_ERR;
5122 }
5123 if ((err = mp_mod(&Uz, a, &Uz)) != MP_OKAY) goto LBL_LS_ERR;
5124 if ((err = mp_mod(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR;
5125
5126 /* Calculating Q^d for later use */
5127 if ((err = mp_mul(&Qkdz, &Qmz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR;
5128 if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR;
5129 }
5130 }
5131
5132 /* If U_d or V_d is congruent to 0 mod N, then N is a prime or a
5133 strong Lucas pseudoprime. */
5134 if (MP_IS_ZERO(&Uz) || MP_IS_ZERO(&Vz)) {
5135 *result = MP_YES;
5136 goto LBL_LS_ERR;
5137 }
5138
5139 /* NOTE: Ribenboim ("The new book of prime number records," 3rd ed.,
5140 1995/6) omits the condition V0 on p.142, but includes it on
5141 p. 130. The condition is NECESSARY; otherwise the test will
5142 return false negatives---e.g., the primes 29 and 2000029 will be
5143 returned as composite. */
5144
5145 /* Otherwise, we must compute V_2d, V_4d, V_8d, ..., V_{2^(s-1)*d}
5146 by repeated use of the formula V_2m = V_m*V_m - 2*Q^m. If any of
5147 these are congruent to 0 mod N, then N is a prime or a strong
5148 Lucas pseudoprime. */
5149
5150 /* Initialize 2*Q^(d*2^r) for V_2m */
5151 if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR;
5152
5153 for (r = 1; r < s; r++) {
5154 if ((err = mp_sqr(&Vz, &Vz)) != MP_OKAY) goto LBL_LS_ERR;
5155 if ((err = mp_sub(&Vz, &Q2kdz, &Vz)) != MP_OKAY) goto LBL_LS_ERR;
5156 if ((err = mp_mod(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR;
5157 if (MP_IS_ZERO(&Vz)) {
5158 *result = MP_YES;
5159 goto LBL_LS_ERR;
5160 }
5161 /* Calculate Q^{d*2^r} for next r (final iteration irrelevant). */
5162 if (r < (s - 1)) {
5163 if ((err = mp_sqr(&Qkdz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR;
5164 if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR;
5165 if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR;
5166 }
5167 }
5168 LBL_LS_ERR:
5169 mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, NULL);
5170 return err;
5171 }
5172 #endif
5173 #endif
5174 #endif
5175
5176 /* End: bn_mp_prime_strong_lucas_selfridge.c */
5177
5178 /* Start: bn_mp_radix_size.c */
5179 #include "tommath_private.h"
5180 #ifdef BN_MP_RADIX_SIZE_C
5181 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5182 /* SPDX-License-Identifier: Unlicense */
5183
5184 /* returns size of ASCII representation */
mp_radix_size(const mp_int * a,int radix,int * size)5185 mp_err mp_radix_size(const mp_int *a, int radix, int *size)
5186 {
5187 mp_err err;
5188 int digs;
5189 mp_int t;
5190 mp_digit d;
5191
5192 *size = 0;
5193
5194 /* make sure the radix is in range */
5195 if ((radix < 2) || (radix > 64)) {
5196 return MP_VAL;
5197 }
5198
5199 if (MP_IS_ZERO(a)) {
5200 *size = 2;
5201 return MP_OKAY;
5202 }
5203
5204 /* special case for binary */
5205 if (radix == 2) {
5206 *size = (mp_count_bits(a) + ((a->sign == MP_NEG) ? 1 : 0) + 1);
5207 return MP_OKAY;
5208 }
5209
5210 /* digs is the digit count */
5211 digs = 0;
5212
5213 /* if it's negative add one for the sign */
5214 if (a->sign == MP_NEG) {
5215 ++digs;
5216 }
5217
5218 /* init a copy of the input */
5219 if ((err = mp_init_copy(&t, a)) != MP_OKAY) {
5220 return err;
5221 }
5222
5223 /* force temp to positive */
5224 t.sign = MP_ZPOS;
5225
5226 /* fetch out all of the digits */
5227 while (!MP_IS_ZERO(&t)) {
5228 if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) {
5229 goto LBL_ERR;
5230 }
5231 ++digs;
5232 }
5233
5234 /* return digs + 1, the 1 is for the NULL byte that would be required. */
5235 *size = digs + 1;
5236 err = MP_OKAY;
5237
5238 LBL_ERR:
5239 mp_clear(&t);
5240 return err;
5241 }
5242
5243 #endif
5244
5245 /* End: bn_mp_radix_size.c */
5246
5247 /* Start: bn_mp_radix_smap.c */
5248 #include "tommath_private.h"
5249 #ifdef BN_MP_RADIX_SMAP_C
5250 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5251 /* SPDX-License-Identifier: Unlicense */
5252
5253 /* chars used in radix conversions */
5254 const char *const mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
5255 const uint8_t mp_s_rmap_reverse[] = {
5256 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, /* ()*+,-./ */
5257 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */
5258 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */
5259 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* @ABCDEFG */
5260 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* HIJKLMNO */
5261 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, /* PQRSTUVW */
5262 0x21, 0x22, 0x23, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */
5263 0xff, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, /* `abcdefg */
5264 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, /* hijklmno */
5265 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, /* pqrstuvw */
5266 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, /* xyz{|}~. */
5267 };
5268 const size_t mp_s_rmap_reverse_sz = sizeof(mp_s_rmap_reverse);
5269 #endif
5270
5271 /* End: bn_mp_radix_smap.c */
5272
5273 /* Start: bn_mp_rand.c */
5274 #include "tommath_private.h"
5275 #ifdef BN_MP_RAND_C
5276 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5277 /* SPDX-License-Identifier: Unlicense */
5278
5279 mp_err(*s_mp_rand_source)(void *out, size_t size) = s_mp_rand_platform;
5280
mp_rand_source(mp_err (* source)(void * out,size_t size))5281 void mp_rand_source(mp_err(*source)(void *out, size_t size))
5282 {
5283 s_mp_rand_source = (source == NULL) ? s_mp_rand_platform : source;
5284 }
5285
mp_rand(mp_int * a,int digits)5286 mp_err mp_rand(mp_int *a, int digits)
5287 {
5288 int i;
5289 mp_err err;
5290
5291 mp_zero(a);
5292
5293 if (digits <= 0) {
5294 return MP_OKAY;
5295 }
5296
5297 if ((err = mp_grow(a, digits)) != MP_OKAY) {
5298 return err;
5299 }
5300
5301 if ((err = s_mp_rand_source(a->dp, (size_t)digits * sizeof(mp_digit))) != MP_OKAY) {
5302 return err;
5303 }
5304
5305 /* TODO: We ensure that the highest digit is nonzero. Should this be removed? */
5306 while ((a->dp[digits - 1] & MP_MASK) == 0u) {
5307 if ((err = s_mp_rand_source(a->dp + digits - 1, sizeof(mp_digit))) != MP_OKAY) {
5308 return err;
5309 }
5310 }
5311
5312 a->used = digits;
5313 for (i = 0; i < digits; ++i) {
5314 a->dp[i] &= MP_MASK;
5315 }
5316
5317 return MP_OKAY;
5318 }
5319 #endif
5320
5321 /* End: bn_mp_rand.c */
5322
5323 /* Start: bn_mp_read_radix.c */
5324 #include "tommath_private.h"
5325 #ifdef BN_MP_READ_RADIX_C
5326 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5327 /* SPDX-License-Identifier: Unlicense */
5328
5329 #define MP_TOUPPER(c) ((((c) >= 'a') && ((c) <= 'z')) ? (((c) + 'A') - 'a') : (c))
5330
5331 /* read a string [ASCII] in a given radix */
mp_read_radix(mp_int * a,const char * str,int radix)5332 mp_err mp_read_radix(mp_int *a, const char *str, int radix)
5333 {
5334 mp_err err;
5335 int y;
5336 mp_sign neg;
5337 unsigned pos;
5338 char ch;
5339
5340 /* zero the digit bignum */
5341 mp_zero(a);
5342
5343 /* make sure the radix is ok */
5344 if ((radix < 2) || (radix > 64)) {
5345 return MP_VAL;
5346 }
5347
5348 /* if the leading digit is a
5349 * minus set the sign to negative.
5350 */
5351 if (*str == '-') {
5352 ++str;
5353 neg = MP_NEG;
5354 } else {
5355 neg = MP_ZPOS;
5356 }
5357
5358 /* set the integer to the default of zero */
5359 mp_zero(a);
5360
5361 /* process each digit of the string */
5362 while (*str != '\0') {
5363 /* if the radix <= 36 the conversion is case insensitive
5364 * this allows numbers like 1AB and 1ab to represent the same value
5365 * [e.g. in hex]
5366 */
5367 ch = (radix <= 36) ? (char)MP_TOUPPER((int)*str) : *str;
5368 pos = (unsigned)(ch - '(');
5369 if (mp_s_rmap_reverse_sz < pos) {
5370 break;
5371 }
5372 y = (int)mp_s_rmap_reverse[pos];
5373
5374 /* if the char was found in the map
5375 * and is less than the given radix add it
5376 * to the number, otherwise exit the loop.
5377 */
5378 if ((y == 0xff) || (y >= radix)) {
5379 break;
5380 }
5381 if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) {
5382 return err;
5383 }
5384 if ((err = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) {
5385 return err;
5386 }
5387 ++str;
5388 }
5389
5390 /* if an illegal character was found, fail. */
5391 if (!((*str == '\0') || (*str == '\r') || (*str == '\n'))) {
5392 mp_zero(a);
5393 return MP_VAL;
5394 }
5395
5396 /* set the sign only if a != 0 */
5397 if (!MP_IS_ZERO(a)) {
5398 a->sign = neg;
5399 }
5400 return MP_OKAY;
5401 }
5402 #endif
5403
5404 /* End: bn_mp_read_radix.c */
5405
5406 /* Start: bn_mp_reduce.c */
5407 #include "tommath_private.h"
5408 #ifdef BN_MP_REDUCE_C
5409 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5410 /* SPDX-License-Identifier: Unlicense */
5411
5412 /* reduces x mod m, assumes 0 < x < m**2, mu is
5413 * precomputed via mp_reduce_setup.
5414 * From HAC pp.604 Algorithm 14.42
5415 */
mp_reduce(mp_int * x,const mp_int * m,const mp_int * mu)5416 mp_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu)
5417 {
5418 mp_int q;
5419 mp_err err;
5420 int um = m->used;
5421
5422 /* q = x */
5423 if ((err = mp_init_copy(&q, x)) != MP_OKAY) {
5424 return err;
5425 }
5426
5427 /* q1 = x / b**(k-1) */
5428 mp_rshd(&q, um - 1);
5429
5430 /* according to HAC this optimization is ok */
5431 if ((mp_digit)um > ((mp_digit)1 << (MP_DIGIT_BIT - 1))) {
5432 if ((err = mp_mul(&q, mu, &q)) != MP_OKAY) {
5433 goto CLEANUP;
5434 }
5435 } else if (MP_HAS(S_MP_MUL_HIGH_DIGS)) {
5436 if ((err = s_mp_mul_high_digs(&q, mu, &q, um)) != MP_OKAY) {
5437 goto CLEANUP;
5438 }
5439 } else if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST)) {
5440 if ((err = s_mp_mul_high_digs_fast(&q, mu, &q, um)) != MP_OKAY) {
5441 goto CLEANUP;
5442 }
5443 } else {
5444 err = MP_VAL;
5445 goto CLEANUP;
5446 }
5447
5448 /* q3 = q2 / b**(k+1) */
5449 mp_rshd(&q, um + 1);
5450
5451 /* x = x mod b**(k+1), quick (no division) */
5452 if ((err = mp_mod_2d(x, MP_DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
5453 goto CLEANUP;
5454 }
5455
5456 /* q = q * m mod b**(k+1), quick (no division) */
5457 if ((err = s_mp_mul_digs(&q, m, &q, um + 1)) != MP_OKAY) {
5458 goto CLEANUP;
5459 }
5460
5461 /* x = x - q */
5462 if ((err = mp_sub(x, &q, x)) != MP_OKAY) {
5463 goto CLEANUP;
5464 }
5465
5466 /* If x < 0, add b**(k+1) to it */
5467 if (mp_cmp_d(x, 0uL) == MP_LT) {
5468 mp_set(&q, 1uL);
5469 if ((err = mp_lshd(&q, um + 1)) != MP_OKAY) {
5470 goto CLEANUP;
5471 }
5472 if ((err = mp_add(x, &q, x)) != MP_OKAY) {
5473 goto CLEANUP;
5474 }
5475 }
5476
5477 /* Back off if it's too big */
5478 while (mp_cmp(x, m) != MP_LT) {
5479 if ((err = s_mp_sub(x, m, x)) != MP_OKAY) {
5480 goto CLEANUP;
5481 }
5482 }
5483
5484 CLEANUP:
5485 mp_clear(&q);
5486
5487 return err;
5488 }
5489 #endif
5490
5491 /* End: bn_mp_reduce.c */
5492
5493 /* Start: bn_mp_reduce_2k.c */
5494 #include "tommath_private.h"
5495 #ifdef BN_MP_REDUCE_2K_C
5496 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5497 /* SPDX-License-Identifier: Unlicense */
5498
5499 /* reduces a modulo n where n is of the form 2**p - d */
mp_reduce_2k(mp_int * a,const mp_int * n,mp_digit d)5500 mp_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d)
5501 {
5502 mp_int q;
5503 mp_err err;
5504 int p;
5505
5506 if ((err = mp_init(&q)) != MP_OKAY) {
5507 return err;
5508 }
5509
5510 p = mp_count_bits(n);
5511 top:
5512 /* q = a/2**p, a = a mod 2**p */
5513 if ((err = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
5514 goto LBL_ERR;
5515 }
5516
5517 if (d != 1u) {
5518 /* q = q * d */
5519 if ((err = mp_mul_d(&q, d, &q)) != MP_OKAY) {
5520 goto LBL_ERR;
5521 }
5522 }
5523
5524 /* a = a + q */
5525 if ((err = s_mp_add(a, &q, a)) != MP_OKAY) {
5526 goto LBL_ERR;
5527 }
5528
5529 if (mp_cmp_mag(a, n) != MP_LT) {
5530 if ((err = s_mp_sub(a, n, a)) != MP_OKAY) {
5531 goto LBL_ERR;
5532 }
5533 goto top;
5534 }
5535
5536 LBL_ERR:
5537 mp_clear(&q);
5538 return err;
5539 }
5540
5541 #endif
5542
5543 /* End: bn_mp_reduce_2k.c */
5544
5545 /* Start: bn_mp_reduce_2k_l.c */
5546 #include "tommath_private.h"
5547 #ifdef BN_MP_REDUCE_2K_L_C
5548 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5549 /* SPDX-License-Identifier: Unlicense */
5550
5551 /* reduces a modulo n where n is of the form 2**p - d
5552 This differs from reduce_2k since "d" can be larger
5553 than a single digit.
5554 */
mp_reduce_2k_l(mp_int * a,const mp_int * n,const mp_int * d)5555 mp_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d)
5556 {
5557 mp_int q;
5558 mp_err err;
5559 int p;
5560
5561 if ((err = mp_init(&q)) != MP_OKAY) {
5562 return err;
5563 }
5564
5565 p = mp_count_bits(n);
5566 top:
5567 /* q = a/2**p, a = a mod 2**p */
5568 if ((err = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
5569 goto LBL_ERR;
5570 }
5571
5572 /* q = q * d */
5573 if ((err = mp_mul(&q, d, &q)) != MP_OKAY) {
5574 goto LBL_ERR;
5575 }
5576
5577 /* a = a + q */
5578 if ((err = s_mp_add(a, &q, a)) != MP_OKAY) {
5579 goto LBL_ERR;
5580 }
5581
5582 if (mp_cmp_mag(a, n) != MP_LT) {
5583 if ((err = s_mp_sub(a, n, a)) != MP_OKAY) {
5584 goto LBL_ERR;
5585 }
5586 goto top;
5587 }
5588
5589 LBL_ERR:
5590 mp_clear(&q);
5591 return err;
5592 }
5593
5594 #endif
5595
5596 /* End: bn_mp_reduce_2k_l.c */
5597
5598 /* Start: bn_mp_reduce_2k_setup.c */
5599 #include "tommath_private.h"
5600 #ifdef BN_MP_REDUCE_2K_SETUP_C
5601 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5602 /* SPDX-License-Identifier: Unlicense */
5603
5604 /* determines the setup value */
mp_reduce_2k_setup(const mp_int * a,mp_digit * d)5605 mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d)
5606 {
5607 mp_err err;
5608 mp_int tmp;
5609 int p;
5610
5611 if ((err = mp_init(&tmp)) != MP_OKAY) {
5612 return err;
5613 }
5614
5615 p = mp_count_bits(a);
5616 if ((err = mp_2expt(&tmp, p)) != MP_OKAY) {
5617 mp_clear(&tmp);
5618 return err;
5619 }
5620
5621 if ((err = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
5622 mp_clear(&tmp);
5623 return err;
5624 }
5625
5626 *d = tmp.dp[0];
5627 mp_clear(&tmp);
5628 return MP_OKAY;
5629 }
5630 #endif
5631
5632 /* End: bn_mp_reduce_2k_setup.c */
5633
5634 /* Start: bn_mp_reduce_2k_setup_l.c */
5635 #include "tommath_private.h"
5636 #ifdef BN_MP_REDUCE_2K_SETUP_L_C
5637 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5638 /* SPDX-License-Identifier: Unlicense */
5639
5640 /* determines the setup value */
mp_reduce_2k_setup_l(const mp_int * a,mp_int * d)5641 mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d)
5642 {
5643 mp_err err;
5644 mp_int tmp;
5645
5646 if ((err = mp_init(&tmp)) != MP_OKAY) {
5647 return err;
5648 }
5649
5650 if ((err = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
5651 goto LBL_ERR;
5652 }
5653
5654 if ((err = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
5655 goto LBL_ERR;
5656 }
5657
5658 LBL_ERR:
5659 mp_clear(&tmp);
5660 return err;
5661 }
5662 #endif
5663
5664 /* End: bn_mp_reduce_2k_setup_l.c */
5665
5666 /* Start: bn_mp_reduce_is_2k.c */
5667 #include "tommath_private.h"
5668 #ifdef BN_MP_REDUCE_IS_2K_C
5669 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5670 /* SPDX-License-Identifier: Unlicense */
5671
5672 /* determines if mp_reduce_2k can be used */
mp_reduce_is_2k(const mp_int * a)5673 mp_bool mp_reduce_is_2k(const mp_int *a)
5674 {
5675 int ix, iy, iw;
5676 mp_digit iz;
5677
5678 if (a->used == 0) {
5679 return MP_NO;
5680 } else if (a->used == 1) {
5681 return MP_YES;
5682 } else if (a->used > 1) {
5683 iy = mp_count_bits(a);
5684 iz = 1;
5685 iw = 1;
5686
5687 /* Test every bit from the second digit up, must be 1 */
5688 for (ix = MP_DIGIT_BIT; ix < iy; ix++) {
5689 if ((a->dp[iw] & iz) == 0u) {
5690 return MP_NO;
5691 }
5692 iz <<= 1;
5693 if (iz > MP_DIGIT_MAX) {
5694 ++iw;
5695 iz = 1;
5696 }
5697 }
5698 return MP_YES;
5699 } else {
5700 return MP_YES;
5701 }
5702 }
5703
5704 #endif
5705
5706 /* End: bn_mp_reduce_is_2k.c */
5707
5708 /* Start: bn_mp_reduce_is_2k_l.c */
5709 #include "tommath_private.h"
5710 #ifdef BN_MP_REDUCE_IS_2K_L_C
5711 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5712 /* SPDX-License-Identifier: Unlicense */
5713
5714 /* determines if reduce_2k_l can be used */
mp_reduce_is_2k_l(const mp_int * a)5715 mp_bool mp_reduce_is_2k_l(const mp_int *a)
5716 {
5717 int ix, iy;
5718
5719 if (a->used == 0) {
5720 return MP_NO;
5721 } else if (a->used == 1) {
5722 return MP_YES;
5723 } else if (a->used > 1) {
5724 /* if more than half of the digits are -1 we're sold */
5725 for (iy = ix = 0; ix < a->used; ix++) {
5726 if (a->dp[ix] == MP_DIGIT_MAX) {
5727 ++iy;
5728 }
5729 }
5730 return (iy >= (a->used/2)) ? MP_YES : MP_NO;
5731 } else {
5732 return MP_NO;
5733 }
5734 }
5735
5736 #endif
5737
5738 /* End: bn_mp_reduce_is_2k_l.c */
5739
5740 /* Start: bn_mp_reduce_setup.c */
5741 #include "tommath_private.h"
5742 #ifdef BN_MP_REDUCE_SETUP_C
5743 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5744 /* SPDX-License-Identifier: Unlicense */
5745
5746 /* pre-calculate the value required for Barrett reduction
5747 * For a given modulus "b" it calulates the value required in "a"
5748 */
mp_reduce_setup(mp_int * a,const mp_int * b)5749 mp_err mp_reduce_setup(mp_int *a, const mp_int *b)
5750 {
5751 mp_err err;
5752 if ((err = mp_2expt(a, b->used * 2 * MP_DIGIT_BIT)) != MP_OKAY) {
5753 return err;
5754 }
5755 return mp_div(a, b, a, NULL);
5756 }
5757 #endif
5758
5759 /* End: bn_mp_reduce_setup.c */
5760
5761 /* Start: bn_mp_root_u32.c */
5762 #include "tommath_private.h"
5763 #ifdef BN_MP_ROOT_U32_C
5764 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5765 /* SPDX-License-Identifier: Unlicense */
5766
5767 /* find the n'th root of an integer
5768 *
5769 * Result found such that (c)**b <= a and (c+1)**b > a
5770 *
5771 * This algorithm uses Newton's approximation
5772 * x[i+1] = x[i] - f(x[i])/f'(x[i])
5773 * which will find the root in log(N) time where
5774 * each step involves a fair bit.
5775 */
mp_root_u32(const mp_int * a,uint32_t b,mp_int * c)5776 mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c)
5777 {
5778 mp_int t1, t2, t3, a_;
5779 mp_ord cmp;
5780 int ilog2;
5781 mp_err err;
5782
5783 /* input must be positive if b is even */
5784 if (((b & 1u) == 0u) && (a->sign == MP_NEG)) {
5785 return MP_VAL;
5786 }
5787
5788 if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) {
5789 return err;
5790 }
5791
5792 /* if a is negative fudge the sign but keep track */
5793 a_ = *a;
5794 a_.sign = MP_ZPOS;
5795
5796 /* Compute seed: 2^(log_2(n)/b + 2)*/
5797 ilog2 = mp_count_bits(a);
5798
5799 /*
5800 If "b" is larger than INT_MAX it is also larger than
5801 log_2(n) because the bit-length of the "n" is measured
5802 with an int and hence the root is always < 2 (two).
5803 */
5804 if (b > (uint32_t)(INT_MAX/2)) {
5805 mp_set(c, 1uL);
5806 c->sign = a->sign;
5807 err = MP_OKAY;
5808 goto LBL_ERR;
5809 }
5810
5811 /* "b" is smaller than INT_MAX, we can cast safely */
5812 if (ilog2 < (int)b) {
5813 mp_set(c, 1uL);
5814 c->sign = a->sign;
5815 err = MP_OKAY;
5816 goto LBL_ERR;
5817 }
5818 ilog2 = ilog2 / ((int)b);
5819 if (ilog2 == 0) {
5820 mp_set(c, 1uL);
5821 c->sign = a->sign;
5822 err = MP_OKAY;
5823 goto LBL_ERR;
5824 }
5825 /* Start value must be larger than root */
5826 ilog2 += 2;
5827 if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY) goto LBL_ERR;
5828 do {
5829 /* t1 = t2 */
5830 if ((err = mp_copy(&t2, &t1)) != MP_OKAY) goto LBL_ERR;
5831
5832 /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
5833
5834 /* t3 = t1**(b-1) */
5835 if ((err = mp_expt_u32(&t1, b - 1u, &t3)) != MP_OKAY) goto LBL_ERR;
5836
5837 /* numerator */
5838 /* t2 = t1**b */
5839 if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY) goto LBL_ERR;
5840
5841 /* t2 = t1**b - a */
5842 if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY) goto LBL_ERR;
5843
5844 /* denominator */
5845 /* t3 = t1**(b-1) * b */
5846 if ((err = mp_mul_d(&t3, b, &t3)) != MP_OKAY) goto LBL_ERR;
5847
5848 /* t3 = (t1**b - a)/(b * t1**(b-1)) */
5849 if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) goto LBL_ERR;
5850
5851 if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY) goto LBL_ERR;
5852
5853 /*
5854 Number of rounds is at most log_2(root). If it is more it
5855 got stuck, so break out of the loop and do the rest manually.
5856 */
5857 if (ilog2-- == 0) {
5858 break;
5859 }
5860 } while (mp_cmp(&t1, &t2) != MP_EQ);
5861
5862 /* result can be off by a few so check */
5863 /* Loop beneath can overshoot by one if found root is smaller than actual root */
5864 for (;;) {
5865 if ((err = mp_expt_u32(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR;
5866 cmp = mp_cmp(&t2, &a_);
5867 if (cmp == MP_EQ) {
5868 err = MP_OKAY;
5869 goto LBL_ERR;
5870 }
5871 if (cmp == MP_LT) {
5872 if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR;
5873 } else {
5874 break;
5875 }
5876 }
5877 /* correct overshoot from above or from recurrence */
5878 for (;;) {
5879 if ((err = mp_expt_u32(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR;
5880 if (mp_cmp(&t2, &a_) == MP_GT) {
5881 if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR;
5882 } else {
5883 break;
5884 }
5885 }
5886
5887 /* set the result */
5888 mp_exch(&t1, c);
5889
5890 /* set the sign of the result */
5891 c->sign = a->sign;
5892
5893 err = MP_OKAY;
5894
5895 LBL_ERR:
5896 mp_clear_multi(&t1, &t2, &t3, NULL);
5897 return err;
5898 }
5899
5900 #endif
5901
5902 /* End: bn_mp_root_u32.c */
5903
5904 /* Start: bn_mp_rshd.c */
5905 #include "tommath_private.h"
5906 #ifdef BN_MP_RSHD_C
5907 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5908 /* SPDX-License-Identifier: Unlicense */
5909
5910 /* shift right a certain amount of digits */
mp_rshd(mp_int * a,int b)5911 void mp_rshd(mp_int *a, int b)
5912 {
5913 int x;
5914 mp_digit *bottom, *top;
5915
5916 /* if b <= 0 then ignore it */
5917 if (b <= 0) {
5918 return;
5919 }
5920
5921 /* if b > used then simply zero it and return */
5922 if (a->used <= b) {
5923 mp_zero(a);
5924 return;
5925 }
5926
5927 /* shift the digits down */
5928
5929 /* bottom */
5930 bottom = a->dp;
5931
5932 /* top [offset into digits] */
5933 top = a->dp + b;
5934
5935 /* this is implemented as a sliding window where
5936 * the window is b-digits long and digits from
5937 * the top of the window are copied to the bottom
5938 *
5939 * e.g.
5940
5941 b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
5942 /\ | ---->
5943 \-------------------/ ---->
5944 */
5945 for (x = 0; x < (a->used - b); x++) {
5946 *bottom++ = *top++;
5947 }
5948
5949 /* zero the top digits */
5950 MP_ZERO_DIGITS(bottom, a->used - x);
5951
5952 /* remove excess digits */
5953 a->used -= b;
5954 }
5955 #endif
5956
5957 /* End: bn_mp_rshd.c */
5958
5959 /* Start: bn_mp_sbin_size.c */
5960 #include "tommath_private.h"
5961 #ifdef BN_MP_SBIN_SIZE_C
5962 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5963 /* SPDX-License-Identifier: Unlicense */
5964
5965 /* get the size for an signed equivalent */
mp_sbin_size(const mp_int * a)5966 size_t mp_sbin_size(const mp_int *a)
5967 {
5968 return 1u + mp_ubin_size(a);
5969 }
5970 #endif
5971
5972 /* End: bn_mp_sbin_size.c */
5973
5974 /* Start: bn_mp_set.c */
5975 #include "tommath_private.h"
5976 #ifdef BN_MP_SET_C
5977 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5978 /* SPDX-License-Identifier: Unlicense */
5979
5980 /* set to a digit */
mp_set(mp_int * a,mp_digit b)5981 void mp_set(mp_int *a, mp_digit b)
5982 {
5983 a->dp[0] = b & MP_MASK;
5984 a->sign = MP_ZPOS;
5985 a->used = (a->dp[0] != 0u) ? 1 : 0;
5986 MP_ZERO_DIGITS(a->dp + a->used, a->alloc - a->used);
5987 }
5988 #endif
5989
5990 /* End: bn_mp_set.c */
5991
5992 /* Start: bn_mp_set_double.c */
5993 #include "tommath_private.h"
5994 #ifdef BN_MP_SET_DOUBLE_C
5995 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5996 /* SPDX-License-Identifier: Unlicense */
5997
5998 #if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559)
mp_set_double(mp_int * a,double b)5999 mp_err mp_set_double(mp_int *a, double b)
6000 {
6001 uint64_t frac;
6002 int exp;
6003 mp_err err;
6004 union {
6005 double dbl;
6006 uint64_t bits;
6007 } cast;
6008 cast.dbl = b;
6009
6010 exp = (int)((unsigned)(cast.bits >> 52) & 0x7FFu);
6011 frac = (cast.bits & ((1uLL << 52) - 1uLL)) | (1uLL << 52);
6012
6013 if (exp == 0x7FF) { /* +-inf, NaN */
6014 return MP_VAL;
6015 }
6016 exp -= 1023 + 52;
6017
6018 mp_set_u64(a, frac);
6019
6020 err = (exp < 0) ? mp_div_2d(a, -exp, a, NULL) : mp_mul_2d(a, exp, a);
6021 if (err != MP_OKAY) {
6022 return err;
6023 }
6024
6025 if (((cast.bits >> 63) != 0uLL) && !MP_IS_ZERO(a)) {
6026 a->sign = MP_NEG;
6027 }
6028
6029 return MP_OKAY;
6030 }
6031 #else
6032 /* pragma message() not supported by several compilers (in mostly older but still used versions) */
6033 # ifdef _MSC_VER
6034 # pragma message("mp_set_double implementation is only available on platforms with IEEE754 floating point format")
6035 # else
6036 # warning "mp_set_double implementation is only available on platforms with IEEE754 floating point format"
6037 # endif
6038 #endif
6039 #endif
6040
6041 /* End: bn_mp_set_double.c */
6042
6043 /* Start: bn_mp_set_i32.c */
6044 #include "tommath_private.h"
6045 #ifdef BN_MP_SET_I32_C
6046 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6047 /* SPDX-License-Identifier: Unlicense */
6048
MP_SET_SIGNED(mp_set_i32,mp_set_u32,int32_t,uint32_t)6049 MP_SET_SIGNED(mp_set_i32, mp_set_u32, int32_t, uint32_t)
6050 #endif
6051
6052 /* End: bn_mp_set_i32.c */
6053
6054 /* Start: bn_mp_set_i64.c */
6055 #include "tommath_private.h"
6056 #ifdef BN_MP_SET_I64_C
6057 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6058 /* SPDX-License-Identifier: Unlicense */
6059
6060 MP_SET_SIGNED(mp_set_i64, mp_set_u64, int64_t, uint64_t)
6061 #endif
6062
6063 /* End: bn_mp_set_i64.c */
6064
6065 /* Start: bn_mp_set_l.c */
6066 #include "tommath_private.h"
6067 #ifdef BN_MP_SET_L_C
6068 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6069 /* SPDX-License-Identifier: Unlicense */
6070
6071 MP_SET_SIGNED(mp_set_l, mp_set_ul, long, unsigned long)
6072 #endif
6073
6074 /* End: bn_mp_set_l.c */
6075
6076 /* Start: bn_mp_set_ll.c */
6077 #include "tommath_private.h"
6078 #ifdef BN_MP_SET_LL_C
6079 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6080 /* SPDX-License-Identifier: Unlicense */
6081
6082 MP_SET_SIGNED(mp_set_ll, mp_set_ull, long long, unsigned long long)
6083 #endif
6084
6085 /* End: bn_mp_set_ll.c */
6086
6087 /* Start: bn_mp_set_u32.c */
6088 #include "tommath_private.h"
6089 #ifdef BN_MP_SET_U32_C
6090 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6091 /* SPDX-License-Identifier: Unlicense */
6092
6093 MP_SET_UNSIGNED(mp_set_u32, uint32_t)
6094 #endif
6095
6096 /* End: bn_mp_set_u32.c */
6097
6098 /* Start: bn_mp_set_u64.c */
6099 #include "tommath_private.h"
6100 #ifdef BN_MP_SET_U64_C
6101 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6102 /* SPDX-License-Identifier: Unlicense */
6103
6104 MP_SET_UNSIGNED(mp_set_u64, uint64_t)
6105 #endif
6106
6107 /* End: bn_mp_set_u64.c */
6108
6109 /* Start: bn_mp_set_ul.c */
6110 #include "tommath_private.h"
6111 #ifdef BN_MP_SET_UL_C
6112 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6113 /* SPDX-License-Identifier: Unlicense */
6114
6115 MP_SET_UNSIGNED(mp_set_ul, unsigned long)
6116 #endif
6117
6118 /* End: bn_mp_set_ul.c */
6119
6120 /* Start: bn_mp_set_ull.c */
6121 #include "tommath_private.h"
6122 #ifdef BN_MP_SET_ULL_C
6123 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6124 /* SPDX-License-Identifier: Unlicense */
6125
6126 MP_SET_UNSIGNED(mp_set_ull, unsigned long long)
6127 #endif
6128
6129 /* End: bn_mp_set_ull.c */
6130
6131 /* Start: bn_mp_shrink.c */
6132 #include "tommath_private.h"
6133 #ifdef BN_MP_SHRINK_C
6134 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6135 /* SPDX-License-Identifier: Unlicense */
6136
6137 /* shrink a bignum */
6138 mp_err mp_shrink(mp_int *a)
6139 {
6140 mp_digit *tmp;
6141 int alloc = MP_MAX(MP_MIN_PREC, a->used);
6142 if (a->alloc != alloc) {
6143 if ((tmp = (mp_digit *) MP_REALLOC(a->dp,
6144 (size_t)a->alloc * sizeof(mp_digit),
6145 (size_t)alloc * sizeof(mp_digit))) == NULL) {
6146 return MP_MEM;
6147 }
6148 a->dp = tmp;
6149 a->alloc = alloc;
6150 }
6151 return MP_OKAY;
6152 }
6153 #endif
6154
6155 /* End: bn_mp_shrink.c */
6156
6157 /* Start: bn_mp_signed_rsh.c */
6158 #include "tommath_private.h"
6159 #ifdef BN_MP_SIGNED_RSH_C
6160 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6161 /* SPDX-License-Identifier: Unlicense */
6162
6163 /* shift right by a certain bit count with sign extension */
mp_signed_rsh(const mp_int * a,int b,mp_int * c)6164 mp_err mp_signed_rsh(const mp_int *a, int b, mp_int *c)
6165 {
6166 mp_err res;
6167 if (a->sign == MP_ZPOS) {
6168 return mp_div_2d(a, b, c, NULL);
6169 }
6170
6171 res = mp_add_d(a, 1uL, c);
6172 if (res != MP_OKAY) {
6173 return res;
6174 }
6175
6176 res = mp_div_2d(c, b, c, NULL);
6177 return (res == MP_OKAY) ? mp_sub_d(c, 1uL, c) : res;
6178 }
6179 #endif
6180
6181 /* End: bn_mp_signed_rsh.c */
6182
6183 /* Start: bn_mp_sqr.c */
6184 #include "tommath_private.h"
6185 #ifdef BN_MP_SQR_C
6186 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6187 /* SPDX-License-Identifier: Unlicense */
6188
6189 /* computes b = a*a */
mp_sqr(const mp_int * a,mp_int * b)6190 mp_err mp_sqr(const mp_int *a, mp_int *b)
6191 {
6192 mp_err err;
6193 if (MP_HAS(S_MP_TOOM_SQR) && /* use Toom-Cook? */
6194 (a->used >= MP_TOOM_SQR_CUTOFF)) {
6195 err = s_mp_toom_sqr(a, b);
6196 } else if (MP_HAS(S_MP_KARATSUBA_SQR) && /* Karatsuba? */
6197 (a->used >= MP_KARATSUBA_SQR_CUTOFF)) {
6198 err = s_mp_karatsuba_sqr(a, b);
6199 } else if (MP_HAS(S_MP_SQR_FAST) && /* can we use the fast comba multiplier? */
6200 (((a->used * 2) + 1) < MP_WARRAY) &&
6201 (a->used < (MP_MAXFAST / 2))) {
6202 err = s_mp_sqr_fast(a, b);
6203 } else if (MP_HAS(S_MP_SQR)) {
6204 err = s_mp_sqr(a, b);
6205 } else {
6206 err = MP_VAL;
6207 }
6208 b->sign = MP_ZPOS;
6209 return err;
6210 }
6211 #endif
6212
6213 /* End: bn_mp_sqr.c */
6214
6215 /* Start: bn_mp_sqrmod.c */
6216 #include "tommath_private.h"
6217 #ifdef BN_MP_SQRMOD_C
6218 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6219 /* SPDX-License-Identifier: Unlicense */
6220
6221 /* c = a * a (mod b) */
mp_sqrmod(const mp_int * a,const mp_int * b,mp_int * c)6222 mp_err mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c)
6223 {
6224 mp_err err;
6225 mp_int t;
6226
6227 if ((err = mp_init(&t)) != MP_OKAY) {
6228 return err;
6229 }
6230
6231 if ((err = mp_sqr(a, &t)) != MP_OKAY) {
6232 goto LBL_ERR;
6233 }
6234 err = mp_mod(&t, b, c);
6235
6236 LBL_ERR:
6237 mp_clear(&t);
6238 return err;
6239 }
6240 #endif
6241
6242 /* End: bn_mp_sqrmod.c */
6243
6244 /* Start: bn_mp_sqrt.c */
6245 #include "tommath_private.h"
6246 #ifdef BN_MP_SQRT_C
6247 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6248 /* SPDX-License-Identifier: Unlicense */
6249
6250 /* this function is less generic than mp_n_root, simpler and faster */
mp_sqrt(const mp_int * arg,mp_int * ret)6251 mp_err mp_sqrt(const mp_int *arg, mp_int *ret)
6252 {
6253 mp_err err;
6254 mp_int t1, t2;
6255
6256 /* must be positive */
6257 if (arg->sign == MP_NEG) {
6258 return MP_VAL;
6259 }
6260
6261 /* easy out */
6262 if (MP_IS_ZERO(arg)) {
6263 mp_zero(ret);
6264 return MP_OKAY;
6265 }
6266
6267 if ((err = mp_init_copy(&t1, arg)) != MP_OKAY) {
6268 return err;
6269 }
6270
6271 if ((err = mp_init(&t2)) != MP_OKAY) {
6272 goto E2;
6273 }
6274
6275 /* First approx. (not very bad for large arg) */
6276 mp_rshd(&t1, t1.used/2);
6277
6278 /* t1 > 0 */
6279 if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) {
6280 goto E1;
6281 }
6282 if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) {
6283 goto E1;
6284 }
6285 if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) {
6286 goto E1;
6287 }
6288 /* And now t1 > sqrt(arg) */
6289 do {
6290 if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) {
6291 goto E1;
6292 }
6293 if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) {
6294 goto E1;
6295 }
6296 if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) {
6297 goto E1;
6298 }
6299 /* t1 >= sqrt(arg) >= t2 at this point */
6300 } while (mp_cmp_mag(&t1, &t2) == MP_GT);
6301
6302 mp_exch(&t1, ret);
6303
6304 E1:
6305 mp_clear(&t2);
6306 E2:
6307 mp_clear(&t1);
6308 return err;
6309 }
6310
6311 #endif
6312
6313 /* End: bn_mp_sqrt.c */
6314
6315 /* Start: bn_mp_sqrtmod_prime.c */
6316 #include "tommath_private.h"
6317 #ifdef BN_MP_SQRTMOD_PRIME_C
6318 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6319 /* SPDX-License-Identifier: Unlicense */
6320
6321 /* Tonelli-Shanks algorithm
6322 * https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm
6323 * https://gmplib.org/list-archives/gmp-discuss/2013-April/005300.html
6324 *
6325 */
6326
mp_sqrtmod_prime(const mp_int * n,const mp_int * prime,mp_int * ret)6327 mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret)
6328 {
6329 mp_err err;
6330 int legendre;
6331 mp_int t1, C, Q, S, Z, M, T, R, two;
6332 mp_digit i;
6333
6334 /* first handle the simple cases */
6335 if (mp_cmp_d(n, 0uL) == MP_EQ) {
6336 mp_zero(ret);
6337 return MP_OKAY;
6338 }
6339 if (mp_cmp_d(prime, 2uL) == MP_EQ) return MP_VAL; /* prime must be odd */
6340 if ((err = mp_kronecker(n, prime, &legendre)) != MP_OKAY) return err;
6341 if (legendre == -1) return MP_VAL; /* quadratic non-residue mod prime */
6342
6343 if ((err = mp_init_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL)) != MP_OKAY) {
6344 return err;
6345 }
6346
6347 /* SPECIAL CASE: if prime mod 4 == 3
6348 * compute directly: err = n^(prime+1)/4 mod prime
6349 * Handbook of Applied Cryptography algorithm 3.36
6350 */
6351 if ((err = mp_mod_d(prime, 4uL, &i)) != MP_OKAY) goto cleanup;
6352 if (i == 3u) {
6353 if ((err = mp_add_d(prime, 1uL, &t1)) != MP_OKAY) goto cleanup;
6354 if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup;
6355 if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup;
6356 if ((err = mp_exptmod(n, &t1, prime, ret)) != MP_OKAY) goto cleanup;
6357 err = MP_OKAY;
6358 goto cleanup;
6359 }
6360
6361 /* NOW: Tonelli-Shanks algorithm */
6362
6363 /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */
6364 if ((err = mp_copy(prime, &Q)) != MP_OKAY) goto cleanup;
6365 if ((err = mp_sub_d(&Q, 1uL, &Q)) != MP_OKAY) goto cleanup;
6366 /* Q = prime - 1 */
6367 mp_zero(&S);
6368 /* S = 0 */
6369 while (MP_IS_EVEN(&Q)) {
6370 if ((err = mp_div_2(&Q, &Q)) != MP_OKAY) goto cleanup;
6371 /* Q = Q / 2 */
6372 if ((err = mp_add_d(&S, 1uL, &S)) != MP_OKAY) goto cleanup;
6373 /* S = S + 1 */
6374 }
6375
6376 /* find a Z such that the Legendre symbol (Z|prime) == -1 */
6377 mp_set_u32(&Z, 2u);
6378 /* Z = 2 */
6379 for (;;) {
6380 if ((err = mp_kronecker(&Z, prime, &legendre)) != MP_OKAY) goto cleanup;
6381 if (legendre == -1) break;
6382 if ((err = mp_add_d(&Z, 1uL, &Z)) != MP_OKAY) goto cleanup;
6383 /* Z = Z + 1 */
6384 }
6385
6386 if ((err = mp_exptmod(&Z, &Q, prime, &C)) != MP_OKAY) goto cleanup;
6387 /* C = Z ^ Q mod prime */
6388 if ((err = mp_add_d(&Q, 1uL, &t1)) != MP_OKAY) goto cleanup;
6389 if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup;
6390 /* t1 = (Q + 1) / 2 */
6391 if ((err = mp_exptmod(n, &t1, prime, &R)) != MP_OKAY) goto cleanup;
6392 /* R = n ^ ((Q + 1) / 2) mod prime */
6393 if ((err = mp_exptmod(n, &Q, prime, &T)) != MP_OKAY) goto cleanup;
6394 /* T = n ^ Q mod prime */
6395 if ((err = mp_copy(&S, &M)) != MP_OKAY) goto cleanup;
6396 /* M = S */
6397 mp_set_u32(&two, 2u);
6398
6399 for (;;) {
6400 if ((err = mp_copy(&T, &t1)) != MP_OKAY) goto cleanup;
6401 i = 0;
6402 for (;;) {
6403 if (mp_cmp_d(&t1, 1uL) == MP_EQ) break;
6404 if ((err = mp_exptmod(&t1, &two, prime, &t1)) != MP_OKAY) goto cleanup;
6405 i++;
6406 }
6407 if (i == 0u) {
6408 if ((err = mp_copy(&R, ret)) != MP_OKAY) goto cleanup;
6409 err = MP_OKAY;
6410 goto cleanup;
6411 }
6412 if ((err = mp_sub_d(&M, i, &t1)) != MP_OKAY) goto cleanup;
6413 if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto cleanup;
6414 if ((err = mp_exptmod(&two, &t1, prime, &t1)) != MP_OKAY) goto cleanup;
6415 /* t1 = 2 ^ (M - i - 1) */
6416 if ((err = mp_exptmod(&C, &t1, prime, &t1)) != MP_OKAY) goto cleanup;
6417 /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
6418 if ((err = mp_sqrmod(&t1, prime, &C)) != MP_OKAY) goto cleanup;
6419 /* C = (t1 * t1) mod prime */
6420 if ((err = mp_mulmod(&R, &t1, prime, &R)) != MP_OKAY) goto cleanup;
6421 /* R = (R * t1) mod prime */
6422 if ((err = mp_mulmod(&T, &C, prime, &T)) != MP_OKAY) goto cleanup;
6423 /* T = (T * C) mod prime */
6424 mp_set(&M, i);
6425 /* M = i */
6426 }
6427
6428 cleanup:
6429 mp_clear_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL);
6430 return err;
6431 }
6432
6433 #endif
6434
6435 /* End: bn_mp_sqrtmod_prime.c */
6436
6437 /* Start: bn_mp_sub.c */
6438 #include "tommath_private.h"
6439 #ifdef BN_MP_SUB_C
6440 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6441 /* SPDX-License-Identifier: Unlicense */
6442
6443 /* high level subtraction (handles signs) */
mp_sub(const mp_int * a,const mp_int * b,mp_int * c)6444 mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
6445 {
6446 mp_sign sa = a->sign, sb = b->sign;
6447 mp_err err;
6448
6449 if (sa != sb) {
6450 /* subtract a negative from a positive, OR */
6451 /* subtract a positive from a negative. */
6452 /* In either case, ADD their magnitudes, */
6453 /* and use the sign of the first number. */
6454 c->sign = sa;
6455 err = s_mp_add(a, b, c);
6456 } else {
6457 /* subtract a positive from a positive, OR */
6458 /* subtract a negative from a negative. */
6459 /* First, take the difference between their */
6460 /* magnitudes, then... */
6461 if (mp_cmp_mag(a, b) != MP_LT) {
6462 /* Copy the sign from the first */
6463 c->sign = sa;
6464 /* The first has a larger or equal magnitude */
6465 err = s_mp_sub(a, b, c);
6466 } else {
6467 /* The result has the *opposite* sign from */
6468 /* the first number. */
6469 c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
6470 /* The second has a larger magnitude */
6471 err = s_mp_sub(b, a, c);
6472 }
6473 }
6474 return err;
6475 }
6476
6477 #endif
6478
6479 /* End: bn_mp_sub.c */
6480
6481 /* Start: bn_mp_sub_d.c */
6482 #include "tommath_private.h"
6483 #ifdef BN_MP_SUB_D_C
6484 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6485 /* SPDX-License-Identifier: Unlicense */
6486
6487 /* single digit subtraction */
mp_sub_d(const mp_int * a,mp_digit b,mp_int * c)6488 mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c)
6489 {
6490 mp_digit *tmpa, *tmpc;
6491 mp_err err;
6492 int ix, oldused;
6493
6494 /* grow c as required */
6495 if (c->alloc < (a->used + 1)) {
6496 if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) {
6497 return err;
6498 }
6499 }
6500
6501 /* if a is negative just do an unsigned
6502 * addition [with fudged signs]
6503 */
6504 if (a->sign == MP_NEG) {
6505 mp_int a_ = *a;
6506 a_.sign = MP_ZPOS;
6507 err = mp_add_d(&a_, b, c);
6508 c->sign = MP_NEG;
6509
6510 /* clamp */
6511 mp_clamp(c);
6512
6513 return err;
6514 }
6515
6516 /* setup regs */
6517 oldused = c->used;
6518 tmpa = a->dp;
6519 tmpc = c->dp;
6520
6521 /* if a <= b simply fix the single digit */
6522 if (((a->used == 1) && (a->dp[0] <= b)) || (a->used == 0)) {
6523 if (a->used == 1) {
6524 *tmpc++ = b - *tmpa;
6525 } else {
6526 *tmpc++ = b;
6527 }
6528 ix = 1;
6529
6530 /* negative/1digit */
6531 c->sign = MP_NEG;
6532 c->used = 1;
6533 } else {
6534 mp_digit mu = b;
6535
6536 /* positive/size */
6537 c->sign = MP_ZPOS;
6538 c->used = a->used;
6539
6540 /* subtract digits, mu is carry */
6541 for (ix = 0; ix < a->used; ix++) {
6542 *tmpc = *tmpa++ - mu;
6543 mu = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u);
6544 *tmpc++ &= MP_MASK;
6545 }
6546 }
6547
6548 /* zero excess digits */
6549 MP_ZERO_DIGITS(tmpc, oldused - ix);
6550
6551 mp_clamp(c);
6552 return MP_OKAY;
6553 }
6554
6555 #endif
6556
6557 /* End: bn_mp_sub_d.c */
6558
6559 /* Start: bn_mp_submod.c */
6560 #include "tommath_private.h"
6561 #ifdef BN_MP_SUBMOD_C
6562 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6563 /* SPDX-License-Identifier: Unlicense */
6564
6565 /* d = a - b (mod c) */
mp_submod(const mp_int * a,const mp_int * b,const mp_int * c,mp_int * d)6566 mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d)
6567 {
6568 mp_err err;
6569 mp_int t;
6570
6571 if ((err = mp_init(&t)) != MP_OKAY) {
6572 return err;
6573 }
6574
6575 if ((err = mp_sub(a, b, &t)) != MP_OKAY) {
6576 goto LBL_ERR;
6577 }
6578 err = mp_mod(&t, c, d);
6579
6580 LBL_ERR:
6581 mp_clear(&t);
6582 return err;
6583 }
6584 #endif
6585
6586 /* End: bn_mp_submod.c */
6587
6588 /* Start: bn_mp_to_radix.c */
6589 #include "tommath_private.h"
6590 #ifdef BN_MP_TO_RADIX_C
6591 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6592 /* SPDX-License-Identifier: Unlicense */
6593
6594 /* stores a bignum as a ASCII string in a given radix (2..64)
6595 *
6596 * Stores upto "size - 1" chars and always a NULL byte, puts the number of characters
6597 * written, including the '\0', in "written".
6598 */
mp_to_radix(const mp_int * a,char * str,size_t maxlen,size_t * written,int radix)6599 mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix)
6600 {
6601 size_t digs;
6602 mp_err err;
6603 mp_int t;
6604 mp_digit d;
6605 char *_s = str;
6606
6607 /* check range of radix and size*/
6608 if (maxlen < 2u) {
6609 return MP_BUF;
6610 }
6611 if ((radix < 2) || (radix > 64)) {
6612 return MP_VAL;
6613 }
6614
6615 /* quick out if its zero */
6616 if (MP_IS_ZERO(a)) {
6617 *str++ = '0';
6618 *str = '\0';
6619 if (written != NULL) {
6620 *written = 2u;
6621 }
6622 return MP_OKAY;
6623 }
6624
6625 if ((err = mp_init_copy(&t, a)) != MP_OKAY) {
6626 return err;
6627 }
6628
6629 /* if it is negative output a - */
6630 if (t.sign == MP_NEG) {
6631 /* we have to reverse our digits later... but not the - sign!! */
6632 ++_s;
6633
6634 /* store the flag and mark the number as positive */
6635 *str++ = '-';
6636 t.sign = MP_ZPOS;
6637
6638 /* subtract a char */
6639 --maxlen;
6640 }
6641 digs = 0u;
6642 while (!MP_IS_ZERO(&t)) {
6643 if (--maxlen < 1u) {
6644 /* no more room */
6645 err = MP_BUF;
6646 goto LBL_ERR;
6647 }
6648 if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) {
6649 goto LBL_ERR;
6650 }
6651 *str++ = mp_s_rmap[d];
6652 ++digs;
6653 }
6654 /* reverse the digits of the string. In this case _s points
6655 * to the first digit [exluding the sign] of the number
6656 */
6657 s_mp_reverse((unsigned char *)_s, digs);
6658
6659 /* append a NULL so the string is properly terminated */
6660 *str = '\0';
6661 digs++;
6662
6663 if (written != NULL) {
6664 *written = (a->sign == MP_NEG) ? (digs + 1u): digs;
6665 }
6666
6667 LBL_ERR:
6668 mp_clear(&t);
6669 return err;
6670 }
6671
6672 #endif
6673
6674 /* End: bn_mp_to_radix.c */
6675
6676 /* Start: bn_mp_to_sbin.c */
6677 #include "tommath_private.h"
6678 #ifdef BN_MP_TO_SBIN_C
6679 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6680 /* SPDX-License-Identifier: Unlicense */
6681
6682 /* store in signed [big endian] format */
mp_to_sbin(const mp_int * a,unsigned char * buf,size_t maxlen,size_t * written)6683 mp_err mp_to_sbin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written)
6684 {
6685 mp_err err;
6686 if (maxlen == 0u) {
6687 return MP_BUF;
6688 }
6689 if ((err = mp_to_ubin(a, buf + 1, maxlen - 1u, written)) != MP_OKAY) {
6690 return err;
6691 }
6692 if (written != NULL) {
6693 (*written)++;
6694 }
6695 buf[0] = (a->sign == MP_ZPOS) ? (unsigned char)0 : (unsigned char)1;
6696 return MP_OKAY;
6697 }
6698 #endif
6699
6700 /* End: bn_mp_to_sbin.c */
6701
6702 /* Start: bn_mp_to_ubin.c */
6703 #include "tommath_private.h"
6704 #ifdef BN_MP_TO_UBIN_C
6705 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6706 /* SPDX-License-Identifier: Unlicense */
6707
6708 /* store in unsigned [big endian] format */
mp_to_ubin(const mp_int * a,unsigned char * buf,size_t maxlen,size_t * written)6709 mp_err mp_to_ubin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written)
6710 {
6711 size_t x, count;
6712 mp_err err;
6713 mp_int t;
6714
6715 count = mp_ubin_size(a);
6716 if (count > maxlen) {
6717 return MP_BUF;
6718 }
6719
6720 if ((err = mp_init_copy(&t, a)) != MP_OKAY) {
6721 return err;
6722 }
6723
6724 for (x = count; x --> 0u;) {
6725 #ifndef MP_8BIT
6726 buf[x] = (unsigned char)(t.dp[0] & 255u);
6727 #else
6728 buf[x] = (unsigned char)(t.dp[0] | ((t.dp[1] & 1u) << 7));
6729 #endif
6730 if ((err = mp_div_2d(&t, 8, &t, NULL)) != MP_OKAY) {
6731 goto LBL_ERR;
6732 }
6733 }
6734
6735 if (written != NULL) {
6736 *written = count;
6737 }
6738
6739 LBL_ERR:
6740 mp_clear(&t);
6741 return err;
6742 }
6743 #endif
6744
6745 /* End: bn_mp_to_ubin.c */
6746
6747 /* Start: bn_mp_ubin_size.c */
6748 #include "tommath_private.h"
6749 #ifdef BN_MP_UBIN_SIZE_C
6750 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6751 /* SPDX-License-Identifier: Unlicense */
6752
6753 /* get the size for an unsigned equivalent */
mp_ubin_size(const mp_int * a)6754 size_t mp_ubin_size(const mp_int *a)
6755 {
6756 size_t size = (size_t)mp_count_bits(a);
6757 return (size / 8u) + (((size & 7u) != 0u) ? 1u : 0u);
6758 }
6759 #endif
6760
6761 /* End: bn_mp_ubin_size.c */
6762
6763 /* Start: bn_mp_unpack.c */
6764 #include "tommath_private.h"
6765 #ifdef BN_MP_UNPACK_C
6766 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6767 /* SPDX-License-Identifier: Unlicense */
6768
6769 /* based on gmp's mpz_import.
6770 * see http://gmplib.org/manual/Integer-Import-and-Export.html
6771 */
mp_unpack(mp_int * rop,size_t count,mp_order order,size_t size,mp_endian endian,size_t nails,const void * op)6772 mp_err mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size,
6773 mp_endian endian, size_t nails, const void *op)
6774 {
6775 mp_err err;
6776 size_t odd_nails, nail_bytes, i, j;
6777 unsigned char odd_nail_mask;
6778
6779 mp_zero(rop);
6780
6781 if (endian == MP_NATIVE_ENDIAN) {
6782 MP_GET_ENDIANNESS(endian);
6783 }
6784
6785 odd_nails = (nails % 8u);
6786 odd_nail_mask = 0xff;
6787 for (i = 0; i < odd_nails; ++i) {
6788 odd_nail_mask ^= (unsigned char)(1u << (7u - i));
6789 }
6790 nail_bytes = nails / 8u;
6791
6792 for (i = 0; i < count; ++i) {
6793 for (j = 0; j < (size - nail_bytes); ++j) {
6794 unsigned char byte = *((const unsigned char *)op +
6795 (((order == MP_MSB_FIRST) ? i : ((count - 1u) - i)) * size) +
6796 ((endian == MP_BIG_ENDIAN) ? (j + nail_bytes) : (((size - 1u) - j) - nail_bytes)));
6797
6798 if ((err = mp_mul_2d(rop, (j == 0u) ? (int)(8u - odd_nails) : 8, rop)) != MP_OKAY) {
6799 return err;
6800 }
6801
6802 rop->dp[0] |= (j == 0u) ? (mp_digit)(byte & odd_nail_mask) : (mp_digit)byte;
6803 rop->used += 1;
6804 }
6805 }
6806
6807 mp_clamp(rop);
6808
6809 return MP_OKAY;
6810 }
6811
6812 #endif
6813
6814 /* End: bn_mp_unpack.c */
6815
6816 /* Start: bn_mp_xor.c */
6817 #include "tommath_private.h"
6818 #ifdef BN_MP_XOR_C
6819 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6820 /* SPDX-License-Identifier: Unlicense */
6821
6822 /* two complement xor */
mp_xor(const mp_int * a,const mp_int * b,mp_int * c)6823 mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c)
6824 {
6825 int used = MP_MAX(a->used, b->used) + 1, i;
6826 mp_err err;
6827 mp_digit ac = 1, bc = 1, cc = 1;
6828 mp_sign csign = (a->sign != b->sign) ? MP_NEG : MP_ZPOS;
6829
6830 if (c->alloc < used) {
6831 if ((err = mp_grow(c, used)) != MP_OKAY) {
6832 return err;
6833 }
6834 }
6835
6836 for (i = 0; i < used; i++) {
6837 mp_digit x, y;
6838
6839 /* convert to two complement if negative */
6840 if (a->sign == MP_NEG) {
6841 ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK);
6842 x = ac & MP_MASK;
6843 ac >>= MP_DIGIT_BIT;
6844 } else {
6845 x = (i >= a->used) ? 0uL : a->dp[i];
6846 }
6847
6848 /* convert to two complement if negative */
6849 if (b->sign == MP_NEG) {
6850 bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK);
6851 y = bc & MP_MASK;
6852 bc >>= MP_DIGIT_BIT;
6853 } else {
6854 y = (i >= b->used) ? 0uL : b->dp[i];
6855 }
6856
6857 c->dp[i] = x ^ y;
6858
6859 /* convert to to sign-magnitude if negative */
6860 if (csign == MP_NEG) {
6861 cc += ~c->dp[i] & MP_MASK;
6862 c->dp[i] = cc & MP_MASK;
6863 cc >>= MP_DIGIT_BIT;
6864 }
6865 }
6866
6867 c->used = used;
6868 c->sign = csign;
6869 mp_clamp(c);
6870 return MP_OKAY;
6871 }
6872 #endif
6873
6874 /* End: bn_mp_xor.c */
6875
6876 /* Start: bn_mp_zero.c */
6877 #include "tommath_private.h"
6878 #ifdef BN_MP_ZERO_C
6879 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6880 /* SPDX-License-Identifier: Unlicense */
6881
6882 /* set to zero */
mp_zero(mp_int * a)6883 void mp_zero(mp_int *a)
6884 {
6885 a->sign = MP_ZPOS;
6886 a->used = 0;
6887 MP_ZERO_DIGITS(a->dp, a->alloc);
6888 }
6889 #endif
6890
6891 /* End: bn_mp_zero.c */
6892
6893 /* Start: bn_prime_tab.c */
6894 #include "tommath_private.h"
6895 #ifdef BN_PRIME_TAB_C
6896 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6897 /* SPDX-License-Identifier: Unlicense */
6898
6899 const mp_digit ltm_prime_tab[] = {
6900 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
6901 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
6902 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
6903 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
6904 #ifndef MP_8BIT
6905 0x0083,
6906 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
6907 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
6908 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
6909 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
6910
6911 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
6912 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
6913 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
6914 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
6915 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
6916 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
6917 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
6918 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
6919
6920 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
6921 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
6922 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
6923 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
6924 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
6925 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
6926 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
6927 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
6928
6929 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
6930 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
6931 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
6932 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
6933 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
6934 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
6935 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
6936 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
6937 #endif
6938 };
6939
6940 #if defined(__GNUC__) && __GNUC__ >= 4
6941 #pragma GCC diagnostic push
6942 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
6943 const mp_digit *s_mp_prime_tab = ltm_prime_tab;
6944 #pragma GCC diagnostic pop
6945 #elif defined(_MSC_VER) && _MSC_VER >= 1500
6946 #pragma warning(push)
6947 #pragma warning(disable: 4996)
6948 const mp_digit *s_mp_prime_tab = ltm_prime_tab;
6949 #pragma warning(pop)
6950 #else
6951 const mp_digit *s_mp_prime_tab = ltm_prime_tab;
6952 #endif
6953
6954 #endif
6955
6956 /* End: bn_prime_tab.c */
6957
6958 /* Start: bn_s_mp_add.c */
6959 #include "tommath_private.h"
6960 #ifdef BN_S_MP_ADD_C
6961 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
6962 /* SPDX-License-Identifier: Unlicense */
6963
6964 /* low level addition, based on HAC pp.594, Algorithm 14.7 */
s_mp_add(const mp_int * a,const mp_int * b,mp_int * c)6965 mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c)
6966 {
6967 const mp_int *x;
6968 mp_err err;
6969 int olduse, min, max;
6970
6971 /* find sizes, we let |a| <= |b| which means we have to sort
6972 * them. "x" will point to the input with the most digits
6973 */
6974 if (a->used > b->used) {
6975 min = b->used;
6976 max = a->used;
6977 x = a;
6978 } else {
6979 min = a->used;
6980 max = b->used;
6981 x = b;
6982 }
6983
6984 /* init result */
6985 if (c->alloc < (max + 1)) {
6986 if ((err = mp_grow(c, max + 1)) != MP_OKAY) {
6987 return err;
6988 }
6989 }
6990
6991 /* get old used digit count and set new one */
6992 olduse = c->used;
6993 c->used = max + 1;
6994
6995 {
6996 mp_digit u, *tmpa, *tmpb, *tmpc;
6997 int i;
6998
6999 /* alias for digit pointers */
7000
7001 /* first input */
7002 tmpa = a->dp;
7003
7004 /* second input */
7005 tmpb = b->dp;
7006
7007 /* destination */
7008 tmpc = c->dp;
7009
7010 /* zero the carry */
7011 u = 0;
7012 for (i = 0; i < min; i++) {
7013 /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
7014 *tmpc = *tmpa++ + *tmpb++ + u;
7015
7016 /* U = carry bit of T[i] */
7017 u = *tmpc >> (mp_digit)MP_DIGIT_BIT;
7018
7019 /* take away carry bit from T[i] */
7020 *tmpc++ &= MP_MASK;
7021 }
7022
7023 /* now copy higher words if any, that is in A+B
7024 * if A or B has more digits add those in
7025 */
7026 if (min != max) {
7027 for (; i < max; i++) {
7028 /* T[i] = X[i] + U */
7029 *tmpc = x->dp[i] + u;
7030
7031 /* U = carry bit of T[i] */
7032 u = *tmpc >> (mp_digit)MP_DIGIT_BIT;
7033
7034 /* take away carry bit from T[i] */
7035 *tmpc++ &= MP_MASK;
7036 }
7037 }
7038
7039 /* add carry */
7040 *tmpc++ = u;
7041
7042 /* clear digits above oldused */
7043 MP_ZERO_DIGITS(tmpc, olduse - c->used);
7044 }
7045
7046 mp_clamp(c);
7047 return MP_OKAY;
7048 }
7049 #endif
7050
7051 /* End: bn_s_mp_add.c */
7052
7053 /* Start: bn_s_mp_balance_mul.c */
7054 #include "tommath_private.h"
7055 #ifdef BN_S_MP_BALANCE_MUL_C
7056 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
7057 /* SPDX-License-Identifier: Unlicense */
7058
7059 /* single-digit multiplication with the smaller number as the single-digit */
s_mp_balance_mul(const mp_int * a,const mp_int * b,mp_int * c)7060 mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c)
7061 {
7062 int count, len_a, len_b, nblocks, i, j, bsize;
7063 mp_int a0, tmp, A, B, r;
7064 mp_err err;
7065
7066 len_a = a->used;
7067 len_b = b->used;
7068
7069 nblocks = MP_MAX(a->used, b->used) / MP_MIN(a->used, b->used);
7070 bsize = MP_MIN(a->used, b->used) ;
7071
7072 if ((err = mp_init_size(&a0, bsize + 2)) != MP_OKAY) {
7073 return err;
7074 }
7075 if ((err = mp_init_multi(&tmp, &r, NULL)) != MP_OKAY) {
7076 mp_clear(&a0);
7077 return err;
7078 }
7079
7080 /* Make sure that A is the larger one*/
7081 if (len_a < len_b) {
7082 B = *a;
7083 A = *b;
7084 } else {
7085 A = *a;
7086 B = *b;
7087 }
7088
7089 for (i = 0, j=0; i < nblocks; i++) {
7090 /* Cut a slice off of a */
7091 a0.used = 0;
7092 for (count = 0; count < bsize; count++) {
7093 a0.dp[count] = A.dp[ j++ ];
7094 a0.used++;
7095 }
7096 mp_clamp(&a0);
7097 /* Multiply with b */
7098 if ((err = mp_mul(&a0, &B, &tmp)) != MP_OKAY) {
7099 goto LBL_ERR;
7100 }
7101 /* Shift tmp to the correct position */
7102 if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) {
7103 goto LBL_ERR;
7104 }
7105 /* Add to output. No carry needed */
7106 if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) {
7107 goto LBL_ERR;
7108 }
7109 }
7110 /* The left-overs; there are always left-overs */
7111 if (j < A.used) {
7112 a0.used = 0;
7113 for (count = 0; j < A.used; count++) {
7114 a0.dp[count] = A.dp[ j++ ];
7115 a0.used++;
7116 }
7117 mp_clamp(&a0);
7118 if ((err = mp_mul(&a0, &B, &tmp)) != MP_OKAY) {
7119 goto LBL_ERR;
7120 }
7121 if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) {
7122 goto LBL_ERR;
7123 }
7124 if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) {
7125 goto LBL_ERR;
7126 }
7127 }
7128
7129 mp_exch(&r,c);
7130 LBL_ERR:
7131 mp_clear_multi(&a0, &tmp, &r,NULL);
7132 return err;
7133 }
7134 #endif
7135
7136 /* End: bn_s_mp_balance_mul.c */
7137
7138 /* Start: bn_s_mp_exptmod.c */
7139 #include "tommath_private.h"
7140 #ifdef BN_S_MP_EXPTMOD_C
7141 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
7142 /* SPDX-License-Identifier: Unlicense */
7143
7144 #ifdef MP_LOW_MEM
7145 # define TAB_SIZE 32
7146 # define MAX_WINSIZE 5
7147 #else
7148 # define TAB_SIZE 256
7149 # define MAX_WINSIZE 0
7150 #endif
7151
s_mp_exptmod(const mp_int * G,const mp_int * X,const mp_int * P,mp_int * Y,int redmode)7152 mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode)
7153 {
7154 mp_int M[TAB_SIZE], res, mu;
7155 mp_digit buf;
7156 mp_err err;
7157 int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
7158 mp_err(*redux)(mp_int *x, const mp_int *m, const mp_int *mu);
7159
7160 /* find window size */
7161 x = mp_count_bits(X);
7162 if (x <= 7) {
7163 winsize = 2;
7164 } else if (x <= 36) {
7165 winsize = 3;
7166 } else if (x <= 140) {
7167 winsize = 4;
7168 } else if (x <= 450) {
7169 winsize = 5;
7170 } else if (x <= 1303) {
7171 winsize = 6;
7172 } else if (x <= 3529) {
7173 winsize = 7;
7174 } else {
7175 winsize = 8;
7176 }
7177
7178 winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize;
7179
7180 /* init M array */
7181 /* init first cell */
7182 if ((err = mp_init(&M[1])) != MP_OKAY) {
7183 return err;
7184 }
7185
7186 /* now init the second half of the array */
7187 for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
7188 if ((err = mp_init(&M[x])) != MP_OKAY) {
7189 for (y = 1<<(winsize-1); y < x; y++) {
7190 mp_clear(&M[y]);
7191 }
7192 mp_clear(&M[1]);
7193 return err;
7194 }
7195 }
7196
7197 /* create mu, used for Barrett reduction */
7198 if ((err = mp_init(&mu)) != MP_OKAY) goto LBL_M;
7199
7200 if (redmode == 0) {
7201 if ((err = mp_reduce_setup(&mu, P)) != MP_OKAY) goto LBL_MU;
7202 redux = mp_reduce;
7203 } else {
7204 if ((err = mp_reduce_2k_setup_l(P, &mu)) != MP_OKAY) goto LBL_MU;
7205 redux = mp_reduce_2k_l;
7206 }
7207
7208 /* create M table
7209 *
7210 * The M table contains powers of the base,
7211 * e.g. M[x] = G**x mod P
7212 *
7213 * The first half of the table is not
7214 * computed though accept for M[0] and M[1]
7215 */
7216 if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) goto LBL_MU;
7217
7218 /* compute the value at M[1<<(winsize-1)] by squaring
7219 * M[1] (winsize-1) times
7220 */
7221 if ((err = mp_copy(&M[1], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU;
7222
7223 for (x = 0; x < (winsize - 1); x++) {
7224 /* square it */
7225 if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)],
7226 &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU;
7227
7228 /* reduce modulo P */
7229 if ((err = redux(&M[(size_t)1 << (winsize - 1)], P, &mu)) != MP_OKAY) goto LBL_MU;
7230 }
7231
7232 /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
7233 * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
7234 */
7235 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
7236 if ((err = mp_mul(&M[x - 1], &M[1], &M[x])) != MP_OKAY) goto LBL_MU;
7237 if ((err = redux(&M[x], P, &mu)) != MP_OKAY) goto LBL_MU;
7238 }
7239
7240 /* setup result */
7241 if ((err = mp_init(&res)) != MP_OKAY) goto LBL_MU;
7242 mp_set(&res, 1uL);
7243
7244 /* set initial mode and bit cnt */
7245 mode = 0;
7246 bitcnt = 1;
7247 buf = 0;
7248 digidx = X->used - 1;
7249 bitcpy = 0;
7250 bitbuf = 0;
7251
7252 for (;;) {
7253 /* grab next digit as required */
7254 if (--bitcnt == 0) {
7255 /* if digidx == -1 we are out of digits */
7256 if (digidx == -1) {
7257 break;
7258 }
7259 /* read next digit and reset the bitcnt */
7260 buf = X->dp[digidx--];
7261 bitcnt = (int)MP_DIGIT_BIT;
7262 }
7263
7264 /* grab the next msb from the exponent */
7265 y = (buf >> (mp_digit)(MP_DIGIT_BIT - 1)) & 1uL;
7266 buf <<= (mp_digit)1;
7267
7268 /* if the bit is zero and mode == 0 then we ignore it
7269 * These represent the leading zero bits before the first 1 bit
7270 * in the exponent. Technically this opt is not required but it
7271 * does lower the # of trivial squaring/reductions used
7272 */
7273 if ((mode == 0) && (y == 0)) {
7274 continue;
7275 }
7276
7277 /* if the bit is zero and mode == 1 then we square */
7278 if ((mode == 1) && (y == 0)) {
7279 if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES;
7280 if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES;
7281 continue;
7282 }
7283
7284 /* else we add it to the window */
7285 bitbuf |= (y << (winsize - ++bitcpy));
7286 mode = 2;
7287
7288 if (bitcpy == winsize) {
7289 /* ok window is filled so square as required and multiply */
7290 /* square first */
7291 for (x = 0; x < winsize; x++) {
7292 if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES;
7293 if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES;
7294 }
7295
7296 /* then multiply */
7297 if ((err = mp_mul(&res, &M[bitbuf], &res)) != MP_OKAY) goto LBL_RES;
7298 if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES;
7299
7300 /* empty window and reset */
7301 bitcpy = 0;
7302 bitbuf = 0;
7303 mode = 1;
7304 }
7305 }
7306
7307 /* if bits remain then square/multiply */
7308 if ((mode == 2) && (bitcpy > 0)) {
7309 /* square then multiply if the bit is set */
7310 for (x = 0; x < bitcpy; x++) {
7311 if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES;
7312 if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES;
7313
7314 bitbuf <<= 1;
7315 if ((bitbuf & (1 << winsize)) != 0) {
7316 /* then multiply */
7317 if ((err = mp_mul(&res, &M[1], &res)) != MP_OKAY) goto LBL_RES;
7318 if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES;
7319 }
7320 }
7321 }
7322
7323 mp_exch(&res, Y);
7324 err = MP_OKAY;
7325 LBL_RES:
7326 mp_clear(&res);
7327 LBL_MU:
7328 mp_clear(&mu);
7329 LBL_M:
7330 mp_clear(&M[1]);
7331 for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
7332 mp_clear(&M[x]);
7333 }
7334 return err;
7335 }
7336 #endif
7337
7338 /* End: bn_s_mp_exptmod.c */
7339
7340 /* Start: bn_s_mp_exptmod_fast.c */
7341 #include "tommath_private.h"
7342 #ifdef BN_S_MP_EXPTMOD_FAST_C
7343 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
7344 /* SPDX-License-Identifier: Unlicense */
7345
7346 /* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
7347 *
7348 * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
7349 * The value of k changes based on the size of the exponent.
7350 *
7351 * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
7352 */
7353
7354 #ifdef MP_LOW_MEM
7355 # define TAB_SIZE 32
7356 # define MAX_WINSIZE 5
7357 #else
7358 # define TAB_SIZE 256
7359 # define MAX_WINSIZE 0
7360 #endif
7361
s_mp_exptmod_fast(const mp_int * G,const mp_int * X,const mp_int * P,mp_int * Y,int redmode)7362 mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode)
7363 {
7364 mp_int M[TAB_SIZE], res;
7365 mp_digit buf, mp;
7366 int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
7367 mp_err err;
7368
7369 /* use a pointer to the reduction algorithm. This allows us to use
7370 * one of many reduction algorithms without modding the guts of
7371 * the code with if statements everywhere.
7372 */
7373 mp_err(*redux)(mp_int *x, const mp_int *n, mp_digit rho);
7374
7375 /* find window size */
7376 x = mp_count_bits(X);
7377 if (x <= 7) {
7378 winsize = 2;
7379 } else if (x <= 36) {
7380 winsize = 3;
7381 } else if (x <= 140) {
7382 winsize = 4;
7383 } else if (x <= 450) {
7384 winsize = 5;
7385 } else if (x <= 1303) {
7386 winsize = 6;
7387 } else if (x <= 3529) {
7388 winsize = 7;
7389 } else {
7390 winsize = 8;
7391 }
7392
7393 winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize;
7394
7395 /* init M array */
7396 /* init first cell */
7397 if ((err = mp_init_size(&M[1], P->alloc)) != MP_OKAY) {
7398 return err;
7399 }
7400
7401 /* now init the second half of the array */
7402 for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
7403 if ((err = mp_init_size(&M[x], P->alloc)) != MP_OKAY) {
7404 for (y = 1<<(winsize-1); y < x; y++) {
7405 mp_clear(&M[y]);
7406 }
7407 mp_clear(&M[1]);
7408 return err;
7409 }
7410 }
7411
7412 /* determine and setup reduction code */
7413 if (redmode == 0) {
7414 if (MP_HAS(MP_MONTGOMERY_SETUP)) {
7415 /* now setup montgomery */
7416 if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) goto LBL_M;
7417 } else {
7418 err = MP_VAL;
7419 goto LBL_M;
7420 }
7421
7422 /* automatically pick the comba one if available (saves quite a few calls/ifs) */
7423 if (MP_HAS(S_MP_MONTGOMERY_REDUCE_FAST) &&
7424 (((P->used * 2) + 1) < MP_WARRAY) &&
7425 (P->used < MP_MAXFAST)) {
7426 redux = s_mp_montgomery_reduce_fast;
7427 } else if (MP_HAS(MP_MONTGOMERY_REDUCE)) {
7428 /* use slower baseline Montgomery method */
7429 redux = mp_montgomery_reduce;
7430 } else {
7431 err = MP_VAL;
7432 goto LBL_M;
7433 }
7434 } else if (redmode == 1) {
7435 if (MP_HAS(MP_DR_SETUP) && MP_HAS(MP_DR_REDUCE)) {
7436 /* setup DR reduction for moduli of the form B**k - b */
7437 mp_dr_setup(P, &mp);
7438 redux = mp_dr_reduce;
7439 } else {
7440 err = MP_VAL;
7441 goto LBL_M;
7442 }
7443 } else if (MP_HAS(MP_REDUCE_2K_SETUP) && MP_HAS(MP_REDUCE_2K)) {
7444 /* setup DR reduction for moduli of the form 2**k - b */
7445 if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) goto LBL_M;
7446 redux = mp_reduce_2k;
7447 } else {
7448 err = MP_VAL;
7449 goto LBL_M;
7450 }
7451
7452 /* setup result */
7453 if ((err = mp_init_size(&res, P->alloc)) != MP_OKAY) goto LBL_M;
7454
7455 /* create M table
7456 *
7457
7458 *
7459 * The first half of the table is not computed though accept for M[0] and M[1]
7460 */
7461
7462 if (redmode == 0) {
7463 if (MP_HAS(MP_MONTGOMERY_CALC_NORMALIZATION)) {
7464 /* now we need R mod m */
7465 if ((err = mp_montgomery_calc_normalization(&res, P)) != MP_OKAY) goto LBL_RES;
7466
7467 /* now set M[1] to G * R mod m */
7468 if ((err = mp_mulmod(G, &res, P, &M[1])) != MP_OKAY) goto LBL_RES;
7469 } else {
7470 err = MP_VAL;
7471 goto LBL_RES;
7472 }
7473 } else {
7474 mp_set(&res, 1uL);
7475 if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) goto LBL_RES;
7476 }
7477
7478 /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
7479 if ((err = mp_copy(&M[1], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_RES;
7480
7481 for (x = 0; x < (winsize - 1); x++) {
7482 if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_RES;
7483 if ((err = redux(&M[(size_t)1 << (winsize - 1)], P, mp)) != MP_OKAY) goto LBL_RES;
7484 }
7485
7486 /* create upper table */
7487 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
7488 if ((err = mp_mul(&M[x - 1], &M[1], &M[x])) != MP_OKAY) goto LBL_RES;
7489 if ((err = redux(&M[x], P, mp)) != MP_OKAY) goto LBL_RES;
7490 }
7491
7492 /* set initial mode and bit cnt */
7493 mode = 0;
7494 bitcnt = 1;
7495 buf = 0;
7496 digidx = X->used - 1;
7497 bitcpy = 0;
7498 bitbuf = 0;
7499
7500 for (;;) {
7501 /* grab next digit as required */
7502 if (--bitcnt == 0) {
7503 /* if digidx == -1 we are out of digits so break */
7504 if (digidx == -1) {
7505 break;
7506 }
7507 /* read next digit and reset bitcnt */
7508 buf = X->dp[digidx--];
7509 bitcnt = (int)MP_DIGIT_BIT;
7510 }
7511
7512 /* grab the next msb from the exponent */
7513 y = (mp_digit)(buf >> (MP_DIGIT_BIT - 1)) & 1uL;
7514 buf <<= (mp_digit)1;
7515
7516 /* if the bit is zero and mode == 0 then we ignore it
7517 * These represent the leading zero bits before the first 1 bit
7518 * in the exponent. Technically this opt is not required but it
7519 * does lower the # of trivial squaring/reductions used
7520 */
7521 if ((mode == 0) && (y == 0)) {
7522 continue;
7523 }
7524
7525 /* if the bit is zero and mode == 1 then we square */
7526 if ((mode == 1) && (y == 0)) {
7527 if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES;
7528 if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES;
7529 continue;
7530 }
7531
7532 /* else we add it to the window */
7533 bitbuf |= (y << (winsize - ++bitcpy));
7534 mode = 2;
7535
7536 if (bitcpy == winsize) {
7537 /* ok window is filled so square as required and multiply */
7538 /* square first */
7539 for (x = 0; x < winsize; x++) {
7540 if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES;
7541 if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES;
7542 }
7543
7544 /* then multiply */
7545 if ((err = mp_mul(&res, &M[bitbuf], &res)) != MP_OKAY) goto LBL_RES;
7546 if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES;
7547
7548 /* empty window and reset */
7549 bitcpy = 0;
7550 bitbuf = 0;
7551 mode = 1;
7552 }
7553 }
7554
7555 /* if bits remain then square/multiply */
7556 if ((mode == 2) && (bitcpy > 0)) {
7557 /* square then multiply if the bit is set */
7558 for (x = 0; x < bitcpy; x++) {
7559 if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES;
7560 if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES;
7561
7562 /* get next bit of the window */
7563 bitbuf <<= 1;
7564 if ((bitbuf & (1 << winsize)) != 0) {
7565 /* then multiply */
7566 if ((err = mp_mul(&res, &M[1], &res)) != MP_OKAY) goto LBL_RES;
7567 if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES;
7568 }
7569 }
7570 }
7571
7572 if (redmode == 0) {
7573 /* fixup result if Montgomery reduction is used
7574 * recall that any value in a Montgomery system is
7575 * actually multiplied by R mod n. So we have
7576 * to reduce one more time to cancel out the factor
7577 * of R.
7578 */
7579 if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES;
7580 }
7581
7582 /* swap res with Y */
7583 mp_exch(&res, Y);
7584 err = MP_OKAY;
7585 LBL_RES:
7586 mp_clear(&res);
7587 LBL_M:
7588 mp_clear(&M[1]);
7589 for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
7590 mp_clear(&M[x]);
7591 }
7592 return err;
7593 }
7594 #endif
7595
7596 /* End: bn_s_mp_exptmod_fast.c */
7597
7598 /* Start: bn_s_mp_get_bit.c */
7599 #include "tommath_private.h"
7600 #ifdef BN_S_MP_GET_BIT_C
7601
7602 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
7603 /* SPDX-License-Identifier: Unlicense */
7604
7605 /* Get bit at position b and return MP_YES if the bit is 1, MP_NO if it is 0 */
s_mp_get_bit(const mp_int * a,unsigned int b)7606 mp_bool s_mp_get_bit(const mp_int *a, unsigned int b)
7607 {
7608 mp_digit bit;
7609 int limb = (int)(b / MP_DIGIT_BIT);
7610
7611 if (limb >= a->used) {
7612 return MP_NO;
7613 }
7614
7615 bit = (mp_digit)1 << (b % MP_DIGIT_BIT);
7616 return ((a->dp[limb] & bit) != 0u) ? MP_YES : MP_NO;
7617 }
7618
7619 #endif
7620
7621 /* End: bn_s_mp_get_bit.c */
7622
7623 /* Start: bn_s_mp_invmod_fast.c */
7624 #include "tommath_private.h"
7625 #ifdef BN_S_MP_INVMOD_FAST_C
7626 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
7627 /* SPDX-License-Identifier: Unlicense */
7628
7629 /* computes the modular inverse via binary extended euclidean algorithm,
7630 * that is c = 1/a mod b
7631 *
7632 * Based on slow invmod except this is optimized for the case where b is
7633 * odd as per HAC Note 14.64 on pp. 610
7634 */
s_mp_invmod_fast(const mp_int * a,const mp_int * b,mp_int * c)7635 mp_err s_mp_invmod_fast(const mp_int *a, const mp_int *b, mp_int *c)
7636 {
7637 mp_int x, y, u, v, B, D;
7638 mp_sign neg;
7639 mp_err err;
7640
7641 /* 2. [modified] b must be odd */
7642 if (MP_IS_EVEN(b)) {
7643 return MP_VAL;
7644 }
7645
7646 /* init all our temps */
7647 if ((err = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
7648 return err;
7649 }
7650
7651 /* x == modulus, y == value to invert */
7652 if ((err = mp_copy(b, &x)) != MP_OKAY) goto LBL_ERR;
7653
7654 /* we need y = |a| */
7655 if ((err = mp_mod(a, b, &y)) != MP_OKAY) goto LBL_ERR;
7656
7657 /* if one of x,y is zero return an error! */
7658 if (MP_IS_ZERO(&x) || MP_IS_ZERO(&y)) {
7659 err = MP_VAL;
7660 goto LBL_ERR;
7661 }
7662
7663 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
7664 if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR;
7665 if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR;
7666 mp_set(&D, 1uL);
7667
7668 top:
7669 /* 4. while u is even do */
7670 while (MP_IS_EVEN(&u)) {
7671 /* 4.1 u = u/2 */
7672 if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR;
7673
7674 /* 4.2 if B is odd then */
7675 if (MP_IS_ODD(&B)) {
7676 if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR;
7677 }
7678 /* B = B/2 */
7679 if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR;
7680 }
7681
7682 /* 5. while v is even do */
7683 while (MP_IS_EVEN(&v)) {
7684 /* 5.1 v = v/2 */
7685 if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR;
7686
7687 /* 5.2 if D is odd then */
7688 if (MP_IS_ODD(&D)) {
7689 /* D = (D-x)/2 */
7690 if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR;
7691 }
7692 /* D = D/2 */
7693 if ((err = mp_div_2(&D, &D)) != MP_OKAY) goto LBL_ERR;
7694 }
7695
7696 /* 6. if u >= v then */
7697 if (mp_cmp(&u, &v) != MP_LT) {
7698 /* u = u - v, B = B - D */
7699 if ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR;
7700
7701 if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR;
7702 } else {
7703 /* v - v - u, D = D - B */
7704 if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR;
7705
7706 if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR;
7707 }
7708
7709 /* if not zero goto step 4 */
7710 if (!MP_IS_ZERO(&u)) {
7711 goto top;
7712 }
7713
7714 /* now a = C, b = D, gcd == g*v */
7715
7716 /* if v != 1 then there is no inverse */
7717 if (mp_cmp_d(&v, 1uL) != MP_EQ) {
7718 err = MP_VAL;
7719 goto LBL_ERR;
7720 }
7721
7722 /* b is now the inverse */
7723 neg = a->sign;
7724 while (D.sign == MP_NEG) {
7725 if ((err = mp_add(&D, b, &D)) != MP_OKAY) goto LBL_ERR;
7726 }
7727
7728 /* too big */
7729 while (mp_cmp_mag(&D, b) != MP_LT) {
7730 if ((err = mp_sub(&D, b, &D)) != MP_OKAY) goto LBL_ERR;
7731 }
7732
7733 mp_exch(&D, c);
7734 c->sign = neg;
7735 err = MP_OKAY;
7736
7737 LBL_ERR:
7738 mp_clear_multi(&x, &y, &u, &v, &B, &D, NULL);
7739 return err;
7740 }
7741 #endif
7742
7743 /* End: bn_s_mp_invmod_fast.c */
7744
7745 /* Start: bn_s_mp_invmod_slow.c */
7746 #include "tommath_private.h"
7747 #ifdef BN_S_MP_INVMOD_SLOW_C
7748 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
7749 /* SPDX-License-Identifier: Unlicense */
7750
7751 /* hac 14.61, pp608 */
s_mp_invmod_slow(const mp_int * a,const mp_int * b,mp_int * c)7752 mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c)
7753 {
7754 mp_int x, y, u, v, A, B, C, D;
7755 mp_err err;
7756
7757 /* b cannot be negative */
7758 if ((b->sign == MP_NEG) || MP_IS_ZERO(b)) {
7759 return MP_VAL;
7760 }
7761
7762 /* init temps */
7763 if ((err = mp_init_multi(&x, &y, &u, &v,
7764 &A, &B, &C, &D, NULL)) != MP_OKAY) {
7765 return err;
7766 }
7767
7768 /* x = a, y = b */
7769 if ((err = mp_mod(a, b, &x)) != MP_OKAY) goto LBL_ERR;
7770 if ((err = mp_copy(b, &y)) != MP_OKAY) goto LBL_ERR;
7771
7772 /* 2. [modified] if x,y are both even then return an error! */
7773 if (MP_IS_EVEN(&x) && MP_IS_EVEN(&y)) {
7774 err = MP_VAL;
7775 goto LBL_ERR;
7776 }
7777
7778 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
7779 if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR;
7780 if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR;
7781 mp_set(&A, 1uL);
7782 mp_set(&D, 1uL);
7783
7784 top:
7785 /* 4. while u is even do */
7786 while (MP_IS_EVEN(&u)) {
7787 /* 4.1 u = u/2 */
7788 if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR;
7789
7790 /* 4.2 if A or B is odd then */
7791 if (MP_IS_ODD(&A) || MP_IS_ODD(&B)) {
7792 /* A = (A+y)/2, B = (B-x)/2 */
7793 if ((err = mp_add(&A, &y, &A)) != MP_OKAY) goto LBL_ERR;
7794 if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR;
7795 }
7796 /* A = A/2, B = B/2 */
7797 if ((err = mp_div_2(&A, &A)) != MP_OKAY) goto LBL_ERR;
7798 if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR;
7799 }
7800
7801 /* 5. while v is even do */
7802 while (MP_IS_EVEN(&v)) {
7803 /* 5.1 v = v/2 */
7804 if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR;
7805
7806 /* 5.2 if C or D is odd then */
7807 if (MP_IS_ODD(&C) || MP_IS_ODD(&D)) {
7808 /* C = (C+y)/2, D = (D-x)/2 */
7809 if ((err = mp_add(&C, &y, &C)) != MP_OKAY) goto LBL_ERR;
7810 if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR;
7811 }
7812 /* C = C/2, D = D/2 */
7813 if ((err = mp_div_2(&C, &C)) != MP_OKAY) goto LBL_ERR;
7814 if ((err = mp_div_2(&D, &D)) != MP_OKAY) goto LBL_ERR;
7815 }
7816
7817 /* 6. if u >= v then */
7818 if (mp_cmp(&u, &v) != MP_LT) {
7819 /* u = u - v, A = A - C, B = B - D */
7820 if ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR;
7821
7822 if ((err = mp_sub(&A, &C, &A)) != MP_OKAY) goto LBL_ERR;
7823
7824 if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR;
7825 } else {
7826 /* v - v - u, C = C - A, D = D - B */
7827 if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR;
7828
7829 if ((err = mp_sub(&C, &A, &C)) != MP_OKAY) goto LBL_ERR;
7830
7831 if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR;
7832 }
7833
7834 /* if not zero goto step 4 */
7835 if (!MP_IS_ZERO(&u)) {
7836 goto top;
7837 }
7838
7839 /* now a = C, b = D, gcd == g*v */
7840
7841 /* if v != 1 then there is no inverse */
7842 if (mp_cmp_d(&v, 1uL) != MP_EQ) {
7843 err = MP_VAL;
7844 goto LBL_ERR;
7845 }
7846
7847 /* if its too low */
7848 while (mp_cmp_d(&C, 0uL) == MP_LT) {
7849 if ((err = mp_add(&C, b, &C)) != MP_OKAY) goto LBL_ERR;
7850 }
7851
7852 /* too big */
7853 while (mp_cmp_mag(&C, b) != MP_LT) {
7854 if ((err = mp_sub(&C, b, &C)) != MP_OKAY) goto LBL_ERR;
7855 }
7856
7857 /* C is now the inverse */
7858 mp_exch(&C, c);
7859 err = MP_OKAY;
7860 LBL_ERR:
7861 mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL);
7862 return err;
7863 }
7864 #endif
7865
7866 /* End: bn_s_mp_invmod_slow.c */
7867
7868 /* Start: bn_s_mp_karatsuba_mul.c */
7869 #include "tommath_private.h"
7870 #ifdef BN_S_MP_KARATSUBA_MUL_C
7871 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
7872 /* SPDX-License-Identifier: Unlicense */
7873
7874 /* c = |a| * |b| using Karatsuba Multiplication using
7875 * three half size multiplications
7876 *
7877 * Let B represent the radix [e.g. 2**MP_DIGIT_BIT] and
7878 * let n represent half of the number of digits in
7879 * the min(a,b)
7880 *
7881 * a = a1 * B**n + a0
7882 * b = b1 * B**n + b0
7883 *
7884 * Then, a * b =>
7885 a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0
7886 *
7887 * Note that a1b1 and a0b0 are used twice and only need to be
7888 * computed once. So in total three half size (half # of
7889 * digit) multiplications are performed, a0b0, a1b1 and
7890 * (a1+b1)(a0+b0)
7891 *
7892 * Note that a multiplication of half the digits requires
7893 * 1/4th the number of single precision multiplications so in
7894 * total after one call 25% of the single precision multiplications
7895 * are saved. Note also that the call to mp_mul can end up back
7896 * in this function if the a0, a1, b0, or b1 are above the threshold.
7897 * This is known as divide-and-conquer and leads to the famous
7898 * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than
7899 * the standard O(N**2) that the baseline/comba methods use.
7900 * Generally though the overhead of this method doesn't pay off
7901 * until a certain size (N ~ 80) is reached.
7902 */
s_mp_karatsuba_mul(const mp_int * a,const mp_int * b,mp_int * c)7903 mp_err s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c)
7904 {
7905 mp_int x0, x1, y0, y1, t1, x0y0, x1y1;
7906 int B;
7907 mp_err err = MP_MEM; /* default the return code to an error */
7908
7909 /* min # of digits */
7910 B = MP_MIN(a->used, b->used);
7911
7912 /* now divide in two */
7913 B = B >> 1;
7914
7915 /* init copy all the temps */
7916 if (mp_init_size(&x0, B) != MP_OKAY) {
7917 goto LBL_ERR;
7918 }
7919 if (mp_init_size(&x1, a->used - B) != MP_OKAY) {
7920 goto X0;
7921 }
7922 if (mp_init_size(&y0, B) != MP_OKAY) {
7923 goto X1;
7924 }
7925 if (mp_init_size(&y1, b->used - B) != MP_OKAY) {
7926 goto Y0;
7927 }
7928
7929 /* init temps */
7930 if (mp_init_size(&t1, B * 2) != MP_OKAY) {
7931 goto Y1;
7932 }
7933 if (mp_init_size(&x0y0, B * 2) != MP_OKAY) {
7934 goto T1;
7935 }
7936 if (mp_init_size(&x1y1, B * 2) != MP_OKAY) {
7937 goto X0Y0;
7938 }
7939
7940 /* now shift the digits */
7941 x0.used = y0.used = B;
7942 x1.used = a->used - B;
7943 y1.used = b->used - B;
7944
7945 {
7946 int x;
7947 mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
7948
7949 /* we copy the digits directly instead of using higher level functions
7950 * since we also need to shift the digits
7951 */
7952 tmpa = a->dp;
7953 tmpb = b->dp;
7954
7955 tmpx = x0.dp;
7956 tmpy = y0.dp;
7957 for (x = 0; x < B; x++) {
7958 *tmpx++ = *tmpa++;
7959 *tmpy++ = *tmpb++;
7960 }
7961
7962 tmpx = x1.dp;
7963 for (x = B; x < a->used; x++) {
7964 *tmpx++ = *tmpa++;
7965 }
7966
7967 tmpy = y1.dp;
7968 for (x = B; x < b->used; x++) {
7969 *tmpy++ = *tmpb++;
7970 }
7971 }
7972
7973 /* only need to clamp the lower words since by definition the
7974 * upper words x1/y1 must have a known number of digits
7975 */
7976 mp_clamp(&x0);
7977 mp_clamp(&y0);
7978
7979 /* now calc the products x0y0 and x1y1 */
7980 /* after this x0 is no longer required, free temp [x0==t2]! */
7981 if (mp_mul(&x0, &y0, &x0y0) != MP_OKAY) {
7982 goto X1Y1; /* x0y0 = x0*y0 */
7983 }
7984 if (mp_mul(&x1, &y1, &x1y1) != MP_OKAY) {
7985 goto X1Y1; /* x1y1 = x1*y1 */
7986 }
7987
7988 /* now calc x1+x0 and y1+y0 */
7989 if (s_mp_add(&x1, &x0, &t1) != MP_OKAY) {
7990 goto X1Y1; /* t1 = x1 - x0 */
7991 }
7992 if (s_mp_add(&y1, &y0, &x0) != MP_OKAY) {
7993 goto X1Y1; /* t2 = y1 - y0 */
7994 }
7995 if (mp_mul(&t1, &x0, &t1) != MP_OKAY) {
7996 goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */
7997 }
7998
7999 /* add x0y0 */
8000 if (mp_add(&x0y0, &x1y1, &x0) != MP_OKAY) {
8001 goto X1Y1; /* t2 = x0y0 + x1y1 */
8002 }
8003 if (s_mp_sub(&t1, &x0, &t1) != MP_OKAY) {
8004 goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
8005 }
8006
8007 /* shift by B */
8008 if (mp_lshd(&t1, B) != MP_OKAY) {
8009 goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
8010 }
8011 if (mp_lshd(&x1y1, B * 2) != MP_OKAY) {
8012 goto X1Y1; /* x1y1 = x1y1 << 2*B */
8013 }
8014
8015 if (mp_add(&x0y0, &t1, &t1) != MP_OKAY) {
8016 goto X1Y1; /* t1 = x0y0 + t1 */
8017 }
8018 if (mp_add(&t1, &x1y1, c) != MP_OKAY) {
8019 goto X1Y1; /* t1 = x0y0 + t1 + x1y1 */
8020 }
8021
8022 /* Algorithm succeeded set the return code to MP_OKAY */
8023 err = MP_OKAY;
8024
8025 X1Y1:
8026 mp_clear(&x1y1);
8027 X0Y0:
8028 mp_clear(&x0y0);
8029 T1:
8030 mp_clear(&t1);
8031 Y1:
8032 mp_clear(&y1);
8033 Y0:
8034 mp_clear(&y0);
8035 X1:
8036 mp_clear(&x1);
8037 X0:
8038 mp_clear(&x0);
8039 LBL_ERR:
8040 return err;
8041 }
8042 #endif
8043
8044 /* End: bn_s_mp_karatsuba_mul.c */
8045
8046 /* Start: bn_s_mp_karatsuba_sqr.c */
8047 #include "tommath_private.h"
8048 #ifdef BN_S_MP_KARATSUBA_SQR_C
8049 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8050 /* SPDX-License-Identifier: Unlicense */
8051
8052 /* Karatsuba squaring, computes b = a*a using three
8053 * half size squarings
8054 *
8055 * See comments of karatsuba_mul for details. It
8056 * is essentially the same algorithm but merely
8057 * tuned to perform recursive squarings.
8058 */
s_mp_karatsuba_sqr(const mp_int * a,mp_int * b)8059 mp_err s_mp_karatsuba_sqr(const mp_int *a, mp_int *b)
8060 {
8061 mp_int x0, x1, t1, t2, x0x0, x1x1;
8062 int B;
8063 mp_err err = MP_MEM;
8064
8065 /* min # of digits */
8066 B = a->used;
8067
8068 /* now divide in two */
8069 B = B >> 1;
8070
8071 /* init copy all the temps */
8072 if (mp_init_size(&x0, B) != MP_OKAY)
8073 goto LBL_ERR;
8074 if (mp_init_size(&x1, a->used - B) != MP_OKAY)
8075 goto X0;
8076
8077 /* init temps */
8078 if (mp_init_size(&t1, a->used * 2) != MP_OKAY)
8079 goto X1;
8080 if (mp_init_size(&t2, a->used * 2) != MP_OKAY)
8081 goto T1;
8082 if (mp_init_size(&x0x0, B * 2) != MP_OKAY)
8083 goto T2;
8084 if (mp_init_size(&x1x1, (a->used - B) * 2) != MP_OKAY)
8085 goto X0X0;
8086
8087 {
8088 int x;
8089 mp_digit *dst, *src;
8090
8091 src = a->dp;
8092
8093 /* now shift the digits */
8094 dst = x0.dp;
8095 for (x = 0; x < B; x++) {
8096 *dst++ = *src++;
8097 }
8098
8099 dst = x1.dp;
8100 for (x = B; x < a->used; x++) {
8101 *dst++ = *src++;
8102 }
8103 }
8104
8105 x0.used = B;
8106 x1.used = a->used - B;
8107
8108 mp_clamp(&x0);
8109
8110 /* now calc the products x0*x0 and x1*x1 */
8111 if (mp_sqr(&x0, &x0x0) != MP_OKAY)
8112 goto X1X1; /* x0x0 = x0*x0 */
8113 if (mp_sqr(&x1, &x1x1) != MP_OKAY)
8114 goto X1X1; /* x1x1 = x1*x1 */
8115
8116 /* now calc (x1+x0)**2 */
8117 if (s_mp_add(&x1, &x0, &t1) != MP_OKAY)
8118 goto X1X1; /* t1 = x1 - x0 */
8119 if (mp_sqr(&t1, &t1) != MP_OKAY)
8120 goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */
8121
8122 /* add x0y0 */
8123 if (s_mp_add(&x0x0, &x1x1, &t2) != MP_OKAY)
8124 goto X1X1; /* t2 = x0x0 + x1x1 */
8125 if (s_mp_sub(&t1, &t2, &t1) != MP_OKAY)
8126 goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */
8127
8128 /* shift by B */
8129 if (mp_lshd(&t1, B) != MP_OKAY)
8130 goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
8131 if (mp_lshd(&x1x1, B * 2) != MP_OKAY)
8132 goto X1X1; /* x1x1 = x1x1 << 2*B */
8133
8134 if (mp_add(&x0x0, &t1, &t1) != MP_OKAY)
8135 goto X1X1; /* t1 = x0x0 + t1 */
8136 if (mp_add(&t1, &x1x1, b) != MP_OKAY)
8137 goto X1X1; /* t1 = x0x0 + t1 + x1x1 */
8138
8139 err = MP_OKAY;
8140
8141 X1X1:
8142 mp_clear(&x1x1);
8143 X0X0:
8144 mp_clear(&x0x0);
8145 T2:
8146 mp_clear(&t2);
8147 T1:
8148 mp_clear(&t1);
8149 X1:
8150 mp_clear(&x1);
8151 X0:
8152 mp_clear(&x0);
8153 LBL_ERR:
8154 return err;
8155 }
8156 #endif
8157
8158 /* End: bn_s_mp_karatsuba_sqr.c */
8159
8160 /* Start: bn_s_mp_montgomery_reduce_fast.c */
8161 #include "tommath_private.h"
8162 #ifdef BN_S_MP_MONTGOMERY_REDUCE_FAST_C
8163 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8164 /* SPDX-License-Identifier: Unlicense */
8165
8166 /* computes xR**-1 == x (mod N) via Montgomery Reduction
8167 *
8168 * This is an optimized implementation of montgomery_reduce
8169 * which uses the comba method to quickly calculate the columns of the
8170 * reduction.
8171 *
8172 * Based on Algorithm 14.32 on pp.601 of HAC.
8173 */
s_mp_montgomery_reduce_fast(mp_int * x,const mp_int * n,mp_digit rho)8174 mp_err s_mp_montgomery_reduce_fast(mp_int *x, const mp_int *n, mp_digit rho)
8175 {
8176 int ix, olduse;
8177 mp_err err;
8178 mp_word W[MP_WARRAY];
8179
8180 if (x->used > MP_WARRAY) {
8181 return MP_VAL;
8182 }
8183
8184 /* get old used count */
8185 olduse = x->used;
8186
8187 /* grow a as required */
8188 if (x->alloc < (n->used + 1)) {
8189 if ((err = mp_grow(x, n->used + 1)) != MP_OKAY) {
8190 return err;
8191 }
8192 }
8193
8194 /* first we have to get the digits of the input into
8195 * an array of double precision words W[...]
8196 */
8197 {
8198 mp_word *_W;
8199 mp_digit *tmpx;
8200
8201 /* alias for the W[] array */
8202 _W = W;
8203
8204 /* alias for the digits of x*/
8205 tmpx = x->dp;
8206
8207 /* copy the digits of a into W[0..a->used-1] */
8208 for (ix = 0; ix < x->used; ix++) {
8209 *_W++ = *tmpx++;
8210 }
8211
8212 /* zero the high words of W[a->used..m->used*2] */
8213 if (ix < ((n->used * 2) + 1)) {
8214 MP_ZERO_BUFFER(_W, sizeof(mp_word) * (size_t)(((n->used * 2) + 1) - ix));
8215 }
8216 }
8217
8218 /* now we proceed to zero successive digits
8219 * from the least significant upwards
8220 */
8221 for (ix = 0; ix < n->used; ix++) {
8222 /* mu = ai * m' mod b
8223 *
8224 * We avoid a double precision multiplication (which isn't required)
8225 * by casting the value down to a mp_digit. Note this requires
8226 * that W[ix-1] have the carry cleared (see after the inner loop)
8227 */
8228 mp_digit mu;
8229 mu = ((W[ix] & MP_MASK) * rho) & MP_MASK;
8230
8231 /* a = a + mu * m * b**i
8232 *
8233 * This is computed in place and on the fly. The multiplication
8234 * by b**i is handled by offseting which columns the results
8235 * are added to.
8236 *
8237 * Note the comba method normally doesn't handle carries in the
8238 * inner loop In this case we fix the carry from the previous
8239 * column since the Montgomery reduction requires digits of the
8240 * result (so far) [see above] to work. This is
8241 * handled by fixing up one carry after the inner loop. The
8242 * carry fixups are done in order so after these loops the
8243 * first m->used words of W[] have the carries fixed
8244 */
8245 {
8246 int iy;
8247 mp_digit *tmpn;
8248 mp_word *_W;
8249
8250 /* alias for the digits of the modulus */
8251 tmpn = n->dp;
8252
8253 /* Alias for the columns set by an offset of ix */
8254 _W = W + ix;
8255
8256 /* inner loop */
8257 for (iy = 0; iy < n->used; iy++) {
8258 *_W++ += (mp_word)mu * (mp_word)*tmpn++;
8259 }
8260 }
8261
8262 /* now fix carry for next digit, W[ix+1] */
8263 W[ix + 1] += W[ix] >> (mp_word)MP_DIGIT_BIT;
8264 }
8265
8266 /* now we have to propagate the carries and
8267 * shift the words downward [all those least
8268 * significant digits we zeroed].
8269 */
8270 {
8271 mp_digit *tmpx;
8272 mp_word *_W, *_W1;
8273
8274 /* nox fix rest of carries */
8275
8276 /* alias for current word */
8277 _W1 = W + ix;
8278
8279 /* alias for next word, where the carry goes */
8280 _W = W + ++ix;
8281
8282 for (; ix < ((n->used * 2) + 1); ix++) {
8283 *_W++ += *_W1++ >> (mp_word)MP_DIGIT_BIT;
8284 }
8285
8286 /* copy out, A = A/b**n
8287 *
8288 * The result is A/b**n but instead of converting from an
8289 * array of mp_word to mp_digit than calling mp_rshd
8290 * we just copy them in the right order
8291 */
8292
8293 /* alias for destination word */
8294 tmpx = x->dp;
8295
8296 /* alias for shifted double precision result */
8297 _W = W + n->used;
8298
8299 for (ix = 0; ix < (n->used + 1); ix++) {
8300 *tmpx++ = *_W++ & (mp_word)MP_MASK;
8301 }
8302
8303 /* zero oldused digits, if the input a was larger than
8304 * m->used+1 we'll have to clear the digits
8305 */
8306 MP_ZERO_DIGITS(tmpx, olduse - ix);
8307 }
8308
8309 /* set the max used and clamp */
8310 x->used = n->used + 1;
8311 mp_clamp(x);
8312
8313 /* if A >= m then A = A - m */
8314 if (mp_cmp_mag(x, n) != MP_LT) {
8315 return s_mp_sub(x, n, x);
8316 }
8317 return MP_OKAY;
8318 }
8319 #endif
8320
8321 /* End: bn_s_mp_montgomery_reduce_fast.c */
8322
8323 /* Start: bn_s_mp_mul_digs.c */
8324 #include "tommath_private.h"
8325 #ifdef BN_S_MP_MUL_DIGS_C
8326 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8327 /* SPDX-License-Identifier: Unlicense */
8328
8329 /* multiplies |a| * |b| and only computes upto digs digits of result
8330 * HAC pp. 595, Algorithm 14.12 Modified so you can control how
8331 * many digits of output are created.
8332 */
s_mp_mul_digs(const mp_int * a,const mp_int * b,mp_int * c,int digs)8333 mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs)
8334 {
8335 mp_int t;
8336 mp_err err;
8337 int pa, pb, ix, iy;
8338 mp_digit u;
8339 mp_word r;
8340 mp_digit tmpx, *tmpt, *tmpy;
8341
8342 /* can we use the fast multiplier? */
8343 if ((digs < MP_WARRAY) &&
8344 (MP_MIN(a->used, b->used) < MP_MAXFAST)) {
8345 return s_mp_mul_digs_fast(a, b, c, digs);
8346 }
8347
8348 if ((err = mp_init_size(&t, digs)) != MP_OKAY) {
8349 return err;
8350 }
8351 t.used = digs;
8352
8353 /* compute the digits of the product directly */
8354 pa = a->used;
8355 for (ix = 0; ix < pa; ix++) {
8356 /* set the carry to zero */
8357 u = 0;
8358
8359 /* limit ourselves to making digs digits of output */
8360 pb = MP_MIN(b->used, digs - ix);
8361
8362 /* setup some aliases */
8363 /* copy of the digit from a used within the nested loop */
8364 tmpx = a->dp[ix];
8365
8366 /* an alias for the destination shifted ix places */
8367 tmpt = t.dp + ix;
8368
8369 /* an alias for the digits of b */
8370 tmpy = b->dp;
8371
8372 /* compute the columns of the output and propagate the carry */
8373 for (iy = 0; iy < pb; iy++) {
8374 /* compute the column as a mp_word */
8375 r = (mp_word)*tmpt +
8376 ((mp_word)tmpx * (mp_word)*tmpy++) +
8377 (mp_word)u;
8378
8379 /* the new column is the lower part of the result */
8380 *tmpt++ = (mp_digit)(r & (mp_word)MP_MASK);
8381
8382 /* get the carry word from the result */
8383 u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
8384 }
8385 /* set carry if it is placed below digs */
8386 if ((ix + iy) < digs) {
8387 *tmpt = u;
8388 }
8389 }
8390
8391 mp_clamp(&t);
8392 mp_exch(&t, c);
8393
8394 mp_clear(&t);
8395 return MP_OKAY;
8396 }
8397 #endif
8398
8399 /* End: bn_s_mp_mul_digs.c */
8400
8401 /* Start: bn_s_mp_mul_digs_fast.c */
8402 #include "tommath_private.h"
8403 #ifdef BN_S_MP_MUL_DIGS_FAST_C
8404 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8405 /* SPDX-License-Identifier: Unlicense */
8406
8407 /* Fast (comba) multiplier
8408 *
8409 * This is the fast column-array [comba] multiplier. It is
8410 * designed to compute the columns of the product first
8411 * then handle the carries afterwards. This has the effect
8412 * of making the nested loops that compute the columns very
8413 * simple and schedulable on super-scalar processors.
8414 *
8415 * This has been modified to produce a variable number of
8416 * digits of output so if say only a half-product is required
8417 * you don't have to compute the upper half (a feature
8418 * required for fast Barrett reduction).
8419 *
8420 * Based on Algorithm 14.12 on pp.595 of HAC.
8421 *
8422 */
s_mp_mul_digs_fast(const mp_int * a,const mp_int * b,mp_int * c,int digs)8423 mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs)
8424 {
8425 int olduse, pa, ix, iz;
8426 mp_err err;
8427 mp_digit W[MP_WARRAY];
8428 mp_word _W;
8429
8430 /* grow the destination as required */
8431 if (c->alloc < digs) {
8432 if ((err = mp_grow(c, digs)) != MP_OKAY) {
8433 return err;
8434 }
8435 }
8436
8437 /* number of output digits to produce */
8438 pa = MP_MIN(digs, a->used + b->used);
8439
8440 /* clear the carry */
8441 _W = 0;
8442 for (ix = 0; ix < pa; ix++) {
8443 int tx, ty;
8444 int iy;
8445 mp_digit *tmpx, *tmpy;
8446
8447 /* get offsets into the two bignums */
8448 ty = MP_MIN(b->used-1, ix);
8449 tx = ix - ty;
8450
8451 /* setup temp aliases */
8452 tmpx = a->dp + tx;
8453 tmpy = b->dp + ty;
8454
8455 /* this is the number of times the loop will iterrate, essentially
8456 while (tx++ < a->used && ty-- >= 0) { ... }
8457 */
8458 iy = MP_MIN(a->used-tx, ty+1);
8459
8460 /* execute loop */
8461 for (iz = 0; iz < iy; ++iz) {
8462 _W += (mp_word)*tmpx++ * (mp_word)*tmpy--;
8463
8464 }
8465
8466 /* store term */
8467 W[ix] = (mp_digit)_W & MP_MASK;
8468
8469 /* make next carry */
8470 _W = _W >> (mp_word)MP_DIGIT_BIT;
8471 }
8472
8473 /* setup dest */
8474 olduse = c->used;
8475 c->used = pa;
8476
8477 {
8478 mp_digit *tmpc;
8479 tmpc = c->dp;
8480 for (ix = 0; ix < pa; ix++) {
8481 /* now extract the previous digit [below the carry] */
8482 *tmpc++ = W[ix];
8483 }
8484
8485 /* clear unused digits [that existed in the old copy of c] */
8486 MP_ZERO_DIGITS(tmpc, olduse - ix);
8487 }
8488 mp_clamp(c);
8489 return MP_OKAY;
8490 }
8491 #endif
8492
8493 /* End: bn_s_mp_mul_digs_fast.c */
8494
8495 /* Start: bn_s_mp_mul_high_digs.c */
8496 #include "tommath_private.h"
8497 #ifdef BN_S_MP_MUL_HIGH_DIGS_C
8498 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8499 /* SPDX-License-Identifier: Unlicense */
8500
8501 /* multiplies |a| * |b| and does not compute the lower digs digits
8502 * [meant to get the higher part of the product]
8503 */
s_mp_mul_high_digs(const mp_int * a,const mp_int * b,mp_int * c,int digs)8504 mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs)
8505 {
8506 mp_int t;
8507 int pa, pb, ix, iy;
8508 mp_err err;
8509 mp_digit u;
8510 mp_word r;
8511 mp_digit tmpx, *tmpt, *tmpy;
8512
8513 /* can we use the fast multiplier? */
8514 if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST)
8515 && ((a->used + b->used + 1) < MP_WARRAY)
8516 && (MP_MIN(a->used, b->used) < MP_MAXFAST)) {
8517 return s_mp_mul_high_digs_fast(a, b, c, digs);
8518 }
8519
8520 if ((err = mp_init_size(&t, a->used + b->used + 1)) != MP_OKAY) {
8521 return err;
8522 }
8523 t.used = a->used + b->used + 1;
8524
8525 pa = a->used;
8526 pb = b->used;
8527 for (ix = 0; ix < pa; ix++) {
8528 /* clear the carry */
8529 u = 0;
8530
8531 /* left hand side of A[ix] * B[iy] */
8532 tmpx = a->dp[ix];
8533
8534 /* alias to the address of where the digits will be stored */
8535 tmpt = &(t.dp[digs]);
8536
8537 /* alias for where to read the right hand side from */
8538 tmpy = b->dp + (digs - ix);
8539
8540 for (iy = digs - ix; iy < pb; iy++) {
8541 /* calculate the double precision result */
8542 r = (mp_word)*tmpt +
8543 ((mp_word)tmpx * (mp_word)*tmpy++) +
8544 (mp_word)u;
8545
8546 /* get the lower part */
8547 *tmpt++ = (mp_digit)(r & (mp_word)MP_MASK);
8548
8549 /* carry the carry */
8550 u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
8551 }
8552 *tmpt = u;
8553 }
8554 mp_clamp(&t);
8555 mp_exch(&t, c);
8556 mp_clear(&t);
8557 return MP_OKAY;
8558 }
8559 #endif
8560
8561 /* End: bn_s_mp_mul_high_digs.c */
8562
8563 /* Start: bn_s_mp_mul_high_digs_fast.c */
8564 #include "tommath_private.h"
8565 #ifdef BN_S_MP_MUL_HIGH_DIGS_FAST_C
8566 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8567 /* SPDX-License-Identifier: Unlicense */
8568
8569 /* this is a modified version of fast_s_mul_digs that only produces
8570 * output digits *above* digs. See the comments for fast_s_mul_digs
8571 * to see how it works.
8572 *
8573 * This is used in the Barrett reduction since for one of the multiplications
8574 * only the higher digits were needed. This essentially halves the work.
8575 *
8576 * Based on Algorithm 14.12 on pp.595 of HAC.
8577 */
s_mp_mul_high_digs_fast(const mp_int * a,const mp_int * b,mp_int * c,int digs)8578 mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs)
8579 {
8580 int olduse, pa, ix, iz;
8581 mp_err err;
8582 mp_digit W[MP_WARRAY];
8583 mp_word _W;
8584
8585 /* grow the destination as required */
8586 pa = a->used + b->used;
8587 if (c->alloc < pa) {
8588 if ((err = mp_grow(c, pa)) != MP_OKAY) {
8589 return err;
8590 }
8591 }
8592
8593 /* number of output digits to produce */
8594 pa = a->used + b->used;
8595 _W = 0;
8596 for (ix = digs; ix < pa; ix++) {
8597 int tx, ty, iy;
8598 mp_digit *tmpx, *tmpy;
8599
8600 /* get offsets into the two bignums */
8601 ty = MP_MIN(b->used-1, ix);
8602 tx = ix - ty;
8603
8604 /* setup temp aliases */
8605 tmpx = a->dp + tx;
8606 tmpy = b->dp + ty;
8607
8608 /* this is the number of times the loop will iterrate, essentially its
8609 while (tx++ < a->used && ty-- >= 0) { ... }
8610 */
8611 iy = MP_MIN(a->used-tx, ty+1);
8612
8613 /* execute loop */
8614 for (iz = 0; iz < iy; iz++) {
8615 _W += (mp_word)*tmpx++ * (mp_word)*tmpy--;
8616 }
8617
8618 /* store term */
8619 W[ix] = (mp_digit)_W & MP_MASK;
8620
8621 /* make next carry */
8622 _W = _W >> (mp_word)MP_DIGIT_BIT;
8623 }
8624
8625 /* setup dest */
8626 olduse = c->used;
8627 c->used = pa;
8628
8629 {
8630 mp_digit *tmpc;
8631
8632 tmpc = c->dp + digs;
8633 for (ix = digs; ix < pa; ix++) {
8634 /* now extract the previous digit [below the carry] */
8635 *tmpc++ = W[ix];
8636 }
8637
8638 /* clear unused digits [that existed in the old copy of c] */
8639 MP_ZERO_DIGITS(tmpc, olduse - ix);
8640 }
8641 mp_clamp(c);
8642 return MP_OKAY;
8643 }
8644 #endif
8645
8646 /* End: bn_s_mp_mul_high_digs_fast.c */
8647
8648 /* Start: bn_s_mp_prime_is_divisible.c */
8649 #include "tommath_private.h"
8650 #ifdef BN_S_MP_PRIME_IS_DIVISIBLE_C
8651 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8652 /* SPDX-License-Identifier: Unlicense */
8653
8654 /* determines if an integers is divisible by one
8655 * of the first PRIME_SIZE primes or not
8656 *
8657 * sets result to 0 if not, 1 if yes
8658 */
s_mp_prime_is_divisible(const mp_int * a,mp_bool * result)8659 mp_err s_mp_prime_is_divisible(const mp_int *a, mp_bool *result)
8660 {
8661 int ix;
8662 mp_err err;
8663 mp_digit res;
8664
8665 /* default to not */
8666 *result = MP_NO;
8667
8668 for (ix = 0; ix < PRIVATE_MP_PRIME_TAB_SIZE; ix++) {
8669 /* what is a mod LBL_prime_tab[ix] */
8670 if ((err = mp_mod_d(a, s_mp_prime_tab[ix], &res)) != MP_OKAY) {
8671 return err;
8672 }
8673
8674 /* is the residue zero? */
8675 if (res == 0u) {
8676 *result = MP_YES;
8677 return MP_OKAY;
8678 }
8679 }
8680
8681 return MP_OKAY;
8682 }
8683 #endif
8684
8685 /* End: bn_s_mp_prime_is_divisible.c */
8686
8687 /* Start: bn_s_mp_rand_jenkins.c */
8688 #include "tommath_private.h"
8689 #ifdef BN_S_MP_RAND_JENKINS_C
8690 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8691 /* SPDX-License-Identifier: Unlicense */
8692
8693 /* Bob Jenkins' http://burtleburtle.net/bob/rand/smallprng.html */
8694 /* Chosen for speed and a good "mix" */
8695 typedef struct {
8696 uint64_t a;
8697 uint64_t b;
8698 uint64_t c;
8699 uint64_t d;
8700 } ranctx;
8701
8702 static ranctx jenkins_x;
8703
8704 #define rot(x,k) (((x)<<(k))|((x)>>(64-(k))))
s_rand_jenkins_val(void)8705 static uint64_t s_rand_jenkins_val(void)
8706 {
8707 uint64_t e = jenkins_x.a - rot(jenkins_x.b, 7);
8708 jenkins_x.a = jenkins_x.b ^ rot(jenkins_x.c, 13);
8709 jenkins_x.b = jenkins_x.c + rot(jenkins_x.d, 37);
8710 jenkins_x.c = jenkins_x.d + e;
8711 jenkins_x.d = e + jenkins_x.a;
8712 return jenkins_x.d;
8713 }
8714
s_mp_rand_jenkins_init(uint64_t seed)8715 void s_mp_rand_jenkins_init(uint64_t seed)
8716 {
8717 uint64_t i;
8718 jenkins_x.a = 0xf1ea5eedULL;
8719 jenkins_x.b = jenkins_x.c = jenkins_x.d = seed;
8720 for (i = 0uLL; i < 20uLL; ++i) {
8721 (void)s_rand_jenkins_val();
8722 }
8723 }
8724
s_mp_rand_jenkins(void * p,size_t n)8725 mp_err s_mp_rand_jenkins(void *p, size_t n)
8726 {
8727 char *q = (char *)p;
8728 while (n > 0u) {
8729 int i;
8730 uint64_t x = s_rand_jenkins_val();
8731 for (i = 0; (i < 8) && (n > 0u); ++i, --n) {
8732 *q++ = (char)(x & 0xFFuLL);
8733 x >>= 8;
8734 }
8735 }
8736 return MP_OKAY;
8737 }
8738
8739 #endif
8740
8741 /* End: bn_s_mp_rand_jenkins.c */
8742
8743 /* Start: bn_s_mp_rand_platform.c */
8744 #include "tommath_private.h"
8745 #ifdef BN_S_MP_RAND_PLATFORM_C
8746 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8747 /* SPDX-License-Identifier: Unlicense */
8748
8749 /* First the OS-specific special cases
8750 * - *BSD
8751 * - Windows
8752 */
8753 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
8754 #define BN_S_READ_ARC4RANDOM_C
s_read_arc4random(void * p,size_t n)8755 static mp_err s_read_arc4random(void *p, size_t n)
8756 {
8757 arc4random_buf(p, n);
8758 return MP_OKAY;
8759 }
8760 #endif
8761
8762 #if defined(_WIN32) || defined(_WIN32_WCE)
8763 #define BN_S_READ_WINCSP_C
8764
8765 #ifndef _WIN32_WINNT
8766 #define _WIN32_WINNT 0x0400
8767 #endif
8768 #ifdef _WIN32_WCE
8769 #define UNDER_CE
8770 #define ARM
8771 #endif
8772
8773 #define WIN32_LEAN_AND_MEAN
8774 #include <windows.h>
8775 #include <wincrypt.h>
8776
s_read_wincsp(void * p,size_t n)8777 static mp_err s_read_wincsp(void *p, size_t n)
8778 {
8779 static HCRYPTPROV hProv = 0;
8780 if (hProv == 0) {
8781 HCRYPTPROV h = 0;
8782 if (!CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL,
8783 (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
8784 !CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL,
8785 CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) {
8786 return MP_ERR;
8787 }
8788 hProv = h;
8789 }
8790 return CryptGenRandom(hProv, (DWORD)n, (BYTE *)p) == TRUE ? MP_OKAY : MP_ERR;
8791 }
8792 #endif /* WIN32 */
8793
8794 #if !defined(BN_S_READ_WINCSP_C) && defined(__linux__) && defined(__GLIBC_PREREQ)
8795 #if __GLIBC_PREREQ(2, 25)
8796 #define BN_S_READ_GETRANDOM_C
8797 #include <sys/random.h>
8798 #include <errno.h>
8799
s_read_getrandom(void * p,size_t n)8800 static mp_err s_read_getrandom(void *p, size_t n)
8801 {
8802 char *q = (char *)p;
8803 while (n > 0u) {
8804 ssize_t ret = getrandom(q, n, 0);
8805 if (ret < 0) {
8806 if (errno == EINTR) {
8807 continue;
8808 }
8809 return MP_ERR;
8810 }
8811 q += ret;
8812 n -= (size_t)ret;
8813 }
8814 return MP_OKAY;
8815 }
8816 #endif
8817 #endif
8818
8819 /* We assume all platforms besides windows provide "/dev/urandom".
8820 * In case yours doesn't, define MP_NO_DEV_URANDOM at compile-time.
8821 */
8822 #if !defined(BN_S_READ_WINCSP_C) && !defined(MP_NO_DEV_URANDOM)
8823 #define BN_S_READ_URANDOM_C
8824 #ifndef MP_DEV_URANDOM
8825 #define MP_DEV_URANDOM "/dev/urandom"
8826 #endif
8827 #include <fcntl.h>
8828 #include <errno.h>
8829 #include <unistd.h>
8830
s_read_urandom(void * p,size_t n)8831 static mp_err s_read_urandom(void *p, size_t n)
8832 {
8833 int fd;
8834 char *q = (char *)p;
8835
8836 do {
8837 fd = open(MP_DEV_URANDOM, O_RDONLY);
8838 } while ((fd == -1) && (errno == EINTR));
8839 if (fd == -1) return MP_ERR;
8840
8841 while (n > 0u) {
8842 ssize_t ret = read(fd, p, n);
8843 if (ret < 0) {
8844 if (errno == EINTR) {
8845 continue;
8846 }
8847 close(fd);
8848 return MP_ERR;
8849 }
8850 q += ret;
8851 n -= (size_t)ret;
8852 }
8853
8854 close(fd);
8855 return MP_OKAY;
8856 }
8857 #endif
8858
8859 #if defined(MP_PRNG_ENABLE_LTM_RNG)
8860 #define BN_S_READ_LTM_RNG
8861 unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void));
8862 void (*ltm_rng_callback)(void);
8863
s_read_ltm_rng(void * p,size_t n)8864 static mp_err s_read_ltm_rng(void *p, size_t n)
8865 {
8866 unsigned long res;
8867 if (ltm_rng == NULL) return MP_ERR;
8868 res = ltm_rng(p, n, ltm_rng_callback);
8869 if (res != n) return MP_ERR;
8870 return MP_OKAY;
8871 }
8872 #endif
8873
8874 mp_err s_read_arc4random(void *p, size_t n);
8875 mp_err s_read_wincsp(void *p, size_t n);
8876 mp_err s_read_getrandom(void *p, size_t n);
8877 mp_err s_read_urandom(void *p, size_t n);
8878 mp_err s_read_ltm_rng(void *p, size_t n);
8879
s_mp_rand_platform(void * p,size_t n)8880 mp_err s_mp_rand_platform(void *p, size_t n)
8881 {
8882 mp_err err = MP_ERR;
8883 if ((err != MP_OKAY) && MP_HAS(S_READ_ARC4RANDOM)) err = s_read_arc4random(p, n);
8884 if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n);
8885 if ((err != MP_OKAY) && MP_HAS(S_READ_GETRANDOM)) err = s_read_getrandom(p, n);
8886 if ((err != MP_OKAY) && MP_HAS(S_READ_URANDOM)) err = s_read_urandom(p, n);
8887 if ((err != MP_OKAY) && MP_HAS(S_READ_LTM_RNG)) err = s_read_ltm_rng(p, n);
8888 return err;
8889 }
8890
8891 #endif
8892
8893 /* End: bn_s_mp_rand_platform.c */
8894
8895 /* Start: bn_s_mp_reverse.c */
8896 #include "tommath_private.h"
8897 #ifdef BN_S_MP_REVERSE_C
8898 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8899 /* SPDX-License-Identifier: Unlicense */
8900
8901 /* reverse an array, used for radix code */
s_mp_reverse(unsigned char * s,size_t len)8902 void s_mp_reverse(unsigned char *s, size_t len)
8903 {
8904 size_t ix, iy;
8905 unsigned char t;
8906
8907 ix = 0u;
8908 iy = len - 1u;
8909 while (ix < iy) {
8910 t = s[ix];
8911 s[ix] = s[iy];
8912 s[iy] = t;
8913 ++ix;
8914 --iy;
8915 }
8916 }
8917 #endif
8918
8919 /* End: bn_s_mp_reverse.c */
8920
8921 /* Start: bn_s_mp_sqr.c */
8922 #include "tommath_private.h"
8923 #ifdef BN_S_MP_SQR_C
8924 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8925 /* SPDX-License-Identifier: Unlicense */
8926
8927 /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
s_mp_sqr(const mp_int * a,mp_int * b)8928 mp_err s_mp_sqr(const mp_int *a, mp_int *b)
8929 {
8930 mp_int t;
8931 int ix, iy, pa;
8932 mp_err err;
8933 mp_word r;
8934 mp_digit u, tmpx, *tmpt;
8935
8936 pa = a->used;
8937 if ((err = mp_init_size(&t, (2 * pa) + 1)) != MP_OKAY) {
8938 return err;
8939 }
8940
8941 /* default used is maximum possible size */
8942 t.used = (2 * pa) + 1;
8943
8944 for (ix = 0; ix < pa; ix++) {
8945 /* first calculate the digit at 2*ix */
8946 /* calculate double precision result */
8947 r = (mp_word)t.dp[2*ix] +
8948 ((mp_word)a->dp[ix] * (mp_word)a->dp[ix]);
8949
8950 /* store lower part in result */
8951 t.dp[ix+ix] = (mp_digit)(r & (mp_word)MP_MASK);
8952
8953 /* get the carry */
8954 u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
8955
8956 /* left hand side of A[ix] * A[iy] */
8957 tmpx = a->dp[ix];
8958
8959 /* alias for where to store the results */
8960 tmpt = t.dp + ((2 * ix) + 1);
8961
8962 for (iy = ix + 1; iy < pa; iy++) {
8963 /* first calculate the product */
8964 r = (mp_word)tmpx * (mp_word)a->dp[iy];
8965
8966 /* now calculate the double precision result, note we use
8967 * addition instead of *2 since it's easier to optimize
8968 */
8969 r = (mp_word)*tmpt + r + r + (mp_word)u;
8970
8971 /* store lower part */
8972 *tmpt++ = (mp_digit)(r & (mp_word)MP_MASK);
8973
8974 /* get carry */
8975 u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
8976 }
8977 /* propagate upwards */
8978 while (u != 0uL) {
8979 r = (mp_word)*tmpt + (mp_word)u;
8980 *tmpt++ = (mp_digit)(r & (mp_word)MP_MASK);
8981 u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
8982 }
8983 }
8984
8985 mp_clamp(&t);
8986 mp_exch(&t, b);
8987 mp_clear(&t);
8988 return MP_OKAY;
8989 }
8990 #endif
8991
8992 /* End: bn_s_mp_sqr.c */
8993
8994 /* Start: bn_s_mp_sqr_fast.c */
8995 #include "tommath_private.h"
8996 #ifdef BN_S_MP_SQR_FAST_C
8997 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
8998 /* SPDX-License-Identifier: Unlicense */
8999
9000 /* the jist of squaring...
9001 * you do like mult except the offset of the tmpx [one that
9002 * starts closer to zero] can't equal the offset of tmpy.
9003 * So basically you set up iy like before then you min it with
9004 * (ty-tx) so that it never happens. You double all those
9005 * you add in the inner loop
9006
9007 After that loop you do the squares and add them in.
9008 */
9009
s_mp_sqr_fast(const mp_int * a,mp_int * b)9010 mp_err s_mp_sqr_fast(const mp_int *a, mp_int *b)
9011 {
9012 int olduse, pa, ix, iz;
9013 mp_digit W[MP_WARRAY], *tmpx;
9014 mp_word W1;
9015 mp_err err;
9016
9017 /* grow the destination as required */
9018 pa = a->used + a->used;
9019 if (b->alloc < pa) {
9020 if ((err = mp_grow(b, pa)) != MP_OKAY) {
9021 return err;
9022 }
9023 }
9024
9025 /* number of output digits to produce */
9026 W1 = 0;
9027 for (ix = 0; ix < pa; ix++) {
9028 int tx, ty, iy;
9029 mp_word _W;
9030 mp_digit *tmpy;
9031
9032 /* clear counter */
9033 _W = 0;
9034
9035 /* get offsets into the two bignums */
9036 ty = MP_MIN(a->used-1, ix);
9037 tx = ix - ty;
9038
9039 /* setup temp aliases */
9040 tmpx = a->dp + tx;
9041 tmpy = a->dp + ty;
9042
9043 /* this is the number of times the loop will iterrate, essentially
9044 while (tx++ < a->used && ty-- >= 0) { ... }
9045 */
9046 iy = MP_MIN(a->used-tx, ty+1);
9047
9048 /* now for squaring tx can never equal ty
9049 * we halve the distance since they approach at a rate of 2x
9050 * and we have to round because odd cases need to be executed
9051 */
9052 iy = MP_MIN(iy, ((ty-tx)+1)>>1);
9053
9054 /* execute loop */
9055 for (iz = 0; iz < iy; iz++) {
9056 _W += (mp_word)*tmpx++ * (mp_word)*tmpy--;
9057 }
9058
9059 /* double the inner product and add carry */
9060 _W = _W + _W + W1;
9061
9062 /* even columns have the square term in them */
9063 if (((unsigned)ix & 1u) == 0u) {
9064 _W += (mp_word)a->dp[ix>>1] * (mp_word)a->dp[ix>>1];
9065 }
9066
9067 /* store it */
9068 W[ix] = (mp_digit)_W & MP_MASK;
9069
9070 /* make next carry */
9071 W1 = _W >> (mp_word)MP_DIGIT_BIT;
9072 }
9073
9074 /* setup dest */
9075 olduse = b->used;
9076 b->used = a->used+a->used;
9077
9078 {
9079 mp_digit *tmpb;
9080 tmpb = b->dp;
9081 for (ix = 0; ix < pa; ix++) {
9082 *tmpb++ = W[ix] & MP_MASK;
9083 }
9084
9085 /* clear unused digits [that existed in the old copy of c] */
9086 MP_ZERO_DIGITS(tmpb, olduse - ix);
9087 }
9088 mp_clamp(b);
9089 return MP_OKAY;
9090 }
9091 #endif
9092
9093 /* End: bn_s_mp_sqr_fast.c */
9094
9095 /* Start: bn_s_mp_sub.c */
9096 #include "tommath_private.h"
9097 #ifdef BN_S_MP_SUB_C
9098 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
9099 /* SPDX-License-Identifier: Unlicense */
9100
9101 /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
s_mp_sub(const mp_int * a,const mp_int * b,mp_int * c)9102 mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
9103 {
9104 int olduse, min, max;
9105 mp_err err;
9106
9107 /* find sizes */
9108 min = b->used;
9109 max = a->used;
9110
9111 /* init result */
9112 if (c->alloc < max) {
9113 if ((err = mp_grow(c, max)) != MP_OKAY) {
9114 return err;
9115 }
9116 }
9117 olduse = c->used;
9118 c->used = max;
9119
9120 {
9121 mp_digit u, *tmpa, *tmpb, *tmpc;
9122 int i;
9123
9124 /* alias for digit pointers */
9125 tmpa = a->dp;
9126 tmpb = b->dp;
9127 tmpc = c->dp;
9128
9129 /* set carry to zero */
9130 u = 0;
9131 for (i = 0; i < min; i++) {
9132 /* T[i] = A[i] - B[i] - U */
9133 *tmpc = (*tmpa++ - *tmpb++) - u;
9134
9135 /* U = carry bit of T[i]
9136 * Note this saves performing an AND operation since
9137 * if a carry does occur it will propagate all the way to the
9138 * MSB. As a result a single shift is enough to get the carry
9139 */
9140 u = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u);
9141
9142 /* Clear carry from T[i] */
9143 *tmpc++ &= MP_MASK;
9144 }
9145
9146 /* now copy higher words if any, e.g. if A has more digits than B */
9147 for (; i < max; i++) {
9148 /* T[i] = A[i] - U */
9149 *tmpc = *tmpa++ - u;
9150
9151 /* U = carry bit of T[i] */
9152 u = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u);
9153
9154 /* Clear carry from T[i] */
9155 *tmpc++ &= MP_MASK;
9156 }
9157
9158 /* clear digits above used (since we may not have grown result above) */
9159 MP_ZERO_DIGITS(tmpc, olduse - c->used);
9160 }
9161
9162 mp_clamp(c);
9163 return MP_OKAY;
9164 }
9165
9166 #endif
9167
9168 /* End: bn_s_mp_sub.c */
9169
9170 /* Start: bn_s_mp_toom_mul.c */
9171 #include "tommath_private.h"
9172 #ifdef BN_S_MP_TOOM_MUL_C
9173 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
9174 /* SPDX-License-Identifier: Unlicense */
9175
9176 /* multiplication using the Toom-Cook 3-way algorithm
9177 *
9178 * Much more complicated than Karatsuba but has a lower
9179 * asymptotic running time of O(N**1.464). This algorithm is
9180 * only particularly useful on VERY large inputs
9181 * (we're talking 1000s of digits here...).
9182 */
9183
9184 /*
9185 This file contains code from J. Arndt's book "Matters Computational"
9186 and the accompanying FXT-library with permission of the author.
9187 */
9188
9189 /*
9190 Setup from
9191
9192 Chung, Jaewook, and M. Anwar Hasan. "Asymmetric squaring formulae."
9193 18th IEEE Symposium on Computer Arithmetic (ARITH'07). IEEE, 2007.
9194
9195 The interpolation from above needed one temporary variable more
9196 than the interpolation here:
9197
9198 Bodrato, Marco, and Alberto Zanoni. "What about Toom-Cook matrices optimality."
9199 Centro Vito Volterra Universita di Roma Tor Vergata (2006)
9200 */
9201
s_mp_toom_mul(const mp_int * a,const mp_int * b,mp_int * c)9202 mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c)
9203 {
9204 mp_int S1, S2, T1, a0, a1, a2, b0, b1, b2;
9205 int B, count;
9206 mp_err err;
9207
9208 /* init temps */
9209 if ((err = mp_init_multi(&S1, &S2, &T1, NULL)) != MP_OKAY) {
9210 return err;
9211 }
9212
9213 /* B */
9214 B = MP_MIN(a->used, b->used) / 3;
9215
9216 /** a = a2 * x^2 + a1 * x + a0; */
9217 if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0;
9218
9219 for (count = 0; count < B; count++) {
9220 a0.dp[count] = a->dp[count];
9221 a0.used++;
9222 }
9223 mp_clamp(&a0);
9224 if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1;
9225 for (; count < (2 * B); count++) {
9226 a1.dp[count - B] = a->dp[count];
9227 a1.used++;
9228 }
9229 mp_clamp(&a1);
9230 if ((err = mp_init_size(&a2, B + (a->used - (3 * B)))) != MP_OKAY) goto LBL_ERRa2;
9231 for (; count < a->used; count++) {
9232 a2.dp[count - (2 * B)] = a->dp[count];
9233 a2.used++;
9234 }
9235 mp_clamp(&a2);
9236
9237 /** b = b2 * x^2 + b1 * x + b0; */
9238 if ((err = mp_init_size(&b0, B)) != MP_OKAY) goto LBL_ERRb0;
9239 for (count = 0; count < B; count++) {
9240 b0.dp[count] = b->dp[count];
9241 b0.used++;
9242 }
9243 mp_clamp(&b0);
9244 if ((err = mp_init_size(&b1, B)) != MP_OKAY) goto LBL_ERRb1;
9245 for (; count < (2 * B); count++) {
9246 b1.dp[count - B] = b->dp[count];
9247 b1.used++;
9248 }
9249 mp_clamp(&b1);
9250 if ((err = mp_init_size(&b2, B + (b->used - (3 * B)))) != MP_OKAY) goto LBL_ERRb2;
9251 for (; count < b->used; count++) {
9252 b2.dp[count - (2 * B)] = b->dp[count];
9253 b2.used++;
9254 }
9255 mp_clamp(&b2);
9256
9257 /** \\ S1 = (a2+a1+a0) * (b2+b1+b0); */
9258 /** T1 = a2 + a1; */
9259 if ((err = mp_add(&a2, &a1, &T1)) != MP_OKAY) goto LBL_ERR;
9260
9261 /** S2 = T1 + a0; */
9262 if ((err = mp_add(&T1, &a0, &S2)) != MP_OKAY) goto LBL_ERR;
9263
9264 /** c = b2 + b1; */
9265 if ((err = mp_add(&b2, &b1, c)) != MP_OKAY) goto LBL_ERR;
9266
9267 /** S1 = c + b0; */
9268 if ((err = mp_add(c, &b0, &S1)) != MP_OKAY) goto LBL_ERR;
9269
9270 /** S1 = S1 * S2; */
9271 if ((err = mp_mul(&S1, &S2, &S1)) != MP_OKAY) goto LBL_ERR;
9272
9273 /** \\S2 = (4*a2+2*a1+a0) * (4*b2+2*b1+b0); */
9274 /** T1 = T1 + a2; */
9275 if ((err = mp_add(&T1, &a2, &T1)) != MP_OKAY) goto LBL_ERR;
9276
9277 /** T1 = T1 << 1; */
9278 if ((err = mp_mul_2(&T1, &T1)) != MP_OKAY) goto LBL_ERR;
9279
9280 /** T1 = T1 + a0; */
9281 if ((err = mp_add(&T1, &a0, &T1)) != MP_OKAY) goto LBL_ERR;
9282
9283 /** c = c + b2; */
9284 if ((err = mp_add(c, &b2, c)) != MP_OKAY) goto LBL_ERR;
9285
9286 /** c = c << 1; */
9287 if ((err = mp_mul_2(c, c)) != MP_OKAY) goto LBL_ERR;
9288
9289 /** c = c + b0; */
9290 if ((err = mp_add(c, &b0, c)) != MP_OKAY) goto LBL_ERR;
9291
9292 /** S2 = T1 * c; */
9293 if ((err = mp_mul(&T1, c, &S2)) != MP_OKAY) goto LBL_ERR;
9294
9295 /** \\S3 = (a2-a1+a0) * (b2-b1+b0); */
9296 /** a1 = a2 - a1; */
9297 if ((err = mp_sub(&a2, &a1, &a1)) != MP_OKAY) goto LBL_ERR;
9298
9299 /** a1 = a1 + a0; */
9300 if ((err = mp_add(&a1, &a0, &a1)) != MP_OKAY) goto LBL_ERR;
9301
9302 /** b1 = b2 - b1; */
9303 if ((err = mp_sub(&b2, &b1, &b1)) != MP_OKAY) goto LBL_ERR;
9304
9305 /** b1 = b1 + b0; */
9306 if ((err = mp_add(&b1, &b0, &b1)) != MP_OKAY) goto LBL_ERR;
9307
9308 /** a1 = a1 * b1; */
9309 if ((err = mp_mul(&a1, &b1, &a1)) != MP_OKAY) goto LBL_ERR;
9310
9311 /** b1 = a2 * b2; */
9312 if ((err = mp_mul(&a2, &b2, &b1)) != MP_OKAY) goto LBL_ERR;
9313
9314 /** \\S2 = (S2 - S3)/3; */
9315 /** S2 = S2 - a1; */
9316 if ((err = mp_sub(&S2, &a1, &S2)) != MP_OKAY) goto LBL_ERR;
9317
9318 /** S2 = S2 / 3; \\ this is an exact division */
9319 if ((err = mp_div_3(&S2, &S2, NULL)) != MP_OKAY) goto LBL_ERR;
9320
9321 /** a1 = S1 - a1; */
9322 if ((err = mp_sub(&S1, &a1, &a1)) != MP_OKAY) goto LBL_ERR;
9323
9324 /** a1 = a1 >> 1; */
9325 if ((err = mp_div_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR;
9326
9327 /** a0 = a0 * b0; */
9328 if ((err = mp_mul(&a0, &b0, &a0)) != MP_OKAY) goto LBL_ERR;
9329
9330 /** S1 = S1 - a0; */
9331 if ((err = mp_sub(&S1, &a0, &S1)) != MP_OKAY) goto LBL_ERR;
9332
9333 /** S2 = S2 - S1; */
9334 if ((err = mp_sub(&S2, &S1, &S2)) != MP_OKAY) goto LBL_ERR;
9335
9336 /** S2 = S2 >> 1; */
9337 if ((err = mp_div_2(&S2, &S2)) != MP_OKAY) goto LBL_ERR;
9338
9339 /** S1 = S1 - a1; */
9340 if ((err = mp_sub(&S1, &a1, &S1)) != MP_OKAY) goto LBL_ERR;
9341
9342 /** S1 = S1 - b1; */
9343 if ((err = mp_sub(&S1, &b1, &S1)) != MP_OKAY) goto LBL_ERR;
9344
9345 /** T1 = b1 << 1; */
9346 if ((err = mp_mul_2(&b1, &T1)) != MP_OKAY) goto LBL_ERR;
9347
9348 /** S2 = S2 - T1; */
9349 if ((err = mp_sub(&S2, &T1, &S2)) != MP_OKAY) goto LBL_ERR;
9350
9351 /** a1 = a1 - S2; */
9352 if ((err = mp_sub(&a1, &S2, &a1)) != MP_OKAY) goto LBL_ERR;
9353
9354
9355 /** P = b1*x^4+ S2*x^3+ S1*x^2+ a1*x + a0; */
9356 if ((err = mp_lshd(&b1, 4 * B)) != MP_OKAY) goto LBL_ERR;
9357 if ((err = mp_lshd(&S2, 3 * B)) != MP_OKAY) goto LBL_ERR;
9358 if ((err = mp_add(&b1, &S2, &b1)) != MP_OKAY) goto LBL_ERR;
9359 if ((err = mp_lshd(&S1, 2 * B)) != MP_OKAY) goto LBL_ERR;
9360 if ((err = mp_add(&b1, &S1, &b1)) != MP_OKAY) goto LBL_ERR;
9361 if ((err = mp_lshd(&a1, 1 * B)) != MP_OKAY) goto LBL_ERR;
9362 if ((err = mp_add(&b1, &a1, &b1)) != MP_OKAY) goto LBL_ERR;
9363 if ((err = mp_add(&b1, &a0, c)) != MP_OKAY) goto LBL_ERR;
9364
9365 /** a * b - P */
9366
9367
9368 LBL_ERR:
9369 mp_clear(&b2);
9370 LBL_ERRb2:
9371 mp_clear(&b1);
9372 LBL_ERRb1:
9373 mp_clear(&b0);
9374 LBL_ERRb0:
9375 mp_clear(&a2);
9376 LBL_ERRa2:
9377 mp_clear(&a1);
9378 LBL_ERRa1:
9379 mp_clear(&a0);
9380 LBL_ERRa0:
9381 mp_clear_multi(&S1, &S2, &T1, NULL);
9382 return err;
9383 }
9384
9385 #endif
9386
9387 /* End: bn_s_mp_toom_mul.c */
9388
9389 /* Start: bn_s_mp_toom_sqr.c */
9390 #include "tommath_private.h"
9391 #ifdef BN_S_MP_TOOM_SQR_C
9392 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
9393 /* SPDX-License-Identifier: Unlicense */
9394
9395 /* squaring using Toom-Cook 3-way algorithm */
9396
9397 /*
9398 This file contains code from J. Arndt's book "Matters Computational"
9399 and the accompanying FXT-library with permission of the author.
9400 */
9401
9402 /* squaring using Toom-Cook 3-way algorithm */
9403 /*
9404 Setup and interpolation from algorithm SQR_3 in
9405
9406 Chung, Jaewook, and M. Anwar Hasan. "Asymmetric squaring formulae."
9407 18th IEEE Symposium on Computer Arithmetic (ARITH'07). IEEE, 2007.
9408
9409 */
s_mp_toom_sqr(const mp_int * a,mp_int * b)9410 mp_err s_mp_toom_sqr(const mp_int *a, mp_int *b)
9411 {
9412 mp_int S0, a0, a1, a2;
9413 mp_digit *tmpa, *tmpc;
9414 int B, count;
9415 mp_err err;
9416
9417
9418 /* init temps */
9419 if ((err = mp_init(&S0)) != MP_OKAY) {
9420 return err;
9421 }
9422
9423 /* B */
9424 B = a->used / 3;
9425
9426 /** a = a2 * x^2 + a1 * x + a0; */
9427 if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0;
9428
9429 a0.used = B;
9430 if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1;
9431 a1.used = B;
9432 if ((err = mp_init_size(&a2, B + (a->used - (3 * B)))) != MP_OKAY) goto LBL_ERRa2;
9433
9434 tmpa = a->dp;
9435 tmpc = a0.dp;
9436 for (count = 0; count < B; count++) {
9437 *tmpc++ = *tmpa++;
9438 }
9439 tmpc = a1.dp;
9440 for (; count < (2 * B); count++) {
9441 *tmpc++ = *tmpa++;
9442 }
9443 tmpc = a2.dp;
9444 for (; count < a->used; count++) {
9445 *tmpc++ = *tmpa++;
9446 a2.used++;
9447 }
9448 mp_clamp(&a0);
9449 mp_clamp(&a1);
9450 mp_clamp(&a2);
9451
9452 /** S0 = a0^2; */
9453 if ((err = mp_sqr(&a0, &S0)) != MP_OKAY) goto LBL_ERR;
9454
9455 /** \\S1 = (a2 + a1 + a0)^2 */
9456 /** \\S2 = (a2 - a1 + a0)^2 */
9457 /** \\S1 = a0 + a2; */
9458 /** a0 = a0 + a2; */
9459 if ((err = mp_add(&a0, &a2, &a0)) != MP_OKAY) goto LBL_ERR;
9460 /** \\S2 = S1 - a1; */
9461 /** b = a0 - a1; */
9462 if ((err = mp_sub(&a0, &a1, b)) != MP_OKAY) goto LBL_ERR;
9463 /** \\S1 = S1 + a1; */
9464 /** a0 = a0 + a1; */
9465 if ((err = mp_add(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR;
9466 /** \\S1 = S1^2; */
9467 /** a0 = a0^2; */
9468 if ((err = mp_sqr(&a0, &a0)) != MP_OKAY) goto LBL_ERR;
9469 /** \\S2 = S2^2; */
9470 /** b = b^2; */
9471 if ((err = mp_sqr(b, b)) != MP_OKAY) goto LBL_ERR;
9472
9473 /** \\ S3 = 2 * a1 * a2 */
9474 /** \\S3 = a1 * a2; */
9475 /** a1 = a1 * a2; */
9476 if ((err = mp_mul(&a1, &a2, &a1)) != MP_OKAY) goto LBL_ERR;
9477 /** \\S3 = S3 << 1; */
9478 /** a1 = a1 << 1; */
9479 if ((err = mp_mul_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR;
9480
9481 /** \\S4 = a2^2; */
9482 /** a2 = a2^2; */
9483 if ((err = mp_sqr(&a2, &a2)) != MP_OKAY) goto LBL_ERR;
9484
9485 /** \\ tmp = (S1 + S2)/2 */
9486 /** \\tmp = S1 + S2; */
9487 /** b = a0 + b; */
9488 if ((err = mp_add(&a0, b, b)) != MP_OKAY) goto LBL_ERR;
9489 /** \\tmp = tmp >> 1; */
9490 /** b = b >> 1; */
9491 if ((err = mp_div_2(b, b)) != MP_OKAY) goto LBL_ERR;
9492
9493 /** \\ S1 = S1 - tmp - S3 */
9494 /** \\S1 = S1 - tmp; */
9495 /** a0 = a0 - b; */
9496 if ((err = mp_sub(&a0, b, &a0)) != MP_OKAY) goto LBL_ERR;
9497 /** \\S1 = S1 - S3; */
9498 /** a0 = a0 - a1; */
9499 if ((err = mp_sub(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR;
9500
9501 /** \\S2 = tmp - S4 -S0 */
9502 /** \\S2 = tmp - S4; */
9503 /** b = b - a2; */
9504 if ((err = mp_sub(b, &a2, b)) != MP_OKAY) goto LBL_ERR;
9505 /** \\S2 = S2 - S0; */
9506 /** b = b - S0; */
9507 if ((err = mp_sub(b, &S0, b)) != MP_OKAY) goto LBL_ERR;
9508
9509
9510 /** \\P = S4*x^4 + S3*x^3 + S2*x^2 + S1*x + S0; */
9511 /** P = a2*x^4 + a1*x^3 + b*x^2 + a0*x + S0; */
9512
9513 if ((err = mp_lshd(&a2, 4 * B)) != MP_OKAY) goto LBL_ERR;
9514 if ((err = mp_lshd(&a1, 3 * B)) != MP_OKAY) goto LBL_ERR;
9515 if ((err = mp_lshd(b, 2 * B)) != MP_OKAY) goto LBL_ERR;
9516 if ((err = mp_lshd(&a0, 1 * B)) != MP_OKAY) goto LBL_ERR;
9517 if ((err = mp_add(&a2, &a1, &a2)) != MP_OKAY) goto LBL_ERR;
9518 if ((err = mp_add(&a2, b, b)) != MP_OKAY) goto LBL_ERR;
9519 if ((err = mp_add(b, &a0, b)) != MP_OKAY) goto LBL_ERR;
9520 if ((err = mp_add(b, &S0, b)) != MP_OKAY) goto LBL_ERR;
9521 /** a^2 - P */
9522
9523
9524 LBL_ERR:
9525 mp_clear(&a2);
9526 LBL_ERRa2:
9527 mp_clear(&a1);
9528 LBL_ERRa1:
9529 mp_clear(&a0);
9530 LBL_ERRa0:
9531 mp_clear(&S0);
9532
9533 return err;
9534 }
9535
9536 #endif
9537
9538 /* End: bn_s_mp_toom_sqr.c */
9539
9540
9541 /* EOF */
9542