comparison pre_gen/mpi.c @ 2:86e0b50a9b58 libtommath-orig ltm-0.30-orig

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