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