xref: /openbsd-src/lib/libcrypto/bn/bn_mul.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /* crypto/bn/bn_mul.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include "bn_lcl.h"
62 
63 #ifdef BN_RECURSION
64 /* Karatsuba recursive multiplication algorithm
65  * (cf. Knuth, The Art of Computer Programming, Vol. 2) */
66 
67 /* r is 2*n2 words in size,
68  * a and b are both n2 words in size.
69  * n2 must be a power of 2.
70  * We multiply and return the result.
71  * t must be 2*n2 words in size
72  * We calculate
73  * a[0]*b[0]
74  * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
75  * a[1]*b[1]
76  */
77 void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
78 	     BN_ULONG *t)
79 	{
80 	int n=n2/2,c1,c2;
81 	unsigned int neg,zero;
82 	BN_ULONG ln,lo,*p;
83 
84 # ifdef BN_COUNT
85 	printf(" bn_mul_recursive %d * %d\n",n2,n2);
86 # endif
87 # ifdef BN_MUL_COMBA
88 #  if 0
89 	if (n2 == 4)
90 		{
91 		bn_mul_comba4(r,a,b);
92 		return;
93 		}
94 #  endif
95 	if (n2 == 8)
96 		{
97 		bn_mul_comba8(r,a,b);
98 		return;
99 		}
100 # endif /* BN_MUL_COMBA */
101 	if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL)
102 		{
103 		/* This should not happen */
104 		bn_mul_normal(r,a,n2,b,n2);
105 		return;
106 		}
107 	/* r=(a[0]-a[1])*(b[1]-b[0]) */
108 	c1=bn_cmp_words(a,&(a[n]),n);
109 	c2=bn_cmp_words(&(b[n]),b,n);
110 	zero=neg=0;
111 	switch (c1*3+c2)
112 		{
113 	case -4:
114 		bn_sub_words(t,      &(a[n]),a,      n); /* - */
115 		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
116 		break;
117 	case -3:
118 		zero=1;
119 		break;
120 	case -2:
121 		bn_sub_words(t,      &(a[n]),a,      n); /* - */
122 		bn_sub_words(&(t[n]),&(b[n]),b,      n); /* + */
123 		neg=1;
124 		break;
125 	case -1:
126 	case 0:
127 	case 1:
128 		zero=1;
129 		break;
130 	case 2:
131 		bn_sub_words(t,      a,      &(a[n]),n); /* + */
132 		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
133 		neg=1;
134 		break;
135 	case 3:
136 		zero=1;
137 		break;
138 	case 4:
139 		bn_sub_words(t,      a,      &(a[n]),n);
140 		bn_sub_words(&(t[n]),&(b[n]),b,      n);
141 		break;
142 		}
143 
144 # ifdef BN_MUL_COMBA
145 	if (n == 4)
146 		{
147 		if (!zero)
148 			bn_mul_comba4(&(t[n2]),t,&(t[n]));
149 		else
150 			memset(&(t[n2]),0,8*sizeof(BN_ULONG));
151 
152 		bn_mul_comba4(r,a,b);
153 		bn_mul_comba4(&(r[n2]),&(a[n]),&(b[n]));
154 		}
155 	else if (n == 8)
156 		{
157 		if (!zero)
158 			bn_mul_comba8(&(t[n2]),t,&(t[n]));
159 		else
160 			memset(&(t[n2]),0,16*sizeof(BN_ULONG));
161 
162 		bn_mul_comba8(r,a,b);
163 		bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n]));
164 		}
165 	else
166 # endif /* BN_MUL_COMBA */
167 		{
168 		p= &(t[n2*2]);
169 		if (!zero)
170 			bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
171 		else
172 			memset(&(t[n2]),0,n2*sizeof(BN_ULONG));
173 		bn_mul_recursive(r,a,b,n,p);
174 		bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,p);
175 		}
176 
177 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
178 	 * r[10] holds (a[0]*b[0])
179 	 * r[32] holds (b[1]*b[1])
180 	 */
181 
182 	c1=(int)(bn_add_words(t,r,&(r[n2]),n2));
183 
184 	if (neg) /* if t[32] is negative */
185 		{
186 		c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
187 		}
188 	else
189 		{
190 		/* Might have a carry */
191 		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));
192 		}
193 
194 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
195 	 * r[10] holds (a[0]*b[0])
196 	 * r[32] holds (b[1]*b[1])
197 	 * c1 holds the carry bits
198 	 */
199 	c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
200 	if (c1)
201 		{
202 		p= &(r[n+n2]);
203 		lo= *p;
204 		ln=(lo+c1)&BN_MASK2;
205 		*p=ln;
206 
207 		/* The overflow will stop before we over write
208 		 * words we should not overwrite */
209 		if (ln < (BN_ULONG)c1)
210 			{
211 			do	{
212 				p++;
213 				lo= *p;
214 				ln=(lo+1)&BN_MASK2;
215 				*p=ln;
216 				} while (ln == 0);
217 			}
218 		}
219 	}
220 
221 /* n+tn is the word length
222  * t needs to be n*4 is size, as does r */
223 void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int tn,
224 	     int n, BN_ULONG *t)
225 	{
226 	int i,j,n2=n*2;
227 	unsigned int c1,c2,neg,zero;
228 	BN_ULONG ln,lo,*p;
229 
230 # ifdef BN_COUNT
231 	printf(" bn_mul_part_recursive %d * %d\n",tn+n,tn+n);
232 # endif
233 	if (n < 8)
234 		{
235 		i=tn+n;
236 		bn_mul_normal(r,a,i,b,i);
237 		return;
238 		}
239 
240 	/* r=(a[0]-a[1])*(b[1]-b[0]) */
241 	c1=bn_cmp_words(a,&(a[n]),n);
242 	c2=bn_cmp_words(&(b[n]),b,n);
243 	zero=neg=0;
244 	switch (c1*3+c2)
245 		{
246 	case -4:
247 		bn_sub_words(t,      &(a[n]),a,      n); /* - */
248 		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
249 		break;
250 	case -3:
251 		zero=1;
252 		/* break; */
253 	case -2:
254 		bn_sub_words(t,      &(a[n]),a,      n); /* - */
255 		bn_sub_words(&(t[n]),&(b[n]),b,      n); /* + */
256 		neg=1;
257 		break;
258 	case -1:
259 	case 0:
260 	case 1:
261 		zero=1;
262 		/* break; */
263 	case 2:
264 		bn_sub_words(t,      a,      &(a[n]),n); /* + */
265 		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
266 		neg=1;
267 		break;
268 	case 3:
269 		zero=1;
270 		/* break; */
271 	case 4:
272 		bn_sub_words(t,      a,      &(a[n]),n);
273 		bn_sub_words(&(t[n]),&(b[n]),b,      n);
274 		break;
275 		}
276 		/* The zero case isn't yet implemented here. The speedup
277 		   would probably be negligible. */
278 # if 0
279 	if (n == 4)
280 		{
281 		bn_mul_comba4(&(t[n2]),t,&(t[n]));
282 		bn_mul_comba4(r,a,b);
283 		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
284 		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
285 		}
286 	else
287 # endif
288 	if (n == 8)
289 		{
290 		bn_mul_comba8(&(t[n2]),t,&(t[n]));
291 		bn_mul_comba8(r,a,b);
292 		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
293 		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
294 		}
295 	else
296 		{
297 		p= &(t[n2*2]);
298 		bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
299 		bn_mul_recursive(r,a,b,n,p);
300 		i=n/2;
301 		/* If there is only a bottom half to the number,
302 		 * just do it */
303 		j=tn-i;
304 		if (j == 0)
305 			{
306 			bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),i,p);
307 			memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2));
308 			}
309 		else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */
310 				{
311 				bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]),
312 					j,i,p);
313 				memset(&(r[n2+tn*2]),0,
314 					sizeof(BN_ULONG)*(n2-tn*2));
315 				}
316 		else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
317 			{
318 			memset(&(r[n2]),0,sizeof(BN_ULONG)*n2);
319 			if (tn < BN_MUL_RECURSIVE_SIZE_NORMAL)
320 				{
321 				bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
322 				}
323 			else
324 				{
325 				for (;;)
326 					{
327 					i/=2;
328 					if (i < tn)
329 						{
330 						bn_mul_part_recursive(&(r[n2]),
331 							&(a[n]),&(b[n]),
332 							tn-i,i,p);
333 						break;
334 						}
335 					else if (i == tn)
336 						{
337 						bn_mul_recursive(&(r[n2]),
338 							&(a[n]),&(b[n]),
339 							i,p);
340 						break;
341 						}
342 					}
343 				}
344 			}
345 		}
346 
347 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
348 	 * r[10] holds (a[0]*b[0])
349 	 * r[32] holds (b[1]*b[1])
350 	 */
351 
352 	c1=(int)(bn_add_words(t,r,&(r[n2]),n2));
353 
354 	if (neg) /* if t[32] is negative */
355 		{
356 		c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
357 		}
358 	else
359 		{
360 		/* Might have a carry */
361 		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));
362 		}
363 
364 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
365 	 * r[10] holds (a[0]*b[0])
366 	 * r[32] holds (b[1]*b[1])
367 	 * c1 holds the carry bits
368 	 */
369 	c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
370 	if (c1)
371 		{
372 		p= &(r[n+n2]);
373 		lo= *p;
374 		ln=(lo+c1)&BN_MASK2;
375 		*p=ln;
376 
377 		/* The overflow will stop before we over write
378 		 * words we should not overwrite */
379 		if (ln < c1)
380 			{
381 			do	{
382 				p++;
383 				lo= *p;
384 				ln=(lo+1)&BN_MASK2;
385 				*p=ln;
386 				} while (ln == 0);
387 			}
388 		}
389 	}
390 
391 /* a and b must be the same size, which is n2.
392  * r needs to be n2 words and t needs to be n2*2
393  */
394 void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
395 	     BN_ULONG *t)
396 	{
397 	int n=n2/2;
398 
399 # ifdef BN_COUNT
400 	printf(" bn_mul_low_recursive %d * %d\n",n2,n2);
401 # endif
402 
403 	bn_mul_recursive(r,a,b,n,&(t[0]));
404 	if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL)
405 		{
406 		bn_mul_low_recursive(&(t[0]),&(a[0]),&(b[n]),n,&(t[n2]));
407 		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
408 		bn_mul_low_recursive(&(t[0]),&(a[n]),&(b[0]),n,&(t[n2]));
409 		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
410 		}
411 	else
412 		{
413 		bn_mul_low_normal(&(t[0]),&(a[0]),&(b[n]),n);
414 		bn_mul_low_normal(&(t[n]),&(a[n]),&(b[0]),n);
415 		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
416 		bn_add_words(&(r[n]),&(r[n]),&(t[n]),n);
417 		}
418 	}
419 
420 /* a and b must be the same size, which is n2.
421  * r needs to be n2 words and t needs to be n2*2
422  * l is the low words of the output.
423  * t needs to be n2*3
424  */
425 void bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2,
426 	     BN_ULONG *t)
427 	{
428 	int i,n;
429 	int c1,c2;
430 	int neg,oneg,zero;
431 	BN_ULONG ll,lc,*lp,*mp;
432 
433 # ifdef BN_COUNT
434 	printf(" bn_mul_high %d * %d\n",n2,n2);
435 # endif
436 	n=n2/2;
437 
438 	/* Calculate (al-ah)*(bh-bl) */
439 	neg=zero=0;
440 	c1=bn_cmp_words(&(a[0]),&(a[n]),n);
441 	c2=bn_cmp_words(&(b[n]),&(b[0]),n);
442 	switch (c1*3+c2)
443 		{
444 	case -4:
445 		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
446 		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
447 		break;
448 	case -3:
449 		zero=1;
450 		break;
451 	case -2:
452 		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
453 		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
454 		neg=1;
455 		break;
456 	case -1:
457 	case 0:
458 	case 1:
459 		zero=1;
460 		break;
461 	case 2:
462 		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
463 		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
464 		neg=1;
465 		break;
466 	case 3:
467 		zero=1;
468 		break;
469 	case 4:
470 		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
471 		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
472 		break;
473 		}
474 
475 	oneg=neg;
476 	/* t[10] = (a[0]-a[1])*(b[1]-b[0]) */
477 	/* r[10] = (a[1]*b[1]) */
478 # ifdef BN_MUL_COMBA
479 	if (n == 8)
480 		{
481 		bn_mul_comba8(&(t[0]),&(r[0]),&(r[n]));
482 		bn_mul_comba8(r,&(a[n]),&(b[n]));
483 		}
484 	else
485 # endif
486 		{
487 		bn_mul_recursive(&(t[0]),&(r[0]),&(r[n]),n,&(t[n2]));
488 		bn_mul_recursive(r,&(a[n]),&(b[n]),n,&(t[n2]));
489 		}
490 
491 	/* s0 == low(al*bl)
492 	 * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
493 	 * We know s0 and s1 so the only unknown is high(al*bl)
494 	 * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl))
495 	 * high(al*bl) == s1 - (r[0]+l[0]+t[0])
496 	 */
497 	if (l != NULL)
498 		{
499 		lp= &(t[n2+n]);
500 		c1=(int)(bn_add_words(lp,&(r[0]),&(l[0]),n));
501 		}
502 	else
503 		{
504 		c1=0;
505 		lp= &(r[0]);
506 		}
507 
508 	if (neg)
509 		neg=(int)(bn_sub_words(&(t[n2]),lp,&(t[0]),n));
510 	else
511 		{
512 		bn_add_words(&(t[n2]),lp,&(t[0]),n);
513 		neg=0;
514 		}
515 
516 	if (l != NULL)
517 		{
518 		bn_sub_words(&(t[n2+n]),&(l[n]),&(t[n2]),n);
519 		}
520 	else
521 		{
522 		lp= &(t[n2+n]);
523 		mp= &(t[n2]);
524 		for (i=0; i<n; i++)
525 			lp[i]=((~mp[i])+1)&BN_MASK2;
526 		}
527 
528 	/* s[0] = low(al*bl)
529 	 * t[3] = high(al*bl)
530 	 * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign
531 	 * r[10] = (a[1]*b[1])
532 	 */
533 	/* R[10] = al*bl
534 	 * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0])
535 	 * R[32] = ah*bh
536 	 */
537 	/* R[1]=t[3]+l[0]+r[0](+-)t[0] (have carry/borrow)
538 	 * R[2]=r[0]+t[3]+r[1](+-)t[1] (have carry/borrow)
539 	 * R[3]=r[1]+(carry/borrow)
540 	 */
541 	if (l != NULL)
542 		{
543 		lp= &(t[n2]);
544 		c1= (int)(bn_add_words(lp,&(t[n2+n]),&(l[0]),n));
545 		}
546 	else
547 		{
548 		lp= &(t[n2+n]);
549 		c1=0;
550 		}
551 	c1+=(int)(bn_add_words(&(t[n2]),lp,  &(r[0]),n));
552 	if (oneg)
553 		c1-=(int)(bn_sub_words(&(t[n2]),&(t[n2]),&(t[0]),n));
554 	else
555 		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),&(t[0]),n));
556 
557 	c2 =(int)(bn_add_words(&(r[0]),&(r[0]),&(t[n2+n]),n));
558 	c2+=(int)(bn_add_words(&(r[0]),&(r[0]),&(r[n]),n));
559 	if (oneg)
560 		c2-=(int)(bn_sub_words(&(r[0]),&(r[0]),&(t[n]),n));
561 	else
562 		c2+=(int)(bn_add_words(&(r[0]),&(r[0]),&(t[n]),n));
563 
564 	if (c1 != 0) /* Add starting at r[0], could be +ve or -ve */
565 		{
566 		i=0;
567 		if (c1 > 0)
568 			{
569 			lc=c1;
570 			do	{
571 				ll=(r[i]+lc)&BN_MASK2;
572 				r[i++]=ll;
573 				lc=(lc > ll);
574 				} while (lc);
575 			}
576 		else
577 			{
578 			lc= -c1;
579 			do	{
580 				ll=r[i];
581 				r[i++]=(ll-lc)&BN_MASK2;
582 				lc=(lc > ll);
583 				} while (lc);
584 			}
585 		}
586 	if (c2 != 0) /* Add starting at r[1] */
587 		{
588 		i=n;
589 		if (c2 > 0)
590 			{
591 			lc=c2;
592 			do	{
593 				ll=(r[i]+lc)&BN_MASK2;
594 				r[i++]=ll;
595 				lc=(lc > ll);
596 				} while (lc);
597 			}
598 		else
599 			{
600 			lc= -c2;
601 			do	{
602 				ll=r[i];
603 				r[i++]=(ll-lc)&BN_MASK2;
604 				lc=(lc > ll);
605 				} while (lc);
606 			}
607 		}
608 	}
609 #endif /* BN_RECURSION */
610 
611 int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
612 	{
613 	int top,al,bl;
614 	BIGNUM *rr;
615 	int ret = 0;
616 #if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
617 	int i;
618 #endif
619 #ifdef BN_RECURSION
620 	BIGNUM *t;
621 	int j,k;
622 #endif
623 
624 #ifdef BN_COUNT
625 	printf("BN_mul %d * %d\n",a->top,b->top);
626 #endif
627 
628 	bn_check_top(a);
629 	bn_check_top(b);
630 	bn_check_top(r);
631 
632 	al=a->top;
633 	bl=b->top;
634 
635 	if ((al == 0) || (bl == 0))
636 		{
637 		BN_zero(r);
638 		return(1);
639 		}
640 	top=al+bl;
641 
642 	BN_CTX_start(ctx);
643 	if ((r == a) || (r == b))
644 		{
645 		if ((rr = BN_CTX_get(ctx)) == NULL) goto err;
646 		}
647 	else
648 		rr = r;
649 	rr->neg=a->neg^b->neg;
650 
651 #if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
652 	i = al-bl;
653 #endif
654 #ifdef BN_MUL_COMBA
655 	if (i == 0)
656 		{
657 # if 0
658 		if (al == 4)
659 			{
660 			if (bn_wexpand(rr,8) == NULL) goto err;
661 			rr->top=8;
662 			bn_mul_comba4(rr->d,a->d,b->d);
663 			goto end;
664 			}
665 # endif
666 		if (al == 8)
667 			{
668 			if (bn_wexpand(rr,16) == NULL) goto err;
669 			rr->top=16;
670 			bn_mul_comba8(rr->d,a->d,b->d);
671 			goto end;
672 			}
673 		}
674 #endif /* BN_MUL_COMBA */
675 #ifdef BN_RECURSION
676 	if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL))
677 		{
678 		if (i == 1 && !BN_get_flags(b,BN_FLG_STATIC_DATA))
679 			{
680 			bn_wexpand(b,al);
681 			b->d[bl]=0;
682 			bl++;
683 			i--;
684 			}
685 		else if (i == -1 && !BN_get_flags(a,BN_FLG_STATIC_DATA))
686 			{
687 			bn_wexpand(a,bl);
688 			a->d[al]=0;
689 			al++;
690 			i++;
691 			}
692 		if (i == 0)
693 			{
694 			/* symmetric and > 4 */
695 			/* 16 or larger */
696 			j=BN_num_bits_word((BN_ULONG)al);
697 			j=1<<(j-1);
698 			k=j+j;
699 			t = BN_CTX_get(ctx);
700 			if (al == j) /* exact multiple */
701 				{
702 				bn_wexpand(t,k*2);
703 				bn_wexpand(rr,k*2);
704 				bn_mul_recursive(rr->d,a->d,b->d,al,t->d);
705 				}
706 			else
707 				{
708 				bn_wexpand(a,k);
709 				bn_wexpand(b,k);
710 				bn_wexpand(t,k*4);
711 				bn_wexpand(rr,k*4);
712 				for (i=a->top; i<k; i++)
713 					a->d[i]=0;
714 				for (i=b->top; i<k; i++)
715 					b->d[i]=0;
716 				bn_mul_part_recursive(rr->d,a->d,b->d,al-j,j,t->d);
717 				}
718 			rr->top=top;
719 			goto end;
720 			}
721 		}
722 #endif /* BN_RECURSION */
723 	if (bn_wexpand(rr,top) == NULL) goto err;
724 	rr->top=top;
725 	bn_mul_normal(rr->d,a->d,al,b->d,bl);
726 
727 #if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
728 end:
729 #endif
730 	bn_fix_top(rr);
731 	if (r != rr) BN_copy(r,rr);
732 	ret=1;
733 err:
734 	BN_CTX_end(ctx);
735 	return(ret);
736 	}
737 
738 void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
739 	{
740 	BN_ULONG *rr;
741 
742 #ifdef BN_COUNT
743 	printf(" bn_mul_normal %d * %d\n",na,nb);
744 #endif
745 
746 	if (na < nb)
747 		{
748 		int itmp;
749 		BN_ULONG *ltmp;
750 
751 		itmp=na; na=nb; nb=itmp;
752 		ltmp=a;   a=b;   b=ltmp;
753 
754 		}
755 	rr= &(r[na]);
756 	rr[0]=bn_mul_words(r,a,na,b[0]);
757 
758 	for (;;)
759 		{
760 		if (--nb <= 0) return;
761 		rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]);
762 		if (--nb <= 0) return;
763 		rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]);
764 		if (--nb <= 0) return;
765 		rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]);
766 		if (--nb <= 0) return;
767 		rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]);
768 		rr+=4;
769 		r+=4;
770 		b+=4;
771 		}
772 	}
773 
774 void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
775 	{
776 #ifdef BN_COUNT
777 	printf(" bn_mul_low_normal %d * %d\n",n,n);
778 #endif
779 	bn_mul_words(r,a,n,b[0]);
780 
781 	for (;;)
782 		{
783 		if (--n <= 0) return;
784 		bn_mul_add_words(&(r[1]),a,n,b[1]);
785 		if (--n <= 0) return;
786 		bn_mul_add_words(&(r[2]),a,n,b[2]);
787 		if (--n <= 0) return;
788 		bn_mul_add_words(&(r[3]),a,n,b[3]);
789 		if (--n <= 0) return;
790 		bn_mul_add_words(&(r[4]),a,n,b[4]);
791 		r+=4;
792 		b+=4;
793 		}
794 	}
795