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