/src/libressl/crypto/bn/bn_mul.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD: bn_mul.c,v 1.20 2015/02/09 15:49:22 jsing Exp $ */ |
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 <assert.h> |
65 | | #include <stdio.h> |
66 | | #include <string.h> |
67 | | |
68 | | #include <openssl/opensslconf.h> |
69 | | |
70 | | #include "bn_lcl.h" |
71 | | |
72 | | #if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS) |
73 | | /* Here follows specialised variants of bn_add_words() and |
74 | | bn_sub_words(). They have the property performing operations on |
75 | | arrays of different sizes. The sizes of those arrays is expressed through |
76 | | cl, which is the common length ( basicall, min(len(a),len(b)) ), and dl, |
77 | | which is the delta between the two lengths, calculated as len(a)-len(b). |
78 | | All lengths are the number of BN_ULONGs... For the operations that require |
79 | | a result array as parameter, it must have the length cl+abs(dl). |
80 | | These functions should probably end up in bn_asm.c as soon as there are |
81 | | assembler counterparts for the systems that use assembler files. */ |
82 | | |
83 | | BN_ULONG |
84 | | bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int cl, |
85 | | int dl) |
86 | 519k | { |
87 | 519k | BN_ULONG c, t; |
88 | | |
89 | 519k | assert(cl >= 0); |
90 | 519k | c = bn_sub_words(r, a, b, cl); |
91 | | |
92 | 519k | if (dl == 0) |
93 | 302k | return c; |
94 | | |
95 | 216k | r += cl; |
96 | 216k | a += cl; |
97 | 216k | b += cl; |
98 | | |
99 | 216k | if (dl < 0) { |
100 | | #ifdef BN_COUNT |
101 | | fprintf(stderr, |
102 | | " bn_sub_part_words %d + %d (dl < 0, c = %d)\n", |
103 | | cl, dl, c); |
104 | | #endif |
105 | 48.8k | for (;;) { |
106 | 48.8k | t = b[0]; |
107 | 48.8k | r[0] = (0 - t - c) & BN_MASK2; |
108 | 48.8k | if (t != 0) |
109 | 0 | c = 1; |
110 | 48.8k | if (++dl >= 0) |
111 | 22.6k | break; |
112 | | |
113 | 26.2k | t = b[1]; |
114 | 26.2k | r[1] = (0 - t - c) & BN_MASK2; |
115 | 26.2k | if (t != 0) |
116 | 0 | c = 1; |
117 | 26.2k | if (++dl >= 0) |
118 | 957 | break; |
119 | | |
120 | 25.2k | t = b[2]; |
121 | 25.2k | r[2] = (0 - t - c) & BN_MASK2; |
122 | 25.2k | if (t != 0) |
123 | 0 | c = 1; |
124 | 25.2k | if (++dl >= 0) |
125 | 695 | break; |
126 | | |
127 | 24.5k | t = b[3]; |
128 | 24.5k | r[3] = (0 - t - c) & BN_MASK2; |
129 | 24.5k | if (t != 0) |
130 | 0 | c = 1; |
131 | 24.5k | if (++dl >= 0) |
132 | 159 | break; |
133 | | |
134 | 24.4k | b += 4; |
135 | 24.4k | r += 4; |
136 | 24.4k | } |
137 | 192k | } else { |
138 | 192k | int save_dl = dl; |
139 | | #ifdef BN_COUNT |
140 | | fprintf(stderr, |
141 | | " bn_sub_part_words %d + %d (dl > 0, c = %d)\n", |
142 | | cl, dl, c); |
143 | | #endif |
144 | 232k | while (c) { |
145 | 45.3k | t = a[0]; |
146 | 45.3k | r[0] = (t - c) & BN_MASK2; |
147 | 45.3k | if (t != 0) |
148 | 14.0k | c = 0; |
149 | 45.3k | if (--dl <= 0) |
150 | 3.76k | break; |
151 | | |
152 | 41.5k | t = a[1]; |
153 | 41.5k | r[1] = (t - c) & BN_MASK2; |
154 | 41.5k | if (t != 0) |
155 | 13.8k | c = 0; |
156 | 41.5k | if (--dl <= 0) |
157 | 489 | break; |
158 | | |
159 | 41.0k | t = a[2]; |
160 | 41.0k | r[2] = (t - c) & BN_MASK2; |
161 | 41.0k | if (t != 0) |
162 | 22.6k | c = 0; |
163 | 41.0k | if (--dl <= 0) |
164 | 468 | break; |
165 | | |
166 | 40.6k | t = a[3]; |
167 | 40.6k | r[3] = (t - c) & BN_MASK2; |
168 | 40.6k | if (t != 0) |
169 | 24.7k | c = 0; |
170 | 40.6k | if (--dl <= 0) |
171 | 382 | break; |
172 | | |
173 | 40.2k | save_dl = dl; |
174 | 40.2k | a += 4; |
175 | 40.2k | r += 4; |
176 | 40.2k | } |
177 | 192k | if (dl > 0) { |
178 | | #ifdef BN_COUNT |
179 | | fprintf(stderr, |
180 | | " bn_sub_part_words %d + %d (dl > 0, c == 0)\n", |
181 | | cl, dl); |
182 | | #endif |
183 | 187k | if (save_dl > dl) { |
184 | 0 | switch (save_dl - dl) { |
185 | 0 | case 1: |
186 | 0 | r[1] = a[1]; |
187 | 0 | if (--dl <= 0) |
188 | 0 | break; |
189 | 0 | case 2: |
190 | 0 | r[2] = a[2]; |
191 | 0 | if (--dl <= 0) |
192 | 0 | break; |
193 | 0 | case 3: |
194 | 0 | r[3] = a[3]; |
195 | 0 | if (--dl <= 0) |
196 | 0 | break; |
197 | 0 | } |
198 | 0 | a += 4; |
199 | 0 | r += 4; |
200 | 0 | } |
201 | 187k | } |
202 | 192k | if (dl > 0) { |
203 | | #ifdef BN_COUNT |
204 | | fprintf(stderr, |
205 | | " bn_sub_part_words %d + %d (dl > 0, copy)\n", |
206 | | cl, dl); |
207 | | #endif |
208 | 413k | for (;;) { |
209 | 413k | r[0] = a[0]; |
210 | 413k | if (--dl <= 0) |
211 | 140k | break; |
212 | 273k | r[1] = a[1]; |
213 | 273k | if (--dl <= 0) |
214 | 6.96k | break; |
215 | 266k | r[2] = a[2]; |
216 | 266k | if (--dl <= 0) |
217 | 27.1k | break; |
218 | 239k | r[3] = a[3]; |
219 | 239k | if (--dl <= 0) |
220 | 12.6k | break; |
221 | | |
222 | 226k | a += 4; |
223 | 226k | r += 4; |
224 | 226k | } |
225 | 187k | } |
226 | 192k | } |
227 | 216k | return c; |
228 | 216k | } |
229 | | #endif |
230 | | |
231 | | BN_ULONG |
232 | | bn_add_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int cl, |
233 | | int dl) |
234 | 0 | { |
235 | 0 | BN_ULONG c, l, t; |
236 | |
|
237 | 0 | assert(cl >= 0); |
238 | 0 | c = bn_add_words(r, a, b, cl); |
239 | |
|
240 | 0 | if (dl == 0) |
241 | 0 | return c; |
242 | | |
243 | 0 | r += cl; |
244 | 0 | a += cl; |
245 | 0 | b += cl; |
246 | |
|
247 | 0 | if (dl < 0) { |
248 | 0 | int save_dl = dl; |
249 | | #ifdef BN_COUNT |
250 | | fprintf(stderr, |
251 | | " bn_add_part_words %d + %d (dl < 0, c = %d)\n", |
252 | | cl, dl, c); |
253 | | #endif |
254 | 0 | while (c) { |
255 | 0 | l = (c + b[0]) & BN_MASK2; |
256 | 0 | c = (l < c); |
257 | 0 | r[0] = l; |
258 | 0 | if (++dl >= 0) |
259 | 0 | break; |
260 | | |
261 | 0 | l = (c + b[1]) & BN_MASK2; |
262 | 0 | c = (l < c); |
263 | 0 | r[1] = l; |
264 | 0 | if (++dl >= 0) |
265 | 0 | break; |
266 | | |
267 | 0 | l = (c + b[2]) & BN_MASK2; |
268 | 0 | c = (l < c); |
269 | 0 | r[2] = l; |
270 | 0 | if (++dl >= 0) |
271 | 0 | break; |
272 | | |
273 | 0 | l = (c + b[3]) & BN_MASK2; |
274 | 0 | c = (l < c); |
275 | 0 | r[3] = l; |
276 | 0 | if (++dl >= 0) |
277 | 0 | break; |
278 | | |
279 | 0 | save_dl = dl; |
280 | 0 | b += 4; |
281 | 0 | r += 4; |
282 | 0 | } |
283 | 0 | if (dl < 0) { |
284 | | #ifdef BN_COUNT |
285 | | fprintf(stderr, |
286 | | " bn_add_part_words %d + %d (dl < 0, c == 0)\n", |
287 | | cl, dl); |
288 | | #endif |
289 | 0 | if (save_dl < dl) { |
290 | 0 | switch (dl - save_dl) { |
291 | 0 | case 1: |
292 | 0 | r[1] = b[1]; |
293 | 0 | if (++dl >= 0) |
294 | 0 | break; |
295 | 0 | case 2: |
296 | 0 | r[2] = b[2]; |
297 | 0 | if (++dl >= 0) |
298 | 0 | break; |
299 | 0 | case 3: |
300 | 0 | r[3] = b[3]; |
301 | 0 | if (++dl >= 0) |
302 | 0 | break; |
303 | 0 | } |
304 | 0 | b += 4; |
305 | 0 | r += 4; |
306 | 0 | } |
307 | 0 | } |
308 | 0 | if (dl < 0) { |
309 | | #ifdef BN_COUNT |
310 | | fprintf(stderr, |
311 | | " bn_add_part_words %d + %d (dl < 0, copy)\n", |
312 | | cl, dl); |
313 | | #endif |
314 | 0 | for (;;) { |
315 | 0 | r[0] = b[0]; |
316 | 0 | if (++dl >= 0) |
317 | 0 | break; |
318 | 0 | r[1] = b[1]; |
319 | 0 | if (++dl >= 0) |
320 | 0 | break; |
321 | 0 | r[2] = b[2]; |
322 | 0 | if (++dl >= 0) |
323 | 0 | break; |
324 | 0 | r[3] = b[3]; |
325 | 0 | if (++dl >= 0) |
326 | 0 | break; |
327 | | |
328 | 0 | b += 4; |
329 | 0 | r += 4; |
330 | 0 | } |
331 | 0 | } |
332 | 0 | } else { |
333 | 0 | int save_dl = dl; |
334 | | #ifdef BN_COUNT |
335 | | fprintf(stderr, |
336 | | " bn_add_part_words %d + %d (dl > 0)\n", cl, dl); |
337 | | #endif |
338 | 0 | while (c) { |
339 | 0 | t = (a[0] + c) & BN_MASK2; |
340 | 0 | c = (t < c); |
341 | 0 | r[0] = t; |
342 | 0 | if (--dl <= 0) |
343 | 0 | break; |
344 | | |
345 | 0 | t = (a[1] + c) & BN_MASK2; |
346 | 0 | c = (t < c); |
347 | 0 | r[1] = t; |
348 | 0 | if (--dl <= 0) |
349 | 0 | break; |
350 | | |
351 | 0 | t = (a[2] + c) & BN_MASK2; |
352 | 0 | c = (t < c); |
353 | 0 | r[2] = t; |
354 | 0 | if (--dl <= 0) |
355 | 0 | break; |
356 | | |
357 | 0 | t = (a[3] + c) & BN_MASK2; |
358 | 0 | c = (t < c); |
359 | 0 | r[3] = t; |
360 | 0 | if (--dl <= 0) |
361 | 0 | break; |
362 | | |
363 | 0 | save_dl = dl; |
364 | 0 | a += 4; |
365 | 0 | r += 4; |
366 | 0 | } |
367 | | #ifdef BN_COUNT |
368 | | fprintf(stderr, |
369 | | " bn_add_part_words %d + %d (dl > 0, c == 0)\n", cl, dl); |
370 | | #endif |
371 | 0 | if (dl > 0) { |
372 | 0 | if (save_dl > dl) { |
373 | 0 | switch (save_dl - dl) { |
374 | 0 | case 1: |
375 | 0 | r[1] = a[1]; |
376 | 0 | if (--dl <= 0) |
377 | 0 | break; |
378 | 0 | case 2: |
379 | 0 | r[2] = a[2]; |
380 | 0 | if (--dl <= 0) |
381 | 0 | break; |
382 | 0 | case 3: |
383 | 0 | r[3] = a[3]; |
384 | 0 | if (--dl <= 0) |
385 | 0 | break; |
386 | 0 | } |
387 | 0 | a += 4; |
388 | 0 | r += 4; |
389 | 0 | } |
390 | 0 | } |
391 | 0 | if (dl > 0) { |
392 | | #ifdef BN_COUNT |
393 | | fprintf(stderr, |
394 | | " bn_add_part_words %d + %d (dl > 0, copy)\n", |
395 | | cl, dl); |
396 | | #endif |
397 | 0 | for (;;) { |
398 | 0 | r[0] = a[0]; |
399 | 0 | if (--dl <= 0) |
400 | 0 | break; |
401 | 0 | r[1] = a[1]; |
402 | 0 | if (--dl <= 0) |
403 | 0 | break; |
404 | 0 | r[2] = a[2]; |
405 | 0 | if (--dl <= 0) |
406 | 0 | break; |
407 | 0 | r[3] = a[3]; |
408 | 0 | if (--dl <= 0) |
409 | 0 | break; |
410 | | |
411 | 0 | a += 4; |
412 | 0 | r += 4; |
413 | 0 | } |
414 | 0 | } |
415 | 0 | } |
416 | 0 | return c; |
417 | 0 | } |
418 | | |
419 | | #ifdef BN_RECURSION |
420 | | /* Karatsuba recursive multiplication algorithm |
421 | | * (cf. Knuth, The Art of Computer Programming, Vol. 2) */ |
422 | | |
423 | | /* r is 2*n2 words in size, |
424 | | * a and b are both n2 words in size. |
425 | | * n2 must be a power of 2. |
426 | | * We multiply and return the result. |
427 | | * t must be 2*n2 words in size |
428 | | * We calculate |
429 | | * a[0]*b[0] |
430 | | * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) |
431 | | * a[1]*b[1] |
432 | | */ |
433 | | /* dnX may not be positive, but n2/2+dnX has to be */ |
434 | | void |
435 | | bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, int dna, |
436 | | int dnb, BN_ULONG *t) |
437 | 161k | { |
438 | 161k | int n = n2 / 2, c1, c2; |
439 | 161k | int tna = n + dna, tnb = n + dnb; |
440 | 161k | unsigned int neg, zero; |
441 | 161k | BN_ULONG ln, lo, *p; |
442 | | |
443 | | # ifdef BN_COUNT |
444 | | fprintf(stderr, " bn_mul_recursive %d%+d * %d%+d\n",n2,dna,n2,dnb); |
445 | | # endif |
446 | 161k | # ifdef BN_MUL_COMBA |
447 | | # if 0 |
448 | | if (n2 == 4) { |
449 | | bn_mul_comba4(r, a, b); |
450 | | return; |
451 | | } |
452 | | # endif |
453 | | /* Only call bn_mul_comba 8 if n2 == 8 and the |
454 | | * two arrays are complete [steve] |
455 | | */ |
456 | 161k | if (n2 == 8 && dna == 0 && dnb == 0) { |
457 | 1.68k | bn_mul_comba8(r, a, b); |
458 | 1.68k | return; |
459 | 1.68k | } |
460 | 159k | # endif /* BN_MUL_COMBA */ |
461 | | /* Else do normal multiply */ |
462 | 159k | if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) { |
463 | 765 | bn_mul_normal(r, a, n2 + dna, b, n2 + dnb); |
464 | 765 | if ((dna + dnb) < 0) |
465 | 765 | memset(&r[2*n2 + dna + dnb], 0, |
466 | 765 | sizeof(BN_ULONG) * -(dna + dnb)); |
467 | 765 | return; |
468 | 765 | } |
469 | | /* r=(a[0]-a[1])*(b[1]-b[0]) */ |
470 | 158k | c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); |
471 | 158k | c2 = bn_cmp_part_words(&(b[n]), b,tnb, tnb - n); |
472 | 158k | zero = neg = 0; |
473 | 158k | switch (c1 * 3 + c2) { |
474 | 39.2k | case -4: |
475 | 39.2k | bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ |
476 | 39.2k | bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ |
477 | 39.2k | break; |
478 | 677 | case -3: |
479 | 677 | zero = 1; |
480 | 677 | break; |
481 | 35.7k | case -2: |
482 | 35.7k | bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ |
483 | 35.7k | bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */ |
484 | 35.7k | neg = 1; |
485 | 35.7k | break; |
486 | 2.15k | case -1: |
487 | 2.89k | case 0: |
488 | 5.71k | case 1: |
489 | 5.71k | zero = 1; |
490 | 5.71k | break; |
491 | 36.6k | case 2: |
492 | 36.6k | bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */ |
493 | 36.6k | bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ |
494 | 36.6k | neg = 1; |
495 | 36.6k | break; |
496 | 520 | case 3: |
497 | 520 | zero = 1; |
498 | 520 | break; |
499 | 40.0k | case 4: |
500 | 40.0k | bn_sub_part_words(t, a, &(a[n]), tna, n - tna); |
501 | 40.0k | bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); |
502 | 40.0k | break; |
503 | 158k | } |
504 | | |
505 | 158k | # ifdef BN_MUL_COMBA |
506 | 158k | if (n == 4 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba4 could take |
507 | | extra args to do this well */ |
508 | 0 | { |
509 | 0 | if (!zero) |
510 | 0 | bn_mul_comba4(&(t[n2]), t, &(t[n])); |
511 | 0 | else |
512 | 0 | memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG)); |
513 | |
|
514 | 0 | bn_mul_comba4(r, a, b); |
515 | 0 | bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n])); |
516 | 158k | } else if (n == 8 && dna == 0 && dnb == 0) /* XXX: bn_mul_comba8 could |
517 | | take extra args to do this |
518 | | well */ |
519 | 151k | { |
520 | 151k | if (!zero) |
521 | 145k | bn_mul_comba8(&(t[n2]), t, &(t[n])); |
522 | 6.65k | else |
523 | 6.65k | memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG)); |
524 | | |
525 | 151k | bn_mul_comba8(r, a, b); |
526 | 151k | bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n])); |
527 | 151k | } else |
528 | 6.77k | # endif /* BN_MUL_COMBA */ |
529 | 6.77k | { |
530 | 6.77k | p = &(t[n2 * 2]); |
531 | 6.77k | if (!zero) |
532 | 6.52k | bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); |
533 | 250 | else |
534 | 250 | memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG)); |
535 | 6.77k | bn_mul_recursive(r, a, b, n, 0, 0, p); |
536 | 6.77k | bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p); |
537 | 6.77k | } |
538 | | |
539 | | /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign |
540 | | * r[10] holds (a[0]*b[0]) |
541 | | * r[32] holds (b[1]*b[1]) |
542 | | */ |
543 | | |
544 | 158k | c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); |
545 | | |
546 | 158k | if (neg) /* if t[32] is negative */ |
547 | 72.4k | { |
548 | 72.4k | c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); |
549 | 86.2k | } else { |
550 | | /* Might have a carry */ |
551 | 86.2k | c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); |
552 | 86.2k | } |
553 | | |
554 | | /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) |
555 | | * r[10] holds (a[0]*b[0]) |
556 | | * r[32] holds (b[1]*b[1]) |
557 | | * c1 holds the carry bits |
558 | | */ |
559 | 158k | c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); |
560 | 158k | if (c1) { |
561 | 51.3k | p = &(r[n + n2]); |
562 | 51.3k | lo= *p; |
563 | 51.3k | ln = (lo + c1) & BN_MASK2; |
564 | 51.3k | *p = ln; |
565 | | |
566 | | /* The overflow will stop before we over write |
567 | | * words we should not overwrite */ |
568 | 51.3k | if (ln < (BN_ULONG)c1) { |
569 | 7.66k | do { |
570 | 7.66k | p++; |
571 | 7.66k | lo= *p; |
572 | 7.66k | ln = (lo + 1) & BN_MASK2; |
573 | 7.66k | *p = ln; |
574 | 7.66k | } while (ln == 0); |
575 | 2.61k | } |
576 | 51.3k | } |
577 | 158k | } |
578 | | |
579 | | /* n+tn is the word length |
580 | | * t needs to be n*4 is size, as does r */ |
581 | | /* tnX may not be negative but less than n */ |
582 | | void |
583 | | bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n, int tna, |
584 | | int tnb, BN_ULONG *t) |
585 | 107k | { |
586 | 107k | int i, j, n2 = n * 2; |
587 | 107k | int c1, c2, neg; |
588 | 107k | BN_ULONG ln, lo, *p; |
589 | | |
590 | | # ifdef BN_COUNT |
591 | | fprintf(stderr, " bn_mul_part_recursive (%d%+d) * (%d%+d)\n", |
592 | | n, tna, n, tnb); |
593 | | # endif |
594 | 107k | if (n < 8) { |
595 | 0 | bn_mul_normal(r, a, n + tna, b, n + tnb); |
596 | 0 | return; |
597 | 0 | } |
598 | | |
599 | | /* r=(a[0]-a[1])*(b[1]-b[0]) */ |
600 | 107k | c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna); |
601 | 107k | c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n); |
602 | 107k | neg = 0; |
603 | 107k | switch (c1 * 3 + c2) { |
604 | 15.9k | case -4: |
605 | 15.9k | bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ |
606 | 15.9k | bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ |
607 | 15.9k | break; |
608 | 100 | case -3: |
609 | | /* break; */ |
610 | 2.70k | case -2: |
611 | 2.70k | bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */ |
612 | 2.70k | bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */ |
613 | 2.70k | neg = 1; |
614 | 2.70k | break; |
615 | 1.15k | case -1: |
616 | 1.28k | case 0: |
617 | 1.38k | case 1: |
618 | | /* break; */ |
619 | 86.0k | case 2: |
620 | 86.0k | bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */ |
621 | 86.0k | bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */ |
622 | 86.0k | neg = 1; |
623 | 86.0k | break; |
624 | 782 | case 3: |
625 | | /* break; */ |
626 | 3.02k | case 4: |
627 | 3.02k | bn_sub_part_words(t, a, &(a[n]), tna, n - tna); |
628 | 3.02k | bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); |
629 | 3.02k | break; |
630 | 107k | } |
631 | | /* The zero case isn't yet implemented here. The speedup |
632 | | would probably be negligible. */ |
633 | | # if 0 |
634 | | if (n == 4) { |
635 | | bn_mul_comba4(&(t[n2]), t, &(t[n])); |
636 | | bn_mul_comba4(r, a, b); |
637 | | bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn); |
638 | | memset(&(r[n2 + tn * 2]), 0, sizeof(BN_ULONG) * (n2 - tn * 2)); |
639 | | } else |
640 | | # endif |
641 | 107k | if (n == 8) { |
642 | 44.1k | bn_mul_comba8(&(t[n2]), t, &(t[n])); |
643 | 44.1k | bn_mul_comba8(r, a, b); |
644 | 44.1k | bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb); |
645 | 44.1k | memset(&(r[n2 + tna + tnb]), 0, |
646 | 44.1k | sizeof(BN_ULONG) * (n2 - tna - tnb)); |
647 | 63.6k | } else { |
648 | 63.6k | p = &(t[n2*2]); |
649 | 63.6k | bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p); |
650 | 63.6k | bn_mul_recursive(r, a, b, n, 0, 0, p); |
651 | 63.6k | i = n / 2; |
652 | | /* If there is only a bottom half to the number, |
653 | | * just do it */ |
654 | 63.6k | if (tna > tnb) |
655 | 3.84k | j = tna - i; |
656 | 59.7k | else |
657 | 59.7k | j = tnb - i; |
658 | 63.6k | if (j == 0) { |
659 | 408 | bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), |
660 | 408 | i, tna - i, tnb - i, p); |
661 | 408 | memset(&(r[n2 + i * 2]), 0, |
662 | 408 | sizeof(BN_ULONG) * (n2 - i * 2)); |
663 | 408 | } |
664 | 63.2k | else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */ |
665 | 44.1k | { |
666 | 44.1k | bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), |
667 | 44.1k | i, tna - i, tnb - i, p); |
668 | 44.1k | memset(&(r[n2 + tna + tnb]), 0, |
669 | 44.1k | sizeof(BN_ULONG) * (n2 - tna - tnb)); |
670 | 44.1k | } |
671 | 19.0k | else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */ |
672 | 19.0k | { |
673 | 19.0k | memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2); |
674 | 19.0k | if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL && |
675 | 19.0k | tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) { |
676 | 19.0k | bn_mul_normal(&(r[n2]), &(a[n]), tna, |
677 | 19.0k | &(b[n]), tnb); |
678 | 19.0k | } else { |
679 | 0 | for (;;) { |
680 | 0 | i /= 2; |
681 | | /* these simplified conditions work |
682 | | * exclusively because difference |
683 | | * between tna and tnb is 1 or 0 */ |
684 | 0 | if (i < tna || i < tnb) { |
685 | 0 | bn_mul_part_recursive(&(r[n2]), |
686 | 0 | &(a[n]), &(b[n]), i, |
687 | 0 | tna - i, tnb - i, p); |
688 | 0 | break; |
689 | 0 | } else if (i == tna || i == tnb) { |
690 | 0 | bn_mul_recursive(&(r[n2]), |
691 | 0 | &(a[n]), &(b[n]), i, |
692 | 0 | tna - i, tnb - i, p); |
693 | 0 | break; |
694 | 0 | } |
695 | 0 | } |
696 | 0 | } |
697 | 19.0k | } |
698 | 63.6k | } |
699 | | |
700 | | /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign |
701 | | * r[10] holds (a[0]*b[0]) |
702 | | * r[32] holds (b[1]*b[1]) |
703 | | */ |
704 | | |
705 | 107k | c1 = (int)(bn_add_words(t, r,&(r[n2]), n2)); |
706 | | |
707 | 107k | if (neg) /* if t[32] is negative */ |
708 | 88.7k | { |
709 | 88.7k | c1 -= (int)(bn_sub_words(&(t[n2]), t,&(t[n2]), n2)); |
710 | 88.7k | } else { |
711 | | /* Might have a carry */ |
712 | 18.9k | c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2)); |
713 | 18.9k | } |
714 | | |
715 | | /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) |
716 | | * r[10] holds (a[0]*b[0]) |
717 | | * r[32] holds (b[1]*b[1]) |
718 | | * c1 holds the carry bits |
719 | | */ |
720 | 107k | c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); |
721 | 107k | if (c1) { |
722 | 1.04k | p = &(r[n + n2]); |
723 | 1.04k | lo= *p; |
724 | 1.04k | ln = (lo + c1)&BN_MASK2; |
725 | 1.04k | *p = ln; |
726 | | |
727 | | /* The overflow will stop before we over write |
728 | | * words we should not overwrite */ |
729 | 1.04k | if (ln < (BN_ULONG)c1) { |
730 | 2.50k | do { |
731 | 2.50k | p++; |
732 | 2.50k | lo= *p; |
733 | 2.50k | ln = (lo + 1) & BN_MASK2; |
734 | 2.50k | *p = ln; |
735 | 2.50k | } while (ln == 0); |
736 | 749 | } |
737 | 1.04k | } |
738 | 107k | } |
739 | | |
740 | | /* a and b must be the same size, which is n2. |
741 | | * r needs to be n2 words and t needs to be n2*2 |
742 | | */ |
743 | | void |
744 | | bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, BN_ULONG *t) |
745 | 0 | { |
746 | 0 | int n = n2 / 2; |
747 | |
|
748 | | # ifdef BN_COUNT |
749 | | fprintf(stderr, " bn_mul_low_recursive %d * %d\n",n2,n2); |
750 | | # endif |
751 | |
|
752 | 0 | bn_mul_recursive(r, a, b, n, 0, 0, &(t[0])); |
753 | 0 | if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) { |
754 | 0 | bn_mul_low_recursive(&(t[0]), &(a[0]), &(b[n]), n, &(t[n2])); |
755 | 0 | bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); |
756 | 0 | bn_mul_low_recursive(&(t[0]), &(a[n]), &(b[0]), n, &(t[n2])); |
757 | 0 | bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); |
758 | 0 | } else { |
759 | 0 | bn_mul_low_normal(&(t[0]), &(a[0]), &(b[n]), n); |
760 | 0 | bn_mul_low_normal(&(t[n]), &(a[n]), &(b[0]), n); |
761 | 0 | bn_add_words(&(r[n]), &(r[n]), &(t[0]), n); |
762 | 0 | bn_add_words(&(r[n]), &(r[n]), &(t[n]), n); |
763 | 0 | } |
764 | 0 | } |
765 | | |
766 | | /* a and b must be the same size, which is n2. |
767 | | * r needs to be n2 words and t needs to be n2*2 |
768 | | * l is the low words of the output. |
769 | | * t needs to be n2*3 |
770 | | */ |
771 | | void |
772 | | bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2, |
773 | | BN_ULONG *t) |
774 | 0 | { |
775 | 0 | int i, n; |
776 | 0 | int c1, c2; |
777 | 0 | int neg, oneg, zero; |
778 | 0 | BN_ULONG ll, lc, *lp, *mp; |
779 | |
|
780 | | # ifdef BN_COUNT |
781 | | fprintf(stderr, " bn_mul_high %d * %d\n",n2,n2); |
782 | | # endif |
783 | 0 | n = n2 / 2; |
784 | | |
785 | | /* Calculate (al-ah)*(bh-bl) */ |
786 | 0 | neg = zero = 0; |
787 | 0 | c1 = bn_cmp_words(&(a[0]), &(a[n]), n); |
788 | 0 | c2 = bn_cmp_words(&(b[n]), &(b[0]), n); |
789 | 0 | switch (c1 * 3 + c2) { |
790 | 0 | case -4: |
791 | 0 | bn_sub_words(&(r[0]), &(a[n]), &(a[0]), n); |
792 | 0 | bn_sub_words(&(r[n]), &(b[0]), &(b[n]), n); |
793 | 0 | break; |
794 | 0 | case -3: |
795 | 0 | zero = 1; |
796 | 0 | break; |
797 | 0 | case -2: |
798 | 0 | bn_sub_words(&(r[0]), &(a[n]), &(a[0]), n); |
799 | 0 | bn_sub_words(&(r[n]), &(b[n]), &(b[0]), n); |
800 | 0 | neg = 1; |
801 | 0 | break; |
802 | 0 | case -1: |
803 | 0 | case 0: |
804 | 0 | case 1: |
805 | 0 | zero = 1; |
806 | 0 | break; |
807 | 0 | case 2: |
808 | 0 | bn_sub_words(&(r[0]), &(a[0]), &(a[n]), n); |
809 | 0 | bn_sub_words(&(r[n]), &(b[0]), &(b[n]), n); |
810 | 0 | neg = 1; |
811 | 0 | break; |
812 | 0 | case 3: |
813 | 0 | zero = 1; |
814 | 0 | break; |
815 | 0 | case 4: |
816 | 0 | bn_sub_words(&(r[0]), &(a[0]), &(a[n]), n); |
817 | 0 | bn_sub_words(&(r[n]), &(b[n]), &(b[0]), n); |
818 | 0 | break; |
819 | 0 | } |
820 | | |
821 | 0 | oneg = neg; |
822 | | /* t[10] = (a[0]-a[1])*(b[1]-b[0]) */ |
823 | | /* r[10] = (a[1]*b[1]) */ |
824 | 0 | # ifdef BN_MUL_COMBA |
825 | 0 | if (n == 8) { |
826 | 0 | bn_mul_comba8(&(t[0]), &(r[0]), &(r[n])); |
827 | 0 | bn_mul_comba8(r, &(a[n]), &(b[n])); |
828 | 0 | } else |
829 | 0 | # endif |
830 | 0 | { |
831 | 0 | bn_mul_recursive(&(t[0]), &(r[0]), &(r[n]), n, 0, 0, &(t[n2])); |
832 | 0 | bn_mul_recursive(r, &(a[n]), &(b[n]), n, 0, 0, &(t[n2])); |
833 | 0 | } |
834 | | |
835 | | /* s0 == low(al*bl) |
836 | | * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl) |
837 | | * We know s0 and s1 so the only unknown is high(al*bl) |
838 | | * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl)) |
839 | | * high(al*bl) == s1 - (r[0]+l[0]+t[0]) |
840 | | */ |
841 | 0 | if (l != NULL) { |
842 | 0 | lp = &(t[n2 + n]); |
843 | 0 | c1 = (int)(bn_add_words(lp, &(r[0]), &(l[0]), n)); |
844 | 0 | } else { |
845 | 0 | c1 = 0; |
846 | 0 | lp = &(r[0]); |
847 | 0 | } |
848 | |
|
849 | 0 | if (neg) |
850 | 0 | neg = (int)(bn_sub_words(&(t[n2]), lp, &(t[0]), n)); |
851 | 0 | else { |
852 | 0 | bn_add_words(&(t[n2]), lp, &(t[0]), n); |
853 | 0 | neg = 0; |
854 | 0 | } |
855 | |
|
856 | 0 | if (l != NULL) { |
857 | 0 | bn_sub_words(&(t[n2 + n]), &(l[n]), &(t[n2]), n); |
858 | 0 | } else { |
859 | 0 | lp = &(t[n2 + n]); |
860 | 0 | mp = &(t[n2]); |
861 | 0 | for (i = 0; i < n; i++) |
862 | 0 | lp[i] = ((~mp[i]) + 1) & BN_MASK2; |
863 | 0 | } |
864 | | |
865 | | /* s[0] = low(al*bl) |
866 | | * t[3] = high(al*bl) |
867 | | * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign |
868 | | * r[10] = (a[1]*b[1]) |
869 | | */ |
870 | | /* R[10] = al*bl |
871 | | * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0]) |
872 | | * R[32] = ah*bh |
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 | { |
900 | 0 | i = 0; |
901 | 0 | if (c1 > 0) { |
902 | 0 | lc = c1; |
903 | 0 | do { |
904 | 0 | ll = (r[i] + lc) & BN_MASK2; |
905 | 0 | r[i++] = ll; |
906 | 0 | lc = (lc > ll); |
907 | 0 | } while (lc); |
908 | 0 | } else { |
909 | 0 | lc = -c1; |
910 | 0 | do { |
911 | 0 | ll = r[i]; |
912 | 0 | r[i++] = (ll - lc) & BN_MASK2; |
913 | 0 | lc = (lc > ll); |
914 | 0 | } while (lc); |
915 | 0 | } |
916 | 0 | } |
917 | 0 | if (c2 != 0) /* Add starting at r[1] */ |
918 | 0 | { |
919 | 0 | i = n; |
920 | 0 | if (c2 > 0) { |
921 | 0 | lc = c2; |
922 | 0 | do { |
923 | 0 | ll = (r[i] + lc) & BN_MASK2; |
924 | 0 | r[i++] = ll; |
925 | 0 | lc = (lc > ll); |
926 | 0 | } while (lc); |
927 | 0 | } else { |
928 | 0 | lc = -c2; |
929 | 0 | do { |
930 | 0 | ll = r[i]; |
931 | 0 | r[i++] = (ll - lc) & BN_MASK2; |
932 | 0 | lc = (lc > ll); |
933 | 0 | } while (lc); |
934 | 0 | } |
935 | 0 | } |
936 | 0 | } |
937 | | #endif /* BN_RECURSION */ |
938 | | |
939 | | int |
940 | | BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) |
941 | 687k | { |
942 | 687k | int ret = 0; |
943 | 687k | int top, al, bl; |
944 | 687k | BIGNUM *rr; |
945 | 687k | #if defined(BN_MUL_COMBA) || defined(BN_RECURSION) |
946 | 687k | int i; |
947 | 687k | #endif |
948 | 687k | #ifdef BN_RECURSION |
949 | 687k | BIGNUM *t = NULL; |
950 | 687k | int j = 0, k; |
951 | 687k | #endif |
952 | | |
953 | | #ifdef BN_COUNT |
954 | | fprintf(stderr, "BN_mul %d * %d\n",a->top,b->top); |
955 | | #endif |
956 | | |
957 | 687k | bn_check_top(a); |
958 | 687k | bn_check_top(b); |
959 | 687k | bn_check_top(r); |
960 | | |
961 | 687k | al = a->top; |
962 | 687k | bl = b->top; |
963 | | |
964 | 687k | if ((al == 0) || (bl == 0)) { |
965 | 31.7k | BN_zero(r); |
966 | 31.7k | return (1); |
967 | 31.7k | } |
968 | 656k | top = al + bl; |
969 | | |
970 | 656k | BN_CTX_start(ctx); |
971 | 656k | if ((r == a) || (r == b)) { |
972 | 0 | if ((rr = BN_CTX_get(ctx)) == NULL) |
973 | 0 | goto err; |
974 | 0 | } else |
975 | 656k | rr = r; |
976 | 656k | rr->neg = a->neg ^ b->neg; |
977 | | |
978 | 656k | #if defined(BN_MUL_COMBA) || defined(BN_RECURSION) |
979 | 656k | i = al - bl; |
980 | 656k | #endif |
981 | 656k | #ifdef BN_MUL_COMBA |
982 | 656k | if (i == 0) { |
983 | | # if 0 |
984 | | if (al == 4) { |
985 | | if (bn_wexpand(rr, 8) == NULL) |
986 | | goto err; |
987 | | rr->top = 8; |
988 | | bn_mul_comba4(rr->d, a->d, b->d); |
989 | | goto end; |
990 | | } |
991 | | # endif |
992 | 270k | if (al == 8) { |
993 | 1.60k | if (bn_wexpand(rr, 16) == NULL) |
994 | 0 | goto err; |
995 | 1.60k | rr->top = 16; |
996 | 1.60k | bn_mul_comba8(rr->d, a->d, b->d); |
997 | 1.60k | goto end; |
998 | 1.60k | } |
999 | 270k | } |
1000 | 654k | #endif /* BN_MUL_COMBA */ |
1001 | 654k | #ifdef BN_RECURSION |
1002 | 654k | if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) { |
1003 | 86.4k | if (i >= -1 && i <= 1) { |
1004 | | /* Find out the power of two lower or equal |
1005 | | to the longest of the two numbers */ |
1006 | 77.0k | if (i >= 0) { |
1007 | 66.1k | j = BN_num_bits_word((BN_ULONG)al); |
1008 | 66.1k | } |
1009 | 77.0k | if (i == -1) { |
1010 | 10.9k | j = BN_num_bits_word((BN_ULONG)bl); |
1011 | 10.9k | } |
1012 | 77.0k | j = 1 << (j - 1); |
1013 | 77.0k | assert(j <= al || j <= bl); |
1014 | 77.0k | k = j + j; |
1015 | 77.0k | if ((t = BN_CTX_get(ctx)) == NULL) |
1016 | 0 | goto err; |
1017 | 77.0k | if (al > j || bl > j) { |
1018 | 63.6k | if (bn_wexpand(t, k * 4) == NULL) |
1019 | 0 | goto err; |
1020 | 63.6k | if (bn_wexpand(rr, k * 4) == NULL) |
1021 | 0 | goto err; |
1022 | 63.6k | bn_mul_part_recursive(rr->d, a->d, b->d, |
1023 | 63.6k | j, al - j, bl - j, t->d); |
1024 | 63.6k | } |
1025 | 13.4k | else /* al <= j || bl <= j */ |
1026 | 13.4k | { |
1027 | 13.4k | if (bn_wexpand(t, k * 2) == NULL) |
1028 | 0 | goto err; |
1029 | 13.4k | if (bn_wexpand(rr, k * 2) == NULL) |
1030 | 0 | goto err; |
1031 | 13.4k | bn_mul_recursive(rr->d, a->d, b->d, |
1032 | 13.4k | j, al - j, bl - j, t->d); |
1033 | 13.4k | } |
1034 | 77.0k | rr->top = top; |
1035 | 77.0k | goto end; |
1036 | 77.0k | } |
1037 | | #if 0 |
1038 | | if (i == 1 && !BN_get_flags(b, BN_FLG_STATIC_DATA)) { |
1039 | | BIGNUM *tmp_bn = (BIGNUM *)b; |
1040 | | if (bn_wexpand(tmp_bn, al) == NULL) |
1041 | | goto err; |
1042 | | tmp_bn->d[bl] = 0; |
1043 | | bl++; |
1044 | | i--; |
1045 | | } else if (i == -1 && !BN_get_flags(a, BN_FLG_STATIC_DATA)) { |
1046 | | BIGNUM *tmp_bn = (BIGNUM *)a; |
1047 | | if (bn_wexpand(tmp_bn, bl) == NULL) |
1048 | | goto err; |
1049 | | tmp_bn->d[al] = 0; |
1050 | | al++; |
1051 | | i++; |
1052 | | } |
1053 | | if (i == 0) { |
1054 | | /* symmetric and > 4 */ |
1055 | | /* 16 or larger */ |
1056 | | j = BN_num_bits_word((BN_ULONG)al); |
1057 | | j = 1 << (j - 1); |
1058 | | k = j + j; |
1059 | | if ((t = BN_CTX_get(ctx)) == NULL) |
1060 | | goto err; |
1061 | | if (al == j) /* exact multiple */ |
1062 | | { |
1063 | | if (bn_wexpand(t, k * 2) == NULL) |
1064 | | goto err; |
1065 | | if (bn_wexpand(rr, k * 2) == NULL) |
1066 | | goto err; |
1067 | | bn_mul_recursive(rr->d, a->d, b->d, al, t->d); |
1068 | | } else { |
1069 | | if (bn_wexpand(t, k * 4) == NULL) |
1070 | | goto err; |
1071 | | if (bn_wexpand(rr, k * 4) == NULL) |
1072 | | goto err; |
1073 | | bn_mul_part_recursive(rr->d, a->d, b->d, |
1074 | | al - j, j, t->d); |
1075 | | } |
1076 | | rr->top = top; |
1077 | | goto end; |
1078 | | } |
1079 | | #endif |
1080 | 86.4k | } |
1081 | 577k | #endif /* BN_RECURSION */ |
1082 | 577k | if (bn_wexpand(rr, top) == NULL) |
1083 | 0 | goto err; |
1084 | 577k | rr->top = top; |
1085 | 577k | bn_mul_normal(rr->d, a->d, al, b->d, bl); |
1086 | | |
1087 | 577k | #if defined(BN_MUL_COMBA) || defined(BN_RECURSION) |
1088 | 656k | end: |
1089 | 656k | #endif |
1090 | 656k | bn_correct_top(rr); |
1091 | 656k | if (r != rr) |
1092 | 0 | BN_copy(r, rr); |
1093 | 656k | ret = 1; |
1094 | 656k | err: |
1095 | 656k | bn_check_top(r); |
1096 | 656k | BN_CTX_end(ctx); |
1097 | 656k | return (ret); |
1098 | 656k | } |
1099 | | |
1100 | | void |
1101 | | bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) |
1102 | 641k | { |
1103 | 641k | BN_ULONG *rr; |
1104 | | |
1105 | | #ifdef BN_COUNT |
1106 | | fprintf(stderr, " bn_mul_normal %d * %d\n", na, nb); |
1107 | | #endif |
1108 | | |
1109 | 641k | if (na < nb) { |
1110 | 309k | int itmp; |
1111 | 309k | BN_ULONG *ltmp; |
1112 | | |
1113 | 309k | itmp = na; |
1114 | 309k | na = nb; |
1115 | 309k | nb = itmp; |
1116 | 309k | ltmp = a; |
1117 | 309k | a = b; |
1118 | 309k | b = ltmp; |
1119 | | |
1120 | 309k | } |
1121 | 641k | rr = &(r[na]); |
1122 | 641k | if (nb <= 0) { |
1123 | 12.1k | (void)bn_mul_words(r, a, na, 0); |
1124 | 12.1k | return; |
1125 | 12.1k | } else |
1126 | 629k | rr[0] = bn_mul_words(r, a, na, b[0]); |
1127 | | |
1128 | 701k | for (;;) { |
1129 | 701k | if (--nb <= 0) |
1130 | 435k | return; |
1131 | 265k | rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]); |
1132 | 265k | if (--nb <= 0) |
1133 | 18.9k | return; |
1134 | 246k | rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]); |
1135 | 246k | if (--nb <= 0) |
1136 | 88.2k | return; |
1137 | 158k | rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]); |
1138 | 158k | if (--nb <= 0) |
1139 | 86.2k | return; |
1140 | 71.9k | rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]); |
1141 | 71.9k | rr += 4; |
1142 | 71.9k | r += 4; |
1143 | 71.9k | b += 4; |
1144 | 71.9k | } |
1145 | 629k | } |
1146 | | |
1147 | | void |
1148 | | bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) |
1149 | 0 | { |
1150 | | #ifdef BN_COUNT |
1151 | | fprintf(stderr, " bn_mul_low_normal %d * %d\n", n, n); |
1152 | | #endif |
1153 | 0 | bn_mul_words(r, a, n, b[0]); |
1154 | |
|
1155 | 0 | for (;;) { |
1156 | 0 | if (--n <= 0) |
1157 | 0 | return; |
1158 | 0 | bn_mul_add_words(&(r[1]), a, n, b[1]); |
1159 | 0 | if (--n <= 0) |
1160 | 0 | return; |
1161 | 0 | bn_mul_add_words(&(r[2]), a, n, b[2]); |
1162 | 0 | if (--n <= 0) |
1163 | 0 | return; |
1164 | 0 | bn_mul_add_words(&(r[3]), a, n, b[3]); |
1165 | 0 | if (--n <= 0) |
1166 | 0 | return; |
1167 | 0 | bn_mul_add_words(&(r[4]), a, n, b[4]); |
1168 | 0 | r += 4; |
1169 | 0 | b += 4; |
1170 | 0 | } |
1171 | 0 | } |