1 /*
2  * bn32.c - the high-level bignum interface
3  *
4  * Like lbn32.c, this reserves the string "32" for textual replacement.
5  * The string must not appear anywhere unless it is intended to be replaced
6  * to generate other bignum interface functions.
7  *
8  * Copyright (c) 1995  Colin Plumb.  All rights reserved.
9  * For licensing and other legal details, see the file legal.c.
10  */
11 
12 #ifndef HAVE_CONFIG_H
13 #define HAVE_CONFIG_H 0
14 #endif
15 #if HAVE_CONFIG_H
16 #include <bnconfig.h>
17 #endif
18 
19 /*
20  * Some compilers complain about #if FOO if FOO isn't defined,
21  * so do the ANSI-mandated thing explicitly...
22  */
23 #ifndef NO_ASSERT_H
24 #define NO_ASSERT_H 0
25 #endif
26 #ifndef NO_STRING_H
27 #define NO_STRING_H 0
28 #endif
29 #ifndef HAVE_STRINGS_H
30 #define HAVE_STRINGS_H 0
31 #endif
32 #ifndef NEED_MEMORY_H
33 #define NEED_MEMORY_H 0
34 #endif
35 
36 #if !NO_ASSERT_H
37 #include <assert.h>
38 #else
39 #define assert(x) (void)0
40 #endif
41 
42 #if !NO_STRING_H
43 #include <string.h>	/* for memmove() in bnMakeOdd */
44 #elif HAVE_STRINGS_H
45 #include <strings.h>
46 #endif
47 #if NEED_MEMORY_H
48 #include <memory.h>
49 #endif
50 
51 /*
52  * This was useful during debugging, so it's left in here.
53  * You can ignore it.  DBMALLOC is generally undefined.
54  */
55 #ifndef DBMALLOC
56 #define DBMALLOC 0
57 #endif
58 #if DBMALLOC
59 #include "../dbmalloc/malloc.h"
60 #define MALLOCDB malloc_chain_check(1)
61 #else
62 #define MALLOCDB (void)0
63 #endif
64 
65 #include "lbn.h"
66 #include "lbn32.h"
67 #include "lbnmem.h"
68 #include "bn32.h"
69 #include "bn.h"
70 
71 /* Work-arounds for some particularly broken systems */
72 #include "kludge.h"	/* For memmove() */
73 
74 /* Functions */
75 void
bnInit_32(void)76 bnInit_32(void)
77 {
78 	bnEnd = bnEnd_32;
79 	bnPrealloc = bnPrealloc_32;
80 	bnCopy = bnCopy_32;
81 	bnNorm = bnNorm_32;
82 	bnExtractBigBytes = bnExtractBigBytes_32;
83 	bnInsertBigBytes = bnInsertBigBytes_32;
84 	bnExtractLittleBytes = bnExtractLittleBytes_32;
85 	bnInsertLittleBytes = bnInsertLittleBytes_32;
86 	bnLSWord = bnLSWord_32;
87 	bnReadBit = bnReadBit_32;
88 	bnBits = bnBits_32;
89 	bnAdd = bnAdd_32;
90 	bnSub = bnSub_32;
91 	bnCmpQ = bnCmpQ_32;
92 	bnSetQ = bnSetQ_32;
93 	bnAddQ = bnAddQ_32;
94 	bnSubQ = bnSubQ_32;
95 	bnCmp = bnCmp_32;
96 	bnSquare = bnSquare_32;
97 	bnMul = bnMul_32;
98 	bnMulQ = bnMulQ_32;
99 	bnDivMod = bnDivMod_32;
100 	bnMod = bnMod_32;
101 	bnModQ = bnModQ_32;
102 	bnExpMod = bnExpMod_32;
103 	bnDoubleExpMod = bnDoubleExpMod_32;
104 	bnTwoExpMod = bnTwoExpMod_32;
105 	bnGcd = bnGcd_32;
106 	bnInv = bnInv_32;
107 	bnLShift = bnLShift_32;
108 	bnRShift = bnRShift_32;
109 	bnMakeOdd = bnMakeOdd_32;
110 	bnBasePrecompBegin = bnBasePrecompBegin_32;
111 	bnBasePrecompEnd = bnBasePrecompEnd_32;
112 	bnBasePrecompExpMod = bnBasePrecompExpMod_32;
113 	bnDoubleBasePrecompExpMod = bnDoubleBasePrecompExpMod_32;
114 }
115 
116 void
bnEnd_32(struct BigNum * bn)117 bnEnd_32(struct BigNum *bn)
118 {
119 	if (bn->ptr) {
120 		LBNFREE((BNWORD32 *)bn->ptr, bn->allocated);
121 		bn->ptr = 0;
122 	}
123 	bn->size = 0;
124 	bn->allocated = 0;
125 
126 	MALLOCDB;
127 }
128 
129 /* Internal function.  It operates in words. */
130 static int
bnResize_32(struct BigNum * bn,unsigned len)131 bnResize_32(struct BigNum *bn, unsigned len)
132 {
133 	void *p;
134 
135 	/* Round size up: most mallocs impose 8-byte granularity anyway */
136 	len = (len + (8/sizeof(BNWORD32) - 1)) & ~(8/sizeof(BNWORD32) - 1);
137 	p = LBNREALLOC((BNWORD32 *)bn->ptr, bn->allocated, len);
138 	if (!p)
139 		return -1;
140 	bn->ptr = p;
141 	bn->allocated = len;
142 
143 	MALLOCDB;
144 
145 	return 0;
146 }
147 
148 #define bnSizeCheck(bn, size) \
149 	if (bn->allocated < size && bnResize_32(bn, size) < 0) \
150 		return -1
151 
152 /* Preallocate enough space in bn to hold "bits" bits. */
153 int
bnPrealloc_32(struct BigNum * bn,unsigned bits)154 bnPrealloc_32(struct BigNum *bn, unsigned bits)
155 {
156 	bits = (bits + 32-1)/32;
157 	bnSizeCheck(bn, bits);
158 	MALLOCDB;
159 	return 0;
160 }
161 
162 int
bnCopy_32(struct BigNum * dest,struct BigNum const * src)163 bnCopy_32(struct BigNum *dest, struct BigNum const *src)
164 {
165 	bnSizeCheck(dest, src->size);
166 	dest->size = src->size;
167 	lbnCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, src->size);
168 	MALLOCDB;
169 	return 0;
170 }
171 
172 /* Is this ever needed?  Normalize the bn by deleting high-order 0 words */
173 void
bnNorm_32(struct BigNum * bn)174 bnNorm_32(struct BigNum *bn)
175 {
176 	bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, bn->size);
177 }
178 
179 /*
180  * Convert a bignum to big-endian bytes.  Returns, in big-endian form, a
181  * substring of the bignum starting from lsbyte and "len" bytes long.
182  * Unused high-order (leading) bytes are filled with 0.
183  */
184 void
bnExtractBigBytes_32(struct BigNum const * bn,unsigned char * dest,unsigned lsbyte,unsigned len)185 bnExtractBigBytes_32(struct BigNum const *bn, unsigned char *dest,
186                   unsigned lsbyte, unsigned len)
187 {
188 	unsigned s = bn->size * (32 / 8);
189 
190 	/* Fill unused leading bytes with 0 */
191 	while (s < lsbyte + len) {
192 		*dest++ = 0;
193 		len--;
194 	}
195 
196 	if (len)
197 		lbnExtractBigBytes_32((BNWORD32 *)bn->ptr, dest, lsbyte, len);
198 	MALLOCDB;
199 }
200 
201 /* The inverse of the above. */
202 int
bnInsertBigBytes_32(struct BigNum * bn,unsigned char const * src,unsigned lsbyte,unsigned len)203 bnInsertBigBytes_32(struct BigNum *bn, unsigned char const *src,
204                  unsigned lsbyte, unsigned len)
205 {
206 	unsigned s = bn->size;
207 	unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32);
208 
209 	/* Pad with zeros as required */
210 	bnSizeCheck(bn, words);
211 
212 	if (s < words) {
213 		lbnZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s);
214 		s = words;
215 	}
216 
217 	lbnInsertBigBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len);
218 
219 	bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, s);
220 
221 	MALLOCDB;
222 	return 0;
223 }
224 
225 
226 /*
227  * Convert a bignum to little-endian bytes.  Returns, in little-endian form, a
228  * substring of the bignum starting from lsbyte and "len" bytes long.
229  * Unused high-order (trailing) bytes are filled with 0.
230  */
231 void
bnExtractLittleBytes_32(struct BigNum const * bn,unsigned char * dest,unsigned lsbyte,unsigned len)232 bnExtractLittleBytes_32(struct BigNum const *bn, unsigned char *dest,
233                   unsigned lsbyte, unsigned len)
234 {
235 	unsigned s = bn->size * (32 / 8);
236 
237 	/* Fill unused leading bytes with 0 */
238 	while (s < lsbyte + len)
239 		dest[--len] = 0;
240 
241 	if (len)
242 		lbnExtractLittleBytes_32((BNWORD32 *)bn->ptr, dest,
243 		                         lsbyte, len);
244 	MALLOCDB;
245 }
246 
247 /* The inverse of the above */
248 int
bnInsertLittleBytes_32(struct BigNum * bn,unsigned char const * src,unsigned lsbyte,unsigned len)249 bnInsertLittleBytes_32(struct BigNum *bn, unsigned char const *src,
250                        unsigned lsbyte, unsigned len)
251 {
252 	unsigned s = bn->size;
253 	unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32);
254 
255 	/* Pad with zeros as required */
256 	bnSizeCheck(bn, words);
257 
258 	if (s < words) {
259 		lbnZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s);
260 		s = words;
261 	}
262 
263 	lbnInsertLittleBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len);
264 
265 	bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, s);
266 
267 	MALLOCDB;
268 	return 0;
269 }
270 
271 /* Return the least-significant word of the input. */
272 unsigned
bnLSWord_32(struct BigNum const * bn)273 bnLSWord_32(struct BigNum const *bn)
274 {
275 	return bn->size ? (unsigned)((BNWORD32 *)bn->ptr)[BIGLITTLE(-1,0)]: 0;
276 }
277 
278 /* Return a selected bit of the data */
279 int
bnReadBit_32(struct BigNum const * bn,unsigned bit)280 bnReadBit_32(struct BigNum const *bn, unsigned bit)
281 {
282 	BNWORD32 word;
283 	if (bit/32 >= bn->size)
284 		return 0;
285 	word = ((BNWORD32 *)bn->ptr)[BIGLITTLE(-1-bit/32,bit/32)];
286 	return (int)(word >> (bit % 32) & 1);
287 }
288 
289 /* Count the number of significant bits. */
290 unsigned
bnBits_32(struct BigNum const * bn)291 bnBits_32(struct BigNum const *bn)
292 {
293 	return lbnBits_32((BNWORD32 *)bn->ptr, bn->size);
294 }
295 
296 /* dest += src */
297 int
bnAdd_32(struct BigNum * dest,struct BigNum const * src)298 bnAdd_32(struct BigNum *dest, struct BigNum const *src)
299 {
300 	unsigned s = src->size, d = dest->size;
301 	BNWORD32 t;
302 
303 	if (!s)
304 		return 0;
305 
306 	bnSizeCheck(dest, s);
307 
308 	if (d < s) {
309 		lbnZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d);
310 		dest->size = d = s;
311 		MALLOCDB;
312 	}
313 	t = lbnAddN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s);
314 	MALLOCDB;
315 	if (t) {
316 		if (d > s) {
317 			t = lbnAdd1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s),
318 			               d-s, t);
319 			MALLOCDB;
320 		}
321 		if (t) {
322 			bnSizeCheck(dest, d+1);
323 			((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t;
324 			dest->size = d+1;
325 		}
326 	}
327 	return 0;
328 }
329 
330 /*
331  * dest -= src.
332  * If dest goes negative, this produces the absolute value of
333  * the difference (the negative of the true value) and returns 1.
334  * Otherwise, it returls 0.
335  */
336 int
bnSub_32(struct BigNum * dest,struct BigNum const * src)337 bnSub_32(struct BigNum *dest, struct BigNum const *src)
338 {
339 	unsigned s = src->size, d = dest->size;
340 	BNWORD32 t;
341 
342 	if (d < s  &&  d < (s = lbnNorm_32((BNWORD32 *)src->ptr, s))) {
343 		bnSizeCheck(dest, s);
344 		lbnZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d);
345 		dest->size = d = s;
346 		MALLOCDB;
347 	}
348 	if (!s)
349 		return 0;
350 	t = lbnSubN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s);
351 	MALLOCDB;
352 	if (t) {
353 		if (d > s) {
354 			t = lbnSub1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s),
355 			               d-s, t);
356 			MALLOCDB;
357 		}
358 		if (t) {
359 			lbnNeg_32((BNWORD32 *)dest->ptr, d);
360 			dest->size = lbnNorm_32((BNWORD32 *)dest->ptr,
361 			                        dest->size);
362 			MALLOCDB;
363 			return 1;
364 		}
365 	}
366 	dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dest->size);
367 	return 0;
368 }
369 
370 /*
371  * Compare the BigNum to the given value, which must be < 65536.
372  * Returns -1. 0 or 1 if a<b, a == b or a>b.
373  * a <=> b --> bnCmpQ(a,b) <=> 0
374  */
375 int
bnCmpQ_32(struct BigNum const * a,unsigned b)376 bnCmpQ_32(struct BigNum const *a, unsigned b)
377 {
378 	unsigned t;
379 	BNWORD32 v;
380 
381 	t = lbnNorm_32((BNWORD32 *)a->ptr, a->size);
382 	/* If a is more than one word long or zero, it's easy... */
383 	if (t != 1)
384 		return (t > 1) ? 1 : (b ? -1 : 0);
385 	v = (unsigned)((BNWORD32 *)a->ptr)[BIGLITTLE(-1,0)];
386 	return (v > b) ? 1 : ((v < b) ? -1 : 0);
387 }
388 
389 /* Set dest to a small value */
390 int
bnSetQ_32(struct BigNum * dest,unsigned src)391 bnSetQ_32(struct BigNum *dest, unsigned src)
392 {
393 	if (src) {
394 		bnSizeCheck(dest, 1);
395 
396 		((BNWORD32 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD32)src;
397 		dest->size = 1;
398 	} else {
399 		dest->size = 0;
400 	}
401 	return 0;
402 }
403 
404 /* dest += src */
405 int
bnAddQ_32(struct BigNum * dest,unsigned src)406 bnAddQ_32(struct BigNum *dest, unsigned src)
407 {
408 	BNWORD32 t;
409 
410 	if (!dest->size)
411 		return bnSetQ(dest, src);
412 
413 	t = lbnAdd1_32((BNWORD32 *)dest->ptr, dest->size, (BNWORD32)src);
414 	MALLOCDB;
415 	if (t) {
416 		src = dest->size;
417 		bnSizeCheck(dest, src+1);
418 		((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t;
419 		dest->size = src+1;
420 	}
421 	return 0;
422 }
423 
424 /*
425  * Return value as for bnSub: 1 if subtract underflowed, in which
426  * case the return is the negative of the computed value.
427  */
428 int
bnSubQ_32(struct BigNum * dest,unsigned src)429 bnSubQ_32(struct BigNum *dest, unsigned src)
430 {
431 	BNWORD32 t;
432 
433 	if (!dest->size)
434 		return bnSetQ(dest, src) < 0 ? -1 : (src != 0);
435 
436 	t = lbnSub1_32((BNWORD32 *)dest->ptr, dest->size, src);
437 	MALLOCDB;
438 	if (t) {
439 		/* Underflow. <= 1 word, so do it simply. */
440 		lbnNeg_32((BNWORD32 *)dest->ptr, 1);
441 		dest->size = 1;
442 		return 1;
443 	}
444 /* Try to normalize?  Needing this is going to be pretty damn rare. */
445 /*		dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dest->size); */
446 	return 0;
447 }
448 
449 /*
450  * Compare two BigNums.  Returns -1. 0 or 1 if a<b, a == b or a>b.
451  * a <=> b --> bnCmp(a,b) <=> 0
452  */
453 int
bnCmp_32(struct BigNum const * a,struct BigNum const * b)454 bnCmp_32(struct BigNum const *a, struct BigNum const *b)
455 {
456 	unsigned s, t;
457 
458 	s = lbnNorm_32((BNWORD32 *)a->ptr, a->size);
459 	t = lbnNorm_32((BNWORD32 *)b->ptr, b->size);
460 
461 	if (s != t)
462 		return s > t ? 1 : -1;
463 	return lbnCmp_32((BNWORD32 *)a->ptr, (BNWORD32 *)b->ptr, s);
464 }
465 
466 /* dest = src*src.  This is more efficient than bnMul. */
467 int
bnSquare_32(struct BigNum * dest,struct BigNum const * src)468 bnSquare_32(struct BigNum *dest, struct BigNum const *src)
469 {
470 	unsigned s;
471 	BNWORD32 *srcbuf;
472 
473 	s = lbnNorm_32((BNWORD32 *)src->ptr, src->size);
474 	if (!s) {
475 		dest->size = 0;
476 		return 0;
477 	}
478 	bnSizeCheck(dest, 2*s);
479 
480 	if (src == dest) {
481 		LBNALLOC(srcbuf, BNWORD32, s);
482 		if (!srcbuf)
483 			return -1;
484 		lbnCopy_32(srcbuf, (BNWORD32 *)src->ptr, s);
485 		lbnSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)srcbuf, s);
486 		LBNFREE(srcbuf, s);
487 	} else {
488 		lbnSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s);
489 	}
490 
491 	dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, 2*s);
492 	MALLOCDB;
493 	return 0;
494 }
495 
496 /* dest = a * b.  Any overlap between operands is allowed. */
497 int
bnMul_32(struct BigNum * dest,struct BigNum const * a,struct BigNum const * b)498 bnMul_32(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b)
499 {
500 	unsigned s, t;
501 	BNWORD32 *srcbuf;
502 
503 	s = lbnNorm_32((BNWORD32 *)a->ptr, a->size);
504 	t = lbnNorm_32((BNWORD32 *)b->ptr, b->size);
505 
506 	if (!s || !t) {
507 		dest->size = 0;
508 		return 0;
509 	}
510 
511 	if (a == b)
512 		return bnSquare_32(dest, a);
513 
514 	bnSizeCheck(dest, s+t);
515 
516 	if (dest == a) {
517 		LBNALLOC(srcbuf, BNWORD32, s);
518 		if (!srcbuf)
519 			return -1;
520 		lbnCopy_32(srcbuf, (BNWORD32 *)a->ptr, s);
521 		lbnMul_32((BNWORD32 *)dest->ptr, srcbuf, s,
522 		                                 (BNWORD32 *)b->ptr, t);
523 		LBNFREE(srcbuf, s);
524 	} else if (dest == b) {
525 		LBNALLOC(srcbuf, BNWORD32, t);
526 		if (!srcbuf)
527 			return -1;
528 		lbnCopy_32(srcbuf, (BNWORD32 *)b->ptr, t);
529 		lbnMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s,
530 		                                 srcbuf, t);
531 		LBNFREE(srcbuf, t);
532 	} else {
533 		lbnMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s,
534 		                                 (BNWORD32 *)b->ptr, t);
535 	}
536 	dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s+t);
537 	MALLOCDB;
538 	return 0;
539 }
540 
541 /* dest = a * b */
542 int
bnMulQ_32(struct BigNum * dest,struct BigNum const * a,unsigned b)543 bnMulQ_32(struct BigNum *dest, struct BigNum const *a, unsigned b)
544 {
545 	unsigned s;
546 
547 	s = lbnNorm_32((BNWORD32 *)a->ptr, a->size);
548 	if (!s || !b) {
549 		dest->size = 0;
550 		return 0;
551 	}
552 	if (b == 1)
553 		return bnCopy_32(dest, a);
554 	bnSizeCheck(dest, s+1);
555 	lbnMulN1_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, b);
556 	dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s+1);
557 	MALLOCDB;
558 	return 0;
559 }
560 
561 /* q = n/d, r = n % d */
562 int
bnDivMod_32(struct BigNum * q,struct BigNum * r,struct BigNum const * n,struct BigNum const * d)563 bnDivMod_32(struct BigNum *q, struct BigNum *r, struct BigNum const *n,
564             struct BigNum const *d)
565 {
566 	unsigned dsize, nsize;
567 	BNWORD32 qhigh;
568 
569 	dsize = lbnNorm_32((BNWORD32 *)d->ptr, d->size);
570 	nsize = lbnNorm_32((BNWORD32 *)n->ptr, n->size);
571 
572 	if (nsize < dsize) {
573 		q->size = 0;	/* No quotient */
574 		r->size = nsize;
575 		return 0;	/* Success */
576 	}
577 
578 	bnSizeCheck(q, nsize-dsize);
579 
580 	if (r != n) {	/* You are allowed to reduce in place */
581 		bnSizeCheck(r, nsize);
582 		lbnCopy_32((BNWORD32 *)r->ptr, (BNWORD32 *)n->ptr, nsize);
583 	}
584 
585 	qhigh = lbnDiv_32((BNWORD32 *)q->ptr, (BNWORD32 *)r->ptr, nsize,
586 	                  (BNWORD32 *)d->ptr, dsize);
587 	nsize -= dsize;
588 	if (qhigh) {
589 		bnSizeCheck(q, nsize+1);
590 		*((BNWORD32 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh;
591 		q->size = nsize+1;
592 	} else {
593 		q->size = lbnNorm_32((BNWORD32 *)q->ptr, nsize);
594 	}
595 	r->size = lbnNorm_32((BNWORD32 *)r->ptr, dsize);
596 	MALLOCDB;
597 	return 0;
598 }
599 
600 /* det = src % d */
601 int
bnMod_32(struct BigNum * dest,struct BigNum const * src,struct BigNum const * d)602 bnMod_32(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d)
603 {
604 	unsigned dsize, nsize;
605 
606 	nsize = lbnNorm_32((BNWORD32 *)src->ptr, src->size);
607 	dsize = lbnNorm_32((BNWORD32 *)d->ptr, d->size);
608 
609 
610 	if (dest != src) {
611 		bnSizeCheck(dest, nsize);
612 		lbnCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, nsize);
613 	}
614 
615 	if (nsize < dsize) {
616 		dest->size = nsize;	/* No quotient */
617 		return 0;
618 	}
619 
620 	(void)lbnDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-dsize,+dsize),
621 	                (BNWORD32 *)dest->ptr, nsize,
622 	                (BNWORD32 *)d->ptr, dsize);
623 	dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dsize);
624 	MALLOCDB;
625 	return 0;
626 }
627 
628 /* return src % d. */
629 unsigned
bnModQ_32(struct BigNum const * src,unsigned d)630 bnModQ_32(struct BigNum const *src, unsigned d)
631 {
632 	unsigned s;
633 
634 	s = lbnNorm_32((BNWORD32 *)src->ptr, src->size);
635 	if (!s)
636 		return 0;
637 
638 	if (d & (d-1))	/* Not a power of 2 */
639 		d = lbnModQ_32((BNWORD32 *)src->ptr, s, d);
640 	else
641 		d = (unsigned)((BNWORD32 *)src->ptr)[BIGLITTLE(-1,0)] & (d-1);
642 	return d;
643 }
644 
645 /* dest = n^exp (mod mod) */
646 int
bnExpMod_32(struct BigNum * dest,struct BigNum const * n,struct BigNum const * exp,struct BigNum const * mod)647 bnExpMod_32(struct BigNum *dest, struct BigNum const *n,
648 	struct BigNum const *exp, struct BigNum const *mod)
649 {
650 	unsigned nsize, esize, msize;
651 
652 	nsize = lbnNorm_32((BNWORD32 *)n->ptr, n->size);
653 	esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size);
654 	msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
655 
656 	if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
657 		return -1;	/* Illegal modulus! */
658 
659 	bnSizeCheck(dest, msize);
660 
661 	/* Special-case base of 2 */
662 	if (nsize == 1 && ((BNWORD32 *)n->ptr)[BIGLITTLE(-1,0)] == 2) {
663 		if (lbnTwoExpMod_32((BNWORD32 *)dest->ptr,
664 				    (BNWORD32 *)exp->ptr, esize,
665 				    (BNWORD32 *)mod->ptr, msize) < 0)
666 			return -1;
667 	} else {
668 		if (lbnExpMod_32((BNWORD32 *)dest->ptr,
669 		                 (BNWORD32 *)n->ptr, nsize,
670 				 (BNWORD32 *)exp->ptr, esize,
671 				 (BNWORD32 *)mod->ptr, msize) < 0)
672 		return -1;
673 	}
674 
675 	dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize);
676 	MALLOCDB;
677 	return 0;
678 }
679 
680 /*
681  * dest = n1^e1 * n2^e2 (mod mod).  This is more efficient than two
682  * separate modular exponentiations, and in fact asymptotically approaches
683  * the cost of one.
684  */
685 int
bnDoubleExpMod_32(struct BigNum * dest,struct BigNum const * n1,struct BigNum const * e1,struct BigNum const * n2,struct BigNum const * e2,struct BigNum const * mod)686 bnDoubleExpMod_32(struct BigNum *dest,
687 	struct BigNum const *n1, struct BigNum const *e1,
688 	struct BigNum const *n2, struct BigNum const *e2,
689 	struct BigNum const *mod)
690 {
691 	unsigned n1size, e1size, n2size, e2size, msize;
692 
693 	n1size = lbnNorm_32((BNWORD32 *)n1->ptr, n1->size);
694 	e1size = lbnNorm_32((BNWORD32 *)e1->ptr, e1->size);
695 	n2size = lbnNorm_32((BNWORD32 *)n2->ptr, n2->size);
696 	e2size = lbnNorm_32((BNWORD32 *)e2->ptr, e2->size);
697 	msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
698 
699 	if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
700 		return -1;	/* Illegal modulus! */
701 
702 	bnSizeCheck(dest, msize);
703 
704 	if (lbnDoubleExpMod_32((BNWORD32 *)dest->ptr,
705 		(BNWORD32 *)n1->ptr, n1size, (BNWORD32 *)e1->ptr, e1size,
706 		(BNWORD32 *)n2->ptr, n2size, (BNWORD32 *)e2->ptr, e2size,
707 		(BNWORD32 *)mod->ptr, msize) < 0)
708 		return -1;
709 
710 	dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize);
711 	MALLOCDB;
712 	return 0;
713 }
714 
715 /* n = 2^exp (mod mod) */
716 int
bnTwoExpMod_32(struct BigNum * n,struct BigNum const * exp,struct BigNum const * mod)717 bnTwoExpMod_32(struct BigNum *n, struct BigNum const *exp,
718 	struct BigNum const *mod)
719 {
720 	unsigned esize, msize;
721 
722 	esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size);
723 	msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
724 
725 	if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
726 		return -1;	/* Illegal modulus! */
727 
728 	bnSizeCheck(n, msize);
729 
730 	if (lbnTwoExpMod_32((BNWORD32 *)n->ptr, (BNWORD32 *)exp->ptr, esize,
731 	                    (BNWORD32 *)mod->ptr, msize) < 0)
732 		return -1;
733 
734 	n->size = lbnNorm_32((BNWORD32 *)n->ptr, msize);
735 	MALLOCDB;
736 	return 0;
737 }
738 
739 /* dest = gcd(a, b) */
740 int
bnGcd_32(struct BigNum * dest,struct BigNum const * a,struct BigNum const * b)741 bnGcd_32(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b)
742 {
743 	BNWORD32 *tmp;
744 	unsigned asize, bsize;
745 	int i;
746 
747 	/* Kind of silly, but we might as well permit it... */
748 	if (a == b)
749 		return dest == a ? 0 : bnCopy(dest, a);
750 
751 	/* Ensure a is not the same as "dest" */
752 	if (a == dest) {
753 		a = b;
754 		b = dest;
755 	}
756 
757 	asize = lbnNorm_32((BNWORD32 *)a->ptr, a->size);
758 	bsize = lbnNorm_32((BNWORD32 *)b->ptr, b->size);
759 
760 	bnSizeCheck(dest, bsize+1);
761 
762 	/* Copy a to tmp */
763 	LBNALLOC(tmp, BNWORD32, asize+1);
764 	if (!tmp)
765 		return -1;
766 	lbnCopy_32(tmp, (BNWORD32 *)a->ptr, asize);
767 
768 	/* Copy b to dest, if necessary */
769 	if (dest != b)
770 		lbnCopy_32((BNWORD32 *)dest->ptr,
771 			   (BNWORD32 *)b->ptr, bsize);
772 	if (bsize > asize || (bsize == asize &&
773 	        lbnCmp_32((BNWORD32 *)b->ptr, (BNWORD32 *)a->ptr, asize) > 0))
774 	{
775 		i = lbnGcd_32((BNWORD32 *)dest->ptr, bsize, tmp, asize,
776 			&dest->size);
777 		if (i > 0)	/* Result in tmp, not dest */
778 			lbnCopy_32((BNWORD32 *)dest->ptr, tmp, dest->size);
779 	} else {
780 		i = lbnGcd_32(tmp, asize, (BNWORD32 *)dest->ptr, bsize,
781 			&dest->size);
782 		if (i == 0)	/* Result in tmp, not dest */
783 			lbnCopy_32((BNWORD32 *)dest->ptr, tmp, dest->size);
784 	}
785 	LBNFREE(tmp, asize+1);
786 	MALLOCDB;
787 	return (i < 0) ? i : 0;
788 }
789 
790 /*
791  * dest = 1/src (mod mod).  Returns >0 if gcd(src, mod) != 1 (in which case
792  * the inverse does not exist).
793  */
794 int
bnInv_32(struct BigNum * dest,struct BigNum const * src,struct BigNum const * mod)795 bnInv_32(struct BigNum *dest, struct BigNum const *src,
796          struct BigNum const *mod)
797 {
798 	unsigned s, m;
799 	int i;
800 
801 	s = lbnNorm_32((BNWORD32 *)src->ptr, src->size);
802 	m = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
803 
804 	/* lbnInv_32 requires that the input be less than the modulus */
805 	if (m < s ||
806 	    (m==s && lbnCmp_32((BNWORD32 *)src->ptr, (BNWORD32 *)mod->ptr, s)))
807 	{
808 		bnSizeCheck(dest, s + (m==s));
809 		if (dest != src)
810 			lbnCopy_32((BNWORD32 *)dest->ptr,
811 			           (BNWORD32 *)src->ptr, s);
812 		/* Pre-reduce modulo the modulus */
813 		(void)lbnDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-m,+m),
814 			        (BNWORD32 *)dest->ptr, s,
815 		                (BNWORD32 *)mod->ptr, m);
816 		s = lbnNorm_32((BNWORD32 *)dest->ptr, m);
817 		MALLOCDB;
818 	} else {
819 		bnSizeCheck(dest, m+1);
820 		if (dest != src)
821 			lbnCopy_32((BNWORD32 *)dest->ptr,
822 			           (BNWORD32 *)src->ptr, s);
823 	}
824 
825 	i = lbnInv_32((BNWORD32 *)dest->ptr, s, (BNWORD32 *)mod->ptr, m);
826 	if (i == 0)
827 		dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, m);
828 
829 	MALLOCDB;
830 	return i;
831 }
832 
833 /*
834  * Shift a bignum left the appropriate number of bits,
835  * multiplying by 2^amt.
836  */
837 int
bnLShift_32(struct BigNum * dest,unsigned amt)838 bnLShift_32(struct BigNum *dest, unsigned amt)
839 {
840 	unsigned s = dest->size;
841 	BNWORD32 carry;
842 
843 	if (amt % 32) {
844 		carry = lbnLshift_32((BNWORD32 *)dest->ptr, s, amt % 32);
845 		if (carry) {
846 			s++;
847 			bnSizeCheck(dest, s);
848 			((BNWORD32 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry;
849 		}
850 	}
851 
852 	amt /= 32;
853 	if (amt) {
854 		bnSizeCheck(dest, s+amt);
855 		memmove((BNWORD32 *)dest->ptr BIGLITTLE(-s-amt, +amt),
856 		        (BNWORD32 *)dest->ptr BIG(-s),
857 			s * sizeof(BNWORD32));
858 		lbnZero_32((BNWORD32 *)dest->ptr, amt);
859 		s += amt;
860 	}
861 	dest->size = s;
862 	MALLOCDB;
863 	return 0;
864 }
865 
866 /*
867  * Shift a bignum right the appropriate number of bits,
868  * dividing by 2^amt.
869  */
870 void
bnRShift_32(struct BigNum * dest,unsigned amt)871 bnRShift_32(struct BigNum *dest, unsigned amt)
872 {
873 	unsigned s = dest->size;
874 
875 	if (amt >= 32) {
876 		memmove(
877 		        (BNWORD32 *)dest->ptr BIG(-s+amt/32),
878 			(BNWORD32 *)dest->ptr BIGLITTLE(-s, +amt/32),
879 			(s-amt/32) * sizeof(BNWORD32));
880 		s -= amt/32;
881 		amt %= 32;
882 	}
883 
884 	if (amt)
885 		(void)lbnRshift_32((BNWORD32 *)dest->ptr, s, amt);
886 
887 	dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s);
888 	MALLOCDB;
889 }
890 
891 /*
892  * Shift a bignum right until it is odd, and return the number of
893  * bits shifted.  n = d * 2^s.  Replaces n with d and returns s.
894  * Returns 0 when given 0.  (Another valid answer is infinity.)
895  */
896 unsigned
bnMakeOdd_32(struct BigNum * n)897 bnMakeOdd_32(struct BigNum *n)
898 {
899 	unsigned size;
900 	unsigned s;	/* shift amount */
901 	BNWORD32 *p;
902 	BNWORD32 t;
903 
904 	p = (BNWORD32 *)n->ptr;
905 	size = lbnNorm_32(p, n->size);
906 	if (!size)
907 		return 0;
908 
909 	t = BIGLITTLE(p[-1],p[0]);
910 	s = 0;
911 
912 	/* See how many words we have to shift */
913 	if (!t) {
914 		/* Shift by words */
915 		do {
916 			s++;
917 			BIGLITTLE(--p,p++);
918 		} while ((t = BIGLITTLE(p[-1],p[0])) == 0);
919 		size -= s;
920 		s *= 32;
921 		memmove((BNWORD32 *)n->ptr BIG(-size), p BIG(-size),
922 			size * sizeof(BNWORD32));
923 		p = (BNWORD32 *)n->ptr;
924 		MALLOCDB;
925 	}
926 
927 	assert(t);
928 
929 	if (!(t & 1)) {
930 		/* Now count the bits */
931 		do {
932 			t >>= 1;
933 			s++;
934 		} while ((t & 1) == 0);
935 
936 		/* Shift the bits */
937 		lbnRshift_32(p, size, s & (32-1));
938 		/* Renormalize */
939 		if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0)
940 			--size;
941 	}
942 	n->size = size;
943 
944 	MALLOCDB;
945 	return s;
946 }
947 
948 /*
949  * Do base- and modulus-dependent precomputation for rapid computation of
950  * base^exp (mod mod) with various exponents.
951  *
952  * See lbn32.c for the details on how the algorithm works.  Basically,
953  * it involves precomputing a table of powers of base, base^(order^k),
954  * for a suitable range 0 <= k < n detemined by the maximum exponent size
955  * desired.  To do eht exponentiation, the exponent is expressed in base
956  * "order" (sorry for the confusing terminology) and the precomputed powers
957  * are combined.
958  *
959  * This implementation allows only power-of-2 values for "order".  Using
960  * other numbers can be more efficient, but it's more work and for the
961  * popular exponent size of 320 bits, an order of 8 is optimal, so it
962  * hasn't seemed worth it to implement.
963  *
964  * Here's a table of the optimal power-of-2 order for various exponent
965  * sizes and the associated (average) cost for an exponentiation.
966  * Note that *higher* orders are more memory-efficient; the number
967  * of precomputed values required is ceil(ebits/order).  (Ignore the
968  * underscores in the middle of numbers; they're harmless.)
969  *
970  * At     2 bits, order   2 uses    0.000000 multiplies
971  * At     4 bits, order   2 uses    1.000000 multiplies
972  * At     8 bits, order   2 uses    3.000000 multiplies
973  * At   1_6 bits, order   2 uses    7.000000 multiplies
974  * At   3_2 bits, order   2 uses   15.000000 multiplies
975  * At    34 bits, 15.750000 (order 4) < 1_6.000000 (order 2)
976  * At   6_4 bits, order   4 uses   27.000000 multiplies
977  * At    99 bits, 39.875000 (order 8) < 40.250000 (order 4)
978  * At   128 bits, order   8 uses   48.500000 multiplies
979  * At   256 bits, order   8 uses   85.875000 multiplies
980  * At   280 bits, 92.625000 (order 1_6) < 92.875000 (order 8)
981  * At   512 bits, order 1_6 uses  147.000000 multiplies
982  * At   785 bits, 211.093750 (order 3_2) < 211.250000 (order 1_6)
983  * At  1024 bits, order 3_2 uses  257.562500 multiplies
984  * At  2048 bits, order 3_2 uses  456.093750 multiplies
985  * At  2148 bits, 475.406250 (order 6_4) < 475.468750 (order 3_2)
986  * At  4096 bits, order 6_4 uses  795.281250 multiplies
987  * At  5726 bits, 1062.609375 (order 128) < 1062.843750 (order 6_4)
988  * At  8192 bits, order 128 uses 1412.609375 multiplies
989  * At 14848 bits, 2355.750000 (order 256) < 2355.929688 (order 128)
990  * At 37593 bits, 5187.841797 (order 512) < 5188.144531 (order 256)
991  */
992 int
bnBasePrecompBegin_32(struct BnBasePrecomp * pre,struct BigNum const * base,struct BigNum const * mod,unsigned maxebits)993 bnBasePrecompBegin_32(struct BnBasePrecomp *pre, struct BigNum const *base,
994 	struct BigNum const *mod, unsigned maxebits)
995 {
996 	int i;
997 	BNWORD32 **array;	/* Array of precomputed powers of base */
998 	unsigned n;	/* Number of entries in array (needed) */
999 	unsigned m;	/* Number of entries in array (non-NULL) */
1000 	unsigned arraysize; /* Number of entries in array (allocated) */
1001 	unsigned bits;	/* log2(order) */
1002 	unsigned msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
1003 	static unsigned const bnBasePrecompThreshTable[] = {
1004 		33, 98, 279, 784, 2147, 5725, 14847, 37592, (unsigned)-1
1005 	};
1006 
1007 	/* Clear pre in case of failure */
1008 	pre->array = 0;
1009 	pre->msize = 0;
1010 	pre->bits = 0;
1011 	pre->maxebits = 0;
1012 	pre->arraysize = 0;
1013 	pre->entries = 0;
1014 
1015 	/* Find the correct bit-window size */
1016 	bits = 0;
1017 	do
1018 		bits++;
1019 	while (maxebits > bnBasePrecompThreshTable[bits]);
1020 
1021 	/* Now the number of precomputed values we need */
1022 	n = (maxebits+bits-1)/bits;
1023 	assert(n*bits >= maxebits);
1024 
1025 	arraysize = n+1;	/* Add one trailing NULL for safety */
1026 	array = lbnMemAlloc(arraysize * sizeof(*array));
1027 	if (!array)
1028 		return -1;	/* Out of memory */
1029 
1030 	/* Now allocate the entries (precomputed powers of base) */
1031 	for (m = 0; m < n; m++) {
1032 		BNWORD32 *entry;
1033 
1034 		LBNALLOC(entry, BNWORD32, msize);
1035 		if (!entry)
1036 			break;
1037 		array[m] = entry;
1038 	}
1039 
1040 	/* "m" is the number of successfully allocated entries */
1041 	if (m < n) {
1042 		/* Ran out of memory; see if we can use a smaller array */
1043 		BNWORD32 **newarray;
1044 
1045 		if (m < 2) {
1046 			n = 0;	/* Forget it */
1047 		} else {
1048 			/* How few bits can we use with what's allocated? */
1049 			bits = (maxebits + m - 1) / m;
1050 retry:
1051 			n = (maxebits + bits - 1) / bits;
1052 			if (! (n >> bits) )
1053 				n = 0; /* Not enough to amount to anything */
1054 		}
1055 		/* Free excess allocated array entries */
1056 		while (m > n) {
1057 			BNWORD32 *entry = array[--m];
1058 			LBNFREE(entry, msize);
1059 		}
1060 		if (!n) {
1061 			/* Give it up */
1062 			lbnMemFree(array, arraysize * sizeof(*array));
1063 			return -1;
1064 		}
1065 		/*
1066 		 * Try to shrink the pointer array.  This might fail, but
1067 		 * it's not critical.  lbnMemRealloc isn't guarnateed to
1068 		 * exist, so we may have to allocate, copy, and free.
1069 		 */
1070 #ifdef lbnMemRealloc
1071 		newarray = lbnMemRealloc(array, arraysize * sizeof(*array),
1072 			       (n+1) * sizeof(*array));
1073 		if (newarray) {
1074 			array = newarray;
1075 			arraysize = n+1;
1076 		}
1077 #else
1078 		newarray = lbnMemAlloc((n+1) * sizeof(*array));
1079 		if (newarray) {
1080 			memcpy(newarray, array, n * sizeof(*array));
1081 			lbnMemFree(array, arraysize * sizeof(*array));
1082 			array = newarray;
1083 			arraysize = n+1;
1084 		}
1085 #endif
1086 	}
1087 
1088 	/* Pad with null pointers */
1089 	while (m < arraysize)
1090 		array[m++] = 0;
1091 
1092 	/* Okay, we have our array, now initialize it */
1093 	i = lbnBasePrecompBegin_32(array, n, bits,
1094 		(BNWORD32 *)base->ptr, base->size,
1095 		(BNWORD32 *)mod->ptr, msize);
1096 	if (i < 0) {
1097 		/* Ack, still out of memory */
1098 		bits++;
1099 		m = n;
1100 		goto retry;
1101 	}
1102 	/* Finally, totoal success */
1103 	pre->array = array;
1104 	pre->bits = bits;
1105 	pre->msize = msize;
1106 	pre->maxebits = n * bits;
1107 	pre->arraysize = arraysize;
1108 	pre->entries = n;
1109 	return 0;
1110 }
1111 
1112 /* Free everything preallocated */
1113 void
bnBasePrecompEnd_32(struct BnBasePrecomp * pre)1114 bnBasePrecompEnd_32(struct BnBasePrecomp *pre)
1115 {
1116 	BNWORD32 **array = pre->array;
1117 
1118 	if (array) {
1119 		unsigned entries = pre->entries;
1120 		unsigned msize = pre->msize;
1121 		unsigned m;
1122 
1123 		for (m = 0; m < entries; m++) {
1124 			BNWORD32 *entry = array[m];
1125 			if (entry)
1126 				LBNFREE(entry, msize);
1127 		}
1128 		lbnMemFree(array, pre->arraysize * sizeof(array));
1129 	}
1130 	pre->array = 0;
1131 	pre->bits = 0;
1132 	pre->msize = 0;
1133 	pre->maxebits = 0;
1134 	pre->arraysize = 0;
1135 	pre->entries = 0;
1136 }
1137 
1138 int
bnBasePrecompExpMod_32(struct BigNum * dest,struct BnBasePrecomp const * pre,struct BigNum const * exp,struct BigNum const * mod)1139 bnBasePrecompExpMod_32(struct BigNum *dest, struct BnBasePrecomp const *pre,
1140 	struct BigNum const *exp, struct BigNum const *mod)
1141 {
1142 	unsigned msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
1143 	unsigned esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size);
1144 	BNWORD32 const * const *array = pre->array;
1145 	int i;
1146 
1147 	assert(msize == pre->msize);
1148 	assert(((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1);
1149 	assert(lbnBits_32((BNWORD32 *)exp->ptr, esize) <= pre->maxebits);
1150 
1151 	bnSizeCheck(dest, msize);
1152 
1153 	i = lbnBasePrecompExp_32(dest->ptr, array, pre->bits,
1154 		       	exp->ptr, esize, mod->ptr, msize);
1155 	if (i == 0)
1156 		dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize);
1157 	return i;
1158 }
1159 
1160 int
bnDoubleBasePrecompExpMod_32(struct BigNum * dest,struct BnBasePrecomp const * pre1,struct BigNum const * exp1,struct BnBasePrecomp const * pre2,struct BigNum const * exp2,struct BigNum const * mod)1161 bnDoubleBasePrecompExpMod_32(struct BigNum *dest,
1162 	struct BnBasePrecomp const *pre1, struct BigNum const *exp1,
1163 	struct BnBasePrecomp const *pre2, struct BigNum const *exp2,
1164 	struct BigNum const *mod)
1165 {
1166 	unsigned msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size);
1167 	unsigned e1size = lbnNorm_32((BNWORD32 *)exp1->ptr, exp1->size);
1168 	unsigned e2size = lbnNorm_32((BNWORD32 *)exp1->ptr, exp2->size);
1169 	BNWORD32 const * const *array1 = pre1->array;
1170 	BNWORD32 const * const *array2 = pre2->array;
1171 	int i;
1172 
1173 	assert(msize == pre1->msize);
1174 	assert(msize == pre2->msize);
1175 	assert(((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1);
1176 	assert(lbnBits_32((BNWORD32 *)exp1->ptr, e1size) <= pre1->maxebits);
1177 	assert(lbnBits_32((BNWORD32 *)exp2->ptr, e2size) <= pre2->maxebits);
1178 	assert(pre1->bits == pre2->bits);
1179 
1180 	bnSizeCheck(dest, msize);
1181 
1182 	i = lbnDoubleBasePrecompExp_32(dest->ptr, pre1->bits, array1,
1183 		       	exp1->ptr, e1size, array2, exp2->ptr, e2size,
1184 			mod->ptr, msize);
1185 	if (i == 0)
1186 		dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize);
1187 	return i;
1188 }
1189