📄 bn_knuth.c
字号:
/* crypto/bn/bn_knuth.c */#include <stdio.h>#include "cryptlib.h"#include "bn.h"/* This is just a test implementation, it has not been modified for * speed and it still has memory leaks. */int BN_mask_bits(BIGNUM *a,int n);#undef DEBUG#define MAIN/* r must be different to a and b * Toom-Cook multiplication algorithm, taken from * The Art Of Computer Programming, Volume 2, Donald Knuth */#define CODE1 ((BIGNUM *)0x01)#define CODE2 ((BIGNUM *)0x02)#define CODE3 ((BIGNUM *)0x03)#define MAXK (30+1)#define C3 3#define C4 4#define C5 5#define C6 6#define C7 7#define C8 8#define C9 9#define C10 10#define DONE 11int new_total=0;int Free_total=0;int max=0,max_total=0;BIGNUM *LBN_new(void );BIGNUM *LBN_dup(BIGNUM *a);void LBN_free(BIGNUM *a);int BN_mul_knuth(w, a, b)BIGNUM *w;BIGNUM *a;BIGNUM *b; { int ret=1; int i,j,n,an,bn,y,z; BIGNUM *U[MAXK],*V[MAXK],*T[MAXK]; BIGNUM *C[(MAXK*2*3)]; BIGNUM *W[(MAXK*2)],*t1,*t2,*t3,*t4; int Utos,Vtos,Ctos,Wtos,Ttos; unsigned int k,Q,R; unsigned int q[MAXK]; unsigned int r[MAXK]; int state; /* C1 */ Utos=Vtos=Ctos=Wtos=Ttos=0; k=1; q[0]=q[1]=64; r[0]=r[1]=4; Q=6; R=2; if (!bn_expand(w,BN_BITS2*2)) goto err; an=BN_num_bits(a); bn=BN_num_bits(b); n=(an > bn)?an:bn; while ((q[k-1]+q[k]) < n) { k++; Q+=R; i=R+1; if ((i*i) <= Q) R=i; q[k]=(1<<Q); r[k]=(1<<R); }#ifdef DEBUG printf("k ="); for (i=0; i<=k; i++) printf("%7d",i); printf("\nq[k]="); for (i=0; i<=k; i++) printf("%7d",q[i]); printf("\nr[k]="); for (i=0; i<=k; i++) printf("%7d",r[i]); printf("\n");#endif /* C2 */ C[Ctos++]=CODE1; if ((t1=LBN_dup(a)) == NULL) goto err; C[Ctos++]=t1; if ((t1=LBN_dup(b)) == NULL) goto err; C[Ctos++]=t1; state=C3; for (;;) {#ifdef DEBUG printf("state=C%d, Ctos=%d Wtos=%d\n",state,Ctos,Wtos);#endif switch (state) { int lr,lq,lp; case C3: k--; if (k == 0) { t1=C[--Ctos]; t2=C[--Ctos];#ifdef DEBUG printf("Ctos=%d poped %d\n",Ctos,2);#endif if ((t2->top == 0) || (t1->top == 0)) w->top=0; else BN_mul(w,t1,t2); LBN_free(t1); /* FREE */ LBN_free(t2); /* FREE */ state=C10; } else { lr=r[k]; lq=q[k]; lp=q[k-1]+q[k]; state=C4; } break; case C4: for (z=0; z<2; z++) /* do for u and v */ { /* break the item at C[Ctos-1] * into lr+1 parts of lq bits each * for j=0; j<=2r; j++ */ t1=C[--Ctos]; /* pop off u */#ifdef DEBUG printf("Ctos=%d poped %d\n",Ctos,1);#endif if ((t2=LBN_dup(t1)) == NULL) goto err; BN_mask_bits(t2,lq); T[Ttos++]=t2;#ifdef DEBUG printf("C4 r=0 bits=%d\n",BN_num_bits(t2));#endif for (i=1; i<=lr; i++) { if (!BN_rshift(t1,t1,lq)) goto err; if ((t2=LBN_dup(t1)) == NULL) goto err; BN_mask_bits(t2,lq); T[Ttos++]=t2;#ifdef DEBUG printf("C4 r=%d bits=%d\n",i, BN_num_bits(t2));#endif } LBN_free(t1); if ((t2=LBN_new()) == NULL) goto err; if ((t3=LBN_new()) == NULL) goto err; for (j=0; j<=2*lr; j++) { if ((t1=LBN_new()) == NULL) goto err; if (!BN_set_word(t3,j)) goto err; for (i=lr; i>=0; i--) { if (!BN_mul(t2,t1,t3)) goto err; if (!BN_add(t1,t2,T[i])) goto err; } /* t1 is U(j) */ if (z == 0) U[Utos++]=t1; else V[Vtos++]=t1; } LBN_free(t2); LBN_free(t3); while (Ttos) LBN_free(T[--Ttos]); }#ifdef DEBUG for (i=0; i<Utos; i++) printf("U[%2d]=%4d bits\n",i,BN_num_bits(U[i])); for (i=0; i<Vtos; i++) printf("V[%2d]=%4d bits\n",i,BN_num_bits(V[i]));#endif /* C5 */#ifdef DEBUG printf("PUSH CODE2 and %d CODE3 onto stack\n",2*lr);#endif C[Ctos++]=CODE2; for (i=2*lr; i>0; i--) { C[Ctos++]=V[i]; C[Ctos++]=U[i]; C[Ctos++]=CODE3; } C[Ctos++]=V[0]; C[Ctos++]=U[0];#ifdef DEBUG printf("Ctos=%d pushed %d\n",Ctos,2*lr*3+3);#endif Vtos=Utos=0; state=C3; break; case C6: if ((t1=LBN_dup(w)) == NULL) goto err; W[Wtos++]=t1;#ifdef DEBUG printf("put %d bit number onto w\n",BN_num_bits(t1));#endif state=C3; break; case C7: lr=r[k]; lq=q[k]; lp=q[k]+q[k-1]; z=Wtos-2*lr-1; for (j=1; j<=2*lr; j++) { for (i=2*lr; i>=j; i--) { if (!BN_sub(W[z+i],W[z+i],W[z+i-1])) goto err; BN_div_word(W[z+i],j); } } state=C8; break; case C8: y=2*lr-1; if ((t1=LBN_new()) == NULL) goto err; if ((t3=LBN_new()) == NULL) goto err; for (j=y; j>0; j--) { if (!BN_set_word(t3,j)) goto err; for (i=j; i<=y; i++) { if (!BN_mul(t1,W[z+i+1],t3)) goto err; if (!BN_sub(W[z+i],W[z+i],t1)) goto err; } } LBN_free(t1); LBN_free(t3); state=C9; break; case C9: BN_zero(w);#ifdef DEBUG printf("lq=%d\n",lq);#endif for (i=lr*2; i>=0; i--) { BN_lshift(w,w,lq); BN_add(w,w,W[z+i]); } for (i=0; i<=lr*2; i++) LBN_free(W[--Wtos]); state=C10; break; case C10: k++; t1=C[--Ctos];#ifdef DEBUG printf("Ctos=%d poped %d\n",Ctos,1); printf("code= CODE%d\n",t1);#endif if (t1 == CODE3) state=C6; else if (t1 == CODE2) { if ((t2=LBN_dup(w)) == NULL) goto err; W[Wtos++]=t2; state=C7; } else if (t1 == CODE1) { state=DONE; } else { printf("BAD ERROR\n"); goto err; } break; default: printf("bad state\n"); goto err; break; } if (state == DONE) break; } ret=1;err: if (ret == 0) printf("ERROR\n"); return(ret); }#ifdef MAINmain() { BIGNUM *a,*b,*r; int i; if ((a=LBN_new()) == NULL) goto err; if ((b=LBN_new()) == NULL) goto err; if ((r=LBN_new()) == NULL) goto err; if (!BN_rand(a,1024*2,0,0)) goto err; if (!BN_rand(b,1024*2,0,0)) goto err; for (i=0; i<10; i++) { if (!BN_mul_knuth(r,a,b)) goto err; /**/ /*if (!BN_mul(r,a,b)) goto err; /**/ }BN_print(stdout,a); printf(" * ");BN_print(stdout,b); printf(" =\n");BN_print(stdout,r); printf("\n");printf("BN_new() =%d\nBN_free()=%d max=%d\n",new_total,Free_total,max); exit(0);err: ERR_load_crypto_strings(); ERR_print_errors(stderr); exit(1); }#endifint BN_mask_bits(a,n)BIGNUM *a;int n; { int b,w; w=n/BN_BITS2; b=n%BN_BITS2; if (w >= a->top) return(0); if (b == 0) a->top=w; else { a->top=w+1; a->d[w]&= ~(BN_MASK2<<b); } return(1); }BIGNUM *LBN_dup(a)BIGNUM *a; { new_total++; max_total++; if (max_total > max) max=max_total; return(BN_dup(a)); }BIGNUM *LBN_new() { new_total++; max_total++; if (max_total > max) max=max_total; return(BN_new()); }void LBN_free(a)BIGNUM *a; { max_total--; if (max_total > max) max=max_total; Free_total++; BN_free(a); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -