296 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			296 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /* polynomial basis GF(2^w) routines */ | ||
|  | #include "mycrypt.h"
 | ||
|  | 
 | ||
|  | #ifdef GF
 | ||
|  | 
 | ||
|  | #define FORLOOP for (i = 0; i < LSIZE; i++) 
 | ||
|  | 
 | ||
|  | /* c = a + b */ | ||
|  | void gf_add(gf_intp a, gf_intp b, gf_intp c) | ||
|  | { | ||
|  |    int i; | ||
|  |    FORLOOP c[i] = a[i]^b[i]; | ||
|  | } | ||
|  | 
 | ||
|  | /* b = a */ | ||
|  | void gf_copy(gf_intp a, gf_intp b) | ||
|  | { | ||
|  |    int i; | ||
|  |    FORLOOP b[i] = a[i]; | ||
|  | } | ||
|  | 
 | ||
|  | /* a = 0 */ | ||
|  | void gf_zero(gf_intp a) | ||
|  | { | ||
|  |    int i; | ||
|  |    FORLOOP a[i] = 0; | ||
|  | } | ||
|  | 
 | ||
|  | /* is a zero? */ | ||
|  | int gf_iszero(gf_intp a) | ||
|  | { | ||
|  |    int i; | ||
|  |    FORLOOP if (a[i]) { | ||
|  |       return 0; | ||
|  |    } | ||
|  |    return 1; | ||
|  | } | ||
|  | 
 | ||
|  | /* is a one? */ | ||
|  | int gf_isone(gf_intp a) | ||
|  | {  | ||
|  |    int i; | ||
|  |    for (i = 1; i < LSIZE; i++) { | ||
|  |        if (a[i]) { | ||
|  |           return 0; | ||
|  |        } | ||
|  |    } | ||
|  |    return a[0] == 1; | ||
|  | } | ||
|  | 
 | ||
|  | /* b = a << 1*/ | ||
|  | void gf_shl(gf_intp a, gf_intp b) | ||
|  | { | ||
|  |    int i; | ||
|  |    gf_int tmp; | ||
|  | 
 | ||
|  |    gf_copy(a, tmp); | ||
|  |    for (i = LSIZE-1; i > 0; i--)  | ||
|  |        b[i] = ((tmp[i]<<1)|((tmp[i-1]&0xFFFFFFFFUL)>>31))&0xFFFFFFFFUL; | ||
|  |    b[0] = (tmp[0] << 1)&0xFFFFFFFFUL; | ||
|  |    gf_zero(tmp); | ||
|  | } | ||
|  | 
 | ||
|  | /* b = a >> 1 */ | ||
|  | void gf_shr(gf_intp a, gf_intp b) | ||
|  | { | ||
|  |    int i; | ||
|  |    gf_int tmp; | ||
|  | 
 | ||
|  |    gf_copy(a, tmp); | ||
|  |    for (i = 0; i < LSIZE-1; i++) | ||
|  |        b[i] = (((tmp[i]&0xFFFFFFFFUL)>>1)|(tmp[i+1]<<31))&0xFFFFFFFFUL; | ||
|  |    b[LSIZE-1] = (tmp[LSIZE-1]&0xFFFFFFFFUL)>>1; | ||
|  |    gf_zero(tmp); | ||
|  | } | ||
|  | 
 | ||
|  | /* returns -1 if its zero, otherwise degree of a */ | ||
|  | int gf_deg(gf_intp a) | ||
|  | { | ||
|  |    int i, ii; | ||
|  |    unsigned long t; | ||
|  | 
 | ||
|  |    ii = -1; | ||
|  |    for (i = LSIZE-1; i >= 0; i--) | ||
|  |        if (a[i]) { | ||
|  |           for (t = a[i], ii = 0; t; t >>= 1, ++ii); | ||
|  |           break; | ||
|  |        } | ||
|  |    if (i == -1) i = 0; | ||
|  |    return (i<<5)+ii; | ||
|  | } | ||
|  | 
 | ||
