Mercurial > dropbear
comparison pre_gen/mpi.c @ 1:22d5cf7d4b1a libtommath
Renaming branch
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 31 May 2004 18:23:46 +0000 |
parents | |
children | d29b64170cf0 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 1:22d5cf7d4b1a |
---|---|
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 */ |