1 /* Start: bn_error.c */
4 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6 * LibTomMath is a library that provides multiple-precision
7 * integer arithmetic as well as number theoretic functionality.
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.
13 * The library is free for all purposes without any express
16 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
23 { MP_OKAY
, "Successful" },
24 { MP_MEM
, "Out of heap" },
25 { MP_VAL
, "Value out of range" }
28 /* return a char * string for a given code */
29 char *mp_error_to_string(int code
)
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
) {
40 /* generic reply for invalid code */
41 return "Invalid error code";
46 /* $Source: /cvs/libtom/libtommath/bn_error.c,v $ */
47 /* $Revision: 1.3 $ */
48 /* $Date: 2006/03/31 14:18:44 $ */
52 /* Start: bn_fast_mp_invmod.c */
54 #ifdef BN_FAST_MP_INVMOD_C
55 /* LibTomMath, multiple-precision integer library -- Tom St Denis
57 * LibTomMath is a library that provides multiple-precision
58 * integer arithmetic as well as number theoretic functionality.
60 * The library was designed directly after the MPI library by
61 * Michael Fromberger but has been written from scratch with
62 * additional optimizations in place.
64 * The library is free for all purposes without any express
67 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
70 /* computes the modular inverse via binary extended euclidean algorithm,
71 * that is c = 1/a mod b
73 * Based on slow invmod except this is optimized for the case where b is
74 * odd as per HAC Note 14.64 on pp. 610
76 int fast_mp_invmod (mp_int
* a
, mp_int
* b
, mp_int
* c
)
78 mp_int x
, y
, u
, v
, B
, D
;
81 /* 2. [modified] b must be odd */
82 if (mp_iseven (b
) == 1) {
86 /* init all our temps */
87 if ((res
= mp_init_multi(&x
, &y
, &u
, &v
, &B
, &D
, NULL
)) != MP_OKAY
) {
91 /* x == modulus, y == value to invert */
92 if ((res
= mp_copy (b
, &x
)) != MP_OKAY
) {
97 if ((res
= mp_mod (a
, b
, &y
)) != MP_OKAY
) {
101 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
102 if ((res
= mp_copy (&x
, &u
)) != MP_OKAY
) {
105 if ((res
= mp_copy (&y
, &v
)) != MP_OKAY
) {
111 /* 4. while u is even do */
112 while (mp_iseven (&u
) == 1) {
114 if ((res
= mp_div_2 (&u
, &u
)) != MP_OKAY
) {
117 /* 4.2 if B is odd then */
118 if (mp_isodd (&B
) == 1) {
119 if ((res
= mp_sub (&B
, &x
, &B
)) != MP_OKAY
) {
124 if ((res
= mp_div_2 (&B
, &B
)) != MP_OKAY
) {
129 /* 5. while v is even do */
130 while (mp_iseven (&v
) == 1) {
132 if ((res
= mp_div_2 (&v
, &v
)) != MP_OKAY
) {
135 /* 5.2 if D is odd then */
136 if (mp_isodd (&D
) == 1) {
138 if ((res
= mp_sub (&D
, &x
, &D
)) != MP_OKAY
) {
143 if ((res
= mp_div_2 (&D
, &D
)) != MP_OKAY
) {
148 /* 6. if u >= v then */
149 if (mp_cmp (&u
, &v
) != MP_LT
) {
150 /* u = u - v, B = B - D */
151 if ((res
= mp_sub (&u
, &v
, &u
)) != MP_OKAY
) {
155 if ((res
= mp_sub (&B
, &D
, &B
)) != MP_OKAY
) {
159 /* v - v - u, D = D - B */
160 if ((res
= mp_sub (&v
, &u
, &v
)) != MP_OKAY
) {
164 if ((res
= mp_sub (&D
, &B
, &D
)) != MP_OKAY
) {
169 /* if not zero goto step 4 */
170 if (mp_iszero (&u
) == 0) {
174 /* now a = C, b = D, gcd == g*v */
176 /* if v != 1 then there is no inverse */
177 if (mp_cmp_d (&v
, 1) != MP_EQ
) {
182 /* b is now the inverse */
184 while (D
.sign
== MP_NEG
) {
185 if ((res
= mp_add (&D
, b
, &D
)) != MP_OKAY
) {
193 LBL_ERR
:mp_clear_multi (&x
, &y
, &u
, &v
, &B
, &D
, NULL
);
198 /* $Source: /cvs/libtom/libtommath/bn_fast_mp_invmod.c,v $ */
199 /* $Revision: 1.3 $ */
200 /* $Date: 2006/03/31 14:18:44 $ */
202 /* End: bn_fast_mp_invmod.c */
204 /* Start: bn_fast_mp_montgomery_reduce.c */
206 #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
207 /* LibTomMath, multiple-precision integer library -- Tom St Denis
209 * LibTomMath is a library that provides multiple-precision
210 * integer arithmetic as well as number theoretic functionality.
212 * The library was designed directly after the MPI library by
213 * Michael Fromberger but has been written from scratch with
214 * additional optimizations in place.
216 * The library is free for all purposes without any express
217 * guarantee it works.
219 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
222 /* computes xR**-1 == x (mod N) via Montgomery Reduction
224 * This is an optimized implementation of montgomery_reduce
225 * which uses the comba method to quickly calculate the columns of the
228 * Based on Algorithm 14.32 on pp.601 of HAC.
230 int fast_mp_montgomery_reduce (mp_int
* x
, mp_int
* n
, mp_digit rho
)
233 mp_word W
[MP_WARRAY
];
235 /* get old used count */
238 /* grow a as required */
239 if (x
->alloc
< n
->used
+ 1) {
240 if ((res
= mp_grow (x
, n
->used
+ 1)) != MP_OKAY
) {
245 /* first we have to get the digits of the input into
246 * an array of double precision words W[...]
249 register mp_word
*_W
;
250 register mp_digit
*tmpx
;
252 /* alias for the W[] array */
255 /* alias for the digits of x*/
258 /* copy the digits of a into W[0..a->used-1] */
259 for (ix
= 0; ix
< x
->used
; ix
++) {
263 /* zero the high words of W[a->used..m->used*2] */
264 for (; ix
< n
->used
* 2 + 1; ix
++) {
269 /* now we proceed to zero successive digits
270 * from the least significant upwards
272 for (ix
= 0; ix
< n
->used
; ix
++) {
273 /* mu = ai * m' mod b
275 * We avoid a double precision multiplication (which isn't required)
276 * by casting the value down to a mp_digit. Note this requires
277 * that W[ix-1] have the carry cleared (see after the inner loop)
279 register mp_digit mu
;
280 mu
= (mp_digit
) (((W
[ix
] & MP_MASK
) * rho
) & MP_MASK
);
282 /* a = a + mu * m * b**i
284 * This is computed in place and on the fly. The multiplication
285 * by b**i is handled by offseting which columns the results
288 * Note the comba method normally doesn't handle carries in the
289 * inner loop In this case we fix the carry from the previous
290 * column since the Montgomery reduction requires digits of the
291 * result (so far) [see above] to work. This is
292 * handled by fixing up one carry after the inner loop. The
293 * carry fixups are done in order so after these loops the
294 * first m->used words of W[] have the carries fixed
298 register mp_digit
*tmpn
;
299 register mp_word
*_W
;
301 /* alias for the digits of the modulus */
304 /* Alias for the columns set by an offset of ix */
308 for (iy
= 0; iy
< n
->used
; iy
++) {
309 *_W
++ += ((mp_word
)mu
) * ((mp_word
)*tmpn
++);
313 /* now fix carry for next digit, W[ix+1] */
314 W
[ix
+ 1] += W
[ix
] >> ((mp_word
) DIGIT_BIT
);
317 /* now we have to propagate the carries and
318 * shift the words downward [all those least
319 * significant digits we zeroed].
322 register mp_digit
*tmpx
;
323 register mp_word
*_W
, *_W1
;
325 /* nox fix rest of carries */
327 /* alias for current word */
330 /* alias for next word, where the carry goes */
333 for (; ix
<= n
->used
* 2 + 1; ix
++) {
334 *_W
++ += *_W1
++ >> ((mp_word
) DIGIT_BIT
);
337 /* copy out, A = A/b**n
339 * The result is A/b**n but instead of converting from an
340 * array of mp_word to mp_digit than calling mp_rshd
341 * we just copy them in the right order
344 /* alias for destination word */
347 /* alias for shifted double precision result */
350 for (ix
= 0; ix
< n
->used
+ 1; ix
++) {
351 *tmpx
++ = (mp_digit
)(*_W
++ & ((mp_word
) MP_MASK
));
354 /* zero oldused digits, if the input a was larger than
355 * m->used+1 we'll have to clear the digits
357 for (; ix
< olduse
; ix
++) {
362 /* set the max used and clamp */
363 x
->used
= n
->used
+ 1;
366 /* if A >= m then A = A - m */
367 if (mp_cmp_mag (x
, n
) != MP_LT
) {
368 return s_mp_sub (x
, n
, x
);
374 /* $Source: /cvs/libtom/libtommath/bn_fast_mp_montgomery_reduce.c,v $ */
375 /* $Revision: 1.3 $ */
376 /* $Date: 2006/03/31 14:18:44 $ */
378 /* End: bn_fast_mp_montgomery_reduce.c */
380 /* Start: bn_fast_s_mp_mul_digs.c */
382 #ifdef BN_FAST_S_MP_MUL_DIGS_C
383 /* LibTomMath, multiple-precision integer library -- Tom St Denis
385 * LibTomMath is a library that provides multiple-precision
386 * integer arithmetic as well as number theoretic functionality.
388 * The library was designed directly after the MPI library by
389 * Michael Fromberger but has been written from scratch with
390 * additional optimizations in place.
392 * The library is free for all purposes without any express
393 * guarantee it works.
395 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
398 /* Fast (comba) multiplier
400 * This is the fast column-array [comba] multiplier. It is
401 * designed to compute the columns of the product first
402 * then handle the carries afterwards. This has the effect
403 * of making the nested loops that compute the columns very
404 * simple and schedulable on super-scalar processors.
406 * This has been modified to produce a variable number of
407 * digits of output so if say only a half-product is required
408 * you don't have to compute the upper half (a feature
409 * required for fast Barrett reduction).
411 * Based on Algorithm 14.12 on pp.595 of HAC.
414 int fast_s_mp_mul_digs (mp_int
* a
, mp_int
* b
, mp_int
* c
, int digs
)
416 int olduse
, res
, pa
, ix
, iz
;
417 mp_digit W
[MP_WARRAY
];
420 /* grow the destination as required */
421 if (c
->alloc
< digs
) {
422 if ((res
= mp_grow (c
, digs
)) != MP_OKAY
) {
427 /* number of output digits to produce */
428 pa
= MIN(digs
, a
->used
+ b
->used
);
430 /* clear the carry */
432 for (ix
= 0; ix
< pa
; ix
++) {
435 mp_digit
*tmpx
, *tmpy
;
437 /* get offsets into the two bignums */
438 ty
= MIN(b
->used
-1, ix
);
441 /* setup temp aliases */
445 /* this is the number of times the loop will iterrate, essentially
446 while (tx++ < a->used && ty-- >= 0) { ... }
448 iy
= MIN(a
->used
-tx
, ty
+1);
451 for (iz
= 0; iz
< iy
; ++iz
) {
452 _W
+= ((mp_word
)*tmpx
++)*((mp_word
)*tmpy
--);
457 W
[ix
] = ((mp_digit
)_W
) & MP_MASK
;
459 /* make next carry */
460 _W
= _W
>> ((mp_word
)DIGIT_BIT
);
468 register mp_digit
*tmpc
;
470 for (ix
= 0; ix
< pa
+1; ix
++) {
471 /* now extract the previous digit [below the carry] */
475 /* clear unused digits [that existed in the old copy of c] */
476 for (; ix
< olduse
; ix
++) {
485 /* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_digs.c,v $ */
486 /* $Revision: 1.7 $ */
487 /* $Date: 2006/03/31 14:18:44 $ */
489 /* End: bn_fast_s_mp_mul_digs.c */
491 /* Start: bn_fast_s_mp_mul_high_digs.c */
493 #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
494 /* LibTomMath, multiple-precision integer library -- Tom St Denis
496 * LibTomMath is a library that provides multiple-precision
497 * integer arithmetic as well as number theoretic functionality.
499 * The library was designed directly after the MPI library by
500 * Michael Fromberger but has been written from scratch with
501 * additional optimizations in place.
503 * The library is free for all purposes without any express
504 * guarantee it works.
506 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
509 /* this is a modified version of fast_s_mul_digs that only produces
510 * output digits *above* digs. See the comments for fast_s_mul_digs
511 * to see how it works.
513 * This is used in the Barrett reduction since for one of the multiplications
514 * only the higher digits were needed. This essentially halves the work.
516 * Based on Algorithm 14.12 on pp.595 of HAC.
518 int fast_s_mp_mul_high_digs (mp_int
* a
, mp_int
* b
, mp_int
* c
, int digs
)
520 int olduse
, res
, pa
, ix
, iz
;
521 mp_digit W
[MP_WARRAY
];
524 /* grow the destination as required */
525 pa
= a
->used
+ b
->used
;
527 if ((res
= mp_grow (c
, pa
)) != MP_OKAY
) {
532 /* number of output digits to produce */
533 pa
= a
->used
+ b
->used
;
535 for (ix
= digs
; ix
< pa
; ix
++) {
537 mp_digit
*tmpx
, *tmpy
;
539 /* get offsets into the two bignums */
540 ty
= MIN(b
->used
-1, ix
);
543 /* setup temp aliases */
547 /* this is the number of times the loop will iterrate, essentially its
548 while (tx++ < a->used && ty-- >= 0) { ... }
550 iy
= MIN(a
->used
-tx
, ty
+1);
553 for (iz
= 0; iz
< iy
; iz
++) {
554 _W
+= ((mp_word
)*tmpx
++)*((mp_word
)*tmpy
--);
558 W
[ix
] = ((mp_digit
)_W
) & MP_MASK
;
560 /* make next carry */
561 _W
= _W
>> ((mp_word
)DIGIT_BIT
);
569 register mp_digit
*tmpc
;
572 for (ix
= digs
; ix
< pa
; ix
++) {
573 /* now extract the previous digit [below the carry] */
577 /* clear unused digits [that existed in the old copy of c] */
578 for (; ix
< olduse
; ix
++) {
587 /* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_high_digs.c,v $ */
588 /* $Revision: 1.5 $ */
589 /* $Date: 2006/11/14 03:46:25 $ */
591 /* End: bn_fast_s_mp_mul_high_digs.c */
593 /* Start: bn_fast_s_mp_sqr.c */
595 #ifdef BN_FAST_S_MP_SQR_C
596 /* LibTomMath, multiple-precision integer library -- Tom St Denis
598 * LibTomMath is a library that provides multiple-precision
599 * integer arithmetic as well as number theoretic functionality.
601 * The library was designed directly after the MPI library by
602 * Michael Fromberger but has been written from scratch with
603 * additional optimizations in place.
605 * The library is free for all purposes without any express
606 * guarantee it works.
608 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
611 /* the jist of squaring...
612 * you do like mult except the offset of the tmpx [one that
613 * starts closer to zero] can't equal the offset of tmpy.
614 * So basically you set up iy like before then you min it with
615 * (ty-tx) so that it never happens. You double all those
616 * you add in the inner loop
618 After that loop you do the squares and add them in.
621 int fast_s_mp_sqr (mp_int
* a
, mp_int
* b
)
623 int olduse
, res
, pa
, ix
, iz
;
624 mp_digit W
[MP_WARRAY
], *tmpx
;
627 /* grow the destination as required */
628 pa
= a
->used
+ a
->used
;
630 if ((res
= mp_grow (b
, pa
)) != MP_OKAY
) {
635 /* number of output digits to produce */
637 for (ix
= 0; ix
< pa
; ix
++) {
645 /* get offsets into the two bignums */
646 ty
= MIN(a
->used
-1, ix
);
649 /* setup temp aliases */
653 /* this is the number of times the loop will iterrate, essentially
654 while (tx++ < a->used && ty-- >= 0) { ... }
656 iy
= MIN(a
->used
-tx
, ty
+1);
658 /* now for squaring tx can never equal ty
659 * we halve the distance since they approach at a rate of 2x
660 * and we have to round because odd cases need to be executed
662 iy
= MIN(iy
, (ty
-tx
+1)>>1);
665 for (iz
= 0; iz
< iy
; iz
++) {
666 _W
+= ((mp_word
)*tmpx
++)*((mp_word
)*tmpy
--);
669 /* double the inner product and add carry */
672 /* even columns have the square term in them */
674 _W
+= ((mp_word
)a
->dp
[ix
>>1])*((mp_word
)a
->dp
[ix
>>1]);
678 W
[ix
] = (mp_digit
)(_W
& MP_MASK
);
680 /* make next carry */
681 W1
= _W
>> ((mp_word
)DIGIT_BIT
);
686 b
->used
= a
->used
+a
->used
;
691 for (ix
= 0; ix
< pa
; ix
++) {
692 *tmpb
++ = W
[ix
] & MP_MASK
;
695 /* clear unused digits [that existed in the old copy of c] */
696 for (; ix
< olduse
; ix
++) {
705 /* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_sqr.c,v $ */
706 /* $Revision: 1.3 $ */
707 /* $Date: 2006/03/31 14:18:44 $ */
709 /* End: bn_fast_s_mp_sqr.c */
711 /* Start: bn_mp_2expt.c */
714 /* LibTomMath, multiple-precision integer library -- Tom St Denis
716 * LibTomMath is a library that provides multiple-precision
717 * integer arithmetic as well as number theoretic functionality.
719 * The library was designed directly after the MPI library by
720 * Michael Fromberger but has been written from scratch with
721 * additional optimizations in place.
723 * The library is free for all purposes without any express
724 * guarantee it works.
726 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
731 * Simple algorithm which zeroes the int, grows it then just sets one bit
735 mp_2expt (mp_int
* a
, int b
)
739 /* zero a as per default */
742 /* grow a to accomodate the single bit */
743 if ((res
= mp_grow (a
, b
/ DIGIT_BIT
+ 1)) != MP_OKAY
) {
747 /* set the used count of where the bit will go */
748 a
->used
= b
/ DIGIT_BIT
+ 1;
750 /* put the single bit in its place */
751 a
->dp
[b
/ DIGIT_BIT
] = ((mp_digit
)1) << (b
% DIGIT_BIT
);
757 /* $Source: /cvs/libtom/libtommath/bn_mp_2expt.c,v $ */
758 /* $Revision: 1.3 $ */
759 /* $Date: 2006/03/31 14:18:44 $ */
761 /* End: bn_mp_2expt.c */
763 /* Start: bn_mp_abs.c */
766 /* LibTomMath, multiple-precision integer library -- Tom St Denis
768 * LibTomMath is a library that provides multiple-precision
769 * integer arithmetic as well as number theoretic functionality.
771 * The library was designed directly after the MPI library by
772 * Michael Fromberger but has been written from scratch with
773 * additional optimizations in place.
775 * The library is free for all purposes without any express
776 * guarantee it works.
778 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
783 * Simple function copies the input and fixes the sign to positive
786 mp_abs (mp_int
* a
, mp_int
* b
)
792 if ((res
= mp_copy (a
, b
)) != MP_OKAY
) {
797 /* force the sign of b to positive */
804 /* $Source: /cvs/libtom/libtommath/bn_mp_abs.c,v $ */
805 /* $Revision: 1.3 $ */
806 /* $Date: 2006/03/31 14:18:44 $ */
808 /* End: bn_mp_abs.c */
810 /* Start: bn_mp_add.c */
813 /* LibTomMath, multiple-precision integer library -- Tom St Denis
815 * LibTomMath is a library that provides multiple-precision
816 * integer arithmetic as well as number theoretic functionality.
818 * The library was designed directly after the MPI library by
819 * Michael Fromberger but has been written from scratch with
820 * additional optimizations in place.
822 * The library is free for all purposes without any express
823 * guarantee it works.
825 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
828 /* high level addition (handles signs) */
829 int mp_add (mp_int
* a
, mp_int
* b
, mp_int
* c
)
833 /* get sign of both inputs */
837 /* handle two cases, not four */
839 /* both positive or both negative */
840 /* add their magnitudes, copy the sign */
842 res
= s_mp_add (a
, b
, c
);
844 /* one positive, the other negative */
845 /* subtract the one with the greater magnitude from */
846 /* the one of the lesser magnitude. The result gets */
847 /* the sign of the one with the greater magnitude. */
848 if (mp_cmp_mag (a
, b
) == MP_LT
) {
850 res
= s_mp_sub (b
, a
, c
);
853 res
= s_mp_sub (a
, b
, c
);
861 /* $Source: /cvs/libtom/libtommath/bn_mp_add.c,v $ */
862 /* $Revision: 1.3 $ */
863 /* $Date: 2006/03/31 14:18:44 $ */
865 /* End: bn_mp_add.c */
867 /* Start: bn_mp_add_d.c */
870 /* LibTomMath, multiple-precision integer library -- Tom St Denis
872 * LibTomMath is a library that provides multiple-precision
873 * integer arithmetic as well as number theoretic functionality.
875 * The library was designed directly after the MPI library by
876 * Michael Fromberger but has been written from scratch with
877 * additional optimizations in place.
879 * The library is free for all purposes without any express
880 * guarantee it works.
882 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
885 /* single digit addition */
887 mp_add_d (mp_int
* a
, mp_digit b
, mp_int
* c
)
889 int res
, ix
, oldused
;
890 mp_digit
*tmpa
, *tmpc
, mu
;
892 /* grow c as required */
893 if (c
->alloc
< a
->used
+ 1) {
894 if ((res
= mp_grow(c
, a
->used
+ 1)) != MP_OKAY
) {
899 /* if a is negative and |a| >= b, call c = |a| - b */
900 if (a
->sign
== MP_NEG
&& (a
->used
> 1 || a
->dp
[0] >= b
)) {
901 /* temporarily fix sign of a */
905 res
= mp_sub_d(a
, b
, c
);
908 a
->sign
= c
->sign
= MP_NEG
;
916 /* old number of used digits in c */
919 /* sign always positive */
925 /* destination alias */
928 /* if a is positive */
929 if (a
->sign
== MP_ZPOS
) {
930 /* add digit, after this we're propagating
934 mu
= *tmpc
>> DIGIT_BIT
;
937 /* now handle rest of the digits */
938 for (ix
= 1; ix
< a
->used
; ix
++) {
939 *tmpc
= *tmpa
++ + mu
;
940 mu
= *tmpc
>> DIGIT_BIT
;
943 /* set final carry */
948 c
->used
= a
->used
+ 1;
950 /* a was negative and |a| < b */
953 /* the result is a single digit */
955 *tmpc
++ = b
- a
->dp
[0];
960 /* setup count so the clearing of oldused
961 * can fall through correctly
966 /* now zero to oldused */
967 while (ix
++ < oldused
) {
977 /* $Source: /cvs/libtom/libtommath/bn_mp_add_d.c,v $ */
978 /* $Revision: 1.4 $ */
979 /* $Date: 2006/03/31 14:18:44 $ */
981 /* End: bn_mp_add_d.c */
983 /* Start: bn_mp_addmod.c */
985 #ifdef BN_MP_ADDMOD_C
986 /* LibTomMath, multiple-precision integer library -- Tom St Denis
988 * LibTomMath is a library that provides multiple-precision
989 * integer arithmetic as well as number theoretic functionality.
991 * The library was designed directly after the MPI library by
992 * Michael Fromberger but has been written from scratch with
993 * additional optimizations in place.
995 * The library is free for all purposes without any express
996 * guarantee it works.
998 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1001 /* d = a + b (mod c) */
1003 mp_addmod (mp_int
* a
, mp_int
* b
, mp_int
* c
, mp_int
* d
)
1008 if ((res
= mp_init (&t
)) != MP_OKAY
) {
1012 if ((res
= mp_add (a
, b
, &t
)) != MP_OKAY
) {
1016 res
= mp_mod (&t
, c
, d
);
1022 /* $Source: /cvs/libtom/libtommath/bn_mp_addmod.c,v $ */
1023 /* $Revision: 1.3 $ */
1024 /* $Date: 2006/03/31 14:18:44 $ */
1026 /* End: bn_mp_addmod.c */
1028 /* Start: bn_mp_and.c */
1029 #include <tommath.h>
1031 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1033 * LibTomMath is a library that provides multiple-precision
1034 * integer arithmetic as well as number theoretic functionality.
1036 * The library was designed directly after the MPI library by
1037 * Michael Fromberger but has been written from scratch with
1038 * additional optimizations in place.
1040 * The library is free for all purposes without any express
1041 * guarantee it works.
1043 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1046 /* AND two ints together */
1048 mp_and (mp_int
* a
, mp_int
* b
, mp_int
* c
)
1053 if (a
->used
> b
->used
) {
1054 if ((res
= mp_init_copy (&t
, a
)) != MP_OKAY
) {
1060 if ((res
= mp_init_copy (&t
, b
)) != MP_OKAY
) {
1067 for (ix
= 0; ix
< px
; ix
++) {
1068 t
.dp
[ix
] &= x
->dp
[ix
];
1071 /* zero digits above the last from the smallest mp_int */
1072 for (; ix
< t
.used
; ix
++) {
1083 /* $Source: /cvs/libtom/libtommath/bn_mp_and.c,v $ */
1084 /* $Revision: 1.3 $ */
1085 /* $Date: 2006/03/31 14:18:44 $ */
1087 /* End: bn_mp_and.c */
1089 /* Start: bn_mp_clamp.c */
1090 #include <tommath.h>
1091 #ifdef BN_MP_CLAMP_C
1092 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1094 * LibTomMath is a library that provides multiple-precision
1095 * integer arithmetic as well as number theoretic functionality.
1097 * The library was designed directly after the MPI library by
1098 * Michael Fromberger but has been written from scratch with
1099 * additional optimizations in place.
1101 * The library is free for all purposes without any express
1102 * guarantee it works.
1104 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1107 /* trim unused digits
1109 * This is used to ensure that leading zero digits are
1110 * trimed and the leading "used" digit will be non-zero
1111 * Typically very fast. Also fixes the sign if there
1112 * are no more leading digits
1115 mp_clamp (mp_int
* a
)
1117 /* decrease used while the most significant digit is
1120 while (a
->used
> 0 && a
->dp
[a
->used
- 1] == 0) {
1124 /* reset the sign flag if used == 0 */
1131 /* $Source: /cvs/libtom/libtommath/bn_mp_clamp.c,v $ */
1132 /* $Revision: 1.3 $ */
1133 /* $Date: 2006/03/31 14:18:44 $ */
1135 /* End: bn_mp_clamp.c */
1137 /* Start: bn_mp_clear.c */
1138 #include <tommath.h>
1139 #ifdef BN_MP_CLEAR_C
1140 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1142 * LibTomMath is a library that provides multiple-precision
1143 * integer arithmetic as well as number theoretic functionality.
1145 * The library was designed directly after the MPI library by
1146 * Michael Fromberger but has been written from scratch with
1147 * additional optimizations in place.
1149 * The library is free for all purposes without any express
1150 * guarantee it works.
1152 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1155 /* clear one (frees) */
1157 mp_clear (mp_int
* a
)
1161 /* only do anything if a hasn't been freed previously */
1162 if (a
->dp
!= NULL
) {
1163 /* first zero the digits */
1164 for (i
= 0; i
< a
->used
; i
++) {
1171 /* reset members to make debugging easier */
1173 a
->alloc
= a
->used
= 0;
1179 /* $Source: /cvs/libtom/libtommath/bn_mp_clear.c,v $ */
1180 /* $Revision: 1.3 $ */
1181 /* $Date: 2006/03/31 14:18:44 $ */
1183 /* End: bn_mp_clear.c */
1185 /* Start: bn_mp_clear_multi.c */
1186 #include <tommath.h>
1187 #ifdef BN_MP_CLEAR_MULTI_C
1188 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1190 * LibTomMath is a library that provides multiple-precision
1191 * integer arithmetic as well as number theoretic functionality.
1193 * The library was designed directly after the MPI library by
1194 * Michael Fromberger but has been written from scratch with
1195 * additional optimizations in place.
1197 * The library is free for all purposes without any express
1198 * guarantee it works.
1200 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1204 void mp_clear_multi(mp_int
*mp
, ...)
1206 mp_int
* next_mp
= mp
;
1209 while (next_mp
!= NULL
) {
1211 next_mp
= va_arg(args
, mp_int
*);
1217 /* $Source: /cvs/libtom/libtommath/bn_mp_clear_multi.c,v $ */
1218 /* $Revision: 1.3 $ */
1219 /* $Date: 2006/03/31 14:18:44 $ */
1221 /* End: bn_mp_clear_multi.c */
1223 /* Start: bn_mp_cmp.c */
1224 #include <tommath.h>
1226 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1228 * LibTomMath is a library that provides multiple-precision
1229 * integer arithmetic as well as number theoretic functionality.
1231 * The library was designed directly after the MPI library by
1232 * Michael Fromberger but has been written from scratch with
1233 * additional optimizations in place.
1235 * The library is free for all purposes without any express
1236 * guarantee it works.
1238 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1241 /* compare two ints (signed)*/
1243 mp_cmp (mp_int
* a
, mp_int
* b
)
1245 /* compare based on sign */
1246 if (a
->sign
!= b
->sign
) {
1247 if (a
->sign
== MP_NEG
) {
1254 /* compare digits */
1255 if (a
->sign
== MP_NEG
) {
1256 /* if negative compare opposite direction */
1257 return mp_cmp_mag(b
, a
);
1259 return mp_cmp_mag(a
, b
);
1264 /* $Source: /cvs/libtom/libtommath/bn_mp_cmp.c,v $ */
1265 /* $Revision: 1.3 $ */
1266 /* $Date: 2006/03/31 14:18:44 $ */
1268 /* End: bn_mp_cmp.c */
1270 /* Start: bn_mp_cmp_d.c */
1271 #include <tommath.h>
1272 #ifdef BN_MP_CMP_D_C
1273 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1275 * LibTomMath is a library that provides multiple-precision
1276 * integer arithmetic as well as number theoretic functionality.
1278 * The library was designed directly after the MPI library by
1279 * Michael Fromberger but has been written from scratch with
1280 * additional optimizations in place.
1282 * The library is free for all purposes without any express
1283 * guarantee it works.
1285 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1288 /* compare a digit */
1289 int mp_cmp_d(mp_int
* a
, mp_digit b
)
1291 /* compare based on sign */
1292 if (a
->sign
== MP_NEG
) {
1296 /* compare based on magnitude */
1301 /* compare the only digit of a to b */
1304 } else if (a
->dp
[0] < b
) {
1312 /* $Source: /cvs/libtom/libtommath/bn_mp_cmp_d.c,v $ */
1313 /* $Revision: 1.3 $ */
1314 /* $Date: 2006/03/31 14:18:44 $ */
1316 /* End: bn_mp_cmp_d.c */
1318 /* Start: bn_mp_cmp_mag.c */
1319 #include <tommath.h>
1320 #ifdef BN_MP_CMP_MAG_C
1321 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1323 * LibTomMath is a library that provides multiple-precision
1324 * integer arithmetic as well as number theoretic functionality.
1326 * The library was designed directly after the MPI library by
1327 * Michael Fromberger but has been written from scratch with
1328 * additional optimizations in place.
1330 * The library is free for all purposes without any express
1331 * guarantee it works.
1333 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1336 /* compare maginitude of two ints (unsigned) */
1337 int mp_cmp_mag (mp_int
* a
, mp_int
* b
)
1340 mp_digit
*tmpa
, *tmpb
;
1342 /* compare based on # of non-zero digits */
1343 if (a
->used
> b
->used
) {
1347 if (a
->used
< b
->used
) {
1352 tmpa
= a
->dp
+ (a
->used
- 1);
1355 tmpb
= b
->dp
+ (a
->used
- 1);
1357 /* compare based on digits */
1358 for (n
= 0; n
< a
->used
; ++n
, --tmpa
, --tmpb
) {
1359 if (*tmpa
> *tmpb
) {
1363 if (*tmpa
< *tmpb
) {
1371 /* $Source: /cvs/libtom/libtommath/bn_mp_cmp_mag.c,v $ */
1372 /* $Revision: 1.3 $ */
1373 /* $Date: 2006/03/31 14:18:44 $ */
1375 /* End: bn_mp_cmp_mag.c */
1377 /* Start: bn_mp_cnt_lsb.c */
1378 #include <tommath.h>
1379 #ifdef BN_MP_CNT_LSB_C
1380 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1382 * LibTomMath is a library that provides multiple-precision
1383 * integer arithmetic as well as number theoretic functionality.
1385 * The library was designed directly after the MPI library by
1386 * Michael Fromberger but has been written from scratch with
1387 * additional optimizations in place.
1389 * The library is free for all purposes without any express
1390 * guarantee it works.
1392 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1395 static const int lnz
[16] = {
1396 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
1399 /* Counts the number of lsbs which are zero before the first zero bit */
1400 int mp_cnt_lsb(mp_int
*a
)
1406 if (mp_iszero(a
) == 1) {
1410 /* scan lower digits until non-zero */
1411 for (x
= 0; x
< a
->used
&& a
->dp
[x
] == 0; x
++);
1415 /* now scan this digit until a 1 is found */
1428 /* $Source: /cvs/libtom/libtommath/bn_mp_cnt_lsb.c,v $ */
1429 /* $Revision: 1.3 $ */
1430 /* $Date: 2006/03/31 14:18:44 $ */
1432 /* End: bn_mp_cnt_lsb.c */
1434 /* Start: bn_mp_copy.c */
1435 #include <tommath.h>
1437 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1439 * LibTomMath is a library that provides multiple-precision
1440 * integer arithmetic as well as number theoretic functionality.
1442 * The library was designed directly after the MPI library by
1443 * Michael Fromberger but has been written from scratch with
1444 * additional optimizations in place.
1446 * The library is free for all purposes without any express
1447 * guarantee it works.
1449 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1454 mp_copy (mp_int
* a
, mp_int
* b
)
1458 /* if dst == src do nothing */
1464 if (b
->alloc
< a
->used
) {
1465 if ((res
= mp_grow (b
, a
->used
)) != MP_OKAY
) {
1470 /* zero b and copy the parameters over */
1472 register mp_digit
*tmpa
, *tmpb
;
1474 /* pointer aliases */
1482 /* copy all the digits */
1483 for (n
= 0; n
< a
->used
; n
++) {
1487 /* clear high digits */
1488 for (; n
< b
->used
; n
++) {
1493 /* copy used count and sign */
1500 /* $Source: /cvs/libtom/libtommath/bn_mp_copy.c,v $ */
1501 /* $Revision: 1.3 $ */
1502 /* $Date: 2006/03/31 14:18:44 $ */
1504 /* End: bn_mp_copy.c */
1506 /* Start: bn_mp_count_bits.c */
1507 #include <tommath.h>
1508 #ifdef BN_MP_COUNT_BITS_C
1509 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1511 * LibTomMath is a library that provides multiple-precision
1512 * integer arithmetic as well as number theoretic functionality.
1514 * The library was designed directly after the MPI library by
1515 * Michael Fromberger but has been written from scratch with
1516 * additional optimizations in place.
1518 * The library is free for all purposes without any express
1519 * guarantee it works.
1521 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1524 /* returns the number of bits in an int */
1526 mp_count_bits (mp_int
* a
)
1536 /* get number of digits and add that */
1537 r
= (a
->used
- 1) * DIGIT_BIT
;
1539 /* take the last digit and count the bits in it */
1540 q
= a
->dp
[a
->used
- 1];
1541 while (q
> ((mp_digit
) 0)) {
1543 q
>>= ((mp_digit
) 1);
1549 /* $Source: /cvs/libtom/libtommath/bn_mp_count_bits.c,v $ */
1550 /* $Revision: 1.3 $ */
1551 /* $Date: 2006/03/31 14:18:44 $ */
1553 /* End: bn_mp_count_bits.c */
1555 /* Start: bn_mp_div.c */
1556 #include <tommath.h>
1558 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1560 * LibTomMath is a library that provides multiple-precision
1561 * integer arithmetic as well as number theoretic functionality.
1563 * The library was designed directly after the MPI library by
1564 * Michael Fromberger but has been written from scratch with
1565 * additional optimizations in place.
1567 * The library is free for all purposes without any express
1568 * guarantee it works.
1570 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1573 #ifdef BN_MP_DIV_SMALL
1575 /* slower bit-bang division... also smaller */
1576 int mp_div(mp_int
* a
, mp_int
* b
, mp_int
* c
, mp_int
* d
)
1578 mp_int ta
, tb
, tq
, q
;
1581 /* is divisor zero ? */
1582 if (mp_iszero (b
) == 1) {
1586 /* if a < b then q=0, r = a */
1587 if (mp_cmp_mag (a
, b
) == MP_LT
) {
1589 res
= mp_copy (a
, d
);
1599 /* init our temps */
1600 if ((res
= mp_init_multi(&ta
, &tb
, &tq
, &q
, NULL
) != MP_OKAY
)) {
1606 n
= mp_count_bits(a
) - mp_count_bits(b
);
1607 if (((res
= mp_abs(a
, &ta
)) != MP_OKAY
) ||
1608 ((res
= mp_abs(b
, &tb
)) != MP_OKAY
) ||
1609 ((res
= mp_mul_2d(&tb
, n
, &tb
)) != MP_OKAY
) ||
1610 ((res
= mp_mul_2d(&tq
, n
, &tq
)) != MP_OKAY
)) {
1615 if (mp_cmp(&tb
, &ta
) != MP_GT
) {
1616 if (((res
= mp_sub(&ta
, &tb
, &ta
)) != MP_OKAY
) ||
1617 ((res
= mp_add(&q
, &tq
, &q
)) != MP_OKAY
)) {
1621 if (((res
= mp_div_2d(&tb
, 1, &tb
, NULL
)) != MP_OKAY
) ||
1622 ((res
= mp_div_2d(&tq
, 1, &tq
, NULL
)) != MP_OKAY
)) {
1627 /* now q == quotient and ta == remainder */
1629 n2
= (a
->sign
== b
->sign
? MP_ZPOS
: MP_NEG
);
1632 c
->sign
= (mp_iszero(c
) == MP_YES
) ? MP_ZPOS
: n2
;
1636 d
->sign
= (mp_iszero(d
) == MP_YES
) ? MP_ZPOS
: n
;
1639 mp_clear_multi(&ta
, &tb
, &tq
, &q
, NULL
);
1645 /* integer signed division.
1646 * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
1647 * HAC pp.598 Algorithm 14.20
1649 * Note that the description in HAC is horribly
1650 * incomplete. For example, it doesn't consider
1651 * the case where digits are removed from 'x' in
1652 * the inner loop. It also doesn't consider the
1653 * case that y has fewer than three digits, etc..
1655 * The overall algorithm is as described as
1656 * 14.20 from HAC but fixed to treat these cases.
1658 int mp_div (mp_int
* a
, mp_int
* b
, mp_int
* c
, mp_int
* d
)
1660 mp_int q
, x
, y
, t1
, t2
;
1661 int res
, n
, t
, i
, norm
, neg
;
1663 /* is divisor zero ? */
1664 if (mp_iszero (b
) == 1) {
1668 /* if a < b then q=0, r = a */
1669 if (mp_cmp_mag (a
, b
) == MP_LT
) {
1671 res
= mp_copy (a
, d
);
1681 if ((res
= mp_init_size (&q
, a
->used
+ 2)) != MP_OKAY
) {
1684 q
.used
= a
->used
+ 2;
1686 if ((res
= mp_init (&t1
)) != MP_OKAY
) {
1690 if ((res
= mp_init (&t2
)) != MP_OKAY
) {
1694 if ((res
= mp_init_copy (&x
, a
)) != MP_OKAY
) {
1698 if ((res
= mp_init_copy (&y
, b
)) != MP_OKAY
) {
1703 neg
= (a
->sign
== b
->sign
) ? MP_ZPOS
: MP_NEG
;
1704 x
.sign
= y
.sign
= MP_ZPOS
;
1706 /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
1707 norm
= mp_count_bits(&y
) % DIGIT_BIT
;
1708 if (norm
< (int)(DIGIT_BIT
-1)) {
1709 norm
= (DIGIT_BIT
-1) - norm
;
1710 if ((res
= mp_mul_2d (&x
, norm
, &x
)) != MP_OKAY
) {
1713 if ((res
= mp_mul_2d (&y
, norm
, &y
)) != MP_OKAY
) {
1720 /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
1724 /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
1725 if ((res
= mp_lshd (&y
, n
- t
)) != MP_OKAY
) { /* y = y*b**{n-t} */
1729 while (mp_cmp (&x
, &y
) != MP_LT
) {
1731 if ((res
= mp_sub (&x
, &y
, &x
)) != MP_OKAY
) {
1736 /* reset y by shifting it back down */
1737 mp_rshd (&y
, n
- t
);
1739 /* step 3. for i from n down to (t + 1) */
1740 for (i
= n
; i
>= (t
+ 1); i
--) {
1745 /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
1746 * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
1747 if (x
.dp
[i
] == y
.dp
[t
]) {
1748 q
.dp
[i
- t
- 1] = ((((mp_digit
)1) << DIGIT_BIT
) - 1);
1751 tmp
= ((mp_word
) x
.dp
[i
]) << ((mp_word
) DIGIT_BIT
);
1752 tmp
|= ((mp_word
) x
.dp
[i
- 1]);
1753 tmp
/= ((mp_word
) y
.dp
[t
]);
1754 if (tmp
> (mp_word
) MP_MASK
)
1756 q
.dp
[i
- t
- 1] = (mp_digit
) (tmp
& (mp_word
) (MP_MASK
));
1759 /* while (q{i-t-1} * (yt * b + y{t-1})) >
1760 xi * b**2 + xi-1 * b + xi-2
1764 q
.dp
[i
- t
- 1] = (q
.dp
[i
- t
- 1] + 1) & MP_MASK
;
1766 q
.dp
[i
- t
- 1] = (q
.dp
[i
- t
- 1] - 1) & MP_MASK
;
1768 /* find left hand */
1770 t1
.dp
[0] = (t
- 1 < 0) ? 0 : y
.dp
[t
- 1];
1773 if ((res
= mp_mul_d (&t1
, q
.dp
[i
- t
- 1], &t1
)) != MP_OKAY
) {
1777 /* find right hand */
1778 t2
.dp
[0] = (i
- 2 < 0) ? 0 : x
.dp
[i
- 2];
1779 t2
.dp
[1] = (i
- 1 < 0) ? 0 : x
.dp
[i
- 1];
1782 } while (mp_cmp_mag(&t1
, &t2
) == MP_GT
);
1784 /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
1785 if ((res
= mp_mul_d (&y
, q
.dp
[i
- t
- 1], &t1
)) != MP_OKAY
) {
1789 if ((res
= mp_lshd (&t1
, i
- t
- 1)) != MP_OKAY
) {
1793 if ((res
= mp_sub (&x
, &t1
, &x
)) != MP_OKAY
) {
1797 /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
1798 if (x
.sign
== MP_NEG
) {
1799 if ((res
= mp_copy (&y
, &t1
)) != MP_OKAY
) {
1802 if ((res
= mp_lshd (&t1
, i
- t
- 1)) != MP_OKAY
) {
1805 if ((res
= mp_add (&x
, &t1
, &x
)) != MP_OKAY
) {
1809 q
.dp
[i
- t
- 1] = (q
.dp
[i
- t
- 1] - 1UL) & MP_MASK
;
1813 /* now q is the quotient and x is the remainder
1814 * [which we have to normalize]
1817 /* get sign before writing to c */
1818 x
.sign
= x
.used
== 0 ? MP_ZPOS
: a
->sign
;
1827 mp_div_2d (&x
, norm
, &x
, NULL
);
1833 LBL_Y
:mp_clear (&y
);
1834 LBL_X
:mp_clear (&x
);
1835 LBL_T2
:mp_clear (&t2
);
1836 LBL_T1
:mp_clear (&t1
);
1837 LBL_Q
:mp_clear (&q
);
1845 /* $Source: /cvs/libtom/libtommath/bn_mp_div.c,v $ */
1846 /* $Revision: 1.3 $ */
1847 /* $Date: 2006/03/31 14:18:44 $ */
1849 /* End: bn_mp_div.c */
1851 /* Start: bn_mp_div_2.c */
1852 #include <tommath.h>
1853 #ifdef BN_MP_DIV_2_C
1854 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1856 * LibTomMath is a library that provides multiple-precision
1857 * integer arithmetic as well as number theoretic functionality.
1859 * The library was designed directly after the MPI library by
1860 * Michael Fromberger but has been written from scratch with
1861 * additional optimizations in place.
1863 * The library is free for all purposes without any express
1864 * guarantee it works.
1866 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1870 int mp_div_2(mp_int
* a
, mp_int
* b
)
1872 int x
, res
, oldused
;
1875 if (b
->alloc
< a
->used
) {
1876 if ((res
= mp_grow (b
, a
->used
)) != MP_OKAY
) {
1884 register mp_digit r
, rr
, *tmpa
, *tmpb
;
1887 tmpa
= a
->dp
+ b
->used
- 1;
1890 tmpb
= b
->dp
+ b
->used
- 1;
1894 for (x
= b
->used
- 1; x
>= 0; x
--) {
1895 /* get the carry for the next iteration */
1898 /* shift the current digit, add in carry and store */
1899 *tmpb
-- = (*tmpa
-- >> 1) | (r
<< (DIGIT_BIT
- 1));
1901 /* forward carry to next iteration */
1905 /* zero excess digits */
1906 tmpb
= b
->dp
+ b
->used
;
1907 for (x
= b
->used
; x
< oldused
; x
++) {
1917 /* $Source: /cvs/libtom/libtommath/bn_mp_div_2.c,v $ */
1918 /* $Revision: 1.3 $ */
1919 /* $Date: 2006/03/31 14:18:44 $ */
1921 /* End: bn_mp_div_2.c */
1923 /* Start: bn_mp_div_2d.c */
1924 #include <tommath.h>
1925 #ifdef BN_MP_DIV_2D_C
1926 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1928 * LibTomMath is a library that provides multiple-precision
1929 * integer arithmetic as well as number theoretic functionality.
1931 * The library was designed directly after the MPI library by
1932 * Michael Fromberger but has been written from scratch with
1933 * additional optimizations in place.
1935 * The library is free for all purposes without any express
1936 * guarantee it works.
1938 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
1941 /* shift right by a certain bit count (store quotient in c, optional remainder in d) */
1942 int mp_div_2d (mp_int
* a
, int b
, mp_int
* c
, mp_int
* d
)
1949 /* if the shift count is <= 0 then we do no work */
1951 res
= mp_copy (a
, c
);
1958 if ((res
= mp_init (&t
)) != MP_OKAY
) {
1962 /* get the remainder */
1964 if ((res
= mp_mod_2d (a
, b
, &t
)) != MP_OKAY
) {
1971 if ((res
= mp_copy (a
, c
)) != MP_OKAY
) {
1976 /* shift by as many digits in the bit count */
1977 if (b
>= (int)DIGIT_BIT
) {
1978 mp_rshd (c
, b
/ DIGIT_BIT
);
1981 /* shift any bit count < DIGIT_BIT */
1982 D
= (mp_digit
) (b
% DIGIT_BIT
);
1984 register mp_digit
*tmpc
, mask
, shift
;
1987 mask
= (((mp_digit
)1) << D
) - 1;
1990 shift
= DIGIT_BIT
- D
;
1993 tmpc
= c
->dp
+ (c
->used
- 1);
1997 for (x
= c
->used
- 1; x
>= 0; x
--) {
1998 /* get the lower bits of this word in a temp */
2001 /* shift the current word and mix in the carry bits from the previous word */
2002 *tmpc
= (*tmpc
>> D
) | (r
<< shift
);
2005 /* set the carry to the carry bits of the current word found above */
2018 /* $Source: /cvs/libtom/libtommath/bn_mp_div_2d.c,v $ */
2019 /* $Revision: 1.3 $ */
2020 /* $Date: 2006/03/31 14:18:44 $ */
2022 /* End: bn_mp_div_2d.c */
2024 /* Start: bn_mp_div_3.c */
2025 #include <tommath.h>
2026 #ifdef BN_MP_DIV_3_C
2027 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2029 * LibTomMath is a library that provides multiple-precision
2030 * integer arithmetic as well as number theoretic functionality.
2032 * The library was designed directly after the MPI library by
2033 * Michael Fromberger but has been written from scratch with
2034 * additional optimizations in place.
2036 * The library is free for all purposes without any express
2037 * guarantee it works.
2039 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
2042 /* divide by three (based on routine from MPI and the GMP manual) */
2044 mp_div_3 (mp_int
* a
, mp_int
*c
, mp_digit
* d
)
2051 /* b = 2**DIGIT_BIT / 3 */
2052 b
= (((mp_word
)1) << ((mp_word
)DIGIT_BIT
)) / ((mp_word
)3);
2054 if ((res
= mp_init_size(&q
, a
->used
)) != MP_OKAY
) {
2061 for (ix
= a
->used
- 1; ix
>= 0; ix
--) {
2062 w
= (w
<< ((mp_word
)DIGIT_BIT
)) | ((mp_word
)a
->dp
[ix
]);
2065 /* multiply w by [1/3] */
2066 t
= (w
* ((mp_word
)b
)) >> ((mp_word
)DIGIT_BIT
);
2068 /* now subtract 3 * [w/3] from w, to get the remainder */
2071 /* fixup the remainder as required since
2072 * the optimization is not exact.
2081 q
.dp
[ix
] = (mp_digit
)t
;
2084 /* [optional] store the remainder */
2089 /* [optional] store the quotient */
2101 /* $Source: /cvs/libtom/libtommath/bn_mp_div_3.c,v $ */
2102 /* $Revision: 1.3 $ */
2103 /* $Date: 2006/03/31 14:18:44 $ */
2105 /* End: bn_mp_div_3.c */
2107 /* Start: bn_mp_div_d.c */
2108 #include <tommath.h>
2109 #ifdef BN_MP_DIV_D_C
2110 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2112 * LibTomMath is a library that provides multiple-precision
2113 * integer arithmetic as well as number theoretic functionality.
2115 * The library was designed directly after the MPI library by
2116 * Michael Fromberger but has been written from scratch with
2117 * additional optimizations in place.
2119 * The library is free for all purposes without any express
2120 * guarantee it works.
2122 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
2125 static int s_is_power_of_two(mp_digit b
, int *p
)
2129 for (x
= 1; x
< DIGIT_BIT
; x
++) {
2130 if (b
== (((mp_digit
)1)<<x
)) {
2138 /* single digit division (based on routine from MPI) */
2139 int mp_div_d (mp_int
* a
, mp_digit b
, mp_int
* c
, mp_digit
* d
)
2146 /* cannot divide by zero */
2152 if (b
== 1 || mp_iszero(a
) == 1) {
2157 return mp_copy(a
, c
);
2162 /* power of two ? */
2163 if (s_is_power_of_two(b
, &ix
) == 1) {
2165 *d
= a
->dp
[0] & ((((mp_digit
)1)<<ix
) - 1);
2168 return mp_div_2d(a
, ix
, c
, NULL
);
2173 #ifdef BN_MP_DIV_3_C
2176 return mp_div_3(a
, c
, d
);
2180 /* no easy answer [c'est la vie]. Just division */
2181 if ((res
= mp_init_size(&q
, a
->used
)) != MP_OKAY
) {
2188 for (ix
= a
->used
- 1; ix
>= 0; ix
--) {
2189 w
= (w
<< ((mp_word
)DIGIT_BIT
)) | ((mp_word
)a
->dp
[ix
]);
2192 t
= (mp_digit
)(w
/ b
);
2193 w
-= ((mp_word
)t
) * ((mp_word
)b
);
2197 q
.dp
[ix
] = (mp_digit
)t
;
2215 /* $Source: /cvs/libtom/libtommath/bn_mp_div_d.c,v $ */
2216 /* $Revision: 1.3 $ */
2217 /* $Date: 2006/03/31 14:18:44 $ */
2219 /* End: bn_mp_div_d.c */
2221 /* Start: bn_mp_dr_is_modulus.c */
2222 #include <tommath.h>
2223 #ifdef BN_MP_DR_IS_MODULUS_C
2224 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2226 * LibTomMath is a library that provides multiple-precision
2227 * integer arithmetic as well as number theoretic functionality.
2229 * The library was designed directly after the MPI library by
2230 * Michael Fromberger but has been written from scratch with
2231 * additional optimizations in place.
2233 * The library is free for all purposes without any express
2234 * guarantee it works.
2236 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
2239 /* determines if a number is a valid DR modulus */
2240 int mp_dr_is_modulus(mp_int
*a
)
2244 /* must be at least two digits */
2249 /* must be of the form b**k - a [a <= b] so all
2250 * but the first digit must be equal to -1 (mod b).
2252 for (ix
= 1; ix
< a
->used
; ix
++) {
2253 if (a
->dp
[ix
] != MP_MASK
) {
2262 /* $Source: /cvs/libtom/libtommath/bn_mp_dr_is_modulus.c,v $ */
2263 /* $Revision: 1.3 $ */
2264 /* $Date: 2006/03/31 14:18:44 $ */
2266 /* End: bn_mp_dr_is_modulus.c */
2268 /* Start: bn_mp_dr_reduce.c */
2269 #include <tommath.h>
2270 #ifdef BN_MP_DR_REDUCE_C
2271 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2273 * LibTomMath is a library that provides multiple-precision
2274 * integer arithmetic as well as number theoretic functionality.
2276 * The library was designed directly after the MPI library by
2277 * Michael Fromberger but has been written from scratch with
2278 * additional optimizations in place.
2280 * The library is free for all purposes without any express
2281 * guarantee it works.
2283 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
2286 /* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
2288 * Based on algorithm from the paper
2290 * "Generating Efficient Primes for Discrete Log Cryptosystems"
2291 * Chae Hoon Lim, Pil Joong Lee,
2292 * POSTECH Information Research Laboratories
2294 * The modulus must be of a special format [see manual]
2296 * Has been modified to use algorithm 7.10 from the LTM book instead
2298 * Input x must be in the range 0 <= x <= (n-1)**2
2301 mp_dr_reduce (mp_int
* x
, mp_int
* n
, mp_digit k
)
2305 mp_digit mu
, *tmpx1
, *tmpx2
;
2307 /* m = digits in modulus */
2310 /* ensure that "x" has at least 2m digits */
2311 if (x
->alloc
< m
+ m
) {
2312 if ((err
= mp_grow (x
, m
+ m
)) != MP_OKAY
) {
2317 /* top of loop, this is where the code resumes if
2318 * another reduction pass is required.
2321 /* aliases for digits */
2322 /* alias for lower half of x */
2325 /* alias for upper half of x, or x/B**m */
2328 /* set carry to zero */
2331 /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
2332 for (i
= 0; i
< m
; i
++) {
2333 r
= ((mp_word
)*tmpx2
++) * ((mp_word
)k
) + *tmpx1
+ mu
;
2334 *tmpx1
++ = (mp_digit
)(r
& MP_MASK
);
2335 mu
= (mp_digit
)(r
>> ((mp_word
)DIGIT_BIT
));
2338 /* set final carry */
2341 /* zero words above m */
2342 for (i
= m
+ 1; i
< x
->used
; i
++) {
2346 /* clamp, sub and return */
2349 /* if x >= n then subtract and reduce again
2350 * Each successive "recursion" makes the input smaller and smaller.
2352 if (mp_cmp_mag (x
, n
) != MP_LT
) {
2360 /* $Source: /cvs/libtom/libtommath/bn_mp_dr_reduce.c,v $ */
2361 /* $Revision: 1.3 $ */
2362 /* $Date: 2006/03/31 14:18:44 $ */
2364 /* End: bn_mp_dr_reduce.c */
2366 /* Start: bn_mp_dr_setup.c */
2367 #include <tommath.h>
2368 #ifdef BN_MP_DR_SETUP_C
2369 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2371 * LibTomMath is a library that provides multiple-precision
2372 * integer arithmetic as well as number theoretic functionality.
2374 * The library was designed directly after the MPI library by
2375 * Michael Fromberger but has been written from scratch with
2376 * additional optimizations in place.
2378 * The library is free for all purposes without any express
2379 * guarantee it works.
2381 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
2384 /* determines the setup value */
2385 void mp_dr_setup(mp_int
*a
, mp_digit
*d
)
2387 /* the casts are required if DIGIT_BIT is one less than
2388 * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
2390 *d
= (mp_digit
)((((mp_word
)1) << ((mp_word
)DIGIT_BIT
)) -
2391 ((mp_word
)a
->dp
[0]));
2396 /* $Source: /cvs/libtom/libtommath/bn_mp_dr_setup.c,v $ */
2397 /* $Revision: 1.3 $ */
2398 /* $Date: 2006/03/31 14:18:44 $ */
2400 /* End: bn_mp_dr_setup.c */
2402 /* Start: bn_mp_exch.c */
2403 #include <tommath.h>
2405 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2407 * LibTomMath is a library that provides multiple-precision
2408 * integer arithmetic as well as number theoretic functionality.
2410 * The library was designed directly after the MPI library by
2411 * Michael Fromberger but has been written from scratch with
2412 * additional optimizations in place.
2414 * The library is free for all purposes without any express
2415 * guarantee it works.
2417 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
2420 /* swap the elements of two integers, for cases where you can't simply swap the
2421 * mp_int pointers around
2424 mp_exch (mp_int
* a
, mp_int
* b
)
2434 /* $Source: /cvs/libtom/libtommath/bn_mp_exch.c,v $ */
2435 /* $Revision: 1.3 $ */
2436 /* $Date: 2006/03/31 14:18:44 $ */
2438 /* End: bn_mp_exch.c */
2440 /* Start: bn_mp_expt_d.c */
2441 #include <tommath.h>
2442 #ifdef BN_MP_EXPT_D_C
2443 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2445 * LibTomMath is a library that provides multiple-precision
2446 * integer arithmetic as well as number theoretic functionality.
2448 * The library was designed directly after the MPI library by
2449 * Michael Fromberger but has been written from scratch with
2450 * additional optimizations in place.
2452 * The library is free for all purposes without any express
2453 * guarantee it works.
2455 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
2458 /* calculate c = a**b using a square-multiply algorithm */
2459 int mp_expt_d (mp_int
* a
, mp_digit b
, mp_int
* c
)
2464 if ((res
= mp_init_copy (&g
, a
)) != MP_OKAY
) {
2468 /* set initial result */
2471 for (x
= 0; x
< (int) DIGIT_BIT
; x
++) {
2473 if ((res
= mp_sqr (c
, c
)) != MP_OKAY
) {
2478 /* if the bit is set multiply */
2479 if ((b
& (mp_digit
) (((mp_digit
)1) << (DIGIT_BIT
- 1))) != 0) {
2480 if ((res
= mp_mul (c
, &g
, c
)) != MP_OKAY
) {
2486 /* shift to next bit */
2495 /* $Source: /cvs/libtom/libtommath/bn_mp_expt_d.c,v $ */
2496 /* $Revision: 1.3 $ */
2497 /* $Date: 2006/03/31 14:18:44 $ */
2499 /* End: bn_mp_expt_d.c */
2501 /* Start: bn_mp_exptmod.c */
2502 #include <tommath.h>
2503 #ifdef BN_MP_EXPTMOD_C
2504 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2506 * LibTomMath is a library that provides multiple-precision
2507 * integer arithmetic as well as number theoretic functionality.
2509 * The library was designed directly after the MPI library by
2510 * Michael Fromberger but has been written from scratch with
2511 * additional optimizations in place.
2513 * The library is free for all purposes without any express
2514 * guarantee it works.
2516 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
2520 /* this is a shell function that calls either the normal or Montgomery
2521 * exptmod functions. Originally the call to the montgomery code was
2522 * embedded in the normal function but that wasted alot of stack space
2523 * for nothing (since 99% of the time the Montgomery code would be called)
2525 int mp_exptmod (mp_int
* G
, mp_int
* X
, mp_int
* P
, mp_int
* Y
)
2529 /* modulus P must be positive */
2530 if (P
->sign
== MP_NEG
) {
2534 /* if exponent X is negative we have to recurse */
2535 if (X
->sign
== MP_NEG
) {
2536 #ifdef BN_MP_INVMOD_C
2540 /* first compute 1/G mod P */
2541 if ((err
= mp_init(&tmpG
)) != MP_OKAY
) {
2544 if ((err
= mp_invmod(G
, P
, &tmpG
)) != MP_OKAY
) {
2550 if ((err
= mp_init(&tmpX
)) != MP_OKAY
) {
2554 if ((err
= mp_abs(X
, &tmpX
)) != MP_OKAY
) {
2555 mp_clear_multi(&tmpG
, &tmpX
, NULL
);
2559 /* and now compute (1/G)**|X| instead of G**X [X < 0] */
2560 err
= mp_exptmod(&tmpG
, &tmpX
, P
, Y
);
2561 mp_clear_multi(&tmpG
, &tmpX
, NULL
);
2569 /* modified diminished radix reduction */
2570 #if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
2571 if (mp_reduce_is_2k_l(P
) == MP_YES
) {
2572 return s_mp_exptmod(G
, X
, P
, Y
, 1);
2576 #ifdef BN_MP_DR_IS_MODULUS_C
2577 /* is it a DR modulus? */
2578 dr
= mp_dr_is_modulus(P
);
2584 #ifdef BN_MP_REDUCE_IS_2K_C
2585 /* if not, is it a unrestricted DR modulus? */
2587 dr
= mp_reduce_is_2k(P
) << 1;
2591 /* if the modulus is odd or dr != 0 use the montgomery method */
2592 #ifdef BN_MP_EXPTMOD_FAST_C
2593 if (mp_isodd (P
) == 1 || dr
!= 0) {
2594 return mp_exptmod_fast (G
, X
, P
, Y
, dr
);
2597 #ifdef BN_S_MP_EXPTMOD_C
2598 /* otherwise use the generic Barrett reduction technique */
2599 return s_mp_exptmod (G
, X
, P
, Y
, 0);
2601 /* no exptmod for evens */
2604 #ifdef BN_MP_EXPTMOD_FAST_C
2611 /* $Source: /cvs/libtom/libtommath/bn_mp_exptmod.c,v $ */
2612 /* $Revision: 1.4 $ */
2613 /* $Date: 2006/03/31 14:18:44 $ */
2615 /* End: bn_mp_exptmod.c */
2617 /* Start: bn_mp_exptmod_fast.c */
2618 #include <tommath.h>
2619 #ifdef BN_MP_EXPTMOD_FAST_C
2620 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2622 * LibTomMath is a library that provides multiple-precision
2623 * integer arithmetic as well as number theoretic functionality.
2625 * The library was designed directly after the MPI library by
2626 * Michael Fromberger but has been written from scratch with
2627 * additional optimizations in place.
2629 * The library is free for all purposes without any express
2630 * guarantee it works.
2632 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
2635 /* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
2637 * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
2638 * The value of k changes based on the size of the exponent.
2640 * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
2646 #define TAB_SIZE 256
2649 int mp_exptmod_fast (mp_int
* G
, mp_int
* X
, mp_int
* P
, mp_int
* Y
, int redmode
)
2651 mp_int M
[TAB_SIZE
], res
;
2653 int err
, bitbuf
, bitcpy
, bitcnt
, mode
, digidx
, x
, y
, winsize
;
2655 /* use a pointer to the reduction algorithm. This allows us to use
2656 * one of many reduction algorithms without modding the guts of
2657 * the code with if statements everywhere.
2659 int (*redux
)(mp_int
*,mp_int
*,mp_digit
);
2661 /* find window size */
2662 x
= mp_count_bits (X
);
2665 } else if (x
<= 36) {
2667 } else if (x
<= 140) {
2669 } else if (x
<= 450) {
2671 } else if (x
<= 1303) {
2673 } else if (x
<= 3529) {
2686 /* init first cell */
2687 if ((err
= mp_init(&M
[1])) != MP_OKAY
) {
2691 /* now init the second half of the array */
2692 for (x
= 1<<(winsize
-1); x
< (1 << winsize
); x
++) {
2693 if ((err
= mp_init(&M
[x
])) != MP_OKAY
) {
2694 for (y
= 1<<(winsize
-1); y
< x
; y
++) {
2702 /* determine and setup reduction code */
2704 #ifdef BN_MP_MONTGOMERY_SETUP_C
2705 /* now setup montgomery */
2706 if ((err
= mp_montgomery_setup (P
, &mp
)) != MP_OKAY
) {
2714 /* automatically pick the comba one if available (saves quite a few calls/ifs) */
2715 #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
2716 if (((P
->used
* 2 + 1) < MP_WARRAY
) &&
2717 P
->used
< (1 << ((CHAR_BIT
* sizeof (mp_word
)) - (2 * DIGIT_BIT
)))) {
2718 redux
= fast_mp_montgomery_reduce
;
2722 #ifdef BN_MP_MONTGOMERY_REDUCE_C
2723 /* use slower baseline Montgomery method */
2724 redux
= mp_montgomery_reduce
;
2730 } else if (redmode
== 1) {
2731 #if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
2732 /* setup DR reduction for moduli of the form B**k - b */
2733 mp_dr_setup(P
, &mp
);
2734 redux
= mp_dr_reduce
;
2740 #if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
2741 /* setup DR reduction for moduli of the form 2**k - b */
2742 if ((err
= mp_reduce_2k_setup(P
, &mp
)) != MP_OKAY
) {
2745 redux
= mp_reduce_2k
;
2753 if ((err
= mp_init (&res
)) != MP_OKAY
) {
2761 * The first half of the table is not computed though accept for M[0] and M[1]
2765 #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
2766 /* now we need R mod m */
2767 if ((err
= mp_montgomery_calc_normalization (&res
, P
)) != MP_OKAY
) {
2775 /* now set M[1] to G * R mod m */
2776 if ((err
= mp_mulmod (G
, &res
, P
, &M
[1])) != MP_OKAY
) {
2781 if ((err
= mp_mod(G
, P
, &M
[1])) != MP_OKAY
) {
2786 /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
2787 if ((err
= mp_copy (&M
[1], &M
[1 << (winsize
- 1)])) != MP_OKAY
) {
2791 for (x
= 0; x
< (winsize
- 1); x
++) {
2792 if ((err
= mp_sqr (&M
[1 << (winsize
- 1)], &M
[1 << (winsize
- 1)])) != MP_OKAY
) {
2795 if ((err
= redux (&M
[1 << (winsize
- 1)], P
, mp
)) != MP_OKAY
) {
2800 /* create upper table */
2801 for (x
= (1 << (winsize
- 1)) + 1; x
< (1 << winsize
); x
++) {
2802 if ((err
= mp_mul (&M
[x
- 1], &M
[1], &M
[x
])) != MP_OKAY
) {
2805 if ((err
= redux (&M
[x
], P
, mp
)) != MP_OKAY
) {
2810 /* set initial mode and bit cnt */
2814 digidx
= X
->used
- 1;
2819 /* grab next digit as required */
2820 if (--bitcnt
== 0) {
2821 /* if digidx == -1 we are out of digits so break */
2825 /* read next digit and reset bitcnt */
2826 buf
= X
->dp
[digidx
--];
2827 bitcnt
= (int)DIGIT_BIT
;
2830 /* grab the next msb from the exponent */
2831 y
= (mp_digit
)(buf
>> (DIGIT_BIT
- 1)) & 1;
2832 buf
<<= (mp_digit
)1;
2834 /* if the bit is zero and mode == 0 then we ignore it
2835 * These represent the leading zero bits before the first 1 bit
2836 * in the exponent. Technically this opt is not required but it
2837 * does lower the # of trivial squaring/reductions used
2839 if (mode
== 0 && y
== 0) {
2843 /* if the bit is zero and mode == 1 then we square */
2844 if (mode
== 1 && y
== 0) {
2845 if ((err
= mp_sqr (&res
, &res
)) != MP_OKAY
) {
2848 if ((err
= redux (&res
, P
, mp
)) != MP_OKAY
) {
2854 /* else we add it to the window */
2855 bitbuf
|= (y
<< (winsize
- ++bitcpy
));
2858 if (bitcpy
== winsize
) {
2859 /* ok window is filled so square as required and multiply */
2861 for (x
= 0; x
< winsize
; x
++) {
2862 if ((err
= mp_sqr (&res
, &res
)) != MP_OKAY
) {
2865 if ((err
= redux (&res
, P
, mp
)) != MP_OKAY
) {
2871 if ((err
= mp_mul (&res
, &M
[bitbuf
], &res
)) != MP_OKAY
) {
2874 if ((err
= redux (&res
, P
, mp
)) != MP_OKAY
) {
2878 /* empty window and reset */
2885 /* if bits remain then square/multiply */
2886 if (mode
== 2 && bitcpy
> 0) {
2887 /* square then multiply if the bit is set */
2888 for (x
= 0; x
< bitcpy
; x
++) {
2889 if ((err
= mp_sqr (&res
, &res
)) != MP_OKAY
) {
2892 if ((err
= redux (&res
, P
, mp
)) != MP_OKAY
) {
2896 /* get next bit of the window */
2898 if ((bitbuf
& (1 << winsize
)) != 0) {
2900 if ((err
= mp_mul (&res
, &M
[1], &res
)) != MP_OKAY
) {
2903 if ((err
= redux (&res
, P
, mp
)) != MP_OKAY
) {
2911 /* fixup result if Montgomery reduction is used
2912 * recall that any value in a Montgomery system is
2913 * actually multiplied by R mod n. So we have
2914 * to reduce one more time to cancel out the factor
2917 if ((err
= redux(&res
, P
, mp
)) != MP_OKAY
) {
2922 /* swap res with Y */
2925 LBL_RES
:mp_clear (&res
);
2928 for (x
= 1<<(winsize
-1); x
< (1 << winsize
); x
++) {
2936 /* $Source: /cvs/libtom/libtommath/bn_mp_exptmod_fast.c,v $ */
2937 /* $Revision: 1.3 $ */
2938 /* $Date: 2006/03/31 14:18:44 $ */
2940 /* End: bn_mp_exptmod_fast.c */
2942 /* Start: bn_mp_exteuclid.c */
2943 #include <tommath.h>
2944 #ifdef BN_MP_EXTEUCLID_C
2945 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2947 * LibTomMath is a library that provides multiple-precision
2948 * integer arithmetic as well as number theoretic functionality.
2950 * The library was designed directly after the MPI library by
2951 * Michael Fromberger but has been written from scratch with
2952 * additional optimizations in place.
2954 * The library is free for all purposes without any express
2955 * guarantee it works.
2957 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
2960 /* Extended euclidean algorithm of (a, b) produces
2963 int mp_exteuclid(mp_int
*a
, mp_int
*b
, mp_int
*U1
, mp_int
*U2
, mp_int
*U3
)
2965 mp_int u1
,u2
,u3
,v1
,v2
,v3
,t1
,t2
,t3
,q
,tmp
;
2968 if ((err
= mp_init_multi(&u1
, &u2
, &u3
, &v1
, &v2
, &v3
, &t1
, &t2
, &t3
, &q
, &tmp
, NULL
)) != MP_OKAY
) {
2972 /* initialize, (u1,u2,u3) = (1,0,a) */
2974 if ((err
= mp_copy(a
, &u3
)) != MP_OKAY
) { goto _ERR
; }
2976 /* initialize, (v1,v2,v3) = (0,1,b) */
2978 if ((err
= mp_copy(b
, &v3
)) != MP_OKAY
) { goto _ERR
; }
2980 /* loop while v3 != 0 */
2981 while (mp_iszero(&v3
) == MP_NO
) {
2983 if ((err
= mp_div(&u3
, &v3
, &q
, NULL
)) != MP_OKAY
) { goto _ERR
; }
2985 /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
2986 if ((err
= mp_mul(&v1
, &q
, &tmp
)) != MP_OKAY
) { goto _ERR
; }
2987 if ((err
= mp_sub(&u1
, &tmp
, &t1
)) != MP_OKAY
) { goto _ERR
; }
2988 if ((err
= mp_mul(&v2
, &q
, &tmp
)) != MP_OKAY
) { goto _ERR
; }
2989 if ((err
= mp_sub(&u2
, &tmp
, &t2
)) != MP_OKAY
) { goto _ERR
; }
2990 if ((err
= mp_mul(&v3
, &q
, &tmp
)) != MP_OKAY
) { goto _ERR
; }
2991 if ((err
= mp_sub(&u3
, &tmp
, &t3
)) != MP_OKAY
) { goto _ERR
; }
2993 /* (u1,u2,u3) = (v1,v2,v3) */
2994 if ((err
= mp_copy(&v1
, &u1
)) != MP_OKAY
) { goto _ERR
; }
2995 if ((err
= mp_copy(&v2
, &u2
)) != MP_OKAY
) { goto _ERR
; }
2996 if ((err
= mp_copy(&v3
, &u3
)) != MP_OKAY
) { goto _ERR
; }
2998 /* (v1,v2,v3) = (t1,t2,t3) */
2999 if ((err
= mp_copy(&t1
, &v1
)) != MP_OKAY
) { goto _ERR
; }
3000 if ((err
= mp_copy(&t2
, &v2
)) != MP_OKAY
) { goto _ERR
; }
3001 if ((err
= mp_copy(&t3
, &v3
)) != MP_OKAY
) { goto _ERR
; }
3004 /* make sure U3 >= 0 */
3005 if (u3
.sign
== MP_NEG
) {
3011 /* copy result out */
3012 if (U1
!= NULL
) { mp_exch(U1
, &u1
); }
3013 if (U2
!= NULL
) { mp_exch(U2
, &u2
); }
3014 if (U3
!= NULL
) { mp_exch(U3
, &u3
); }
3017 _ERR
: mp_clear_multi(&u1
, &u2
, &u3
, &v1
, &v2
, &v3
, &t1
, &t2
, &t3
, &q
, &tmp
, NULL
);
3022 /* $Source: /cvs/libtom/libtommath/bn_mp_exteuclid.c,v $ */
3023 /* $Revision: 1.3 $ */
3024 /* $Date: 2006/03/31 14:18:44 $ */
3026 /* End: bn_mp_exteuclid.c */
3028 /* Start: bn_mp_fread.c */
3029 #include <tommath.h>
3030 #ifdef BN_MP_FREAD_C
3031 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3033 * LibTomMath is a library that provides multiple-precision
3034 * integer arithmetic as well as number theoretic functionality.
3036 * The library was designed directly after the MPI library by
3037 * Michael Fromberger but has been written from scratch with
3038 * additional optimizations in place.
3040 * The library is free for all purposes without any express
3041 * guarantee it works.
3043 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3046 /* read a bigint from a file stream in ASCII */
3047 int mp_fread(mp_int
*a
, int radix
, FILE *stream
)
3049 int err
, ch
, neg
, y
;
3054 /* if first digit is - then set negative */
3064 /* find y in the radix map */
3065 for (y
= 0; y
< radix
; y
++) {
3066 if (mp_s_rmap
[y
] == ch
) {
3074 /* shift up and add */
3075 if ((err
= mp_mul_d(a
, radix
, a
)) != MP_OKAY
) {
3078 if ((err
= mp_add_d(a
, y
, a
)) != MP_OKAY
) {
3084 if (mp_cmp_d(a
, 0) != MP_EQ
) {
3093 /* $Source: /cvs/libtom/libtommath/bn_mp_fread.c,v $ */
3094 /* $Revision: 1.3 $ */
3095 /* $Date: 2006/03/31 14:18:44 $ */
3097 /* End: bn_mp_fread.c */
3099 /* Start: bn_mp_fwrite.c */
3100 #include <tommath.h>
3101 #ifdef BN_MP_FWRITE_C
3102 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3104 * LibTomMath is a library that provides multiple-precision
3105 * integer arithmetic as well as number theoretic functionality.
3107 * The library was designed directly after the MPI library by
3108 * Michael Fromberger but has been written from scratch with
3109 * additional optimizations in place.
3111 * The library is free for all purposes without any express
3112 * guarantee it works.
3114 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3117 int mp_fwrite(mp_int
*a
, int radix
, FILE *stream
)
3122 if ((err
= mp_radix_size(a
, radix
, &len
)) != MP_OKAY
) {
3126 buf
= OPT_CAST(char) XMALLOC (len
);
3131 if ((err
= mp_toradix(a
, buf
, radix
)) != MP_OKAY
) {
3136 for (x
= 0; x
< len
; x
++) {
3137 if (fputc(buf
[x
], stream
) == EOF
) {
3149 /* $Source: /cvs/libtom/libtommath/bn_mp_fwrite.c,v $ */
3150 /* $Revision: 1.3 $ */
3151 /* $Date: 2006/03/31 14:18:44 $ */
3153 /* End: bn_mp_fwrite.c */
3155 /* Start: bn_mp_gcd.c */
3156 #include <tommath.h>
3158 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3160 * LibTomMath is a library that provides multiple-precision
3161 * integer arithmetic as well as number theoretic functionality.
3163 * The library was designed directly after the MPI library by
3164 * Michael Fromberger but has been written from scratch with
3165 * additional optimizations in place.
3167 * The library is free for all purposes without any express
3168 * guarantee it works.
3170 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3173 /* Greatest Common Divisor using the binary method */
3174 int mp_gcd (mp_int
* a
, mp_int
* b
, mp_int
* c
)
3177 int k
, u_lsb
, v_lsb
, res
;
3179 /* either zero than gcd is the largest */
3180 if (mp_iszero (a
) == MP_YES
) {
3181 return mp_abs (b
, c
);
3183 if (mp_iszero (b
) == MP_YES
) {
3184 return mp_abs (a
, c
);
3187 /* get copies of a and b we can modify */
3188 if ((res
= mp_init_copy (&u
, a
)) != MP_OKAY
) {
3192 if ((res
= mp_init_copy (&v
, b
)) != MP_OKAY
) {
3196 /* must be positive for the remainder of the algorithm */
3197 u
.sign
= v
.sign
= MP_ZPOS
;
3199 /* B1. Find the common power of two for u and v */
3200 u_lsb
= mp_cnt_lsb(&u
);
3201 v_lsb
= mp_cnt_lsb(&v
);
3202 k
= MIN(u_lsb
, v_lsb
);
3205 /* divide the power of two out */
3206 if ((res
= mp_div_2d(&u
, k
, &u
, NULL
)) != MP_OKAY
) {
3210 if ((res
= mp_div_2d(&v
, k
, &v
, NULL
)) != MP_OKAY
) {
3215 /* divide any remaining factors of two out */
3217 if ((res
= mp_div_2d(&u
, u_lsb
- k
, &u
, NULL
)) != MP_OKAY
) {
3223 if ((res
= mp_div_2d(&v
, v_lsb
- k
, &v
, NULL
)) != MP_OKAY
) {
3228 while (mp_iszero(&v
) == 0) {
3229 /* make sure v is the largest */
3230 if (mp_cmp_mag(&u
, &v
) == MP_GT
) {
3231 /* swap u and v to make sure v is >= u */
3235 /* subtract smallest from largest */
3236 if ((res
= s_mp_sub(&v
, &u
, &v
)) != MP_OKAY
) {
3240 /* Divide out all factors of two */
3241 if ((res
= mp_div_2d(&v
, mp_cnt_lsb(&v
), &v
, NULL
)) != MP_OKAY
) {
3246 /* multiply by 2**k which we divided out at the beginning */
3247 if ((res
= mp_mul_2d (&u
, k
, c
)) != MP_OKAY
) {
3252 LBL_V
:mp_clear (&u
);
3253 LBL_U
:mp_clear (&v
);
3258 /* $Source: /cvs/libtom/libtommath/bn_mp_gcd.c,v $ */
3259 /* $Revision: 1.4 $ */
3260 /* $Date: 2006/03/31 14:18:44 $ */
3262 /* End: bn_mp_gcd.c */
3264 /* Start: bn_mp_get_int.c */
3265 #include <tommath.h>
3266 #ifdef BN_MP_GET_INT_C
3267 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3269 * LibTomMath is a library that provides multiple-precision
3270 * integer arithmetic as well as number theoretic functionality.
3272 * The library was designed directly after the MPI library by
3273 * Michael Fromberger but has been written from scratch with
3274 * additional optimizations in place.
3276 * The library is free for all purposes without any express
3277 * guarantee it works.
3279 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3282 /* get the lower 32-bits of an mp_int */
3283 unsigned long mp_get_int(mp_int
* a
)
3292 /* get number of digits of the lsb we have to read */
3293 i
= MIN(a
->used
,(int)((sizeof(unsigned long)*CHAR_BIT
+DIGIT_BIT
-1)/DIGIT_BIT
))-1;
3295 /* get most significant digit of result */
3299 res
= (res
<< DIGIT_BIT
) | DIGIT(a
,i
);
3302 /* force result to 32-bits always so it is consistent on non 32-bit platforms */
3303 return res
& 0xFFFFFFFFUL
;
3307 /* $Source: /cvs/libtom/libtommath/bn_mp_get_int.c,v $ */
3308 /* $Revision: 1.3 $ */
3309 /* $Date: 2006/03/31 14:18:44 $ */
3311 /* End: bn_mp_get_int.c */
3313 /* Start: bn_mp_grow.c */
3314 #include <tommath.h>
3316 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3318 * LibTomMath is a library that provides multiple-precision
3319 * integer arithmetic as well as number theoretic functionality.
3321 * The library was designed directly after the MPI library by
3322 * Michael Fromberger but has been written from scratch with
3323 * additional optimizations in place.
3325 * The library is free for all purposes without any express
3326 * guarantee it works.
3328 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3331 /* grow as required */
3332 int mp_grow (mp_int
* a
, int size
)
3337 /* if the alloc size is smaller alloc more ram */
3338 if (a
->alloc
< size
) {
3339 /* ensure there are always at least MP_PREC digits extra on top */
3340 size
+= (MP_PREC
* 2) - (size
% MP_PREC
);
3342 /* reallocate the array a->dp
3344 * We store the return in a temporary variable
3345 * in case the operation failed we don't want
3346 * to overwrite the dp member of a.
3348 tmp
= OPT_CAST(mp_digit
) XREALLOC (a
->dp
, sizeof (mp_digit
) * size
);
3350 /* reallocation failed but "a" is still valid [can be freed] */
3354 /* reallocation succeeded so set a->dp */
3357 /* zero excess digits */
3360 for (; i
< a
->alloc
; i
++) {
3368 /* $Source: /cvs/libtom/libtommath/bn_mp_grow.c,v $ */
3369 /* $Revision: 1.3 $ */
3370 /* $Date: 2006/03/31 14:18:44 $ */
3372 /* End: bn_mp_grow.c */
3374 /* Start: bn_mp_init.c */
3375 #include <tommath.h>
3377 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3379 * LibTomMath is a library that provides multiple-precision
3380 * integer arithmetic as well as number theoretic functionality.
3382 * The library was designed directly after the MPI library by
3383 * Michael Fromberger but has been written from scratch with
3384 * additional optimizations in place.
3386 * The library is free for all purposes without any express
3387 * guarantee it works.
3389 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3392 /* init a new mp_int */
3393 int mp_init (mp_int
* a
)
3397 /* allocate memory required and clear it */
3398 a
->dp
= OPT_CAST(mp_digit
) XMALLOC (sizeof (mp_digit
) * MP_PREC
);
3399 if (a
->dp
== NULL
) {
3403 /* set the digits to zero */
3404 for (i
= 0; i
< MP_PREC
; i
++) {
3408 /* set the used to zero, allocated digits to the default precision
3409 * and sign to positive */
3418 /* $Source: /cvs/libtom/libtommath/bn_mp_init.c,v $ */
3419 /* $Revision: 1.3 $ */
3420 /* $Date: 2006/03/31 14:18:44 $ */
3422 /* End: bn_mp_init.c */
3424 /* Start: bn_mp_init_copy.c */
3425 #include <tommath.h>
3426 #ifdef BN_MP_INIT_COPY_C
3427 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3429 * LibTomMath is a library that provides multiple-precision
3430 * integer arithmetic as well as number theoretic functionality.
3432 * The library was designed directly after the MPI library by
3433 * Michael Fromberger but has been written from scratch with
3434 * additional optimizations in place.
3436 * The library is free for all purposes without any express
3437 * guarantee it works.
3439 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3442 /* creates "a" then copies b into it */
3443 int mp_init_copy (mp_int
* a
, mp_int
* b
)
3447 if ((res
= mp_init (a
)) != MP_OKAY
) {
3450 return mp_copy (b
, a
);
3454 /* $Source: /cvs/libtom/libtommath/bn_mp_init_copy.c,v $ */
3455 /* $Revision: 1.3 $ */
3456 /* $Date: 2006/03/31 14:18:44 $ */
3458 /* End: bn_mp_init_copy.c */
3460 /* Start: bn_mp_init_multi.c */
3461 #include <tommath.h>
3462 #ifdef BN_MP_INIT_MULTI_C
3463 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3465 * LibTomMath is a library that provides multiple-precision
3466 * integer arithmetic as well as number theoretic functionality.
3468 * The library was designed directly after the MPI library by
3469 * Michael Fromberger but has been written from scratch with
3470 * additional optimizations in place.
3472 * The library is free for all purposes without any express
3473 * guarantee it works.
3475 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3479 int mp_init_multi(mp_int
*mp
, ...)
3481 mp_err res
= MP_OKAY
; /* Assume ok until proven otherwise */
3482 int n
= 0; /* Number of ok inits */
3483 mp_int
* cur_arg
= mp
;
3486 va_start(args
, mp
); /* init args to next argument from caller */
3487 while (cur_arg
!= NULL
) {
3488 if (mp_init(cur_arg
) != MP_OKAY
) {
3489 /* Oops - error! Back-track and mp_clear what we already
3490 succeeded in init-ing, then return error.
3494 /* end the current list */
3497 /* now start cleaning up */
3499 va_start(clean_args
, mp
);
3502 cur_arg
= va_arg(clean_args
, mp_int
*);
3509 cur_arg
= va_arg(args
, mp_int
*);
3512 return res
; /* Assumed ok, if error flagged above. */
3517 /* $Source: /cvs/libtom/libtommath/bn_mp_init_multi.c,v $ */
3518 /* $Revision: 1.3 $ */
3519 /* $Date: 2006/03/31 14:18:44 $ */
3521 /* End: bn_mp_init_multi.c */
3523 /* Start: bn_mp_init_set.c */
3524 #include <tommath.h>
3525 #ifdef BN_MP_INIT_SET_C
3526 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3528 * LibTomMath is a library that provides multiple-precision
3529 * integer arithmetic as well as number theoretic functionality.
3531 * The library was designed directly after the MPI library by
3532 * Michael Fromberger but has been written from scratch with
3533 * additional optimizations in place.
3535 * The library is free for all purposes without any express
3536 * guarantee it works.
3538 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3541 /* initialize and set a digit */
3542 int mp_init_set (mp_int
* a
, mp_digit b
)
3545 if ((err
= mp_init(a
)) != MP_OKAY
) {
3553 /* $Source: /cvs/libtom/libtommath/bn_mp_init_set.c,v $ */
3554 /* $Revision: 1.3 $ */
3555 /* $Date: 2006/03/31 14:18:44 $ */
3557 /* End: bn_mp_init_set.c */
3559 /* Start: bn_mp_init_set_int.c */
3560 #include <tommath.h>
3561 #ifdef BN_MP_INIT_SET_INT_C
3562 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3564 * LibTomMath is a library that provides multiple-precision
3565 * integer arithmetic as well as number theoretic functionality.
3567 * The library was designed directly after the MPI library by
3568 * Michael Fromberger but has been written from scratch with
3569 * additional optimizations in place.
3571 * The library is free for all purposes without any express
3572 * guarantee it works.
3574 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3577 /* initialize and set a digit */
3578 int mp_init_set_int (mp_int
* a
, unsigned long b
)
3581 if ((err
= mp_init(a
)) != MP_OKAY
) {
3584 return mp_set_int(a
, b
);
3588 /* $Source: /cvs/libtom/libtommath/bn_mp_init_set_int.c,v $ */
3589 /* $Revision: 1.3 $ */
3590 /* $Date: 2006/03/31 14:18:44 $ */
3592 /* End: bn_mp_init_set_int.c */
3594 /* Start: bn_mp_init_size.c */
3595 #include <tommath.h>
3596 #ifdef BN_MP_INIT_SIZE_C
3597 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3599 * LibTomMath is a library that provides multiple-precision
3600 * integer arithmetic as well as number theoretic functionality.
3602 * The library was designed directly after the MPI library by
3603 * Michael Fromberger but has been written from scratch with
3604 * additional optimizations in place.
3606 * The library is free for all purposes without any express
3607 * guarantee it works.
3609 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3612 /* init an mp_init for a given size */
3613 int mp_init_size (mp_int
* a
, int size
)
3617 /* pad size so there are always extra digits */
3618 size
+= (MP_PREC
* 2) - (size
% MP_PREC
);
3621 a
->dp
= OPT_CAST(mp_digit
) XMALLOC (sizeof (mp_digit
) * size
);
3622 if (a
->dp
== NULL
) {
3626 /* set the members */
3631 /* zero the digits */
3632 for (x
= 0; x
< size
; x
++) {
3640 /* $Source: /cvs/libtom/libtommath/bn_mp_init_size.c,v $ */
3641 /* $Revision: 1.3 $ */
3642 /* $Date: 2006/03/31 14:18:44 $ */
3644 /* End: bn_mp_init_size.c */
3646 /* Start: bn_mp_invmod.c */
3647 #include <tommath.h>
3648 #ifdef BN_MP_INVMOD_C
3649 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3651 * LibTomMath is a library that provides multiple-precision
3652 * integer arithmetic as well as number theoretic functionality.
3654 * The library was designed directly after the MPI library by
3655 * Michael Fromberger but has been written from scratch with
3656 * additional optimizations in place.
3658 * The library is free for all purposes without any express
3659 * guarantee it works.
3661 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3664 /* hac 14.61, pp608 */
3665 int mp_invmod (mp_int
* a
, mp_int
* b
, mp_int
* c
)
3667 /* b cannot be negative */
3668 if (b
->sign
== MP_NEG
|| mp_iszero(b
) == 1) {
3672 #ifdef BN_FAST_MP_INVMOD_C
3673 /* if the modulus is odd we can use a faster routine instead */
3674 if (mp_isodd (b
) == 1) {
3675 return fast_mp_invmod (a
, b
, c
);
3679 #ifdef BN_MP_INVMOD_SLOW_C
3680 return mp_invmod_slow(a
, b
, c
);
3687 /* $Source: /cvs/libtom/libtommath/bn_mp_invmod.c,v $ */
3688 /* $Revision: 1.3 $ */
3689 /* $Date: 2006/03/31 14:18:44 $ */
3691 /* End: bn_mp_invmod.c */
3693 /* Start: bn_mp_invmod_slow.c */
3694 #include <tommath.h>
3695 #ifdef BN_MP_INVMOD_SLOW_C
3696 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3698 * LibTomMath is a library that provides multiple-precision
3699 * integer arithmetic as well as number theoretic functionality.
3701 * The library was designed directly after the MPI library by
3702 * Michael Fromberger but has been written from scratch with
3703 * additional optimizations in place.
3705 * The library is free for all purposes without any express
3706 * guarantee it works.
3708 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3711 /* hac 14.61, pp608 */
3712 int mp_invmod_slow (mp_int
* a
, mp_int
* b
, mp_int
* c
)
3714 mp_int x
, y
, u
, v
, A
, B
, C
, D
;
3717 /* b cannot be negative */
3718 if (b
->sign
== MP_NEG
|| mp_iszero(b
) == 1) {
3723 if ((res
= mp_init_multi(&x
, &y
, &u
, &v
,
3724 &A
, &B
, &C
, &D
, NULL
)) != MP_OKAY
) {
3729 if ((res
= mp_mod(a
, b
, &x
)) != MP_OKAY
) {
3732 if ((res
= mp_copy (b
, &y
)) != MP_OKAY
) {
3736 /* 2. [modified] if x,y are both even then return an error! */
3737 if (mp_iseven (&x
) == 1 && mp_iseven (&y
) == 1) {
3742 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
3743 if ((res
= mp_copy (&x
, &u
)) != MP_OKAY
) {
3746 if ((res
= mp_copy (&y
, &v
)) != MP_OKAY
) {
3753 /* 4. while u is even do */
3754 while (mp_iseven (&u
) == 1) {
3756 if ((res
= mp_div_2 (&u
, &u
)) != MP_OKAY
) {
3759 /* 4.2 if A or B is odd then */
3760 if (mp_isodd (&A
) == 1 || mp_isodd (&B
) == 1) {
3761 /* A = (A+y)/2, B = (B-x)/2 */
3762 if ((res
= mp_add (&A
, &y
, &A
)) != MP_OKAY
) {
3765 if ((res
= mp_sub (&B
, &x
, &B
)) != MP_OKAY
) {
3769 /* A = A/2, B = B/2 */
3770 if ((res
= mp_div_2 (&A
, &A
)) != MP_OKAY
) {
3773 if ((res
= mp_div_2 (&B
, &B
)) != MP_OKAY
) {
3778 /* 5. while v is even do */
3779 while (mp_iseven (&v
) == 1) {
3781 if ((res
= mp_div_2 (&v
, &v
)) != MP_OKAY
) {
3784 /* 5.2 if C or D is odd then */
3785 if (mp_isodd (&C
) == 1 || mp_isodd (&D
) == 1) {
3786 /* C = (C+y)/2, D = (D-x)/2 */
3787 if ((res
= mp_add (&C
, &y
, &C
)) != MP_OKAY
) {
3790 if ((res
= mp_sub (&D
, &x
, &D
)) != MP_OKAY
) {
3794 /* C = C/2, D = D/2 */
3795 if ((res
= mp_div_2 (&C
, &C
)) != MP_OKAY
) {
3798 if ((res
= mp_div_2 (&D
, &D
)) != MP_OKAY
) {
3803 /* 6. if u >= v then */
3804 if (mp_cmp (&u
, &v
) != MP_LT
) {
3805 /* u = u - v, A = A - C, B = B - D */
3806 if ((res
= mp_sub (&u
, &v
, &u
)) != MP_OKAY
) {
3810 if ((res
= mp_sub (&A
, &C
, &A
)) != MP_OKAY
) {
3814 if ((res
= mp_sub (&B
, &D
, &B
)) != MP_OKAY
) {
3818 /* v - v - u, C = C - A, D = D - B */
3819 if ((res
= mp_sub (&v
, &u
, &v
)) != MP_OKAY
) {
3823 if ((res
= mp_sub (&C
, &A
, &C
)) != MP_OKAY
) {
3827 if ((res
= mp_sub (&D
, &B
, &D
)) != MP_OKAY
) {
3832 /* if not zero goto step 4 */
3833 if (mp_iszero (&u
) == 0)
3836 /* now a = C, b = D, gcd == g*v */
3838 /* if v != 1 then there is no inverse */
3839 if (mp_cmp_d (&v
, 1) != MP_EQ
) {
3844 /* if its too low */
3845 while (mp_cmp_d(&C
, 0) == MP_LT
) {
3846 if ((res
= mp_add(&C
, b
, &C
)) != MP_OKAY
) {
3852 while (mp_cmp_mag(&C
, b
) != MP_LT
) {
3853 if ((res
= mp_sub(&C
, b
, &C
)) != MP_OKAY
) {
3858 /* C is now the inverse */
3861 LBL_ERR
:mp_clear_multi (&x
, &y
, &u
, &v
, &A
, &B
, &C
, &D
, NULL
);
3866 /* $Source: /cvs/libtom/libtommath/bn_mp_invmod_slow.c,v $ */
3867 /* $Revision: 1.3 $ */
3868 /* $Date: 2006/03/31 14:18:44 $ */
3870 /* End: bn_mp_invmod_slow.c */
3872 /* Start: bn_mp_is_square.c */
3873 #include <tommath.h>
3874 #ifdef BN_MP_IS_SQUARE_C
3875 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3877 * LibTomMath is a library that provides multiple-precision
3878 * integer arithmetic as well as number theoretic functionality.
3880 * The library was designed directly after the MPI library by
3881 * Michael Fromberger but has been written from scratch with
3882 * additional optimizations in place.
3884 * The library is free for all purposes without any express
3885 * guarantee it works.
3887 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
3890 /* Check if remainders are possible squares - fast exclude non-squares */
3891 static const char rem_128
[128] = {
3892 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3893 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3894 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3895 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3896 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3897 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3898 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3899 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
3902 static const char rem_105
[105] = {
3903 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
3904 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
3905 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
3906 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
3907 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
3908 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
3909 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
3912 /* Store non-zero to ret if arg is square, and zero if not */
3913 int mp_is_square(mp_int
*arg
,int *ret
)
3920 /* Default to Non-square :) */
3923 if (arg
->sign
== MP_NEG
) {
3927 /* digits used? (TSD) */
3928 if (arg
->used
== 0) {
3932 /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
3933 if (rem_128
[127 & DIGIT(arg
,0)] == 1) {
3937 /* Next check mod 105 (3*5*7) */
3938 if ((res
= mp_mod_d(arg
,105,&c
)) != MP_OKAY
) {
3941 if (rem_105
[c
] == 1) {
3946 if ((res
= mp_init_set_int(&t
,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY
) {
3949 if ((res
= mp_mod(arg
,&t
,&t
)) != MP_OKAY
) {
3953 /* Check for other prime modules, note it's not an ERROR but we must
3954 * free "t" so the easiest way is to goto ERR. We know that res
3955 * is already equal to MP_OKAY from the mp_mod call
3957 if ( (1L<<(r
%11)) & 0x5C4L
) goto ERR
;
3958 if ( (1L<<(r
%13)) & 0x9E4L
) goto ERR
;
3959 if ( (1L<<(r
%17)) & 0x5CE8L
) goto ERR
;
3960 if ( (1L<<(r
%19)) & 0x4F50CL
) goto ERR
;
3961 if ( (1L<<(r
%23)) & 0x7ACCA0L
) goto ERR
;
3962 if ( (1L<<(r
%29)) & 0xC2EDD0CL
) goto ERR
;
3963 if ( (1L<<(r
%31)) & 0x6DE2B848L
) goto ERR
;
3965 /* Final check - is sqr(sqrt(arg)) == arg ? */
3966 if ((res
= mp_sqrt(arg
,&t
)) != MP_OKAY
) {
3969 if ((res
= mp_sqr(&t
,&t
)) != MP_OKAY
) {
3973 *ret
= (mp_cmp_mag(&t
,arg
) == MP_EQ
) ? MP_YES
: MP_NO
;
3979 /* $Source: /cvs/libtom/libtommath/bn_mp_is_square.c,v $ */
3980 /* $Revision: 1.3 $ */
3981 /* $Date: 2006/03/31 14:18:44 $ */
3983 /* End: bn_mp_is_square.c */
3985 /* Start: bn_mp_jacobi.c */
3986 #include <tommath.h>
3987 #ifdef BN_MP_JACOBI_C
3988 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3990 * LibTomMath is a library that provides multiple-precision
3991 * integer arithmetic as well as number theoretic functionality.
3993 * The library was designed directly after the MPI library by
3994 * Michael Fromberger but has been written from scratch with
3995 * additional optimizations in place.
3997 * The library is free for all purposes without any express
3998 * guarantee it works.
4000 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4003 /* computes the jacobi c = (a | n) (or Legendre if n is prime)
4004 * HAC pp. 73 Algorithm 2.149
4006 int mp_jacobi (mp_int
* a
, mp_int
* p
, int *c
)
4012 /* if p <= 0 return MP_VAL */
4013 if (mp_cmp_d(p
, 0) != MP_GT
) {
4017 /* step 1. if a == 0, return 0 */
4018 if (mp_iszero (a
) == 1) {
4023 /* step 2. if a == 1, return 1 */
4024 if (mp_cmp_d (a
, 1) == MP_EQ
) {
4032 /* step 3. write a = a1 * 2**k */
4033 if ((res
= mp_init_copy (&a1
, a
)) != MP_OKAY
) {
4037 if ((res
= mp_init (&p1
)) != MP_OKAY
) {
4041 /* divide out larger power of two */
4042 k
= mp_cnt_lsb(&a1
);
4043 if ((res
= mp_div_2d(&a1
, k
, &a1
, NULL
)) != MP_OKAY
) {
4047 /* step 4. if e is even set s=1 */
4051 /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
4052 residue
= p
->dp
[0] & 7;
4054 if (residue
== 1 || residue
== 7) {
4056 } else if (residue
== 3 || residue
== 5) {
4061 /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
4062 if ( ((p
->dp
[0] & 3) == 3) && ((a1
.dp
[0] & 3) == 3)) {
4066 /* if a1 == 1 we're done */
4067 if (mp_cmp_d (&a1
, 1) == MP_EQ
) {
4071 if ((res
= mp_mod (p
, &a1
, &p1
)) != MP_OKAY
) {
4074 if ((res
= mp_jacobi (&p1
, &a1
, &r
)) != MP_OKAY
) {
4082 LBL_P1
:mp_clear (&p1
);
4083 LBL_A1
:mp_clear (&a1
);
4088 /* $Source: /cvs/libtom/libtommath/bn_mp_jacobi.c,v $ */
4089 /* $Revision: 1.3 $ */
4090 /* $Date: 2006/03/31 14:18:44 $ */
4092 /* End: bn_mp_jacobi.c */
4094 /* Start: bn_mp_karatsuba_mul.c */
4095 #include <tommath.h>
4096 #ifdef BN_MP_KARATSUBA_MUL_C
4097 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4099 * LibTomMath is a library that provides multiple-precision
4100 * integer arithmetic as well as number theoretic functionality.
4102 * The library was designed directly after the MPI library by
4103 * Michael Fromberger but has been written from scratch with
4104 * additional optimizations in place.
4106 * The library is free for all purposes without any express
4107 * guarantee it works.
4109 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4112 /* c = |a| * |b| using Karatsuba Multiplication using
4113 * three half size multiplications
4115 * Let B represent the radix [e.g. 2**DIGIT_BIT] and
4116 * let n represent half of the number of digits in
4119 * a = a1 * B**n + a0
4120 * b = b1 * B**n + b0
4123 a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0
4125 * Note that a1b1 and a0b0 are used twice and only need to be
4126 * computed once. So in total three half size (half # of
4127 * digit) multiplications are performed, a0b0, a1b1 and
4130 * Note that a multiplication of half the digits requires
4131 * 1/4th the number of single precision multiplications so in
4132 * total after one call 25% of the single precision multiplications
4133 * are saved. Note also that the call to mp_mul can end up back
4134 * in this function if the a0, a1, b0, or b1 are above the threshold.
4135 * This is known as divide-and-conquer and leads to the famous
4136 * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than
4137 * the standard O(N**2) that the baseline/comba methods use.
4138 * Generally though the overhead of this method doesn't pay off
4139 * until a certain size (N ~ 80) is reached.
4141 int mp_karatsuba_mul (mp_int
* a
, mp_int
* b
, mp_int
* c
)
4143 mp_int x0
, x1
, y0
, y1
, t1
, x0y0
, x1y1
;
4146 /* default the return code to an error */
4149 /* min # of digits */
4150 B
= MIN (a
->used
, b
->used
);
4152 /* now divide in two */
4155 /* init copy all the temps */
4156 if (mp_init_size (&x0
, B
) != MP_OKAY
)
4158 if (mp_init_size (&x1
, a
->used
- B
) != MP_OKAY
)
4160 if (mp_init_size (&y0
, B
) != MP_OKAY
)
4162 if (mp_init_size (&y1
, b
->used
- B
) != MP_OKAY
)
4166 if (mp_init_size (&t1
, B
* 2) != MP_OKAY
)
4168 if (mp_init_size (&x0y0
, B
* 2) != MP_OKAY
)
4170 if (mp_init_size (&x1y1
, B
* 2) != MP_OKAY
)
4173 /* now shift the digits */
4174 x0
.used
= y0
.used
= B
;
4175 x1
.used
= a
->used
- B
;
4176 y1
.used
= b
->used
- B
;
4180 register mp_digit
*tmpa
, *tmpb
, *tmpx
, *tmpy
;
4182 /* we copy the digits directly instead of using higher level functions
4183 * since we also need to shift the digits
4190 for (x
= 0; x
< B
; x
++) {
4196 for (x
= B
; x
< a
->used
; x
++) {
4201 for (x
= B
; x
< b
->used
; x
++) {
4206 /* only need to clamp the lower words since by definition the
4207 * upper words x1/y1 must have a known number of digits
4212 /* now calc the products x0y0 and x1y1 */
4213 /* after this x0 is no longer required, free temp [x0==t2]! */
4214 if (mp_mul (&x0
, &y0
, &x0y0
) != MP_OKAY
)
4215 goto X1Y1
; /* x0y0 = x0*y0 */
4216 if (mp_mul (&x1
, &y1
, &x1y1
) != MP_OKAY
)
4217 goto X1Y1
; /* x1y1 = x1*y1 */
4219 /* now calc x1+x0 and y1+y0 */
4220 if (s_mp_add (&x1
, &x0
, &t1
) != MP_OKAY
)
4221 goto X1Y1
; /* t1 = x1 - x0 */
4222 if (s_mp_add (&y1
, &y0
, &x0
) != MP_OKAY
)
4223 goto X1Y1
; /* t2 = y1 - y0 */
4224 if (mp_mul (&t1
, &x0
, &t1
) != MP_OKAY
)
4225 goto X1Y1
; /* t1 = (x1 + x0) * (y1 + y0) */
4228 if (mp_add (&x0y0
, &x1y1
, &x0
) != MP_OKAY
)
4229 goto X1Y1
; /* t2 = x0y0 + x1y1 */
4230 if (s_mp_sub (&t1
, &x0
, &t1
) != MP_OKAY
)
4231 goto X1Y1
; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
4234 if (mp_lshd (&t1
, B
) != MP_OKAY
)
4235 goto X1Y1
; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
4236 if (mp_lshd (&x1y1
, B
* 2) != MP_OKAY
)
4237 goto X1Y1
; /* x1y1 = x1y1 << 2*B */
4239 if (mp_add (&x0y0
, &t1
, &t1
) != MP_OKAY
)
4240 goto X1Y1
; /* t1 = x0y0 + t1 */
4241 if (mp_add (&t1
, &x1y1
, c
) != MP_OKAY
)
4242 goto X1Y1
; /* t1 = x0y0 + t1 + x1y1 */
4244 /* Algorithm succeeded set the return code to MP_OKAY */
4247 X1Y1
:mp_clear (&x1y1
);
4248 X0Y0
:mp_clear (&x0y0
);
4259 /* $Source: /cvs/libtom/libtommath/bn_mp_karatsuba_mul.c,v $ */
4260 /* $Revision: 1.5 $ */
4261 /* $Date: 2006/03/31 14:18:44 $ */
4263 /* End: bn_mp_karatsuba_mul.c */
4265 /* Start: bn_mp_karatsuba_sqr.c */
4266 #include <tommath.h>
4267 #ifdef BN_MP_KARATSUBA_SQR_C
4268 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4270 * LibTomMath is a library that provides multiple-precision
4271 * integer arithmetic as well as number theoretic functionality.
4273 * The library was designed directly after the MPI library by
4274 * Michael Fromberger but has been written from scratch with
4275 * additional optimizations in place.
4277 * The library is free for all purposes without any express
4278 * guarantee it works.
4280 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4283 /* Karatsuba squaring, computes b = a*a using three
4284 * half size squarings
4286 * See comments of karatsuba_mul for details. It
4287 * is essentially the same algorithm but merely
4288 * tuned to perform recursive squarings.
4290 int mp_karatsuba_sqr (mp_int
* a
, mp_int
* b
)
4292 mp_int x0
, x1
, t1
, t2
, x0x0
, x1x1
;
4297 /* min # of digits */
4300 /* now divide in two */
4303 /* init copy all the temps */
4304 if (mp_init_size (&x0
, B
) != MP_OKAY
)
4306 if (mp_init_size (&x1
, a
->used
- B
) != MP_OKAY
)
4310 if (mp_init_size (&t1
, a
->used
* 2) != MP_OKAY
)
4312 if (mp_init_size (&t2
, a
->used
* 2) != MP_OKAY
)
4314 if (mp_init_size (&x0x0
, B
* 2) != MP_OKAY
)
4316 if (mp_init_size (&x1x1
, (a
->used
- B
) * 2) != MP_OKAY
)
4321 register mp_digit
*dst
, *src
;
4325 /* now shift the digits */
4327 for (x
= 0; x
< B
; x
++) {
4332 for (x
= B
; x
< a
->used
; x
++) {
4338 x1
.used
= a
->used
- B
;
4342 /* now calc the products x0*x0 and x1*x1 */
4343 if (mp_sqr (&x0
, &x0x0
) != MP_OKAY
)
4344 goto X1X1
; /* x0x0 = x0*x0 */
4345 if (mp_sqr (&x1
, &x1x1
) != MP_OKAY
)
4346 goto X1X1
; /* x1x1 = x1*x1 */
4348 /* now calc (x1+x0)**2 */
4349 if (s_mp_add (&x1
, &x0
, &t1
) != MP_OKAY
)
4350 goto X1X1
; /* t1 = x1 - x0 */
4351 if (mp_sqr (&t1
, &t1
) != MP_OKAY
)
4352 goto X1X1
; /* t1 = (x1 - x0) * (x1 - x0) */
4355 if (s_mp_add (&x0x0
, &x1x1
, &t2
) != MP_OKAY
)
4356 goto X1X1
; /* t2 = x0x0 + x1x1 */
4357 if (s_mp_sub (&t1
, &t2
, &t1
) != MP_OKAY
)
4358 goto X1X1
; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */
4361 if (mp_lshd (&t1
, B
) != MP_OKAY
)
4362 goto X1X1
; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
4363 if (mp_lshd (&x1x1
, B
* 2) != MP_OKAY
)
4364 goto X1X1
; /* x1x1 = x1x1 << 2*B */
4366 if (mp_add (&x0x0
, &t1
, &t1
) != MP_OKAY
)
4367 goto X1X1
; /* t1 = x0x0 + t1 */
4368 if (mp_add (&t1
, &x1x1
, b
) != MP_OKAY
)
4369 goto X1X1
; /* t1 = x0x0 + t1 + x1x1 */
4373 X1X1
:mp_clear (&x1x1
);
4374 X0X0
:mp_clear (&x0x0
);
4384 /* $Source: /cvs/libtom/libtommath/bn_mp_karatsuba_sqr.c,v $ */
4385 /* $Revision: 1.5 $ */
4386 /* $Date: 2006/03/31 14:18:44 $ */
4388 /* End: bn_mp_karatsuba_sqr.c */
4390 /* Start: bn_mp_lcm.c */
4391 #include <tommath.h>
4393 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4395 * LibTomMath is a library that provides multiple-precision
4396 * integer arithmetic as well as number theoretic functionality.
4398 * The library was designed directly after the MPI library by
4399 * Michael Fromberger but has been written from scratch with
4400 * additional optimizations in place.
4402 * The library is free for all purposes without any express
4403 * guarantee it works.
4405 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4408 /* computes least common multiple as |a*b|/(a, b) */
4409 int mp_lcm (mp_int
* a
, mp_int
* b
, mp_int
* c
)
4415 if ((res
= mp_init_multi (&t1
, &t2
, NULL
)) != MP_OKAY
) {
4419 /* t1 = get the GCD of the two inputs */
4420 if ((res
= mp_gcd (a
, b
, &t1
)) != MP_OKAY
) {
4424 /* divide the smallest by the GCD */
4425 if (mp_cmp_mag(a
, b
) == MP_LT
) {
4426 /* store quotient in t2 such that t2 * b is the LCM */
4427 if ((res
= mp_div(a
, &t1
, &t2
, NULL
)) != MP_OKAY
) {
4430 res
= mp_mul(b
, &t2
, c
);
4432 /* store quotient in t2 such that t2 * a is the LCM */
4433 if ((res
= mp_div(b
, &t1
, &t2
, NULL
)) != MP_OKAY
) {
4436 res
= mp_mul(a
, &t2
, c
);
4439 /* fix the sign to positive */
4443 mp_clear_multi (&t1
, &t2
, NULL
);
4448 /* $Source: /cvs/libtom/libtommath/bn_mp_lcm.c,v $ */
4449 /* $Revision: 1.3 $ */
4450 /* $Date: 2006/03/31 14:18:44 $ */
4452 /* End: bn_mp_lcm.c */
4454 /* Start: bn_mp_lshd.c */
4455 #include <tommath.h>
4457 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4459 * LibTomMath is a library that provides multiple-precision
4460 * integer arithmetic as well as number theoretic functionality.
4462 * The library was designed directly after the MPI library by
4463 * Michael Fromberger but has been written from scratch with
4464 * additional optimizations in place.
4466 * The library is free for all purposes without any express
4467 * guarantee it works.
4469 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4472 /* shift left a certain amount of digits */
4473 int mp_lshd (mp_int
* a
, int b
)
4477 /* if its less than zero return */
4482 /* grow to fit the new digits */
4483 if (a
->alloc
< a
->used
+ b
) {
4484 if ((res
= mp_grow (a
, a
->used
+ b
)) != MP_OKAY
) {
4490 register mp_digit
*top
, *bottom
;
4492 /* increment the used by the shift amount then copy upwards */
4496 top
= a
->dp
+ a
->used
- 1;
4499 bottom
= a
->dp
+ a
->used
- 1 - b
;
4501 /* much like mp_rshd this is implemented using a sliding window
4502 * except the window goes the otherway around. Copying from
4503 * the bottom to the top. see bn_mp_rshd.c for more info.
4505 for (x
= a
->used
- 1; x
>= b
; x
--) {
4509 /* zero the lower digits */
4511 for (x
= 0; x
< b
; x
++) {
4519 /* $Source: /cvs/libtom/libtommath/bn_mp_lshd.c,v $ */
4520 /* $Revision: 1.3 $ */
4521 /* $Date: 2006/03/31 14:18:44 $ */
4523 /* End: bn_mp_lshd.c */
4525 /* Start: bn_mp_mod.c */
4526 #include <tommath.h>
4528 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4530 * LibTomMath is a library that provides multiple-precision
4531 * integer arithmetic as well as number theoretic functionality.
4533 * The library was designed directly after the MPI library by
4534 * Michael Fromberger but has been written from scratch with
4535 * additional optimizations in place.
4537 * The library is free for all purposes without any express
4538 * guarantee it works.
4540 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4543 /* c = a mod b, 0 <= c < b */
4545 mp_mod (mp_int
* a
, mp_int
* b
, mp_int
* c
)
4550 if ((res
= mp_init (&t
)) != MP_OKAY
) {
4554 if ((res
= mp_div (a
, b
, NULL
, &t
)) != MP_OKAY
) {
4559 if (t
.sign
!= b
->sign
) {
4560 res
= mp_add (b
, &t
, c
);
4571 /* $Source: /cvs/libtom/libtommath/bn_mp_mod.c,v $ */
4572 /* $Revision: 1.3 $ */
4573 /* $Date: 2006/03/31 14:18:44 $ */
4575 /* End: bn_mp_mod.c */
4577 /* Start: bn_mp_mod_2d.c */
4578 #include <tommath.h>
4579 #ifdef BN_MP_MOD_2D_C
4580 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4582 * LibTomMath is a library that provides multiple-precision
4583 * integer arithmetic as well as number theoretic functionality.
4585 * The library was designed directly after the MPI library by
4586 * Michael Fromberger but has been written from scratch with
4587 * additional optimizations in place.
4589 * The library is free for all purposes without any express
4590 * guarantee it works.
4592 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4595 /* calc a value mod 2**b */
4597 mp_mod_2d (mp_int
* a
, int b
, mp_int
* c
)
4601 /* if b is <= 0 then zero the int */
4607 /* if the modulus is larger than the value than return */
4608 if (b
>= (int) (a
->used
* DIGIT_BIT
)) {
4609 res
= mp_copy (a
, c
);
4614 if ((res
= mp_copy (a
, c
)) != MP_OKAY
) {
4618 /* zero digits above the last digit of the modulus */
4619 for (x
= (b
/ DIGIT_BIT
) + ((b
% DIGIT_BIT
) == 0 ? 0 : 1); x
< c
->used
; x
++) {
4622 /* clear the digit that is not completely outside/inside the modulus */
4623 c
->dp
[b
/ DIGIT_BIT
] &=
4624 (mp_digit
) ((((mp_digit
) 1) << (((mp_digit
) b
) % DIGIT_BIT
)) - ((mp_digit
) 1));
4630 /* $Source: /cvs/libtom/libtommath/bn_mp_mod_2d.c,v $ */
4631 /* $Revision: 1.3 $ */
4632 /* $Date: 2006/03/31 14:18:44 $ */
4634 /* End: bn_mp_mod_2d.c */
4636 /* Start: bn_mp_mod_d.c */
4637 #include <tommath.h>
4638 #ifdef BN_MP_MOD_D_C
4639 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4641 * LibTomMath is a library that provides multiple-precision
4642 * integer arithmetic as well as number theoretic functionality.
4644 * The library was designed directly after the MPI library by
4645 * Michael Fromberger but has been written from scratch with
4646 * additional optimizations in place.
4648 * The library is free for all purposes without any express
4649 * guarantee it works.
4651 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4655 mp_mod_d (mp_int
* a
, mp_digit b
, mp_digit
* c
)
4657 return mp_div_d(a
, b
, NULL
, c
);
4661 /* $Source: /cvs/libtom/libtommath/bn_mp_mod_d.c,v $ */
4662 /* $Revision: 1.3 $ */
4663 /* $Date: 2006/03/31 14:18:44 $ */
4665 /* End: bn_mp_mod_d.c */
4667 /* Start: bn_mp_montgomery_calc_normalization.c */
4668 #include <tommath.h>
4669 #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
4670 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4672 * LibTomMath is a library that provides multiple-precision
4673 * integer arithmetic as well as number theoretic functionality.
4675 * The library was designed directly after the MPI library by
4676 * Michael Fromberger but has been written from scratch with
4677 * additional optimizations in place.
4679 * The library is free for all purposes without any express
4680 * guarantee it works.
4682 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4686 * shifts with subtractions when the result is greater than b.
4688 * The method is slightly modified to shift B unconditionally upto just under
4689 * the leading bit of b. This saves alot of multiple precision shifting.
4691 int mp_montgomery_calc_normalization (mp_int
* a
, mp_int
* b
)
4695 /* how many bits of last digit does b use */
4696 bits
= mp_count_bits (b
) % DIGIT_BIT
;
4699 if ((res
= mp_2expt (a
, (b
->used
- 1) * DIGIT_BIT
+ bits
- 1)) != MP_OKAY
) {
4708 /* now compute C = A * B mod b */
4709 for (x
= bits
- 1; x
< (int)DIGIT_BIT
; x
++) {
4710 if ((res
= mp_mul_2 (a
, a
)) != MP_OKAY
) {
4713 if (mp_cmp_mag (a
, b
) != MP_LT
) {
4714 if ((res
= s_mp_sub (a
, b
, a
)) != MP_OKAY
) {
4724 /* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_calc_normalization.c,v $ */
4725 /* $Revision: 1.3 $ */
4726 /* $Date: 2006/03/31 14:18:44 $ */
4728 /* End: bn_mp_montgomery_calc_normalization.c */
4730 /* Start: bn_mp_montgomery_reduce.c */
4731 #include <tommath.h>
4732 #ifdef BN_MP_MONTGOMERY_REDUCE_C
4733 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4735 * LibTomMath is a library that provides multiple-precision
4736 * integer arithmetic as well as number theoretic functionality.
4738 * The library was designed directly after the MPI library by
4739 * Michael Fromberger but has been written from scratch with
4740 * additional optimizations in place.
4742 * The library is free for all purposes without any express
4743 * guarantee it works.
4745 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4748 /* computes xR**-1 == x (mod N) via Montgomery Reduction */
4750 mp_montgomery_reduce (mp_int
* x
, mp_int
* n
, mp_digit rho
)
4755 /* can the fast reduction [comba] method be used?
4757 * Note that unlike in mul you're safely allowed *less*
4758 * than the available columns [255 per default] since carries
4759 * are fixed up in the inner loop.
4761 digs
= n
->used
* 2 + 1;
4762 if ((digs
< MP_WARRAY
) &&
4764 (1 << ((CHAR_BIT
* sizeof (mp_word
)) - (2 * DIGIT_BIT
)))) {
4765 return fast_mp_montgomery_reduce (x
, n
, rho
);
4768 /* grow the input as required */
4769 if (x
->alloc
< digs
) {
4770 if ((res
= mp_grow (x
, digs
)) != MP_OKAY
) {
4776 for (ix
= 0; ix
< n
->used
; ix
++) {
4777 /* mu = ai * rho mod b
4779 * The value of rho must be precalculated via
4780 * montgomery_setup() such that
4781 * it equals -1/n0 mod b this allows the
4782 * following inner loop to reduce the
4783 * input one digit at a time
4785 mu
= (mp_digit
) (((mp_word
)x
->dp
[ix
]) * ((mp_word
)rho
) & MP_MASK
);
4787 /* a = a + mu * m * b**i */
4790 register mp_digit
*tmpn
, *tmpx
, u
;
4793 /* alias for digits of the modulus */
4796 /* alias for the digits of x [the input] */
4799 /* set the carry to zero */
4802 /* Multiply and add in place */
4803 for (iy
= 0; iy
< n
->used
; iy
++) {
4804 /* compute product and sum */
4805 r
= ((mp_word
)mu
) * ((mp_word
)*tmpn
++) +
4806 ((mp_word
) u
) + ((mp_word
) * tmpx
);
4809 u
= (mp_digit
)(r
>> ((mp_word
) DIGIT_BIT
));
4812 *tmpx
++ = (mp_digit
)(r
& ((mp_word
) MP_MASK
));
4814 /* At this point the ix'th digit of x should be zero */
4817 /* propagate carries upwards as required*/
4820 u
= *tmpx
>> DIGIT_BIT
;
4826 /* at this point the n.used'th least
4827 * significant digits of x are all zero
4828 * which means we can shift x to the
4829 * right by n.used digits and the
4830 * residue is unchanged.
4833 /* x = x/b**n.used */
4835 mp_rshd (x
, n
->used
);
4837 /* if x >= n then x = x - n */
4838 if (mp_cmp_mag (x
, n
) != MP_LT
) {
4839 return s_mp_sub (x
, n
, x
);
4846 /* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_reduce.c,v $ */
4847 /* $Revision: 1.3 $ */
4848 /* $Date: 2006/03/31 14:18:44 $ */
4850 /* End: bn_mp_montgomery_reduce.c */
4852 /* Start: bn_mp_montgomery_setup.c */
4853 #include <tommath.h>
4854 #ifdef BN_MP_MONTGOMERY_SETUP_C
4855 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4857 * LibTomMath is a library that provides multiple-precision
4858 * integer arithmetic as well as number theoretic functionality.
4860 * The library was designed directly after the MPI library by
4861 * Michael Fromberger but has been written from scratch with
4862 * additional optimizations in place.
4864 * The library is free for all purposes without any express
4865 * guarantee it works.
4867 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4870 /* setups the montgomery reduction stuff */
4872 mp_montgomery_setup (mp_int
* n
, mp_digit
* rho
)
4876 /* fast inversion mod 2**k
4878 * Based on the fact that
4880 * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
4881 * => 2*X*A - X*X*A*A = 1
4882 * => 2*(1) - (1) = 1
4890 x
= (((b
+ 2) & 4) << 1) + b
; /* here x*a==1 mod 2**4 */
4891 x
*= 2 - b
* x
; /* here x*a==1 mod 2**8 */
4892 #if !defined(MP_8BIT)
4893 x
*= 2 - b
* x
; /* here x*a==1 mod 2**16 */
4895 #if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
4896 x
*= 2 - b
* x
; /* here x*a==1 mod 2**32 */
4899 x
*= 2 - b
* x
; /* here x*a==1 mod 2**64 */
4902 /* rho = -1/m mod b */
4903 *rho
= (unsigned long)(((mp_word
)1 << ((mp_word
) DIGIT_BIT
)) - x
) & MP_MASK
;
4909 /* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_setup.c,v $ */
4910 /* $Revision: 1.4 $ */
4911 /* $Date: 2006/12/04 21:34:03 $ */
4913 /* End: bn_mp_montgomery_setup.c */
4915 /* Start: bn_mp_mul.c */
4916 #include <tommath.h>
4918 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4920 * LibTomMath is a library that provides multiple-precision
4921 * integer arithmetic as well as number theoretic functionality.
4923 * The library was designed directly after the MPI library by
4924 * Michael Fromberger but has been written from scratch with
4925 * additional optimizations in place.
4927 * The library is free for all purposes without any express
4928 * guarantee it works.
4930 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
4933 /* high level multiplication (handles sign) */
4934 int mp_mul (mp_int
* a
, mp_int
* b
, mp_int
* c
)
4937 neg
= (a
->sign
== b
->sign
) ? MP_ZPOS
: MP_NEG
;
4939 /* use Toom-Cook? */
4940 #ifdef BN_MP_TOOM_MUL_C
4941 if (MIN (a
->used
, b
->used
) >= TOOM_MUL_CUTOFF
) {
4942 res
= mp_toom_mul(a
, b
, c
);
4945 #ifdef BN_MP_KARATSUBA_MUL_C
4946 /* use Karatsuba? */
4947 if (MIN (a
->used
, b
->used
) >= KARATSUBA_MUL_CUTOFF
) {
4948 res
= mp_karatsuba_mul (a
, b
, c
);
4952 /* can we use the fast multiplier?
4954 * The fast multiplier can be used if the output will
4955 * have less than MP_WARRAY digits and the number of
4956 * digits won't affect carry propagation
4958 int digs
= a
->used
+ b
->used
+ 1;
4960 #ifdef BN_FAST_S_MP_MUL_DIGS_C
4961 if ((digs
< MP_WARRAY
) &&
4962 MIN(a
->used
, b
->used
) <=
4963 (1 << ((CHAR_BIT
* sizeof (mp_word
)) - (2 * DIGIT_BIT
)))) {
4964 res
= fast_s_mp_mul_digs (a
, b
, c
, digs
);
4967 #ifdef BN_S_MP_MUL_DIGS_C
4968 res
= s_mp_mul (a
, b
, c
); /* uses s_mp_mul_digs */
4974 c
->sign
= (c
->used
> 0) ? neg
: MP_ZPOS
;
4979 /* $Source: /cvs/libtom/libtommath/bn_mp_mul.c,v $ */
4980 /* $Revision: 1.3 $ */
4981 /* $Date: 2006/03/31 14:18:44 $ */
4983 /* End: bn_mp_mul.c */
4985 /* Start: bn_mp_mul_2.c */
4986 #include <tommath.h>
4987 #ifdef BN_MP_MUL_2_C
4988 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4990 * LibTomMath is a library that provides multiple-precision
4991 * integer arithmetic as well as number theoretic functionality.
4993 * The library was designed directly after the MPI library by
4994 * Michael Fromberger but has been written from scratch with
4995 * additional optimizations in place.
4997 * The library is free for all purposes without any express
4998 * guarantee it works.
5000 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5004 int mp_mul_2(mp_int
* a
, mp_int
* b
)
5006 int x
, res
, oldused
;
5008 /* grow to accomodate result */
5009 if (b
->alloc
< a
->used
+ 1) {
5010 if ((res
= mp_grow (b
, a
->used
+ 1)) != MP_OKAY
) {
5019 register mp_digit r
, rr
, *tmpa
, *tmpb
;
5021 /* alias for source */
5024 /* alias for dest */
5029 for (x
= 0; x
< a
->used
; x
++) {
5031 /* get what will be the *next* carry bit from the
5032 * MSB of the current digit
5034 rr
= *tmpa
>> ((mp_digit
)(DIGIT_BIT
- 1));
5036 /* now shift up this digit, add in the carry [from the previous] */
5037 *tmpb
++ = ((*tmpa
++ << ((mp_digit
)1)) | r
) & MP_MASK
;
5039 /* copy the carry that would be from the source
5040 * digit into the next iteration
5045 /* new leading digit? */
5047 /* add a MSB which is always 1 at this point */
5052 /* now zero any excess digits on the destination
5053 * that we didn't write to
5055 tmpb
= b
->dp
+ b
->used
;
5056 for (x
= b
->used
; x
< oldused
; x
++) {
5065 /* $Source: /cvs/libtom/libtommath/bn_mp_mul_2.c,v $ */
5066 /* $Revision: 1.3 $ */
5067 /* $Date: 2006/03/31 14:18:44 $ */
5069 /* End: bn_mp_mul_2.c */
5071 /* Start: bn_mp_mul_2d.c */
5072 #include <tommath.h>
5073 #ifdef BN_MP_MUL_2D_C
5074 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5076 * LibTomMath is a library that provides multiple-precision
5077 * integer arithmetic as well as number theoretic functionality.
5079 * The library was designed directly after the MPI library by
5080 * Michael Fromberger but has been written from scratch with
5081 * additional optimizations in place.
5083 * The library is free for all purposes without any express
5084 * guarantee it works.
5086 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5089 /* shift left by a certain bit count */
5090 int mp_mul_2d (mp_int
* a
, int b
, mp_int
* c
)
5097 if ((res
= mp_copy (a
, c
)) != MP_OKAY
) {
5102 if (c
->alloc
< (int)(c
->used
+ b
/DIGIT_BIT
+ 1)) {
5103 if ((res
= mp_grow (c
, c
->used
+ b
/ DIGIT_BIT
+ 1)) != MP_OKAY
) {
5108 /* shift by as many digits in the bit count */
5109 if (b
>= (int)DIGIT_BIT
) {
5110 if ((res
= mp_lshd (c
, b
/ DIGIT_BIT
)) != MP_OKAY
) {
5115 /* shift any bit count < DIGIT_BIT */
5116 d
= (mp_digit
) (b
% DIGIT_BIT
);
5118 register mp_digit
*tmpc
, shift
, mask
, r
, rr
;
5121 /* bitmask for carries */
5122 mask
= (((mp_digit
)1) << d
) - 1;
5124 /* shift for msbs */
5125 shift
= DIGIT_BIT
- d
;
5132 for (x
= 0; x
< c
->used
; x
++) {
5133 /* get the higher bits of the current word */
5134 rr
= (*tmpc
>> shift
) & mask
;
5136 /* shift the current word and OR in the carry */
5137 *tmpc
= ((*tmpc
<< d
) | r
) & MP_MASK
;
5140 /* set the carry to the carry bits of the current word */
5144 /* set final carry */
5146 c
->dp
[(c
->used
)++] = r
;
5154 /* $Source: /cvs/libtom/libtommath/bn_mp_mul_2d.c,v $ */
5155 /* $Revision: 1.3 $ */
5156 /* $Date: 2006/03/31 14:18:44 $ */
5158 /* End: bn_mp_mul_2d.c */
5160 /* Start: bn_mp_mul_d.c */
5161 #include <tommath.h>
5162 #ifdef BN_MP_MUL_D_C
5163 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5165 * LibTomMath is a library that provides multiple-precision
5166 * integer arithmetic as well as number theoretic functionality.
5168 * The library was designed directly after the MPI library by
5169 * Michael Fromberger but has been written from scratch with
5170 * additional optimizations in place.
5172 * The library is free for all purposes without any express
5173 * guarantee it works.
5175 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5178 /* multiply by a digit */
5180 mp_mul_d (mp_int
* a
, mp_digit b
, mp_int
* c
)
5182 mp_digit u
, *tmpa
, *tmpc
;
5184 int ix
, res
, olduse
;
5186 /* make sure c is big enough to hold a*b */
5187 if (c
->alloc
< a
->used
+ 1) {
5188 if ((res
= mp_grow (c
, a
->used
+ 1)) != MP_OKAY
) {
5193 /* get the original destinations used count */
5199 /* alias for a->dp [source] */
5202 /* alias for c->dp [dest] */
5208 /* compute columns */
5209 for (ix
= 0; ix
< a
->used
; ix
++) {
5210 /* compute product and carry sum for this term */
5211 r
= ((mp_word
) u
) + ((mp_word
)*tmpa
++) * ((mp_word
)b
);
5213 /* mask off higher bits to get a single digit */
5214 *tmpc
++ = (mp_digit
) (r
& ((mp_word
) MP_MASK
));
5216 /* send carry into next iteration */
5217 u
= (mp_digit
) (r
>> ((mp_word
) DIGIT_BIT
));
5220 /* store final carry [if any] and increment ix offset */
5224 /* now zero digits above the top */
5225 while (ix
++ < olduse
) {
5229 /* set used count */
5230 c
->used
= a
->used
+ 1;
5237 /* $Source: /cvs/libtom/libtommath/bn_mp_mul_d.c,v $ */
5238 /* $Revision: 1.3 $ */
5239 /* $Date: 2006/03/31 14:18:44 $ */
5241 /* End: bn_mp_mul_d.c */
5243 /* Start: bn_mp_mulmod.c */
5244 #include <tommath.h>
5245 #ifdef BN_MP_MULMOD_C
5246 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5248 * LibTomMath is a library that provides multiple-precision
5249 * integer arithmetic as well as number theoretic functionality.
5251 * The library was designed directly after the MPI library by
5252 * Michael Fromberger but has been written from scratch with
5253 * additional optimizations in place.
5255 * The library is free for all purposes without any express
5256 * guarantee it works.
5258 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5261 /* d = a * b (mod c) */
5262 int mp_mulmod (mp_int
* a
, mp_int
* b
, mp_int
* c
, mp_int
* d
)
5267 if ((res
= mp_init (&t
)) != MP_OKAY
) {
5271 if ((res
= mp_mul (a
, b
, &t
)) != MP_OKAY
) {
5275 res
= mp_mod (&t
, c
, d
);
5281 /* $Source: /cvs/libtom/libtommath/bn_mp_mulmod.c,v $ */
5282 /* $Revision: 1.4 $ */
5283 /* $Date: 2006/03/31 14:18:44 $ */
5285 /* End: bn_mp_mulmod.c */
5287 /* Start: bn_mp_n_root.c */
5288 #include <tommath.h>
5289 #ifdef BN_MP_N_ROOT_C
5290 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5292 * LibTomMath is a library that provides multiple-precision
5293 * integer arithmetic as well as number theoretic functionality.
5295 * The library was designed directly after the MPI library by
5296 * Michael Fromberger but has been written from scratch with
5297 * additional optimizations in place.
5299 * The library is free for all purposes without any express
5300 * guarantee it works.
5302 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5305 /* find the n'th root of an integer
5307 * Result found such that (c)**b <= a and (c+1)**b > a
5309 * This algorithm uses Newton's approximation
5310 * x[i+1] = x[i] - f(x[i])/f'(x[i])
5311 * which will find the root in log(N) time where
5312 * each step involves a fair bit. This is not meant to
5313 * find huge roots [square and cube, etc].
5315 int mp_n_root (mp_int
* a
, mp_digit b
, mp_int
* c
)
5320 /* input must be positive if b is even */
5321 if ((b
& 1) == 0 && a
->sign
== MP_NEG
) {
5325 if ((res
= mp_init (&t1
)) != MP_OKAY
) {
5329 if ((res
= mp_init (&t2
)) != MP_OKAY
) {
5333 if ((res
= mp_init (&t3
)) != MP_OKAY
) {
5337 /* if a is negative fudge the sign but keep track */
5346 if ((res
= mp_copy (&t2
, &t1
)) != MP_OKAY
) {
5350 /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
5352 /* t3 = t1**(b-1) */
5353 if ((res
= mp_expt_d (&t1
, b
- 1, &t3
)) != MP_OKAY
) {
5359 if ((res
= mp_mul (&t3
, &t1
, &t2
)) != MP_OKAY
) {
5363 /* t2 = t1**b - a */
5364 if ((res
= mp_sub (&t2
, a
, &t2
)) != MP_OKAY
) {
5369 /* t3 = t1**(b-1) * b */
5370 if ((res
= mp_mul_d (&t3
, b
, &t3
)) != MP_OKAY
) {
5374 /* t3 = (t1**b - a)/(b * t1**(b-1)) */
5375 if ((res
= mp_div (&t2
, &t3
, &t3
, NULL
)) != MP_OKAY
) {
5379 if ((res
= mp_sub (&t1
, &t3
, &t2
)) != MP_OKAY
) {
5382 } while (mp_cmp (&t1
, &t2
) != MP_EQ
);
5384 /* result can be off by a few so check */
5386 if ((res
= mp_expt_d (&t1
, b
, &t2
)) != MP_OKAY
) {
5390 if (mp_cmp (&t2
, a
) == MP_GT
) {
5391 if ((res
= mp_sub_d (&t1
, 1, &t1
)) != MP_OKAY
) {
5399 /* reset the sign of a first */
5402 /* set the result */
5405 /* set the sign of the result */
5410 LBL_T3
:mp_clear (&t3
);
5411 LBL_T2
:mp_clear (&t2
);
5412 LBL_T1
:mp_clear (&t1
);
5417 /* $Source: /cvs/libtom/libtommath/bn_mp_n_root.c,v $ */
5418 /* $Revision: 1.3 $ */
5419 /* $Date: 2006/03/31 14:18:44 $ */
5421 /* End: bn_mp_n_root.c */
5423 /* Start: bn_mp_neg.c */
5424 #include <tommath.h>
5426 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5428 * LibTomMath is a library that provides multiple-precision
5429 * integer arithmetic as well as number theoretic functionality.
5431 * The library was designed directly after the MPI library by
5432 * Michael Fromberger but has been written from scratch with
5433 * additional optimizations in place.
5435 * The library is free for all purposes without any express
5436 * guarantee it works.
5438 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5442 int mp_neg (mp_int
* a
, mp_int
* b
)
5446 if ((res
= mp_copy (a
, b
)) != MP_OKAY
) {
5451 if (mp_iszero(b
) != MP_YES
) {
5452 b
->sign
= (a
->sign
== MP_ZPOS
) ? MP_NEG
: MP_ZPOS
;
5461 /* $Source: /cvs/libtom/libtommath/bn_mp_neg.c,v $ */
5462 /* $Revision: 1.3 $ */
5463 /* $Date: 2006/03/31 14:18:44 $ */
5465 /* End: bn_mp_neg.c */
5467 /* Start: bn_mp_or.c */
5468 #include <tommath.h>
5470 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5472 * LibTomMath is a library that provides multiple-precision
5473 * integer arithmetic as well as number theoretic functionality.
5475 * The library was designed directly after the MPI library by
5476 * Michael Fromberger but has been written from scratch with
5477 * additional optimizations in place.
5479 * The library is free for all purposes without any express
5480 * guarantee it works.
5482 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5485 /* OR two ints together */
5486 int mp_or (mp_int
* a
, mp_int
* b
, mp_int
* c
)
5491 if (a
->used
> b
->used
) {
5492 if ((res
= mp_init_copy (&t
, a
)) != MP_OKAY
) {
5498 if ((res
= mp_init_copy (&t
, b
)) != MP_OKAY
) {
5505 for (ix
= 0; ix
< px
; ix
++) {
5506 t
.dp
[ix
] |= x
->dp
[ix
];
5515 /* $Source: /cvs/libtom/libtommath/bn_mp_or.c,v $ */
5516 /* $Revision: 1.3 $ */
5517 /* $Date: 2006/03/31 14:18:44 $ */
5519 /* End: bn_mp_or.c */
5521 /* Start: bn_mp_prime_fermat.c */
5522 #include <tommath.h>
5523 #ifdef BN_MP_PRIME_FERMAT_C
5524 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5526 * LibTomMath is a library that provides multiple-precision
5527 * integer arithmetic as well as number theoretic functionality.
5529 * The library was designed directly after the MPI library by
5530 * Michael Fromberger but has been written from scratch with
5531 * additional optimizations in place.
5533 * The library is free for all purposes without any express
5534 * guarantee it works.
5536 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5539 /* performs one Fermat test.
5541 * If "a" were prime then b**a == b (mod a) since the order of
5542 * the multiplicative sub-group would be phi(a) = a-1. That means
5543 * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
5545 * Sets result to 1 if the congruence holds, or zero otherwise.
5547 int mp_prime_fermat (mp_int
* a
, mp_int
* b
, int *result
)
5552 /* default to composite */
5556 if (mp_cmp_d(b
, 1) != MP_GT
) {
5561 if ((err
= mp_init (&t
)) != MP_OKAY
) {
5565 /* compute t = b**a mod a */
5566 if ((err
= mp_exptmod (b
, a
, a
, &t
)) != MP_OKAY
) {
5570 /* is it equal to b? */
5571 if (mp_cmp (&t
, b
) == MP_EQ
) {
5576 LBL_T
:mp_clear (&t
);
5581 /* $Source: /cvs/libtom/libtommath/bn_mp_prime_fermat.c,v $ */
5582 /* $Revision: 1.3 $ */
5583 /* $Date: 2006/03/31 14:18:44 $ */
5585 /* End: bn_mp_prime_fermat.c */
5587 /* Start: bn_mp_prime_is_divisible.c */
5588 #include <tommath.h>
5589 #ifdef BN_MP_PRIME_IS_DIVISIBLE_C
5590 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5592 * LibTomMath is a library that provides multiple-precision
5593 * integer arithmetic as well as number theoretic functionality.
5595 * The library was designed directly after the MPI library by
5596 * Michael Fromberger but has been written from scratch with
5597 * additional optimizations in place.
5599 * The library is free for all purposes without any express
5600 * guarantee it works.
5602 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5605 /* determines if an integers is divisible by one
5606 * of the first PRIME_SIZE primes or not
5608 * sets result to 0 if not, 1 if yes
5610 int mp_prime_is_divisible (mp_int
* a
, int *result
)
5615 /* default to not */
5618 for (ix
= 0; ix
< PRIME_SIZE
; ix
++) {
5619 /* what is a mod LBL_prime_tab[ix] */
5620 if ((err
= mp_mod_d (a
, ltm_prime_tab
[ix
], &res
)) != MP_OKAY
) {
5624 /* is the residue zero? */
5635 /* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_divisible.c,v $ */
5636 /* $Revision: 1.3 $ */
5637 /* $Date: 2006/03/31 14:18:44 $ */
5639 /* End: bn_mp_prime_is_divisible.c */
5641 /* Start: bn_mp_prime_is_prime.c */
5642 #include <tommath.h>
5643 #ifdef BN_MP_PRIME_IS_PRIME_C
5644 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5646 * LibTomMath is a library that provides multiple-precision
5647 * integer arithmetic as well as number theoretic functionality.
5649 * The library was designed directly after the MPI library by
5650 * Michael Fromberger but has been written from scratch with
5651 * additional optimizations in place.
5653 * The library is free for all purposes without any express
5654 * guarantee it works.
5656 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5659 /* performs a variable number of rounds of Miller-Rabin
5661 * Probability of error after t rounds is no more than
5664 * Sets result to 1 if probably prime, 0 otherwise
5666 int mp_prime_is_prime (mp_int
* a
, int t
, int *result
)
5674 /* valid value of t? */
5675 if (t
<= 0 || t
> PRIME_SIZE
) {
5679 /* is the input equal to one of the primes in the table? */
5680 for (ix
= 0; ix
< PRIME_SIZE
; ix
++) {
5681 if (mp_cmp_d(a
, ltm_prime_tab
[ix
]) == MP_EQ
) {
5687 /* first perform trial division */
5688 if ((err
= mp_prime_is_divisible (a
, &res
)) != MP_OKAY
) {
5692 /* return if it was trivially divisible */
5693 if (res
== MP_YES
) {
5697 /* now perform the miller-rabin rounds */
5698 if ((err
= mp_init (&b
)) != MP_OKAY
) {
5702 for (ix
= 0; ix
< t
; ix
++) {
5704 mp_set (&b
, ltm_prime_tab
[ix
]);
5706 if ((err
= mp_prime_miller_rabin (a
, &b
, &res
)) != MP_OKAY
) {
5715 /* passed the test */
5717 LBL_B
:mp_clear (&b
);
5722 /* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_prime.c,v $ */
5723 /* $Revision: 1.3 $ */
5724 /* $Date: 2006/03/31 14:18:44 $ */
5726 /* End: bn_mp_prime_is_prime.c */
5728 /* Start: bn_mp_prime_miller_rabin.c */
5729 #include <tommath.h>
5730 #ifdef BN_MP_PRIME_MILLER_RABIN_C
5731 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5733 * LibTomMath is a library that provides multiple-precision
5734 * integer arithmetic as well as number theoretic functionality.
5736 * The library was designed directly after the MPI library by
5737 * Michael Fromberger but has been written from scratch with
5738 * additional optimizations in place.
5740 * The library is free for all purposes without any express
5741 * guarantee it works.
5743 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5746 /* Miller-Rabin test of "a" to the base of "b" as described in
5747 * HAC pp. 139 Algorithm 4.24
5749 * Sets result to 0 if definitely composite or 1 if probably prime.
5750 * Randomly the chance of error is no more than 1/4 and often
5753 int mp_prime_miller_rabin (mp_int
* a
, mp_int
* b
, int *result
)
5762 if (mp_cmp_d(b
, 1) != MP_GT
) {
5766 /* get n1 = a - 1 */
5767 if ((err
= mp_init_copy (&n1
, a
)) != MP_OKAY
) {
5770 if ((err
= mp_sub_d (&n1
, 1, &n1
)) != MP_OKAY
) {
5774 /* set 2**s * r = n1 */
5775 if ((err
= mp_init_copy (&r
, &n1
)) != MP_OKAY
) {
5779 /* count the number of least significant bits
5784 /* now divide n - 1 by 2**s */
5785 if ((err
= mp_div_2d (&r
, s
, &r
, NULL
)) != MP_OKAY
) {
5789 /* compute y = b**r mod a */
5790 if ((err
= mp_init (&y
)) != MP_OKAY
) {
5793 if ((err
= mp_exptmod (b
, &r
, a
, &y
)) != MP_OKAY
) {
5797 /* if y != 1 and y != n1 do */
5798 if (mp_cmp_d (&y
, 1) != MP_EQ
&& mp_cmp (&y
, &n1
) != MP_EQ
) {
5800 /* while j <= s-1 and y != n1 */
5801 while ((j
<= (s
- 1)) && mp_cmp (&y
, &n1
) != MP_EQ
) {
5802 if ((err
= mp_sqrmod (&y
, a
, &y
)) != MP_OKAY
) {
5806 /* if y == 1 then composite */
5807 if (mp_cmp_d (&y
, 1) == MP_EQ
) {
5814 /* if y != n1 then composite */
5815 if (mp_cmp (&y
, &n1
) != MP_EQ
) {
5820 /* probably prime now */
5822 LBL_Y
:mp_clear (&y
);
5823 LBL_R
:mp_clear (&r
);
5824 LBL_N1
:mp_clear (&n1
);
5829 /* $Source: /cvs/libtom/libtommath/bn_mp_prime_miller_rabin.c,v $ */
5830 /* $Revision: 1.3 $ */
5831 /* $Date: 2006/03/31 14:18:44 $ */
5833 /* End: bn_mp_prime_miller_rabin.c */
5835 /* Start: bn_mp_prime_next_prime.c */
5836 #include <tommath.h>
5837 #ifdef BN_MP_PRIME_NEXT_PRIME_C
5838 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5840 * LibTomMath is a library that provides multiple-precision
5841 * integer arithmetic as well as number theoretic functionality.
5843 * The library was designed directly after the MPI library by
5844 * Michael Fromberger but has been written from scratch with
5845 * additional optimizations in place.
5847 * The library is free for all purposes without any express
5848 * guarantee it works.
5850 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
5853 /* finds the next prime after the number "a" using "t" trials
5856 * bbs_style = 1 means the prime must be congruent to 3 mod 4
5858 int mp_prime_next_prime(mp_int
*a
, int t
, int bbs_style
)
5861 mp_digit res_tab
[PRIME_SIZE
], step
, kstep
;
5864 /* ensure t is valid */
5865 if (t
<= 0 || t
> PRIME_SIZE
) {
5869 /* force positive */
5872 /* simple algo if a is less than the largest prime in the table */
5873 if (mp_cmp_d(a
, ltm_prime_tab
[PRIME_SIZE
-1]) == MP_LT
) {
5874 /* find which prime it is bigger than */
5875 for (x
= PRIME_SIZE
- 2; x
>= 0; x
--) {
5876 if (mp_cmp_d(a
, ltm_prime_tab
[x
]) != MP_LT
) {
5877 if (bbs_style
== 1) {
5878 /* ok we found a prime smaller or
5879 * equal [so the next is larger]
5881 * however, the prime must be
5882 * congruent to 3 mod 4
5884 if ((ltm_prime_tab
[x
+ 1] & 3) != 3) {
5885 /* scan upwards for a prime congruent to 3 mod 4 */
5886 for (y
= x
+ 1; y
< PRIME_SIZE
; y
++) {
5887 if ((ltm_prime_tab
[y
] & 3) == 3) {
5888 mp_set(a
, ltm_prime_tab
[y
]);
5894 mp_set(a
, ltm_prime_tab
[x
+ 1]);
5899 /* at this point a maybe 1 */
5900 if (mp_cmp_d(a
, 1) == MP_EQ
) {
5904 /* fall through to the sieve */
5907 /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
5908 if (bbs_style
== 1) {
5914 /* at this point we will use a combination of a sieve and Miller-Rabin */
5916 if (bbs_style
== 1) {
5917 /* if a mod 4 != 3 subtract the correct value to make it so */
5918 if ((a
->dp
[0] & 3) != 3) {
5919 if ((err
= mp_sub_d(a
, (a
->dp
[0] & 3) + 1, a
)) != MP_OKAY
) { return err
; };
5922 if (mp_iseven(a
) == 1) {
5924 if ((err
= mp_sub_d(a
, 1, a
)) != MP_OKAY
) {
5930 /* generate the restable */
5931 for (x
= 1; x
< PRIME_SIZE
; x
++) {
5932 if ((err
= mp_mod_d(a
, ltm_prime_tab
[x
], res_tab
+ x
)) != MP_OKAY
) {
5937 /* init temp used for Miller-Rabin Testing */
5938 if ((err
= mp_init(&b
)) != MP_OKAY
) {
5943 /* skip to the next non-trivially divisible candidate */
5946 /* y == 1 if any residue was zero [e.g. cannot be prime] */
5949 /* increase step to next candidate */
5952 /* compute the new residue without using division */
5953 for (x
= 1; x
< PRIME_SIZE
; x
++) {
5954 /* add the step to each residue */
5955 res_tab
[x
] += kstep
;
5957 /* subtract the modulus [instead of using division] */
5958 if (res_tab
[x
] >= ltm_prime_tab
[x
]) {
5959 res_tab
[x
] -= ltm_prime_tab
[x
];
5962 /* set flag if zero */
5963 if (res_tab
[x
] == 0) {
5967 } while (y
== 1 && step
< ((((mp_digit
)1)<<DIGIT_BIT
) - kstep
));
5970 if ((err
= mp_add_d(a
, step
, a
)) != MP_OKAY
) {
5974 /* if didn't pass sieve and step == MAX then skip test */
5975 if (y
== 1 && step
>= ((((mp_digit
)1)<<DIGIT_BIT
) - kstep
)) {
5979 /* is this prime? */
5980 for (x
= 0; x
< t
; x
++) {
5981 mp_set(&b
, ltm_prime_tab
[t
]);
5982 if ((err
= mp_prime_miller_rabin(a
, &b
, &res
)) != MP_OKAY
) {
5990 if (res
== MP_YES
) {
6003 /* $Source: /cvs/libtom/libtommath/bn_mp_prime_next_prime.c,v $ */
6004 /* $Revision: 1.3 $ */
6005 /* $Date: 2006/03/31 14:18:44 $ */
6007 /* End: bn_mp_prime_next_prime.c */
6009 /* Start: bn_mp_prime_rabin_miller_trials.c */
6010 #include <tommath.h>
6011 #ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
6012 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6014 * LibTomMath is a library that provides multiple-precision
6015 * integer arithmetic as well as number theoretic functionality.
6017 * The library was designed directly after the MPI library by
6018 * Michael Fromberger but has been written from scratch with
6019 * additional optimizations in place.
6021 * The library is free for all purposes without any express
6022 * guarantee it works.
6024 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6028 static const struct {
6041 /* returns # of RM trials required for a given bit size */
6042 int mp_prime_rabin_miller_trials(int size
)
6046 for (x
= 0; x
< (int)(sizeof(sizes
)/(sizeof(sizes
[0]))); x
++) {
6047 if (sizes
[x
].k
== size
) {
6049 } else if (sizes
[x
].k
> size
) {
6050 return (x
== 0) ? sizes
[0].t
: sizes
[x
- 1].t
;
6053 return sizes
[x
-1].t
+ 1;
6059 /* $Source: /cvs/libtom/libtommath/bn_mp_prime_rabin_miller_trials.c,v $ */
6060 /* $Revision: 1.3 $ */
6061 /* $Date: 2006/03/31 14:18:44 $ */
6063 /* End: bn_mp_prime_rabin_miller_trials.c */
6065 /* Start: bn_mp_prime_random_ex.c */
6066 #include <tommath.h>
6067 #ifdef BN_MP_PRIME_RANDOM_EX_C
6068 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6070 * LibTomMath is a library that provides multiple-precision
6071 * integer arithmetic as well as number theoretic functionality.
6073 * The library was designed directly after the MPI library by
6074 * Michael Fromberger but has been written from scratch with
6075 * additional optimizations in place.
6077 * The library is free for all purposes without any express
6078 * guarantee it works.
6080 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6083 /* makes a truly random prime of a given size (bits),
6085 * Flags are as follows:
6087 * LTM_PRIME_BBS - make prime congruent to 3 mod 4
6088 * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
6089 * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
6090 * LTM_PRIME_2MSB_ON - make the 2nd highest bit one
6092 * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
6093 * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
6098 /* This is possibly the mother of all prime generation functions, muahahahahaha! */
6099 int mp_prime_random_ex(mp_int
*a
, int t
, int size
, int flags
, ltm_prime_callback cb
, void *dat
)
6101 unsigned char *tmp
, maskAND
, maskOR_msb
, maskOR_lsb
;
6102 int res
, err
, bsize
, maskOR_msb_offset
;
6104 /* sanity check the input */
6105 if (size
<= 1 || t
<= 0) {
6109 /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
6110 if (flags
& LTM_PRIME_SAFE
) {
6111 flags
|= LTM_PRIME_BBS
;
6114 /* calc the byte size */
6115 bsize
= (size
>>3) + ((size
&7)?1:0);
6117 /* we need a buffer of bsize bytes */
6118 tmp
= OPT_CAST(unsigned char) XMALLOC(bsize
);
6123 /* calc the maskAND value for the MSbyte*/
6124 maskAND
= ((size
&7) == 0) ? 0xFF : (0xFF >> (8 - (size
& 7)));
6126 /* calc the maskOR_msb */
6128 maskOR_msb_offset
= ((size
& 7) == 1) ? 1 : 0;
6129 if (flags
& LTM_PRIME_2MSB_ON
) {
6130 maskOR_msb
|= 0x80 >> ((9 - size
) & 7);
6133 /* get the maskOR_lsb */
6135 if (flags
& LTM_PRIME_BBS
) {
6140 /* read the bytes */
6141 if (cb(tmp
, bsize
, dat
) != bsize
) {
6146 /* work over the MSbyte */
6148 tmp
[0] |= 1 << ((size
- 1) & 7);
6150 /* mix in the maskORs */
6151 tmp
[maskOR_msb_offset
] |= maskOR_msb
;
6152 tmp
[bsize
-1] |= maskOR_lsb
;
6155 if ((err
= mp_read_unsigned_bin(a
, tmp
, bsize
)) != MP_OKAY
) { goto error
; }
6158 if ((err
= mp_prime_is_prime(a
, t
, &res
)) != MP_OKAY
) { goto error
; }
6163 if (flags
& LTM_PRIME_SAFE
) {
6164 /* see if (a-1)/2 is prime */
6165 if ((err
= mp_sub_d(a
, 1, a
)) != MP_OKAY
) { goto error
; }
6166 if ((err
= mp_div_2(a
, a
)) != MP_OKAY
) { goto error
; }
6169 if ((err
= mp_prime_is_prime(a
, t
, &res
)) != MP_OKAY
) { goto error
; }
6171 } while (res
== MP_NO
);
6173 if (flags
& LTM_PRIME_SAFE
) {
6174 /* restore a to the original value */
6175 if ((err
= mp_mul_2(a
, a
)) != MP_OKAY
) { goto error
; }
6176 if ((err
= mp_add_d(a
, 1, a
)) != MP_OKAY
) { goto error
; }
6188 /* $Source: /cvs/libtom/libtommath/bn_mp_prime_random_ex.c,v $ */
6189 /* $Revision: 1.4 $ */
6190 /* $Date: 2006/03/31 14:18:44 $ */
6192 /* End: bn_mp_prime_random_ex.c */
6194 /* Start: bn_mp_radix_size.c */
6195 #include <tommath.h>
6196 #ifdef BN_MP_RADIX_SIZE_C
6197 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6199 * LibTomMath is a library that provides multiple-precision
6200 * integer arithmetic as well as number theoretic functionality.
6202 * The library was designed directly after the MPI library by
6203 * Michael Fromberger but has been written from scratch with
6204 * additional optimizations in place.
6206 * The library is free for all purposes without any express
6207 * guarantee it works.
6209 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6212 /* returns size of ASCII reprensentation */
6213 int mp_radix_size (mp_int
* a
, int radix
, int *size
)
6221 /* special case for binary */
6223 *size
= mp_count_bits (a
) + (a
->sign
== MP_NEG
? 1 : 0) + 1;
6227 /* make sure the radix is in range */
6228 if (radix
< 2 || radix
> 64) {
6232 if (mp_iszero(a
) == MP_YES
) {
6237 /* digs is the digit count */
6240 /* if it's negative add one for the sign */
6241 if (a
->sign
== MP_NEG
) {
6245 /* init a copy of the input */
6246 if ((res
= mp_init_copy (&t
, a
)) != MP_OKAY
) {
6250 /* force temp to positive */
6253 /* fetch out all of the digits */
6254 while (mp_iszero (&t
) == MP_NO
) {
6255 if ((res
= mp_div_d (&t
, (mp_digit
) radix
, &t
, &d
)) != MP_OKAY
) {
6263 /* return digs + 1, the 1 is for the NULL byte that would be required. */
6270 /* $Source: /cvs/libtom/libtommath/bn_mp_radix_size.c,v $ */
6271 /* $Revision: 1.4 $ */
6272 /* $Date: 2006/03/31 14:18:44 $ */
6274 /* End: bn_mp_radix_size.c */
6276 /* Start: bn_mp_radix_smap.c */
6277 #include <tommath.h>
6278 #ifdef BN_MP_RADIX_SMAP_C
6279 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6281 * LibTomMath is a library that provides multiple-precision
6282 * integer arithmetic as well as number theoretic functionality.
6284 * The library was designed directly after the MPI library by
6285 * Michael Fromberger but has been written from scratch with
6286 * additional optimizations in place.
6288 * The library is free for all purposes without any express
6289 * guarantee it works.
6291 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6294 /* chars used in radix conversions */
6295 const char *mp_s_rmap
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
6298 /* $Source: /cvs/libtom/libtommath/bn_mp_radix_smap.c,v $ */
6299 /* $Revision: 1.3 $ */
6300 /* $Date: 2006/03/31 14:18:44 $ */
6302 /* End: bn_mp_radix_smap.c */
6304 /* Start: bn_mp_rand.c */
6305 #include <tommath.h>
6307 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6309 * LibTomMath is a library that provides multiple-precision
6310 * integer arithmetic as well as number theoretic functionality.
6312 * The library was designed directly after the MPI library by
6313 * Michael Fromberger but has been written from scratch with
6314 * additional optimizations in place.
6316 * The library is free for all purposes without any express
6317 * guarantee it works.
6319 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6322 /* makes a pseudo-random int of a given size */
6324 mp_rand (mp_int
* a
, int digits
)
6334 /* first place a random non-zero digit */
6336 d
= ((mp_digit
) abs (rand ())) & MP_MASK
;
6339 if ((res
= mp_add_d (a
, d
, a
)) != MP_OKAY
) {
6343 while (--digits
> 0) {
6344 if ((res
= mp_lshd (a
, 1)) != MP_OKAY
) {
6348 if ((res
= mp_add_d (a
, ((mp_digit
) abs (rand ())), a
)) != MP_OKAY
) {
6357 /* $Source: /cvs/libtom/libtommath/bn_mp_rand.c,v $ */
6358 /* $Revision: 1.3 $ */
6359 /* $Date: 2006/03/31 14:18:44 $ */
6361 /* End: bn_mp_rand.c */
6363 /* Start: bn_mp_read_radix.c */
6364 #include <tommath.h>
6365 #ifdef BN_MP_READ_RADIX_C
6366 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6368 * LibTomMath is a library that provides multiple-precision
6369 * integer arithmetic as well as number theoretic functionality.
6371 * The library was designed directly after the MPI library by
6372 * Michael Fromberger but has been written from scratch with
6373 * additional optimizations in place.
6375 * The library is free for all purposes without any express
6376 * guarantee it works.
6378 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6381 /* read a string [ASCII] in a given radix */
6382 int mp_read_radix (mp_int
* a
, const char *str
, int radix
)
6387 /* zero the digit bignum */
6390 /* make sure the radix is ok */
6391 if (radix
< 2 || radix
> 64) {
6395 /* if the leading digit is a
6396 * minus set the sign to negative.
6405 /* set the integer to the default of zero */
6408 /* process each digit of the string */
6410 /* if the radix < 36 the conversion is case insensitive
6411 * this allows numbers like 1AB and 1ab to represent the same value
6414 ch
= (char) ((radix
< 36) ? toupper (*str
) : *str
);
6415 for (y
= 0; y
< 64; y
++) {
6416 if (ch
== mp_s_rmap
[y
]) {
6421 /* if the char was found in the map
6422 * and is less than the given radix add it
6423 * to the number, otherwise exit the loop.
6426 if ((res
= mp_mul_d (a
, (mp_digit
) radix
, a
)) != MP_OKAY
) {
6429 if ((res
= mp_add_d (a
, (mp_digit
) y
, a
)) != MP_OKAY
) {
6438 /* set the sign only if a != 0 */
6439 if (mp_iszero(a
) != 1) {
6446 /* $Source: /cvs/libtom/libtommath/bn_mp_read_radix.c,v $ */
6447 /* $Revision: 1.4 $ */
6448 /* $Date: 2006/03/31 14:18:44 $ */
6450 /* End: bn_mp_read_radix.c */
6452 /* Start: bn_mp_read_signed_bin.c */
6453 #include <tommath.h>
6454 #ifdef BN_MP_READ_SIGNED_BIN_C
6455 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6457 * LibTomMath is a library that provides multiple-precision
6458 * integer arithmetic as well as number theoretic functionality.
6460 * The library was designed directly after the MPI library by
6461 * Michael Fromberger but has been written from scratch with
6462 * additional optimizations in place.
6464 * The library is free for all purposes without any express
6465 * guarantee it works.
6467 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6470 /* read signed bin, big endian, first byte is 0==positive or 1==negative */
6471 int mp_read_signed_bin (mp_int
* a
, const unsigned char *b
, int c
)
6475 /* read magnitude */
6476 if ((res
= mp_read_unsigned_bin (a
, b
+ 1, c
- 1)) != MP_OKAY
) {
6480 /* first byte is 0 for positive, non-zero for negative */
6491 /* $Source: /cvs/libtom/libtommath/bn_mp_read_signed_bin.c,v $ */
6492 /* $Revision: 1.4 $ */
6493 /* $Date: 2006/03/31 14:18:44 $ */
6495 /* End: bn_mp_read_signed_bin.c */
6497 /* Start: bn_mp_read_unsigned_bin.c */
6498 #include <tommath.h>
6499 #ifdef BN_MP_READ_UNSIGNED_BIN_C
6500 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6502 * LibTomMath is a library that provides multiple-precision
6503 * integer arithmetic as well as number theoretic functionality.
6505 * The library was designed directly after the MPI library by
6506 * Michael Fromberger but has been written from scratch with
6507 * additional optimizations in place.
6509 * The library is free for all purposes without any express
6510 * guarantee it works.
6512 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6515 /* reads a unsigned char array, assumes the msb is stored first [big endian] */
6516 int mp_read_unsigned_bin (mp_int
* a
, const unsigned char *b
, int c
)
6520 /* make sure there are at least two digits */
6522 if ((res
= mp_grow(a
, 2)) != MP_OKAY
) {
6530 /* read the bytes in */
6532 if ((res
= mp_mul_2d (a
, 8, a
)) != MP_OKAY
) {
6540 a
->dp
[0] = (*b
& MP_MASK
);
6541 a
->dp
[1] |= ((*b
++ >> 7U) & 1);
6550 /* $Source: /cvs/libtom/libtommath/bn_mp_read_unsigned_bin.c,v $ */
6551 /* $Revision: 1.4 $ */
6552 /* $Date: 2006/03/31 14:18:44 $ */
6554 /* End: bn_mp_read_unsigned_bin.c */
6556 /* Start: bn_mp_reduce.c */
6557 #include <tommath.h>
6558 #ifdef BN_MP_REDUCE_C
6559 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6561 * LibTomMath is a library that provides multiple-precision
6562 * integer arithmetic as well as number theoretic functionality.
6564 * The library was designed directly after the MPI library by
6565 * Michael Fromberger but has been written from scratch with
6566 * additional optimizations in place.
6568 * The library is free for all purposes without any express
6569 * guarantee it works.
6571 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6574 /* reduces x mod m, assumes 0 < x < m**2, mu is
6575 * precomputed via mp_reduce_setup.
6576 * From HAC pp.604 Algorithm 14.42
6578 int mp_reduce (mp_int
* x
, mp_int
* m
, mp_int
* mu
)
6581 int res
, um
= m
->used
;
6584 if ((res
= mp_init_copy (&q
, x
)) != MP_OKAY
) {
6588 /* q1 = x / b**(k-1) */
6589 mp_rshd (&q
, um
- 1);
6591 /* according to HAC this optimization is ok */
6592 if (((unsigned long) um
) > (((mp_digit
)1) << (DIGIT_BIT
- 1))) {
6593 if ((res
= mp_mul (&q
, mu
, &q
)) != MP_OKAY
) {
6597 #ifdef BN_S_MP_MUL_HIGH_DIGS_C
6598 if ((res
= s_mp_mul_high_digs (&q
, mu
, &q
, um
)) != MP_OKAY
) {
6601 #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
6602 if ((res
= fast_s_mp_mul_high_digs (&q
, mu
, &q
, um
)) != MP_OKAY
) {
6613 /* q3 = q2 / b**(k+1) */
6614 mp_rshd (&q
, um
+ 1);
6616 /* x = x mod b**(k+1), quick (no division) */
6617 if ((res
= mp_mod_2d (x
, DIGIT_BIT
* (um
+ 1), x
)) != MP_OKAY
) {
6621 /* q = q * m mod b**(k+1), quick (no division) */
6622 if ((res
= s_mp_mul_digs (&q
, m
, &q
, um
+ 1)) != MP_OKAY
) {
6627 if ((res
= mp_sub (x
, &q
, x
)) != MP_OKAY
) {
6631 /* If x < 0, add b**(k+1) to it */
6632 if (mp_cmp_d (x
, 0) == MP_LT
) {
6634 if ((res
= mp_lshd (&q
, um
+ 1)) != MP_OKAY
)
6636 if ((res
= mp_add (x
, &q
, x
)) != MP_OKAY
)
6640 /* Back off if it's too big */
6641 while (mp_cmp (x
, m
) != MP_LT
) {
6642 if ((res
= s_mp_sub (x
, m
, x
)) != MP_OKAY
) {
6654 /* $Source: /cvs/libtom/libtommath/bn_mp_reduce.c,v $ */
6655 /* $Revision: 1.3 $ */
6656 /* $Date: 2006/03/31 14:18:44 $ */
6658 /* End: bn_mp_reduce.c */
6660 /* Start: bn_mp_reduce_2k.c */
6661 #include <tommath.h>
6662 #ifdef BN_MP_REDUCE_2K_C
6663 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6665 * LibTomMath is a library that provides multiple-precision
6666 * integer arithmetic as well as number theoretic functionality.
6668 * The library was designed directly after the MPI library by
6669 * Michael Fromberger but has been written from scratch with
6670 * additional optimizations in place.
6672 * The library is free for all purposes without any express
6673 * guarantee it works.
6675 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6678 /* reduces a modulo n where n is of the form 2**p - d */
6679 int mp_reduce_2k(mp_int
*a
, mp_int
*n
, mp_digit d
)
6684 if ((res
= mp_init(&q
)) != MP_OKAY
) {
6688 p
= mp_count_bits(n
);
6690 /* q = a/2**p, a = a mod 2**p */
6691 if ((res
= mp_div_2d(a
, p
, &q
, a
)) != MP_OKAY
) {
6697 if ((res
= mp_mul_d(&q
, d
, &q
)) != MP_OKAY
) {
6703 if ((res
= s_mp_add(a
, &q
, a
)) != MP_OKAY
) {
6707 if (mp_cmp_mag(a
, n
) != MP_LT
) {
6719 /* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k.c,v $ */
6720 /* $Revision: 1.3 $ */
6721 /* $Date: 2006/03/31 14:18:44 $ */
6723 /* End: bn_mp_reduce_2k.c */
6725 /* Start: bn_mp_reduce_2k_l.c */
6726 #include <tommath.h>
6727 #ifdef BN_MP_REDUCE_2K_L_C
6728 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6730 * LibTomMath is a library that provides multiple-precision
6731 * integer arithmetic as well as number theoretic functionality.
6733 * The library was designed directly after the MPI library by
6734 * Michael Fromberger but has been written from scratch with
6735 * additional optimizations in place.
6737 * The library is free for all purposes without any express
6738 * guarantee it works.
6740 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6743 /* reduces a modulo n where n is of the form 2**p - d
6744 This differs from reduce_2k since "d" can be larger
6745 than a single digit.
6747 int mp_reduce_2k_l(mp_int
*a
, mp_int
*n
, mp_int
*d
)
6752 if ((res
= mp_init(&q
)) != MP_OKAY
) {
6756 p
= mp_count_bits(n
);
6758 /* q = a/2**p, a = a mod 2**p */
6759 if ((res
= mp_div_2d(a
, p
, &q
, a
)) != MP_OKAY
) {
6764 if ((res
= mp_mul(&q
, d
, &q
)) != MP_OKAY
) {
6769 if ((res
= s_mp_add(a
, &q
, a
)) != MP_OKAY
) {
6773 if (mp_cmp_mag(a
, n
) != MP_LT
) {
6785 /* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_l.c,v $ */
6786 /* $Revision: 1.3 $ */
6787 /* $Date: 2006/03/31 14:18:44 $ */
6789 /* End: bn_mp_reduce_2k_l.c */
6791 /* Start: bn_mp_reduce_2k_setup.c */
6792 #include <tommath.h>
6793 #ifdef BN_MP_REDUCE_2K_SETUP_C
6794 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6796 * LibTomMath is a library that provides multiple-precision
6797 * integer arithmetic as well as number theoretic functionality.
6799 * The library was designed directly after the MPI library by
6800 * Michael Fromberger but has been written from scratch with
6801 * additional optimizations in place.
6803 * The library is free for all purposes without any express
6804 * guarantee it works.
6806 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6809 /* determines the setup value */
6810 int mp_reduce_2k_setup(mp_int
*a
, mp_digit
*d
)
6815 if ((res
= mp_init(&tmp
)) != MP_OKAY
) {
6819 p
= mp_count_bits(a
);
6820 if ((res
= mp_2expt(&tmp
, p
)) != MP_OKAY
) {
6825 if ((res
= s_mp_sub(&tmp
, a
, &tmp
)) != MP_OKAY
) {
6836 /* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup.c,v $ */
6837 /* $Revision: 1.3 $ */
6838 /* $Date: 2006/03/31 14:18:44 $ */
6840 /* End: bn_mp_reduce_2k_setup.c */
6842 /* Start: bn_mp_reduce_2k_setup_l.c */
6843 #include <tommath.h>
6844 #ifdef BN_MP_REDUCE_2K_SETUP_L_C
6845 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6847 * LibTomMath is a library that provides multiple-precision
6848 * integer arithmetic as well as number theoretic functionality.
6850 * The library was designed directly after the MPI library by
6851 * Michael Fromberger but has been written from scratch with
6852 * additional optimizations in place.
6854 * The library is free for all purposes without any express
6855 * guarantee it works.
6857 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6860 /* determines the setup value */
6861 int mp_reduce_2k_setup_l(mp_int
*a
, mp_int
*d
)
6866 if ((res
= mp_init(&tmp
)) != MP_OKAY
) {
6870 if ((res
= mp_2expt(&tmp
, mp_count_bits(a
))) != MP_OKAY
) {
6874 if ((res
= s_mp_sub(&tmp
, a
, d
)) != MP_OKAY
) {
6884 /* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup_l.c,v $ */
6885 /* $Revision: 1.3 $ */
6886 /* $Date: 2006/03/31 14:18:44 $ */
6888 /* End: bn_mp_reduce_2k_setup_l.c */
6890 /* Start: bn_mp_reduce_is_2k.c */
6891 #include <tommath.h>
6892 #ifdef BN_MP_REDUCE_IS_2K_C
6893 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6895 * LibTomMath is a library that provides multiple-precision
6896 * integer arithmetic as well as number theoretic functionality.
6898 * The library was designed directly after the MPI library by
6899 * Michael Fromberger but has been written from scratch with
6900 * additional optimizations in place.
6902 * The library is free for all purposes without any express
6903 * guarantee it works.
6905 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6908 /* determines if mp_reduce_2k can be used */
6909 int mp_reduce_is_2k(mp_int
*a
)
6916 } else if (a
->used
== 1) {
6918 } else if (a
->used
> 1) {
6919 iy
= mp_count_bits(a
);
6923 /* Test every bit from the second digit up, must be 1 */
6924 for (ix
= DIGIT_BIT
; ix
< iy
; ix
++) {
6925 if ((a
->dp
[iw
] & iz
) == 0) {
6929 if (iz
> (mp_digit
)MP_MASK
) {
6940 /* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k.c,v $ */
6941 /* $Revision: 1.3 $ */
6942 /* $Date: 2006/03/31 14:18:44 $ */
6944 /* End: bn_mp_reduce_is_2k.c */
6946 /* Start: bn_mp_reduce_is_2k_l.c */
6947 #include <tommath.h>
6948 #ifdef BN_MP_REDUCE_IS_2K_L_C
6949 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6951 * LibTomMath is a library that provides multiple-precision
6952 * integer arithmetic as well as number theoretic functionality.
6954 * The library was designed directly after the MPI library by
6955 * Michael Fromberger but has been written from scratch with
6956 * additional optimizations in place.
6958 * The library is free for all purposes without any express
6959 * guarantee it works.
6961 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
6964 /* determines if reduce_2k_l can be used */
6965 int mp_reduce_is_2k_l(mp_int
*a
)
6971 } else if (a
->used
== 1) {
6973 } else if (a
->used
> 1) {
6974 /* if more than half of the digits are -1 we're sold */
6975 for (iy
= ix
= 0; ix
< a
->used
; ix
++) {
6976 if (a
->dp
[ix
] == MP_MASK
) {
6980 return (iy
>= (a
->used
/2)) ? MP_YES
: MP_NO
;
6988 /* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k_l.c,v $ */
6989 /* $Revision: 1.3 $ */
6990 /* $Date: 2006/03/31 14:18:44 $ */
6992 /* End: bn_mp_reduce_is_2k_l.c */
6994 /* Start: bn_mp_reduce_setup.c */
6995 #include <tommath.h>
6996 #ifdef BN_MP_REDUCE_SETUP_C
6997 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6999 * LibTomMath is a library that provides multiple-precision
7000 * integer arithmetic as well as number theoretic functionality.
7002 * The library was designed directly after the MPI library by
7003 * Michael Fromberger but has been written from scratch with
7004 * additional optimizations in place.
7006 * The library is free for all purposes without any express
7007 * guarantee it works.
7009 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7012 /* pre-calculate the value required for Barrett reduction
7013 * For a given modulus "b" it calulates the value required in "a"
7015 int mp_reduce_setup (mp_int
* a
, mp_int
* b
)
7019 if ((res
= mp_2expt (a
, b
->used
* 2 * DIGIT_BIT
)) != MP_OKAY
) {
7022 return mp_div (a
, b
, a
, NULL
);
7026 /* $Source: /cvs/libtom/libtommath/bn_mp_reduce_setup.c,v $ */
7027 /* $Revision: 1.3 $ */
7028 /* $Date: 2006/03/31 14:18:44 $ */
7030 /* End: bn_mp_reduce_setup.c */
7032 /* Start: bn_mp_rshd.c */
7033 #include <tommath.h>
7035 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7037 * LibTomMath is a library that provides multiple-precision
7038 * integer arithmetic as well as number theoretic functionality.
7040 * The library was designed directly after the MPI library by
7041 * Michael Fromberger but has been written from scratch with
7042 * additional optimizations in place.
7044 * The library is free for all purposes without any express
7045 * guarantee it works.
7047 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7050 /* shift right a certain amount of digits */
7051 void mp_rshd (mp_int
* a
, int b
)
7055 /* if b <= 0 then ignore it */
7060 /* if b > used then simply zero it and return */
7067 register mp_digit
*bottom
, *top
;
7069 /* shift the digits down */
7074 /* top [offset into digits] */
7077 /* this is implemented as a sliding window where
7078 * the window is b-digits long and digits from
7079 * the top of the window are copied to the bottom
7083 b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
7085 \-------------------/ ---->
7087 for (x
= 0; x
< (a
->used
- b
); x
++) {
7091 /* zero the top digits */
7092 for (; x
< a
->used
; x
++) {
7097 /* remove excess digits */
7102 /* $Source: /cvs/libtom/libtommath/bn_mp_rshd.c,v $ */
7103 /* $Revision: 1.3 $ */
7104 /* $Date: 2006/03/31 14:18:44 $ */
7106 /* End: bn_mp_rshd.c */
7108 /* Start: bn_mp_set.c */
7109 #include <tommath.h>
7111 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7113 * LibTomMath is a library that provides multiple-precision
7114 * integer arithmetic as well as number theoretic functionality.
7116 * The library was designed directly after the MPI library by
7117 * Michael Fromberger but has been written from scratch with
7118 * additional optimizations in place.
7120 * The library is free for all purposes without any express
7121 * guarantee it works.
7123 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7126 /* set to a digit */
7127 void mp_set (mp_int
* a
, mp_digit b
)
7130 a
->dp
[0] = b
& MP_MASK
;
7131 a
->used
= (a
->dp
[0] != 0) ? 1 : 0;
7135 /* $Source: /cvs/libtom/libtommath/bn_mp_set.c,v $ */
7136 /* $Revision: 1.3 $ */
7137 /* $Date: 2006/03/31 14:18:44 $ */
7139 /* End: bn_mp_set.c */
7141 /* Start: bn_mp_set_int.c */
7142 #include <tommath.h>
7143 #ifdef BN_MP_SET_INT_C
7144 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7146 * LibTomMath is a library that provides multiple-precision
7147 * integer arithmetic as well as number theoretic functionality.
7149 * The library was designed directly after the MPI library by
7150 * Michael Fromberger but has been written from scratch with
7151 * additional optimizations in place.
7153 * The library is free for all purposes without any express
7154 * guarantee it works.
7156 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7159 /* set a 32-bit const */
7160 int mp_set_int (mp_int
* a
, unsigned long b
)
7166 /* set four bits at a time */
7167 for (x
= 0; x
< 8; x
++) {
7168 /* shift the number up four bits */
7169 if ((res
= mp_mul_2d (a
, 4, a
)) != MP_OKAY
) {
7173 /* OR in the top four bits of the source */
7174 a
->dp
[0] |= (b
>> 28) & 15;
7176 /* shift the source up to the next four bits */
7179 /* ensure that digits are not clamped off */
7187 /* $Source: /cvs/libtom/libtommath/bn_mp_set_int.c,v $ */
7188 /* $Revision: 1.3 $ */
7189 /* $Date: 2006/03/31 14:18:44 $ */
7191 /* End: bn_mp_set_int.c */
7193 /* Start: bn_mp_shrink.c */
7194 #include <tommath.h>
7195 #ifdef BN_MP_SHRINK_C
7196 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7198 * LibTomMath is a library that provides multiple-precision
7199 * integer arithmetic as well as number theoretic functionality.
7201 * The library was designed directly after the MPI library by
7202 * Michael Fromberger but has been written from scratch with
7203 * additional optimizations in place.
7205 * The library is free for all purposes without any express
7206 * guarantee it works.
7208 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7211 /* shrink a bignum */
7212 int mp_shrink (mp_int
* a
)
7215 if (a
->alloc
!= a
->used
&& a
->used
> 0) {
7216 if ((tmp
= OPT_CAST(mp_digit
) XREALLOC (a
->dp
, sizeof (mp_digit
) * a
->used
)) == NULL
) {
7226 /* $Source: /cvs/libtom/libtommath/bn_mp_shrink.c,v $ */
7227 /* $Revision: 1.3 $ */
7228 /* $Date: 2006/03/31 14:18:44 $ */
7230 /* End: bn_mp_shrink.c */
7232 /* Start: bn_mp_signed_bin_size.c */
7233 #include <tommath.h>
7234 #ifdef BN_MP_SIGNED_BIN_SIZE_C
7235 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7237 * LibTomMath is a library that provides multiple-precision
7238 * integer arithmetic as well as number theoretic functionality.
7240 * The library was designed directly after the MPI library by
7241 * Michael Fromberger but has been written from scratch with
7242 * additional optimizations in place.
7244 * The library is free for all purposes without any express
7245 * guarantee it works.
7247 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7250 /* get the size for an signed equivalent */
7251 int mp_signed_bin_size (mp_int
* a
)
7253 return 1 + mp_unsigned_bin_size (a
);
7257 /* $Source: /cvs/libtom/libtommath/bn_mp_signed_bin_size.c,v $ */
7258 /* $Revision: 1.3 $ */
7259 /* $Date: 2006/03/31 14:18:44 $ */
7261 /* End: bn_mp_signed_bin_size.c */
7263 /* Start: bn_mp_sqr.c */
7264 #include <tommath.h>
7266 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7268 * LibTomMath is a library that provides multiple-precision
7269 * integer arithmetic as well as number theoretic functionality.
7271 * The library was designed directly after the MPI library by
7272 * Michael Fromberger but has been written from scratch with
7273 * additional optimizations in place.
7275 * The library is free for all purposes without any express
7276 * guarantee it works.
7278 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7281 /* computes b = a*a */
7283 mp_sqr (mp_int
* a
, mp_int
* b
)
7287 #ifdef BN_MP_TOOM_SQR_C
7288 /* use Toom-Cook? */
7289 if (a
->used
>= TOOM_SQR_CUTOFF
) {
7290 res
= mp_toom_sqr(a
, b
);
7294 #ifdef BN_MP_KARATSUBA_SQR_C
7295 if (a
->used
>= KARATSUBA_SQR_CUTOFF
) {
7296 res
= mp_karatsuba_sqr (a
, b
);
7300 #ifdef BN_FAST_S_MP_SQR_C
7301 /* can we use the fast comba multiplier? */
7302 if ((a
->used
* 2 + 1) < MP_WARRAY
&&
7304 (1 << (sizeof(mp_word
) * CHAR_BIT
- 2*DIGIT_BIT
- 1))) {
7305 res
= fast_s_mp_sqr (a
, b
);
7308 #ifdef BN_S_MP_SQR_C
7309 res
= s_mp_sqr (a
, b
);
7319 /* $Source: /cvs/libtom/libtommath/bn_mp_sqr.c,v $ */
7320 /* $Revision: 1.3 $ */
7321 /* $Date: 2006/03/31 14:18:44 $ */
7323 /* End: bn_mp_sqr.c */
7325 /* Start: bn_mp_sqrmod.c */
7326 #include <tommath.h>
7327 #ifdef BN_MP_SQRMOD_C
7328 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7330 * LibTomMath is a library that provides multiple-precision
7331 * integer arithmetic as well as number theoretic functionality.
7333 * The library was designed directly after the MPI library by
7334 * Michael Fromberger but has been written from scratch with
7335 * additional optimizations in place.
7337 * The library is free for all purposes without any express
7338 * guarantee it works.
7340 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7343 /* c = a * a (mod b) */
7345 mp_sqrmod (mp_int
* a
, mp_int
* b
, mp_int
* c
)
7350 if ((res
= mp_init (&t
)) != MP_OKAY
) {
7354 if ((res
= mp_sqr (a
, &t
)) != MP_OKAY
) {
7358 res
= mp_mod (&t
, b
, c
);
7364 /* $Source: /cvs/libtom/libtommath/bn_mp_sqrmod.c,v $ */
7365 /* $Revision: 1.3 $ */
7366 /* $Date: 2006/03/31 14:18:44 $ */
7368 /* End: bn_mp_sqrmod.c */
7370 /* Start: bn_mp_sqrt.c */
7371 #include <tommath.h>
7373 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7375 * LibTomMath is a library that provides multiple-precision
7376 * integer arithmetic as well as number theoretic functionality.
7378 * The library was designed directly after the MPI library by
7379 * Michael Fromberger but has been written from scratch with
7380 * additional optimizations in place.
7382 * The library is free for all purposes without any express
7383 * guarantee it works.
7385 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7388 /* this function is less generic than mp_n_root, simpler and faster */
7389 int mp_sqrt(mp_int
*arg
, mp_int
*ret
)
7394 /* must be positive */
7395 if (arg
->sign
== MP_NEG
) {
7400 if (mp_iszero(arg
) == MP_YES
) {
7405 if ((res
= mp_init_copy(&t1
, arg
)) != MP_OKAY
) {
7409 if ((res
= mp_init(&t2
)) != MP_OKAY
) {
7413 /* First approx. (not very bad for large arg) */
7414 mp_rshd (&t1
,t1
.used
/2);
7417 if ((res
= mp_div(arg
,&t1
,&t2
,NULL
)) != MP_OKAY
) {
7420 if ((res
= mp_add(&t1
,&t2
,&t1
)) != MP_OKAY
) {
7423 if ((res
= mp_div_2(&t1
,&t1
)) != MP_OKAY
) {
7426 /* And now t1 > sqrt(arg) */
7428 if ((res
= mp_div(arg
,&t1
,&t2
,NULL
)) != MP_OKAY
) {
7431 if ((res
= mp_add(&t1
,&t2
,&t1
)) != MP_OKAY
) {
7434 if ((res
= mp_div_2(&t1
,&t1
)) != MP_OKAY
) {
7437 /* t1 >= sqrt(arg) >= t2 at this point */
7438 } while (mp_cmp_mag(&t1
,&t2
) == MP_GT
);
7449 /* $Source: /cvs/libtom/libtommath/bn_mp_sqrt.c,v $ */
7450 /* $Revision: 1.3 $ */
7451 /* $Date: 2006/03/31 14:18:44 $ */
7453 /* End: bn_mp_sqrt.c */
7455 /* Start: bn_mp_sub.c */
7456 #include <tommath.h>
7458 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7460 * LibTomMath is a library that provides multiple-precision
7461 * integer arithmetic as well as number theoretic functionality.
7463 * The library was designed directly after the MPI library by
7464 * Michael Fromberger but has been written from scratch with
7465 * additional optimizations in place.
7467 * The library is free for all purposes without any express
7468 * guarantee it works.
7470 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7473 /* high level subtraction (handles signs) */
7475 mp_sub (mp_int
* a
, mp_int
* b
, mp_int
* c
)
7483 /* subtract a negative from a positive, OR */
7484 /* subtract a positive from a negative. */
7485 /* In either case, ADD their magnitudes, */
7486 /* and use the sign of the first number. */
7488 res
= s_mp_add (a
, b
, c
);
7490 /* subtract a positive from a positive, OR */
7491 /* subtract a negative from a negative. */
7492 /* First, take the difference between their */
7493 /* magnitudes, then... */
7494 if (mp_cmp_mag (a
, b
) != MP_LT
) {
7495 /* Copy the sign from the first */
7497 /* The first has a larger or equal magnitude */
7498 res
= s_mp_sub (a
, b
, c
);
7500 /* The result has the *opposite* sign from */
7501 /* the first number. */
7502 c
->sign
= (sa
== MP_ZPOS
) ? MP_NEG
: MP_ZPOS
;
7503 /* The second has a larger magnitude */
7504 res
= s_mp_sub (b
, a
, c
);
7512 /* $Source: /cvs/libtom/libtommath/bn_mp_sub.c,v $ */
7513 /* $Revision: 1.3 $ */
7514 /* $Date: 2006/03/31 14:18:44 $ */
7516 /* End: bn_mp_sub.c */
7518 /* Start: bn_mp_sub_d.c */
7519 #include <tommath.h>
7520 #ifdef BN_MP_SUB_D_C
7521 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7523 * LibTomMath is a library that provides multiple-precision
7524 * integer arithmetic as well as number theoretic functionality.
7526 * The library was designed directly after the MPI library by
7527 * Michael Fromberger but has been written from scratch with
7528 * additional optimizations in place.
7530 * The library is free for all purposes without any express
7531 * guarantee it works.
7533 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7536 /* single digit subtraction */
7538 mp_sub_d (mp_int
* a
, mp_digit b
, mp_int
* c
)
7540 mp_digit
*tmpa
, *tmpc
, mu
;
7541 int res
, ix
, oldused
;
7543 /* grow c as required */
7544 if (c
->alloc
< a
->used
+ 1) {
7545 if ((res
= mp_grow(c
, a
->used
+ 1)) != MP_OKAY
) {
7550 /* if a is negative just do an unsigned
7551 * addition [with fudged signs]
7553 if (a
->sign
== MP_NEG
) {
7555 res
= mp_add_d(a
, b
, c
);
7556 a
->sign
= c
->sign
= MP_NEG
;
7569 /* if a <= b simply fix the single digit */
7570 if ((a
->used
== 1 && a
->dp
[0] <= b
) || a
->used
== 0) {
7572 *tmpc
++ = b
- *tmpa
;
7578 /* negative/1digit */
7586 /* subtract first digit */
7587 *tmpc
= *tmpa
++ - b
;
7588 mu
= *tmpc
>> (sizeof(mp_digit
) * CHAR_BIT
- 1);
7591 /* handle rest of the digits */
7592 for (ix
= 1; ix
< a
->used
; ix
++) {
7593 *tmpc
= *tmpa
++ - mu
;
7594 mu
= *tmpc
>> (sizeof(mp_digit
) * CHAR_BIT
- 1);
7599 /* zero excess digits */
7600 while (ix
++ < oldused
) {
7609 /* $Source: /cvs/libtom/libtommath/bn_mp_sub_d.c,v $ */
7610 /* $Revision: 1.5 $ */
7611 /* $Date: 2006/03/31 14:18:44 $ */
7613 /* End: bn_mp_sub_d.c */
7615 /* Start: bn_mp_submod.c */
7616 #include <tommath.h>
7617 #ifdef BN_MP_SUBMOD_C
7618 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7620 * LibTomMath is a library that provides multiple-precision
7621 * integer arithmetic as well as number theoretic functionality.
7623 * The library was designed directly after the MPI library by
7624 * Michael Fromberger but has been written from scratch with
7625 * additional optimizations in place.
7627 * The library is free for all purposes without any express
7628 * guarantee it works.
7630 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7633 /* d = a - b (mod c) */
7635 mp_submod (mp_int
* a
, mp_int
* b
, mp_int
* c
, mp_int
* d
)
7641 if ((res
= mp_init (&t
)) != MP_OKAY
) {
7645 if ((res
= mp_sub (a
, b
, &t
)) != MP_OKAY
) {
7649 res
= mp_mod (&t
, c
, d
);
7655 /* $Source: /cvs/libtom/libtommath/bn_mp_submod.c,v $ */
7656 /* $Revision: 1.3 $ */
7657 /* $Date: 2006/03/31 14:18:44 $ */
7659 /* End: bn_mp_submod.c */
7661 /* Start: bn_mp_to_signed_bin.c */
7662 #include <tommath.h>
7663 #ifdef BN_MP_TO_SIGNED_BIN_C
7664 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7666 * LibTomMath is a library that provides multiple-precision
7667 * integer arithmetic as well as number theoretic functionality.
7669 * The library was designed directly after the MPI library by
7670 * Michael Fromberger but has been written from scratch with
7671 * additional optimizations in place.
7673 * The library is free for all purposes without any express
7674 * guarantee it works.
7676 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7679 /* store in signed [big endian] format */
7680 int mp_to_signed_bin (mp_int
* a
, unsigned char *b
)
7684 if ((res
= mp_to_unsigned_bin (a
, b
+ 1)) != MP_OKAY
) {
7687 b
[0] = (unsigned char) ((a
->sign
== MP_ZPOS
) ? 0 : 1);
7692 /* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin.c,v $ */
7693 /* $Revision: 1.3 $ */
7694 /* $Date: 2006/03/31 14:18:44 $ */
7696 /* End: bn_mp_to_signed_bin.c */
7698 /* Start: bn_mp_to_signed_bin_n.c */
7699 #include <tommath.h>
7700 #ifdef BN_MP_TO_SIGNED_BIN_N_C
7701 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7703 * LibTomMath is a library that provides multiple-precision
7704 * integer arithmetic as well as number theoretic functionality.
7706 * The library was designed directly after the MPI library by
7707 * Michael Fromberger but has been written from scratch with
7708 * additional optimizations in place.
7710 * The library is free for all purposes without any express
7711 * guarantee it works.
7713 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7716 /* store in signed [big endian] format */
7717 int mp_to_signed_bin_n (mp_int
* a
, unsigned char *b
, unsigned long *outlen
)
7719 if (*outlen
< (unsigned long)mp_signed_bin_size(a
)) {
7722 *outlen
= mp_signed_bin_size(a
);
7723 return mp_to_signed_bin(a
, b
);
7727 /* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin_n.c,v $ */
7728 /* $Revision: 1.3 $ */
7729 /* $Date: 2006/03/31 14:18:44 $ */
7731 /* End: bn_mp_to_signed_bin_n.c */
7733 /* Start: bn_mp_to_unsigned_bin.c */
7734 #include <tommath.h>
7735 #ifdef BN_MP_TO_UNSIGNED_BIN_C
7736 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7738 * LibTomMath is a library that provides multiple-precision
7739 * integer arithmetic as well as number theoretic functionality.
7741 * The library was designed directly after the MPI library by
7742 * Michael Fromberger but has been written from scratch with
7743 * additional optimizations in place.
7745 * The library is free for all purposes without any express
7746 * guarantee it works.
7748 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7751 /* store in unsigned [big endian] format */
7752 int mp_to_unsigned_bin (mp_int
* a
, unsigned char *b
)
7757 if ((res
= mp_init_copy (&t
, a
)) != MP_OKAY
) {
7762 while (mp_iszero (&t
) == 0) {
7764 b
[x
++] = (unsigned char) (t
.dp
[0] & 255);
7766 b
[x
++] = (unsigned char) (t
.dp
[0] | ((t
.dp
[1] & 0x01) << 7));
7768 if ((res
= mp_div_2d (&t
, 8, &t
, NULL
)) != MP_OKAY
) {
7779 /* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin.c,v $ */
7780 /* $Revision: 1.3 $ */
7781 /* $Date: 2006/03/31 14:18:44 $ */
7783 /* End: bn_mp_to_unsigned_bin.c */
7785 /* Start: bn_mp_to_unsigned_bin_n.c */
7786 #include <tommath.h>
7787 #ifdef BN_MP_TO_UNSIGNED_BIN_N_C
7788 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7790 * LibTomMath is a library that provides multiple-precision
7791 * integer arithmetic as well as number theoretic functionality.
7793 * The library was designed directly after the MPI library by
7794 * Michael Fromberger but has been written from scratch with
7795 * additional optimizations in place.
7797 * The library is free for all purposes without any express
7798 * guarantee it works.
7800 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7803 /* store in unsigned [big endian] format */
7804 int mp_to_unsigned_bin_n (mp_int
* a
, unsigned char *b
, unsigned long *outlen
)
7806 if (*outlen
< (unsigned long)mp_unsigned_bin_size(a
)) {
7809 *outlen
= mp_unsigned_bin_size(a
);
7810 return mp_to_unsigned_bin(a
, b
);
7814 /* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin_n.c,v $ */
7815 /* $Revision: 1.3 $ */
7816 /* $Date: 2006/03/31 14:18:44 $ */
7818 /* End: bn_mp_to_unsigned_bin_n.c */
7820 /* Start: bn_mp_toom_mul.c */
7821 #include <tommath.h>
7822 #ifdef BN_MP_TOOM_MUL_C
7823 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7825 * LibTomMath is a library that provides multiple-precision
7826 * integer arithmetic as well as number theoretic functionality.
7828 * The library was designed directly after the MPI library by
7829 * Michael Fromberger but has been written from scratch with
7830 * additional optimizations in place.
7832 * The library is free for all purposes without any express
7833 * guarantee it works.
7835 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
7838 /* multiplication using the Toom-Cook 3-way algorithm
7840 * Much more complicated than Karatsuba but has a lower
7841 * asymptotic running time of O(N**1.464). This algorithm is
7842 * only particularly useful on VERY large inputs
7843 * (we're talking 1000s of digits here...).
7845 int mp_toom_mul(mp_int
*a
, mp_int
*b
, mp_int
*c
)
7847 mp_int w0
, w1
, w2
, w3
, w4
, tmp1
, tmp2
, a0
, a1
, a2
, b0
, b1
, b2
;
7851 if ((res
= mp_init_multi(&w0
, &w1
, &w2
, &w3
, &w4
,
7852 &a0
, &a1
, &a2
, &b0
, &b1
,
7853 &b2
, &tmp1
, &tmp2
, NULL
)) != MP_OKAY
) {
7858 B
= MIN(a
->used
, b
->used
) / 3;
7860 /* a = a2 * B**2 + a1 * B + a0 */
7861 if ((res
= mp_mod_2d(a
, DIGIT_BIT
* B
, &a0
)) != MP_OKAY
) {
7865 if ((res
= mp_copy(a
, &a1
)) != MP_OKAY
) {
7869 mp_mod_2d(&a1
, DIGIT_BIT
* B
, &a1
);
7871 if ((res
= mp_copy(a
, &a2
)) != MP_OKAY
) {
7876 /* b = b2 * B**2 + b1 * B + b0 */
7877 if ((res
= mp_mod_2d(b
, DIGIT_BIT
* B
, &b0
)) != MP_OKAY
) {
7881 if ((res
= mp_copy(b
, &b1
)) != MP_OKAY
) {
7885 mp_mod_2d(&b1
, DIGIT_BIT
* B
, &b1
);
7887 if ((res
= mp_copy(b
, &b2
)) != MP_OKAY
) {
7893 if ((res
= mp_mul(&a0
, &b0
, &w0
)) != MP_OKAY
) {
7898 if ((res
= mp_mul(&a2
, &b2
, &w4
)) != MP_OKAY
) {
7902 /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
7903 if ((res
= mp_mul_2(&a0
, &tmp1
)) != MP_OKAY
) {
7906 if ((res
= mp_add(&tmp1
, &a1
, &tmp1
)) != MP_OKAY
) {
7909 if ((res
= mp_mul_2(&tmp1
, &tmp1
)) != MP_OKAY
) {
7912 if ((res
= mp_add(&tmp1
, &a2
, &tmp1
)) != MP_OKAY
) {
7916 if ((res
= mp_mul_2(&b0
, &tmp2
)) != MP_OKAY
) {
7919 if ((res
= mp_add(&tmp2
, &b1
, &tmp2
)) != MP_OKAY
) {
7922 if ((res
= mp_mul_2(&tmp2
, &tmp2
)) != MP_OKAY
) {
7925 if ((res
= mp_add(&tmp2
, &b2
, &tmp2
)) != MP_OKAY
) {
7929 if ((res
= mp_mul(&tmp1
, &tmp2
, &w1
)) != MP_OKAY
) {
7933 /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
7934 if ((res
= mp_mul_2(&a2
, &tmp1
)) != MP_OKAY
) {
7937 if ((res
= mp_add(&tmp1
, &a1
, &tmp1
)) != MP_OKAY
) {
7940 if ((res
= mp_mul_2(&tmp1
, &tmp1
)) != MP_OKAY
) {
7943 if ((res
= mp_add(&tmp1
, &a0
, &tmp1
)) != MP_OKAY
) {
7947 if ((res
= mp_mul_2(&b2
, &tmp2
)) != MP_OKAY
) {
7950 if ((res
= mp_add(&tmp2
, &b1
, &tmp2
)) != MP_OKAY
) {
7953 if ((res
= mp_mul_2(&tmp2
, &tmp2
)) != MP_OKAY
) {
7956 if ((res
= mp_add(&tmp2
, &b0
, &tmp2
)) != MP_OKAY
) {
7960 if ((res
= mp_mul(&tmp1
, &tmp2
, &w3
)) != MP_OKAY
) {
7965 /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
7966 if ((res
= mp_add(&a2
, &a1
, &tmp1
)) != MP_OKAY
) {
7969 if ((res
= mp_add(&tmp1
, &a0
, &tmp1
)) != MP_OKAY
) {
7972 if ((res
= mp_add(&b2
, &b1
, &tmp2
)) != MP_OKAY
) {
7975 if ((res
= mp_add(&tmp2
, &b0
, &tmp2
)) != MP_OKAY
) {
7978 if ((res
= mp_mul(&tmp1
, &tmp2
, &w2
)) != MP_OKAY
) {
7982 /* now solve the matrix
7990 using 12 subtractions, 4 shifts,
7991 2 small divisions and 1 small multiplication
7995 if ((res
= mp_sub(&w1
, &w4
, &w1
)) != MP_OKAY
) {
7999 if ((res
= mp_sub(&w3
, &w0
, &w3
)) != MP_OKAY
) {
8003 if ((res
= mp_div_2(&w1
, &w1
)) != MP_OKAY
) {
8007 if ((res
= mp_div_2(&w3
, &w3
)) != MP_OKAY
) {
8011 if ((res
= mp_sub(&w2
, &w0
, &w2
)) != MP_OKAY
) {
8014 if ((res
= mp_sub(&w2
, &w4
, &w2
)) != MP_OKAY
) {
8018 if ((res
= mp_sub(&w1
, &w2
, &w1
)) != MP_OKAY
) {
8022 if ((res
= mp_sub(&w3
, &w2
, &w3
)) != MP_OKAY
) {
8026 if ((res
= mp_mul_2d(&w0
, 3, &tmp1
)) != MP_OKAY
) {
8029 if ((res
= mp_sub(&w1
, &tmp1
, &w1
)) != MP_OKAY
) {
8033 if ((res
= mp_mul_2d(&w4
, 3, &tmp1
)) != MP_OKAY
) {
8036 if ((res
= mp_sub(&w3
, &tmp1
, &w3
)) != MP_OKAY
) {
8040 if ((res
= mp_mul_d(&w2
, 3, &w2
)) != MP_OKAY
) {
8043 if ((res
= mp_sub(&w2
, &w1
, &w2
)) != MP_OKAY
) {
8046 if ((res
= mp_sub(&w2
, &w3
, &w2
)) != MP_OKAY
) {
8050 if ((res
= mp_sub(&w1
, &w2
, &w1
)) != MP_OKAY
) {
8054 if ((res
= mp_sub(&w3
, &w2
, &w3
)) != MP_OKAY
) {
8058 if ((res
= mp_div_3(&w1
, &w1
, NULL
)) != MP_OKAY
) {
8062 if ((res
= mp_div_3(&w3
, &w3
, NULL
)) != MP_OKAY
) {
8066 /* at this point shift W[n] by B*n */
8067 if ((res
= mp_lshd(&w1
, 1*B
)) != MP_OKAY
) {
8070 if ((res
= mp_lshd(&w2
, 2*B
)) != MP_OKAY
) {
8073 if ((res
= mp_lshd(&w3
, 3*B
)) != MP_OKAY
) {
8076 if ((res
= mp_lshd(&w4
, 4*B
)) != MP_OKAY
) {
8080 if ((res
= mp_add(&w0
, &w1
, c
)) != MP_OKAY
) {
8083 if ((res
= mp_add(&w2
, &w3
, &tmp1
)) != MP_OKAY
) {
8086 if ((res
= mp_add(&w4
, &tmp1
, &tmp1
)) != MP_OKAY
) {
8089 if ((res
= mp_add(&tmp1
, c
, c
)) != MP_OKAY
) {
8094 mp_clear_multi(&w0
, &w1
, &w2
, &w3
, &w4
,
8095 &a0
, &a1
, &a2
, &b0
, &b1
,
8096 &b2
, &tmp1
, &tmp2
, NULL
);
8102 /* $Source: /cvs/libtom/libtommath/bn_mp_toom_mul.c,v $ */
8103 /* $Revision: 1.3 $ */
8104 /* $Date: 2006/03/31 14:18:44 $ */
8106 /* End: bn_mp_toom_mul.c */
8108 /* Start: bn_mp_toom_sqr.c */
8109 #include <tommath.h>
8110 #ifdef BN_MP_TOOM_SQR_C
8111 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8113 * LibTomMath is a library that provides multiple-precision
8114 * integer arithmetic as well as number theoretic functionality.
8116 * The library was designed directly after the MPI library by
8117 * Michael Fromberger but has been written from scratch with
8118 * additional optimizations in place.
8120 * The library is free for all purposes without any express
8121 * guarantee it works.
8123 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
8126 /* squaring using Toom-Cook 3-way algorithm */
8128 mp_toom_sqr(mp_int
*a
, mp_int
*b
)
8130 mp_int w0
, w1
, w2
, w3
, w4
, tmp1
, a0
, a1
, a2
;
8134 if ((res
= mp_init_multi(&w0
, &w1
, &w2
, &w3
, &w4
, &a0
, &a1
, &a2
, &tmp1
, NULL
)) != MP_OKAY
) {
8141 /* a = a2 * B**2 + a1 * B + a0 */
8142 if ((res
= mp_mod_2d(a
, DIGIT_BIT
* B
, &a0
)) != MP_OKAY
) {
8146 if ((res
= mp_copy(a
, &a1
)) != MP_OKAY
) {
8150 mp_mod_2d(&a1
, DIGIT_BIT
* B
, &a1
);
8152 if ((res
= mp_copy(a
, &a2
)) != MP_OKAY
) {
8158 if ((res
= mp_sqr(&a0
, &w0
)) != MP_OKAY
) {
8163 if ((res
= mp_sqr(&a2
, &w4
)) != MP_OKAY
) {
8167 /* w1 = (a2 + 2(a1 + 2a0))**2 */
8168 if ((res
= mp_mul_2(&a0
, &tmp1
)) != MP_OKAY
) {
8171 if ((res
= mp_add(&tmp1
, &a1
, &tmp1
)) != MP_OKAY
) {
8174 if ((res
= mp_mul_2(&tmp1
, &tmp1
)) != MP_OKAY
) {
8177 if ((res
= mp_add(&tmp1
, &a2
, &tmp1
)) != MP_OKAY
) {
8181 if ((res
= mp_sqr(&tmp1
, &w1
)) != MP_OKAY
) {
8185 /* w3 = (a0 + 2(a1 + 2a2))**2 */
8186 if ((res
= mp_mul_2(&a2
, &tmp1
)) != MP_OKAY
) {
8189 if ((res
= mp_add(&tmp1
, &a1
, &tmp1
)) != MP_OKAY
) {
8192 if ((res
= mp_mul_2(&tmp1
, &tmp1
)) != MP_OKAY
) {
8195 if ((res
= mp_add(&tmp1
, &a0
, &tmp1
)) != MP_OKAY
) {
8199 if ((res
= mp_sqr(&tmp1
, &w3
)) != MP_OKAY
) {
8204 /* w2 = (a2 + a1 + a0)**2 */
8205 if ((res
= mp_add(&a2
, &a1
, &tmp1
)) != MP_OKAY
) {
8208 if ((res
= mp_add(&tmp1
, &a0
, &tmp1
)) != MP_OKAY
) {
8211 if ((res
= mp_sqr(&tmp1
, &w2
)) != MP_OKAY
) {
8215 /* now solve the matrix
8223 using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
8227 if ((res
= mp_sub(&w1
, &w4
, &w1
)) != MP_OKAY
) {
8231 if ((res
= mp_sub(&w3
, &w0
, &w3
)) != MP_OKAY
) {
8235 if ((res
= mp_div_2(&w1
, &w1
)) != MP_OKAY
) {
8239 if ((res
= mp_div_2(&w3
, &w3
)) != MP_OKAY
) {
8243 if ((res
= mp_sub(&w2
, &w0
, &w2
)) != MP_OKAY
) {
8246 if ((res
= mp_sub(&w2
, &w4
, &w2
)) != MP_OKAY
) {
8250 if ((res
= mp_sub(&w1
, &w2
, &w1
)) != MP_OKAY
) {
8254 if ((res
= mp_sub(&w3
, &w2
, &w3
)) != MP_OKAY
) {
8258 if ((res
= mp_mul_2d(&w0
, 3, &tmp1
)) != MP_OKAY
) {
8261 if ((res
= mp_sub(&w1
, &tmp1
, &w1
)) != MP_OKAY
) {
8265 if ((res
= mp_mul_2d(&w4
, 3, &tmp1
)) != MP_OKAY
) {
8268 if ((res
= mp_sub(&w3
, &tmp1
, &w3
)) != MP_OKAY
) {
8272 if ((res
= mp_mul_d(&w2
, 3, &w2
)) != MP_OKAY
) {
8275 if ((res
= mp_sub(&w2
, &w1
, &w2
)) != MP_OKAY
) {
8278 if ((res
= mp_sub(&w2
, &w3
, &w2
)) != MP_OKAY
) {
8282 if ((res
= mp_sub(&w1
, &w2
, &w1
)) != MP_OKAY
) {
8286 if ((res
= mp_sub(&w3
, &w2
, &w3
)) != MP_OKAY
) {
8290 if ((res
= mp_div_3(&w1
, &w1
, NULL
)) != MP_OKAY
) {
8294 if ((res
= mp_div_3(&w3
, &w3
, NULL
)) != MP_OKAY
) {
8298 /* at this point shift W[n] by B*n */
8299 if ((res
= mp_lshd(&w1
, 1*B
)) != MP_OKAY
) {
8302 if ((res
= mp_lshd(&w2
, 2*B
)) != MP_OKAY
) {
8305 if ((res
= mp_lshd(&w3
, 3*B
)) != MP_OKAY
) {
8308 if ((res
= mp_lshd(&w4
, 4*B
)) != MP_OKAY
) {
8312 if ((res
= mp_add(&w0
, &w1
, b
)) != MP_OKAY
) {
8315 if ((res
= mp_add(&w2
, &w3
, &tmp1
)) != MP_OKAY
) {
8318 if ((res
= mp_add(&w4
, &tmp1
, &tmp1
)) != MP_OKAY
) {
8321 if ((res
= mp_add(&tmp1
, b
, b
)) != MP_OKAY
) {
8326 mp_clear_multi(&w0
, &w1
, &w2
, &w3
, &w4
, &a0
, &a1
, &a2
, &tmp1
, NULL
);
8332 /* $Source: /cvs/libtom/libtommath/bn_mp_toom_sqr.c,v $ */
8333 /* $Revision: 1.3 $ */
8334 /* $Date: 2006/03/31 14:18:44 $ */
8336 /* End: bn_mp_toom_sqr.c */
8338 /* Start: bn_mp_toradix.c */
8339 #include <tommath.h>
8340 #ifdef BN_MP_TORADIX_C
8341 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8343 * LibTomMath is a library that provides multiple-precision
8344 * integer arithmetic as well as number theoretic functionality.
8346 * The library was designed directly after the MPI library by
8347 * Michael Fromberger but has been written from scratch with
8348 * additional optimizations in place.
8350 * The library is free for all purposes without any express
8351 * guarantee it works.
8353 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
8356 /* stores a bignum as a ASCII string in a given radix (2..64) */
8357 int mp_toradix (mp_int
* a
, char *str
, int radix
)
8364 /* check range of the radix */
8365 if (radix
< 2 || radix
> 64) {
8369 /* quick out if its zero */
8370 if (mp_iszero(a
) == 1) {
8376 if ((res
= mp_init_copy (&t
, a
)) != MP_OKAY
) {
8380 /* if it is negative output a - */
8381 if (t
.sign
== MP_NEG
) {
8388 while (mp_iszero (&t
) == 0) {
8389 if ((res
= mp_div_d (&t
, (mp_digit
) radix
, &t
, &d
)) != MP_OKAY
) {
8393 *str
++ = mp_s_rmap
[d
];
8397 /* reverse the digits of the string. In this case _s points
8398 * to the first digit [exluding the sign] of the number]
8400 bn_reverse ((unsigned char *)_s
, digs
);
8402 /* append a NULL so the string is properly terminated */
8411 /* $Source: /cvs/libtom/libtommath/bn_mp_toradix.c,v $ */
8412 /* $Revision: 1.3 $ */
8413 /* $Date: 2006/03/31 14:18:44 $ */
8415 /* End: bn_mp_toradix.c */
8417 /* Start: bn_mp_toradix_n.c */
8418 #include <tommath.h>
8419 #ifdef BN_MP_TORADIX_N_C
8420 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8422 * LibTomMath is a library that provides multiple-precision
8423 * integer arithmetic as well as number theoretic functionality.
8425 * The library was designed directly after the MPI library by
8426 * Michael Fromberger but has been written from scratch with
8427 * additional optimizations in place.
8429 * The library is free for all purposes without any express
8430 * guarantee it works.
8432 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
8435 /* stores a bignum as a ASCII string in a given radix (2..64)
8437 * Stores upto maxlen-1 chars and always a NULL byte
8439 int mp_toradix_n(mp_int
* a
, char *str
, int radix
, int maxlen
)
8446 /* check range of the maxlen, radix */
8447 if (maxlen
< 2 || radix
< 2 || radix
> 64) {
8451 /* quick out if its zero */
8452 if (mp_iszero(a
) == MP_YES
) {
8458 if ((res
= mp_init_copy (&t
, a
)) != MP_OKAY
) {
8462 /* if it is negative output a - */
8463 if (t
.sign
== MP_NEG
) {
8464 /* we have to reverse our digits later... but not the - sign!! */
8467 /* store the flag and mark the number as positive */
8471 /* subtract a char */
8476 while (mp_iszero (&t
) == 0) {
8481 if ((res
= mp_div_d (&t
, (mp_digit
) radix
, &t
, &d
)) != MP_OKAY
) {
8485 *str
++ = mp_s_rmap
[d
];
8489 /* reverse the digits of the string. In this case _s points
8490 * to the first digit [exluding the sign] of the number
8492 bn_reverse ((unsigned char *)_s
, digs
);
8494 /* append a NULL so the string is properly terminated */
8503 /* $Source: /cvs/libtom/libtommath/bn_mp_toradix_n.c,v $ */
8504 /* $Revision: 1.4 $ */
8505 /* $Date: 2006/03/31 14:18:44 $ */
8507 /* End: bn_mp_toradix_n.c */
8509 /* Start: bn_mp_unsigned_bin_size.c */
8510 #include <tommath.h>
8511 #ifdef BN_MP_UNSIGNED_BIN_SIZE_C
8512 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8514 * LibTomMath is a library that provides multiple-precision
8515 * integer arithmetic as well as number theoretic functionality.
8517 * The library was designed directly after the MPI library by
8518 * Michael Fromberger but has been written from scratch with
8519 * additional optimizations in place.
8521 * The library is free for all purposes without any express
8522 * guarantee it works.
8524 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
8527 /* get the size for an unsigned equivalent */
8528 int mp_unsigned_bin_size (mp_int
* a
)
8530 int size
= mp_count_bits (a
);
8531 return (size
/ 8 + ((size
& 7) != 0 ? 1 : 0));
8535 /* $Source: /cvs/libtom/libtommath/bn_mp_unsigned_bin_size.c,v $ */
8536 /* $Revision: 1.3 $ */
8537 /* $Date: 2006/03/31 14:18:44 $ */
8539 /* End: bn_mp_unsigned_bin_size.c */
8541 /* Start: bn_mp_xor.c */
8542 #include <tommath.h>
8544 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8546 * LibTomMath is a library that provides multiple-precision
8547 * integer arithmetic as well as number theoretic functionality.
8549 * The library was designed directly after the MPI library by
8550 * Michael Fromberger but has been written from scratch with
8551 * additional optimizations in place.
8553 * The library is free for all purposes without any express
8554 * guarantee it works.
8556 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
8559 /* XOR two ints together */
8561 mp_xor (mp_int
* a
, mp_int
* b
, mp_int
* c
)
8566 if (a
->used
> b
->used
) {
8567 if ((res
= mp_init_copy (&t
, a
)) != MP_OKAY
) {
8573 if ((res
= mp_init_copy (&t
, b
)) != MP_OKAY
) {
8580 for (ix
= 0; ix
< px
; ix
++) {
8581 t
.dp
[ix
] ^= x
->dp
[ix
];
8590 /* $Source: /cvs/libtom/libtommath/bn_mp_xor.c,v $ */
8591 /* $Revision: 1.3 $ */
8592 /* $Date: 2006/03/31 14:18:44 $ */
8594 /* End: bn_mp_xor.c */
8596 /* Start: bn_mp_zero.c */
8597 #include <tommath.h>
8599 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8601 * LibTomMath is a library that provides multiple-precision
8602 * integer arithmetic as well as number theoretic functionality.
8604 * The library was designed directly after the MPI library by
8605 * Michael Fromberger but has been written from scratch with
8606 * additional optimizations in place.
8608 * The library is free for all purposes without any express
8609 * guarantee it works.
8611 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
8615 void mp_zero (mp_int
* a
)
8624 for (n
= 0; n
< a
->alloc
; n
++) {
8630 /* $Source: /cvs/libtom/libtommath/bn_mp_zero.c,v $ */
8631 /* $Revision: 1.3 $ */
8632 /* $Date: 2006/03/31 14:18:44 $ */
8634 /* End: bn_mp_zero.c */
8636 /* Start: bn_prime_tab.c */
8637 #include <tommath.h>
8638 #ifdef BN_PRIME_TAB_C
8639 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8641 * LibTomMath is a library that provides multiple-precision
8642 * integer arithmetic as well as number theoretic functionality.
8644 * The library was designed directly after the MPI library by
8645 * Michael Fromberger but has been written from scratch with
8646 * additional optimizations in place.
8648 * The library is free for all purposes without any express
8649 * guarantee it works.
8651 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
8653 const mp_digit ltm_prime_tab
[] = {
8654 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
8655 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
8656 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
8657 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
8660 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
8661 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
8662 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
8663 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
8665 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
8666 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
8667 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
8668 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
8669 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
8670 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
8671 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
8672 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
8674 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
8675 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
8676 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
8677 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
8678 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
8679 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
8680 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
8681 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
8683 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
8684 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
8685 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
8686 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
8687 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
8688 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
8689 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
8690 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
8695 /* $Source: /cvs/libtom/libtommath/bn_prime_tab.c,v $ */
8696 /* $Revision: 1.3 $ */
8697 /* $Date: 2006/03/31 14:18:44 $ */
8699 /* End: bn_prime_tab.c */
8701 /* Start: bn_reverse.c */
8702 #include <tommath.h>
8704 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8706 * LibTomMath is a library that provides multiple-precision
8707 * integer arithmetic as well as number theoretic functionality.
8709 * The library was designed directly after the MPI library by
8710 * Michael Fromberger but has been written from scratch with
8711 * additional optimizations in place.
8713 * The library is free for all purposes without any express
8714 * guarantee it works.
8716 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
8719 /* reverse an array, used for radix code */
8721 bn_reverse (unsigned char *s
, int len
)
8738 /* $Source: /cvs/libtom/libtommath/bn_reverse.c,v $ */
8739 /* $Revision: 1.3 $ */
8740 /* $Date: 2006/03/31 14:18:44 $ */
8742 /* End: bn_reverse.c */
8744 /* Start: bn_s_mp_add.c */
8745 #include <tommath.h>
8746 #ifdef BN_S_MP_ADD_C
8747 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8749 * LibTomMath is a library that provides multiple-precision
8750 * integer arithmetic as well as number theoretic functionality.
8752 * The library was designed directly after the MPI library by
8753 * Michael Fromberger but has been written from scratch with
8754 * additional optimizations in place.
8756 * The library is free for all purposes without any express
8757 * guarantee it works.
8759 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
8762 /* low level addition, based on HAC pp.594, Algorithm 14.7 */
8764 s_mp_add (mp_int
* a
, mp_int
* b
, mp_int
* c
)
8767 int olduse
, res
, min
, max
;
8769 /* find sizes, we let |a| <= |b| which means we have to sort
8770 * them. "x" will point to the input with the most digits
8772 if (a
->used
> b
->used
) {
8783 if (c
->alloc
< max
+ 1) {
8784 if ((res
= mp_grow (c
, max
+ 1)) != MP_OKAY
) {
8789 /* get old used digit count and set new one */
8794 register mp_digit u
, *tmpa
, *tmpb
, *tmpc
;
8797 /* alias for digit pointers */
8808 /* zero the carry */
8810 for (i
= 0; i
< min
; i
++) {
8811 /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
8812 *tmpc
= *tmpa
++ + *tmpb
++ + u
;
8814 /* U = carry bit of T[i] */
8815 u
= *tmpc
>> ((mp_digit
)DIGIT_BIT
);
8817 /* take away carry bit from T[i] */
8821 /* now copy higher words if any, that is in A+B
8822 * if A or B has more digits add those in
8825 for (; i
< max
; i
++) {
8826 /* T[i] = X[i] + U */
8827 *tmpc
= x
->dp
[i
] + u
;
8829 /* U = carry bit of T[i] */
8830 u
= *tmpc
>> ((mp_digit
)DIGIT_BIT
);
8832 /* take away carry bit from T[i] */
8840 /* clear digits above oldused */
8841 for (i
= c
->used
; i
< olduse
; i
++) {
8851 /* $Source: /cvs/libtom/libtommath/bn_s_mp_add.c,v $ */
8852 /* $Revision: 1.3 $ */
8853 /* $Date: 2006/03/31 14:18:44 $ */
8855 /* End: bn_s_mp_add.c */
8857 /* Start: bn_s_mp_exptmod.c */
8858 #include <tommath.h>
8859 #ifdef BN_S_MP_EXPTMOD_C
8860 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8862 * LibTomMath is a library that provides multiple-precision
8863 * integer arithmetic as well as number theoretic functionality.
8865 * The library was designed directly after the MPI library by
8866 * Michael Fromberger but has been written from scratch with
8867 * additional optimizations in place.
8869 * The library is free for all purposes without any express
8870 * guarantee it works.
8872 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
8877 #define TAB_SIZE 256
8880 int s_mp_exptmod (mp_int
* G
, mp_int
* X
, mp_int
* P
, mp_int
* Y
, int redmode
)
8882 mp_int M
[TAB_SIZE
], res
, mu
;
8884 int err
, bitbuf
, bitcpy
, bitcnt
, mode
, digidx
, x
, y
, winsize
;
8885 int (*redux
)(mp_int
*,mp_int
*,mp_int
*);
8887 /* find window size */
8888 x
= mp_count_bits (X
);
8891 } else if (x
<= 36) {
8893 } else if (x
<= 140) {
8895 } else if (x
<= 450) {
8897 } else if (x
<= 1303) {
8899 } else if (x
<= 3529) {
8912 /* init first cell */
8913 if ((err
= mp_init(&M
[1])) != MP_OKAY
) {
8917 /* now init the second half of the array */
8918 for (x
= 1<<(winsize
-1); x
< (1 << winsize
); x
++) {
8919 if ((err
= mp_init(&M
[x
])) != MP_OKAY
) {
8920 for (y
= 1<<(winsize
-1); y
< x
; y
++) {
8928 /* create mu, used for Barrett reduction */
8929 if ((err
= mp_init (&mu
)) != MP_OKAY
) {
8934 if ((err
= mp_reduce_setup (&mu
, P
)) != MP_OKAY
) {
8939 if ((err
= mp_reduce_2k_setup_l (P
, &mu
)) != MP_OKAY
) {
8942 redux
= mp_reduce_2k_l
;
8947 * The M table contains powers of the base,
8948 * e.g. M[x] = G**x mod P
8950 * The first half of the table is not
8951 * computed though accept for M[0] and M[1]
8953 if ((err
= mp_mod (G
, P
, &M
[1])) != MP_OKAY
) {
8957 /* compute the value at M[1<<(winsize-1)] by squaring
8958 * M[1] (winsize-1) times
8960 if ((err
= mp_copy (&M
[1], &M
[1 << (winsize
- 1)])) != MP_OKAY
) {
8964 for (x
= 0; x
< (winsize
- 1); x
++) {
8966 if ((err
= mp_sqr (&M
[1 << (winsize
- 1)],
8967 &M
[1 << (winsize
- 1)])) != MP_OKAY
) {
8971 /* reduce modulo P */
8972 if ((err
= redux (&M
[1 << (winsize
- 1)], P
, &mu
)) != MP_OKAY
) {
8977 /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
8978 * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
8980 for (x
= (1 << (winsize
- 1)) + 1; x
< (1 << winsize
); x
++) {
8981 if ((err
= mp_mul (&M
[x
- 1], &M
[1], &M
[x
])) != MP_OKAY
) {
8984 if ((err
= redux (&M
[x
], P
, &mu
)) != MP_OKAY
) {
8990 if ((err
= mp_init (&res
)) != MP_OKAY
) {
8995 /* set initial mode and bit cnt */
8999 digidx
= X
->used
- 1;
9004 /* grab next digit as required */
9005 if (--bitcnt
== 0) {
9006 /* if digidx == -1 we are out of digits */
9010 /* read next digit and reset the bitcnt */
9011 buf
= X
->dp
[digidx
--];
9012 bitcnt
= (int) DIGIT_BIT
;
9015 /* grab the next msb from the exponent */
9016 y
= (buf
>> (mp_digit
)(DIGIT_BIT
- 1)) & 1;
9017 buf
<<= (mp_digit
)1;
9019 /* if the bit is zero and mode == 0 then we ignore it
9020 * These represent the leading zero bits before the first 1 bit
9021 * in the exponent. Technically this opt is not required but it
9022 * does lower the # of trivial squaring/reductions used
9024 if (mode
== 0 && y
== 0) {
9028 /* if the bit is zero and mode == 1 then we square */
9029 if (mode
== 1 && y
== 0) {
9030 if ((err
= mp_sqr (&res
, &res
)) != MP_OKAY
) {
9033 if ((err
= redux (&res
, P
, &mu
)) != MP_OKAY
) {
9039 /* else we add it to the window */
9040 bitbuf
|= (y
<< (winsize
- ++bitcpy
));
9043 if (bitcpy
== winsize
) {
9044 /* ok window is filled so square as required and multiply */
9046 for (x
= 0; x
< winsize
; x
++) {
9047 if ((err
= mp_sqr (&res
, &res
)) != MP_OKAY
) {
9050 if ((err
= redux (&res
, P
, &mu
)) != MP_OKAY
) {
9056 if ((err
= mp_mul (&res
, &M
[bitbuf
], &res
)) != MP_OKAY
) {
9059 if ((err
= redux (&res
, P
, &mu
)) != MP_OKAY
) {
9063 /* empty window and reset */
9070 /* if bits remain then square/multiply */
9071 if (mode
== 2 && bitcpy
> 0) {
9072 /* square then multiply if the bit is set */
9073 for (x
= 0; x
< bitcpy
; x
++) {
9074 if ((err
= mp_sqr (&res
, &res
)) != MP_OKAY
) {
9077 if ((err
= redux (&res
, P
, &mu
)) != MP_OKAY
) {
9082 if ((bitbuf
& (1 << winsize
)) != 0) {
9084 if ((err
= mp_mul (&res
, &M
[1], &res
)) != MP_OKAY
) {
9087 if ((err
= redux (&res
, P
, &mu
)) != MP_OKAY
) {
9096 LBL_RES
:mp_clear (&res
);
9097 LBL_MU
:mp_clear (&mu
);
9100 for (x
= 1<<(winsize
-1); x
< (1 << winsize
); x
++) {
9107 /* $Source: /cvs/libtom/libtommath/bn_s_mp_exptmod.c,v $ */
9108 /* $Revision: 1.4 $ */
9109 /* $Date: 2006/03/31 14:18:44 $ */
9111 /* End: bn_s_mp_exptmod.c */
9113 /* Start: bn_s_mp_mul_digs.c */
9114 #include <tommath.h>
9115 #ifdef BN_S_MP_MUL_DIGS_C
9116 /* LibTomMath, multiple-precision integer library -- Tom St Denis
9118 * LibTomMath is a library that provides multiple-precision
9119 * integer arithmetic as well as number theoretic functionality.
9121 * The library was designed directly after the MPI library by
9122 * Michael Fromberger but has been written from scratch with
9123 * additional optimizations in place.
9125 * The library is free for all purposes without any express
9126 * guarantee it works.
9128 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
9131 /* multiplies |a| * |b| and only computes upto digs digits of result
9132 * HAC pp. 595, Algorithm 14.12 Modified so you can control how
9133 * many digits of output are created.
9135 int s_mp_mul_digs (mp_int
* a
, mp_int
* b
, mp_int
* c
, int digs
)
9138 int res
, pa
, pb
, ix
, iy
;
9141 mp_digit tmpx
, *tmpt
, *tmpy
;
9143 /* can we use the fast multiplier? */
9144 if (((digs
) < MP_WARRAY
) &&
9145 MIN (a
->used
, b
->used
) <
9146 (1 << ((CHAR_BIT
* sizeof (mp_word
)) - (2 * DIGIT_BIT
)))) {
9147 return fast_s_mp_mul_digs (a
, b
, c
, digs
);
9150 if ((res
= mp_init_size (&t
, digs
)) != MP_OKAY
) {
9155 /* compute the digits of the product directly */
9157 for (ix
= 0; ix
< pa
; ix
++) {
9158 /* set the carry to zero */
9161 /* limit ourselves to making digs digits of output */
9162 pb
= MIN (b
->used
, digs
- ix
);
9164 /* setup some aliases */
9165 /* copy of the digit from a used within the nested loop */
9168 /* an alias for the destination shifted ix places */
9171 /* an alias for the digits of b */
9174 /* compute the columns of the output and propagate the carry */
9175 for (iy
= 0; iy
< pb
; iy
++) {
9176 /* compute the column as a mp_word */
9177 r
= ((mp_word
)*tmpt
) +
9178 ((mp_word
)tmpx
) * ((mp_word
)*tmpy
++) +
9181 /* the new column is the lower part of the result */
9182 *tmpt
++ = (mp_digit
) (r
& ((mp_word
) MP_MASK
));
9184 /* get the carry word from the result */
9185 u
= (mp_digit
) (r
>> ((mp_word
) DIGIT_BIT
));
9187 /* set carry if it is placed below digs */
9188 if (ix
+ iy
< digs
) {
9201 /* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_digs.c,v $ */
9202 /* $Revision: 1.3 $ */
9203 /* $Date: 2006/03/31 14:18:44 $ */
9205 /* End: bn_s_mp_mul_digs.c */
9207 /* Start: bn_s_mp_mul_high_digs.c */
9208 #include <tommath.h>
9209 #ifdef BN_S_MP_MUL_HIGH_DIGS_C
9210 /* LibTomMath, multiple-precision integer library -- Tom St Denis
9212 * LibTomMath is a library that provides multiple-precision
9213 * integer arithmetic as well as number theoretic functionality.
9215 * The library was designed directly after the MPI library by
9216 * Michael Fromberger but has been written from scratch with
9217 * additional optimizations in place.
9219 * The library is free for all purposes without any express
9220 * guarantee it works.
9222 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
9225 /* multiplies |a| * |b| and does not compute the lower digs digits
9226 * [meant to get the higher part of the product]
9229 s_mp_mul_high_digs (mp_int
* a
, mp_int
* b
, mp_int
* c
, int digs
)
9232 int res
, pa
, pb
, ix
, iy
;
9235 mp_digit tmpx
, *tmpt
, *tmpy
;
9237 /* can we use the fast multiplier? */
9238 #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
9239 if (((a
->used
+ b
->used
+ 1) < MP_WARRAY
)
9240 && MIN (a
->used
, b
->used
) < (1 << ((CHAR_BIT
* sizeof (mp_word
)) - (2 * DIGIT_BIT
)))) {
9241 return fast_s_mp_mul_high_digs (a
, b
, c
, digs
);
9245 if ((res
= mp_init_size (&t
, a
->used
+ b
->used
+ 1)) != MP_OKAY
) {
9248 t
.used
= a
->used
+ b
->used
+ 1;
9252 for (ix
= 0; ix
< pa
; ix
++) {
9253 /* clear the carry */
9256 /* left hand side of A[ix] * B[iy] */
9259 /* alias to the address of where the digits will be stored */
9260 tmpt
= &(t
.dp
[digs
]);
9262 /* alias for where to read the right hand side from */
9263 tmpy
= b
->dp
+ (digs
- ix
);
9265 for (iy
= digs
- ix
; iy
< pb
; iy
++) {
9266 /* calculate the double precision result */
9267 r
= ((mp_word
)*tmpt
) +
9268 ((mp_word
)tmpx
) * ((mp_word
)*tmpy
++) +
9271 /* get the lower part */
9272 *tmpt
++ = (mp_digit
) (r
& ((mp_word
) MP_MASK
));
9274 /* carry the carry */
9275 u
= (mp_digit
) (r
>> ((mp_word
) DIGIT_BIT
));
9286 /* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_high_digs.c,v $ */
9287 /* $Revision: 1.3 $ */
9288 /* $Date: 2006/03/31 14:18:44 $ */
9290 /* End: bn_s_mp_mul_high_digs.c */
9292 /* Start: bn_s_mp_sqr.c */
9293 #include <tommath.h>
9294 #ifdef BN_S_MP_SQR_C
9295 /* LibTomMath, multiple-precision integer library -- Tom St Denis
9297 * LibTomMath is a library that provides multiple-precision
9298 * integer arithmetic as well as number theoretic functionality.
9300 * The library was designed directly after the MPI library by
9301 * Michael Fromberger but has been written from scratch with
9302 * additional optimizations in place.
9304 * The library is free for all purposes without any express
9305 * guarantee it works.
9307 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
9310 /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
9311 int s_mp_sqr (mp_int
* a
, mp_int
* b
)
9314 int res
, ix
, iy
, pa
;
9316 mp_digit u
, tmpx
, *tmpt
;
9319 if ((res
= mp_init_size (&t
, 2*pa
+ 1)) != MP_OKAY
) {
9323 /* default used is maximum possible size */
9326 for (ix
= 0; ix
< pa
; ix
++) {
9327 /* first calculate the digit at 2*ix */
9328 /* calculate double precision result */
9329 r
= ((mp_word
) t
.dp
[2*ix
]) +
9330 ((mp_word
)a
->dp
[ix
])*((mp_word
)a
->dp
[ix
]);
9332 /* store lower part in result */
9333 t
.dp
[ix
+ix
] = (mp_digit
) (r
& ((mp_word
) MP_MASK
));
9336 u
= (mp_digit
)(r
>> ((mp_word
) DIGIT_BIT
));
9338 /* left hand side of A[ix] * A[iy] */
9341 /* alias for where to store the results */
9342 tmpt
= t
.dp
+ (2*ix
+ 1);
9344 for (iy
= ix
+ 1; iy
< pa
; iy
++) {
9345 /* first calculate the product */
9346 r
= ((mp_word
)tmpx
) * ((mp_word
)a
->dp
[iy
]);
9348 /* now calculate the double precision result, note we use
9349 * addition instead of *2 since it's easier to optimize
9351 r
= ((mp_word
) *tmpt
) + r
+ r
+ ((mp_word
) u
);
9353 /* store lower part */
9354 *tmpt
++ = (mp_digit
) (r
& ((mp_word
) MP_MASK
));
9357 u
= (mp_digit
)(r
>> ((mp_word
) DIGIT_BIT
));
9359 /* propagate upwards */
9360 while (u
!= ((mp_digit
) 0)) {
9361 r
= ((mp_word
) *tmpt
) + ((mp_word
) u
);
9362 *tmpt
++ = (mp_digit
) (r
& ((mp_word
) MP_MASK
));
9363 u
= (mp_digit
)(r
>> ((mp_word
) DIGIT_BIT
));
9374 /* $Source: /cvs/libtom/libtommath/bn_s_mp_sqr.c,v $ */
9375 /* $Revision: 1.3 $ */
9376 /* $Date: 2006/03/31 14:18:44 $ */
9378 /* End: bn_s_mp_sqr.c */
9380 /* Start: bn_s_mp_sub.c */
9381 #include <tommath.h>
9382 #ifdef BN_S_MP_SUB_C
9383 /* LibTomMath, multiple-precision integer library -- Tom St Denis
9385 * LibTomMath is a library that provides multiple-precision
9386 * integer arithmetic as well as number theoretic functionality.
9388 * The library was designed directly after the MPI library by
9389 * Michael Fromberger but has been written from scratch with
9390 * additional optimizations in place.
9392 * The library is free for all purposes without any express
9393 * guarantee it works.
9395 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
9398 /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
9400 s_mp_sub (mp_int
* a
, mp_int
* b
, mp_int
* c
)
9402 int olduse
, res
, min
, max
;
9409 if (c
->alloc
< max
) {
9410 if ((res
= mp_grow (c
, max
)) != MP_OKAY
) {
9418 register mp_digit u
, *tmpa
, *tmpb
, *tmpc
;
9421 /* alias for digit pointers */
9426 /* set carry to zero */
9428 for (i
= 0; i
< min
; i
++) {
9429 /* T[i] = A[i] - B[i] - U */
9430 *tmpc
= *tmpa
++ - *tmpb
++ - u
;
9432 /* U = carry bit of T[i]
9433 * Note this saves performing an AND operation since
9434 * if a carry does occur it will propagate all the way to the
9435 * MSB. As a result a single shift is enough to get the carry
9437 u
= *tmpc
>> ((mp_digit
)(CHAR_BIT
* sizeof (mp_digit
) - 1));
9439 /* Clear carry from T[i] */
9443 /* now copy higher words if any, e.g. if A has more digits than B */
9444 for (; i
< max
; i
++) {
9445 /* T[i] = A[i] - U */
9446 *tmpc
= *tmpa
++ - u
;
9448 /* U = carry bit of T[i] */
9449 u
= *tmpc
>> ((mp_digit
)(CHAR_BIT
* sizeof (mp_digit
) - 1));
9451 /* Clear carry from T[i] */
9455 /* clear digits above used (since we may not have grown result above) */
9456 for (i
= c
->used
; i
< olduse
; i
++) {
9467 /* $Source: /cvs/libtom/libtommath/bn_s_mp_sub.c,v $ */
9468 /* $Revision: 1.3 $ */
9469 /* $Date: 2006/03/31 14:18:44 $ */
9471 /* End: bn_s_mp_sub.c */
9473 /* Start: bncore.c */
9474 #include <tommath.h>
9476 /* LibTomMath, multiple-precision integer library -- Tom St Denis
9478 * LibTomMath is a library that provides multiple-precision
9479 * integer arithmetic as well as number theoretic functionality.
9481 * The library was designed directly after the MPI library by
9482 * Michael Fromberger but has been written from scratch with
9483 * additional optimizations in place.
9485 * The library is free for all purposes without any express
9486 * guarantee it works.
9488 * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
9491 /* Known optimal configurations
9493 CPU /Compiler /MUL CUTOFF/SQR CUTOFF
9494 -------------------------------------------------------------
9495 Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-)
9496 AMD Athlon64 /GCC v3.4.4 / 80/ 120/LTM 0.35
9500 int KARATSUBA_MUL_CUTOFF
= 80, /* Min. number of digits before Karatsuba multiplication is used. */
9501 KARATSUBA_SQR_CUTOFF
= 120, /* Min. number of digits before Karatsuba squaring is used. */
9503 TOOM_MUL_CUTOFF
= 350, /* no optimal values of these are known yet so set em high */
9504 TOOM_SQR_CUTOFF
= 400;
9507 /* $Source: /cvs/libtom/libtommath/bncore.c,v $ */
9508 /* $Revision: 1.4 $ */
9509 /* $Date: 2006/03/31 14:18:44 $ */