|  | /* c = ab */ | ||
|  | void gf_mul(gf_intp a, gf_intp b, gf_intp c) | ||
|  | { | ||
|  |    gf_int ta, tb; | ||
|  |    int i, n; | ||
|  | 
 | ||
|  |    gf_copy(a, ta); | ||
|  |    gf_copy(b, tb); | ||
|  |    gf_zero(c); | ||
|  |    n = gf_deg(ta)+1; | ||
|  |    for (i = 0; i < n; i++) { | ||
|  |        if (ta[i>>5]&(1<<(i&31))) | ||
|  |           gf_add(c, tb, c); | ||
|  |        gf_shl(tb, tb); | ||
|  |    } | ||
|  |    gf_zero(ta); | ||
|  |    gf_zero(tb); | ||
|  | } | ||
|  | 
 | ||
|  | /* q = a/b, r = a%b */ | ||
|  | void gf_div(gf_intp a, gf_intp b, gf_intp q, gf_intp r) | ||
|  | { | ||
|  |    gf_int ta, tb, shifts[LSIZE*32]; | ||
|  |    int i, magb, mag; | ||
|  | 
 | ||
|  |    mag  = gf_deg(a); | ||
|  |    magb = gf_deg(b); | ||
|  | 
 | ||
|  |    /* special cases */ | ||
|  |    if (magb > mag) { | ||
|  |       gf_copy(a, r); | ||
|  |       gf_zero(q); | ||
|  |       return; | ||
|  |    } | ||
|  |    if (magb == -1) { | ||
|  |       return; | ||
|  |    } | ||
|  | 
 | ||
|  |    /* copy locally */ | ||
|  |    gf_copy(a, ta); | ||
|  |    gf_copy(b, tb); | ||
|  |    gf_zero(q); | ||
|  | 
 | ||
|  |    /* make shifted versions of "b" */ | ||
|  |    gf_copy(tb, shifts[0]); | ||
|  |    for (i = 1; i <= (mag-magb); i++)  | ||
|  |        gf_shl(shifts[i-1], shifts[i]); | ||
|  | 
 | ||
|  |    while (mag >= magb) { | ||
|  |        i = (mag - magb); | ||
|  |        q[i>>5] |= (1<<(i&31)); | ||
|  |        gf_add(ta, shifts[i], ta); | ||
|  |        mag = gf_deg(ta); | ||
|  |    } | ||
|  |    gf_copy(ta, r); | ||
|  |    gf_zero(ta); | ||
|  |    gf_zero(tb); | ||
|  |    zeromem(shifts, sizeof(shifts)); | ||
|  | } | ||
|  | 
 | ||
|  | /* b = a mod m */ | ||
|  | void gf_mod(gf_intp a, gf_intp m, gf_intp b) | ||
|  | { | ||
|  |    gf_int tmp; | ||
|  |    gf_div(a,m,tmp,b); | ||
|  |    gf_zero(tmp); | ||
|  | } | ||
|  | 
 | ||
|  | /* c = ab (mod m) */ | ||
|  | void gf_mulmod(gf_intp a, gf_intp b, gf_intp m, gf_intp c) | ||
|  | { | ||
|  |    gf_int tmp; | ||
|  |    gf_mul(a, b, tmp); | ||
|  |    gf_mod(tmp, m, c); | ||
|  |    gf_zero(tmp); | ||
|  | } | ||
|  | 
 | ||
|  | /* B = 1/A mod M */ | ||
|  | void gf_invmod(gf_intp A, gf_intp M, gf_intp B) | ||
|  | { | ||
|  |   gf_int m, n, p0, p1, p2, r, q, tmp; | ||
|  | 
 | ||
|  |   /* put all variables in known setup state */ | ||
|  |   gf_zero(p0); | ||
|  |   gf_zero(p2); | ||
|  |   gf_copy(M, m); | ||
|  |   gf_copy(A, n); | ||
|  |   p0[0] = 1; | ||
|  |   gf_div(m, n, p1, r); | ||
|  |   gf_copy(p1, q); | ||
|  | 
 | ||
|  |   /* loop until r == 0 */ | ||
|  |   while (!gf_iszero(r)) { | ||
|  |      gf_copy(n, m); | ||
|  |      gf_copy(r, n); | ||
|  |      gf_div(m, n, q, r); | ||
|  |      gf_mul(q, p1, tmp); | ||
|  |      gf_add(tmp, p0, p2); | ||
|  |      gf_copy(p1, p0); | ||
|  |      gf_copy(p2, p1); | ||
|  |   } | ||
|  |   gf_copy(p0, B); | ||
|  |   gf_zero(p0); | ||
|  | } | ||
|  | 
 | ||
