Initial revision
[crypto.git] / lib / silccrypt / crypton.c
1 /* Modified for SILC. -Pekka */\r
2 \r
3 /* This is an independent implementation of the encryption algorithm:   */\r
4 /*                                                                      */\r
5 /*         CRYPTON by Chae Hoon Lim of Future Systms Inc                */\r
6 /*                                                                      */\r
7 /* which is a candidate algorithm in the Advanced Encryption Standard   */\r
8 /* programme of the US National Institute of Standards and Technology.  */\r
9 /*                                                                      */\r
10 /* Copyright in this implementation is held by Dr B R Gladman but I     */\r
11 /* hereby give permission for its free direct or derivative use subject */\r
12 /* to acknowledgment of its origin and compliance with any conditions   */\r
13 /* that the originators of the algorithm place on its exploitation.     */\r
14 /*                                                                      */\r
15 /* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999     */\r
16 \r
17 /* Timing data for CRYPTON (crypton.c)\r
18 \r
19 128 bit key:\r
20 Key Setup:    531/1369 cycles (encrypt/decrypt)\r
21 Encrypt:       474 cycles =    54.0 mbits/sec\r
22 Decrypt:       474 cycles =    54.0 mbits/sec\r
23 Mean:          474 cycles =    54.0 mbits/sec\r
24 \r
25 192 bit key:\r
26 Key Setup:    539/1381 cycles (encrypt/decrypt)\r
27 Encrypt:       473 cycles =    54.1 mbits/sec\r
28 Decrypt:       470 cycles =    54.5 mbits/sec\r
29 Mean:          472 cycles =    54.3 mbits/sec\r
30 \r
31 256 bit key:\r
32 Key Setup:    552/1392 cycles (encrypt/decrypt)\r
33 Encrypt:       469 cycles =    54.6 mbits/sec\r
34 Decrypt:       483 cycles =    53.0 mbits/sec\r
35 Mean:          476 cycles =    53.8 mbits/sec\r
36 \r
37 */\r
38 \r
39 #include "silcincludes.h"\r
40 #include "crypton.h"\r
41 \r
42 #define gamma_tau(x,b,m,p,q) \\r
43     (x) = (((u4byte)s_box[p][byte(b[0],m)]      ) | \\r
44            ((u4byte)s_box[q][byte(b[1],m)] <<  8) | \\r
45            ((u4byte)s_box[p][byte(b[2],m)] << 16) | \\r
46            ((u4byte)s_box[q][byte(b[3],m)] << 24))\r
47 \r
48 #define ma_0    0x3fcff3fc\r
49 #define ma_1    0xfc3fcff3\r
50 #define ma_2    0xf3fc3fcf\r
51 #define ma_3    0xcff3fc3f\r
52 \r
53 #define mb_0    0xcffccffc\r
54 #define mb_1    0xf33ff33f\r
55 #define mb_2    0xfccffccf\r
56 #define mb_3    0x3ff33ff3\r
57 \r
58 #define pi(b,n0,n1,n2,n3)       \\r
59     (((b)[0] & ma_##n0) ^       \\r
60      ((b)[1] & ma_##n1) ^       \\r
61      ((b)[2] & ma_##n2) ^       \\r
62      ((b)[3] & ma_##n3))\r
63 \r
64 #define phi_n(x,n0,n1,n2,n3)    \\r
65     (     (x)      & mb_##n0) ^ \\r
66     (rotl((x),  8) & mb_##n1) ^ \\r
67     (rotl((x), 16) & mb_##n2) ^ \\r
68     (rotl((x), 24) & mb_##n3)\r
69 \r
70 #define phi_00(x)   phi_n(x,0,1,2,3)\r
71 #define phi_01(x)   phi_n(x,3,0,1,2)\r
72 #define phi_02(x)   phi_n(x,2,3,0,1)\r
73 #define phi_03(x)   phi_n(x,1,2,3,0)\r
74 \r
75 #define phi_10(x)   phi_n(x,3,0,1,2)\r
76 #define phi_11(x)   phi_n(x,2,3,0,1)\r
77 #define phi_12(x)   phi_n(x,1,2,3,0)\r
78 #define phi_13(x)   phi_n(x,0,1,2,3)\r
79 \r
80 #define phi0(x,y)               \\r
81     (y)[0] = phi_00((x)[0]);    \\r
82     (y)[1] = phi_01((x)[1]);    \\r
83     (y)[2] = phi_02((x)[2]);    \\r
84     (y)[3] = phi_03((x)[3])\r
85 \r
86 #define phi1(x,y)               \\r
87     (y)[0] = phi_10((x)[0]);    \\r
88     (y)[1] = phi_11((x)[1]);    \\r
89     (y)[2] = phi_12((x)[2]);    \\r
90     (y)[3] = phi_13((x)[3])\r
91 \r
92 u1byte p_box[3][16] = \r
93 {   { 15,  9,  6,  8,  9,  9,  4, 12,  6,  2,  6, 10,  1,  3,  5, 15 },\r
94     { 10, 15,  4,  7,  5,  2, 14,  6,  9,  3, 12,  8, 13,  1, 11,  0 },\r
95     {  0,  4,  8,  4,  2, 15,  8, 13,  1,  1, 15,  7,  2, 11, 14, 15 }\r
96 };\r
97 \r
98 u4byte  tab_gen = 0;\r
99 u1byte  s_box[2][256];\r
100 u4byte  s_tab[4][256];\r
101 \r
102 void gen_tab(void)\r
103 {   u4byte  i, xl, xr, yl, yr;\r
104 \r
105     for(i = 0; i < 256; ++i)\r
106     {\r
107         xl = (i & 0xf0) >> 4; xr = i & 15;\r
108 \r
109         yr = xr ^ p_box[1][xl ^ p_box[0][xr]];\r
110         yl = xl ^ p_box[0][xr] ^ p_box[2][yr];\r
111 \r
112         yr |= (yl << 4); s_box[0][i] = (u1byte)yr; s_box[1][yr] = (u1byte)i;\r
113 \r
114         xr = yr * 0x01010101; xl = i * 0x01010101;\r
115 \r
116         s_tab[0][ i] = xr & 0x3fcff3fc;\r
117         s_tab[1][yr] = xl & 0xfc3fcff3;\r
118         s_tab[2][ i] = xr & 0xf3fc3fcf;\r
119         s_tab[3][yr] = xl & 0xcff3fc3f;\r
120     }\r
121 };\r
122 \r
123 /* initialise the key schedule from the user supplied key   */\r
124 \r
125 u4byte  kp[4] = { 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f };\r
126 u4byte  kq[4] = { 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, 0xcbbb9d5d };\r
127 \r
128 #define h0_block(n,r0,r1)                           \\r
129     e_key[4 * n +  8] = rotl(e_key[4 * n + 0], r0); \\r
130     e_key[4 * n +  9] = rc ^ e_key[4 * n + 1];      \\r
131     e_key[4 * n + 10] = rotl(e_key[4 * n + 2], r1); \\r
132     e_key[4 * n + 11] = rc ^ e_key[4 * n + 3]\r
133 \r
134 #define h1_block(n,r0,r1)                           \\r
135     e_key[4 * n +  8] = rc ^ e_key[4 * n + 0];      \\r
136     e_key[4 * n +  9] = rotl(e_key[4 * n + 1], r0); \\r
137     e_key[4 * n + 10] = rc ^ e_key[4 * n + 2];      \\r
138     e_key[4 * n + 11] = rotl(e_key[4 * n + 3], r1)\r
139 \r
140 u4byte *crypton_set_key(CryptonContext *ctx,\r
141                         const u4byte in_key[], const u4byte key_len)\r
142 {   \r
143     u4byte  i, rc, t0, t1, tmp[4];\r
144     u4byte *e_key = ctx->l_key + 52;\r
145     u4byte *d_key = ctx->l_key;\r
146 \r
147     if(!tab_gen)\r
148     {\r
149         gen_tab(); tab_gen = 1;\r
150     }\r
151 \r
152     e_key[2] = e_key[3] = e_key[6] = e_key[7] = 0;\r
153 \r
154     switch((key_len + 63) / 64)\r
155     {\r
156     case 4: e_key[3] = in_key[6]; e_key[7] = in_key[7];\r
157     case 3: e_key[2] = in_key[4]; e_key[6] = in_key[5];\r
158     case 2: e_key[0] = in_key[0]; e_key[4] = in_key[1];\r
159             e_key[1] = in_key[2]; e_key[5] = in_key[3];\r
160     }\r
161 \r
162     tmp[0] = pi(e_key, 0, 1, 2, 3) ^ kp[0];\r
163     tmp[1] = pi(e_key, 1, 2, 3, 0) ^ kp[1];\r
164     tmp[2] = pi(e_key, 2, 3, 0, 1) ^ kp[2];\r
165     tmp[3] = pi(e_key, 3, 0, 1, 2) ^ kp[3];\r
166     \r
167     gamma_tau(e_key[0], tmp, 0, 0, 1); \r
168     gamma_tau(e_key[1], tmp, 1, 1, 0);\r
169     gamma_tau(e_key[2], tmp, 2, 0, 1); \r
170     gamma_tau(e_key[3], tmp, 3, 1, 0);\r
171 \r
172     tmp[0] = pi(e_key + 4, 1, 2, 3, 0) ^ kq[0]; \r
173     tmp[1] = pi(e_key + 4, 2, 3, 0, 1) ^ kq[1];\r
174     tmp[2] = pi(e_key + 4, 3, 0, 1, 2) ^ kq[2]; \r
175     tmp[3] = pi(e_key + 4, 0, 1, 2, 3) ^ kq[3];\r
176 \r
177     gamma_tau(e_key[4], tmp, 0, 1, 0); \r
178     gamma_tau(e_key[5], tmp, 1, 0, 1);\r
179     gamma_tau(e_key[6], tmp, 2, 1, 0); \r
180     gamma_tau(e_key[7], tmp, 3, 0, 1);\r
181 \r
182     t0 = e_key[0] ^ e_key[1] ^ e_key[2] ^ e_key[3];\r
183     t1 = e_key[4] ^ e_key[5] ^ e_key[6] ^ e_key[7];\r
184     \r
185     e_key[0] ^= t1; e_key[1] ^= t1;\r
186     e_key[2] ^= t1; e_key[3] ^= t1;\r
187     e_key[4] ^= t0; e_key[5] ^= t0;\r
188     e_key[6] ^= t0; e_key[7] ^= t0;\r
189 \r
190     rc = 0x01010101; \r
191     h0_block( 0,  8, 16); h1_block(1, 16, 24); rc <<= 1;\r
192     h1_block( 2, 24,  8); h0_block(3,  8, 16); rc <<= 1;\r
193     h0_block( 4, 16, 24); h1_block(5, 24,  8); rc <<= 1;\r
194     h1_block( 6,  8, 16); h0_block(7, 16, 24); rc <<= 1;\r
195     h0_block( 8, 24,  8); h1_block(9,  8, 16); rc <<= 1;\r
196     h1_block(10, 16, 24);\r
197 \r
198     for(i = 0; i < 13; ++i)\r
199     {\r
200         if(i & 1)\r
201         {\r
202             phi0(e_key + 4 * i, d_key + 48 - 4 * i);\r
203         }\r
204         else\r
205         {\r
206             phi1(e_key + 4 * i, d_key + 48 - 4 * i);\r
207         }\r
208     }\r
209 \r
210     phi1(d_key + 48, d_key + 48);\r
211     phi1(e_key + 48, e_key + 48);\r
212 \r
213     return l_key;\r
214 };\r
215 \r
216 /* encrypt a block of text  */\r
217 \r
218 #define fr0(i,k)                                    \\r
219     b1[i] = s_tab[ (i)         ][byte(b0[0],i)] ^   \\r
220             s_tab[((i) + 1) & 3][byte(b0[1],i)] ^   \\r
221             s_tab[((i) + 2) & 3][byte(b0[2],i)] ^   \\r
222             s_tab[((i) + 3) & 3][byte(b0[3],i)] ^ (k)\r
223 \r
224 #define fr1(i,k)                                    \\r
225     b0[i] = s_tab[((i) + 1) & 3][byte(b1[0],i)] ^   \\r
226             s_tab[((i) + 2) & 3][byte(b1[1],i)] ^   \\r
227             s_tab[((i) + 3) & 3][byte(b1[2],i)] ^   \\r
228             s_tab[(i)          ][byte(b1[3],i)] ^ (k)\r
229 \r
230 #define f0_rnd(kp)                  \\r
231     fr0(0,(kp)[0]); fr0(1,(kp)[1]); \\r
232     fr0(2,(kp)[2]); fr0(3,(kp)[3])\r
233 \r
234 #define f1_rnd(kp)                  \\r
235     fr1(0,(kp)[0]); fr1(1,(kp)[1]); \\r
236     fr1(2,(kp)[2]); fr1(3,(kp)[3])\r
237 \r
238 void crypton_encrypt(CryptonContext *ctx,\r
239                      const u4byte in_blk[4], u4byte out_blk[4])\r
240 {   \r
241     u4byte  b0[4], b1[4];\r
242     u4byte *e_key = ctx->l_key + 52;\r
243     u4byte *d_key = ctx->l_key;\r
244 \r
245     b0[0] = in_blk[0] ^ e_key[0];\r
246     b0[1] = in_blk[1] ^ e_key[1];\r
247     b0[2] = in_blk[2] ^ e_key[2];\r
248     b0[3] = in_blk[3] ^ e_key[3];\r
249 \r
250     f0_rnd(e_key +  4); f1_rnd(e_key +  8);\r
251     f0_rnd(e_key + 12); f1_rnd(e_key + 16);\r
252     f0_rnd(e_key + 20); f1_rnd(e_key + 24);\r
253     f0_rnd(e_key + 28); f1_rnd(e_key + 32);\r
254     f0_rnd(e_key + 36); f1_rnd(e_key + 40);\r
255     f0_rnd(e_key + 44);\r
256 \r
257     gamma_tau(b0[0], b1, 0, 1, 0); \r
258     gamma_tau(b0[1], b1, 1, 0, 1); \r
259     gamma_tau(b0[2], b1, 2, 1, 0); \r
260     gamma_tau(b0[3], b1, 3, 0, 1);\r
261 \r
262     out_blk[0] = b0[0] ^ e_key[48]; \r
263     out_blk[1] = b0[1] ^ e_key[49];\r
264     out_blk[2] = b0[2] ^ e_key[50]; \r
265     out_blk[3] = b0[3] ^ e_key[51];\r
266 };\r
267 \r
268 /* decrypt a block of text  */\r
269 \r
270 void crypton_decrypt(CryptonContext *ctx,\r
271                      const u4byte in_blk[4], u4byte out_blk[4])\r
272 {   \r
273     u4byte  b0[4], b1[4];\r
274     u4byte *e_key = ctx->l_key + 52;\r
275     u4byte *d_key = ctx->l_key;\r
276 \r
277     b0[0] = in_blk[0] ^ d_key[0];\r
278     b0[1] = in_blk[1] ^ d_key[1];\r
279     b0[2] = in_blk[2] ^ d_key[2];\r
280     b0[3] = in_blk[3] ^ d_key[3];\r
281 \r
282     f0_rnd(d_key +  4); f1_rnd(d_key +  8);\r
283     f0_rnd(d_key + 12); f1_rnd(d_key + 16);\r
284     f0_rnd(d_key + 20); f1_rnd(d_key + 24);\r
285     f0_rnd(d_key + 28); f1_rnd(d_key + 32);\r
286     f0_rnd(d_key + 36); f1_rnd(d_key + 40);\r
287     f0_rnd(d_key + 44);\r
288 \r
289     gamma_tau(b0[0], b1, 0, 1, 0); \r
290     gamma_tau(b0[1], b1, 1, 0, 1); \r
291     gamma_tau(b0[2], b1, 2, 1, 0); \r
292     gamma_tau(b0[3], b1, 3, 0, 1);\r
293     \r
294     out_blk[0] = b0[0] ^ d_key[48]; \r
295     out_blk[1] = b0[1] ^ d_key[49];\r
296     out_blk[2] = b0[2] ^ d_key[50]; \r
297     out_blk[3] = b0[3] ^ d_key[51];\r
298 };\r