| /* crypto/bn/wei_mulw.c */ |
| |
| #include <stdio.h> |
| #include "cryptlib.h" |
| #include "bn.h" |
| #include "bn_lcl.h" |
| |
| BN_ULONG bn_add_word(BN_ULONG *a,BN_ULONG c,int num); |
| BN_ULONG bn_add_words(BN_ULONG *ret,BN_ULONG *a,BN_ULONG *b,int num); |
| BN_ULONG bn_sub_words(BN_ULONG *ret,BN_ULONG *a,BN_ULONG *b,int num); |
| |
| void BN_mul_4words(BN_ULONG *ret,BN_ULONG a0,BN_ULONG a1, |
| BN_ULONG b0,BN_ULONG b1); |
| |
| void pr(a,n,s) |
| BN_ULONG *a; |
| int n; |
| { |
| while (n--) |
| fprintf(stdout,"%02X",a[n]); |
| fprintf(stdout,"%s",s); |
| } |
| |
| |
| BN_ULONG bn_add_word(a,w,num) |
| BN_ULONG *a; |
| BN_ULONG w; |
| int num; |
| { |
| BN_ULONG t; |
| |
| #ifdef DEBUG |
| { BN_ULONG *aa=a; int i; for (i=num; i>0; i--) fprintf(stdout,"%02X",aa[i-1]); |
| fprintf(stdout," + %X - ",w); i=num; |
| #endif |
| |
| loop: |
| t= *a; |
| t=(t+w)&BN_MASK2; |
| *(a++)=t; |
| w=(t < w); |
| if (w && --num) goto loop; |
| |
| #ifdef DEBUG |
| for (; i>0; i--) fprintf(stdout,"%02X",aa[i-1]); |
| fprintf(stdout,"\n"); |
| } |
| #endif |
| |
| return(w); |
| } |
| |
| BN_ULONG bn_add_words(r,a,b,num) |
| BN_ULONG *r; |
| BN_ULONG *a; |
| BN_ULONG *b; |
| int num; |
| { |
| #if defined(BN_LLONG) |
| BN_ULLONG t; |
| BN_ULONG c=0; |
| int i; |
| |
| if (num&1) abort(); |
| |
| for (i=0; i<num; i+=2) |
| { |
| t=(BN_ULLONG)a[i]+b[i]+c; |
| r[i+0]=L(t); |
| t=(BN_ULLONG) H(t)+a[i+1]+b[i+1]; |
| r[i+1]=L(t); |
| c=H(t); |
| } |
| return(c); |
| #else |
| BN_ULONG c=0,t1,t2; |
| |
| for ( ; num; num--) |
| { |
| t1= *(a++); |
| t2= *(b++); |
| |
| if (c) |
| { |
| c=(t2 >= ((~t1)&BN_MASK2)); |
| (*r++)=(t1+t2+1)&BN_MASK2; |
| } |
| else |
| { |
| t2=(t1+t2)&BN_MASK2; |
| c=(t2 < t1); |
| (*r++)=t2; |
| } |
| } |
| return(c); |
| #endif |
| } |
| |
| BN_ULONG bn_sub_words(r,a,b,num) |
| BN_ULONG *r; |
| BN_ULONG *a; |
| BN_ULONG *b; |
| int num; |
| { |
| #if defined(BN_LLONG) |
| BN_ULLONG t; |
| BN_ULONG c=0; |
| int i; |
| |
| if (num&1) abort(); |
| |
| for (i=0; i<num; i+=2) |
| { |
| t=(BN_ULLONG)a[i]-b[i]-c; |
| r[i+0]=L(t); |
| t=(BN_ULLONG)a[i+1]-b[i+1]-(0-H(t))&BN_MASK2; |
| r[i+1]=L(t); |
| c=H(t); |
| } |
| return(c); |
| #else |
| BN_ULONG c=0,t1,t2; |
| |
| for ( ; num; num--) |
| { |
| t1= *(a++); |
| t2= *(b++); |
| |
| if (c) |
| { |
| c=(t1 <= t2); |
| t1=(t1-t2-1); |
| } |
| else |
| { |
| c=(t1 < t2); |
| t1=(t1-t2); |
| } |
| (*r++)=t1&BN_MASK2; |
| } |
| return(c); |
| #endif |
| } |
| |
| |
| /* ret[3,2,1,0] = a1,a0 * b1,b0 */ |
| void BN_mul_4words(ret,a0,a1,b0,b1) |
| BN_ULONG *ret; |
| BN_ULONG a0,a1,b0,b1; |
| { |
| BN_ULONG s,u; |
| BN_ULLONG fix,a0b0,a1b1,tmp; |
| |
| if (a1 >= a0) |
| { |
| s=(a1-a0); |
| u=(b0-b1); |
| fix=(BN_ULLONG)s*u; |
| if (b0 >= b1) s=0; |
| } |
| else |
| { |
| BN_ULONG u; |
| |
| if (b0 > b1) |
| { |
| s=(b0-b1); |
| u=(a1-a0); |
| fix=(BN_ULLONG)s*u; |
| } |
| else |
| { |
| u=(a0-a1); |
| s=(b1-b0); |
| fix=(BN_ULLONG)s*u; |
| s=0; |
| } |
| } |
| |
| a0b0=(BN_ULLONG)a0*b0; |
| ret[0]=L(a0b0); |
| |
| a1b1=(BN_ULLONG)a1*b1; |
| tmp=(BN_ULLONG) H(a0b0) + L(a0b0) + L(fix) + L(a1b1); |
| ret[1]=L(tmp); |
| |
| tmp=(BN_ULLONG) a1b1 + H(tmp) + H(a0b0) + H(fix) + H(a1b1) - s; |
| ret[2]=L(tmp); |
| ret[3]=H(tmp); |
| } |
| |
| /* ret[3,2,1,0] += a1,a0 * b1,b0 */ |
| BN_ULONG BN_mul_add_4words(ret,a0,a1,b0,b1) |
| BN_ULONG *ret; |
| BN_ULONG a0,a1,b0,b1; |
| { |
| BN_ULONG s,u; |
| BN_ULLONG fix,a0b0,a1b1,tmp; |
| |
| #ifdef DEBUG |
| fprintf(stdout,"%02X%02X%02X%02X",ret[3],ret[2],ret[1],ret[0]); |
| fprintf(stdout," + ( %02X%02X * %02X%02X ) - ",a1,a0,b1,b0); |
| #endif |
| if (a1 >= a0) |
| { |
| s=(a1-a0); |
| u=(b0-b1); |
| fix=(BN_ULLONG)s*u; |
| if (b0 >= b1) s=0; |
| } |
| else |
| { |
| if (b0 > b1) |
| { |
| s=(b0-b1); |
| u=(a1-a0); |
| fix=(BN_ULLONG)s*u; |
| } |
| else |
| { |
| u=(a0-a1); |
| s=(b1-b0); |
| fix=(BN_ULLONG)s*u; |
| s=0; |
| } |
| } |
| |
| a0b0=(BN_ULLONG)a0*b0; |
| tmp=a0b0+ret[0]; |
| ret[0]=L(tmp); |
| |
| a1b1=(BN_ULLONG)a1*b1; |
| tmp=(BN_ULLONG) H(tmp) + L(a0b0) + L(fix) + L(a1b1) + ret[1]; |
| ret[1]=L(tmp); |
| |
| tmp=(BN_ULLONG) H(tmp) + L(a1b1) + H(a0b0) + |
| H(fix) + H(a1b1) -s + ret[2]; |
| ret[2]=L(tmp); |
| |
| tmp=(BN_ULLONG) H(tmp) + H(a1b1) + ret[3]; |
| ret[3]=L(tmp); |
| #ifdef DEBUG |
| fprintf(stdout,"%02X%02X%02X%02X%02X\n",H(tmp),ret[3],ret[2],ret[1],ret[0]); |
| #endif |
| return(H(tmp)); |
| } |
| |
| /* ret[3,2,1,0] += a1,a0 * a1,a0 */ |
| void BN_sqr_4words(ret,a0,a1) |
| BN_ULONG *ret; |
| BN_ULONG a0,a1; |
| { |
| BN_ULONG s,u; |
| BN_ULLONG tmp,tmp2; |
| |
| tmp=(BN_ULLONG)a0*a0; |
| ret[0]=L(tmp); |
| |
| tmp2=(BN_ULLONG)a0*a1; |
| tmp=(BN_ULLONG)H(tmp)+L(tmp2)*2; |
| ret[1]=L(tmp); |
| |
| tmp=(BN_ULLONG)a1*a1+H(tmp)+H(tmp2)*2; |
| ret[2]=L(tmp); |
| ret[3]=L(tmp); |
| } |
| |
| #define N0 (0) |
| #define N1 (half) |
| #define N2 (num) |
| #define N3 (num+half) |
| |
| #define word_cmp(r,a,b,num) \ |
| { \ |
| int n=num; \ |
| \ |
| (r)=0; \ |
| while (n--) \ |
| { \ |
| if ((a)[(n)] > (b)[(n)]) \ |
| { (r)=1; break; } \ |
| else if ((a)[(n)] < (b)[(n)]) \ |
| { (r)= -1; break; } \ |
| } \ |
| } |
| |
| |
| /* (a->top == b->top) && (a->top >= 2) && !(a->top & 1) */ |
| void bn_recursize_mul(r,t,a,b,num) |
| BN_ULONG *r,*t,*a,*b; |
| int num; |
| { |
| if ((num < 2) || (num&1)) |
| abort(); |
| |
| /* fprintf(stderr,"num=%d half=%d\n",num,num/2);*/ |
| if (num == 2) |
| BN_mul_4words(r,a[0],a[1],b[0],b[1]); |
| else if (num == 4) |
| { |
| BN_ULONG c,tmp; |
| |
| BN_mul_4words(&(r[0]),a[0],a[1],b[0],b[1]); |
| BN_mul_4words(&(r[4]),a[2],a[3],b[2],b[3]); |
| |
| c =BN_mul_add_4words(&(r[2]),a[0],a[1],b[2],b[3]); |
| c+=BN_mul_add_4words(&(r[2]),a[2],a[3],b[0],b[1]); |
| |
| bn_add_word(&(r[6]),c,2); |
| } |
| else |
| { |
| int half=num/2; |
| int carry,cmp_a,cmp_b; |
| |
| word_cmp(cmp_a,&(a[0]),&(a[half]),half); |
| word_cmp(cmp_b,&(b[0]),&(b[half]),half); |
| |
| switch (cmp_a*2+cmp_a+cmp_b) |
| { |
| case -4: |
| bn_sub_words(&(t[N0]),&(a[N1]),&(a[N0]),half); |
| bn_sub_words(&(t[N1]),&(b[N0]),&(b[N1]),half); |
| bn_recursize_mul(&(r[N1]),&(t[N2]), |
| &(t[N0]),&(t[N1]),half); |
| bn_sub_words(&(r[N2]),&(r[N2]),&(t[N0]),half); |
| carry= -1; |
| break; |
| case -2: |
| bn_sub_words(&(t[N0]),&(a[N1]),&(a[N0]),half); |
| bn_sub_words(&(t[N1]),&(b[N0]),&(b[N1]),half); |
| bn_recursize_mul(&(r[N1]),&(t[N2]), |
| &(t[N0]),&(t[N1]),half); |
| carry=0; |
| break; |
| case 2: |
| bn_sub_words(&(t[N0]),&(a[N0]),&(a[N1]),half); |
| bn_sub_words(&(t[N1]),&(b[N1]),&(b[N0]),half); |
| bn_recursize_mul(&(r[N1]),&(t[N2]), |
| &(t[N0]),&(t[N1]),half); |
| carry=0; |
| break; |
| case 4: |
| bn_sub_words(&(t[N0]),&(a[N1]),&(a[N0]),half); |
| bn_sub_words(&(t[N1]),&(b[N0]),&(b[N1]),half); |
| bn_recursize_mul(&(r[N1]),&(t[N2]), |
| &(t[N0]),&(t[N1]),half); |
| bn_sub_words(&(r[N2]),&(r[N2]),&(t[N1]),half); |
| carry= -1; |
| break; |
| default: |
| memset(&(r[N1]),0,sizeof(BN_ULONG)*num); |
| break; |
| } |
| |
| bn_recursize_mul(&(t[N0]),&(t[N2]),&(a[N0]),&(b[N0]),half); |
| #ifdef DEBUG |
| pr(a,half," * "); |
| pr(b,half," - "); |
| pr(t,num," - 0\n"); |
| #endif |
| memcpy(&(r[N0]),&(t[N0]),half*sizeof(BN_ULONG)); |
| if (bn_add_words(&(r[N1]),&(r[N1]),&(t[N1]),half)) |
| { bn_add_word(&(t[N1]),1,half); } |
| |
| carry+=bn_add_words(&(r[N1]),&(r[N1]),&(t[N0]),num); |
| |
| bn_recursize_mul(&(t[N0]),&(t[N2]),&(a[N1]),&(b[N1]),half); |
| |
| carry+=bn_add_words(&(r[N1]),&(r[N1]),&(t[N0]),num); |
| carry+=bn_add_words(&(r[N2]),&(r[N2]),&(t[N0]),half); |
| memcpy(&(r[N3]),&(t[N1]),half*sizeof(BN_ULONG)); |
| |
| bn_add_word(&(r[N3]),carry,half); |
| } |
| } |
| |
| main() |
| { |
| BIGNUM *a,*b,*r,*t; |
| int i,j; |
| |
| a=BN_new(); |
| b=BN_new(); |
| r=BN_new(); |
| t=BN_new(); |
| |
| #define BITS 1024 |
| bn_expand(r,BITS*2); |
| bn_expand(t,BITS*2); |
| fprintf(stdout,"obase=16\n"); |
| fprintf(stdout,"ibase=16\n"); |
| for (i=0; i<10; i++) |
| { |
| BN_rand(a,BITS,0,0); |
| BN_rand(b,BITS,0,0); |
| r->top=(BITS*2)/BN_BITS2; |
| memset(r->d,0,sizeof(r->top)*sizeof(BN_ULONG)); |
| memset(t->d,0,sizeof(r->top)*sizeof(BN_ULONG)); |
| for (j=0; j<1000; j++) |
| { |
| |
| /* BN_mul(r,a,b); /**/ |
| bn_recursize_mul(r->d,t->d,a->d,b->d,a->top); /**/ |
| } |
| BN_print(stdout,a); fprintf(stdout," * "); |
| BN_print(stdout,b); fprintf(stdout," - "); |
| BN_print(stdout,r); fprintf(stdout,"\n"); |
| } |
| } |