|  | /* find a square root modulo a prime.  Note the number of 
 | ||
|  |  * elements is 2^k - 1, so we must square k-2 times to get the | ||
|  |  * square root..  | ||
|  |  */ | ||
|  | void gf_sqrt(gf_intp a, gf_intp M, gf_intp b) | ||
|  | { | ||
|  |    int k; | ||
|  |    k = gf_deg(M)-2; | ||
|  |    gf_copy(a, b); | ||
|  |    while (k--) | ||
|  |       gf_mulmod(b, b, M, b); | ||
|  | } | ||
|  | 
 | ||
|  | /* c = gcd(A,B) */ | ||
|  | void gf_gcd(gf_intp A, gf_intp B, gf_intp c) | ||
|  | { | ||
|  |    gf_int a, b, r; | ||
|  |    int n; | ||
|  | 
 | ||
|  |    gf_add(A, B, r); | ||
|  |    n = gf_deg(r); | ||
|  |    if (gf_deg(A) > n) { | ||
|  |       gf_copy(A, a); | ||
|  |       gf_copy(B, b); | ||
|  |    } else { | ||
|  |       gf_copy(A, b); | ||
|  |       gf_copy(B, a); | ||
|  |    } | ||
|  | 
 | ||
|  |    do { | ||
|  |       gf_mod(a, b, r); | ||
|  |       gf_copy(b, a); | ||
|  |       gf_copy(r, b); | ||
|  |    } while (!gf_iszero(r)); | ||
|  |    gf_copy(a, c); | ||
|  |    gf_zero(a); | ||
|  |    gf_zero(b); | ||
|  | } | ||
|  | 
 | ||
|  | /* returns non-zero if 'a' is irreducible */ | ||
|  | int gf_is_prime(gf_intp a) | ||
|  | { | ||
|  |    gf_int u, tmp; | ||
|  |    int m, n; | ||
|  | 
 | ||
|  |    gf_zero(u); | ||
|  |    u[0] = 2;			/* u(x) = x */ | ||
|  |    m = gf_deg(a); | ||
|  |    for (n = 0; n < (m/2); n++) {  | ||
|  |        gf_mulmod(u, u, a, u);   /* u(x) = u(x)^2 mod a(x) */ | ||
|  |        gf_copy(u, tmp); | ||
|  |        tmp[0] ^= 2;		/* tmp(x) = u(x) - x */ | ||
|  |        gf_gcd(tmp, a, tmp);     /* tmp(x) = gcd(a(x), u(x) - x) */ | ||
|  |        if (!gf_isone(tmp)) { | ||
|  |           return 0; | ||
|  |        } | ||
|  |    } | ||
|  |    return 1; | ||
|  | }   | ||
|  | 
 | ||
|  | /* returns bytes required to store a gf_int */ | ||
|  | int gf_size(gf_intp a) | ||
|  | { | ||
|  |    int n; | ||
|  | 
 | ||
|  |    n = gf_deg(a); | ||
|  |    if (n == -1) { | ||
|  |       return 4; | ||
|  |    } | ||
|  |    n = n + (32 - (n&31)); | ||
|  |    return n/8; | ||
|  | } | ||
|  | 
 | ||
|  | /* store a gf_int */ | ||
|  | void gf_toraw(gf_intp a, unsigned char *dst) | ||
|  | { | ||
|  |    int x, n; | ||
|  |    n = gf_size(a)/4; | ||
|  |    for (x = 0; x < n; x++) { | ||
|  |        STORE32L(a[x], dst); | ||
|  |        dst += 4; | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | /* read a gf_int (len == in bytes) */ | ||
|  | void gf_readraw(gf_intp a, unsigned char *str, int len) | ||
|  | { | ||
|  |    int x; | ||
|  |    gf_zero(a); | ||
|  |    for (x = 0; x < len/4; x++) { | ||
|  |        LOAD32L(a[x], str); | ||
|  |        str += 4; | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 
 |