/* ------------------------------------------------------------------------------ mix.c: some sort of block cipher. By Bob Jenkins, 1997. Public Domain. ------------------------------------------------------------------------------ */ #ifndef STANDARD #include "standard.h" #endif #ifndef MIX #include "mix.h" #endif #define xor(a,b) (a ^ b) #define or(a,b) (a | b) #define and(a,b) (a & b) #define ant(a,b) (~a & b) #define not(a) ~a #define read(x,i) x[i*2] #define write(y,i,a) y[i*2] = a /* apply the 8-bit permutation to the even bits */ static void eight( ub8 *x, ub8 *y) { ub8 q,r; ub8 a0 = read(x,0); ub8 a1 = read(x,1); ub8 a2 = read(x,2); ub8 a3 = read(x,3); ub8 a4 = read(x,4); ub8 a5 = read(x,5); ub8 a6 = read(x,6); ub8 a7 = read(x,7); q = xor(a4,a5); r = xor(a7,a0); write(y,0,xor(q,r)); q = xor(a5,a1); r = xor(a3,a2); write(y,1,xor(q,r)); q = xor(a3,a4); r = xor(a5,a1); write(y,2,xor(q,r)); q = ant(xor(a0,a3),xor(a6,a4)); r = ant(xor(a4,a6),or(and(a0,a1),ant(a0,a3))); write(y,3,or(q,r)); q = ant(xor(a6,a7),xor(a5,a2)); r = and(or(not(or(a2,a5)),and(a4,a5)),xor(a7,a6)); write(y,4,or(q,r)); q = and(xor(a5,a0),xor(a4,a2)); r = ant(xor(a2,a4),or(and(a0,a5),ant(a0,a1))); write(y,5,or(q,r)); q = and(xor(a4,a2),xor(a7,a6)); r = ant(xor(a2,a4),or(ant(a7,a0),and(a6,a7))); write(y,6,or(q,r)); q = and(or(not(or(a6,a7)),ant(and(a6,a7),a0)),xor(a4,a2)); r = ant(xor(a2,a4),or(ant(and(a0,a2),a6),ant(a0,a7))); write(y,7,or(q,r)); } static int shift[16] = {14,55,61,35,30,60,32,49,16,4,42,5,26,11,47,17}; static int map[16] = {2,12,8,3,1,15,11,0,14,5,13,7,9,4,10,6}; /* one permutation of the internal state */ static void perm(ub8 *x) { int i; ub8 y[16]; /* do 128 8-bit permutations */ eight(x, y); eight(&x[1], &y[1]); /* break symmetry among the 64 16-bit permutations */ y[0] ^= 0x18f8aa72369b75c2LL; y[1] ^= 0x337b824aab77201fLL; y[2] ^= 0x60bd51315e37b49cLL; y[3] ^= 0x82ed31eb138e02efLL; y[4] ^= 0x5fe101ed66fc3130LL; y[5] ^= 0x1019906dca58dffbLL; /* shuffle and rotate the 16 output bits among the 64 chunks */ x[ 2] = (y[0] << 14) | (y[0] >> (64-14)); x[12] = (y[1] << 55) | (y[1] >> (64-55)); x[ 8] = (y[2] << 61) | (y[2] >> (64-61)); x[ 3] = (y[3] << 35) | (y[3] >> (64-35)); x[ 1] = (y[4] << 30) | (y[4] >> (64-30)); x[15] = (y[5] << 60) | (y[5] >> (64-60)); x[11] = (y[6] << 32) | (y[6] >> (64-32)); x[ 0] = (y[7] << 49) | (y[7] >> (64-49)); x[14] = (y[8] << 16) | (y[8] >> (64-16)); x[ 5] = (y[9] << 4) | (y[9] >> (64- 4)); x[13] = (y[10]<< 42) | (y[10]>> (64-42)); x[ 7] = (y[11]<< 5) | (y[11]>> (64- 5)); x[ 9] = (y[12]<< 26) | (y[12]>> (64-26)); x[ 4] = (y[13]<< 11) | (y[13]>> (64-11)); x[10] = (y[14]<< 47) | (y[14]>> (64-47)); x[ 6] = (y[15]<< 17) | (y[15]>> (64-17)); } static int unperm[256]; /* the inverse of eight(x,y) */ static void uneight(ub8 *y, ub8 *x) { int i, j; for (i=0; i<8; ++i) { x[2*i] = 0; } for (i=0; i<64; ++i) { int z = 0; for (j=0; j<8; ++j) { if (y[2*j] & (((ub8)1)<> shift[i]) | (y[i] << (64-shift[i])); } /* break symmetry among the 64 16-bit permutations */ y[0] ^= 0x18f8aa72369b75c2LL; y[1] ^= 0x337b824aab77201fLL; y[2] ^= 0x60bd51315e37b49cLL; y[3] ^= 0x82ed31eb138e02efLL; y[4] ^= 0x5fe101ed66fc3130LL; y[5] ^= 0x1019906dca58dffbLL; /* revert the two 8-bit permutations */ uneight(&y[1], &x[1]); uneight(y, x); } /* mix the x */ void mix(x) ub4 *x; { ub8 x2[16]; memcpy(x2, x, sizeof(x2)); perm(x2); memcpy(x, x2, sizeof(x2)); } /* the reverse of mix */ void unmix(x) ub4 *x; { ub8 x2[16]; memcpy(x2, x, sizeof(x2)); iperm(x2); memcpy(x, x2, sizeof(x2)); } /* given the x at some point in the mix, roll back to the start */ void preimage(x) ub4 *x; { ub8 x2[16]; memcpy(x2, x, sizeof(x2)); memcpy(x, x2, sizeof(x2)); } /* given the x at some point in the mix, roll forward to the end */ void postimage(x) ub4 *x; { ub8 x2[16]; memcpy(x2, x, sizeof(x2)); perm(x2); memcpy(x, x2, sizeof(x2)); }