comparison libtommath/pre_gen/mpi.c @ 284:eed26cff980b

propagate from branch 'au.asn.ucc.matt.ltm.dropbear' (head 6c790cad5a7fa866ad062cb3a0c279f7ba788583) to branch 'au.asn.ucc.matt.dropbear' (head fff0894a0399405a9410ea1c6d118f342cf2aa64)
author Matt Johnston <matt@ucc.asn.au>
date Wed, 08 Mar 2006 13:23:49 +0000
parents
children 5ff8218bcee9
comparison
equal deleted inserted replaced
283:bd240aa12ba7 284:eed26cff980b
1 /* Start: bn_error.c */
2 #include <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 <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 |= 1 << ((size - 2) & 7);
5850 } else if (flags & LTM_PRIME_2MSB_OFF) {
5851 maskAND &= ~(1 << ((size - 2) & 7));
5852 }
5853
5854 /* get the maskOR_lsb */
5855 maskOR_lsb = 1;
5856 if (flags & LTM_PRIME_BBS) {
5857 maskOR_lsb |= 3;
5858 }
5859
5860 do {
5861 /* read the bytes */
5862 if (cb(tmp, bsize, dat) != bsize) {
5863 err = MP_VAL;
5864 goto error;
5865 }
5866
5867 /* work over the MSbyte */
5868 tmp[0] &= maskAND;
5869 tmp[0] |= 1 << ((size - 1) & 7);
5870
5871 /* mix in the maskORs */
5872 tmp[maskOR_msb_offset] |= maskOR_msb;
5873 tmp[bsize-1] |= maskOR_lsb;
5874
5875 /* read it in */
5876 if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; }
5877
5878 /* is it prime? */
5879 if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
5880 if (res == MP_NO) {
5881 continue;
5882 }
5883
5884 if (flags & LTM_PRIME_SAFE) {
5885 /* see if (a-1)/2 is prime */
5886 if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; }
5887 if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; }
5888
5889 /* is it prime? */
5890 if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
5891 }
5892 } while (res == MP_NO);
5893
5894 if (flags & LTM_PRIME_SAFE) {
5895 /* restore a to the original value */
5896 if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; }
5897 if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; }
5898 }
5899
5900 err = MP_OKAY;
5901 error:
5902 XFREE(tmp);
5903 return err;
5904 }
5905
5906
5907 #endif
5908
5909 /* End: bn_mp_prime_random_ex.c */
5910
5911 /* Start: bn_mp_radix_size.c */
5912 #include <tommath.h>
5913 #ifdef BN_MP_RADIX_SIZE_C
5914 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5915 *
5916 * LibTomMath is a library that provides multiple-precision
5917 * integer arithmetic as well as number theoretic functionality.
5918 *
5919 * The library was designed directly after the MPI library by
5920 * Michael Fromberger but has been written from scratch with
5921 * additional optimizations in place.
5922 *
5923 * The library is free for all purposes without any express
5924 * guarantee it works.
5925 *
5926 * Tom St Denis, [email protected], http://math.libtomcrypt.org
5927 */
5928
5929 /* returns size of ASCII reprensentation */
5930 int mp_radix_size (mp_int * a, int radix, int *size)
5931 {
5932 int res, digs;
5933 mp_int t;
5934 mp_digit d;
5935
5936 *size = 0;
5937
5938 /* special case for binary */
5939 if (radix == 2) {
5940 *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
5941 return MP_OKAY;
5942 }
5943
5944 /* make sure the radix is in range */
5945 if (radix < 2 || radix > 64) {
5946 return MP_VAL;
5947 }
5948
5949 if (mp_iszero(a) == MP_YES) {
5950 *size = 2;
5951 return MP_OKAY;
5952 }
5953
5954 /* digs is the digit count */
5955 digs = 0;
5956
5957 /* if it's negative add one for the sign */
5958 if (a->sign == MP_NEG) {
5959 ++digs;
5960 }
5961
5962 /* init a copy of the input */
5963 if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
5964 return res;
5965 }
5966
5967 /* force temp to positive */
5968 t.sign = MP_ZPOS;
5969
5970 /* fetch out all of the digits */
5971 while (mp_iszero (&t) == MP_NO) {
5972 if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
5973 mp_clear (&t);
5974 return res;
5975 }
5976 ++digs;
5977 }
5978 mp_clear (&t);
5979
5980 /* return digs + 1, the 1 is for the NULL byte that would be required. */
5981 *size = digs + 1;
5982 return MP_OKAY;
5983 }
5984
5985 #endif
5986
5987 /* End: bn_mp_radix_size.c */
5988
5989 /* Start: bn_mp_radix_smap.c */
5990 #include <tommath.h>
5991 #ifdef BN_MP_RADIX_SMAP_C
5992 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5993 *
5994 * LibTomMath is a library that provides multiple-precision
5995 * integer arithmetic as well as number theoretic functionality.
5996 *
5997 * The library was designed directly after the MPI library by
5998 * Michael Fromberger but has been written from scratch with
5999 * additional optimizations in place.
6000 *
6001 * The library is free for all purposes without any express
6002 * guarantee it works.
6003 *
6004 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6005 */
6006
6007 /* chars used in radix conversions */
6008 const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
6009 #endif
6010
6011 /* End: bn_mp_radix_smap.c */
6012
6013 /* Start: bn_mp_rand.c */
6014 #include <tommath.h>
6015 #ifdef BN_MP_RAND_C
6016 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6017 *
6018 * LibTomMath is a library that provides multiple-precision
6019 * integer arithmetic as well as number theoretic functionality.
6020 *
6021 * The library was designed directly after the MPI library by
6022 * Michael Fromberger but has been written from scratch with
6023 * additional optimizations in place.
6024 *
6025 * The library is free for all purposes without any express
6026 * guarantee it works.
6027 *
6028 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6029 */
6030
6031 /* makes a pseudo-random int of a given size */
6032 int
6033 mp_rand (mp_int * a, int digits)
6034 {
6035 int res;
6036 mp_digit d;
6037
6038 mp_zero (a);
6039 if (digits <= 0) {
6040 return MP_OKAY;
6041 }
6042
6043 /* first place a random non-zero digit */
6044 do {
6045 d = ((mp_digit) abs (rand ())) & MP_MASK;
6046 } while (d == 0);
6047
6048 if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
6049 return res;
6050 }
6051
6052 while (--digits > 0) {
6053 if ((res = mp_lshd (a, 1)) != MP_OKAY) {
6054 return res;
6055 }
6056
6057 if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
6058 return res;
6059 }
6060 }
6061
6062 return MP_OKAY;
6063 }
6064 #endif
6065
6066 /* End: bn_mp_rand.c */
6067
6068 /* Start: bn_mp_read_radix.c */
6069 #include <tommath.h>
6070 #ifdef BN_MP_READ_RADIX_C
6071 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6072 *
6073 * LibTomMath is a library that provides multiple-precision
6074 * integer arithmetic as well as number theoretic functionality.
6075 *
6076 * The library was designed directly after the MPI library by
6077 * Michael Fromberger but has been written from scratch with
6078 * additional optimizations in place.
6079 *
6080 * The library is free for all purposes without any express
6081 * guarantee it works.
6082 *
6083 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6084 */
6085
6086 /* read a string [ASCII] in a given radix */
6087 int mp_read_radix (mp_int * a, const char *str, int radix)
6088 {
6089 int y, res, neg;
6090 char ch;
6091
6092 /* make sure the radix is ok */
6093 if (radix < 2 || radix > 64) {
6094 return MP_VAL;
6095 }
6096
6097 /* if the leading digit is a
6098 * minus set the sign to negative.
6099 */
6100 if (*str == '-') {
6101 ++str;
6102 neg = MP_NEG;
6103 } else {
6104 neg = MP_ZPOS;
6105 }
6106
6107 /* set the integer to the default of zero */
6108 mp_zero (a);
6109
6110 /* process each digit of the string */
6111 while (*str) {
6112 /* if the radix < 36 the conversion is case insensitive
6113 * this allows numbers like 1AB and 1ab to represent the same value
6114 * [e.g. in hex]
6115 */
6116 ch = (char) ((radix < 36) ? toupper (*str) : *str);
6117 for (y = 0; y < 64; y++) {
6118 if (ch == mp_s_rmap[y]) {
6119 break;
6120 }
6121 }
6122
6123 /* if the char was found in the map
6124 * and is less than the given radix add it
6125 * to the number, otherwise exit the loop.
6126 */
6127 if (y < radix) {
6128 if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
6129 return res;
6130 }
6131 if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
6132 return res;
6133 }
6134 } else {
6135 break;
6136 }
6137 ++str;
6138 }
6139
6140 /* set the sign only if a != 0 */
6141 if (mp_iszero(a) != 1) {
6142 a->sign = neg;
6143 }
6144 return MP_OKAY;
6145 }
6146 #endif
6147
6148 /* End: bn_mp_read_radix.c */
6149
6150 /* Start: bn_mp_read_signed_bin.c */
6151 #include <tommath.h>
6152 #ifdef BN_MP_READ_SIGNED_BIN_C
6153 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6154 *
6155 * LibTomMath is a library that provides multiple-precision
6156 * integer arithmetic as well as number theoretic functionality.
6157 *
6158 * The library was designed directly after the MPI library by
6159 * Michael Fromberger but has been written from scratch with
6160 * additional optimizations in place.
6161 *
6162 * The library is free for all purposes without any express
6163 * guarantee it works.
6164 *
6165 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6166 */
6167
6168 /* read signed bin, big endian, first byte is 0==positive or 1==negative */
6169 int
6170 mp_read_signed_bin (mp_int * a, unsigned char *b, int c)
6171 {
6172 int res;
6173
6174 /* read magnitude */
6175 if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
6176 return res;
6177 }
6178
6179 /* first byte is 0 for positive, non-zero for negative */
6180 if (b[0] == 0) {
6181 a->sign = MP_ZPOS;
6182 } else {
6183 a->sign = MP_NEG;
6184 }
6185
6186 return MP_OKAY;
6187 }
6188 #endif
6189
6190 /* End: bn_mp_read_signed_bin.c */
6191
6192 /* Start: bn_mp_read_unsigned_bin.c */
6193 #include <tommath.h>
6194 #ifdef BN_MP_READ_UNSIGNED_BIN_C
6195 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6196 *
6197 * LibTomMath is a library that provides multiple-precision
6198 * integer arithmetic as well as number theoretic functionality.
6199 *
6200 * The library was designed directly after the MPI library by
6201 * Michael Fromberger but has been written from scratch with
6202 * additional optimizations in place.
6203 *
6204 * The library is free for all purposes without any express
6205 * guarantee it works.
6206 *
6207 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6208 */
6209
6210 /* reads a unsigned char array, assumes the msb is stored first [big endian] */
6211 int
6212 mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c)
6213 {
6214 int res;
6215
6216 /* make sure there are at least two digits */
6217 if (a->alloc < 2) {
6218 if ((res = mp_grow(a, 2)) != MP_OKAY) {
6219 return res;
6220 }
6221 }
6222
6223 /* zero the int */
6224 mp_zero (a);
6225
6226 /* read the bytes in */
6227 while (c-- > 0) {
6228 if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
6229 return res;
6230 }
6231
6232 #ifndef MP_8BIT
6233 a->dp[0] |= *b++;
6234 a->used += 1;
6235 #else
6236 a->dp[0] = (*b & MP_MASK);
6237 a->dp[1] |= ((*b++ >> 7U) & 1);
6238 a->used += 2;
6239 #endif
6240 }
6241 mp_clamp (a);
6242 return MP_OKAY;
6243 }
6244 #endif
6245
6246 /* End: bn_mp_read_unsigned_bin.c */
6247
6248 /* Start: bn_mp_reduce.c */
6249 #include <tommath.h>
6250 #ifdef BN_MP_REDUCE_C
6251 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6252 *
6253 * LibTomMath is a library that provides multiple-precision
6254 * integer arithmetic as well as number theoretic functionality.
6255 *
6256 * The library was designed directly after the MPI library by
6257 * Michael Fromberger but has been written from scratch with
6258 * additional optimizations in place.
6259 *
6260 * The library is free for all purposes without any express
6261 * guarantee it works.
6262 *
6263 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6264 */
6265
6266 /* reduces x mod m, assumes 0 < x < m**2, mu is
6267 * precomputed via mp_reduce_setup.
6268 * From HAC pp.604 Algorithm 14.42
6269 */
6270 int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
6271 {
6272 mp_int q;
6273 int res, um = m->used;
6274
6275 /* q = x */
6276 if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
6277 return res;
6278 }
6279
6280 /* q1 = x / b**(k-1) */
6281 mp_rshd (&q, um - 1);
6282
6283 /* according to HAC this optimization is ok */
6284 if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
6285 if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
6286 goto CLEANUP;
6287 }
6288 } else {
6289 #ifdef BN_S_MP_MUL_HIGH_DIGS_C
6290 if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
6291 goto CLEANUP;
6292 }
6293 #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
6294 if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
6295 goto CLEANUP;
6296 }
6297 #else
6298 {
6299 res = MP_VAL;
6300 goto CLEANUP;
6301 }
6302 #endif
6303 }
6304
6305 /* q3 = q2 / b**(k+1) */
6306 mp_rshd (&q, um + 1);
6307
6308 /* x = x mod b**(k+1), quick (no division) */
6309 if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
6310 goto CLEANUP;
6311 }
6312
6313 /* q = q * m mod b**(k+1), quick (no division) */
6314 if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
6315 goto CLEANUP;
6316 }
6317
6318 /* x = x - q */
6319 if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
6320 goto CLEANUP;
6321 }
6322
6323 /* If x < 0, add b**(k+1) to it */
6324 if (mp_cmp_d (x, 0) == MP_LT) {
6325 mp_set (&q, 1);
6326 if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
6327 goto CLEANUP;
6328 if ((res = mp_add (x, &q, x)) != MP_OKAY)
6329 goto CLEANUP;
6330 }
6331
6332 /* Back off if it's too big */
6333 while (mp_cmp (x, m) != MP_LT) {
6334 if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
6335 goto CLEANUP;
6336 }
6337 }
6338
6339 CLEANUP:
6340 mp_clear (&q);
6341
6342 return res;
6343 }
6344 #endif
6345
6346 /* End: bn_mp_reduce.c */
6347
6348 /* Start: bn_mp_reduce_2k.c */
6349 #include <tommath.h>
6350 #ifdef BN_MP_REDUCE_2K_C
6351 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6352 *
6353 * LibTomMath is a library that provides multiple-precision
6354 * integer arithmetic as well as number theoretic functionality.
6355 *
6356 * The library was designed directly after the MPI library by
6357 * Michael Fromberger but has been written from scratch with
6358 * additional optimizations in place.
6359 *
6360 * The library is free for all purposes without any express
6361 * guarantee it works.
6362 *
6363 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6364 */
6365
6366 /* reduces a modulo n where n is of the form 2**p - d */
6367 int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
6368 {
6369 mp_int q;
6370 int p, res;
6371
6372 if ((res = mp_init(&q)) != MP_OKAY) {
6373 return res;
6374 }
6375
6376 p = mp_count_bits(n);
6377 top:
6378 /* q = a/2**p, a = a mod 2**p */
6379 if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
6380 goto ERR;
6381 }
6382
6383 if (d != 1) {
6384 /* q = q * d */
6385 if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {
6386 goto ERR;
6387 }
6388 }
6389
6390 /* a = a + q */
6391 if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
6392 goto ERR;
6393 }
6394
6395 if (mp_cmp_mag(a, n) != MP_LT) {
6396 s_mp_sub(a, n, a);
6397 goto top;
6398 }
6399
6400 ERR:
6401 mp_clear(&q);
6402 return res;
6403 }
6404
6405 #endif
6406
6407 /* End: bn_mp_reduce_2k.c */
6408
6409 /* Start: bn_mp_reduce_2k_l.c */
6410 #include <tommath.h>
6411 #ifdef BN_MP_REDUCE_2K_L_C
6412 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6413 *
6414 * LibTomMath is a library that provides multiple-precision
6415 * integer arithmetic as well as number theoretic functionality.
6416 *
6417 * The library was designed directly after the MPI library by
6418 * Michael Fromberger but has been written from scratch with
6419 * additional optimizations in place.
6420 *
6421 * The library is free for all purposes without any express
6422 * guarantee it works.
6423 *
6424 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6425 */
6426
6427 /* reduces a modulo n where n is of the form 2**p - d
6428 This differs from reduce_2k since "d" can be larger
6429 than a single digit.
6430 */
6431 int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
6432 {
6433 mp_int q;
6434 int p, res;
6435
6436 if ((res = mp_init(&q)) != MP_OKAY) {
6437 return res;
6438 }
6439
6440 p = mp_count_bits(n);
6441 top:
6442 /* q = a/2**p, a = a mod 2**p */
6443 if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
6444 goto ERR;
6445 }
6446
6447 /* q = q * d */
6448 if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {
6449 goto ERR;
6450 }
6451
6452 /* a = a + q */
6453 if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
6454 goto ERR;
6455 }
6456
6457 if (mp_cmp_mag(a, n) != MP_LT) {
6458 s_mp_sub(a, n, a);
6459 goto top;
6460 }
6461
6462 ERR:
6463 mp_clear(&q);
6464 return res;
6465 }
6466
6467 #endif
6468
6469 /* End: bn_mp_reduce_2k_l.c */
6470
6471 /* Start: bn_mp_reduce_2k_setup.c */
6472 #include <tommath.h>
6473 #ifdef BN_MP_REDUCE_2K_SETUP_C
6474 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6475 *
6476 * LibTomMath is a library that provides multiple-precision
6477 * integer arithmetic as well as number theoretic functionality.
6478 *
6479 * The library was designed directly after the MPI library by
6480 * Michael Fromberger but has been written from scratch with
6481 * additional optimizations in place.
6482 *
6483 * The library is free for all purposes without any express
6484 * guarantee it works.
6485 *
6486 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6487 */
6488
6489 /* determines the setup value */
6490 int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
6491 {
6492 int res, p;
6493 mp_int tmp;
6494
6495 if ((res = mp_init(&tmp)) != MP_OKAY) {
6496 return res;
6497 }
6498
6499 p = mp_count_bits(a);
6500 if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
6501 mp_clear(&tmp);
6502 return res;
6503 }
6504
6505 if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
6506 mp_clear(&tmp);
6507 return res;
6508 }
6509
6510 *d = tmp.dp[0];
6511 mp_clear(&tmp);
6512 return MP_OKAY;
6513 }
6514 #endif
6515
6516 /* End: bn_mp_reduce_2k_setup.c */
6517
6518 /* Start: bn_mp_reduce_2k_setup_l.c */
6519 #include <tommath.h>
6520 #ifdef BN_MP_REDUCE_2K_SETUP_L_C
6521 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6522 *
6523 * LibTomMath is a library that provides multiple-precision
6524 * integer arithmetic as well as number theoretic functionality.
6525 *
6526 * The library was designed directly after the MPI library by
6527 * Michael Fromberger but has been written from scratch with
6528 * additional optimizations in place.
6529 *
6530 * The library is free for all purposes without any express
6531 * guarantee it works.
6532 *
6533 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6534 */
6535
6536 /* determines the setup value */
6537 int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
6538 {
6539 int res;
6540 mp_int tmp;
6541
6542 if ((res = mp_init(&tmp)) != MP_OKAY) {
6543 return res;
6544 }
6545
6546 if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
6547 goto ERR;
6548 }
6549
6550 if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
6551 goto ERR;
6552 }
6553
6554 ERR:
6555 mp_clear(&tmp);
6556 return res;
6557 }
6558 #endif
6559
6560 /* End: bn_mp_reduce_2k_setup_l.c */
6561
6562 /* Start: bn_mp_reduce_is_2k.c */
6563 #include <tommath.h>
6564 #ifdef BN_MP_REDUCE_IS_2K_C
6565 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6566 *
6567 * LibTomMath is a library that provides multiple-precision
6568 * integer arithmetic as well as number theoretic functionality.
6569 *
6570 * The library was designed directly after the MPI library by
6571 * Michael Fromberger but has been written from scratch with
6572 * additional optimizations in place.
6573 *
6574 * The library is free for all purposes without any express
6575 * guarantee it works.
6576 *
6577 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6578 */
6579
6580 /* determines if mp_reduce_2k can be used */
6581 int mp_reduce_is_2k(mp_int *a)
6582 {
6583 int ix, iy, iw;
6584 mp_digit iz;
6585
6586 if (a->used == 0) {
6587 return MP_NO;
6588 } else if (a->used == 1) {
6589 return MP_YES;
6590 } else if (a->used > 1) {
6591 iy = mp_count_bits(a);
6592 iz = 1;
6593 iw = 1;
6594
6595 /* Test every bit from the second digit up, must be 1 */
6596 for (ix = DIGIT_BIT; ix < iy; ix++) {
6597 if ((a->dp[iw] & iz) == 0) {
6598 return MP_NO;
6599 }
6600 iz <<= 1;
6601 if (iz > (mp_digit)MP_MASK) {
6602 ++iw;
6603 iz = 1;
6604 }
6605 }
6606 }
6607 return MP_YES;
6608 }
6609
6610 #endif
6611
6612 /* End: bn_mp_reduce_is_2k.c */
6613
6614 /* Start: bn_mp_reduce_is_2k_l.c */
6615 #include <tommath.h>
6616 #ifdef BN_MP_REDUCE_IS_2K_L_C
6617 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6618 *
6619 * LibTomMath is a library that provides multiple-precision
6620 * integer arithmetic as well as number theoretic functionality.
6621 *
6622 * The library was designed directly after the MPI library by
6623 * Michael Fromberger but has been written from scratch with
6624 * additional optimizations in place.
6625 *
6626 * The library is free for all purposes without any express
6627 * guarantee it works.
6628 *
6629 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6630 */
6631
6632 /* determines if reduce_2k_l can be used */
6633 int mp_reduce_is_2k_l(mp_int *a)
6634 {
6635 int ix, iy;
6636
6637 if (a->used == 0) {
6638 return MP_NO;
6639 } else if (a->used == 1) {
6640 return MP_YES;
6641 } else if (a->used > 1) {
6642 /* if more than half of the digits are -1 we're sold */
6643 for (iy = ix = 0; ix < a->used; ix++) {
6644 if (a->dp[ix] == MP_MASK) {
6645 ++iy;
6646 }
6647 }
6648 return (iy >= (a->used/2)) ? MP_YES : MP_NO;
6649
6650 }
6651 return MP_NO;
6652 }
6653
6654 #endif
6655
6656 /* End: bn_mp_reduce_is_2k_l.c */
6657
6658 /* Start: bn_mp_reduce_setup.c */
6659 #include <tommath.h>
6660 #ifdef BN_MP_REDUCE_SETUP_C
6661 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6662 *
6663 * LibTomMath is a library that provides multiple-precision
6664 * integer arithmetic as well as number theoretic functionality.
6665 *
6666 * The library was designed directly after the MPI library by
6667 * Michael Fromberger but has been written from scratch with
6668 * additional optimizations in place.
6669 *
6670 * The library is free for all purposes without any express
6671 * guarantee it works.
6672 *
6673 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6674 */
6675
6676 /* pre-calculate the value required for Barrett reduction
6677 * For a given modulus "b" it calulates the value required in "a"
6678 */
6679 int mp_reduce_setup (mp_int * a, mp_int * b)
6680 {
6681 int res;
6682
6683 if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
6684 return res;
6685 }
6686 return mp_div (a, b, a, NULL);
6687 }
6688 #endif
6689
6690 /* End: bn_mp_reduce_setup.c */
6691
6692 /* Start: bn_mp_rshd.c */
6693 #include <tommath.h>
6694 #ifdef BN_MP_RSHD_C
6695 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6696 *
6697 * LibTomMath is a library that provides multiple-precision
6698 * integer arithmetic as well as number theoretic functionality.
6699 *
6700 * The library was designed directly after the MPI library by
6701 * Michael Fromberger but has been written from scratch with
6702 * additional optimizations in place.
6703 *
6704 * The library is free for all purposes without any express
6705 * guarantee it works.
6706 *
6707 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6708 */
6709
6710 /* shift right a certain amount of digits */
6711 void mp_rshd (mp_int * a, int b)
6712 {
6713 int x;
6714
6715 /* if b <= 0 then ignore it */
6716 if (b <= 0) {
6717 return;
6718 }
6719
6720 /* if b > used then simply zero it and return */
6721 if (a->used <= b) {
6722 mp_zero (a);
6723 return;
6724 }
6725
6726 {
6727 register mp_digit *bottom, *top;
6728
6729 /* shift the digits down */
6730
6731 /* bottom */
6732 bottom = a->dp;
6733
6734 /* top [offset into digits] */
6735 top = a->dp + b;
6736
6737 /* this is implemented as a sliding window where
6738 * the window is b-digits long and digits from
6739 * the top of the window are copied to the bottom
6740 *
6741 * e.g.
6742
6743 b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
6744 /\ | ---->
6745 \-------------------/ ---->
6746 */
6747 for (x = 0; x < (a->used - b); x++) {
6748 *bottom++ = *top++;
6749 }
6750
6751 /* zero the top digits */
6752 for (; x < a->used; x++) {
6753 *bottom++ = 0;
6754 }
6755 }
6756
6757 /* remove excess digits */
6758 a->used -= b;
6759 }
6760 #endif
6761
6762 /* End: bn_mp_rshd.c */
6763
6764 /* Start: bn_mp_set.c */
6765 #include <tommath.h>
6766 #ifdef BN_MP_SET_C
6767 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6768 *
6769 * LibTomMath is a library that provides multiple-precision
6770 * integer arithmetic as well as number theoretic functionality.
6771 *
6772 * The library was designed directly after the MPI library by
6773 * Michael Fromberger but has been written from scratch with
6774 * additional optimizations in place.
6775 *
6776 * The library is free for all purposes without any express
6777 * guarantee it works.
6778 *
6779 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6780 */
6781
6782 /* set to a digit */
6783 void mp_set (mp_int * a, mp_digit b)
6784 {
6785 mp_zero (a);
6786 a->dp[0] = b & MP_MASK;
6787 a->used = (a->dp[0] != 0) ? 1 : 0;
6788 }
6789 #endif
6790
6791 /* End: bn_mp_set.c */
6792
6793 /* Start: bn_mp_set_int.c */
6794 #include <tommath.h>
6795 #ifdef BN_MP_SET_INT_C
6796 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6797 *
6798 * LibTomMath is a library that provides multiple-precision
6799 * integer arithmetic as well as number theoretic functionality.
6800 *
6801 * The library was designed directly after the MPI library by
6802 * Michael Fromberger but has been written from scratch with
6803 * additional optimizations in place.
6804 *
6805 * The library is free for all purposes without any express
6806 * guarantee it works.
6807 *
6808 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6809 */
6810
6811 /* set a 32-bit const */
6812 int mp_set_int (mp_int * a, unsigned long b)
6813 {
6814 int x, res;
6815
6816 mp_zero (a);
6817
6818 /* set four bits at a time */
6819 for (x = 0; x < 8; x++) {
6820 /* shift the number up four bits */
6821 if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
6822 return res;
6823 }
6824
6825 /* OR in the top four bits of the source */
6826 a->dp[0] |= (b >> 28) & 15;
6827
6828 /* shift the source up to the next four bits */
6829 b <<= 4;
6830
6831 /* ensure that digits are not clamped off */
6832 a->used += 1;
6833 }
6834 mp_clamp (a);
6835 return MP_OKAY;
6836 }
6837 #endif
6838
6839 /* End: bn_mp_set_int.c */
6840
6841 /* Start: bn_mp_shrink.c */
6842 #include <tommath.h>
6843 #ifdef BN_MP_SHRINK_C
6844 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6845 *
6846 * LibTomMath is a library that provides multiple-precision
6847 * integer arithmetic as well as number theoretic functionality.
6848 *
6849 * The library was designed directly after the MPI library by
6850 * Michael Fromberger but has been written from scratch with
6851 * additional optimizations in place.
6852 *
6853 * The library is free for all purposes without any express
6854 * guarantee it works.
6855 *
6856 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6857 */
6858
6859 /* shrink a bignum */
6860 int mp_shrink (mp_int * a)
6861 {
6862 mp_digit *tmp;
6863 if (a->alloc != a->used && a->used > 0) {
6864 if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
6865 return MP_MEM;
6866 }
6867 a->dp = tmp;
6868 a->alloc = a->used;
6869 }
6870 return MP_OKAY;
6871 }
6872 #endif
6873
6874 /* End: bn_mp_shrink.c */
6875
6876 /* Start: bn_mp_signed_bin_size.c */
6877 #include <tommath.h>
6878 #ifdef BN_MP_SIGNED_BIN_SIZE_C
6879 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6880 *
6881 * LibTomMath is a library that provides multiple-precision
6882 * integer arithmetic as well as number theoretic functionality.
6883 *
6884 * The library was designed directly after the MPI library by
6885 * Michael Fromberger but has been written from scratch with
6886 * additional optimizations in place.
6887 *
6888 * The library is free for all purposes without any express
6889 * guarantee it works.
6890 *
6891 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6892 */
6893
6894 /* get the size for an signed equivalent */
6895 int mp_signed_bin_size (mp_int * a)
6896 {
6897 return 1 + mp_unsigned_bin_size (a);
6898 }
6899 #endif
6900
6901 /* End: bn_mp_signed_bin_size.c */
6902
6903 /* Start: bn_mp_sqr.c */
6904 #include <tommath.h>
6905 #ifdef BN_MP_SQR_C
6906 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6907 *
6908 * LibTomMath is a library that provides multiple-precision
6909 * integer arithmetic as well as number theoretic functionality.
6910 *
6911 * The library was designed directly after the MPI library by
6912 * Michael Fromberger but has been written from scratch with
6913 * additional optimizations in place.
6914 *
6915 * The library is free for all purposes without any express
6916 * guarantee it works.
6917 *
6918 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6919 */
6920
6921 /* computes b = a*a */
6922 int
6923 mp_sqr (mp_int * a, mp_int * b)
6924 {
6925 int res;
6926
6927 #ifdef BN_MP_TOOM_SQR_C
6928 /* use Toom-Cook? */
6929 if (a->used >= TOOM_SQR_CUTOFF) {
6930 res = mp_toom_sqr(a, b);
6931 /* Karatsuba? */
6932 } else
6933 #endif
6934 #ifdef BN_MP_KARATSUBA_SQR_C
6935 if (a->used >= KARATSUBA_SQR_CUTOFF) {
6936 res = mp_karatsuba_sqr (a, b);
6937 } else
6938 #endif
6939 {
6940 #ifdef BN_FAST_S_MP_SQR_C
6941 /* can we use the fast comba multiplier? */
6942 if ((a->used * 2 + 1) < MP_WARRAY &&
6943 a->used <
6944 (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
6945 res = fast_s_mp_sqr (a, b);
6946 } else
6947 #endif
6948 #ifdef BN_S_MP_SQR_C
6949 res = s_mp_sqr (a, b);
6950 #else
6951 res = MP_VAL;
6952 #endif
6953 }
6954 b->sign = MP_ZPOS;
6955 return res;
6956 }
6957 #endif
6958
6959 /* End: bn_mp_sqr.c */
6960
6961 /* Start: bn_mp_sqrmod.c */
6962 #include <tommath.h>
6963 #ifdef BN_MP_SQRMOD_C
6964 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6965 *
6966 * LibTomMath is a library that provides multiple-precision
6967 * integer arithmetic as well as number theoretic functionality.
6968 *
6969 * The library was designed directly after the MPI library by
6970 * Michael Fromberger but has been written from scratch with
6971 * additional optimizations in place.
6972 *
6973 * The library is free for all purposes without any express
6974 * guarantee it works.
6975 *
6976 * Tom St Denis, [email protected], http://math.libtomcrypt.org
6977 */
6978
6979 /* c = a * a (mod b) */
6980 int
6981 mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
6982 {
6983 int res;
6984 mp_int t;
6985
6986 if ((res = mp_init (&t)) != MP_OKAY) {
6987 return res;
6988 }
6989
6990 if ((res = mp_sqr (a, &t)) != MP_OKAY) {
6991 mp_clear (&t);
6992 return res;
6993 }
6994 res = mp_mod (&t, b, c);
6995 mp_clear (&t);
6996 return res;
6997 }
6998 #endif
6999
7000 /* End: bn_mp_sqrmod.c */
7001
7002 /* Start: bn_mp_sqrt.c */
7003 #include <tommath.h>
7004 #ifdef BN_MP_SQRT_C
7005 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7006 *
7007 * LibTomMath is a library that provides multiple-precision
7008 * integer arithmetic as well as number theoretic functionality.
7009 *
7010 * The library was designed directly after the MPI library by
7011 * Michael Fromberger but has been written from scratch with
7012 * additional optimizations in place.
7013 *
7014 * The library is free for all purposes without any express
7015 * guarantee it works.
7016 *
7017 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7018 */
7019
7020 /* this function is less generic than mp_n_root, simpler and faster */
7021 int mp_sqrt(mp_int *arg, mp_int *ret)
7022 {
7023 int res;
7024 mp_int t1,t2;
7025
7026 /* must be positive */
7027 if (arg->sign == MP_NEG) {
7028 return MP_VAL;
7029 }
7030
7031 /* easy out */
7032 if (mp_iszero(arg) == MP_YES) {
7033 mp_zero(ret);
7034 return MP_OKAY;
7035 }
7036
7037 if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
7038 return res;
7039 }
7040
7041 if ((res = mp_init(&t2)) != MP_OKAY) {
7042 goto E2;
7043 }
7044
7045 /* First approx. (not very bad for large arg) */
7046 mp_rshd (&t1,t1.used/2);
7047
7048 /* t1 > 0 */
7049 if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
7050 goto E1;
7051 }
7052 if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
7053 goto E1;
7054 }
7055 if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
7056 goto E1;
7057 }
7058 /* And now t1 > sqrt(arg) */
7059 do {
7060 if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
7061 goto E1;
7062 }
7063 if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
7064 goto E1;
7065 }
7066 if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
7067 goto E1;
7068 }
7069 /* t1 >= sqrt(arg) >= t2 at this point */
7070 } while (mp_cmp_mag(&t1,&t2) == MP_GT);
7071
7072 mp_exch(&t1,ret);
7073
7074 E1: mp_clear(&t2);
7075 E2: mp_clear(&t1);
7076 return res;
7077 }
7078
7079 #endif
7080
7081 /* End: bn_mp_sqrt.c */
7082
7083 /* Start: bn_mp_sub.c */
7084 #include <tommath.h>
7085 #ifdef BN_MP_SUB_C
7086 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7087 *
7088 * LibTomMath is a library that provides multiple-precision
7089 * integer arithmetic as well as number theoretic functionality.
7090 *
7091 * The library was designed directly after the MPI library by
7092 * Michael Fromberger but has been written from scratch with
7093 * additional optimizations in place.
7094 *
7095 * The library is free for all purposes without any express
7096 * guarantee it works.
7097 *
7098 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7099 */
7100
7101 /* high level subtraction (handles signs) */
7102 int
7103 mp_sub (mp_int * a, mp_int * b, mp_int * c)
7104 {
7105 int sa, sb, res;
7106
7107 sa = a->sign;
7108 sb = b->sign;
7109
7110 if (sa != sb) {
7111 /* subtract a negative from a positive, OR */
7112 /* subtract a positive from a negative. */
7113 /* In either case, ADD their magnitudes, */
7114 /* and use the sign of the first number. */
7115 c->sign = sa;
7116 res = s_mp_add (a, b, c);
7117 } else {
7118 /* subtract a positive from a positive, OR */
7119 /* subtract a negative from a negative. */
7120 /* First, take the difference between their */
7121 /* magnitudes, then... */
7122 if (mp_cmp_mag (a, b) != MP_LT) {
7123 /* Copy the sign from the first */
7124 c->sign = sa;
7125 /* The first has a larger or equal magnitude */
7126 res = s_mp_sub (a, b, c);
7127 } else {
7128 /* The result has the *opposite* sign from */
7129 /* the first number. */
7130 c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
7131 /* The second has a larger magnitude */
7132 res = s_mp_sub (b, a, c);
7133 }
7134 }
7135 return res;
7136 }
7137
7138 #endif
7139
7140 /* End: bn_mp_sub.c */
7141
7142 /* Start: bn_mp_sub_d.c */
7143 #include <tommath.h>
7144 #ifdef BN_MP_SUB_D_C
7145 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7146 *
7147 * LibTomMath is a library that provides multiple-precision
7148 * integer arithmetic as well as number theoretic functionality.
7149 *
7150 * The library was designed directly after the MPI library by
7151 * Michael Fromberger but has been written from scratch with
7152 * additional optimizations in place.
7153 *
7154 * The library is free for all purposes without any express
7155 * guarantee it works.
7156 *
7157 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7158 */
7159
7160 /* single digit subtraction */
7161 int
7162 mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
7163 {
7164 mp_digit *tmpa, *tmpc, mu;
7165 int res, ix, oldused;
7166
7167 /* grow c as required */
7168 if (c->alloc < a->used + 1) {
7169 if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
7170 return res;
7171 }
7172 }
7173
7174 /* if a is negative just do an unsigned
7175 * addition [with fudged signs]
7176 */
7177 if (a->sign == MP_NEG) {
7178 a->sign = MP_ZPOS;
7179 res = mp_add_d(a, b, c);
7180 a->sign = c->sign = MP_NEG;
7181 return res;
7182 }
7183
7184 /* setup regs */
7185 oldused = c->used;
7186 tmpa = a->dp;
7187 tmpc = c->dp;
7188
7189 /* if a <= b simply fix the single digit */
7190 if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
7191 if (a->used == 1) {
7192 *tmpc++ = b - *tmpa;
7193 } else {
7194 *tmpc++ = b;
7195 }
7196 ix = 1;
7197
7198 /* negative/1digit */
7199 c->sign = MP_NEG;
7200 c->used = 1;
7201 } else {
7202 /* positive/size */
7203 c->sign = MP_ZPOS;
7204 c->used = a->used;
7205
7206 /* subtract first digit */
7207 *tmpc = *tmpa++ - b;
7208 mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
7209 *tmpc++ &= MP_MASK;
7210
7211 /* handle rest of the digits */
7212 for (ix = 1; ix < a->used; ix++) {
7213 *tmpc = *tmpa++ - mu;
7214 mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
7215 *tmpc++ &= MP_MASK;
7216 }
7217 }
7218
7219 /* zero excess digits */
7220 while (ix++ < oldused) {
7221 *tmpc++ = 0;
7222 }
7223 mp_clamp(c);
7224 return MP_OKAY;
7225 }
7226
7227 #endif
7228
7229 /* End: bn_mp_sub_d.c */
7230
7231 /* Start: bn_mp_submod.c */
7232 #include <tommath.h>
7233 #ifdef BN_MP_SUBMOD_C
7234 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7235 *
7236 * LibTomMath is a library that provides multiple-precision
7237 * integer arithmetic as well as number theoretic functionality.
7238 *
7239 * The library was designed directly after the MPI library by
7240 * Michael Fromberger but has been written from scratch with
7241 * additional optimizations in place.
7242 *
7243 * The library is free for all purposes without any express
7244 * guarantee it works.
7245 *
7246 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7247 */
7248
7249 /* d = a - b (mod c) */
7250 int
7251 mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
7252 {
7253 int res;
7254 mp_int t;
7255
7256
7257 if ((res = mp_init (&t)) != MP_OKAY) {
7258 return res;
7259 }
7260
7261 if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
7262 mp_clear (&t);
7263 return res;
7264 }
7265 res = mp_mod (&t, c, d);
7266 mp_clear (&t);
7267 return res;
7268 }
7269 #endif
7270
7271 /* End: bn_mp_submod.c */
7272
7273 /* Start: bn_mp_to_signed_bin.c */
7274 #include <tommath.h>
7275 #ifdef BN_MP_TO_SIGNED_BIN_C
7276 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7277 *
7278 * LibTomMath is a library that provides multiple-precision
7279 * integer arithmetic as well as number theoretic functionality.
7280 *
7281 * The library was designed directly after the MPI library by
7282 * Michael Fromberger but has been written from scratch with
7283 * additional optimizations in place.
7284 *
7285 * The library is free for all purposes without any express
7286 * guarantee it works.
7287 *
7288 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7289 */
7290
7291 /* store in signed [big endian] format */
7292 int mp_to_signed_bin (mp_int * a, unsigned char *b)
7293 {
7294 int res;
7295
7296 if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
7297 return res;
7298 }
7299 b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
7300 return MP_OKAY;
7301 }
7302 #endif
7303
7304 /* End: bn_mp_to_signed_bin.c */
7305
7306 /* Start: bn_mp_to_signed_bin_n.c */
7307 #include <tommath.h>
7308 #ifdef BN_MP_TO_SIGNED_BIN_N_C
7309 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7310 *
7311 * LibTomMath is a library that provides multiple-precision
7312 * integer arithmetic as well as number theoretic functionality.
7313 *
7314 * The library was designed directly after the MPI library by
7315 * Michael Fromberger but has been written from scratch with
7316 * additional optimizations in place.
7317 *
7318 * The library is free for all purposes without any express
7319 * guarantee it works.
7320 *
7321 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7322 */
7323
7324 /* store in signed [big endian] format */
7325 int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
7326 {
7327 if (*outlen < (unsigned long)mp_signed_bin_size(a)) {
7328 return MP_VAL;
7329 }
7330 *outlen = mp_signed_bin_size(a);
7331 return mp_to_signed_bin(a, b);
7332 }
7333 #endif
7334
7335 /* End: bn_mp_to_signed_bin_n.c */
7336
7337 /* Start: bn_mp_to_unsigned_bin.c */
7338 #include <tommath.h>
7339 #ifdef BN_MP_TO_UNSIGNED_BIN_C
7340 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7341 *
7342 * LibTomMath is a library that provides multiple-precision
7343 * integer arithmetic as well as number theoretic functionality.
7344 *
7345 * The library was designed directly after the MPI library by
7346 * Michael Fromberger but has been written from scratch with
7347 * additional optimizations in place.
7348 *
7349 * The library is free for all purposes without any express
7350 * guarantee it works.
7351 *
7352 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7353 */
7354
7355 /* store in unsigned [big endian] format */
7356 int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
7357 {
7358 int x, res;
7359 mp_int t;
7360
7361 if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
7362 return res;
7363 }
7364
7365 x = 0;
7366 while (mp_iszero (&t) == 0) {
7367 #ifndef MP_8BIT
7368 b[x++] = (unsigned char) (t.dp[0] & 255);
7369 #else
7370 b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
7371 #endif
7372 if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
7373 mp_clear (&t);
7374 return res;
7375 }
7376 }
7377 bn_reverse (b, x);
7378 mp_clear (&t);
7379 return MP_OKAY;
7380 }
7381 #endif
7382
7383 /* End: bn_mp_to_unsigned_bin.c */
7384
7385 /* Start: bn_mp_to_unsigned_bin_n.c */
7386 #include <tommath.h>
7387 #ifdef BN_MP_TO_UNSIGNED_BIN_N_C
7388 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7389 *
7390 * LibTomMath is a library that provides multiple-precision
7391 * integer arithmetic as well as number theoretic functionality.
7392 *
7393 * The library was designed directly after the MPI library by
7394 * Michael Fromberger but has been written from scratch with
7395 * additional optimizations in place.
7396 *
7397 * The library is free for all purposes without any express
7398 * guarantee it works.
7399 *
7400 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7401 */
7402
7403 /* store in unsigned [big endian] format */
7404 int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
7405 {
7406 if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) {
7407 return MP_VAL;
7408 }
7409 *outlen = mp_unsigned_bin_size(a);
7410 return mp_to_unsigned_bin(a, b);
7411 }
7412 #endif
7413
7414 /* End: bn_mp_to_unsigned_bin_n.c */
7415
7416 /* Start: bn_mp_toom_mul.c */
7417 #include <tommath.h>
7418 #ifdef BN_MP_TOOM_MUL_C
7419 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7420 *
7421 * LibTomMath is a library that provides multiple-precision
7422 * integer arithmetic as well as number theoretic functionality.
7423 *
7424 * The library was designed directly after the MPI library by
7425 * Michael Fromberger but has been written from scratch with
7426 * additional optimizations in place.
7427 *
7428 * The library is free for all purposes without any express
7429 * guarantee it works.
7430 *
7431 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7432 */
7433
7434 /* multiplication using the Toom-Cook 3-way algorithm
7435 *
7436 * Much more complicated than Karatsuba but has a lower
7437 * asymptotic running time of O(N**1.464). This algorithm is
7438 * only particularly useful on VERY large inputs
7439 * (we're talking 1000s of digits here...).
7440 */
7441 int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
7442 {
7443 mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
7444 int res, B;
7445
7446 /* init temps */
7447 if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4,
7448 &a0, &a1, &a2, &b0, &b1,
7449 &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
7450 return res;
7451 }
7452
7453 /* B */
7454 B = MIN(a->used, b->used) / 3;
7455
7456 /* a = a2 * B**2 + a1 * B + a0 */
7457 if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
7458 goto ERR;
7459 }
7460
7461 if ((res = mp_copy(a, &a1)) != MP_OKAY) {
7462 goto ERR;
7463 }
7464 mp_rshd(&a1, B);
7465 mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
7466
7467 if ((res = mp_copy(a, &a2)) != MP_OKAY) {
7468 goto ERR;
7469 }
7470 mp_rshd(&a2, B*2);
7471
7472 /* b = b2 * B**2 + b1 * B + b0 */
7473 if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
7474 goto ERR;
7475 }
7476
7477 if ((res = mp_copy(b, &b1)) != MP_OKAY) {
7478 goto ERR;
7479 }
7480 mp_rshd(&b1, B);
7481 mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
7482
7483 if ((res = mp_copy(b, &b2)) != MP_OKAY) {
7484 goto ERR;
7485 }
7486 mp_rshd(&b2, B*2);
7487
7488 /* w0 = a0*b0 */
7489 if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
7490 goto ERR;
7491 }
7492
7493 /* w4 = a2 * b2 */
7494 if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
7495 goto ERR;
7496 }
7497
7498 /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
7499 if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
7500 goto ERR;
7501 }
7502 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
7503 goto ERR;
7504 }
7505 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
7506 goto ERR;
7507 }
7508 if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
7509 goto ERR;
7510 }
7511
7512 if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
7513 goto ERR;
7514 }
7515 if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
7516 goto ERR;
7517 }
7518 if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
7519 goto ERR;
7520 }
7521 if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
7522 goto ERR;
7523 }
7524
7525 if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
7526 goto ERR;
7527 }
7528
7529 /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
7530 if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
7531 goto ERR;
7532 }
7533 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
7534 goto ERR;
7535 }
7536 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
7537 goto ERR;
7538 }
7539 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
7540 goto ERR;
7541 }
7542
7543 if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
7544 goto ERR;
7545 }
7546 if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
7547 goto ERR;
7548 }
7549 if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
7550 goto ERR;
7551 }
7552 if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
7553 goto ERR;
7554 }
7555
7556 if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
7557 goto ERR;
7558 }
7559
7560
7561 /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
7562 if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
7563 goto ERR;
7564 }
7565 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
7566 goto ERR;
7567 }
7568 if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
7569 goto ERR;
7570 }
7571 if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
7572 goto ERR;
7573 }
7574 if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
7575 goto ERR;
7576 }
7577
7578 /* now solve the matrix
7579
7580 0 0 0 0 1
7581 1 2 4 8 16
7582 1 1 1 1 1
7583 16 8 4 2 1
7584 1 0 0 0 0
7585
7586 using 12 subtractions, 4 shifts,
7587 2 small divisions and 1 small multiplication
7588 */
7589
7590 /* r1 - r4 */
7591 if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
7592 goto ERR;
7593 }
7594 /* r3 - r0 */
7595 if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
7596 goto ERR;
7597 }
7598 /* r1/2 */
7599 if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
7600 goto ERR;
7601 }
7602 /* r3/2 */
7603 if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
7604 goto ERR;
7605 }
7606 /* r2 - r0 - r4 */
7607 if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
7608 goto ERR;
7609 }
7610 if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
7611 goto ERR;
7612 }
7613 /* r1 - r2 */
7614 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
7615 goto ERR;
7616 }
7617 /* r3 - r2 */
7618 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
7619 goto ERR;
7620 }
7621 /* r1 - 8r0 */
7622 if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
7623 goto ERR;
7624 }
7625 if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
7626 goto ERR;
7627 }
7628 /* r3 - 8r4 */
7629 if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
7630 goto ERR;
7631 }
7632 if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
7633 goto ERR;
7634 }
7635 /* 3r2 - r1 - r3 */
7636 if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
7637 goto ERR;
7638 }
7639 if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
7640 goto ERR;
7641 }
7642 if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
7643 goto ERR;
7644 }
7645 /* r1 - r2 */
7646 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
7647 goto ERR;
7648 }
7649 /* r3 - r2 */
7650 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
7651 goto ERR;
7652 }
7653 /* r1/3 */
7654 if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
7655 goto ERR;
7656 }
7657 /* r3/3 */
7658 if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
7659 goto ERR;
7660 }
7661
7662 /* at this point shift W[n] by B*n */
7663 if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
7664 goto ERR;
7665 }
7666 if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
7667 goto ERR;
7668 }
7669 if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
7670 goto ERR;
7671 }
7672 if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
7673 goto ERR;
7674 }
7675
7676 if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
7677 goto ERR;
7678 }
7679 if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
7680 goto ERR;
7681 }
7682 if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
7683 goto ERR;
7684 }
7685 if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
7686 goto ERR;
7687 }
7688
7689 ERR:
7690 mp_clear_multi(&w0, &w1, &w2, &w3, &w4,
7691 &a0, &a1, &a2, &b0, &b1,
7692 &b2, &tmp1, &tmp2, NULL);
7693 return res;
7694 }
7695
7696 #endif
7697
7698 /* End: bn_mp_toom_mul.c */
7699
7700 /* Start: bn_mp_toom_sqr.c */
7701 #include <tommath.h>
7702 #ifdef BN_MP_TOOM_SQR_C
7703 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7704 *
7705 * LibTomMath is a library that provides multiple-precision
7706 * integer arithmetic as well as number theoretic functionality.
7707 *
7708 * The library was designed directly after the MPI library by
7709 * Michael Fromberger but has been written from scratch with
7710 * additional optimizations in place.
7711 *
7712 * The library is free for all purposes without any express
7713 * guarantee it works.
7714 *
7715 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7716 */
7717
7718 /* squaring using Toom-Cook 3-way algorithm */
7719 int
7720 mp_toom_sqr(mp_int *a, mp_int *b)
7721 {
7722 mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
7723 int res, B;
7724
7725 /* init temps */
7726 if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
7727 return res;
7728 }
7729
7730 /* B */
7731 B = a->used / 3;
7732
7733 /* a = a2 * B**2 + a1 * B + a0 */
7734 if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
7735 goto ERR;
7736 }
7737
7738 if ((res = mp_copy(a, &a1)) != MP_OKAY) {
7739 goto ERR;
7740 }
7741 mp_rshd(&a1, B);
7742 mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
7743
7744 if ((res = mp_copy(a, &a2)) != MP_OKAY) {
7745 goto ERR;
7746 }
7747 mp_rshd(&a2, B*2);
7748
7749 /* w0 = a0*a0 */
7750 if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
7751 goto ERR;
7752 }
7753
7754 /* w4 = a2 * a2 */
7755 if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
7756 goto ERR;
7757 }
7758
7759 /* w1 = (a2 + 2(a1 + 2a0))**2 */
7760 if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
7761 goto ERR;
7762 }
7763 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
7764 goto ERR;
7765 }
7766 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
7767 goto ERR;
7768 }
7769 if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
7770 goto ERR;
7771 }
7772
7773 if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
7774 goto ERR;
7775 }
7776
7777 /* w3 = (a0 + 2(a1 + 2a2))**2 */
7778 if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
7779 goto ERR;
7780 }
7781 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
7782 goto ERR;
7783 }
7784 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
7785 goto ERR;
7786 }
7787 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
7788 goto ERR;
7789 }
7790
7791 if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
7792 goto ERR;
7793 }
7794
7795
7796 /* w2 = (a2 + a1 + a0)**2 */
7797 if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
7798 goto ERR;
7799 }
7800 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
7801 goto ERR;
7802 }
7803 if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
7804 goto ERR;
7805 }
7806
7807 /* now solve the matrix
7808
7809 0 0 0 0 1
7810 1 2 4 8 16
7811 1 1 1 1 1
7812 16 8 4 2 1
7813 1 0 0 0 0
7814
7815 using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
7816 */
7817
7818 /* r1 - r4 */
7819 if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
7820 goto ERR;
7821 }
7822 /* r3 - r0 */
7823 if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
7824 goto ERR;
7825 }
7826 /* r1/2 */
7827 if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
7828 goto ERR;
7829 }
7830 /* r3/2 */
7831 if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
7832 goto ERR;
7833 }
7834 /* r2 - r0 - r4 */
7835 if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
7836 goto ERR;
7837 }
7838 if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
7839 goto ERR;
7840 }
7841 /* r1 - r2 */
7842 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
7843 goto ERR;
7844 }
7845 /* r3 - r2 */
7846 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
7847 goto ERR;
7848 }
7849 /* r1 - 8r0 */
7850 if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
7851 goto ERR;
7852 }
7853 if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
7854 goto ERR;
7855 }
7856 /* r3 - 8r4 */
7857 if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
7858 goto ERR;
7859 }
7860 if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
7861 goto ERR;
7862 }
7863 /* 3r2 - r1 - r3 */
7864 if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
7865 goto ERR;
7866 }
7867 if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
7868 goto ERR;
7869 }
7870 if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
7871 goto ERR;
7872 }
7873 /* r1 - r2 */
7874 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
7875 goto ERR;
7876 }
7877 /* r3 - r2 */
7878 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
7879 goto ERR;
7880 }
7881 /* r1/3 */
7882 if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
7883 goto ERR;
7884 }
7885 /* r3/3 */
7886 if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
7887 goto ERR;
7888 }
7889
7890 /* at this point shift W[n] by B*n */
7891 if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
7892 goto ERR;
7893 }
7894 if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
7895 goto ERR;
7896 }
7897 if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
7898 goto ERR;
7899 }
7900 if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
7901 goto ERR;
7902 }
7903
7904 if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
7905 goto ERR;
7906 }
7907 if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
7908 goto ERR;
7909 }
7910 if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
7911 goto ERR;
7912 }
7913 if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
7914 goto ERR;
7915 }
7916
7917 ERR:
7918 mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
7919 return res;
7920 }
7921
7922 #endif
7923
7924 /* End: bn_mp_toom_sqr.c */
7925
7926 /* Start: bn_mp_toradix.c */
7927 #include <tommath.h>
7928 #ifdef BN_MP_TORADIX_C
7929 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7930 *
7931 * LibTomMath is a library that provides multiple-precision
7932 * integer arithmetic as well as number theoretic functionality.
7933 *
7934 * The library was designed directly after the MPI library by
7935 * Michael Fromberger but has been written from scratch with
7936 * additional optimizations in place.
7937 *
7938 * The library is free for all purposes without any express
7939 * guarantee it works.
7940 *
7941 * Tom St Denis, [email protected], http://math.libtomcrypt.org
7942 */
7943
7944 /* stores a bignum as a ASCII string in a given radix (2..64) */
7945 int mp_toradix (mp_int * a, char *str, int radix)
7946 {
7947 int res, digs;
7948 mp_int t;
7949 mp_digit d;
7950 char *_s = str;
7951
7952 /* check range of the radix */
7953 if (radix < 2 || radix > 64) {
7954 return MP_VAL;
7955 }
7956
7957 /* quick out if its zero */
7958 if (mp_iszero(a) == 1) {
7959 *str++ = '0';
7960 *str = '\0';
7961 return MP_OKAY;
7962 }
7963
7964 if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
7965 return res;
7966 }
7967
7968 /* if it is negative output a - */
7969 if (t.sign == MP_NEG) {
7970 ++_s;
7971 *str++ = '-';
7972 t.sign = MP_ZPOS;
7973 }
7974
7975 digs = 0;
7976 while (mp_iszero (&t) == 0) {
7977 if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
7978 mp_clear (&t);
7979 return res;
7980 }
7981 *str++ = mp_s_rmap[d];
7982 ++digs;
7983 }
7984
7985 /* reverse the digits of the string. In this case _s points
7986 * to the first digit [exluding the sign] of the number]
7987 */
7988 bn_reverse ((unsigned char *)_s, digs);
7989
7990 /* append a NULL so the string is properly terminated */
7991 *str = '\0';
7992
7993 mp_clear (&t);
7994 return MP_OKAY;
7995 }
7996
7997 #endif
7998
7999 /* End: bn_mp_toradix.c */
8000
8001 /* Start: bn_mp_toradix_n.c */
8002 #include <tommath.h>
8003 #ifdef BN_MP_TORADIX_N_C
8004 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8005 *
8006 * LibTomMath is a library that provides multiple-precision
8007 * integer arithmetic as well as number theoretic functionality.
8008 *
8009 * The library was designed directly after the MPI library by
8010 * Michael Fromberger but has been written from scratch with
8011 * additional optimizations in place.
8012 *
8013 * The library is free for all purposes without any express
8014 * guarantee it works.
8015 *
8016 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8017 */
8018
8019 /* stores a bignum as a ASCII string in a given radix (2..64)
8020 *
8021 * Stores upto maxlen-1 chars and always a NULL byte
8022 */
8023 int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
8024 {
8025 int res, digs;
8026 mp_int t;
8027 mp_digit d;
8028 char *_s = str;
8029
8030 /* check range of the maxlen, radix */
8031 if (maxlen < 3 || radix < 2 || radix > 64) {
8032 return MP_VAL;
8033 }
8034
8035 /* quick out if its zero */
8036 if (mp_iszero(a) == 1) {
8037 *str++ = '0';
8038 *str = '\0';
8039 return MP_OKAY;
8040 }
8041
8042 if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
8043 return res;
8044 }
8045
8046 /* if it is negative output a - */
8047 if (t.sign == MP_NEG) {
8048 /* we have to reverse our digits later... but not the - sign!! */
8049 ++_s;
8050
8051 /* store the flag and mark the number as positive */
8052 *str++ = '-';
8053 t.sign = MP_ZPOS;
8054
8055 /* subtract a char */
8056 --maxlen;
8057 }
8058
8059 digs = 0;
8060 while (mp_iszero (&t) == 0) {
8061 if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
8062 mp_clear (&t);
8063 return res;
8064 }
8065 *str++ = mp_s_rmap[d];
8066 ++digs;
8067
8068 if (--maxlen == 1) {
8069 /* no more room */
8070 break;
8071 }
8072 }
8073
8074 /* reverse the digits of the string. In this case _s points
8075 * to the first digit [exluding the sign] of the number]
8076 */
8077 bn_reverse ((unsigned char *)_s, digs);
8078
8079 /* append a NULL so the string is properly terminated */
8080 *str = '\0';
8081
8082 mp_clear (&t);
8083 return MP_OKAY;
8084 }
8085
8086 #endif
8087
8088 /* End: bn_mp_toradix_n.c */
8089
8090 /* Start: bn_mp_unsigned_bin_size.c */
8091 #include <tommath.h>
8092 #ifdef BN_MP_UNSIGNED_BIN_SIZE_C
8093 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8094 *
8095 * LibTomMath is a library that provides multiple-precision
8096 * integer arithmetic as well as number theoretic functionality.
8097 *
8098 * The library was designed directly after the MPI library by
8099 * Michael Fromberger but has been written from scratch with
8100 * additional optimizations in place.
8101 *
8102 * The library is free for all purposes without any express
8103 * guarantee it works.
8104 *
8105 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8106 */
8107
8108 /* get the size for an unsigned equivalent */
8109 int mp_unsigned_bin_size (mp_int * a)
8110 {
8111 int size = mp_count_bits (a);
8112 return (size / 8 + ((size & 7) != 0 ? 1 : 0));
8113 }
8114 #endif
8115
8116 /* End: bn_mp_unsigned_bin_size.c */
8117
8118 /* Start: bn_mp_xor.c */
8119 #include <tommath.h>
8120 #ifdef BN_MP_XOR_C
8121 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8122 *
8123 * LibTomMath is a library that provides multiple-precision
8124 * integer arithmetic as well as number theoretic functionality.
8125 *
8126 * The library was designed directly after the MPI library by
8127 * Michael Fromberger but has been written from scratch with
8128 * additional optimizations in place.
8129 *
8130 * The library is free for all purposes without any express
8131 * guarantee it works.
8132 *
8133 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8134 */
8135
8136 /* XOR two ints together */
8137 int
8138 mp_xor (mp_int * a, mp_int * b, mp_int * c)
8139 {
8140 int res, ix, px;
8141 mp_int t, *x;
8142
8143 if (a->used > b->used) {
8144 if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
8145 return res;
8146 }
8147 px = b->used;
8148 x = b;
8149 } else {
8150 if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
8151 return res;
8152 }
8153 px = a->used;
8154 x = a;
8155 }
8156
8157 for (ix = 0; ix < px; ix++) {
8158 t.dp[ix] ^= x->dp[ix];
8159 }
8160 mp_clamp (&t);
8161 mp_exch (c, &t);
8162 mp_clear (&t);
8163 return MP_OKAY;
8164 }
8165 #endif
8166
8167 /* End: bn_mp_xor.c */
8168
8169 /* Start: bn_mp_zero.c */
8170 #include <tommath.h>
8171 #ifdef BN_MP_ZERO_C
8172 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8173 *
8174 * LibTomMath is a library that provides multiple-precision
8175 * integer arithmetic as well as number theoretic functionality.
8176 *
8177 * The library was designed directly after the MPI library by
8178 * Michael Fromberger but has been written from scratch with
8179 * additional optimizations in place.
8180 *
8181 * The library is free for all purposes without any express
8182 * guarantee it works.
8183 *
8184 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8185 */
8186
8187 /* set to zero */
8188 void mp_zero (mp_int * a)
8189 {
8190 int n;
8191 mp_digit *tmp;
8192
8193 a->sign = MP_ZPOS;
8194 a->used = 0;
8195
8196 tmp = a->dp;
8197 for (n = 0; n < a->alloc; n++) {
8198 *tmp++ = 0;
8199 }
8200 }
8201 #endif
8202
8203 /* End: bn_mp_zero.c */
8204
8205 /* Start: bn_prime_tab.c */
8206 #include <tommath.h>
8207 #ifdef BN_PRIME_TAB_C
8208 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8209 *
8210 * LibTomMath is a library that provides multiple-precision
8211 * integer arithmetic as well as number theoretic functionality.
8212 *
8213 * The library was designed directly after the MPI library by
8214 * Michael Fromberger but has been written from scratch with
8215 * additional optimizations in place.
8216 *
8217 * The library is free for all purposes without any express
8218 * guarantee it works.
8219 *
8220 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8221 */
8222 const mp_digit ltm_prime_tab[] = {
8223 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
8224 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
8225 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
8226 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
8227 #ifndef MP_8BIT
8228 0x0083,
8229 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
8230 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
8231 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
8232 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
8233
8234 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
8235 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
8236 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
8237 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
8238 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
8239 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
8240 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
8241 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
8242
8243 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
8244 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
8245 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
8246 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
8247 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
8248 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
8249 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
8250 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
8251
8252 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
8253 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
8254 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
8255 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
8256 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
8257 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
8258 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
8259 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
8260 #endif
8261 };
8262 #endif
8263
8264 /* End: bn_prime_tab.c */
8265
8266 /* Start: bn_reverse.c */
8267 #include <tommath.h>
8268 #ifdef BN_REVERSE_C
8269 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8270 *
8271 * LibTomMath is a library that provides multiple-precision
8272 * integer arithmetic as well as number theoretic functionality.
8273 *
8274 * The library was designed directly after the MPI library by
8275 * Michael Fromberger but has been written from scratch with
8276 * additional optimizations in place.
8277 *
8278 * The library is free for all purposes without any express
8279 * guarantee it works.
8280 *
8281 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8282 */
8283
8284 /* reverse an array, used for radix code */
8285 void
8286 bn_reverse (unsigned char *s, int len)
8287 {
8288 int ix, iy;
8289 unsigned char t;
8290
8291 ix = 0;
8292 iy = len - 1;
8293 while (ix < iy) {
8294 t = s[ix];
8295 s[ix] = s[iy];
8296 s[iy] = t;
8297 ++ix;
8298 --iy;
8299 }
8300 }
8301 #endif
8302
8303 /* End: bn_reverse.c */
8304
8305 /* Start: bn_s_mp_add.c */
8306 #include <tommath.h>
8307 #ifdef BN_S_MP_ADD_C
8308 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8309 *
8310 * LibTomMath is a library that provides multiple-precision
8311 * integer arithmetic as well as number theoretic functionality.
8312 *
8313 * The library was designed directly after the MPI library by
8314 * Michael Fromberger but has been written from scratch with
8315 * additional optimizations in place.
8316 *
8317 * The library is free for all purposes without any express
8318 * guarantee it works.
8319 *
8320 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8321 */
8322
8323 /* low level addition, based on HAC pp.594, Algorithm 14.7 */
8324 int
8325 s_mp_add (mp_int * a, mp_int * b, mp_int * c)
8326 {
8327 mp_int *x;
8328 int olduse, res, min, max;
8329
8330 /* find sizes, we let |a| <= |b| which means we have to sort
8331 * them. "x" will point to the input with the most digits
8332 */
8333 if (a->used > b->used) {
8334 min = b->used;
8335 max = a->used;
8336 x = a;
8337 } else {
8338 min = a->used;
8339 max = b->used;
8340 x = b;
8341 }
8342
8343 /* init result */
8344 if (c->alloc < max + 1) {
8345 if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
8346 return res;
8347 }
8348 }
8349
8350 /* get old used digit count and set new one */
8351 olduse = c->used;
8352 c->used = max + 1;
8353
8354 {
8355 register mp_digit u, *tmpa, *tmpb, *tmpc;
8356 register int i;
8357
8358 /* alias for digit pointers */
8359
8360 /* first input */
8361 tmpa = a->dp;
8362
8363 /* second input */
8364 tmpb = b->dp;
8365
8366 /* destination */
8367 tmpc = c->dp;
8368
8369 /* zero the carry */
8370 u = 0;
8371 for (i = 0; i < min; i++) {
8372 /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
8373 *tmpc = *tmpa++ + *tmpb++ + u;
8374
8375 /* U = carry bit of T[i] */
8376 u = *tmpc >> ((mp_digit)DIGIT_BIT);
8377
8378 /* take away carry bit from T[i] */
8379 *tmpc++ &= MP_MASK;
8380 }
8381
8382 /* now copy higher words if any, that is in A+B
8383 * if A or B has more digits add those in
8384 */
8385 if (min != max) {
8386 for (; i < max; i++) {
8387 /* T[i] = X[i] + U */
8388 *tmpc = x->dp[i] + u;
8389
8390 /* U = carry bit of T[i] */
8391 u = *tmpc >> ((mp_digit)DIGIT_BIT);
8392
8393 /* take away carry bit from T[i] */
8394 *tmpc++ &= MP_MASK;
8395 }
8396 }
8397
8398 /* add carry */
8399 *tmpc++ = u;
8400
8401 /* clear digits above oldused */
8402 for (i = c->used; i < olduse; i++) {
8403 *tmpc++ = 0;
8404 }
8405 }
8406
8407 mp_clamp (c);
8408 return MP_OKAY;
8409 }
8410 #endif
8411
8412 /* End: bn_s_mp_add.c */
8413
8414 /* Start: bn_s_mp_exptmod.c */
8415 #include <tommath.h>
8416 #ifdef BN_S_MP_EXPTMOD_C
8417 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8418 *
8419 * LibTomMath is a library that provides multiple-precision
8420 * integer arithmetic as well as number theoretic functionality.
8421 *
8422 * The library was designed directly after the MPI library by
8423 * Michael Fromberger but has been written from scratch with
8424 * additional optimizations in place.
8425 *
8426 * The library is free for all purposes without any express
8427 * guarantee it works.
8428 *
8429 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8430 */
8431
8432 #ifdef MP_LOW_MEM
8433 #define TAB_SIZE 32
8434 #else
8435 #define TAB_SIZE 256
8436 #endif
8437
8438 int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
8439 {
8440 mp_int M[TAB_SIZE], res, mu;
8441 mp_digit buf;
8442 int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
8443 int (*redux)(mp_int*,mp_int*,mp_int*);
8444
8445 /* find window size */
8446 x = mp_count_bits (X);
8447 if (x <= 7) {
8448 winsize = 2;
8449 } else if (x <= 36) {
8450 winsize = 3;
8451 } else if (x <= 140) {
8452 winsize = 4;
8453 } else if (x <= 450) {
8454 winsize = 5;
8455 } else if (x <= 1303) {
8456 winsize = 6;
8457 } else if (x <= 3529) {
8458 winsize = 7;
8459 } else {
8460 winsize = 8;
8461 }
8462
8463 #ifdef MP_LOW_MEM
8464 if (winsize > 5) {
8465 winsize = 5;
8466 }
8467 #endif
8468
8469 /* init M array */
8470 /* init first cell */
8471 if ((err = mp_init(&M[1])) != MP_OKAY) {
8472 return err;
8473 }
8474
8475 /* now init the second half of the array */
8476 for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
8477 if ((err = mp_init(&M[x])) != MP_OKAY) {
8478 for (y = 1<<(winsize-1); y < x; y++) {
8479 mp_clear (&M[y]);
8480 }
8481 mp_clear(&M[1]);
8482 return err;
8483 }
8484 }
8485
8486 /* create mu, used for Barrett reduction */
8487 if ((err = mp_init (&mu)) != MP_OKAY) {
8488 goto LBL_M;
8489 }
8490
8491 if (redmode == 0) {
8492 if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
8493 goto LBL_MU;
8494 }
8495 redux = mp_reduce;
8496 } else {
8497 if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
8498 goto LBL_MU;
8499 }
8500 redux = mp_reduce_2k_l;
8501 }
8502
8503 /* create M table
8504 *
8505 * The M table contains powers of the base,
8506 * e.g. M[x] = G**x mod P
8507 *
8508 * The first half of the table is not
8509 * computed though accept for M[0] and M[1]
8510 */
8511 if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
8512 goto LBL_MU;
8513 }
8514
8515 /* compute the value at M[1<<(winsize-1)] by squaring
8516 * M[1] (winsize-1) times
8517 */
8518 if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
8519 goto LBL_MU;
8520 }
8521
8522 for (x = 0; x < (winsize - 1); x++) {
8523 /* square it */
8524 if ((err = mp_sqr (&M[1 << (winsize - 1)],
8525 &M[1 << (winsize - 1)])) != MP_OKAY) {
8526 goto LBL_MU;
8527 }
8528
8529 /* reduce modulo P */
8530 if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
8531 goto LBL_MU;
8532 }
8533 }
8534
8535 /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
8536 * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
8537 */
8538 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
8539 if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
8540 goto LBL_MU;
8541 }
8542 if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
8543 goto LBL_MU;
8544 }
8545 }
8546
8547 /* setup result */
8548 if ((err = mp_init (&res)) != MP_OKAY) {
8549 goto LBL_MU;
8550 }
8551 mp_set (&res, 1);
8552
8553 /* set initial mode and bit cnt */
8554 mode = 0;
8555 bitcnt = 1;
8556 buf = 0;
8557 digidx = X->used - 1;
8558 bitcpy = 0;
8559 bitbuf = 0;
8560
8561 for (;;) {
8562 /* grab next digit as required */
8563 if (--bitcnt == 0) {
8564 /* if digidx == -1 we are out of digits */
8565 if (digidx == -1) {
8566 break;
8567 }
8568 /* read next digit and reset the bitcnt */
8569 buf = X->dp[digidx--];
8570 bitcnt = (int) DIGIT_BIT;
8571 }
8572
8573 /* grab the next msb from the exponent */
8574 y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
8575 buf <<= (mp_digit)1;
8576
8577 /* if the bit is zero and mode == 0 then we ignore it
8578 * These represent the leading zero bits before the first 1 bit
8579 * in the exponent. Technically this opt is not required but it
8580 * does lower the # of trivial squaring/reductions used
8581 */
8582 if (mode == 0 && y == 0) {
8583 continue;
8584 }
8585
8586 /* if the bit is zero and mode == 1 then we square */
8587 if (mode == 1 && y == 0) {
8588 if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
8589 goto LBL_RES;
8590 }
8591 if ((err = redux (&res, P, &mu)) != MP_OKAY) {
8592 goto LBL_RES;
8593 }
8594 continue;
8595 }
8596
8597 /* else we add it to the window */
8598 bitbuf |= (y << (winsize - ++bitcpy));
8599 mode = 2;
8600
8601 if (bitcpy == winsize) {
8602 /* ok window is filled so square as required and multiply */
8603 /* square first */
8604 for (x = 0; x < winsize; x++) {
8605 if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
8606 goto LBL_RES;
8607 }
8608 if ((err = redux (&res, P, &mu)) != MP_OKAY) {
8609 goto LBL_RES;
8610 }
8611 }
8612
8613 /* then multiply */
8614 if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
8615 goto LBL_RES;
8616 }
8617 if ((err = redux (&res, P, &mu)) != MP_OKAY) {
8618 goto LBL_RES;
8619 }
8620
8621 /* empty window and reset */
8622 bitcpy = 0;
8623 bitbuf = 0;
8624 mode = 1;
8625 }
8626 }
8627
8628 /* if bits remain then square/multiply */
8629 if (mode == 2 && bitcpy > 0) {
8630 /* square then multiply if the bit is set */
8631 for (x = 0; x < bitcpy; x++) {
8632 if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
8633 goto LBL_RES;
8634 }
8635 if ((err = redux (&res, P, &mu)) != MP_OKAY) {
8636 goto LBL_RES;
8637 }
8638
8639 bitbuf <<= 1;
8640 if ((bitbuf & (1 << winsize)) != 0) {
8641 /* then multiply */
8642 if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
8643 goto LBL_RES;
8644 }
8645 if ((err = redux (&res, P, &mu)) != MP_OKAY) {
8646 goto LBL_RES;
8647 }
8648 }
8649 }
8650 }
8651
8652 mp_exch (&res, Y);
8653 err = MP_OKAY;
8654 LBL_RES:mp_clear (&res);
8655 LBL_MU:mp_clear (&mu);
8656 LBL_M:
8657 mp_clear(&M[1]);
8658 for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
8659 mp_clear (&M[x]);
8660 }
8661 return err;
8662 }
8663 #endif
8664
8665 /* End: bn_s_mp_exptmod.c */
8666
8667 /* Start: bn_s_mp_mul_digs.c */
8668 #include <tommath.h>
8669 #ifdef BN_S_MP_MUL_DIGS_C
8670 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8671 *
8672 * LibTomMath is a library that provides multiple-precision
8673 * integer arithmetic as well as number theoretic functionality.
8674 *
8675 * The library was designed directly after the MPI library by
8676 * Michael Fromberger but has been written from scratch with
8677 * additional optimizations in place.
8678 *
8679 * The library is free for all purposes without any express
8680 * guarantee it works.
8681 *
8682 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8683 */
8684
8685 /* multiplies |a| * |b| and only computes upto digs digits of result
8686 * HAC pp. 595, Algorithm 14.12 Modified so you can control how
8687 * many digits of output are created.
8688 */
8689 int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
8690 {
8691 mp_int t;
8692 int res, pa, pb, ix, iy;
8693 mp_digit u;
8694 mp_word r;
8695 mp_digit tmpx, *tmpt, *tmpy;
8696
8697 /* can we use the fast multiplier? */
8698 if (((digs) < MP_WARRAY) &&
8699 MIN (a->used, b->used) <
8700 (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
8701 return fast_s_mp_mul_digs (a, b, c, digs);
8702 }
8703
8704 if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
8705 return res;
8706 }
8707 t.used = digs;
8708
8709 /* compute the digits of the product directly */
8710 pa = a->used;
8711 for (ix = 0; ix < pa; ix++) {
8712 /* set the carry to zero */
8713 u = 0;
8714
8715 /* limit ourselves to making digs digits of output */
8716 pb = MIN (b->used, digs - ix);
8717
8718 /* setup some aliases */
8719 /* copy of the digit from a used within the nested loop */
8720 tmpx = a->dp[ix];
8721
8722 /* an alias for the destination shifted ix places */
8723 tmpt = t.dp + ix;
8724
8725 /* an alias for the digits of b */
8726 tmpy = b->dp;
8727
8728 /* compute the columns of the output and propagate the carry */
8729 for (iy = 0; iy < pb; iy++) {
8730 /* compute the column as a mp_word */
8731 r = ((mp_word)*tmpt) +
8732 ((mp_word)tmpx) * ((mp_word)*tmpy++) +
8733 ((mp_word) u);
8734
8735 /* the new column is the lower part of the result */
8736 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
8737
8738 /* get the carry word from the result */
8739 u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
8740 }
8741 /* set carry if it is placed below digs */
8742 if (ix + iy < digs) {
8743 *tmpt = u;
8744 }
8745 }
8746
8747 mp_clamp (&t);
8748 mp_exch (&t, c);
8749
8750 mp_clear (&t);
8751 return MP_OKAY;
8752 }
8753 #endif
8754
8755 /* End: bn_s_mp_mul_digs.c */
8756
8757 /* Start: bn_s_mp_mul_high_digs.c */
8758 #include <tommath.h>
8759 #ifdef BN_S_MP_MUL_HIGH_DIGS_C
8760 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8761 *
8762 * LibTomMath is a library that provides multiple-precision
8763 * integer arithmetic as well as number theoretic functionality.
8764 *
8765 * The library was designed directly after the MPI library by
8766 * Michael Fromberger but has been written from scratch with
8767 * additional optimizations in place.
8768 *
8769 * The library is free for all purposes without any express
8770 * guarantee it works.
8771 *
8772 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8773 */
8774
8775 /* multiplies |a| * |b| and does not compute the lower digs digits
8776 * [meant to get the higher part of the product]
8777 */
8778 int
8779 s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
8780 {
8781 mp_int t;
8782 int res, pa, pb, ix, iy;
8783 mp_digit u;
8784 mp_word r;
8785 mp_digit tmpx, *tmpt, *tmpy;
8786
8787 /* can we use the fast multiplier? */
8788 #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
8789 if (((a->used + b->used + 1) < MP_WARRAY)
8790 && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
8791 return fast_s_mp_mul_high_digs (a, b, c, digs);
8792 }
8793 #endif
8794
8795 if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
8796 return res;
8797 }
8798 t.used = a->used + b->used + 1;
8799
8800 pa = a->used;
8801 pb = b->used;
8802 for (ix = 0; ix < pa; ix++) {
8803 /* clear the carry */
8804 u = 0;
8805
8806 /* left hand side of A[ix] * B[iy] */
8807 tmpx = a->dp[ix];
8808
8809 /* alias to the address of where the digits will be stored */
8810 tmpt = &(t.dp[digs]);
8811
8812 /* alias for where to read the right hand side from */
8813 tmpy = b->dp + (digs - ix);
8814
8815 for (iy = digs - ix; iy < pb; iy++) {
8816 /* calculate the double precision result */
8817 r = ((mp_word)*tmpt) +
8818 ((mp_word)tmpx) * ((mp_word)*tmpy++) +
8819 ((mp_word) u);
8820
8821 /* get the lower part */
8822 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
8823
8824 /* carry the carry */
8825 u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
8826 }
8827 *tmpt = u;
8828 }
8829 mp_clamp (&t);
8830 mp_exch (&t, c);
8831 mp_clear (&t);
8832 return MP_OKAY;
8833 }
8834 #endif
8835
8836 /* End: bn_s_mp_mul_high_digs.c */
8837
8838 /* Start: bn_s_mp_sqr.c */
8839 #include <tommath.h>
8840 #ifdef BN_S_MP_SQR_C
8841 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8842 *
8843 * LibTomMath is a library that provides multiple-precision
8844 * integer arithmetic as well as number theoretic functionality.
8845 *
8846 * The library was designed directly after the MPI library by
8847 * Michael Fromberger but has been written from scratch with
8848 * additional optimizations in place.
8849 *
8850 * The library is free for all purposes without any express
8851 * guarantee it works.
8852 *
8853 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8854 */
8855
8856 /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
8857 int s_mp_sqr (mp_int * a, mp_int * b)
8858 {
8859 mp_int t;
8860 int res, ix, iy, pa;
8861 mp_word r;
8862 mp_digit u, tmpx, *tmpt;
8863
8864 pa = a->used;
8865 if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
8866 return res;
8867 }
8868
8869 /* default used is maximum possible size */
8870 t.used = 2*pa + 1;
8871
8872 for (ix = 0; ix < pa; ix++) {
8873 /* first calculate the digit at 2*ix */
8874 /* calculate double precision result */
8875 r = ((mp_word) t.dp[2*ix]) +
8876 ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
8877
8878 /* store lower part in result */
8879 t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
8880
8881 /* get the carry */
8882 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
8883
8884 /* left hand side of A[ix] * A[iy] */
8885 tmpx = a->dp[ix];
8886
8887 /* alias for where to store the results */
8888 tmpt = t.dp + (2*ix + 1);
8889
8890 for (iy = ix + 1; iy < pa; iy++) {
8891 /* first calculate the product */
8892 r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
8893
8894 /* now calculate the double precision result, note we use
8895 * addition instead of *2 since it's easier to optimize
8896 */
8897 r = ((mp_word) *tmpt) + r + r + ((mp_word) u);
8898
8899 /* store lower part */
8900 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
8901
8902 /* get carry */
8903 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
8904 }
8905 /* propagate upwards */
8906 while (u != ((mp_digit) 0)) {
8907 r = ((mp_word) *tmpt) + ((mp_word) u);
8908 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
8909 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
8910 }
8911 }
8912
8913 mp_clamp (&t);
8914 mp_exch (&t, b);
8915 mp_clear (&t);
8916 return MP_OKAY;
8917 }
8918 #endif
8919
8920 /* End: bn_s_mp_sqr.c */
8921
8922 /* Start: bn_s_mp_sub.c */
8923 #include <tommath.h>
8924 #ifdef BN_S_MP_SUB_C
8925 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8926 *
8927 * LibTomMath is a library that provides multiple-precision
8928 * integer arithmetic as well as number theoretic functionality.
8929 *
8930 * The library was designed directly after the MPI library by
8931 * Michael Fromberger but has been written from scratch with
8932 * additional optimizations in place.
8933 *
8934 * The library is free for all purposes without any express
8935 * guarantee it works.
8936 *
8937 * Tom St Denis, [email protected], http://math.libtomcrypt.org
8938 */
8939
8940 /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
8941 int
8942 s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
8943 {
8944 int olduse, res, min, max;
8945
8946 /* find sizes */
8947 min = b->used;
8948 max = a->used;
8949
8950 /* init result */
8951 if (c->alloc < max) {
8952 if ((res = mp_grow (c, max)) != MP_OKAY) {
8953 return res;
8954 }
8955 }
8956 olduse = c->used;
8957 c->used = max;
8958
8959 {
8960 register mp_digit u, *tmpa, *tmpb, *tmpc;
8961 register int i;
8962
8963 /* alias for digit pointers */
8964 tmpa = a->dp;
8965 tmpb = b->dp;
8966 tmpc = c->dp;
8967
8968 /* set carry to zero */
8969 u = 0;
8970 for (i = 0; i < min; i++) {
8971 /* T[i] = A[i] - B[i] - U */
8972 *tmpc = *tmpa++ - *tmpb++ - u;
8973
8974 /* U = carry bit of T[i]
8975 * Note this saves performing an AND operation since
8976 * if a carry does occur it will propagate all the way to the
8977 * MSB. As a result a single shift is enough to get the carry
8978 */
8979 u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
8980
8981 /* Clear carry from T[i] */
8982 *tmpc++ &= MP_MASK;
8983 }
8984
8985 /* now copy higher words if any, e.g. if A has more digits than B */
8986 for (; i < max; i++) {
8987 /* T[i] = A[i] - U */
8988 *tmpc = *tmpa++ - u;
8989
8990 /* U = carry bit of T[i] */
8991 u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
8992
8993 /* Clear carry from T[i] */
8994 *tmpc++ &= MP_MASK;
8995 }
8996
8997 /* clear digits above used (since we may not have grown result above) */
8998 for (i = c->used; i < olduse; i++) {
8999 *tmpc++ = 0;
9000 }
9001 }
9002
9003 mp_clamp (c);
9004 return MP_OKAY;
9005 }
9006
9007 #endif
9008
9009 /* End: bn_s_mp_sub.c */
9010
9011 /* Start: bncore.c */
9012 #include <tommath.h>
9013 #ifdef BNCORE_C
9014 /* LibTomMath, multiple-precision integer library -- Tom St Denis
9015 *
9016 * LibTomMath is a library that provides multiple-precision
9017 * integer arithmetic as well as number theoretic functionality.
9018 *
9019 * The library was designed directly after the MPI library by
9020 * Michael Fromberger but has been written from scratch with
9021 * additional optimizations in place.
9022 *
9023 * The library is free for all purposes without any express
9024 * guarantee it works.
9025 *
9026 * Tom St Denis, [email protected], http://math.libtomcrypt.org
9027 */
9028
9029 /* Known optimal configurations
9030
9031 CPU /Compiler /MUL CUTOFF/SQR CUTOFF
9032 -------------------------------------------------------------
9033 Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-)
9034 AMD Athlon64 /GCC v3.4.4 / 74/ 124/LTM 0.34
9035
9036 */
9037
9038 int KARATSUBA_MUL_CUTOFF = 74, /* Min. number of digits before Karatsuba multiplication is used. */
9039 KARATSUBA_SQR_CUTOFF = 124, /* Min. number of digits before Karatsuba squaring is used. */
9040
9041 TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */
9042 TOOM_SQR_CUTOFF = 400;
9043 #endif
9044
9045 /* End: bncore.c */
9046
9047
9048 /* EOF */