ispell (and minor modifications)
[openssl.git] / crypto / bn / bn_mul.c
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 calculate
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  */
74 void 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
82 printf(" 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 */
218 void 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
226 printf(" 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  */
343 void 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
349 printf(" 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  */
374 void 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
383 printf(" 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
560 int 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
570 printf("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 symmetric;
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 symmetric;
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 symmetric;
651                         }
652                 }
653 #endif
654
655         /* asymmetric 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                 {
663 symmetric:
664                 /* symmetric 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)
692 end:
693 #endif
694         bn_fix_top(rr);
695         if (r != rr) BN_copy(r,rr);
696         return(1);
697         }
698
699 void 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
704 printf(" 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
735 void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
736         {
737 #ifdef BN_COUNT
738 printf(" 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