typedef unsigned char uchar; typedef unsigned long ulong; typedef unsigned long long uvlong; #include "des.h" static uchar initperm[] = { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7, }; static uchar finalperm[] = { 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25, }; /* expand, for round function */ static uchar eperm[] = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1, }; /* permute, for round function */ static uchar pperm[] = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25, }; static uchar sbox[8][64] = { { /* s1 */ 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13, }, { /* s2 */ 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2, 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9, }, { /* s3 */ 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12, }, { /* s4 */ 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9, 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14, }, { /* s5 */ 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13, 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3, }, { /* s6 */ 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13, }, { /* s7 */ 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12, }, { /* s8 */ 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11, }, }; /* key permutation 1 for c */ static uchar pc1perm0[] = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, }; /* key permutation 1 for d */ static uchar pc1perm1[] = { 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4, }; /* key permutation 2 */ static uchar pc2perm[] = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32, }; static uchar keyshifts[] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, }; enum { Mask6 = (1<<6)-1, Mask7 = (1<<7)-1, Mask28 = (1<<28)-1, }; static ulong g32(uchar *p) { ulong v; v = 0; v = (v<<8)|*p++; v = (v<<8)|*p++; v = (v<<8)|*p++; v = (v<<8)|*p++; return v; } static void p32(uchar *p, ulong v) { *p++ = v>>24; *p++ = v>>16; *p++ = v>>8; *p++ = v>>0; } /* input 32 bit, output 6 bit */ static uchar perm6(ulong r, uchar *index) { uchar v; int i; v = 0; for(i = 0; i < 6; i++) v |= ((r>>(32-index[i]))&1)<<(6-1-i); return v; } /* input 32 bit, output 32 bit */ static ulong perm32(ulong r, uchar *index) { ulong v; int i; v = 0; for(i = 0; i < 32; i++) v |= ((r>>(32-index[i]))&1)<<(32-1-i); return v; } /* input 64 bit, output 28 bit */ static ulong perm28(uvlong r, uchar *index) { ulong v; int i; v = 0; for(i = 0; i < 28; i++) v |= ((r>>(64-index[i]))&1)<<(28-1-i); return v; } /* input 56 bit, output 48 bit */ static uvlong perm56(uvlong r, uchar *index) { uvlong v; int i; v = 0; for(i = 0; i < 48; i++) v |= ((r>>(56-index[i]))&1)<<(48-1-i); return v; } /* input 64 bit, output 64 bit */ static uvlong perm64(uvlong r, uchar *index) { uvlong v; int i; v = 0; for(i = 0; i < 64; i++) v |= ((r>>(64-index[i]))&1)<<(64-1-i); return v; } static ulong f(ulong r, uvlong k) { ulong p; uchar ei, ki; int i, j; p = 0; for(i = 0; i < 8; i++) { j = 7-i; ei = perm6(r, eperm+i*6); ki = (k>>(j*6))&Mask6; p |= (ulong)sbox[i][ei^ki]<<(j*4); } return perm32(p, pperm); } static ulong rotateleft28(ulong v, int i) { ulong left, right; left = (v<>(28-i))&((1<keys[i] = perm56(((uvlong)c<<28)|d, pc2perm); } } static void descrypt(Desks *ks, void *buf, int s, int e, int delta) { ulong l, r, tmp; uvlong v; int i; v = g32(buf); v = (v<<32)|g32(buf+4); v = perm64(v, initperm); l = v>>32; r = v; for(i = s; i != e; i += delta) { tmp = r; r = l^f(r, ks->keys[i]); l = tmp; } v = r; v = (v<<32)|l; v = perm64(v, finalperm); p32(buf, v>>32); p32(buf+4, v); } void deskey56(Desks *ks, uchar *k56) { uvlong t, k; int i, j; t = 0; for(i = 0; i < 7; i++) t = (t<<8)|*k56++; k = 0; for(i = 0; i < 8; i++) { j = 8-1-i; k |= ((t>>(j*7))&Mask7)<<(j*8+1); } deskey(ks, k); } void deskey64(Desks *ks, uchar *k64) { uvlong k; int i; k = 0; for(i = 0; i < 8; i++) k = (k<<8)|*k64++; deskey(ks, k); } void desenc(Desks *ks, void *buf) { descrypt(ks, buf, 0, 16, 1); } void desdec(Desks *ks, void *buf) { descrypt(ks, buf, 15, -1, -1); }