xref: /dragonfly/crypto/libressl/crypto/bn/bn_mul.c (revision 72c33676)
172c33676SMaxim Ag /* $OpenBSD: bn_mul.c,v 1.20 2015/02/09 15:49:22 jsing Exp $ */
2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3f5b1c8a1SJohn Marino  * All rights reserved.
4f5b1c8a1SJohn Marino  *
5f5b1c8a1SJohn Marino  * This package is an SSL implementation written
6f5b1c8a1SJohn Marino  * by Eric Young (eay@cryptsoft.com).
7f5b1c8a1SJohn Marino  * The implementation was written so as to conform with Netscapes SSL.
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * This library is free for commercial and non-commercial use as long as
10f5b1c8a1SJohn Marino  * the following conditions are aheared to.  The following conditions
11f5b1c8a1SJohn Marino  * apply to all code found in this distribution, be it the RC4, RSA,
12f5b1c8a1SJohn Marino  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13f5b1c8a1SJohn Marino  * included with this distribution is covered by the same copyright terms
14f5b1c8a1SJohn Marino  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15f5b1c8a1SJohn Marino  *
16f5b1c8a1SJohn Marino  * Copyright remains Eric Young's, and as such any Copyright notices in
17f5b1c8a1SJohn Marino  * the code are not to be removed.
18f5b1c8a1SJohn Marino  * If this package is used in a product, Eric Young should be given attribution
19f5b1c8a1SJohn Marino  * as the author of the parts of the library used.
20f5b1c8a1SJohn Marino  * This can be in the form of a textual message at program startup or
21f5b1c8a1SJohn Marino  * in documentation (online or textual) provided with the package.
22f5b1c8a1SJohn Marino  *
23f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
24f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
25f5b1c8a1SJohn Marino  * are met:
26f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the copyright
27f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
28f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
29f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
30f5b1c8a1SJohn Marino  *    documentation and/or other materials provided with the distribution.
31f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this software
32f5b1c8a1SJohn Marino  *    must display the following acknowledgement:
33f5b1c8a1SJohn Marino  *    "This product includes cryptographic software written by
34f5b1c8a1SJohn Marino  *     Eric Young (eay@cryptsoft.com)"
35f5b1c8a1SJohn Marino  *    The word 'cryptographic' can be left out if the rouines from the library
36f5b1c8a1SJohn Marino  *    being used are not cryptographic related :-).
37f5b1c8a1SJohn Marino  * 4. If you include any Windows specific code (or a derivative thereof) from
38f5b1c8a1SJohn Marino  *    the apps directory (application code) you must include an acknowledgement:
39f5b1c8a1SJohn Marino  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40f5b1c8a1SJohn Marino  *
41f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42f5b1c8a1SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44f5b1c8a1SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45f5b1c8a1SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46f5b1c8a1SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47f5b1c8a1SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49f5b1c8a1SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50f5b1c8a1SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51f5b1c8a1SJohn Marino  * SUCH DAMAGE.
52f5b1c8a1SJohn Marino  *
53f5b1c8a1SJohn Marino  * The licence and distribution terms for any publically available version or
54f5b1c8a1SJohn Marino  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55f5b1c8a1SJohn Marino  * copied and put under another distribution licence
56f5b1c8a1SJohn Marino  * [including the GNU Public Licence.]
57f5b1c8a1SJohn Marino  */
58f5b1c8a1SJohn Marino 
59f5b1c8a1SJohn Marino #ifndef BN_DEBUG
60f5b1c8a1SJohn Marino # undef NDEBUG /* avoid conflicting definitions */
61f5b1c8a1SJohn Marino # define NDEBUG
62f5b1c8a1SJohn Marino #endif
63f5b1c8a1SJohn Marino 
64f5b1c8a1SJohn Marino #include <assert.h>
65f5b1c8a1SJohn Marino #include <stdio.h>
66f5b1c8a1SJohn Marino #include <string.h>
67f5b1c8a1SJohn Marino 
68f5b1c8a1SJohn Marino #include <openssl/opensslconf.h>
69f5b1c8a1SJohn Marino 
70f5b1c8a1SJohn Marino #include "bn_lcl.h"
71f5b1c8a1SJohn Marino 
72f5b1c8a1SJohn Marino #if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS)
73f5b1c8a1SJohn Marino /* Here follows specialised variants of bn_add_words() and
74f5b1c8a1SJohn Marino    bn_sub_words().  They have the property performing operations on
75f5b1c8a1SJohn Marino    arrays of different sizes.  The sizes of those arrays is expressed through
76f5b1c8a1SJohn Marino    cl, which is the common length ( basicall, min(len(a),len(b)) ), and dl,
77f5b1c8a1SJohn Marino    which is the delta between the two lengths, calculated as len(a)-len(b).
78f5b1c8a1SJohn Marino    All lengths are the number of BN_ULONGs...  For the operations that require
79f5b1c8a1SJohn Marino    a result array as parameter, it must have the length cl+abs(dl).
80f5b1c8a1SJohn Marino    These functions should probably end up in bn_asm.c as soon as there are
81f5b1c8a1SJohn Marino    assembler counterparts for the systems that use assembler files.  */
82f5b1c8a1SJohn Marino 
83f5b1c8a1SJohn Marino BN_ULONG
bn_sub_part_words(BN_ULONG * r,const BN_ULONG * a,const BN_ULONG * b,int cl,int dl)84f5b1c8a1SJohn Marino bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int cl,
85f5b1c8a1SJohn Marino     int dl)
86f5b1c8a1SJohn Marino {
87f5b1c8a1SJohn Marino 	BN_ULONG c, t;
88f5b1c8a1SJohn Marino 
89f5b1c8a1SJohn Marino 	assert(cl >= 0);
90f5b1c8a1SJohn Marino 	c = bn_sub_words(r, a, b, cl);
91f5b1c8a1SJohn Marino 
92f5b1c8a1SJohn Marino 	if (dl == 0)
93f5b1c8a1SJohn Marino 		return c;
94f5b1c8a1SJohn Marino 
95f5b1c8a1SJohn Marino 	r += cl;
96f5b1c8a1SJohn Marino 	a += cl;
97f5b1c8a1SJohn Marino 	b += cl;
98f5b1c8a1SJohn Marino 
99f5b1c8a1SJohn Marino 	if (dl < 0) {
100f5b1c8a1SJohn Marino #ifdef BN_COUNT
101f5b1c8a1SJohn Marino 		fprintf(stderr,
102f5b1c8a1SJohn Marino 		    "  bn_sub_part_words %d + %d (dl < 0, c = %d)\n",
103f5b1c8a1SJohn Marino 		    cl, dl, c);
104f5b1c8a1SJohn Marino #endif
105f5b1c8a1SJohn Marino 		for (;;) {
106f5b1c8a1SJohn Marino 			t = b[0];
107f5b1c8a1SJohn Marino 			r[0] = (0 - t - c) & BN_MASK2;
108f5b1c8a1SJohn Marino 			if (t != 0)
109f5b1c8a1SJohn Marino 				c = 1;
110f5b1c8a1SJohn Marino 			if (++dl >= 0)
111f5b1c8a1SJohn Marino 				break;
112f5b1c8a1SJohn Marino 
113f5b1c8a1SJohn Marino 			t = b[1];
114f5b1c8a1SJohn Marino 			r[1] = (0 - t - c) & BN_MASK2;
115f5b1c8a1SJohn Marino 			if (t != 0)
116f5b1c8a1SJohn Marino 				c = 1;
117f5b1c8a1SJohn Marino 			if (++dl >= 0)
118f5b1c8a1SJohn Marino 				break;
119f5b1c8a1SJohn Marino 
120f5b1c8a1SJohn Marino 			t = b[2];
121f5b1c8a1SJohn Marino 			r[2] = (0 - t - c) & BN_MASK2;
122f5b1c8a1SJohn Marino 			if (t != 0)
123f5b1c8a1SJohn Marino 				c = 1;
124f5b1c8a1SJohn Marino 			if (++dl >= 0)
125f5b1c8a1SJohn Marino 				break;
126f5b1c8a1SJohn Marino 
127f5b1c8a1SJohn Marino 			t = b[3];
128f5b1c8a1SJohn Marino 			r[3] = (0 - t - c) & BN_MASK2;
129f5b1c8a1SJohn Marino 			if (t != 0)
130f5b1c8a1SJohn Marino 				c = 1;
131f5b1c8a1SJohn Marino 			if (++dl >= 0)
132f5b1c8a1SJohn Marino 				break;
133f5b1c8a1SJohn Marino 
134f5b1c8a1SJohn Marino 			b += 4;
135f5b1c8a1SJohn Marino 			r += 4;
136f5b1c8a1SJohn Marino 		}
137f5b1c8a1SJohn Marino 	} else {
138f5b1c8a1SJohn Marino 		int save_dl = dl;
139f5b1c8a1SJohn Marino #ifdef BN_COUNT
140f5b1c8a1SJohn Marino 		fprintf(stderr,
141f5b1c8a1SJohn Marino 		    "  bn_sub_part_words %d + %d (dl > 0, c = %d)\n",
142f5b1c8a1SJohn Marino 		    cl, dl, c);
143f5b1c8a1SJohn Marino #endif
144f5b1c8a1SJohn Marino 		while (c) {
145f5b1c8a1SJohn Marino 			t = a[0];
146f5b1c8a1SJohn Marino 			r[0] = (t - c) & BN_MASK2;
147f5b1c8a1SJohn Marino 			if (t != 0)
148f5b1c8a1SJohn Marino 				c = 0;
149f5b1c8a1SJohn Marino 			if (--dl <= 0)
150f5b1c8a1SJohn Marino 				break;
151f5b1c8a1SJohn Marino 
152f5b1c8a1SJohn Marino 			t = a[1];
153f5b1c8a1SJohn Marino 			r[1] = (t - c) & BN_MASK2;
154f5b1c8a1SJohn Marino 			if (t != 0)
155f5b1c8a1SJohn Marino 				c = 0;
156f5b1c8a1SJohn Marino 			if (--dl <= 0)
157f5b1c8a1SJohn Marino 				break;
158f5b1c8a1SJohn Marino 
159f5b1c8a1SJohn Marino 			t = a[2];
160f5b1c8a1SJohn Marino 			r[2] = (t - c) & BN_MASK2;
161f5b1c8a1SJohn Marino 			if (t != 0)
162f5b1c8a1SJohn Marino 				c = 0;
163f5b1c8a1SJohn Marino 			if (--dl <= 0)
164f5b1c8a1SJohn Marino 				break;
165f5b1c8a1SJohn Marino 
166f5b1c8a1SJohn Marino 			t = a[3];
167f5b1c8a1SJohn Marino 			r[3] = (t - c) & BN_MASK2;
168f5b1c8a1SJohn Marino 			if (t != 0)
169f5b1c8a1SJohn Marino 				c = 0;
170f5b1c8a1SJohn Marino 			if (--dl <= 0)
171f5b1c8a1SJohn Marino 				break;
172f5b1c8a1SJohn Marino 
173f5b1c8a1SJohn Marino 			save_dl = dl;
174f5b1c8a1SJohn Marino 			a += 4;
175f5b1c8a1SJohn Marino 			r += 4;
176f5b1c8a1SJohn Marino 		}
177f5b1c8a1SJohn Marino 		if (dl > 0) {
178f5b1c8a1SJohn Marino #ifdef BN_COUNT
179f5b1c8a1SJohn Marino 			fprintf(stderr,
180f5b1c8a1SJohn Marino 			    "  bn_sub_part_words %d + %d (dl > 0, c == 0)\n",
181f5b1c8a1SJohn Marino 			    cl, dl);
182f5b1c8a1SJohn Marino #endif
183f5b1c8a1SJohn Marino 			if (save_dl > dl) {
184f5b1c8a1SJohn Marino 				switch (save_dl - dl) {
185f5b1c8a1SJohn Marino 				case 1:
186f5b1c8a1SJohn Marino 					r[1] = a[1];
187f5b1c8a1SJohn Marino 					if (--dl <= 0)
188f5b1c8a1SJohn Marino 						break;
189f5b1c8a1SJohn Marino 				case 2:
190f5b1c8a1SJohn Marino 					r[2] = a[2];
191f5b1c8a1SJohn Marino 					if (--dl <= 0)
192f5b1c8a1SJohn Marino 						break;
193f5b1c8a1SJohn Marino 				case 3:
194f5b1c8a1SJohn Marino 					r[3] = a[3];
195f5b1c8a1SJohn Marino 					if (--dl <= 0)
196f5b1c8a1SJohn Marino 						break;
197f5b1c8a1SJohn Marino 				}
198f5b1c8a1SJohn Marino 				a += 4;
199f5b1c8a1SJohn Marino 				r += 4;
200f5b1c8a1SJohn Marino 			}
201f5b1c8a1SJohn Marino 		}
202f5b1c8a1SJohn Marino 		if (dl > 0) {
203f5b1c8a1SJohn Marino #ifdef BN_COUNT
204f5b1c8a1SJohn Marino 			fprintf(stderr,
205f5b1c8a1SJohn Marino 			    "  bn_sub_part_words %d + %d (dl > 0, copy)\n",
206f5b1c8a1SJohn Marino 			    cl, dl);
207f5b1c8a1SJohn Marino #endif
208f5b1c8a1SJohn Marino 			for (;;) {
209f5b1c8a1SJohn Marino 				r[0] = a[0];
210f5b1c8a1SJohn Marino 				if (--dl <= 0)
211f5b1c8a1SJohn Marino 					break;
212f5b1c8a1SJohn Marino 				r[1] = a[1];
213f5b1c8a1SJohn Marino 				if (--dl <= 0)
214f5b1c8a1SJohn Marino 					break;
215f5b1c8a1SJohn Marino 				r[2] = a[2];
216f5b1c8a1SJohn Marino 				if (--dl <= 0)
217f5b1c8a1SJohn Marino 					break;
218f5b1c8a1SJohn Marino 				r[3] = a[3];
219f5b1c8a1SJohn Marino 				if (--dl <= 0)
220f5b1c8a1SJohn Marino 					break;
221f5b1c8a1SJohn Marino 
222f5b1c8a1SJohn Marino 				a += 4;
223f5b1c8a1SJohn Marino 				r += 4;
224f5b1c8a1SJohn Marino 			}
225f5b1c8a1SJohn Marino 		}
226f5b1c8a1SJohn Marino 	}
227f5b1c8a1SJohn Marino 	return c;
228f5b1c8a1SJohn Marino }
229f5b1c8a1SJohn Marino #endif
230f5b1c8a1SJohn Marino 
231f5b1c8a1SJohn Marino BN_ULONG
bn_add_part_words(BN_ULONG * r,const BN_ULONG * a,const BN_ULONG * b,int cl,int dl)232f5b1c8a1SJohn Marino bn_add_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int cl,
233f5b1c8a1SJohn Marino     int dl)
234f5b1c8a1SJohn Marino {
235f5b1c8a1SJohn Marino 	BN_ULONG c, l, t;
236f5b1c8a1SJohn Marino 
237f5b1c8a1SJohn Marino 	assert(cl >= 0);
238f5b1c8a1SJohn Marino 	c = bn_add_words(r, a, b, cl);
239f5b1c8a1SJohn Marino 
240f5b1c8a1SJohn Marino 	if (dl == 0)
241f5b1c8a1SJohn Marino 		return c;
242f5b1c8a1SJohn Marino 
243f5b1c8a1SJohn Marino 	r += cl;
244f5b1c8a1SJohn Marino 	a += cl;
245f5b1c8a1SJohn Marino 	b += cl;
246f5b1c8a1SJohn Marino 
247f5b1c8a1SJohn Marino 	if (dl < 0) {
248f5b1c8a1SJohn Marino 		int save_dl = dl;
249f5b1c8a1SJohn Marino #ifdef BN_COUNT
250f5b1c8a1SJohn Marino 		fprintf(stderr,
251f5b1c8a1SJohn Marino 		    "  bn_add_part_words %d + %d (dl < 0, c = %d)\n",
252f5b1c8a1SJohn Marino 		    cl, dl, c);
253f5b1c8a1SJohn Marino #endif
254f5b1c8a1SJohn Marino 		while (c) {
255f5b1c8a1SJohn Marino 			l = (c + b[0]) & BN_MASK2;
256f5b1c8a1SJohn Marino 			c = (l < c);
257f5b1c8a1SJohn Marino 			r[0] = l;
258f5b1c8a1SJohn Marino 			if (++dl >= 0)
259f5b1c8a1SJohn Marino 				break;
260f5b1c8a1SJohn Marino 
261f5b1c8a1SJohn Marino 			l = (c + b[1]) & BN_MASK2;
262f5b1c8a1SJohn Marino 			c = (l < c);
263f5b1c8a1SJohn Marino 			r[1] = l;
264f5b1c8a1SJohn Marino 			if (++dl >= 0)
265f5b1c8a1SJohn Marino 				break;
266f5b1c8a1SJohn Marino 
267f5b1c8a1SJohn Marino 			l = (c + b[2]) & BN_MASK2;
268f5b1c8a1SJohn Marino 			c = (l < c);
269f5b1c8a1SJohn Marino 			r[2] = l;
270f5b1c8a1SJohn Marino 			if (++dl >= 0)
271f5b1c8a1SJohn Marino 				break;
272f5b1c8a1SJohn Marino 
273f5b1c8a1SJohn Marino 			l = (c + b[3]) & BN_MASK2;
274f5b1c8a1SJohn Marino 			c = (l < c);
275f5b1c8a1SJohn Marino 			r[3] = l;
276f5b1c8a1SJohn Marino 			if (++dl >= 0)
277f5b1c8a1SJohn Marino 				break;
278f5b1c8a1SJohn Marino 
279f5b1c8a1SJohn Marino 			save_dl = dl;
280f5b1c8a1SJohn Marino 			b += 4;
281f5b1c8a1SJohn Marino 			r += 4;
282f5b1c8a1SJohn Marino 		}
283f5b1c8a1SJohn Marino 		if (dl < 0) {
284f5b1c8a1SJohn Marino #ifdef BN_COUNT
285f5b1c8a1SJohn Marino 			fprintf(stderr,
286f5b1c8a1SJohn Marino 			    "  bn_add_part_words %d + %d (dl < 0, c == 0)\n",
287f5b1c8a1SJohn Marino 			    cl, dl);
288f5b1c8a1SJohn Marino #endif
289f5b1c8a1SJohn Marino 			if (save_dl < dl) {
290f5b1c8a1SJohn Marino 				switch (dl - save_dl) {
291f5b1c8a1SJohn Marino 				case 1:
292f5b1c8a1SJohn Marino 					r[1] = b[1];
293f5b1c8a1SJohn Marino 					if (++dl >= 0)
294f5b1c8a1SJohn Marino 						break;
295f5b1c8a1SJohn Marino 				case 2:
296f5b1c8a1SJohn Marino 					r[2] = b[2];
297f5b1c8a1SJohn Marino 					if (++dl >= 0)
298f5b1c8a1SJohn Marino 						break;
299f5b1c8a1SJohn Marino 				case 3:
300f5b1c8a1SJohn Marino 					r[3] = b[3];
301f5b1c8a1SJohn Marino 					if (++dl >= 0)
302f5b1c8a1SJohn Marino 						break;
303f5b1c8a1SJohn Marino 				}
304f5b1c8a1SJohn Marino 				b += 4;
305f5b1c8a1SJohn Marino 				r += 4;
306f5b1c8a1SJohn Marino 			}
307f5b1c8a1SJohn Marino 		}
308f5b1c8a1SJohn Marino 		if (dl < 0) {
309f5b1c8a1SJohn Marino #ifdef BN_COUNT
310f5b1c8a1SJohn Marino 			fprintf(stderr,
311f5b1c8a1SJohn Marino 			    "  bn_add_part_words %d + %d (dl < 0, copy)\n",
312f5b1c8a1SJohn Marino 			    cl, dl);
313f5b1c8a1SJohn Marino #endif
314f5b1c8a1SJohn Marino 			for (;;) {
315f5b1c8a1SJohn Marino 				r[0] = b[0];
316f5b1c8a1SJohn Marino 				if (++dl >= 0)
317f5b1c8a1SJohn Marino 					break;
318f5b1c8a1SJohn Marino 				r[1] = b[1];
319f5b1c8a1SJohn Marino 				if (++dl >= 0)
320f5b1c8a1SJohn Marino 					break;
321f5b1c8a1SJohn Marino 				r[2] = b[2];
322f5b1c8a1SJohn Marino 				if (++dl >= 0)
323f5b1c8a1SJohn Marino 					break;
324f5b1c8a1SJohn Marino 				r[3] = b[3];
325f5b1c8a1SJohn Marino 				if (++dl >= 0)
326f5b1c8a1SJohn Marino 					break;
327f5b1c8a1SJohn Marino 
328f5b1c8a1SJohn Marino 				b += 4;
329f5b1c8a1SJohn Marino 				r += 4;
330f5b1c8a1SJohn Marino 			}
331f5b1c8a1SJohn Marino 		}
332f5b1c8a1SJohn Marino 	} else {
333f5b1c8a1SJohn Marino 		int save_dl = dl;
334f5b1c8a1SJohn Marino #ifdef BN_COUNT
335f5b1c8a1SJohn Marino 		fprintf(stderr,
336f5b1c8a1SJohn Marino 		    "  bn_add_part_words %d + %d (dl > 0)\n", cl, dl);
337f5b1c8a1SJohn Marino #endif
338f5b1c8a1SJohn Marino 		while (c) {
339f5b1c8a1SJohn Marino 			t = (a[0] + c) & BN_MASK2;
340f5b1c8a1SJohn Marino 			c = (t < c);
341f5b1c8a1SJohn Marino 			r[0] = t;
342f5b1c8a1SJohn Marino 			if (--dl <= 0)
343f5b1c8a1SJohn Marino 				break;
344f5b1c8a1SJohn Marino 
345f5b1c8a1SJohn Marino 			t = (a[1] + c) & BN_MASK2;
346f5b1c8a1SJohn Marino 			c = (t < c);
347f5b1c8a1SJohn Marino 			r[1] = t;
348f5b1c8a1SJohn Marino 			if (--dl <= 0)
349f5b1c8a1SJohn Marino 				break;
350f5b1c8a1SJohn Marino 
351f5b1c8a1SJohn Marino 			t = (a[2] + c) & BN_MASK2;
352f5b1c8a1SJohn Marino 			c = (t < c);
353f5b1c8a1SJohn Marino 			r[2] = t;
354f5b1c8a1SJohn Marino 			if (--dl <= 0)
355f5b1c8a1SJohn Marino 				break;
356f5b1c8a1SJohn Marino 
357f5b1c8a1SJohn Marino 			t = (a[3] + c) & BN_MASK2;
358f5b1c8a1SJohn Marino 			c = (t < c);
359f5b1c8a1SJohn Marino 			r[3] = t;
360f5b1c8a1SJohn Marino 			if (--dl <= 0)
361f5b1c8a1SJohn Marino 				break;
362f5b1c8a1SJohn Marino 
363f5b1c8a1SJohn Marino 			save_dl = dl;
364f5b1c8a1SJohn Marino 			a += 4;
365f5b1c8a1SJohn Marino 			r += 4;
366f5b1c8a1SJohn Marino 		}
367f5b1c8a1SJohn Marino #ifdef BN_COUNT
368f5b1c8a1SJohn Marino 		fprintf(stderr,
369f5b1c8a1SJohn Marino 		    "  bn_add_part_words %d + %d (dl > 0, c == 0)\n", cl, dl);
370f5b1c8a1SJohn Marino #endif
371f5b1c8a1SJohn Marino 		if (dl > 0) {
372f5b1c8a1SJohn Marino 			if (save_dl > dl) {
373f5b1c8a1SJohn Marino 				switch (save_dl - dl) {
374f5b1c8a1SJohn Marino 				case 1:
375f5b1c8a1SJohn Marino 					r[1] = a[1];
376f5b1c8a1SJohn Marino 					if (--dl <= 0)
377f5b1c8a1SJohn Marino 						break;
378f5b1c8a1SJohn Marino 				case 2:
379f5b1c8a1SJohn Marino 					r[2] = a[2];
380f5b1c8a1SJohn Marino 					if (--dl <= 0)
381f5b1c8a1SJohn Marino 						break;
382f5b1c8a1SJohn Marino 				case 3:
383f5b1c8a1SJohn Marino 					r[3] = a[3];
384f5b1c8a1SJohn Marino 					if (--dl <= 0)
385f5b1c8a1SJohn Marino 						break;
386f5b1c8a1SJohn Marino 				}
387f5b1c8a1SJohn Marino 				a += 4;
388f5b1c8a1SJohn Marino 				r += 4;
389f5b1c8a1SJohn Marino 			}
390f5b1c8a1SJohn Marino 		}
391f5b1c8a1SJohn Marino 		if (dl > 0) {
392f5b1c8a1SJohn Marino #ifdef BN_COUNT
393f5b1c8a1SJohn Marino 			fprintf(stderr,
394f5b1c8a1SJohn Marino 			    "  bn_add_part_words %d + %d (dl > 0, copy)\n",
395f5b1c8a1SJohn Marino 			    cl, dl);
396f5b1c8a1SJohn Marino #endif
397f5b1c8a1SJohn Marino 			for (;;) {
398f5b1c8a1SJohn Marino 				r[0] = a[0];
399f5b1c8a1SJohn Marino 				if (--dl <= 0)
400f5b1c8a1SJohn Marino 					break;
401f5b1c8a1SJohn Marino 				r[1] = a[1];
402f5b1c8a1SJohn Marino 				if (--dl <= 0)
403f5b1c8a1SJohn Marino 					break;
404f5b1c8a1SJohn Marino 				r[2] = a[2];
405f5b1c8a1SJohn Marino 				if (--dl <= 0)
406f5b1c8a1SJohn Marino 					break;
407f5b1c8a1SJohn Marino 				r[3] = a[3];
408f5b1c8a1SJohn Marino 				if (--dl <= 0)
409f5b1c8a1SJohn Marino 					break;
410f5b1c8a1SJohn Marino 
411f5b1c8a1SJohn Marino 				a += 4;
412f5b1c8a1SJohn Marino 				r += 4;
413f5b1c8a1SJohn Marino 			}
414f5b1c8a1SJohn Marino 		}
415f5b1c8a1SJohn Marino 	}
416f5b1c8a1SJohn Marino 	return c;
417f5b1c8a1SJohn Marino }
418f5b1c8a1SJohn Marino 
419f5b1c8a1SJohn Marino #ifdef BN_RECURSION
420f5b1c8a1SJohn Marino /* Karatsuba recursive multiplication algorithm
421f5b1c8a1SJohn Marino  * (cf. Knuth, The Art of Computer Programming, Vol. 2) */
422f5b1c8a1SJohn Marino 
423f5b1c8a1SJohn Marino /* r is 2*n2 words in size,
424f5b1c8a1SJohn Marino  * a and b are both n2 words in size.
425f5b1c8a1SJohn Marino  * n2 must be a power of 2.
426f5b1c8a1SJohn Marino  * We multiply and return the result.
427f5b1c8a1SJohn Marino  * t must be 2*n2 words in size
428f5b1c8a1SJohn Marino  * We calculate
429f5b1c8a1SJohn Marino  * a[0]*b[0]
430f5b1c8a1SJohn Marino  * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
431f5b1c8a1SJohn Marino  * a[1]*b[1]
432f5b1c8a1SJohn Marino  */
433f5b1c8a1SJohn Marino /* dnX may not be positive, but n2/2+dnX has to be */
434f5b1c8a1SJohn Marino void
bn_mul_recursive(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,int n2,int dna,int dnb,BN_ULONG * t)435f5b1c8a1SJohn Marino bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, int dna,
436f5b1c8a1SJohn Marino     int dnb, BN_ULONG *t)
437f5b1c8a1SJohn Marino {
438f5b1c8a1SJohn Marino 	int n = n2 / 2, c1, c2;
439f5b1c8a1SJohn Marino 	int tna = n + dna, tnb = n + dnb;
440f5b1c8a1SJohn Marino 	unsigned int neg, zero;
441f5b1c8a1SJohn Marino 	BN_ULONG ln, lo, *p;
442f5b1c8a1SJohn Marino 
443f5b1c8a1SJohn Marino # ifdef BN_COUNT
444f5b1c8a1SJohn Marino 	fprintf(stderr, " bn_mul_recursive %d%+d * %d%+d\n",n2,dna,n2,dnb);
445f5b1c8a1SJohn Marino # endif
446f5b1c8a1SJohn Marino # ifdef BN_MUL_COMBA
447f5b1c8a1SJohn Marino #  if 0
448f5b1c8a1SJohn Marino 	if (n2 == 4) {
449f5b1c8a1SJohn Marino 		bn_mul_comba4(r, a, b);
450f5b1c8a1SJohn Marino 		return;
451f5b1c8a1SJohn Marino 	}
452f5b1c8a1SJohn Marino #  endif
453f5b1c8a1SJohn Marino 	/* Only call bn_mul_comba 8 if n2 == 8 and the
454f5b1c8a1SJohn Marino 	 * two arrays are complete [steve]
455f5b1c8a1SJohn Marino 	 */
456f5b1c8a1SJohn Marino 	if (n2 == 8 && dna == 0 && dnb == 0) {
457f5b1c8a1SJohn Marino 		bn_mul_comba8(r, a, b);
458f5b1c8a1SJohn Marino 		return;
459f5b1c8a1SJohn Marino 	}
460f5b1c8a1SJohn Marino # endif /* BN_MUL_COMBA */
461f5b1c8a1SJohn Marino 	/* Else do normal multiply */
462f5b1c8a1SJohn Marino 	if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) {
463f5b1c8a1SJohn Marino 		bn_mul_normal(r, a, n2 + dna, b, n2 + dnb);
464f5b1c8a1SJohn Marino 		if ((dna + dnb) < 0)
465f5b1c8a1SJohn Marino 			memset(&r[2*n2 + dna + dnb], 0,
466f5b1c8a1SJohn Marino 			    sizeof(BN_ULONG) * -(dna + dnb));
467f5b1c8a1SJohn Marino 		return;
468f5b1c8a1SJohn Marino 	}
469f5b1c8a1SJohn Marino 	/* r=(a[0]-a[1])*(b[1]-b[0]) */
470f5b1c8a1SJohn Marino 	c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
471f5b1c8a1SJohn Marino 	c2 = bn_cmp_part_words(&(b[n]), b,tnb, tnb - n);
472f5b1c8a1SJohn Marino 	zero = neg = 0;
473f5b1c8a1SJohn Marino 	switch (c1 * 3 + c2) {
474f5b1c8a1SJohn Marino 	case -4:
475f5b1c8a1SJohn Marino 		bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
476f5b1c8a1SJohn Marino 		bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
477f5b1c8a1SJohn Marino 		break;
478f5b1c8a1SJohn Marino 	case -3:
479f5b1c8a1SJohn Marino 		zero = 1;
480f5b1c8a1SJohn Marino 		break;
481f5b1c8a1SJohn Marino 	case -2:
482f5b1c8a1SJohn Marino 		bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
483f5b1c8a1SJohn Marino 		bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */
484f5b1c8a1SJohn Marino 		neg = 1;
485f5b1c8a1SJohn Marino 		break;
486f5b1c8a1SJohn Marino 	case -1:
487f5b1c8a1SJohn Marino 	case 0:
488f5b1c8a1SJohn Marino 	case 1:
489f5b1c8a1SJohn Marino 		zero = 1;
490f5b1c8a1SJohn Marino 		break;
491f5b1c8a1SJohn Marino 	case 2:
492f5b1c8a1SJohn Marino 		bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */
493f5b1c8a1SJohn Marino 		bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
494f5b1c8a1SJohn Marino 		neg = 1;
495f5b1c8a1SJohn Marino 		break;
496f5b1c8a1SJohn Marino 	case 3:
497f5b1c8a1SJohn Marino 		zero = 1;
498f5b1c8a1SJohn Marino 		break;
499f5b1c8a1SJohn Marino 	case 4:
500f5b1c8a1SJohn Marino 		bn_sub_part_words(t, a, &(a[n]), tna, n - tna);
501f5b1c8a1SJohn Marino 		bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);
502f5b1c8a1SJohn Marino 		break;
503f5b1c8a1SJohn Marino 	}
504f5b1c8a1SJohn Marino 
505f5b1c8a1SJohn Marino # ifdef BN_MUL_COMBA
506f5b1c8a1SJohn Marino 	if (n == 4 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba4 could take
507f5b1c8a1SJohn Marino 					       extra args to do this well */
508f5b1c8a1SJohn Marino 	{
509f5b1c8a1SJohn Marino 		if (!zero)
510f5b1c8a1SJohn Marino 			bn_mul_comba4(&(t[n2]), t, &(t[n]));
511f5b1c8a1SJohn Marino 		else
512f5b1c8a1SJohn Marino 			memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG));
513f5b1c8a1SJohn Marino 
514f5b1c8a1SJohn Marino 		bn_mul_comba4(r, a, b);
515f5b1c8a1SJohn Marino 		bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n]));
516f5b1c8a1SJohn Marino 	} else if (n == 8 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba8 could
517f5b1c8a1SJohn Marino 						    take extra args to do this
518f5b1c8a1SJohn Marino 						    well */
519f5b1c8a1SJohn Marino 	{
520f5b1c8a1SJohn Marino 		if (!zero)
521f5b1c8a1SJohn Marino 			bn_mul_comba8(&(t[n2]), t, &(t[n]));
522f5b1c8a1SJohn Marino 		else
523f5b1c8a1SJohn Marino 			memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG));
524f5b1c8a1SJohn Marino 
525f5b1c8a1SJohn Marino 		bn_mul_comba8(r, a, b);
526f5b1c8a1SJohn Marino 		bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n]));
527f5b1c8a1SJohn Marino 	} else
528f5b1c8a1SJohn Marino # endif /* BN_MUL_COMBA */
529f5b1c8a1SJohn Marino 	{
530f5b1c8a1SJohn Marino 		p = &(t[n2 * 2]);
531f5b1c8a1SJohn Marino 		if (!zero)
532f5b1c8a1SJohn Marino 			bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
533f5b1c8a1SJohn Marino 		else
534f5b1c8a1SJohn Marino 			memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
535f5b1c8a1SJohn Marino 		bn_mul_recursive(r, a, b, n, 0, 0, p);
536f5b1c8a1SJohn Marino 		bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p);
537f5b1c8a1SJohn Marino 	}
538f5b1c8a1SJohn Marino 
539f5b1c8a1SJohn Marino 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
540f5b1c8a1SJohn Marino 	 * r[10] holds (a[0]*b[0])
541f5b1c8a1SJohn Marino 	 * r[32] holds (b[1]*b[1])
542f5b1c8a1SJohn Marino 	 */
543f5b1c8a1SJohn Marino 
544f5b1c8a1SJohn Marino 	c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
545f5b1c8a1SJohn Marino 
546f5b1c8a1SJohn Marino 	if (neg) /* if t[32] is negative */
547f5b1c8a1SJohn Marino 	{
548f5b1c8a1SJohn Marino 		c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
549f5b1c8a1SJohn Marino 	} else {
550f5b1c8a1SJohn Marino 		/* Might have a carry */
551f5b1c8a1SJohn Marino 		c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));
552f5b1c8a1SJohn Marino 	}
553f5b1c8a1SJohn Marino 
554f5b1c8a1SJohn Marino 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
555f5b1c8a1SJohn Marino 	 * r[10] holds (a[0]*b[0])
556f5b1c8a1SJohn Marino 	 * r[32] holds (b[1]*b[1])
557f5b1c8a1SJohn Marino 	 * c1 holds the carry bits
558f5b1c8a1SJohn Marino 	 */
559f5b1c8a1SJohn Marino 	c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
560f5b1c8a1SJohn Marino 	if (c1) {
561f5b1c8a1SJohn Marino 		p = &(r[n + n2]);
562f5b1c8a1SJohn Marino 		lo= *p;
563f5b1c8a1SJohn Marino 		ln = (lo + c1) & BN_MASK2;
564f5b1c8a1SJohn Marino 		*p = ln;
565f5b1c8a1SJohn Marino 
566f5b1c8a1SJohn Marino 		/* The overflow will stop before we over write
567f5b1c8a1SJohn Marino 		 * words we should not overwrite */
568f5b1c8a1SJohn Marino 		if (ln < (BN_ULONG)c1) {
569f5b1c8a1SJohn Marino 			do {
570f5b1c8a1SJohn Marino 				p++;
571f5b1c8a1SJohn Marino 				lo= *p;
572f5b1c8a1SJohn Marino 				ln = (lo + 1) & BN_MASK2;
573f5b1c8a1SJohn Marino 				*p = ln;
574f5b1c8a1SJohn Marino 			} while (ln == 0);
575f5b1c8a1SJohn Marino 		}
576f5b1c8a1SJohn Marino 	}
577f5b1c8a1SJohn Marino }
578f5b1c8a1SJohn Marino 
579f5b1c8a1SJohn Marino /* n+tn is the word length
580f5b1c8a1SJohn Marino  * t needs to be n*4 is size, as does r */
581f5b1c8a1SJohn Marino /* tnX may not be negative but less than n */
582f5b1c8a1SJohn Marino void
bn_mul_part_recursive(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,int n,int tna,int tnb,BN_ULONG * t)583f5b1c8a1SJohn Marino bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n, int tna,
584f5b1c8a1SJohn Marino     int tnb, BN_ULONG *t)
585f5b1c8a1SJohn Marino {
586f5b1c8a1SJohn Marino 	int i, j, n2 = n * 2;
587f5b1c8a1SJohn Marino 	int c1, c2, neg;
588f5b1c8a1SJohn Marino 	BN_ULONG ln, lo, *p;
589f5b1c8a1SJohn Marino 
590f5b1c8a1SJohn Marino # ifdef BN_COUNT
591f5b1c8a1SJohn Marino 	fprintf(stderr, " bn_mul_part_recursive (%d%+d) * (%d%+d)\n",
592f5b1c8a1SJohn Marino 	    n, tna, n, tnb);
593f5b1c8a1SJohn Marino # endif
594f5b1c8a1SJohn Marino 	if (n < 8) {
595f5b1c8a1SJohn Marino 		bn_mul_normal(r, a, n + tna, b, n + tnb);
596f5b1c8a1SJohn Marino 		return;
597f5b1c8a1SJohn Marino 	}
598f5b1c8a1SJohn Marino 
599f5b1c8a1SJohn Marino 	/* r=(a[0]-a[1])*(b[1]-b[0]) */
600f5b1c8a1SJohn Marino 	c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
601f5b1c8a1SJohn Marino 	c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);
602f5b1c8a1SJohn Marino 	neg = 0;
603f5b1c8a1SJohn Marino 	switch (c1 * 3 + c2) {
604f5b1c8a1SJohn Marino 	case -4:
605f5b1c8a1SJohn Marino 		bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
606f5b1c8a1SJohn Marino 		bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
607f5b1c8a1SJohn Marino 		break;
608f5b1c8a1SJohn Marino 	case -3:
609f5b1c8a1SJohn Marino 		/* break; */
610f5b1c8a1SJohn Marino 	case -2:
611f5b1c8a1SJohn Marino 		bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */
612f5b1c8a1SJohn Marino 		bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */
613f5b1c8a1SJohn Marino 		neg = 1;
614f5b1c8a1SJohn Marino 		break;
615f5b1c8a1SJohn Marino 	case -1:
616f5b1c8a1SJohn Marino 	case 0:
617f5b1c8a1SJohn Marino 	case 1:
618f5b1c8a1SJohn Marino 		/* break; */
619f5b1c8a1SJohn Marino 	case 2:
620f5b1c8a1SJohn Marino 		bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */
621f5b1c8a1SJohn Marino 		bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */
622f5b1c8a1SJohn Marino 		neg = 1;
623f5b1c8a1SJohn Marino 		break;
624f5b1c8a1SJohn Marino 	case 3:
625f5b1c8a1SJohn Marino 		/* break; */
626f5b1c8a1SJohn Marino 	case 4:
627f5b1c8a1SJohn Marino 		bn_sub_part_words(t, a, &(a[n]), tna, n - tna);
628f5b1c8a1SJohn Marino 		bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);
629f5b1c8a1SJohn Marino 		break;
630f5b1c8a1SJohn Marino 	}
631f5b1c8a1SJohn Marino 		/* The zero case isn't yet implemented here. The speedup
632f5b1c8a1SJohn Marino 		   would probably be negligible. */
633f5b1c8a1SJohn Marino # if 0
634f5b1c8a1SJohn Marino 	if (n == 4) {
635f5b1c8a1SJohn Marino 		bn_mul_comba4(&(t[n2]), t, &(t[n]));
636f5b1c8a1SJohn Marino 		bn_mul_comba4(r, a, b);
637f5b1c8a1SJohn Marino 		bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn);
638f5b1c8a1SJohn Marino 		memset(&(r[n2 + tn * 2]), 0, sizeof(BN_ULONG) * (n2 - tn * 2));
639f5b1c8a1SJohn Marino 	} else
640f5b1c8a1SJohn Marino # endif
641f5b1c8a1SJohn Marino 		if (n == 8) {
642f5b1c8a1SJohn Marino 		bn_mul_comba8(&(t[n2]), t, &(t[n]));
643f5b1c8a1SJohn Marino 		bn_mul_comba8(r, a, b);
644f5b1c8a1SJohn Marino 		bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
645f5b1c8a1SJohn Marino 		memset(&(r[n2 + tna + tnb]), 0,
646f5b1c8a1SJohn Marino 		    sizeof(BN_ULONG) * (n2 - tna - tnb));
647f5b1c8a1SJohn Marino 	} else {
648f5b1c8a1SJohn Marino 		p = &(t[n2*2]);
649f5b1c8a1SJohn Marino 		bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
650f5b1c8a1SJohn Marino 		bn_mul_recursive(r, a, b, n, 0, 0, p);
651f5b1c8a1SJohn Marino 		i = n / 2;
652f5b1c8a1SJohn Marino 		/* If there is only a bottom half to the number,
653f5b1c8a1SJohn Marino 		 * just do it */
654f5b1c8a1SJohn Marino 		if (tna > tnb)
655f5b1c8a1SJohn Marino 			j = tna - i;
656f5b1c8a1SJohn Marino 		else
657f5b1c8a1SJohn Marino 			j = tnb - i;
658f5b1c8a1SJohn Marino 		if (j == 0) {
659f5b1c8a1SJohn Marino 			bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]),
660f5b1c8a1SJohn Marino 			    i, tna - i, tnb - i, p);
661f5b1c8a1SJohn Marino 			memset(&(r[n2 + i * 2]), 0,
662f5b1c8a1SJohn Marino 			    sizeof(BN_ULONG) * (n2 - i * 2));
663f5b1c8a1SJohn Marino 		}
664f5b1c8a1SJohn Marino 		else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */
665f5b1c8a1SJohn Marino 		{
666f5b1c8a1SJohn Marino 			bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]),
667f5b1c8a1SJohn Marino 			    i, tna - i, tnb - i, p);
668f5b1c8a1SJohn Marino 			memset(&(r[n2 + tna + tnb]), 0,
669f5b1c8a1SJohn Marino 			    sizeof(BN_ULONG) * (n2 - tna - tnb));
670f5b1c8a1SJohn Marino 		}
671f5b1c8a1SJohn Marino 		else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
672f5b1c8a1SJohn Marino 		{
673f5b1c8a1SJohn Marino 			memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2);
674f5b1c8a1SJohn Marino 			if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL &&
675f5b1c8a1SJohn Marino 			    tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) {
676f5b1c8a1SJohn Marino 				bn_mul_normal(&(r[n2]), &(a[n]), tna,
677f5b1c8a1SJohn Marino 				    &(b[n]), tnb);
678f5b1c8a1SJohn Marino 			} else {
679f5b1c8a1SJohn Marino 				for (;;) {
680f5b1c8a1SJohn Marino 					i /= 2;
681f5b1c8a1SJohn Marino 					/* these simplified conditions work
682f5b1c8a1SJohn Marino 					 * exclusively because difference
683f5b1c8a1SJohn Marino 					 * between tna and tnb is 1 or 0 */
684f5b1c8a1SJohn Marino 					if (i < tna || i < tnb) {
685f5b1c8a1SJohn Marino 						bn_mul_part_recursive(&(r[n2]),
686f5b1c8a1SJohn Marino 						    &(a[n]), &(b[n]), i,
687f5b1c8a1SJohn Marino 						    tna - i, tnb - i, p);
688f5b1c8a1SJohn Marino 						break;
689f5b1c8a1SJohn Marino 					} else if (i == tna || i == tnb) {
690f5b1c8a1SJohn Marino 						bn_mul_recursive(&(r[n2]),
691f5b1c8a1SJohn Marino 						    &(a[n]), &(b[n]), i,
692f5b1c8a1SJohn Marino 						    tna - i, tnb - i, p);
693f5b1c8a1SJohn Marino 						break;
694f5b1c8a1SJohn Marino 					}
695f5b1c8a1SJohn Marino 				}
696f5b1c8a1SJohn Marino 			}
697f5b1c8a1SJohn Marino 		}
698f5b1c8a1SJohn Marino 	}
699f5b1c8a1SJohn Marino 
700f5b1c8a1SJohn Marino 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
701f5b1c8a1SJohn Marino 	 * r[10] holds (a[0]*b[0])
702f5b1c8a1SJohn Marino 	 * r[32] holds (b[1]*b[1])
703f5b1c8a1SJohn Marino 	 */
704f5b1c8a1SJohn Marino 
705f5b1c8a1SJohn Marino 	c1 = (int)(bn_add_words(t, r,&(r[n2]), n2));
706f5b1c8a1SJohn Marino 
707f5b1c8a1SJohn Marino 	if (neg) /* if t[32] is negative */
708f5b1c8a1SJohn Marino 	{
709f5b1c8a1SJohn Marino 		c1 -= (int)(bn_sub_words(&(t[n2]), t,&(t[n2]), n2));
710f5b1c8a1SJohn Marino 	} else {
711f5b1c8a1SJohn Marino 		/* Might have a carry */
712f5b1c8a1SJohn Marino 		c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));
713f5b1c8a1SJohn Marino 	}
714f5b1c8a1SJohn Marino 
715f5b1c8a1SJohn Marino 	/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
716f5b1c8a1SJohn Marino 	 * r[10] holds (a[0]*b[0])
717f5b1c8a1SJohn Marino 	 * r[32] holds (b[1]*b[1])
718f5b1c8a1SJohn Marino 	 * c1 holds the carry bits
719f5b1c8a1SJohn Marino 	 */
720f5b1c8a1SJohn Marino 	c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
721f5b1c8a1SJohn Marino 	if (c1) {
722f5b1c8a1SJohn Marino 		p = &(r[n + n2]);
723f5b1c8a1SJohn Marino 		lo= *p;
724f5b1c8a1SJohn Marino 		ln = (lo + c1)&BN_MASK2;
725f5b1c8a1SJohn Marino 		*p = ln;
726f5b1c8a1SJohn Marino 
727f5b1c8a1SJohn Marino 		/* The overflow will stop before we over write
728f5b1c8a1SJohn Marino 		 * words we should not overwrite */
729f5b1c8a1SJohn Marino 		if (ln < (BN_ULONG)c1) {
730f5b1c8a1SJohn Marino 			do {
731f5b1c8a1SJohn Marino 				p++;
732f5b1c8a1SJohn Marino 				lo= *p;
733f5b1c8a1SJohn Marino 				ln = (lo + 1) & BN_MASK2;
734f5b1c8a1SJohn Marino 				*p = ln;
735f5b1c8a1SJohn Marino 			} while (ln == 0);
736f5b1c8a1SJohn Marino 		}
737f5b1c8a1SJohn Marino 	}
738f5b1c8a1SJohn Marino }
739f5b1c8a1SJohn Marino 
740f5b1c8a1SJohn Marino /* a and b must be the same size, which is n2.
741f5b1c8a1SJohn Marino  * r needs to be n2 words and t needs to be n2*2
742f5b1c8a1SJohn Marino  */
743f5b1c8a1SJohn Marino void
bn_mul_low_recursive(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,int n2,BN_ULONG * t)744f5b1c8a1SJohn Marino bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, BN_ULONG *t)
745f5b1c8a1SJohn Marino {
746f5b1c8a1SJohn Marino 	int n = n2 / 2;
747f5b1c8a1SJohn Marino 
748f5b1c8a1SJohn Marino # ifdef BN_COUNT
749f5b1c8a1SJohn Marino 	fprintf(stderr, " bn_mul_low_recursive %d * %d\n",n2,n2);
750f5b1c8a1SJohn Marino # endif
751f5b1c8a1SJohn Marino 
752f5b1c8a1SJohn Marino 	bn_mul_recursive(r, a, b, n, 0, 0, &(t[0]));
753f5b1c8a1SJohn Marino 	if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) {
754f5b1c8a1SJohn Marino 		bn_mul_low_recursive(&(t[0]), &(a[0]), &(b[n]), n, &(t[n2]));
755f5b1c8a1SJohn Marino 		bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);
756f5b1c8a1SJohn Marino 		bn_mul_low_recursive(&(t[0]), &(a[n]), &(b[0]), n, &(t[n2]));
757f5b1c8a1SJohn Marino 		bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);
758f5b1c8a1SJohn Marino 	} else {
759f5b1c8a1SJohn Marino 		bn_mul_low_normal(&(t[0]), &(a[0]), &(b[n]), n);
760f5b1c8a1SJohn Marino 		bn_mul_low_normal(&(t[n]), &(a[n]), &(b[0]), n);
761f5b1c8a1SJohn Marino 		bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);
762f5b1c8a1SJohn Marino 		bn_add_words(&(r[n]), &(r[n]), &(t[n]), n);
763f5b1c8a1SJohn Marino 	}
764f5b1c8a1SJohn Marino }
765f5b1c8a1SJohn Marino 
766f5b1c8a1SJohn Marino /* a and b must be the same size, which is n2.
767f5b1c8a1SJohn Marino  * r needs to be n2 words and t needs to be n2*2
768f5b1c8a1SJohn Marino  * l is the low words of the output.
769f5b1c8a1SJohn Marino  * t needs to be n2*3
770f5b1c8a1SJohn Marino  */
771f5b1c8a1SJohn Marino void
bn_mul_high(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,BN_ULONG * l,int n2,BN_ULONG * t)772f5b1c8a1SJohn Marino bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2,
773f5b1c8a1SJohn Marino     BN_ULONG *t)
774f5b1c8a1SJohn Marino {
775f5b1c8a1SJohn Marino 	int i, n;
776f5b1c8a1SJohn Marino 	int c1, c2;
777f5b1c8a1SJohn Marino 	int neg, oneg, zero;
778f5b1c8a1SJohn Marino 	BN_ULONG ll, lc, *lp, *mp;
779f5b1c8a1SJohn Marino 
780f5b1c8a1SJohn Marino # ifdef BN_COUNT
781f5b1c8a1SJohn Marino 	fprintf(stderr, " bn_mul_high %d * %d\n",n2,n2);
782f5b1c8a1SJohn Marino # endif
783f5b1c8a1SJohn Marino 	n = n2 / 2;
784f5b1c8a1SJohn Marino 
785f5b1c8a1SJohn Marino 	/* Calculate (al-ah)*(bh-bl) */
786f5b1c8a1SJohn Marino 	neg = zero = 0;
787f5b1c8a1SJohn Marino 	c1 = bn_cmp_words(&(a[0]), &(a[n]), n);
788f5b1c8a1SJohn Marino 	c2 = bn_cmp_words(&(b[n]), &(b[0]), n);
789f5b1c8a1SJohn Marino 	switch (c1 * 3 + c2) {
790f5b1c8a1SJohn Marino 	case -4:
791f5b1c8a1SJohn Marino 		bn_sub_words(&(r[0]), &(a[n]), &(a[0]), n);
792f5b1c8a1SJohn Marino 		bn_sub_words(&(r[n]), &(b[0]), &(b[n]), n);
793f5b1c8a1SJohn Marino 		break;
794f5b1c8a1SJohn Marino 	case -3:
795f5b1c8a1SJohn Marino 		zero = 1;
796f5b1c8a1SJohn Marino 		break;
797f5b1c8a1SJohn Marino 	case -2:
798f5b1c8a1SJohn Marino 		bn_sub_words(&(r[0]), &(a[n]), &(a[0]), n);
799f5b1c8a1SJohn Marino 		bn_sub_words(&(r[n]), &(b[n]), &(b[0]), n);
800f5b1c8a1SJohn Marino 		neg = 1;
801f5b1c8a1SJohn Marino 		break;
802f5b1c8a1SJohn Marino 	case -1:
803f5b1c8a1SJohn Marino 	case 0:
804f5b1c8a1SJohn Marino 	case 1:
805f5b1c8a1SJohn Marino 		zero = 1;
806f5b1c8a1SJohn Marino 		break;
807f5b1c8a1SJohn Marino 	case 2:
808f5b1c8a1SJohn Marino 		bn_sub_words(&(r[0]), &(a[0]), &(a[n]), n);
809f5b1c8a1SJohn Marino 		bn_sub_words(&(r[n]), &(b[0]), &(b[n]), n);
810f5b1c8a1SJohn Marino 		neg = 1;
811f5b1c8a1SJohn Marino 		break;
812f5b1c8a1SJohn Marino 	case 3:
813f5b1c8a1SJohn Marino 		zero = 1;
814f5b1c8a1SJohn Marino 		break;
815f5b1c8a1SJohn Marino 	case 4:
816f5b1c8a1SJohn Marino 		bn_sub_words(&(r[0]), &(a[0]), &(a[n]), n);
817f5b1c8a1SJohn Marino 		bn_sub_words(&(r[n]), &(b[n]), &(b[0]), n);
818f5b1c8a1SJohn Marino 		break;
819f5b1c8a1SJohn Marino 	}
820f5b1c8a1SJohn Marino 
821f5b1c8a1SJohn Marino 	oneg = neg;
822f5b1c8a1SJohn Marino 	/* t[10] = (a[0]-a[1])*(b[1]-b[0]) */
823f5b1c8a1SJohn Marino 	/* r[10] = (a[1]*b[1]) */
824f5b1c8a1SJohn Marino # ifdef BN_MUL_COMBA
825f5b1c8a1SJohn Marino 	if (n == 8) {
826f5b1c8a1SJohn Marino 		bn_mul_comba8(&(t[0]), &(r[0]), &(r[n]));
827f5b1c8a1SJohn Marino 		bn_mul_comba8(r, &(a[n]), &(b[n]));
828f5b1c8a1SJohn Marino 	} else
829f5b1c8a1SJohn Marino # endif
830f5b1c8a1SJohn Marino 	{
831f5b1c8a1SJohn Marino 		bn_mul_recursive(&(t[0]), &(r[0]), &(r[n]), n, 0, 0, &(t[n2]));
832f5b1c8a1SJohn Marino 		bn_mul_recursive(r, &(a[n]), &(b[n]), n, 0, 0, &(t[n2]));
833f5b1c8a1SJohn Marino 	}
834f5b1c8a1SJohn Marino 
835f5b1c8a1SJohn Marino 	/* s0 == low(al*bl)
836f5b1c8a1SJohn Marino 	 * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
837f5b1c8a1SJohn Marino 	 * We know s0 and s1 so the only unknown is high(al*bl)
838f5b1c8a1SJohn Marino 	 * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl))
839f5b1c8a1SJohn Marino 	 * high(al*bl) == s1 - (r[0]+l[0]+t[0])
840f5b1c8a1SJohn Marino 	 */
841f5b1c8a1SJohn Marino 	if (l != NULL) {
842f5b1c8a1SJohn Marino 		lp = &(t[n2 + n]);
843f5b1c8a1SJohn Marino 		c1 = (int)(bn_add_words(lp, &(r[0]), &(l[0]), n));
844f5b1c8a1SJohn Marino 	} else {
845f5b1c8a1SJohn Marino 		c1 = 0;
846f5b1c8a1SJohn Marino 		lp = &(r[0]);
847f5b1c8a1SJohn Marino 	}
848f5b1c8a1SJohn Marino 
849f5b1c8a1SJohn Marino 	if (neg)
850f5b1c8a1SJohn Marino 		neg = (int)(bn_sub_words(&(t[n2]), lp, &(t[0]), n));
851f5b1c8a1SJohn Marino 	else {
852f5b1c8a1SJohn Marino 		bn_add_words(&(t[n2]), lp, &(t[0]), n);
853f5b1c8a1SJohn Marino 		neg = 0;
854f5b1c8a1SJohn Marino 	}
855f5b1c8a1SJohn Marino 
856f5b1c8a1SJohn Marino 	if (l != NULL) {
857f5b1c8a1SJohn Marino 		bn_sub_words(&(t[n2 + n]), &(l[n]), &(t[n2]), n);
858f5b1c8a1SJohn Marino 	} else {
859f5b1c8a1SJohn Marino 		lp = &(t[n2 + n]);
860f5b1c8a1SJohn Marino 		mp = &(t[n2]);
861f5b1c8a1SJohn Marino 		for (i = 0; i < n; i++)
862f5b1c8a1SJohn Marino 			lp[i] = ((~mp[i]) + 1) & BN_MASK2;
863f5b1c8a1SJohn Marino 	}
864f5b1c8a1SJohn Marino 
865f5b1c8a1SJohn Marino 	/* s[0] = low(al*bl)
866f5b1c8a1SJohn Marino 	 * t[3] = high(al*bl)
867f5b1c8a1SJohn Marino 	 * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign
868f5b1c8a1SJohn Marino 	 * r[10] = (a[1]*b[1])
869f5b1c8a1SJohn Marino 	 */
870f5b1c8a1SJohn Marino 	/* R[10] = al*bl
871f5b1c8a1SJohn Marino 	 * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0])
872f5b1c8a1SJohn Marino 	 * R[32] = ah*bh
873f5b1c8a1SJohn Marino 	 */
874f5b1c8a1SJohn Marino 	/* R[1]=t[3]+l[0]+r[0](+-)t[0] (have carry/borrow)
875f5b1c8a1SJohn Marino 	 * R[2]=r[0]+t[3]+r[1](+-)t[1] (have carry/borrow)
876f5b1c8a1SJohn Marino 	 * R[3]=r[1]+(carry/borrow)
877f5b1c8a1SJohn Marino 	 */
878f5b1c8a1SJohn Marino 	if (l != NULL) {
879f5b1c8a1SJohn Marino 		lp = &(t[n2]);
880f5b1c8a1SJohn Marino 		c1 = (int)(bn_add_words(lp, &(t[n2 + n]), &(l[0]), n));
881f5b1c8a1SJohn Marino 	} else {
882f5b1c8a1SJohn Marino 		lp = &(t[n2 + n]);
883f5b1c8a1SJohn Marino 		c1 = 0;
884f5b1c8a1SJohn Marino 	}
885f5b1c8a1SJohn Marino 	c1 += (int)(bn_add_words(&(t[n2]), lp, &(r[0]), n));
886f5b1c8a1SJohn Marino 	if (oneg)
887f5b1c8a1SJohn Marino 		c1 -= (int)(bn_sub_words(&(t[n2]), &(t[n2]), &(t[0]), n));
888f5b1c8a1SJohn Marino 	else
889f5b1c8a1SJohn Marino 		c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), &(t[0]), n));
890f5b1c8a1SJohn Marino 
891f5b1c8a1SJohn Marino 	c2 = (int)(bn_add_words(&(r[0]), &(r[0]), &(t[n2 + n]), n));
892f5b1c8a1SJohn Marino 	c2 += (int)(bn_add_words(&(r[0]), &(r[0]), &(r[n]), n));
893f5b1c8a1SJohn Marino 	if (oneg)
894f5b1c8a1SJohn Marino 		c2 -= (int)(bn_sub_words(&(r[0]), &(r[0]), &(t[n]), n));
895f5b1c8a1SJohn Marino 	else
896f5b1c8a1SJohn Marino 		c2 += (int)(bn_add_words(&(r[0]), &(r[0]), &(t[n]), n));
897f5b1c8a1SJohn Marino 
898f5b1c8a1SJohn Marino 	if (c1 != 0) /* Add starting at r[0], could be +ve or -ve */
899f5b1c8a1SJohn Marino 	{
900f5b1c8a1SJohn Marino 		i = 0;
901f5b1c8a1SJohn Marino 		if (c1 > 0) {
902f5b1c8a1SJohn Marino 			lc = c1;
903f5b1c8a1SJohn Marino 			do {
904f5b1c8a1SJohn Marino 				ll = (r[i] + lc) & BN_MASK2;
905f5b1c8a1SJohn Marino 				r[i++] = ll;
906f5b1c8a1SJohn Marino 				lc = (lc > ll);
907f5b1c8a1SJohn Marino 			} while (lc);
908f5b1c8a1SJohn Marino 		} else {
909f5b1c8a1SJohn Marino 			lc = -c1;
910f5b1c8a1SJohn Marino 			do {
911f5b1c8a1SJohn Marino 				ll = r[i];
912f5b1c8a1SJohn Marino 				r[i++] = (ll - lc) & BN_MASK2;
913f5b1c8a1SJohn Marino 				lc = (lc > ll);
914f5b1c8a1SJohn Marino 			} while (lc);
915f5b1c8a1SJohn Marino 		}
916f5b1c8a1SJohn Marino 	}
917f5b1c8a1SJohn Marino 	if (c2 != 0) /* Add starting at r[1] */
918f5b1c8a1SJohn Marino 	{
919f5b1c8a1SJohn Marino 		i = n;
920f5b1c8a1SJohn Marino 		if (c2 > 0) {
921f5b1c8a1SJohn Marino 			lc = c2;
922f5b1c8a1SJohn Marino 			do {
923f5b1c8a1SJohn Marino 				ll = (r[i] + lc) & BN_MASK2;
924f5b1c8a1SJohn Marino 				r[i++] = ll;
925f5b1c8a1SJohn Marino 				lc = (lc > ll);
926f5b1c8a1SJohn Marino 			} while (lc);
927f5b1c8a1SJohn Marino 		} else {
928f5b1c8a1SJohn Marino 			lc = -c2;
929f5b1c8a1SJohn Marino 			do {
930f5b1c8a1SJohn Marino 				ll = r[i];
931f5b1c8a1SJohn Marino 				r[i++] = (ll - lc) & BN_MASK2;
932f5b1c8a1SJohn Marino 				lc = (lc > ll);
933f5b1c8a1SJohn Marino 			} while (lc);
934f5b1c8a1SJohn Marino 		}
935f5b1c8a1SJohn Marino 	}
936f5b1c8a1SJohn Marino }
937f5b1c8a1SJohn Marino #endif /* BN_RECURSION */
938f5b1c8a1SJohn Marino 
939f5b1c8a1SJohn Marino int
BN_mul(BIGNUM * r,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)940f5b1c8a1SJohn Marino BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
941f5b1c8a1SJohn Marino {
942f5b1c8a1SJohn Marino 	int ret = 0;
943f5b1c8a1SJohn Marino 	int top, al, bl;
944f5b1c8a1SJohn Marino 	BIGNUM *rr;
945f5b1c8a1SJohn Marino #if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
946f5b1c8a1SJohn Marino 	int i;
947f5b1c8a1SJohn Marino #endif
948f5b1c8a1SJohn Marino #ifdef BN_RECURSION
949f5b1c8a1SJohn Marino 	BIGNUM *t = NULL;
950f5b1c8a1SJohn Marino 	int j = 0, k;
951f5b1c8a1SJohn Marino #endif
952f5b1c8a1SJohn Marino 
953f5b1c8a1SJohn Marino #ifdef BN_COUNT
954f5b1c8a1SJohn Marino 	fprintf(stderr, "BN_mul %d * %d\n",a->top,b->top);
955f5b1c8a1SJohn Marino #endif
956f5b1c8a1SJohn Marino 
957f5b1c8a1SJohn Marino 	bn_check_top(a);
958f5b1c8a1SJohn Marino 	bn_check_top(b);
959f5b1c8a1SJohn Marino 	bn_check_top(r);
960f5b1c8a1SJohn Marino 
961f5b1c8a1SJohn Marino 	al = a->top;
962f5b1c8a1SJohn Marino 	bl = b->top;
963f5b1c8a1SJohn Marino 
964f5b1c8a1SJohn Marino 	if ((al == 0) || (bl == 0)) {
965f5b1c8a1SJohn Marino 		BN_zero(r);
966f5b1c8a1SJohn Marino 		return (1);
967f5b1c8a1SJohn Marino 	}
968f5b1c8a1SJohn Marino 	top = al + bl;
969f5b1c8a1SJohn Marino 
970f5b1c8a1SJohn Marino 	BN_CTX_start(ctx);
971f5b1c8a1SJohn Marino 	if ((r == a) || (r == b)) {
972f5b1c8a1SJohn Marino 		if ((rr = BN_CTX_get(ctx)) == NULL)
973f5b1c8a1SJohn Marino 			goto err;
974f5b1c8a1SJohn Marino 	} else
975f5b1c8a1SJohn Marino 		rr = r;
976f5b1c8a1SJohn Marino 	rr->neg = a->neg ^ b->neg;
977f5b1c8a1SJohn Marino 
978f5b1c8a1SJohn Marino #if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
979f5b1c8a1SJohn Marino 	i = al - bl;
980f5b1c8a1SJohn Marino #endif
981f5b1c8a1SJohn Marino #ifdef BN_MUL_COMBA
982f5b1c8a1SJohn Marino 	if (i == 0) {
983f5b1c8a1SJohn Marino # if 0
984f5b1c8a1SJohn Marino 		if (al == 4) {
985f5b1c8a1SJohn Marino 			if (bn_wexpand(rr, 8) == NULL)
986f5b1c8a1SJohn Marino 				goto err;
987f5b1c8a1SJohn Marino 			rr->top = 8;
988f5b1c8a1SJohn Marino 			bn_mul_comba4(rr->d, a->d, b->d);
989f5b1c8a1SJohn Marino 			goto end;
990f5b1c8a1SJohn Marino 		}
991f5b1c8a1SJohn Marino # endif
992f5b1c8a1SJohn Marino 		if (al == 8) {
993f5b1c8a1SJohn Marino 			if (bn_wexpand(rr, 16) == NULL)
994f5b1c8a1SJohn Marino 				goto err;
995f5b1c8a1SJohn Marino 			rr->top = 16;
996f5b1c8a1SJohn Marino 			bn_mul_comba8(rr->d, a->d, b->d);
997f5b1c8a1SJohn Marino 			goto end;
998f5b1c8a1SJohn Marino 		}
999f5b1c8a1SJohn Marino 	}
1000f5b1c8a1SJohn Marino #endif /* BN_MUL_COMBA */
1001f5b1c8a1SJohn Marino #ifdef BN_RECURSION
1002f5b1c8a1SJohn Marino 	if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {
1003f5b1c8a1SJohn Marino 		if (i >= -1 && i <= 1) {
1004f5b1c8a1SJohn Marino 			/* Find out the power of two lower or equal
1005f5b1c8a1SJohn Marino 			   to the longest of the two numbers */
1006f5b1c8a1SJohn Marino 			if (i >= 0) {
1007f5b1c8a1SJohn Marino 				j = BN_num_bits_word((BN_ULONG)al);
1008f5b1c8a1SJohn Marino 			}
1009f5b1c8a1SJohn Marino 			if (i == -1) {
1010f5b1c8a1SJohn Marino 				j = BN_num_bits_word((BN_ULONG)bl);
1011f5b1c8a1SJohn Marino 			}
1012f5b1c8a1SJohn Marino 			j = 1 << (j - 1);
1013f5b1c8a1SJohn Marino 			assert(j <= al || j <= bl);
1014f5b1c8a1SJohn Marino 			k = j + j;
1015f5b1c8a1SJohn Marino 			if ((t = BN_CTX_get(ctx)) == NULL)
1016f5b1c8a1SJohn Marino 				goto err;
1017f5b1c8a1SJohn Marino 			if (al > j || bl > j) {
1018f5b1c8a1SJohn Marino 				if (bn_wexpand(t, k * 4) == NULL)
1019f5b1c8a1SJohn Marino 					goto err;
1020f5b1c8a1SJohn Marino 				if (bn_wexpand(rr, k * 4) == NULL)
1021f5b1c8a1SJohn Marino 					goto err;
1022f5b1c8a1SJohn Marino 				bn_mul_part_recursive(rr->d, a->d, b->d,
1023f5b1c8a1SJohn Marino 				    j, al - j, bl - j, t->d);
1024f5b1c8a1SJohn Marino 			}
1025f5b1c8a1SJohn Marino 			else	/* al <= j || bl <= j */
1026f5b1c8a1SJohn Marino 			{
1027f5b1c8a1SJohn Marino 				if (bn_wexpand(t, k * 2) == NULL)
1028f5b1c8a1SJohn Marino 					goto err;
1029f5b1c8a1SJohn Marino 				if (bn_wexpand(rr, k * 2) == NULL)
1030f5b1c8a1SJohn Marino 					goto err;
1031f5b1c8a1SJohn Marino 				bn_mul_recursive(rr->d, a->d, b->d,
1032f5b1c8a1SJohn Marino 				    j, al - j, bl - j, t->d);
1033f5b1c8a1SJohn Marino 			}
1034f5b1c8a1SJohn Marino 			rr->top = top;
1035f5b1c8a1SJohn Marino 			goto end;
1036f5b1c8a1SJohn Marino 		}
1037f5b1c8a1SJohn Marino #if 0
1038f5b1c8a1SJohn Marino 		if (i == 1 && !BN_get_flags(b, BN_FLG_STATIC_DATA)) {
1039f5b1c8a1SJohn Marino 			BIGNUM *tmp_bn = (BIGNUM *)b;
1040f5b1c8a1SJohn Marino 			if (bn_wexpand(tmp_bn, al) == NULL)
1041f5b1c8a1SJohn Marino 				goto err;
1042f5b1c8a1SJohn Marino 			tmp_bn->d[bl] = 0;
1043f5b1c8a1SJohn Marino 			bl++;
1044f5b1c8a1SJohn Marino 			i--;
1045f5b1c8a1SJohn Marino 		} else if (i == -1 && !BN_get_flags(a, BN_FLG_STATIC_DATA)) {
1046f5b1c8a1SJohn Marino 			BIGNUM *tmp_bn = (BIGNUM *)a;
1047f5b1c8a1SJohn Marino 			if (bn_wexpand(tmp_bn, bl) == NULL)
1048f5b1c8a1SJohn Marino 				goto err;
1049f5b1c8a1SJohn Marino 			tmp_bn->d[al] = 0;
1050f5b1c8a1SJohn Marino 			al++;
1051f5b1c8a1SJohn Marino 			i++;
1052f5b1c8a1SJohn Marino 		}
1053f5b1c8a1SJohn Marino 		if (i == 0) {
1054f5b1c8a1SJohn Marino 			/* symmetric and > 4 */
1055f5b1c8a1SJohn Marino 			/* 16 or larger */
1056f5b1c8a1SJohn Marino 			j = BN_num_bits_word((BN_ULONG)al);
1057f5b1c8a1SJohn Marino 			j = 1 << (j - 1);
1058f5b1c8a1SJohn Marino 			k = j + j;
1059f5b1c8a1SJohn Marino 			if ((t = BN_CTX_get(ctx)) == NULL)
1060f5b1c8a1SJohn Marino 				goto err;
1061f5b1c8a1SJohn Marino 			if (al == j) /* exact multiple */
1062f5b1c8a1SJohn Marino 			{
1063f5b1c8a1SJohn Marino 				if (bn_wexpand(t, k * 2) == NULL)
1064f5b1c8a1SJohn Marino 					goto err;
1065f5b1c8a1SJohn Marino 				if (bn_wexpand(rr, k * 2) == NULL)
1066f5b1c8a1SJohn Marino 					goto err;
1067f5b1c8a1SJohn Marino 				bn_mul_recursive(rr->d, a->d, b->d, al, t->d);
1068f5b1c8a1SJohn Marino 			} else {
1069f5b1c8a1SJohn Marino 				if (bn_wexpand(t, k * 4) == NULL)
1070f5b1c8a1SJohn Marino 					goto err;
1071f5b1c8a1SJohn Marino 				if (bn_wexpand(rr, k * 4) == NULL)
1072f5b1c8a1SJohn Marino 					goto err;
1073f5b1c8a1SJohn Marino 				bn_mul_part_recursive(rr->d, a->d, b->d,
1074f5b1c8a1SJohn Marino 				    al - j, j, t->d);
1075f5b1c8a1SJohn Marino 			}
1076f5b1c8a1SJohn Marino 			rr->top = top;
1077f5b1c8a1SJohn Marino 			goto end;
1078f5b1c8a1SJohn Marino 		}
1079f5b1c8a1SJohn Marino #endif
1080f5b1c8a1SJohn Marino 	}
1081f5b1c8a1SJohn Marino #endif /* BN_RECURSION */
1082f5b1c8a1SJohn Marino 	if (bn_wexpand(rr, top) == NULL)
1083f5b1c8a1SJohn Marino 		goto err;
1084f5b1c8a1SJohn Marino 	rr->top = top;
1085f5b1c8a1SJohn Marino 	bn_mul_normal(rr->d, a->d, al, b->d, bl);
1086f5b1c8a1SJohn Marino 
1087f5b1c8a1SJohn Marino #if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
1088f5b1c8a1SJohn Marino end:
1089f5b1c8a1SJohn Marino #endif
1090f5b1c8a1SJohn Marino 	bn_correct_top(rr);
1091f5b1c8a1SJohn Marino 	if (r != rr)
1092f5b1c8a1SJohn Marino 		BN_copy(r, rr);
1093f5b1c8a1SJohn Marino 	ret = 1;
1094f5b1c8a1SJohn Marino err:
1095f5b1c8a1SJohn Marino 	bn_check_top(r);
1096f5b1c8a1SJohn Marino 	BN_CTX_end(ctx);
1097f5b1c8a1SJohn Marino 	return (ret);
1098f5b1c8a1SJohn Marino }
1099f5b1c8a1SJohn Marino 
1100f5b1c8a1SJohn Marino void
bn_mul_normal(BN_ULONG * r,BN_ULONG * a,int na,BN_ULONG * b,int nb)1101f5b1c8a1SJohn Marino bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
1102f5b1c8a1SJohn Marino {
1103f5b1c8a1SJohn Marino 	BN_ULONG *rr;
1104f5b1c8a1SJohn Marino 
1105f5b1c8a1SJohn Marino #ifdef BN_COUNT
1106f5b1c8a1SJohn Marino 	fprintf(stderr, " bn_mul_normal %d * %d\n", na, nb);
1107f5b1c8a1SJohn Marino #endif
1108f5b1c8a1SJohn Marino 
1109f5b1c8a1SJohn Marino 	if (na < nb) {
1110f5b1c8a1SJohn Marino 		int itmp;
1111f5b1c8a1SJohn Marino 		BN_ULONG *ltmp;
1112f5b1c8a1SJohn Marino 
1113f5b1c8a1SJohn Marino 		itmp = na;
1114f5b1c8a1SJohn Marino 		na = nb;
1115f5b1c8a1SJohn Marino 		nb = itmp;
1116f5b1c8a1SJohn Marino 		ltmp = a;
1117f5b1c8a1SJohn Marino 		a = b;
1118f5b1c8a1SJohn Marino 		b = ltmp;
1119f5b1c8a1SJohn Marino 
1120f5b1c8a1SJohn Marino 	}
1121f5b1c8a1SJohn Marino 	rr = &(r[na]);
1122f5b1c8a1SJohn Marino 	if (nb <= 0) {
1123f5b1c8a1SJohn Marino 		(void)bn_mul_words(r, a, na, 0);
1124f5b1c8a1SJohn Marino 		return;
1125f5b1c8a1SJohn Marino 	} else
1126f5b1c8a1SJohn Marino 		rr[0] = bn_mul_words(r, a, na, b[0]);
1127f5b1c8a1SJohn Marino 
1128f5b1c8a1SJohn Marino 	for (;;) {
1129f5b1c8a1SJohn Marino 		if (--nb <= 0)
1130f5b1c8a1SJohn Marino 			return;
1131f5b1c8a1SJohn Marino 		rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]);
1132f5b1c8a1SJohn Marino 		if (--nb <= 0)
1133f5b1c8a1SJohn Marino 			return;
1134f5b1c8a1SJohn Marino 		rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]);
1135f5b1c8a1SJohn Marino 		if (--nb <= 0)
1136f5b1c8a1SJohn Marino 			return;
1137f5b1c8a1SJohn Marino 		rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]);
1138f5b1c8a1SJohn Marino 		if (--nb <= 0)
1139f5b1c8a1SJohn Marino 			return;
1140f5b1c8a1SJohn Marino 		rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]);
1141f5b1c8a1SJohn Marino 		rr += 4;
1142f5b1c8a1SJohn Marino 		r += 4;
1143f5b1c8a1SJohn Marino 		b += 4;
1144f5b1c8a1SJohn Marino 	}
1145f5b1c8a1SJohn Marino }
1146f5b1c8a1SJohn Marino 
1147f5b1c8a1SJohn Marino void
bn_mul_low_normal(BN_ULONG * r,BN_ULONG * a,BN_ULONG * b,int n)1148f5b1c8a1SJohn Marino bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
1149f5b1c8a1SJohn Marino {
1150f5b1c8a1SJohn Marino #ifdef BN_COUNT
1151f5b1c8a1SJohn Marino 	fprintf(stderr, " bn_mul_low_normal %d * %d\n", n, n);
1152f5b1c8a1SJohn Marino #endif
1153f5b1c8a1SJohn Marino 	bn_mul_words(r, a, n, b[0]);
1154f5b1c8a1SJohn Marino 
1155f5b1c8a1SJohn Marino 	for (;;) {
1156f5b1c8a1SJohn Marino 		if (--n <= 0)
1157f5b1c8a1SJohn Marino 			return;
1158f5b1c8a1SJohn Marino 		bn_mul_add_words(&(r[1]), a, n, b[1]);
1159f5b1c8a1SJohn Marino 		if (--n <= 0)
1160f5b1c8a1SJohn Marino 			return;
1161f5b1c8a1SJohn Marino 		bn_mul_add_words(&(r[2]), a, n, b[2]);
1162f5b1c8a1SJohn Marino 		if (--n <= 0)
1163f5b1c8a1SJohn Marino 			return;
1164f5b1c8a1SJohn Marino 		bn_mul_add_words(&(r[3]), a, n, b[3]);
1165f5b1c8a1SJohn Marino 		if (--n <= 0)
1166f5b1c8a1SJohn Marino 			return;
1167f5b1c8a1SJohn Marino 		bn_mul_add_words(&(r[4]), a, n, b[4]);
1168f5b1c8a1SJohn Marino 		r += 4;
1169f5b1c8a1SJohn Marino 		b += 4;
1170f5b1c8a1SJohn Marino 	}
1171f5b1c8a1SJohn Marino }
1172