1
/* crypto/bn/bn_mul.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
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.
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).
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.
23
* Redistribution and use in source and binary forms, with or without
24
* modification, are permitted provided that the following conditions
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)"
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
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.]
63
/* Karatsuba recursive multiplication algorithm
64
* (cf. Knuth, The Art of Computer Programming, Vol. 2) */
66
/* r is 2*n2 words in size,
67
* a and b are both n2 words in size.
68
* n2 must be a power of 2.
69
* We multiply and return the result.
70
* t must be 2*n2 words in size
73
* a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
76
void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
80
unsigned int neg,zero;
84
printf(" bn_mul_recursive %d * %d\n",n2,n2);
99
# endif /* BN_MUL_COMBA */
100
if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL)
102
/* This should not happen */
103
bn_mul_normal(r,a,n2,b,n2);
106
/* r=(a[0]-a[1])*(b[1]-b[0]) */
107
c1=bn_cmp_words(a,&(a[n]),n);
108
c2=bn_cmp_words(&(b[n]),b,n);
113
bn_sub_words(t, &(a[n]),a, n); /* - */
114
bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */
120
bn_sub_words(t, &(a[n]),a, n); /* - */
121
bn_sub_words(&(t[n]),&(b[n]),b, n); /* + */
130
bn_sub_words(t, a, &(a[n]),n); /* + */
131
bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */
138
bn_sub_words(t, a, &(a[n]),n);
139
bn_sub_words(&(t[n]),&(b[n]),b, n);
147
bn_mul_comba4(&(t[n2]),t,&(t[n]));
149
memset(&(t[n2]),0,8*sizeof(BN_ULONG));
151
bn_mul_comba4(r,a,b);
152
bn_mul_comba4(&(r[n2]),&(a[n]),&(b[n]));
157
bn_mul_comba8(&(t[n2]),t,&(t[n]));
159
memset(&(t[n2]),0,16*sizeof(BN_ULONG));
161
bn_mul_comba8(r,a,b);
162
bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n]));
165
# endif /* BN_MUL_COMBA */
169
bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
171
memset(&(t[n2]),0,n2*sizeof(BN_ULONG));
172
bn_mul_recursive(r,a,b,n,p);
173
bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,p);
176
/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
177
* r[10] holds (a[0]*b[0])
178
* r[32] holds (b[1]*b[1])
181
c1=(int)(bn_add_words(t,r,&(r[n2]),n2));
183
if (neg) /* if t[32] is negative */
185
c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
189
/* Might have a carry */
190
c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));
193
/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
194
* r[10] holds (a[0]*b[0])
195
* r[32] holds (b[1]*b[1])
196
* c1 holds the carry bits
198
c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
206
/* The overflow will stop before we over write
207
* words we should not overwrite */
208
if (ln < (BN_ULONG)c1)
220
/* n+tn is the word length
221
* t needs to be n*4 is size, as does r */
222
void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int tn,
226
unsigned int c1,c2,neg,zero;
230
printf(" bn_mul_part_recursive %d * %d\n",tn+n,tn+n);
235
bn_mul_normal(r,a,i,b,i);
239
/* r=(a[0]-a[1])*(b[1]-b[0]) */
240
c1=bn_cmp_words(a,&(a[n]),n);
241
c2=bn_cmp_words(&(b[n]),b,n);
246
bn_sub_words(t, &(a[n]),a, n); /* - */
247
bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */
253
bn_sub_words(t, &(a[n]),a, n); /* - */
254
bn_sub_words(&(t[n]),&(b[n]),b, n); /* + */
263
bn_sub_words(t, a, &(a[n]),n); /* + */
264
bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */
271
bn_sub_words(t, a, &(a[n]),n);
272
bn_sub_words(&(t[n]),&(b[n]),b, n);
275
/* The zero case isn't yet implemented here. The speedup
276
would probably be negligible. */
280
bn_mul_comba4(&(t[n2]),t,&(t[n]));
281
bn_mul_comba4(r,a,b);
282
bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
283
memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
289
bn_mul_comba8(&(t[n2]),t,&(t[n]));
290
bn_mul_comba8(r,a,b);
291
bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
292
memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2));
297
bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p);
298
bn_mul_recursive(r,a,b,n,p);
300
/* If there is only a bottom half to the number,
305
bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),i,p);
306
memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2));
308
else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */
310
bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]),
312
memset(&(r[n2+tn*2]),0,
313
sizeof(BN_ULONG)*(n2-tn*2));
315
else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
317
memset(&(r[n2]),0,sizeof(BN_ULONG)*n2);
318
if (tn < BN_MUL_RECURSIVE_SIZE_NORMAL)
320
bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn);
329
bn_mul_part_recursive(&(r[n2]),
336
bn_mul_recursive(&(r[n2]),
346
/* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign
347
* r[10] holds (a[0]*b[0])
348
* r[32] holds (b[1]*b[1])
351
c1=(int)(bn_add_words(t,r,&(r[n2]),n2));
353
if (neg) /* if t[32] is negative */
355
c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2));
359
/* Might have a carry */
360
c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),t,n2));
363
/* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])
364
* r[10] holds (a[0]*b[0])
365
* r[32] holds (b[1]*b[1])
366
* c1 holds the carry bits
368
c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2));
376
/* The overflow will stop before we over write
377
* words we should not overwrite */
390
/* a and b must be the same size, which is n2.
391
* r needs to be n2 words and t needs to be n2*2
393
void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
399
printf(" bn_mul_low_recursive %d * %d\n",n2,n2);
402
bn_mul_recursive(r,a,b,n,&(t[0]));
403
if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL)
405
bn_mul_low_recursive(&(t[0]),&(a[0]),&(b[n]),n,&(t[n2]));
406
bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
407
bn_mul_low_recursive(&(t[0]),&(a[n]),&(b[0]),n,&(t[n2]));
408
bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
412
bn_mul_low_normal(&(t[0]),&(a[0]),&(b[n]),n);
413
bn_mul_low_normal(&(t[n]),&(a[n]),&(b[0]),n);
414
bn_add_words(&(r[n]),&(r[n]),&(t[0]),n);
415
bn_add_words(&(r[n]),&(r[n]),&(t[n]),n);
419
/* a and b must be the same size, which is n2.
420
* r needs to be n2 words and t needs to be n2*2
421
* l is the low words of the output.
424
void bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2,
430
BN_ULONG ll,lc,*lp,*mp;
433
printf(" bn_mul_high %d * %d\n",n2,n2);
437
/* Calculate (al-ah)*(bh-bl) */
439
c1=bn_cmp_words(&(a[0]),&(a[n]),n);
440
c2=bn_cmp_words(&(b[n]),&(b[0]),n);
444
bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
445
bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
451
bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n);
452
bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
461
bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
462
bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n);
469
bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n);
470
bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n);
475
/* t[10] = (a[0]-a[1])*(b[1]-b[0]) */
476
/* r[10] = (a[1]*b[1]) */
480
bn_mul_comba8(&(t[0]),&(r[0]),&(r[n]));
481
bn_mul_comba8(r,&(a[n]),&(b[n]));
486
bn_mul_recursive(&(t[0]),&(r[0]),&(r[n]),n,&(t[n2]));
487
bn_mul_recursive(r,&(a[n]),&(b[n]),n,&(t[n2]));
491
* s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)
492
* We know s0 and s1 so the only unknown is high(al*bl)
493
* high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl))
494
* high(al*bl) == s1 - (r[0]+l[0]+t[0])
499
c1=(int)(bn_add_words(lp,&(r[0]),&(l[0]),n));
508
neg=(int)(bn_sub_words(&(t[n2]),lp,&(t[0]),n));
511
bn_add_words(&(t[n2]),lp,&(t[0]),n);
517
bn_sub_words(&(t[n2+n]),&(l[n]),&(t[n2]),n);
524
lp[i]=((~mp[i])+1)&BN_MASK2;
529
* t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign
530
* r[10] = (a[1]*b[1])
533
* R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0])
536
/* R[1]=t[3]+l[0]+r[0](+-)t[0] (have carry/borrow)
537
* R[2]=r[0]+t[3]+r[1](+-)t[1] (have carry/borrow)
538
* R[3]=r[1]+(carry/borrow)
543
c1= (int)(bn_add_words(lp,&(t[n2+n]),&(l[0]),n));
550
c1+=(int)(bn_add_words(&(t[n2]),lp, &(r[0]),n));
552
c1-=(int)(bn_sub_words(&(t[n2]),&(t[n2]),&(t[0]),n));
554
c1+=(int)(bn_add_words(&(t[n2]),&(t[n2]),&(t[0]),n));
556
c2 =(int)(bn_add_words(&(r[0]),&(r[0]),&(t[n2+n]),n));
557
c2+=(int)(bn_add_words(&(r[0]),&(r[0]),&(r[n]),n));
559
c2-=(int)(bn_sub_words(&(r[0]),&(r[0]),&(t[n]),n));
561
c2+=(int)(bn_add_words(&(r[0]),&(r[0]),&(t[n]),n));
563
if (c1 != 0) /* Add starting at r[0], could be +ve or -ve */
570
ll=(r[i]+lc)&BN_MASK2;
580
r[i++]=(ll-lc)&BN_MASK2;
585
if (c2 != 0) /* Add starting at r[1] */
592
ll=(r[i]+lc)&BN_MASK2;
602
r[i++]=(ll-lc)&BN_MASK2;
608
#endif /* BN_RECURSION */
610
int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
615
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
624
printf("BN_mul %d * %d\n",a->top,b->top);
634
if ((al == 0) || (bl == 0))
636
if (!BN_zero(r)) goto err;
642
if ((r == a) || (r == b))
644
if ((rr = BN_CTX_get(ctx)) == NULL) goto err;
648
rr->neg=a->neg^b->neg;
650
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
659
if (bn_wexpand(rr,8) == NULL) goto err;
661
bn_mul_comba4(rr->d,a->d,b->d);
667
if (bn_wexpand(rr,16) == NULL) goto err;
669
bn_mul_comba8(rr->d,a->d,b->d);
673
#endif /* BN_MUL_COMBA */
675
if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL))
677
if (i == 1 && !BN_get_flags(b,BN_FLG_STATIC_DATA))
679
if (bn_wexpand(b,al) == NULL) goto err;
684
else if (i == -1 && !BN_get_flags(a,BN_FLG_STATIC_DATA))
686
if (bn_wexpand(a,bl) == NULL) goto err;
693
/* symmetric and > 4 */
695
j=BN_num_bits_word((BN_ULONG)al);
699
if (al == j) /* exact multiple */
701
if (bn_wexpand(t,k*2) == NULL) goto err;
702
if (bn_wexpand(rr,k*2) == NULL) goto err;
703
bn_mul_recursive(rr->d,a->d,b->d,al,t->d);
707
if (bn_wexpand(a,k) == NULL ) goto err;
708
if (bn_wexpand(b,k) == NULL ) goto err;
709
if (bn_wexpand(t,k*4) == NULL ) goto err;
710
if (bn_wexpand(rr,k*4) == NULL ) goto err;
711
for (i=a->top; i<k; i++)
713
for (i=b->top; i<k; i++)
715
bn_mul_part_recursive(rr->d,a->d,b->d,al-j,j,t->d);
721
#endif /* BN_RECURSION */
722
if (bn_wexpand(rr,top) == NULL) goto err;
724
bn_mul_normal(rr->d,a->d,al,b->d,bl);
726
#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)
730
if (r != rr) BN_copy(r,rr);
737
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
742
printf(" bn_mul_normal %d * %d\n",na,nb);
750
itmp=na; na=nb; nb=itmp;
755
rr[0]=bn_mul_words(r,a,na,b[0]);
759
if (--nb <= 0) return;
760
rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]);
761
if (--nb <= 0) return;
762
rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]);
763
if (--nb <= 0) return;
764
rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]);
765
if (--nb <= 0) return;
766
rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]);
773
void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
776
printf(" bn_mul_low_normal %d * %d\n",n,n);
778
bn_mul_words(r,a,n,b[0]);
782
if (--n <= 0) return;
783
bn_mul_add_words(&(r[1]),a,n,b[1]);
784
if (--n <= 0) return;
785
bn_mul_add_words(&(r[2]),a,n,b[2]);
786
if (--n <= 0) return;
787
bn_mul_add_words(&(r[3]),a,n,b[3]);
788
if (--n <= 0) return;
789
bn_mul_add_words(&(r[4]),a,n,b[4]);