bn_mul.c revision 1.2
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/* r is 2*n2 words in size,
65 * a and b are both n2 words in size.
66 * n2 must be a power of 2.
67 * We multiply and return the result.
68 * t must be 2*n2 words in size
69 * We calulate
70 * a[0]*b[0]
71 * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
72 * a[1]*b[1]
73 */
74void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
75	     BN_ULONG *t)
76	{
77	int n=n2/2,c1,c2;
78	unsigned int neg,zero;
79	BN_ULONG ln,lo,*p;
80
81#ifdef BN_COUNT
82printf(" bn_mul_recursive %d * %d\n",n2,n2);
83#endif
84#ifdef BN_MUL_COMBA
85/*	if (n2 == 4)
86		{
87		bn_mul_comba4(r,a,b);
88		return;
89		}
90	else */ if (n2 == 8)
91		{
92		bn_mul_comba8(r,a,b);
93		return;
94		}
95#endif
96	if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL)
97		{
98		/* This should not happen */
99		bn_mul_normal(r,a,n2,b,n2);
100		return;
101		}
102	/* r=(a[0]-a[1])*(b[1]-b[0]) */
103	c1=bn_cmp_words(a,&(a[n]),n);
104	c2=bn_cmp_words(&(b[n]),b,n);
105	zero=neg=0;
106	switch (c1*3+c2)
107		{
108	case -4:
109		bn_sub_words(t,      &(a[n]),a,      n); /* - */
110		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
111		break;
112	case -3:
113		zero=1;
114		break;
115	case -2:
116		bn_sub_words(t,      &(a[n]),a,      n); /* - */
117		bn_sub_words(&(t[n]),&(b[n]),b,      n); /* + */
118		neg=1;
119		break;
120	case -1:
121	case 0:
122	case 1:
123		zero=1;
124		break;
125	case 2:
126		bn_sub_words(t,      a,      &(a[n]),n); /* + */
127		bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
128		neg=1;
129		break;
130	case 3:
131		zero=1;
132		break;
133	case 4:
134		bn_sub_words(t,      a,      &(a[n]),n);
135		bn_sub_words(&(t[n]),&(b[n]),b,      n);
136		break;
137		}
138
139#ifdef BN_MUL_COMBA
140	if (n == 4)
141		{
142		if (!zero)
143			bn_mul_comba4(&(t[n2]),t,&(t[n]));
144		else
145			memset(&(t[n2]),0,8*sizeof(BN_ULONG));
146
147		bn_mul_comba4(r,a,b);
148		bn_mul_comba4(&(r[n2]),&(a[n]),&(b[n]));
149		}
150	else if (n == 8)
151		{
152		if (!zero)
153			bn_mul_comba8(&(t[n2]),t,&(t[n]));
154		else
155			memset(&(t[n2]),0,16*sizeof(BN_ULONG));
156
157		bn_mul_comba8(r,a,b);
158		bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n]));
159		}
160	else
161#endif
162		{
163		p= &(t[n2*2]);
164		if (!zero)
165			bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
166		else
167			memset(&(t[n2]),0,n2*sizeof(BN_ULONG));
168		bn_mul_recursive(r,a,b,n,p);
169		bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,p);
170		}
171
172	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
173	 * r[10] holds (a[0]*b[0])
174	 * r[32] holds (b[1]*b[1])
175	 */
176
177	c1=(int)(bn_add_words(t,r,&(r[n2]),n2));
178
179	if (neg) /* if t[32] is negative */
180		{
181		c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
182		}
183	else
184		{
185		/* Might have a carry */
186		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));
187		}
188
189	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
190	 * r[10] holds (a[0]*b[0])
191	 * r[32] holds (b[1]*b[1])
192	 * c1 holds the carry bits
193	 */
194	c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
195	if (c1)
196		{
197		p= &(r[n+n2]);
198		lo= *p;
199		ln=(lo+c1)&BN_MASK2;
200		*p=ln;
201
202		/* The overflow will stop before we over write
203		 * words we should not overwrite */
204		if (ln < (BN_ULONG)c1)
205			{
206			do	{
207				p++;
208				lo= *p;
209				ln=(lo+1)&BN_MASK2;
210				*p=ln;
211				} while (ln == 0);
212			}
213		}
214	}
215
216/* n+tn is the word length
217 * t needs to be n*4 is size, as does r */
218void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int tn,
219	     int n, BN_ULONG *t)
220	{
221	int i,j,n2=n*2;
222	unsigned int c1;
223	BN_ULONG ln,lo,*p;
224
225#ifdef BN_COUNT
226printf(" bn_mul_part_recursive %d * %d\n",tn+n,tn+n);
227#endif
228	if (n < 8)
229		{
230		i=tn+n;
231		bn_mul_normal(r,a,i,b,i);
232		return;
233		}
234
235	/* r=(a[0]-a[1])*(b[1]-b[0]) */
236	bn_sub_words(t,      a,      &(a[n]),n); /* + */
237	bn_sub_words(&(t[n]),b,      &(b[n]),n); /* - */
238
239/*	if (n == 4)
240		{
241		bn_mul_comba4(&(t[n2]),t,&(t[n]));
242		bn_mul_comba4(r,a,b);
243		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
244		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
245		}
246	else */ if (n == 8)
247		{
248		bn_mul_comba8(&(t[n2]),t,&(t[n]));
249		bn_mul_comba8(r,a,b);
250		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
251		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
252		}
253	else
254		{
255		p= &(t[n2*2]);
256		bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
257		bn_mul_recursive(r,a,b,n,p);
258		i=n/2;
259		/* If there is only a bottom half to the number,
260		 * just do it */
261		j=tn-i;
262		if (j == 0)
263			{
264			bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),i,p);
265			memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2));
266			}
267		else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */
268				{
269				bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]),
270					j,i,p);
271				memset(&(r[n2+tn*2]),0,
272					sizeof(BN_ULONG)*(n2-tn*2));
273				}
274		else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
275			{
276			memset(&(r[n2]),0,sizeof(BN_ULONG)*n2);
277			if (tn < BN_MUL_RECURSIVE_SIZE_NORMAL)
278				{
279				bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
280				}
281			else
282				{
283				for (;;)
284					{
285					i/=2;
286					if (i < tn)
287						{
288						bn_mul_part_recursive(&(r[n2]),
289							&(a[n]),&(b[n]),
290							tn-i,i,p);
291						break;
292						}
293					else if (i == tn)
294						{
295						bn_mul_recursive(&(r[n2]),
296							&(a[n]),&(b[n]),
297							i,p);
298						break;
299						}
300					}
301				}
302			}
303		}
304
305	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
306	 * r[10] holds (a[0]*b[0])
307	 * r[32] holds (b[1]*b[1])
308	 */
309
310	c1=(int)(bn_add_words(t,r,&(r[n2]),n2));
311	c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
312
313	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
314	 * r[10] holds (a[0]*b[0])
315	 * r[32] holds (b[1]*b[1])
316	 * c1 holds the carry bits
317	 */
318	c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
319	if (c1)
320		{
321		p= &(r[n+n2]);
322		lo= *p;
323		ln=(lo+c1)&BN_MASK2;
324		*p=ln;
325
326		/* The overflow will stop before we over write
327		 * words we should not overwrite */
328		if (ln < c1)
329			{
330			do	{
331				p++;
332				lo= *p;
333				ln=(lo+1)&BN_MASK2;
334				*p=ln;
335				} while (ln == 0);
336			}
337		}
338	}
339
340/* a and b must be the same size, which is n2.
341 * r needs to be n2 words and t needs to be n2*2
342 */
343void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
344	     BN_ULONG *t)
345	{
346	int n=n2/2;
347
348#ifdef BN_COUNT
349printf(" bn_mul_low_recursive %d * %d\n",n2,n2);
350#endif
351
352	bn_mul_recursive(r,a,b,n,&(t[0]));
353	if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL)
354		{
355		bn_mul_low_recursive(&(t[0]),&(a[0]),&(b[n]),n,&(t[n2]));
356		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
357		bn_mul_low_recursive(&(t[0]),&(a[n]),&(b[0]),n,&(t[n2]));
358		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
359		}
360	else
361		{
362		bn_mul_low_normal(&(t[0]),&(a[0]),&(b[n]),n);
363		bn_mul_low_normal(&(t[n]),&(a[n]),&(b[0]),n);
364		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
365		bn_add_words(&(r[n]),&(r[n]),&(t[n]),n);
366		}
367	}
368
369/* a and b must be the same size, which is n2.
370 * r needs to be n2 words and t needs to be n2*2
371 * l is the low words of the output.
372 * t needs to be n2*3
373 */
374void bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2,
375	     BN_ULONG *t)
376	{
377	int i,n;
378	int c1,c2;
379	int neg,oneg,zero;
380	BN_ULONG ll,lc,*lp,*mp;
381
382#ifdef BN_COUNT
383printf(" bn_mul_high %d * %d\n",n2,n2);
384#endif
385	n=n2/2;
386
387	/* Calculate (al-ah)*(bh-bl) */
388	neg=zero=0;
389	c1=bn_cmp_words(&(a[0]),&(a[n]),n);
390	c2=bn_cmp_words(&(b[n]),&(b[0]),n);
391	switch (c1*3+c2)
392		{
393	case -4:
394		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
395		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
396		break;
397	case -3:
398		zero=1;
399		break;
400	case -2:
401		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
402		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
403		neg=1;
404		break;
405	case -1:
406	case 0:
407	case 1:
408		zero=1;
409		break;
410	case 2:
411		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
412		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
413		neg=1;
414		break;
415	case 3:
416		zero=1;
417		break;
418	case 4:
419		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
420		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
421		break;
422		}
423
424	oneg=neg;
425	/* t[10] = (a[0]-a[1])*(b[1]-b[0]) */
426	/* r[10] = (a[1]*b[1]) */
427#ifdef BN_MUL_COMBA
428	if (n == 8)
429		{
430		bn_mul_comba8(&(t[0]),&(r[0]),&(r[n]));
431		bn_mul_comba8(r,&(a[n]),&(b[n]));
432		}
433	else
434#endif
435		{
436		bn_mul_recursive(&(t[0]),&(r[0]),&(r[n]),n,&(t[n2]));
437		bn_mul_recursive(r,&(a[n]),&(b[n]),n,&(t[n2]));
438		}
439
440	/* s0 == low(al*bl)
441	 * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
442	 * We know s0 and s1 so the only unknown is high(al*bl)
443	 * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl))
444	 * high(al*bl) == s1 - (r[0]+l[0]+t[0])
445	 */
446	if (l != NULL)
447		{
448		lp= &(t[n2+n]);
449		c1=(int)(bn_add_words(lp,&(r[0]),&(l[0]),n));
450		}
451	else
452		{
453		c1=0;
454		lp= &(r[0]);
455		}
456
457	if (neg)
458		neg=(int)(bn_sub_words(&(t[n2]),lp,&(t[0]),n));
459	else
460		{
461		bn_add_words(&(t[n2]),lp,&(t[0]),n);
462		neg=0;
463		}
464
465	if (l != NULL)
466		{
467		bn_sub_words(&(t[n2+n]),&(l[n]),&(t[n2]),n);
468		}
469	else
470		{
471		lp= &(t[n2+n]);
472		mp= &(t[n2]);
473		for (i=0; i<n; i++)
474			lp[i]=((~mp[i])+1)&BN_MASK2;
475		}
476
477	/* s[0] = low(al*bl)
478	 * t[3] = high(al*bl)
479	 * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign
480	 * r[10] = (a[1]*b[1])
481	 */
482	/* R[10] = al*bl
483	 * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0])
484	 * R[32] = ah*bh
485	 */
486	/* R[1]=t[3]+l[0]+r[0](+-)t[0] (have carry/borrow)
487	 * R[2]=r[0]+t[3]+r[1](+-)t[1] (have carry/borrow)
488	 * R[3]=r[1]+(carry/borrow)
489	 */
490	if (l != NULL)
491		{
492		lp= &(t[n2]);
493		c1= (int)(bn_add_words(lp,&(t[n2+n]),&(l[0]),n));
494		}
495	else
496		{
497		lp= &(t[n2+n]);
498		c1=0;
499		}
500	c1+=(int)(bn_add_words(&(t[n2]),lp,  &(r[0]),n));
501	if (oneg)
502		c1-=(int)(bn_sub_words(&(t[n2]),&(t[n2]),&(t[0]),n));
503	else
504		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),&(t[0]),n));
505
506	c2 =(int)(bn_add_words(&(r[0]),&(r[0]),&(t[n2+n]),n));
507	c2+=(int)(bn_add_words(&(r[0]),&(r[0]),&(r[n]),n));
508	if (oneg)
509		c2-=(int)(bn_sub_words(&(r[0]),&(r[0]),&(t[n]),n));
510	else
511		c2+=(int)(bn_add_words(&(r[0]),&(r[0]),&(t[n]),n));
512
513	if (c1 != 0) /* Add starting at r[0], could be +ve or -ve */
514		{
515		i=0;
516		if (c1 > 0)
517			{
518			lc=c1;
519			do	{
520				ll=(r[i]+lc)&BN_MASK2;
521				r[i++]=ll;
522				lc=(lc > ll);
523				} while (lc);
524			}
525		else
526			{
527			lc= -c1;
528			do	{
529				ll=r[i];
530				r[i++]=(ll-lc)&BN_MASK2;
531				lc=(lc > ll);
532				} while (lc);
533			}
534		}
535	if (c2 != 0) /* Add starting at r[1] */
536		{
537		i=n;
538		if (c2 > 0)
539			{
540			lc=c2;
541			do	{
542				ll=(r[i]+lc)&BN_MASK2;
543				r[i++]=ll;
544				lc=(lc > ll);
545				} while (lc);
546			}
547		else
548			{
549			lc= -c2;
550			do	{
551				ll=r[i];
552				r[i++]=(ll-lc)&BN_MASK2;
553				lc=(lc > ll);
554				} while (lc);
555			}
556		}
557	}
558#endif
559
560int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
561	{
562	int top,al,bl;
563	BIGNUM *rr;
564#ifdef BN_RECURSION
565	BIGNUM *t;
566	int i,j,k;
567#endif
568
569#ifdef BN_COUNT
570printf("BN_mul %d * %d\n",a->top,b->top);
571#endif
572
573	bn_check_top(a);
574	bn_check_top(b);
575	bn_check_top(r);
576
577	al=a->top;
578	bl=b->top;
579	r->neg=a->neg^b->neg;
580
581	if ((al == 0) || (bl == 0))
582		{
583		BN_zero(r);
584		return(1);
585		}
586	top=al+bl;
587
588	if ((r == a) || (r == b))
589		rr= &(ctx->bn[ctx->tos+1]);
590	else
591		rr=r;
592
593#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
594	if (al == bl)
595		{
596#  ifdef BN_MUL_COMBA
597/*		if (al == 4)
598			{
599			if (bn_wexpand(rr,8) == NULL) return(0);
600			rr->top=8;
601			bn_mul_comba4(rr->d,a->d,b->d);
602			goto end;
603			}
604		else */ if (al == 8)
605			{
606			if (bn_wexpand(rr,16) == NULL) return(0);
607			rr->top=16;
608			bn_mul_comba8(rr->d,a->d,b->d);
609			goto end;
610			}
611		else
612#  endif
613#ifdef BN_RECURSION
614		if (al < BN_MULL_SIZE_NORMAL)
615#endif
616			{
617			if (bn_wexpand(rr,top) == NULL) return(0);
618			rr->top=top;
619			bn_mul_normal(rr->d,a->d,al,b->d,bl);
620			goto end;
621			}
622#  ifdef BN_RECURSION
623		goto symetric;
624#  endif
625		}
626#endif
627#ifdef BN_RECURSION
628	else if ((al < BN_MULL_SIZE_NORMAL) || (bl < BN_MULL_SIZE_NORMAL))
629		{
630		if (bn_wexpand(rr,top) == NULL) return(0);
631		rr->top=top;
632		bn_mul_normal(rr->d,a->d,al,b->d,bl);
633		goto end;
634		}
635	else
636		{
637		i=(al-bl);
638		if ((i ==  1) && !BN_get_flags(b,BN_FLG_STATIC_DATA))
639			{
640			bn_wexpand(b,al);
641			b->d[bl]=0;
642			bl++;
643			goto symetric;
644			}
645		else if ((i ==  -1) && !BN_get_flags(a,BN_FLG_STATIC_DATA))
646			{
647			bn_wexpand(a,bl);
648			a->d[al]=0;
649			al++;
650			goto symetric;
651			}
652		}
653#endif
654
655	/* asymetric and >= 4 */
656	if (bn_wexpand(rr,top) == NULL) return(0);
657	rr->top=top;
658	bn_mul_normal(rr->d,a->d,al,b->d,bl);
659
660#ifdef BN_RECURSION
661	if (0)
662		{
663symetric:
664		/* symetric and > 4 */
665		/* 16 or larger */
666		j=BN_num_bits_word((BN_ULONG)al);
667		j=1<<(j-1);
668		k=j+j;
669		t= &(ctx->bn[ctx->tos]);
670		if (al == j) /* exact multiple */
671			{
672			bn_wexpand(t,k*2);
673			bn_wexpand(rr,k*2);
674			bn_mul_recursive(rr->d,a->d,b->d,al,t->d);
675			}
676		else
677			{
678			bn_wexpand(a,k);
679			bn_wexpand(b,k);
680			bn_wexpand(t,k*4);
681			bn_wexpand(rr,k*4);
682			for (i=a->top; i<k; i++)
683				a->d[i]=0;
684			for (i=b->top; i<k; i++)
685				b->d[i]=0;
686			bn_mul_part_recursive(rr->d,a->d,b->d,al-j,j,t->d);
687			}
688		rr->top=top;
689		}
690#endif
691#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
692end:
693#endif
694	bn_fix_top(rr);
695	if (r != rr) BN_copy(r,rr);
696	return(1);
697	}
698
699void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
700	{
701	BN_ULONG *rr;
702
703#ifdef BN_COUNT
704printf(" bn_mul_normal %d * %d\n",na,nb);
705#endif
706
707	if (na < nb)
708		{
709		int itmp;
710		BN_ULONG *ltmp;
711
712		itmp=na; na=nb; nb=itmp;
713		ltmp=a;   a=b;   b=ltmp;
714
715		}
716	rr= &(r[na]);
717	rr[0]=bn_mul_words(r,a,na,b[0]);
718
719	for (;;)
720		{
721		if (--nb <= 0) return;
722		rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]);
723		if (--nb <= 0) return;
724		rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]);
725		if (--nb <= 0) return;
726		rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]);
727		if (--nb <= 0) return;
728		rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]);
729		rr+=4;
730		r+=4;
731		b+=4;
732		}
733	}
734
735void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
736	{
737#ifdef BN_COUNT
738printf(" bn_mul_low_normal %d * %d\n",n,n);
739#endif
740	bn_mul_words(r,a,n,b[0]);
741
742	for (;;)
743		{
744		if (--n <= 0) return;
745		bn_mul_add_words(&(r[1]),a,n,b[1]);
746		if (--n <= 0) return;
747		bn_mul_add_words(&(r[2]),a,n,b[2]);
748		if (--n <= 0) return;
749		bn_mul_add_words(&(r[3]),a,n,b[3]);
750		if (--n <= 0) return;
751		bn_mul_add_words(&(r[4]),a,n,b[4]);
752		r+=4;
753		b+=4;
754		}
755	}
756
757