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