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