comparison src/misc/mpi/mpi.c @ 280:59400faa4b44 libtomcrypt-orig libtomcrypt-1.05

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