1 /*
2 * Copyright (c) 2002 Bob Deblier
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19
20 /*!\file mpbarrett.c
21 * \brief Multi-precision integer routines using Barrett modular reduction.
22 * For more information on this algorithm, see:
23 * "Handbook of Applied Cryptography", Chapter 14.3.3
24 * Menezes, van Oorschot, Vanstone
25 * CRC Press
26 * \author Bob Deblier <bob.deblier@telenet.be>
27 * \ingroup MP__m
28 */
29
30 #define BEECRYPT_DLL_EXPORT
31
32 #if HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include "beecrypt/beecrypt.h"
37 #include "beecrypt/mpprime.h"
38 #include "beecrypt/mpnumber.h"
39 #include "beecrypt/mpbarrett.h"
40
41 /*
42 * mpbzero
43 */
mpbzero(mpbarrett * b)44 void mpbzero(mpbarrett* b)
45 {
46 b->size = 0;
47 b->modl = b->mu = (mpw*) 0;
48 }
49
50 /*
51 * mpbinit
52 * \brief allocates the data words for an mpbarrett structure
53 * will allocate 2*size+1 words
54 */
mpbinit(mpbarrett * b,size_t size)55 void mpbinit(mpbarrett* b, size_t size)
56 {
57 b->size = size;
58 b->modl = (mpw*) calloc(2*size+1, sizeof(mpw));
59
60 if (b->modl != (mpw*) 0)
61 b->mu = b->modl+size;
62 else
63 b->mu = (mpw*) 0;
64 }
65
66 /*
67 * mpbfree
68 */
mpbfree(mpbarrett * b)69 void mpbfree(mpbarrett* b)
70 {
71 if (b->modl != (mpw*) 0)
72 {
73 free(b->modl);
74 b->modl = b->mu = (mpw*) 0;
75 }
76 b->size = 0;
77 }
78
mpbcopy(mpbarrett * b,const mpbarrett * copy)79 void mpbcopy(mpbarrett* b, const mpbarrett* copy)
80 {
81 register size_t size = copy->size;
82
83 if (size)
84 {
85 if (b->modl)
86 {
87 if (b->size != size)
88 b->modl = (mpw*) realloc(b->modl, (2*size+1) * sizeof(mpw));
89 }
90 else
91 b->modl = (mpw*) malloc((2*size+1) * sizeof(mpw));
92
93 if (b->modl)
94 {
95 b->size = size;
96 b->mu = b->modl+copy->size;
97 mpcopy(2*size+1, b->modl, copy->modl);
98 }
99 else
100 {
101 b->size = 0;
102 b->mu = (mpw*) 0;
103 }
104 }
105 else if (b->modl)
106 {
107 free(b->modl);
108 b->size = 0;
109 b->modl = b->mu = (mpw*) 0;
110 }
111 }
112
mpbwipe(mpbarrett * b)113 void mpbwipe(mpbarrett* b)
114 {
115 if (b->modl != (mpw*) 0)
116 mpzero(2*(b->size)+1, b->modl);
117 }
118
119 /*
120 * mpbset
121 */
mpbset(mpbarrett * b,size_t size,const mpw * data)122 void mpbset(mpbarrett* b, size_t size, const mpw *data)
123 {
124 if (size > 0)
125 {
126 if (b->modl)
127 {
128 if (b->size != size)
129 b->modl = (mpw*) realloc(b->modl, (2*size+1) * sizeof(mpw));
130 }
131 else
132 b->modl = (mpw*) malloc((2*size+1) * sizeof(mpw));
133
134 if (b->modl)
135 {
136 mpw* temp = (mpw*) malloc((6*size+4) * sizeof(mpw));
137
138 b->size = size;
139 b->mu = b->modl+size;
140 mpcopy(size, b->modl, data);
141 mpbmu_w(b, temp);
142
143 free(temp);
144 }
145 else
146 {
147 b->size = 0;
148 b->mu = (mpw*) 0;
149 }
150 }
151 }
152
mpbsetbin(mpbarrett * b,const byte * osdata,size_t ossize)153 int mpbsetbin(mpbarrett* b, const byte* osdata, size_t ossize)
154 {
155 int rc = -1;
156 size_t size;
157
158 /* skip zero bytes */
159 while (!(*osdata) && ossize)
160 {
161 osdata++;
162 ossize--;
163 }
164
165 size = MP_BYTES_TO_WORDS(ossize + MP_WBYTES - 1);
166
167 if (b->modl)
168 {
169 if (b->size != size)
170 b->modl = (mpw*) realloc(b->modl, (2*size+1) * sizeof(mpw));
171 }
172 else
173 b->modl = (mpw*) malloc((2*size+1) * sizeof(mpw));
174
175 if (b->modl)
176 {
177 register mpw* temp = (mpw*) malloc((6*size+4) * sizeof(mpw));
178
179 b->size = size;
180 b->mu = b->modl+size;
181
182 rc = os2ip(b->modl, size, osdata, ossize);
183
184 mpbmu_w(b, temp);
185
186 free(temp);
187 }
188
189 return rc;
190 }
191
mpbsethex(mpbarrett * b,const char * hex)192 int mpbsethex(mpbarrett* b, const char* hex)
193 {
194 int rc = -1;
195 size_t len = strlen(hex);
196 size_t size = MP_NIBBLES_TO_WORDS(len + MP_WNIBBLES - 1);
197
198 if (b->modl)
199 {
200 if (b->size != size)
201 b->modl = (mpw*) realloc(b->modl, (2*size+1) * sizeof(mpw));
202 }
203 else
204 b->modl = (mpw*) malloc((2*size+1) * sizeof(mpw));
205
206 if (b->modl)
207 {
208 register mpw* temp = (mpw*) malloc((6*size+4) * sizeof(mpw));
209
210 b->size = size;
211 b->mu = b->modl+size;
212
213 rc = hs2ip(b->modl, size, hex, len);
214
215 mpbmu_w(b, temp);
216
217 free(temp);
218 }
219 else
220 {
221 b->size = 0;
222 b->mu = 0;
223 }
224
225 return rc;
226 }
227
228 /*
229 * mpbmu_w
230 * computes the Barrett 'mu' coefficient
231 * needs workspace of (6*size+4) words
232 */
mpbmu_w(mpbarrett * b,mpw * wksp)233 void mpbmu_w(mpbarrett* b, mpw* wksp)
234 {
235 register size_t size = b->size;
236 register size_t shift;
237 register mpw* divmod = wksp;
238 register mpw* dividend = divmod+(size*2+2);
239 register mpw* workspace = dividend+(size*2+1);
240
241 /* normalize modulus before division */
242 shift = mpnorm(size, b->modl);
243 /* make the dividend, initialize first word to 1 (shifted); the rest is zero */
244 *dividend = ((mpw) MP_LSBMASK << shift);
245 mpzero(size*2, dividend+1);
246 mpndivmod(divmod, size*2+1, dividend, size, b->modl, workspace);
247 mpcopy(size+1, b->mu, divmod+1);
248 /* de-normalize */
249 mprshift(size, b->modl, shift);
250 }
251
252 /*
253 * mpbrnd_w
254 * generates a random number in the range 1 < r < b-1
255 * need workspace of (size) words
256 */
mpbrnd_w(const mpbarrett * b,randomGeneratorContext * rc,mpw * result,mpw * wksp)257 void mpbrnd_w(const mpbarrett* b, randomGeneratorContext* rc, mpw* result, mpw* wksp)
258 {
259 size_t msz = mpmszcnt(b->size, b->modl);
260
261 mpcopy(b->size, wksp, b->modl);
262 mpsubw(b->size, wksp, 1);
263
264 do
265 {
266 rc->rng->next(rc->param, (byte*) result, MP_WORDS_TO_BYTES(b->size));
267
268 result[0] &= (MP_ALLMASK >> msz);
269
270 while (mpge(b->size, result, wksp))
271 mpsub(b->size, result, wksp);
272 } while (mpleone(b->size, result));
273 }
274
275 /*
276 * mpbrndodd_w
277 * generates a random odd number in the range 1 < r < b-1
278 * needs workspace of (size) words
279 */
mpbrndodd_w(const mpbarrett * b,randomGeneratorContext * rc,mpw * result,mpw * wksp)280 void mpbrndodd_w(const mpbarrett* b, randomGeneratorContext* rc, mpw* result, mpw* wksp)
281 {
282 size_t msz = mpmszcnt(b->size, b->modl);
283
284 mpcopy(b->size, wksp, b->modl);
285 mpsubw(b->size, wksp, 1);
286
287 do
288 {
289 rc->rng->next(rc->param, (byte*) result, MP_WORDS_TO_BYTES(b->size));
290
291 result[0] &= (MP_ALLMASK >> msz);
292 mpsetlsb(b->size, result);
293
294 while (mpge(b->size, result, wksp))
295 {
296 mpsub(b->size, result, wksp);
297 mpsetlsb(b->size, result);
298 }
299 } while (mpleone(b->size, result));
300 }
301
302 /*
303 * mpbrndinv_w
304 * generates a random invertible (modulo b) in the range 1 < r < b-1
305 * needs workspace of (6*size+6) words
306 */
mpbrndinv_w(const mpbarrett * b,randomGeneratorContext * rc,mpw * result,mpw * inverse,mpw * wksp)307 void mpbrndinv_w(const mpbarrett* b, randomGeneratorContext* rc, mpw* result, mpw* inverse, mpw* wksp)
308 {
309 register size_t size = b->size;
310
311 do
312 {
313 if (mpeven(size, b->modl))
314 mpbrndodd_w(b, rc, result, wksp);
315 else
316 mpbrnd_w(b, rc, result, wksp);
317
318 } while (mpextgcd_w(size, b->modl, result, inverse, wksp) == 0);
319 }
320
321 /*
322 * mpbmod_w
323 * computes the barrett modular reduction of a number x, which has twice the size of b
324 * needs workspace of (2*size+2) words
325 */
mpbmod_w(const mpbarrett * b,const mpw * data,mpw * result,mpw * wksp)326 void mpbmod_w(const mpbarrett* b, const mpw* data, mpw* result, mpw* wksp)
327 {
328 register mpw rc;
329 register size_t sp = 2;
330 register const mpw* src = data+b->size+1;
331 register mpw* dst = wksp+b->size+1;
332
333 rc = mpsetmul(sp, dst, b->mu, *(--src));
334 *(--dst) = rc;
335
336 while (sp <= b->size)
337 {
338 sp++;
339 if ((rc = *(--src)))
340 {
341 rc = mpaddmul(sp, dst, b->mu, rc);
342 *(--dst) = rc;
343 }
344 else
345 *(--dst) = 0;
346 }
347 if ((rc = *(--src)))
348 {
349 rc = mpaddmul(sp, dst, b->mu, rc);
350 *(--dst) = rc;
351 }
352 else
353 *(--dst) = 0;
354
355 sp = b->size;
356 rc = 0;
357
358 dst = wksp+b->size+1;
359 src = dst;
360
361 *dst = mpsetmul(sp, dst+1, b->modl, *(--src));
362
363 while (sp > 0)
364 mpaddmul(sp--, dst, b->modl+(rc++), *(--src));
365
366 mpsetx(b->size+1, wksp, b->size*2, data);
367 mpsub(b->size+1, wksp, wksp+b->size+1);
368
369 while (mpgex(b->size+1, wksp, b->size, b->modl))
370 mpsubx(b->size+1, wksp, b->size, b->modl);
371
372 mpcopy(b->size, result, wksp+1);
373 }
374
375 /*
376 * mpbsubone
377 * copies (b-1) into result
378 */
mpbsubone(const mpbarrett * b,mpw * result)379 void mpbsubone(const mpbarrett* b, mpw* result)
380 {
381 register size_t size = b->size;
382
383 mpcopy(size, result, b->modl);
384 mpsubw(size, result, 1);
385 }
386
387 /*
388 * mpbneg
389 * computes the negative (modulo b) of x, where x must contain a value between 0 and b-1
390 */
mpbneg(const mpbarrett * b,const mpw * data,mpw * result)391 void mpbneg(const mpbarrett* b, const mpw* data, mpw* result)
392 {
393 register size_t size = b->size;
394
395 mpcopy(size, result, data);
396 mpneg(size, result);
397 mpadd(size, result, b->modl);
398 }
399
400 /*
401 * mpbaddmod_w
402 * computes the sum (modulo b) of x and y
403 * needs a workspace of (4*size+2) words
404 */
mpbaddmod_w(const mpbarrett * b,size_t xsize,const mpw * xdata,size_t ysize,const mpw * ydata,mpw * result,mpw * wksp)405 void mpbaddmod_w(const mpbarrett* b, size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata, mpw* result, mpw* wksp)
406 {
407 /* xsize and ysize must be less than or equal to b->size */
408 register size_t size = b->size;
409 register mpw* temp = wksp + size*2+2;
410
411 mpsetx(2*size, temp, xsize, xdata);
412 mpaddx(2*size, temp, ysize, ydata);
413
414 mpbmod_w(b, temp, result, wksp);
415 }
416
417 /*
418 * mpbsubmod_w
419 * computes the difference (modulo b) of x and y
420 * needs a workspace of (4*size+2) words
421 */
mpbsubmod_w(const mpbarrett * b,size_t xsize,const mpw * xdata,size_t ysize,const mpw * ydata,mpw * result,mpw * wksp)422 void mpbsubmod_w(const mpbarrett* b, size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata, mpw* result, mpw* wksp)
423 {
424 /* xsize and ysize must be less than or equal to b->size */
425 register size_t size = b->size;
426 register mpw* temp = wksp + size*2+2;
427
428 mpsetx(2*size, temp, xsize, xdata);
429 if (mpsubx(2*size, temp, ysize, ydata)) /* if there's carry, i.e. the result would be negative, add the modulus */
430 while (!mpaddx(2*size, temp, size, b->modl)); /* keep adding the modulus until we get a carry */
431
432 mpbmod_w(b, temp, result, wksp);
433 }
434
435 /*
436 * mpmulmod_w
437 * computes the product (modulo b) of x and y
438 * needs a workspace of (4*size+2) words
439 */
mpbmulmod_w(const mpbarrett * b,size_t xsize,const mpw * xdata,size_t ysize,const mpw * ydata,mpw * result,mpw * wksp)440 void mpbmulmod_w(const mpbarrett* b, size_t xsize, const mpw* xdata, size_t ysize, const mpw* ydata, mpw* result, mpw* wksp)
441 {
442 /* xsize and ysize must be <= b->size */
443 register size_t size = b->size;
444 register size_t fill = size*2-xsize-ysize;
445 register mpw* temp = wksp + size*2+2;
446
447 if (fill)
448 mpzero(fill, temp);
449
450 mpmul(temp+fill, xsize, xdata, ysize, ydata);
451 mpbmod_w(b, temp, result, wksp);
452 }
453
454 /*
455 * mpbsqrmod_w
456 * computes the square (modulo b) of x
457 * needs a workspace of (4*size+2) words
458 */
mpbsqrmod_w(const mpbarrett * b,size_t xsize,const mpw * xdata,mpw * result,mpw * wksp)459 void mpbsqrmod_w(const mpbarrett* b, size_t xsize, const mpw* xdata, mpw* result, mpw* wksp)
460 {
461 /* xsize must be <= b->size */
462 register size_t size = b->size;
463 register size_t fill = 2*(size-xsize);
464 register mpw* temp = wksp + size*2+2;
465
466 if (fill)
467 mpzero(fill, temp);
468
469 mpsqr(temp+fill, xsize, xdata);
470 mpbmod_w(b, temp, result, wksp);
471 }
472
473 /*
474 * Sliding Window Exponentiation technique, slightly altered from the method Applied Cryptography:
475 *
476 * First of all, the table with the powers of g can be reduced by about half; the even powers don't
477 * need to be accessed or stored.
478 *
479 * Get up to K bits starting with a one, if we have that many still available
480 *
481 * Do the number of squarings of A in the first column, the multiply by the value in column two,
482 * and finally do the number of squarings in column three.
483 *
484 * This table can be used for K=2,3,4 and can be extended
485 *
486 * 0 : - | - | -
487 * 1 : 1 | g1 @ 0 | 0
488 * 10 : 1 | g1 @ 0 | 1
489 * 11 : 2 | g3 @ 1 | 0
490 * 100 : 1 | g1 @ 0 | 2
491 * 101 : 3 | g5 @ 2 | 0
492 * 110 : 2 | g3 @ 1 | 1
493 * 111 : 3 | g7 @ 3 | 0
494 * 1000 : 1 | g1 @ 0 | 3
495 * 1001 : 4 | g9 @ 4 | 0
496 * 1010 : 3 | g5 @ 2 | 1
497 * 1011 : 4 | g11 @ 5 | 0
498 * 1100 : 2 | g3 @ 1 | 2
499 * 1101 : 4 | g13 @ 6 | 0
500 * 1110 : 3 | g7 @ 3 | 1
501 * 1111 : 4 | g15 @ 7 | 0
502 *
503 */
504
505 /*
506 * mpbslide_w
507 * precomputes the sliding window table for computing powers of x modulo b
508 * needs workspace (4*size+2)
509 */
mpbslide_w(const mpbarrett * b,size_t xsize,const mpw * xdata,mpw * slide,mpw * wksp)510 void mpbslide_w(const mpbarrett* b, size_t xsize, const mpw* xdata, mpw* slide, mpw* wksp)
511 {
512 register size_t size = b->size;
513 mpbsqrmod_w(b, xsize, xdata, slide , wksp); /* x^2 mod b, temp */
514 mpbmulmod_w(b, xsize, xdata, size, slide , slide+size , wksp); /* x^3 mod b */
515 mpbmulmod_w(b, size, slide, size, slide+size , slide+2*size, wksp); /* x^5 mod b */
516 mpbmulmod_w(b, size, slide, size, slide+2*size, slide+3*size, wksp); /* x^7 mod b */
517 mpbmulmod_w(b, size, slide, size, slide+3*size, slide+4*size, wksp); /* x^9 mod b */
518 mpbmulmod_w(b, size, slide, size, slide+4*size, slide+5*size, wksp); /* x^11 mod b */
519 mpbmulmod_w(b, size, slide, size, slide+5*size, slide+6*size, wksp); /* x^13 mod b */
520 mpbmulmod_w(b, size, slide, size, slide+6*size, slide+7*size, wksp); /* x^15 mod b */
521 mpsetx(size, slide, xsize, xdata); /* x^1 mod b */
522 }
523
524 static byte mpbslide_presq[16] =
525 { 0, 1, 1, 2, 1, 3, 2, 3, 1, 4, 3, 4, 2, 4, 3, 4 };
526
527 static byte mpbslide_mulg[16] =
528 { 0, 0, 0, 1, 0, 2, 1, 3, 0, 4, 2, 5, 1, 6, 3, 7 };
529
530 static byte mpbslide_postsq[16] =
531 { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
532
533 /*
534 * needs workspace of 4*size+2 words
535 */
mpbpowmod_w(const mpbarrett * b,size_t xsize,const mpw * xdata,size_t psize,const mpw * pdata,mpw * result,mpw * wksp)536 void mpbpowmod_w(const mpbarrett* b, size_t xsize, const mpw* xdata, size_t psize, const mpw* pdata, mpw* result, mpw* wksp)
537 {
538 /*
539 * Modular exponention
540 *
541 * Uses sliding window exponentiation; needs extra storage: if K=3, needs 8*size, if K=4, needs 16*size
542 *
543 */
544
545 /* K == 4 for the first try */
546
547 size_t size = b->size;
548 mpw temp;
549
550 while (psize)
551 {
552 if ((temp = *(pdata++))) /* break when first non-zero word found */
553 break;
554 psize--;
555 }
556
557 /* if temp is still zero, then we're trying to raise x to power zero, and result stays one */
558 if (temp)
559 {
560 mpw* slide = (mpw*) malloc((8*size)*sizeof(mpw));
561
562 mpbslide_w(b, xsize, xdata, slide, wksp);
563
564 mpbpowmodsld_w(b, slide, psize, pdata-1, result, wksp);
565
566 free(slide);
567 }
568 }
569
mpbpowmodsld_w(const mpbarrett * b,const mpw * slide,size_t psize,const mpw * pdata,mpw * result,mpw * wksp)570 void mpbpowmodsld_w(const mpbarrett* b, const mpw* slide, size_t psize, const mpw* pdata, mpw* result, mpw* wksp)
571 {
572 /*
573 * Modular exponentiation with precomputed sliding window table, so no x is required
574 *
575 */
576
577 size_t size = b->size;
578 mpw temp;
579
580 mpsetw(size, result, 1);
581
582 while (psize)
583 {
584 if ((temp = *(pdata++))) /* break when first non-zero word found in power */
585 break;
586 psize--;
587 }
588
589 /* if temp is still zero, then we're trying to raise x to power zero, and result stays one */
590 if (temp)
591 {
592 short l = 0, n = 0, count = MP_WBITS;
593
594 /* first skip bits until we reach a one */
595 while (count)
596 {
597 if (temp & MP_MSBMASK)
598 break;
599 temp <<= 1;
600 count--;
601 }
602
603 while (psize)
604 {
605 while (count)
606 {
607 byte bit = (temp & MP_MSBMASK) ? 1 : 0;
608
609 n <<= 1;
610 n += bit;
611
612 if (n)
613 {
614 if (l)
615 l++;
616 else if (bit)
617 l = 1;
618
619 if (l == 4)
620 {
621 byte s = mpbslide_presq[n];
622
623 while (s--)
624 mpbsqrmod_w(b, size, result, result, wksp);
625
626 mpbmulmod_w(b, size, result, size, slide+mpbslide_mulg[n]*size, result, wksp);
627
628 s = mpbslide_postsq[n];
629
630 while (s--)
631 mpbsqrmod_w(b, size, result, result, wksp);
632
633 l = n = 0;
634 }
635 }
636 else
637 mpbsqrmod_w(b, size, result, result, wksp);
638
639 temp <<= 1;
640 count--;
641 }
642 if (--psize)
643 {
644 count = MP_WBITS;
645 temp = *(pdata++);
646 }
647 }
648
649 if (n)
650 {
651 byte s = mpbslide_presq[n];
652
653 while (s--)
654 mpbsqrmod_w(b, size, result, result, wksp);
655
656 mpbmulmod_w(b, size, result, size, slide+mpbslide_mulg[n]*size, result, wksp);
657
658 s = mpbslide_postsq[n];
659
660 while (s--)
661 mpbsqrmod_w(b, size, result, result, wksp);
662 }
663 }
664 }
665
666 /*
667 * mpbtwopowmod_w
668 * needs workspace of (4*size+2) words
669 */
mpbtwopowmod_w(const mpbarrett * b,size_t psize,const mpw * pdata,mpw * result,mpw * wksp)670 void mpbtwopowmod_w(const mpbarrett* b, size_t psize, const mpw* pdata, mpw* result, mpw* wksp)
671 {
672 /*
673 * Modular exponention, 2^p mod modulus, special optimization
674 *
675 * Uses left-to-right exponentiation; needs no extra storage
676 *
677 */
678
679 /* this routine calls mpbmod, which needs (size*2+2), this routine needs (size*2) for sdata */
680
681 register size_t size = b->size;
682 register mpw temp = 0;
683
684 mpsetw(size, result, 1);
685
686 while (psize)
687 {
688 if ((temp = *(pdata++))) /* break when first non-zero word found */
689 break;
690 psize--;
691 }
692
693 /* if temp is still zero, then we're trying to raise x to power zero, and result stays one */
694 if (temp)
695 {
696 register int count = MP_WBITS;
697
698 /* first skip bits until we reach a one */
699 while (count)
700 {
701 if (temp & MP_MSBMASK)
702 break;
703 temp <<= 1;
704 count--;
705 }
706
707 while (psize--)
708 {
709 while (count)
710 {
711 /* always square */
712 mpbsqrmod_w(b, size, result, result, wksp);
713
714 /* multiply by two if bit is 1 */
715 if (temp & MP_MSBMASK)
716 {
717 if (mpadd(size, result, result) || mpge(size, result, b->modl))
718 {
719 /* there was carry, or the result is greater than the modulus, so we need to adjust */
720 mpsub(size, result, b->modl);
721 }
722 }
723
724 temp <<= 1;
725 count--;
726 }
727 count = MP_WBITS;
728 temp = *(pdata++);
729 }
730 }
731 }
732
733 /*
734 * needs workspace of (7*size+2) words
735 */
mpbpprime_w(const mpbarrett * b,randomGeneratorContext * r,int t,mpw * wksp)736 int mpbpprime_w(const mpbarrett* b, randomGeneratorContext* r, int t, mpw* wksp)
737 {
738 /*
739 * This test works for candidate probable primes >= 3, which are also not small primes.
740 *
741 * It assumes that b->modl contains the candidate prime
742 *
743 */
744
745 size_t size = b->size;
746
747 /* first test if modl is odd */
748
749 if (mpodd(b->size, b->modl))
750 {
751 /*
752 * Small prime factor test:
753 *
754 * Tables in mpspprod contain multi-precision integers with products of small primes
755 * If the greatest common divisor of this product and the candidate is not one, then
756 * the candidate has small prime factors, or is a small prime. Neither is acceptable when
757 * we are looking for large probable primes =)
758 *
759 */
760
761 if (size > SMALL_PRIMES_PRODUCT_MAX)
762 {
763 mpsetx(size, wksp+size, SMALL_PRIMES_PRODUCT_MAX, mpspprod[SMALL_PRIMES_PRODUCT_MAX-1]);
764 mpgcd_w(size, b->modl, wksp+size, wksp, wksp+2*size);
765 }
766 else
767 {
768 mpgcd_w(size, b->modl, mpspprod[size-1], wksp, wksp+2*size);
769 }
770
771 if (mpisone(size, wksp))
772 {
773 return mppmilrab_w(b, r, t, wksp);
774 }
775 }
776
777 return 0;
778 }
779
mpbnrnd(const mpbarrett * b,randomGeneratorContext * rc,mpnumber * result)780 void mpbnrnd(const mpbarrett* b, randomGeneratorContext* rc, mpnumber* result)
781 {
782 register size_t size = b->size;
783 register mpw* temp = (mpw*) malloc(size * sizeof(mpw));
784
785 mpnfree(result);
786 mpnsize(result, size);
787 mpbrnd_w(b, rc, result->data, temp);
788
789 free(temp);
790 }
791
mpbnmulmod(const mpbarrett * b,const mpnumber * x,const mpnumber * y,mpnumber * result)792 void mpbnmulmod(const mpbarrett* b, const mpnumber* x, const mpnumber* y, mpnumber* result)
793 {
794 register size_t size = b->size;
795 register mpw* temp = (mpw*) malloc((4*size+2) * sizeof(mpw));
796
797 /* xsize and ysize must be <= b->size */
798 register size_t fill = 2*size-x->size-y->size;
799 register mpw* opnd = temp+size*2+2;
800
801 mpnfree(result);
802 mpnsize(result, size);
803
804 if (fill)
805 mpzero(fill, opnd);
806
807 mpmul(opnd+fill, x->size, x->data, y->size, y->data);
808 mpbmod_w(b, opnd, result->data, temp);
809
810 free(temp);
811 }
812
mpbnsqrmod(const mpbarrett * b,const mpnumber * x,mpnumber * result)813 void mpbnsqrmod(const mpbarrett* b, const mpnumber* x, mpnumber* result)
814 {
815 register size_t size = b->size;
816 register mpw* temp = (mpw*) malloc(size * sizeof(mpw));
817
818 /* xsize must be <= b->size */
819 register size_t fill = 2*(size-x->size);
820 register mpw* opnd = temp + size*2+2;
821
822 if (fill)
823 mpzero(fill, opnd);
824
825 mpsqr(opnd+fill, x->size, x->data);
826 mpnsize(result, size);
827 mpbmod_w(b, opnd, result->data, temp);
828
829 free(temp);
830 }
831
mpbnpowmod(const mpbarrett * b,const mpnumber * x,const mpnumber * pow,mpnumber * y)832 void mpbnpowmod(const mpbarrett* b, const mpnumber* x, const mpnumber* pow, mpnumber* y)
833 {
834 register size_t size = b->size;
835 register mpw* temp = (mpw*) malloc((4*size+2) * sizeof(mpw));
836
837 mpnfree(y);
838 mpnsize(y, size);
839
840 mpbpowmod_w(b, x->size, x->data, pow->size, pow->data, y->data, temp);
841
842 free(temp);
843 }
844
mpbnpowmodsld(const mpbarrett * b,const mpw * slide,const mpnumber * pow,mpnumber * y)845 void mpbnpowmodsld(const mpbarrett* b, const mpw* slide, const mpnumber* pow, mpnumber* y)
846 {
847 register size_t size = b->size;
848 register mpw* temp = (mpw*) malloc((4*size+2) * sizeof(mpw));
849
850 mpnfree(y);
851 mpnsize(y, size);
852
853 mpbpowmodsld_w(b, slide, pow->size, pow->data, y->data, temp);
854
855 free(temp);
856 }
857
mpbbits(const mpbarrett * b)858 size_t mpbbits(const mpbarrett* b)
859 {
860 return mpbits(b->size, b->modl);
861 }
862