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