xref: /onnv-gate/usr/src/common/openssl/crypto/bn/bn_mul.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* crypto/bn/bn_mul.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate  * All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * This package is an SSL implementation written
60Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
110Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
130Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate  * the code are not to be removed.
180Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate  * as the author of the parts of the library used.
200Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate  * are met:
260Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate  *    must display the following acknowledgement:
330Sstevel@tonic-gate  *    "This product includes cryptographic software written by
340Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate  *    being used are not cryptographic related :-).
370Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate  *
410Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate  * SUCH DAMAGE.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
550Sstevel@tonic-gate  * copied and put under another distribution licence
560Sstevel@tonic-gate  * [including the GNU Public Licence.]
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
59*2139Sjp161948 #ifndef BN_DEBUG
60*2139Sjp161948 # undef NDEBUG /* avoid conflicting definitions */
61*2139Sjp161948 # define NDEBUG
62*2139Sjp161948 #endif
63*2139Sjp161948 
640Sstevel@tonic-gate #include <stdio.h>
65*2139Sjp161948 #include <assert.h>
660Sstevel@tonic-gate #include "cryptlib.h"
670Sstevel@tonic-gate #include "bn_lcl.h"
680Sstevel@tonic-gate 
69*2139Sjp161948 #if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS)
70*2139Sjp161948 /* Here follows specialised variants of bn_add_words() and
71*2139Sjp161948    bn_sub_words().  They have the property performing operations on
72*2139Sjp161948    arrays of different sizes.  The sizes of those arrays is expressed through
73*2139Sjp161948    cl, which is the common length ( basicall, min(len(a),len(b)) ), and dl,
74*2139Sjp161948    which is the delta between the two lengths, calculated as len(a)-len(b).
75*2139Sjp161948    All lengths are the number of BN_ULONGs...  For the operations that require
76*2139Sjp161948    a result array as parameter, it must have the length cl+abs(dl).
77*2139Sjp161948    These functions should probably end up in bn_asm.c as soon as there are
78*2139Sjp161948    assembler counterparts for the systems that use assembler files.  */
79*2139Sjp161948 
bn_sub_part_words(BN_ULONG * r,const BN_ULONG * a,const BN_ULONG * b,int cl,int dl)80*2139Sjp161948 BN_ULONG bn_sub_part_words(BN_ULONG *r,
81*2139Sjp161948 	const BN_ULONG *a, const BN_ULONG *b,
82*2139Sjp161948 	int cl, int dl)
83*2139Sjp161948 	{
84*2139Sjp161948 	BN_ULONG c, t;
85*2139Sjp161948 
86*2139Sjp161948 	assert(cl >= 0);
87*2139Sjp161948 	c = bn_sub_words(r, a, b, cl);
88*2139Sjp161948 
89*2139Sjp161948 	if (dl == 0)
90*2139Sjp161948 		return c;
91*2139Sjp161948 
92*2139Sjp161948 	r += cl;
93*2139Sjp161948 	a += cl;
94*2139Sjp161948 	b += cl;
95*2139Sjp161948 
96*2139Sjp161948 	if (dl < 0)
97*2139Sjp161948 		{
98*2139Sjp161948 #ifdef BN_COUNT
99*2139Sjp161948 		fprintf(stderr, "  bn_sub_part_words %d + %d (dl < 0, c = %d)\n", cl, dl, c);
100*2139Sjp161948 #endif
101*2139Sjp161948 		for (;;)
102*2139Sjp161948 			{
103*2139Sjp161948 			t = b[0];
104*2139Sjp161948 			r[0] = (0-t-c)&BN_MASK2;
105*2139Sjp161948 			if (t != 0) c=1;
106*2139Sjp161948 			if (++dl >= 0) break;
107*2139Sjp161948 
108*2139Sjp161948 			t = b[1];
109*2139Sjp161948 			r[1] = (0-t-c)&BN_MASK2;
110*2139Sjp161948 			if (t != 0) c=1;
111*2139Sjp161948 			if (++dl >= 0) break;
112*2139Sjp161948 
113*2139Sjp161948 			t = b[2];
114*2139Sjp161948 			r[2] = (0-t-c)&BN_MASK2;
115*2139Sjp161948 			if (t != 0) c=1;
116*2139Sjp161948 			if (++dl >= 0) break;
117*2139Sjp161948 
118*2139Sjp161948 			t = b[3];
119*2139Sjp161948 			r[3] = (0-t-c)&BN_MASK2;
120*2139Sjp161948 			if (t != 0) c=1;
121*2139Sjp161948 			if (++dl >= 0) break;
122*2139Sjp161948 
123*2139Sjp161948 			b += 4;
124*2139Sjp161948 			r += 4;
125*2139Sjp161948 			}
126*2139Sjp161948 		}
127*2139Sjp161948 	else
128*2139Sjp161948 		{
129*2139Sjp161948 		int save_dl = dl;
130*2139Sjp161948 #ifdef BN_COUNT
131*2139Sjp161948 		fprintf(stderr, "  bn_sub_part_words %d + %d (dl > 0, c = %d)\n", cl, dl, c);
132*2139Sjp161948 #endif
133*2139Sjp161948 		while(c)
134*2139Sjp161948 			{
135*2139Sjp161948 			t = a[0];
136*2139Sjp161948 			r[0] = (t-c)&BN_MASK2;
137*2139Sjp161948 			if (t != 0) c=0;
138*2139Sjp161948 			if (--dl <= 0) break;
139*2139Sjp161948 
140*2139Sjp161948 			t = a[1];
141*2139Sjp161948 			r[1] = (t-c)&BN_MASK2;
142*2139Sjp161948 			if (t != 0) c=0;
143*2139Sjp161948 			if (--dl <= 0) break;
144*2139Sjp161948 
145*2139Sjp161948 			t = a[2];
146*2139Sjp161948 			r[2] = (t-c)&BN_MASK2;
147*2139Sjp161948 			if (t != 0) c=0;
148*2139Sjp161948 			if (--dl <= 0) break;
149*2139Sjp161948 
150*2139Sjp161948 			t = a[3];
151*2139Sjp161948 			r[3] = (t-c)&BN_MASK2;
152*2139Sjp161948 			if (t != 0) c=0;
153*2139Sjp161948 			if (--dl <= 0) break;
154*2139Sjp161948 
155*2139Sjp161948 			save_dl = dl;
156*2139Sjp161948 			a += 4;
157*2139Sjp161948 			r += 4;
158*2139Sjp161948 			}
159*2139Sjp161948 		if (dl > 0)
160*2139Sjp161948 			{
161*2139Sjp161948 #ifdef BN_COUNT
162*2139Sjp161948 			fprintf(stderr, "  bn_sub_part_words %d + %d (dl > 0, c == 0)\n", cl, dl);
163*2139Sjp161948 #endif
164*2139Sjp161948 			if (save_dl > dl)
165*2139Sjp161948 				{
166*2139Sjp161948 				switch (save_dl - dl)
167*2139Sjp161948 					{
168*2139Sjp161948 				case 1:
169*2139Sjp161948 					r[1] = a[1];
170*2139Sjp161948 					if (--dl <= 0) break;
171*2139Sjp161948 				case 2:
172*2139Sjp161948 					r[2] = a[2];
173*2139Sjp161948 					if (--dl <= 0) break;
174*2139Sjp161948 				case 3:
175*2139Sjp161948 					r[3] = a[3];
176*2139Sjp161948 					if (--dl <= 0) break;
177*2139Sjp161948 					}
178*2139Sjp161948 				a += 4;
179*2139Sjp161948 				r += 4;
180*2139Sjp161948 				}
181*2139Sjp161948 			}
182*2139Sjp161948 		if (dl > 0)
183*2139Sjp161948 			{
184*2139Sjp161948 #ifdef BN_COUNT
185*2139Sjp161948 			fprintf(stderr, "  bn_sub_part_words %d + %d (dl > 0, copy)\n", cl, dl);
186*2139Sjp161948 #endif
187*2139Sjp161948 			for(;;)
188*2139Sjp161948 				{
189*2139Sjp161948 				r[0] = a[0];
190*2139Sjp161948 				if (--dl <= 0) break;
191*2139Sjp161948 				r[1] = a[1];
192*2139Sjp161948 				if (--dl <= 0) break;
193*2139Sjp161948 				r[2] = a[2];
194*2139Sjp161948 				if (--dl <= 0) break;
195*2139Sjp161948 				r[3] = a[3];
196*2139Sjp161948 				if (--dl <= 0) break;
197*2139Sjp161948 
198*2139Sjp161948 				a += 4;
199*2139Sjp161948 				r += 4;
200*2139Sjp161948 				}
201*2139Sjp161948 			}
202*2139Sjp161948 		}
203*2139Sjp161948 	return c;
204*2139Sjp161948 	}
205*2139Sjp161948 #endif
206*2139Sjp161948 
bn_add_part_words(BN_ULONG * r,const BN_ULONG * a,const BN_ULONG * b,int cl,int dl)207*2139Sjp161948 BN_ULONG bn_add_part_words(BN_ULONG *r,
208*2139Sjp161948 	const BN_ULONG *a, const BN_ULONG *b,
209*2139Sjp161948 	int cl, int dl)
210*2139Sjp161948 	{
211*2139Sjp161948 	BN_ULONG c, l, t;
212*2139Sjp161948 
213*2139Sjp161948 	assert(cl >= 0);
214*2139Sjp161948 	c = bn_add_words(r, a, b, cl);
215*2139Sjp161948 
216*2139Sjp161948 	if (dl == 0)
217*2139Sjp161948 		return c;
218*2139Sjp161948 
219*2139Sjp161948 	r += cl;
220*2139Sjp161948 	a += cl;
221*2139Sjp161948 	b += cl;
222*2139Sjp161948 
223*2139Sjp161948 	if (dl < 0)
224*2139Sjp161948 		{
225*2139Sjp161948 		int save_dl = dl;
226*2139Sjp161948 #ifdef BN_COUNT
227*2139Sjp161948 		fprintf(stderr, "  bn_add_part_words %d + %d (dl < 0, c = %d)\n", cl, dl, c);
228*2139Sjp161948 #endif
229*2139Sjp161948 		while (c)
230*2139Sjp161948 			{
231*2139Sjp161948 			l=(c+b[0])&BN_MASK2;
232*2139Sjp161948 			c=(l < c);
233*2139Sjp161948 			r[0]=l;
234*2139Sjp161948 			if (++dl >= 0) break;
235*2139Sjp161948 
236*2139Sjp161948 			l=(c+b[1])&BN_MASK2;
237*2139Sjp161948 			c=(l < c);
238*2139Sjp161948 			r[1]=l;
239*2139Sjp161948 			if (++dl >= 0) break;
240*2139Sjp161948 
241*2139Sjp161948 			l=(c+b[2])&BN_MASK2;
242*2139Sjp161948 			c=(l < c);
243*2139Sjp161948 			r[2]=l;
244*2139Sjp161948 			if (++dl >= 0) break;
245*2139Sjp161948 
246*2139Sjp161948 			l=(c+b[3])&BN_MASK2;
247*2139Sjp161948 			c=(l < c);
248*2139Sjp161948 			r[3]=l;
249*2139Sjp161948 			if (++dl >= 0) break;
250*2139Sjp161948 
251*2139Sjp161948 			save_dl = dl;
252*2139Sjp161948 			b+=4;
253*2139Sjp161948 			r+=4;
254*2139Sjp161948 			}
255*2139Sjp161948 		if (dl < 0)
256*2139Sjp161948 			{
257*2139Sjp161948 #ifdef BN_COUNT
258*2139Sjp161948 			fprintf(stderr, "  bn_add_part_words %d + %d (dl < 0, c == 0)\n", cl, dl);
259*2139Sjp161948 #endif
260*2139Sjp161948 			if (save_dl < dl)
261*2139Sjp161948 				{
262*2139Sjp161948 				switch (dl - save_dl)
263*2139Sjp161948 					{
264*2139Sjp161948 				case 1:
265*2139Sjp161948 					r[1] = b[1];
266*2139Sjp161948 					if (++dl >= 0) break;
267*2139Sjp161948 				case 2:
268*2139Sjp161948 					r[2] = b[2];
269*2139Sjp161948 					if (++dl >= 0) break;
270*2139Sjp161948 				case 3:
271*2139Sjp161948 					r[3] = b[3];
272*2139Sjp161948 					if (++dl >= 0) break;
273*2139Sjp161948 					}
274*2139Sjp161948 				b += 4;
275*2139Sjp161948 				r += 4;
276*2139Sjp161948 				}
277*2139Sjp161948 			}
278*2139Sjp161948 		if (dl < 0)
279*2139Sjp161948 			{
280*2139Sjp161948 #ifdef BN_COUNT
281*2139Sjp161948 			fprintf(stderr, "  bn_add_part_words %d + %d (dl < 0, copy)\n", cl, dl);
282*2139Sjp161948 #endif
283*2139Sjp161948 			for(;;)
284*2139Sjp161948 				{
285*2139Sjp161948 				r[0] = b[0];
286*2139Sjp161948 				if (++dl >= 0) break;
287*2139Sjp161948 				r[1] = b[1];
288*2139Sjp161948 				if (++dl >= 0) break;
289*2139Sjp161948 				r[2] = b[2];
290*2139Sjp161948 				if (++dl >= 0) break;
291*2139Sjp161948 				r[3] = b[3];
292*2139Sjp161948 				if (++dl >= 0) break;
293*2139Sjp161948 
294*2139Sjp161948 				b += 4;
295*2139Sjp161948 				r += 4;
296*2139Sjp161948 				}
297*2139Sjp161948 			}
298*2139Sjp161948 		}
299*2139Sjp161948 	else
300*2139Sjp161948 		{
301*2139Sjp161948 		int save_dl = dl;
302*2139Sjp161948 #ifdef BN_COUNT
303*2139Sjp161948 		fprintf(stderr, "  bn_add_part_words %d + %d (dl > 0)\n", cl, dl);
304*2139Sjp161948 #endif
305*2139Sjp161948 		while (c)
306*2139Sjp161948 			{
307*2139Sjp161948 			t=(a[0]+c)&BN_MASK2;
308*2139Sjp161948 			c=(t < c);
309*2139Sjp161948 			r[0]=t;
310*2139Sjp161948 			if (--dl <= 0) break;
311*2139Sjp161948 
312*2139Sjp161948 			t=(a[1]+c)&BN_MASK2;
313*2139Sjp161948 			c=(t < c);
314*2139Sjp161948 			r[1]=t;
315*2139Sjp161948 			if (--dl <= 0) break;
316*2139Sjp161948 
317*2139Sjp161948 			t=(a[2]+c)&BN_MASK2;
318*2139Sjp161948 			c=(t < c);
319*2139Sjp161948 			r[2]=t;
320*2139Sjp161948 			if (--dl <= 0) break;
321*2139Sjp161948 
322*2139Sjp161948 			t=(a[3]+c)&BN_MASK2;
323*2139Sjp161948 			c=(t < c);
324*2139Sjp161948 			r[3]=t;
325*2139Sjp161948 			if (--dl <= 0) break;
326*2139Sjp161948 
327*2139Sjp161948 			save_dl = dl;
328*2139Sjp161948 			a+=4;
329*2139Sjp161948 			r+=4;
330*2139Sjp161948 			}
331*2139Sjp161948 #ifdef BN_COUNT
332*2139Sjp161948 		fprintf(stderr, "  bn_add_part_words %d + %d (dl > 0, c == 0)\n", cl, dl);
333*2139Sjp161948 #endif
334*2139Sjp161948 		if (dl > 0)
335*2139Sjp161948 			{
336*2139Sjp161948 			if (save_dl > dl)
337*2139Sjp161948 				{
338*2139Sjp161948 				switch (save_dl - dl)
339*2139Sjp161948 					{
340*2139Sjp161948 				case 1:
341*2139Sjp161948 					r[1] = a[1];
342*2139Sjp161948 					if (--dl <= 0) break;
343*2139Sjp161948 				case 2:
344*2139Sjp161948 					r[2] = a[2];
345*2139Sjp161948 					if (--dl <= 0) break;
346*2139Sjp161948 				case 3:
347*2139Sjp161948 					r[3] = a[3];
348*2139Sjp161948 					if (--dl <= 0) break;
349*2139Sjp161948 					}
350*2139Sjp161948 				a += 4;
351*2139Sjp161948 				r += 4;
352*2139Sjp161948 				}
353*2139Sjp161948 			}
354*2139Sjp161948 		if (dl > 0)
355*2139Sjp161948 			{
356*2139Sjp161948 #ifdef BN_COUNT
357*2139Sjp161948 			fprintf(stderr, "  bn_add_part_words %d + %d (dl > 0, copy)\n", cl, dl);
358*2139Sjp161948 #endif
359*2139Sjp161948 			for(;;)
360*2139Sjp161948 				{
361*2139Sjp161948 				r[0] = a[0];
362*2139Sjp161948 				if (--dl <= 0) break;
363*2139Sjp161948 				r[1] = a[1];
364*2139Sjp161948 				if (--dl <= 0) break;
365*2139Sjp161948 				r[2] = a[2];
366*2139Sjp161948 				if (--dl <= 0) break;
367*2139Sjp161948 				r[3] = a[3];
368*2139Sjp161948 				if (--dl <= 0) break;
369*2139Sjp161948 
370*2139Sjp161948 				a += 4;
371*2139Sjp161948 				r += 4;
372*2139Sjp161948 				}
373*2139Sjp161948 			}
374*2139Sjp161948 		}
375*2139Sjp161948 	return c;
376*2139Sjp161948 	}
377*2139Sjp161948 
3780Sstevel@tonic-gate #ifdef BN_RECURSION
3790Sstevel@tonic-gate /* Karatsuba recursive multiplication algorithm
3800Sstevel@tonic-gate  * (cf. Knuth, The Art of Computer Programming, Vol. 2) */
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate /* r is 2*n2 words in size,
3830Sstevel@tonic-gate  * a and b are both n2 words in size.
3840Sstevel@tonic-gate  * n2 must be a power of 2.
3850Sstevel@tonic-gate  * We multiply and return the result.
3860Sstevel@tonic-gate  * t must be 2*n2 words in size
3870Sstevel@tonic-gate  * We calculate
3880Sstevel@tonic-gate  * a[0]*b[0]
3890Sstevel@tonic-gate  * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
3900Sstevel@tonic-gate  * a[1]*b[1]
3910Sstevel@tonic-gate  */
bn_mul_recursive(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,int n2,int dna,int dnb,BN_ULONG * t)3920Sstevel@tonic-gate void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
393*2139Sjp161948 	int dna, int dnb, BN_ULONG *t)
3940Sstevel@tonic-gate 	{
3950Sstevel@tonic-gate 	int n=n2/2,c1,c2;
396*2139Sjp161948 	int tna=n+dna, tnb=n+dnb;
3970Sstevel@tonic-gate 	unsigned int neg,zero;
3980Sstevel@tonic-gate 	BN_ULONG ln,lo,*p;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate # ifdef BN_COUNT
401*2139Sjp161948 	fprintf(stderr," bn_mul_recursive %d * %d\n",n2,n2);
4020Sstevel@tonic-gate # endif
4030Sstevel@tonic-gate # ifdef BN_MUL_COMBA
4040Sstevel@tonic-gate #  if 0
4050Sstevel@tonic-gate 	if (n2 == 4)
4060Sstevel@tonic-gate 		{
4070Sstevel@tonic-gate 		bn_mul_comba4(r,a,b);
4080Sstevel@tonic-gate 		return;
4090Sstevel@tonic-gate 		}
4100Sstevel@tonic-gate #  endif
411*2139Sjp161948 	/* Only call bn_mul_comba 8 if n2 == 8 and the
412*2139Sjp161948 	 * two arrays are complete [steve]
413*2139Sjp161948 	 */
414*2139Sjp161948 	if (n2 == 8 && dna == 0 && dnb == 0)
4150Sstevel@tonic-gate 		{
4160Sstevel@tonic-gate 		bn_mul_comba8(r,a,b);
4170Sstevel@tonic-gate 		return;
4180Sstevel@tonic-gate 		}
4190Sstevel@tonic-gate # endif /* BN_MUL_COMBA */
420*2139Sjp161948 	/* Else do normal multiply */
4210Sstevel@tonic-gate 	if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL)
4220Sstevel@tonic-gate 		{
423*2139Sjp161948 		bn_mul_normal(r,a,n2+dna,b,n2+dnb);
424*2139Sjp161948 		if ((dna + dnb) < 0)
425*2139Sjp161948 			memset(&r[2*n2 + dna + dnb], 0,
426*2139Sjp161948 				sizeof(BN_ULONG) * -(dna + dnb));
4270Sstevel@tonic-gate 		return;
4280Sstevel@tonic-gate 		}
4290Sstevel@tonic-gate 	/* r=(a[0]-a[1])*(b[1]-b[0]) */
430*2139Sjp161948 	c1=bn_cmp_part_words(a,&(a[n]),tna,n-tna);
431*2139Sjp161948 	c2=bn_cmp_part_words(&(b[n]),b,tnb,tnb-n);
4320Sstevel@tonic-gate 	zero=neg=0;
4330Sstevel@tonic-gate 	switch (c1*3+c2)
4340Sstevel@tonic-gate 		{
4350Sstevel@tonic-gate 	case -4:
436*2139Sjp161948 		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */
437*2139Sjp161948 		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */
4380Sstevel@tonic-gate 		break;
4390Sstevel@tonic-gate 	case -3:
4400Sstevel@tonic-gate 		zero=1;
4410Sstevel@tonic-gate 		break;
4420Sstevel@tonic-gate 	case -2:
443*2139Sjp161948 		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */
444*2139Sjp161948 		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n); /* + */
4450Sstevel@tonic-gate 		neg=1;
4460Sstevel@tonic-gate 		break;
4470Sstevel@tonic-gate 	case -1:
4480Sstevel@tonic-gate 	case 0:
4490Sstevel@tonic-gate 	case 1:
4500Sstevel@tonic-gate 		zero=1;
4510Sstevel@tonic-gate 		break;
4520Sstevel@tonic-gate 	case 2:
453*2139Sjp161948 		bn_sub_part_words(t,      a,      &(a[n]),tna,n-tna); /* + */
454*2139Sjp161948 		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */
4550Sstevel@tonic-gate 		neg=1;
4560Sstevel@tonic-gate 		break;
4570Sstevel@tonic-gate 	case 3:
4580Sstevel@tonic-gate 		zero=1;
4590Sstevel@tonic-gate 		break;
4600Sstevel@tonic-gate 	case 4:
461*2139Sjp161948 		bn_sub_part_words(t,      a,      &(a[n]),tna,n-tna);
462*2139Sjp161948 		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n);
4630Sstevel@tonic-gate 		break;
4640Sstevel@tonic-gate 		}
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate # ifdef BN_MUL_COMBA
467*2139Sjp161948 	if (n == 4 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba4 could take
468*2139Sjp161948 					       extra args to do this well */
4690Sstevel@tonic-gate 		{
4700Sstevel@tonic-gate 		if (!zero)
4710Sstevel@tonic-gate 			bn_mul_comba4(&(t[n2]),t,&(t[n]));
4720Sstevel@tonic-gate 		else
4730Sstevel@tonic-gate 			memset(&(t[n2]),0,8*sizeof(BN_ULONG));
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 		bn_mul_comba4(r,a,b);
4760Sstevel@tonic-gate 		bn_mul_comba4(&(r[n2]),&(a[n]),&(b[n]));
4770Sstevel@tonic-gate 		}
478*2139Sjp161948 	else if (n == 8 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba8 could
479*2139Sjp161948 						    take extra args to do this
480*2139Sjp161948 						    well */
4810Sstevel@tonic-gate 		{
4820Sstevel@tonic-gate 		if (!zero)
4830Sstevel@tonic-gate 			bn_mul_comba8(&(t[n2]),t,&(t[n]));
4840Sstevel@tonic-gate 		else
4850Sstevel@tonic-gate 			memset(&(t[n2]),0,16*sizeof(BN_ULONG));
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 		bn_mul_comba8(r,a,b);
4880Sstevel@tonic-gate 		bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n]));
4890Sstevel@tonic-gate 		}
4900Sstevel@tonic-gate 	else
4910Sstevel@tonic-gate # endif /* BN_MUL_COMBA */
4920Sstevel@tonic-gate 		{
4930Sstevel@tonic-gate 		p= &(t[n2*2]);
4940Sstevel@tonic-gate 		if (!zero)
495*2139Sjp161948 			bn_mul_recursive(&(t[n2]),t,&(t[n]),n,0,0,p);
4960Sstevel@tonic-gate 		else
4970Sstevel@tonic-gate 			memset(&(t[n2]),0,n2*sizeof(BN_ULONG));
498*2139Sjp161948 		bn_mul_recursive(r,a,b,n,0,0,p);
499*2139Sjp161948 		bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,dna,dnb,p);
5000Sstevel@tonic-gate 		}
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
5030Sstevel@tonic-gate 	 * r[10] holds (a[0]*b[0])
5040Sstevel@tonic-gate 	 * r[32] holds (b[1]*b[1])
5050Sstevel@tonic-gate 	 */
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 	c1=(int)(bn_add_words(t,r,&(r[n2]),n2));
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	if (neg) /* if t[32] is negative */
5100Sstevel@tonic-gate 		{
5110Sstevel@tonic-gate 		c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
5120Sstevel@tonic-gate 		}
5130Sstevel@tonic-gate 	else
5140Sstevel@tonic-gate 		{
5150Sstevel@tonic-gate 		/* Might have a carry */
5160Sstevel@tonic-gate 		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));
5170Sstevel@tonic-gate 		}
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
5200Sstevel@tonic-gate 	 * r[10] holds (a[0]*b[0])
5210Sstevel@tonic-gate 	 * r[32] holds (b[1]*b[1])
5220Sstevel@tonic-gate 	 * c1 holds the carry bits
5230Sstevel@tonic-gate 	 */
5240Sstevel@tonic-gate 	c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
5250Sstevel@tonic-gate 	if (c1)
5260Sstevel@tonic-gate 		{
5270Sstevel@tonic-gate 		p= &(r[n+n2]);
5280Sstevel@tonic-gate 		lo= *p;
5290Sstevel@tonic-gate 		ln=(lo+c1)&BN_MASK2;
5300Sstevel@tonic-gate 		*p=ln;
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 		/* The overflow will stop before we over write
5330Sstevel@tonic-gate 		 * words we should not overwrite */
5340Sstevel@tonic-gate 		if (ln < (BN_ULONG)c1)
5350Sstevel@tonic-gate 			{
5360Sstevel@tonic-gate 			do	{
5370Sstevel@tonic-gate 				p++;
5380Sstevel@tonic-gate 				lo= *p;
5390Sstevel@tonic-gate 				ln=(lo+1)&BN_MASK2;
5400Sstevel@tonic-gate 				*p=ln;
5410Sstevel@tonic-gate 				} while (ln == 0);
5420Sstevel@tonic-gate 			}
5430Sstevel@tonic-gate 		}
5440Sstevel@tonic-gate 	}
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate /* n+tn is the word length
5470Sstevel@tonic-gate  * t needs to be n*4 is size, as does r */
bn_mul_part_recursive(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,int n,int tna,int tnb,BN_ULONG * t)548*2139Sjp161948 void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
549*2139Sjp161948 	     int tna, int tnb, BN_ULONG *t)
5500Sstevel@tonic-gate 	{
5510Sstevel@tonic-gate 	int i,j,n2=n*2;
5520Sstevel@tonic-gate 	int c1,c2,neg,zero;
5530Sstevel@tonic-gate 	BN_ULONG ln,lo,*p;
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate # ifdef BN_COUNT
556*2139Sjp161948 	fprintf(stderr," bn_mul_part_recursive (%d+%d) * (%d+%d)\n",
557*2139Sjp161948 		tna, n, tnb, n);
5580Sstevel@tonic-gate # endif
5590Sstevel@tonic-gate 	if (n < 8)
5600Sstevel@tonic-gate 		{
561*2139Sjp161948 		bn_mul_normal(r,a,n+tna,b,n+tnb);
5620Sstevel@tonic-gate 		return;
5630Sstevel@tonic-gate 		}
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	/* r=(a[0]-a[1])*(b[1]-b[0]) */
566*2139Sjp161948 	c1=bn_cmp_part_words(a,&(a[n]),tna,n-tna);
567*2139Sjp161948 	c2=bn_cmp_part_words(&(b[n]),b,tnb,tnb-n);
5680Sstevel@tonic-gate 	zero=neg=0;
5690Sstevel@tonic-gate 	switch (c1*3+c2)
5700Sstevel@tonic-gate 		{
5710Sstevel@tonic-gate 	case -4:
572*2139Sjp161948 		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */
573*2139Sjp161948 		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */
5740Sstevel@tonic-gate 		break;
5750Sstevel@tonic-gate 	case -3:
5760Sstevel@tonic-gate 		zero=1;
5770Sstevel@tonic-gate 		/* break; */
5780Sstevel@tonic-gate 	case -2:
579*2139Sjp161948 		bn_sub_part_words(t,      &(a[n]),a,      tna,tna-n); /* - */
580*2139Sjp161948 		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n); /* + */
5810Sstevel@tonic-gate 		neg=1;
5820Sstevel@tonic-gate 		break;
5830Sstevel@tonic-gate 	case -1:
5840Sstevel@tonic-gate 	case 0:
5850Sstevel@tonic-gate 	case 1:
5860Sstevel@tonic-gate 		zero=1;
5870Sstevel@tonic-gate 		/* break; */
5880Sstevel@tonic-gate 	case 2:
589*2139Sjp161948 		bn_sub_part_words(t,      a,      &(a[n]),tna,n-tna); /* + */
590*2139Sjp161948 		bn_sub_part_words(&(t[n]),b,      &(b[n]),tnb,n-tnb); /* - */
5910Sstevel@tonic-gate 		neg=1;
5920Sstevel@tonic-gate 		break;
5930Sstevel@tonic-gate 	case 3:
5940Sstevel@tonic-gate 		zero=1;
5950Sstevel@tonic-gate 		/* break; */
5960Sstevel@tonic-gate 	case 4:
597*2139Sjp161948 		bn_sub_part_words(t,      a,      &(a[n]),tna,n-tna);
598*2139Sjp161948 		bn_sub_part_words(&(t[n]),&(b[n]),b,      tnb,tnb-n);
5990Sstevel@tonic-gate 		break;
6000Sstevel@tonic-gate 		}
6010Sstevel@tonic-gate 		/* The zero case isn't yet implemented here. The speedup
6020Sstevel@tonic-gate 		   would probably be negligible. */
6030Sstevel@tonic-gate # if 0
6040Sstevel@tonic-gate 	if (n == 4)
6050Sstevel@tonic-gate 		{
6060Sstevel@tonic-gate 		bn_mul_comba4(&(t[n2]),t,&(t[n]));
6070Sstevel@tonic-gate 		bn_mul_comba4(r,a,b);
6080Sstevel@tonic-gate 		bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
6090Sstevel@tonic-gate 		memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
6100Sstevel@tonic-gate 		}
6110Sstevel@tonic-gate 	else
6120Sstevel@tonic-gate # endif
6130Sstevel@tonic-gate 	if (n == 8)
6140Sstevel@tonic-gate 		{
6150Sstevel@tonic-gate 		bn_mul_comba8(&(t[n2]),t,&(t[n]));
6160Sstevel@tonic-gate 		bn_mul_comba8(r,a,b);
617*2139Sjp161948 		bn_mul_normal(&(r[n2]),&(a[n]),tna,&(b[n]),tnb);
618*2139Sjp161948 		memset(&(r[n2+tna+tnb]),0,sizeof(BN_ULONG)*(n2-tna-tnb));
6190Sstevel@tonic-gate 		}
6200Sstevel@tonic-gate 	else
6210Sstevel@tonic-gate 		{
6220Sstevel@tonic-gate 		p= &(t[n2*2]);
623*2139Sjp161948 		bn_mul_recursive(&(t[n2]),t,&(t[n]),n,0,0,p);
624*2139Sjp161948 		bn_mul_recursive(r,a,b,n,0,0,p);
6250Sstevel@tonic-gate 		i=n/2;
6260Sstevel@tonic-gate 		/* If there is only a bottom half to the number,
6270Sstevel@tonic-gate 		 * just do it */
628*2139Sjp161948 		if (tna > tnb)
629*2139Sjp161948 			j = tna - i;
630*2139Sjp161948 		else
631*2139Sjp161948 			j = tnb - i;
6320Sstevel@tonic-gate 		if (j == 0)
6330Sstevel@tonic-gate 			{
634*2139Sjp161948 			bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),
635*2139Sjp161948 				i,tna-i,tnb-i,p);
6360Sstevel@tonic-gate 			memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2));
6370Sstevel@tonic-gate 			}
6380Sstevel@tonic-gate 		else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */
6390Sstevel@tonic-gate 				{
6400Sstevel@tonic-gate 				bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]),
641*2139Sjp161948 					i,tna-i,tnb-i,p);
642*2139Sjp161948 				memset(&(r[n2+tna+tnb]),0,
643*2139Sjp161948 					sizeof(BN_ULONG)*(n2-tna-tnb));
6440Sstevel@tonic-gate 				}
6450Sstevel@tonic-gate 		else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
6460Sstevel@tonic-gate 			{
6470Sstevel@tonic-gate 			memset(&(r[n2]),0,sizeof(BN_ULONG)*n2);
648*2139Sjp161948 			if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL
649*2139Sjp161948 				&& tnb < BN_MUL_RECURSIVE_SIZE_NORMAL)
6500Sstevel@tonic-gate 				{
651*2139Sjp161948 				bn_mul_normal(&(r[n2]),&(a[n]),tna,&(b[n]),tnb);
6520Sstevel@tonic-gate 				}
6530Sstevel@tonic-gate 			else
6540Sstevel@tonic-gate 				{
6550Sstevel@tonic-gate 				for (;;)
6560Sstevel@tonic-gate 					{
6570Sstevel@tonic-gate 					i/=2;
658*2139Sjp161948 					if (i < tna && i < tnb)
6590Sstevel@tonic-gate 						{
6600Sstevel@tonic-gate 						bn_mul_part_recursive(&(r[n2]),
6610Sstevel@tonic-gate 							&(a[n]),&(b[n]),
662*2139Sjp161948 							i,tna-i,tnb-i,p);
6630Sstevel@tonic-gate 						break;
6640Sstevel@tonic-gate 						}
665*2139Sjp161948 					else if (i <= tna && i <= tnb)
6660Sstevel@tonic-gate 						{
6670Sstevel@tonic-gate 						bn_mul_recursive(&(r[n2]),
6680Sstevel@tonic-gate 							&(a[n]),&(b[n]),
669*2139Sjp161948 							i,tna-i,tnb-i,p);
6700Sstevel@tonic-gate 						break;
6710Sstevel@tonic-gate 						}
6720Sstevel@tonic-gate 					}
6730Sstevel@tonic-gate 				}
6740Sstevel@tonic-gate 			}
6750Sstevel@tonic-gate 		}
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
6780Sstevel@tonic-gate 	 * r[10] holds (a[0]*b[0])
6790Sstevel@tonic-gate 	 * r[32] holds (b[1]*b[1])
6800Sstevel@tonic-gate 	 */
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	c1=(int)(bn_add_words(t,r,&(r[n2]),n2));
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate 	if (neg) /* if t[32] is negative */
6850Sstevel@tonic-gate 		{
6860Sstevel@tonic-gate 		c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
6870Sstevel@tonic-gate 		}
6880Sstevel@tonic-gate 	else
6890Sstevel@tonic-gate 		{
6900Sstevel@tonic-gate 		/* Might have a carry */
6910Sstevel@tonic-gate 		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));
6920Sstevel@tonic-gate 		}
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
6950Sstevel@tonic-gate 	 * r[10] holds (a[0]*b[0])
6960Sstevel@tonic-gate 	 * r[32] holds (b[1]*b[1])
6970Sstevel@tonic-gate 	 * c1 holds the carry bits
6980Sstevel@tonic-gate 	 */
6990Sstevel@tonic-gate 	c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
7000Sstevel@tonic-gate 	if (c1)
7010Sstevel@tonic-gate 		{
7020Sstevel@tonic-gate 		p= &(r[n+n2]);
7030Sstevel@tonic-gate 		lo= *p;
7040Sstevel@tonic-gate 		ln=(lo+c1)&BN_MASK2;
7050Sstevel@tonic-gate 		*p=ln;
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 		/* The overflow will stop before we over write
7080Sstevel@tonic-gate 		 * words we should not overwrite */
7090Sstevel@tonic-gate 		if (ln < (BN_ULONG)c1)
7100Sstevel@tonic-gate 			{
7110Sstevel@tonic-gate 			do	{
7120Sstevel@tonic-gate 				p++;
7130Sstevel@tonic-gate 				lo= *p;
7140Sstevel@tonic-gate 				ln=(lo+1)&BN_MASK2;
7150Sstevel@tonic-gate 				*p=ln;
7160Sstevel@tonic-gate 				} while (ln == 0);
7170Sstevel@tonic-gate 			}
7180Sstevel@tonic-gate 		}
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate /* a and b must be the same size, which is n2.
7220Sstevel@tonic-gate  * r needs to be n2 words and t needs to be n2*2
7230Sstevel@tonic-gate  */
bn_mul_low_recursive(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,int n2,BN_ULONG * t)7240Sstevel@tonic-gate void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
7250Sstevel@tonic-gate 	     BN_ULONG *t)
7260Sstevel@tonic-gate 	{
7270Sstevel@tonic-gate 	int n=n2/2;
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate # ifdef BN_COUNT
730*2139Sjp161948 	fprintf(stderr," bn_mul_low_recursive %d * %d\n",n2,n2);
7310Sstevel@tonic-gate # endif
7320Sstevel@tonic-gate 
733*2139Sjp161948 	bn_mul_recursive(r,a,b,n,0,0,&(t[0]));
7340Sstevel@tonic-gate 	if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL)
7350Sstevel@tonic-gate 		{
7360Sstevel@tonic-gate 		bn_mul_low_recursive(&(t[0]),&(a[0]),&(b[n]),n,&(t[n2]));
7370Sstevel@tonic-gate 		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
7380Sstevel@tonic-gate 		bn_mul_low_recursive(&(t[0]),&(a[n]),&(b[0]),n,&(t[n2]));
7390Sstevel@tonic-gate 		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
7400Sstevel@tonic-gate 		}
7410Sstevel@tonic-gate 	else
7420Sstevel@tonic-gate 		{
7430Sstevel@tonic-gate 		bn_mul_low_normal(&(t[0]),&(a[0]),&(b[n]),n);
7440Sstevel@tonic-gate 		bn_mul_low_normal(&(t[n]),&(a[n]),&(b[0]),n);
7450Sstevel@tonic-gate 		bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
7460Sstevel@tonic-gate 		bn_add_words(&(r[n]),&(r[n]),&(t[n]),n);
7470Sstevel@tonic-gate 		}
7480Sstevel@tonic-gate 	}
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate /* a and b must be the same size, which is n2.
7510Sstevel@tonic-gate  * r needs to be n2 words and t needs to be n2*2
7520Sstevel@tonic-gate  * l is the low words of the output.
7530Sstevel@tonic-gate  * t needs to be n2*3
7540Sstevel@tonic-gate  */
bn_mul_high(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,BN_ULONG * l,int n2,BN_ULONG * t)7550Sstevel@tonic-gate void bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2,
7560Sstevel@tonic-gate 	     BN_ULONG *t)
7570Sstevel@tonic-gate 	{
7580Sstevel@tonic-gate 	int i,n;
7590Sstevel@tonic-gate 	int c1,c2;
7600Sstevel@tonic-gate 	int neg,oneg,zero;
7610Sstevel@tonic-gate 	BN_ULONG ll,lc,*lp,*mp;
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate # ifdef BN_COUNT
764*2139Sjp161948 	fprintf(stderr," bn_mul_high %d * %d\n",n2,n2);
7650Sstevel@tonic-gate # endif
7660Sstevel@tonic-gate 	n=n2/2;
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 	/* Calculate (al-ah)*(bh-bl) */
7690Sstevel@tonic-gate 	neg=zero=0;
7700Sstevel@tonic-gate 	c1=bn_cmp_words(&(a[0]),&(a[n]),n);
7710Sstevel@tonic-gate 	c2=bn_cmp_words(&(b[n]),&(b[0]),n);
7720Sstevel@tonic-gate 	switch (c1*3+c2)
7730Sstevel@tonic-gate 		{
7740Sstevel@tonic-gate 	case -4:
7750Sstevel@tonic-gate 		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
7760Sstevel@tonic-gate 		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
7770Sstevel@tonic-gate 		break;
7780Sstevel@tonic-gate 	case -3:
7790Sstevel@tonic-gate 		zero=1;
7800Sstevel@tonic-gate 		break;
7810Sstevel@tonic-gate 	case -2:
7820Sstevel@tonic-gate 		bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
7830Sstevel@tonic-gate 		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
7840Sstevel@tonic-gate 		neg=1;
7850Sstevel@tonic-gate 		break;
7860Sstevel@tonic-gate 	case -1:
7870Sstevel@tonic-gate 	case 0:
7880Sstevel@tonic-gate 	case 1:
7890Sstevel@tonic-gate 		zero=1;
7900Sstevel@tonic-gate 		break;
7910Sstevel@tonic-gate 	case 2:
7920Sstevel@tonic-gate 		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
7930Sstevel@tonic-gate 		bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
7940Sstevel@tonic-gate 		neg=1;
7950Sstevel@tonic-gate 		break;
7960Sstevel@tonic-gate 	case 3:
7970Sstevel@tonic-gate 		zero=1;
7980Sstevel@tonic-gate 		break;
7990Sstevel@tonic-gate 	case 4:
8000Sstevel@tonic-gate 		bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
8010Sstevel@tonic-gate 		bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
8020Sstevel@tonic-gate 		break;
8030Sstevel@tonic-gate 		}
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 	oneg=neg;
8060Sstevel@tonic-gate 	/* t[10] = (a[0]-a[1])*(b[1]-b[0]) */
8070Sstevel@tonic-gate 	/* r[10] = (a[1]*b[1]) */
8080Sstevel@tonic-gate # ifdef BN_MUL_COMBA
8090Sstevel@tonic-gate 	if (n == 8)
8100Sstevel@tonic-gate 		{
8110Sstevel@tonic-gate 		bn_mul_comba8(&(t[0]),&(r[0]),&(r[n]));
8120Sstevel@tonic-gate 		bn_mul_comba8(r,&(a[n]),&(b[n]));
8130Sstevel@tonic-gate 		}
8140Sstevel@tonic-gate 	else
8150Sstevel@tonic-gate # endif
8160Sstevel@tonic-gate 		{
817*2139Sjp161948 		bn_mul_recursive(&(t[0]),&(r[0]),&(r[n]),n,0,0,&(t[n2]));
818*2139Sjp161948 		bn_mul_recursive(r,&(a[n]),&(b[n]),n,0,0,&(t[n2]));
8190Sstevel@tonic-gate 		}
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 	/* s0 == low(al*bl)
8220Sstevel@tonic-gate 	 * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
8230Sstevel@tonic-gate 	 * We know s0 and s1 so the only unknown is high(al*bl)
8240Sstevel@tonic-gate 	 * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl))
8250Sstevel@tonic-gate 	 * high(al*bl) == s1 - (r[0]+l[0]+t[0])
8260Sstevel@tonic-gate 	 */
8270Sstevel@tonic-gate 	if (l != NULL)
8280Sstevel@tonic-gate 		{
8290Sstevel@tonic-gate 		lp= &(t[n2+n]);
8300Sstevel@tonic-gate 		c1=(int)(bn_add_words(lp,&(r[0]),&(l[0]),n));
8310Sstevel@tonic-gate 		}
8320Sstevel@tonic-gate 	else
8330Sstevel@tonic-gate 		{
8340Sstevel@tonic-gate 		c1=0;
8350Sstevel@tonic-gate 		lp= &(r[0]);
8360Sstevel@tonic-gate 		}
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate 	if (neg)
8390Sstevel@tonic-gate 		neg=(int)(bn_sub_words(&(t[n2]),lp,&(t[0]),n));
8400Sstevel@tonic-gate 	else
8410Sstevel@tonic-gate 		{
8420Sstevel@tonic-gate 		bn_add_words(&(t[n2]),lp,&(t[0]),n);
8430Sstevel@tonic-gate 		neg=0;
8440Sstevel@tonic-gate 		}
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	if (l != NULL)
8470Sstevel@tonic-gate 		{
8480Sstevel@tonic-gate 		bn_sub_words(&(t[n2+n]),&(l[n]),&(t[n2]),n);
8490Sstevel@tonic-gate 		}
8500Sstevel@tonic-gate 	else
8510Sstevel@tonic-gate 		{
8520Sstevel@tonic-gate 		lp= &(t[n2+n]);
8530Sstevel@tonic-gate 		mp= &(t[n2]);
8540Sstevel@tonic-gate 		for (i=0; i<n; i++)
8550Sstevel@tonic-gate 			lp[i]=((~mp[i])+1)&BN_MASK2;
8560Sstevel@tonic-gate 		}
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate 	/* s[0] = low(al*bl)
8590Sstevel@tonic-gate 	 * t[3] = high(al*bl)
8600Sstevel@tonic-gate 	 * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign
8610Sstevel@tonic-gate 	 * r[10] = (a[1]*b[1])
8620Sstevel@tonic-gate 	 */
8630Sstevel@tonic-gate 	/* R[10] = al*bl
8640Sstevel@tonic-gate 	 * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0])
8650Sstevel@tonic-gate 	 * R[32] = ah*bh
8660Sstevel@tonic-gate 	 */
8670Sstevel@tonic-gate 	/* R[1]=t[3]+l[0]+r[0](+-)t[0] (have carry/borrow)
8680Sstevel@tonic-gate 	 * R[2]=r[0]+t[3]+r[1](+-)t[1] (have carry/borrow)
8690Sstevel@tonic-gate 	 * R[3]=r[1]+(carry/borrow)
8700Sstevel@tonic-gate 	 */
8710Sstevel@tonic-gate 	if (l != NULL)
8720Sstevel@tonic-gate 		{
8730Sstevel@tonic-gate 		lp= &(t[n2]);
8740Sstevel@tonic-gate 		c1= (int)(bn_add_words(lp,&(t[n2+n]),&(l[0]),n));
8750Sstevel@tonic-gate 		}
8760Sstevel@tonic-gate 	else
8770Sstevel@tonic-gate 		{
8780Sstevel@tonic-gate 		lp= &(t[n2+n]);
8790Sstevel@tonic-gate 		c1=0;
8800Sstevel@tonic-gate 		}
8810Sstevel@tonic-gate 	c1+=(int)(bn_add_words(&(t[n2]),lp,  &(r[0]),n));
8820Sstevel@tonic-gate 	if (oneg)
8830Sstevel@tonic-gate 		c1-=(int)(bn_sub_words(&(t[n2]),&(t[n2]),&(t[0]),n));
8840Sstevel@tonic-gate 	else
8850Sstevel@tonic-gate 		c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),&(t[0]),n));
8860Sstevel@tonic-gate 
8870Sstevel@tonic-gate 	c2 =(int)(bn_add_words(&(r[0]),&(r[0]),&(t[n2+n]),n));
8880Sstevel@tonic-gate 	c2+=(int)(bn_add_words(&(r[0]),&(r[0]),&(r[n]),n));
8890Sstevel@tonic-gate 	if (oneg)
8900Sstevel@tonic-gate 		c2-=(int)(bn_sub_words(&(r[0]),&(r[0]),&(t[n]),n));
8910Sstevel@tonic-gate 	else
8920Sstevel@tonic-gate 		c2+=(int)(bn_add_words(&(r[0]),&(r[0]),&(t[n]),n));
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate 	if (c1 != 0) /* Add starting at r[0], could be +ve or -ve */
8950Sstevel@tonic-gate 		{
8960Sstevel@tonic-gate 		i=0;
8970Sstevel@tonic-gate 		if (c1 > 0)
8980Sstevel@tonic-gate 			{
8990Sstevel@tonic-gate 			lc=c1;
9000Sstevel@tonic-gate 			do	{
9010Sstevel@tonic-gate 				ll=(r[i]+lc)&BN_MASK2;
9020Sstevel@tonic-gate 				r[i++]=ll;
9030Sstevel@tonic-gate 				lc=(lc > ll);
9040Sstevel@tonic-gate 				} while (lc);
9050Sstevel@tonic-gate 			}
9060Sstevel@tonic-gate 		else
9070Sstevel@tonic-gate 			{
9080Sstevel@tonic-gate 			lc= -c1;
9090Sstevel@tonic-gate 			do	{
9100Sstevel@tonic-gate 				ll=r[i];
9110Sstevel@tonic-gate 				r[i++]=(ll-lc)&BN_MASK2;
9120Sstevel@tonic-gate 				lc=(lc > ll);
9130Sstevel@tonic-gate 				} while (lc);
9140Sstevel@tonic-gate 			}
9150Sstevel@tonic-gate 		}
9160Sstevel@tonic-gate 	if (c2 != 0) /* Add starting at r[1] */
9170Sstevel@tonic-gate 		{
9180Sstevel@tonic-gate 		i=n;
9190Sstevel@tonic-gate 		if (c2 > 0)
9200Sstevel@tonic-gate 			{
9210Sstevel@tonic-gate 			lc=c2;
9220Sstevel@tonic-gate 			do	{
9230Sstevel@tonic-gate 				ll=(r[i]+lc)&BN_MASK2;
9240Sstevel@tonic-gate 				r[i++]=ll;
9250Sstevel@tonic-gate 				lc=(lc > ll);
9260Sstevel@tonic-gate 				} while (lc);
9270Sstevel@tonic-gate 			}
9280Sstevel@tonic-gate 		else
9290Sstevel@tonic-gate 			{
9300Sstevel@tonic-gate 			lc= -c2;
9310Sstevel@tonic-gate 			do	{
9320Sstevel@tonic-gate 				ll=r[i];
9330Sstevel@tonic-gate 				r[i++]=(ll-lc)&BN_MASK2;
9340Sstevel@tonic-gate 				lc=(lc > ll);
9350Sstevel@tonic-gate 				} while (lc);
9360Sstevel@tonic-gate 			}
9370Sstevel@tonic-gate 		}
9380Sstevel@tonic-gate 	}
9390Sstevel@tonic-gate #endif /* BN_RECURSION */
9400Sstevel@tonic-gate 
BN_mul(BIGNUM * r,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)9410Sstevel@tonic-gate int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
9420Sstevel@tonic-gate 	{
943*2139Sjp161948 	int ret=0;
9440Sstevel@tonic-gate 	int top,al,bl;
9450Sstevel@tonic-gate 	BIGNUM *rr;
9460Sstevel@tonic-gate #if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
9470Sstevel@tonic-gate 	int i;
9480Sstevel@tonic-gate #endif
9490Sstevel@tonic-gate #ifdef BN_RECURSION
950*2139Sjp161948 	BIGNUM *t=NULL;
951*2139Sjp161948 	int j=0,k;
9520Sstevel@tonic-gate #endif
9530Sstevel@tonic-gate 
9540Sstevel@tonic-gate #ifdef BN_COUNT
955*2139Sjp161948 	fprintf(stderr,"BN_mul %d * %d\n",a->top,b->top);
9560Sstevel@tonic-gate #endif
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate 	bn_check_top(a);
9590Sstevel@tonic-gate 	bn_check_top(b);
9600Sstevel@tonic-gate 	bn_check_top(r);
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate 	al=a->top;
9630Sstevel@tonic-gate 	bl=b->top;
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 	if ((al == 0) || (bl == 0))
9660Sstevel@tonic-gate 		{
967*2139Sjp161948 		BN_zero(r);
9680Sstevel@tonic-gate 		return(1);
9690Sstevel@tonic-gate 		}
9700Sstevel@tonic-gate 	top=al+bl;
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 	BN_CTX_start(ctx);
9730Sstevel@tonic-gate 	if ((r == a) || (r == b))
9740Sstevel@tonic-gate 		{
9750Sstevel@tonic-gate 		if ((rr = BN_CTX_get(ctx)) == NULL) goto err;
9760Sstevel@tonic-gate 		}
9770Sstevel@tonic-gate 	else
9780Sstevel@tonic-gate 		rr = r;
9790Sstevel@tonic-gate 	rr->neg=a->neg^b->neg;
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate #if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
9820Sstevel@tonic-gate 	i = al-bl;
9830Sstevel@tonic-gate #endif
9840Sstevel@tonic-gate #ifdef BN_MUL_COMBA
9850Sstevel@tonic-gate 	if (i == 0)
9860Sstevel@tonic-gate 		{
9870Sstevel@tonic-gate # if 0
9880Sstevel@tonic-gate 		if (al == 4)
9890Sstevel@tonic-gate 			{
9900Sstevel@tonic-gate 			if (bn_wexpand(rr,8) == NULL) goto err;
9910Sstevel@tonic-gate 			rr->top=8;
9920Sstevel@tonic-gate 			bn_mul_comba4(rr->d,a->d,b->d);
9930Sstevel@tonic-gate 			goto end;
9940Sstevel@tonic-gate 			}
9950Sstevel@tonic-gate # endif
9960Sstevel@tonic-gate 		if (al == 8)
9970Sstevel@tonic-gate 			{
9980Sstevel@tonic-gate 			if (bn_wexpand(rr,16) == NULL) goto err;
9990Sstevel@tonic-gate 			rr->top=16;
10000Sstevel@tonic-gate 			bn_mul_comba8(rr->d,a->d,b->d);
10010Sstevel@tonic-gate 			goto end;
10020Sstevel@tonic-gate 			}
10030Sstevel@tonic-gate 		}
10040Sstevel@tonic-gate #endif /* BN_MUL_COMBA */
10050Sstevel@tonic-gate #ifdef BN_RECURSION
10060Sstevel@tonic-gate 	if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL))
10070Sstevel@tonic-gate 		{
1008*2139Sjp161948 		if (i >= -1 && i <= 1)
10090Sstevel@tonic-gate 			{
1010*2139Sjp161948 			int sav_j =0;
1011*2139Sjp161948 			/* Find out the power of two lower or equal
1012*2139Sjp161948 			   to the longest of the two numbers */
1013*2139Sjp161948 			if (i >= 0)
1014*2139Sjp161948 				{
1015*2139Sjp161948 				j = BN_num_bits_word((BN_ULONG)al);
1016*2139Sjp161948 				}
1017*2139Sjp161948 			if (i == -1)
1018*2139Sjp161948 				{
1019*2139Sjp161948 				j = BN_num_bits_word((BN_ULONG)bl);
1020*2139Sjp161948 				}
1021*2139Sjp161948 			sav_j = j;
1022*2139Sjp161948 			j = 1<<(j-1);
1023*2139Sjp161948 			assert(j <= al || j <= bl);
1024*2139Sjp161948 			k = j+j;
1025*2139Sjp161948 			t = BN_CTX_get(ctx);
1026*2139Sjp161948 			if (al > j || bl > j)
1027*2139Sjp161948 				{
1028*2139Sjp161948 				bn_wexpand(t,k*4);
1029*2139Sjp161948 				bn_wexpand(rr,k*4);
1030*2139Sjp161948 				bn_mul_part_recursive(rr->d,a->d,b->d,
1031*2139Sjp161948 					j,al-j,bl-j,t->d);
1032*2139Sjp161948 				}
1033*2139Sjp161948 			else	/* al <= j || bl <= j */
1034*2139Sjp161948 				{
1035*2139Sjp161948 				bn_wexpand(t,k*2);
1036*2139Sjp161948 				bn_wexpand(rr,k*2);
1037*2139Sjp161948 				bn_mul_recursive(rr->d,a->d,b->d,
1038*2139Sjp161948 					j,al-j,bl-j,t->d);
1039*2139Sjp161948 				}
1040*2139Sjp161948 			rr->top=top;
1041*2139Sjp161948 			goto end;
1042*2139Sjp161948 			}
1043*2139Sjp161948 #if 0
1044*2139Sjp161948 		if (i == 1 && !BN_get_flags(b,BN_FLG_STATIC_DATA))
1045*2139Sjp161948 			{
1046*2139Sjp161948 			BIGNUM *tmp_bn = (BIGNUM *)b;
1047*2139Sjp161948 			if (bn_wexpand(tmp_bn,al) == NULL) goto err;
1048*2139Sjp161948 			tmp_bn->d[bl]=0;
10490Sstevel@tonic-gate 			bl++;
10500Sstevel@tonic-gate 			i--;
10510Sstevel@tonic-gate 			}
1052*2139Sjp161948 		else if (i == -1 && !BN_get_flags(a,BN_FLG_STATIC_DATA))
10530Sstevel@tonic-gate 			{
1054*2139Sjp161948 			BIGNUM *tmp_bn = (BIGNUM *)a;
1055*2139Sjp161948 			if (bn_wexpand(tmp_bn,bl) == NULL) goto err;
1056*2139Sjp161948 			tmp_bn->d[al]=0;
10570Sstevel@tonic-gate 			al++;
10580Sstevel@tonic-gate 			i++;
10590Sstevel@tonic-gate 			}
10600Sstevel@tonic-gate 		if (i == 0)
10610Sstevel@tonic-gate 			{
10620Sstevel@tonic-gate 			/* symmetric and > 4 */
10630Sstevel@tonic-gate 			/* 16 or larger */
10640Sstevel@tonic-gate 			j=BN_num_bits_word((BN_ULONG)al);
10650Sstevel@tonic-gate 			j=1<<(j-1);
10660Sstevel@tonic-gate 			k=j+j;
10670Sstevel@tonic-gate 			t = BN_CTX_get(ctx);
10680Sstevel@tonic-gate 			if (al == j) /* exact multiple */
10690Sstevel@tonic-gate 				{
10700Sstevel@tonic-gate 				if (bn_wexpand(t,k*2) == NULL) goto err;
10710Sstevel@tonic-gate 				if (bn_wexpand(rr,k*2) == NULL) goto err;
10720Sstevel@tonic-gate 				bn_mul_recursive(rr->d,a->d,b->d,al,t->d);
10730Sstevel@tonic-gate 				}
10740Sstevel@tonic-gate 			else
10750Sstevel@tonic-gate 				{
1076*2139Sjp161948 				if (bn_wexpand(t,k*4) == NULL) goto err;
1077*2139Sjp161948 				if (bn_wexpand(rr,k*4) == NULL) goto err;
10780Sstevel@tonic-gate 				bn_mul_part_recursive(rr->d,a->d,b->d,al-j,j,t->d);
10790Sstevel@tonic-gate 				}
10800Sstevel@tonic-gate 			rr->top=top;
10810Sstevel@tonic-gate 			goto end;
1082*2139Sjp161948 			}
10830Sstevel@tonic-gate #endif
10840Sstevel@tonic-gate 		}
10850Sstevel@tonic-gate #endif /* BN_RECURSION */
10860Sstevel@tonic-gate 	if (bn_wexpand(rr,top) == NULL) goto err;
10870Sstevel@tonic-gate 	rr->top=top;
10880Sstevel@tonic-gate 	bn_mul_normal(rr->d,a->d,al,b->d,bl);
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate #if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
10910Sstevel@tonic-gate end:
10920Sstevel@tonic-gate #endif
1093*2139Sjp161948 	bn_correct_top(rr);
10940Sstevel@tonic-gate 	if (r != rr) BN_copy(r,rr);
10950Sstevel@tonic-gate 	ret=1;
10960Sstevel@tonic-gate err:
1097*2139Sjp161948 	bn_check_top(r);
10980Sstevel@tonic-gate 	BN_CTX_end(ctx);
10990Sstevel@tonic-gate 	return(ret);
11000Sstevel@tonic-gate 	}
11010Sstevel@tonic-gate 
bn_mul_normal(BN_ULONG * r,BN_ULONG * a,int na,BN_ULONG * b,int nb)11020Sstevel@tonic-gate void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
11030Sstevel@tonic-gate 	{
11040Sstevel@tonic-gate 	BN_ULONG *rr;
11050Sstevel@tonic-gate 
11060Sstevel@tonic-gate #ifdef BN_COUNT
1107*2139Sjp161948 	fprintf(stderr," bn_mul_normal %d * %d\n",na,nb);
11080Sstevel@tonic-gate #endif
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 	if (na < nb)
11110Sstevel@tonic-gate 		{
11120Sstevel@tonic-gate 		int itmp;
11130Sstevel@tonic-gate 		BN_ULONG *ltmp;
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate 		itmp=na; na=nb; nb=itmp;
11160Sstevel@tonic-gate 		ltmp=a;   a=b;   b=ltmp;
11170Sstevel@tonic-gate 
11180Sstevel@tonic-gate 		}
11190Sstevel@tonic-gate 	rr= &(r[na]);
1120*2139Sjp161948 	if (nb <= 0)
1121*2139Sjp161948 		{
1122*2139Sjp161948 		(void)bn_mul_words(r,a,na,0);
1123*2139Sjp161948 		return;
1124*2139Sjp161948 		}
1125*2139Sjp161948 	else
1126*2139Sjp161948 		rr[0]=bn_mul_words(r,a,na,b[0]);
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate 	for (;;)
11290Sstevel@tonic-gate 		{
11300Sstevel@tonic-gate 		if (--nb <= 0) return;
11310Sstevel@tonic-gate 		rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]);
11320Sstevel@tonic-gate 		if (--nb <= 0) return;
11330Sstevel@tonic-gate 		rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]);
11340Sstevel@tonic-gate 		if (--nb <= 0) return;
11350Sstevel@tonic-gate 		rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]);
11360Sstevel@tonic-gate 		if (--nb <= 0) return;
11370Sstevel@tonic-gate 		rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]);
11380Sstevel@tonic-gate 		rr+=4;
11390Sstevel@tonic-gate 		r+=4;
11400Sstevel@tonic-gate 		b+=4;
11410Sstevel@tonic-gate 		}
11420Sstevel@tonic-gate 	}
11430Sstevel@tonic-gate 
bn_mul_low_normal(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,int n)11440Sstevel@tonic-gate void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
11450Sstevel@tonic-gate 	{
11460Sstevel@tonic-gate #ifdef BN_COUNT
1147*2139Sjp161948 	fprintf(stderr," bn_mul_low_normal %d * %d\n",n,n);
11480Sstevel@tonic-gate #endif
11490Sstevel@tonic-gate 	bn_mul_words(r,a,n,b[0]);
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate 	for (;;)
11520Sstevel@tonic-gate 		{
11530Sstevel@tonic-gate 		if (--n <= 0) return;
11540Sstevel@tonic-gate 		bn_mul_add_words(&(r[1]),a,n,b[1]);
11550Sstevel@tonic-gate 		if (--n <= 0) return;
11560Sstevel@tonic-gate 		bn_mul_add_words(&(r[2]),a,n,b[2]);
11570Sstevel@tonic-gate 		if (--n <= 0) return;
11580Sstevel@tonic-gate 		bn_mul_add_words(&(r[3]),a,n,b[3]);
11590Sstevel@tonic-gate 		if (--n <= 0) return;
11600Sstevel@tonic-gate 		bn_mul_add_words(&(r[4]),a,n,b[4]);
11610Sstevel@tonic-gate 		r+=4;
11620Sstevel@tonic-gate 		b+=4;
11630Sstevel@tonic-gate 		}
11640Sstevel@tonic-gate 	}
1165