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 */
77void 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 */
223void 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	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 < (BN_ULONG)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 */
394void 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 */
425void 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
611int BN_mul(BIGNUM *r, const BIGNUM *a, const 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		if (!BN_zero(r)) goto err;
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) && bl<b->dmax)
679			{
680#if 0	/* tribute to const-ification, bl<b->dmax above covers for this */
681			if (bn_wexpand(b,al) == NULL) goto err;
682#endif
683			b->d[bl]=0;
684			bl++;
685			i--;
686			}
687		else if (i == -1 && !BN_get_flags(a,BN_FLG_STATIC_DATA) && al<a->dmax)
688			{
689#if 0	/* tribute to const-ification, al<a->dmax above covers for this */
690			if (bn_wexpand(a,bl) == NULL) goto err;
691#endif
692			a->d[al]=0;
693			al++;
694			i++;
695			}
696		if (i == 0)
697			{
698			/* symmetric and > 4 */
699			/* 16 or larger */
700			j=BN_num_bits_word((BN_ULONG)al);
701			j=1<<(j-1);
702			k=j+j;
703			t = BN_CTX_get(ctx);
704			if (al == j) /* exact multiple */
705				{
706				if (bn_wexpand(t,k*2) == NULL) goto err;
707				if (bn_wexpand(rr,k*2) == NULL) goto err;
708				bn_mul_recursive(rr->d,a->d,b->d,al,t->d);
709				rr->top=top;
710				goto end;
711				}
712#if 0	/* tribute to const-ification, rsa/dsa performance is not affected */
713			else
714				{
715				if (bn_wexpand(a,k) == NULL ) goto err;
716				if (bn_wexpand(b,k) == NULL ) goto err;
717				if (bn_wexpand(t,k*4) == NULL ) goto err;
718				if (bn_wexpand(rr,k*4) == NULL ) goto err;
719				for (i=a->top; i<k; i++)
720					a->d[i]=0;
721				for (i=b->top; i<k; i++)
722					b->d[i]=0;
723				bn_mul_part_recursive(rr->d,a->d,b->d,al-j,j,t->d);
724				}
725			rr->top=top;
726			goto end;
727#endif
728			}
729		}
730#endif /* BN_RECURSION */
731	if (bn_wexpand(rr,top) == NULL) goto err;
732	rr->top=top;
733	bn_mul_normal(rr->d,a->d,al,b->d,bl);
734
735#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
736end:
737#endif
738	bn_fix_top(rr);
739	if (r != rr) BN_copy(r,rr);
740	ret=1;
741err:
742	BN_CTX_end(ctx);
743	return(ret);
744	}
745
746void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
747	{
748	BN_ULONG *rr;
749
750#ifdef BN_COUNT
751	printf(" bn_mul_normal %d * %d\n",na,nb);
752#endif
753
754	if (na < nb)
755		{
756		int itmp;
757		BN_ULONG *ltmp;
758
759		itmp=na; na=nb; nb=itmp;
760		ltmp=a;   a=b;   b=ltmp;
761
762		}
763	rr= &(r[na]);
764	rr[0]=bn_mul_words(r,a,na,b[0]);
765
766	for (;;)
767		{
768		if (--nb <= 0) return;
769		rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]);
770		if (--nb <= 0) return;
771		rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]);
772		if (--nb <= 0) return;
773		rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]);
774		if (--nb <= 0) return;
775		rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]);
776		rr+=4;
777		r+=4;
778		b+=4;
779		}
780	}
781
782void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
783	{
784#ifdef BN_COUNT
785	printf(" bn_mul_low_normal %d * %d\n",n,n);
786#endif
787	bn_mul_words(r,a,n,b[0]);
788
789	for (;;)
790		{
791		if (--n <= 0) return;
792		bn_mul_add_words(&(r[1]),a,n,b[1]);
793		if (--n <= 0) return;
794		bn_mul_add_words(&(r[2]),a,n,b[2]);
795		if (--n <= 0) return;
796		bn_mul_add_words(&(r[3]),a,n,b[3]);
797		if (--n <= 0) return;
798		bn_mul_add_words(&(r[4]),a,n,b[4]);
799		r+=4;
800		b+=4;
801		}
802	}
803