OSDN Git Service

Compile executable files.
[ffftp/ffftp.git] / aescrypt.c
1 /*\r
2  ---------------------------------------------------------------------------\r
3  Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.\r
4 \r
5  LICENSE TERMS\r
6 \r
7  The redistribution and use of this software (with or without changes)\r
8  is allowed without the payment of fees or royalties provided that:\r
9 \r
10   1. source code distributions include the above copyright notice, this\r
11      list of conditions and the following disclaimer;\r
12 \r
13   2. binary distributions include the above copyright notice, this list\r
14      of conditions and the following disclaimer in their documentation;\r
15 \r
16   3. the name of the copyright holder is not used to endorse products\r
17      built using this software without specific written permission.\r
18 \r
19  DISCLAIMER\r
20 \r
21  This software is provided 'as is' with no explicit or implied warranties\r
22  in respect of its properties, including, but not limited to, correctness\r
23  and/or fitness for purpose.\r
24  ---------------------------------------------------------------------------\r
25  Issue Date: 20/12/2007\r
26 */\r
27 \r
28 #include "aesopt.h"\r
29 #include "aestab.h"\r
30 \r
31 #if defined(__cplusplus)\r
32 extern "C"\r
33 {\r
34 #endif\r
35 \r
36 #define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])\r
37 #define so(y,x,c)   word_out(y, c, s(x,c))\r
38 \r
39 #if defined(ARRAYS)\r
40 #define locals(y,x)     x[4],y[4]\r
41 #else\r
42 #define locals(y,x)     x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3\r
43 #endif\r
44 \r
45 #define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \\r
46                         s(y,2) = s(x,2); s(y,3) = s(x,3);\r
47 #define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)\r
48 #define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)\r
49 #define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)\r
50 \r
51 #if ( FUNCS_IN_C & ENCRYPTION_IN_C )\r
52 \r
53 /* Visual C++ .Net v7.1 provides the fastest encryption code when using\r
54    Pentium optimiation with small code but this is poor for decryption\r
55    so we need to control this with the following VC++ pragmas\r
56 */\r
57 \r
58 #if defined( _MSC_VER ) && !defined( _WIN64 )\r
59 #pragma optimize( "s", on )\r
60 #endif\r
61 \r
62 /* Given the column (c) of the output state variable, the following\r
63    macros give the input state variables which are needed in its\r
64    computation for each row (r) of the state. All the alternative\r
65    macros give the same end values but expand into different ways\r
66    of calculating these values.  In particular the complex macro\r
67    used for dynamically variable block sizes is designed to expand\r
68    to a compile time constant whenever possible but will expand to\r
69    conditional clauses on some branches (I am grateful to Frank\r
70    Yellin for this construction)\r
71 */\r
72 \r
73 #define fwd_var(x,r,c)\\r
74  ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\\r
75  : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\\r
76  : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\\r
77  :          ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))\r
78 \r
79 #if defined(FT4_SET)\r
80 #undef  dec_fmvars\r
81 #define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))\r
82 #elif defined(FT1_SET)\r
83 #undef  dec_fmvars\r
84 #define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c))\r
85 #else\r
86 #define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c)))\r
87 #endif\r
88 \r
89 #if defined(FL4_SET)\r
90 #define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))\r
91 #elif defined(FL1_SET)\r
92 #define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c))\r
93 #else\r
94 #define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c))\r
95 #endif\r
96 \r
97 AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1])\r
98 {   uint_32t         locals(b0, b1);\r
99     const uint_32t   *kp;\r
100 #if defined( dec_fmvars )\r
101     dec_fmvars; /* declare variables for fwd_mcol() if needed */\r
102 #endif\r
103 \r
104     if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 )\r
105         return EXIT_FAILURE;\r
106 \r
107     kp = cx->ks;\r
108     state_in(b0, in, kp);\r
109 \r
110 #if (ENC_UNROLL == FULL)\r
111 \r
112     switch(cx->inf.b[0])\r
113     {\r
114     case 14 * 16:\r
115         round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);\r
116         round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);\r
117         kp += 2 * N_COLS;\r
118     case 12 * 16:\r
119         round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);\r
120         round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);\r
121         kp += 2 * N_COLS;\r
122     case 10 * 16:\r
123         round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);\r
124         round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);\r
125         round(fwd_rnd,  b1, b0, kp + 3 * N_COLS);\r
126         round(fwd_rnd,  b0, b1, kp + 4 * N_COLS);\r
127         round(fwd_rnd,  b1, b0, kp + 5 * N_COLS);\r
128         round(fwd_rnd,  b0, b1, kp + 6 * N_COLS);\r
129         round(fwd_rnd,  b1, b0, kp + 7 * N_COLS);\r
130         round(fwd_rnd,  b0, b1, kp + 8 * N_COLS);\r
131         round(fwd_rnd,  b1, b0, kp + 9 * N_COLS);\r
132         round(fwd_lrnd, b0, b1, kp +10 * N_COLS);\r
133     }\r
134 \r
135 #else\r
136 \r
137 #if (ENC_UNROLL == PARTIAL)\r
138     {   uint_32t    rnd;\r
139         for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd)\r
140         {\r
141             kp += N_COLS;\r
142             round(fwd_rnd, b1, b0, kp);\r
143             kp += N_COLS;\r
144             round(fwd_rnd, b0, b1, kp);\r
145         }\r
146         kp += N_COLS;\r
147         round(fwd_rnd,  b1, b0, kp);\r
148 #else\r
149     {   uint_32t    rnd;\r
150         for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd)\r
151         {\r
152             kp += N_COLS;\r
153             round(fwd_rnd, b1, b0, kp);\r
154             l_copy(b0, b1);\r
155         }\r
156 #endif\r
157         kp += N_COLS;\r
158         round(fwd_lrnd, b0, b1, kp);\r
159     }\r
160 #endif\r
161 \r
162     state_out(out, b0);\r
163     return EXIT_SUCCESS;\r
164 }\r
165 \r
166 #endif\r
167 \r
168 #if ( FUNCS_IN_C & DECRYPTION_IN_C)\r
169 \r
170 /* Visual C++ .Net v7.1 provides the fastest encryption code when using\r
171    Pentium optimiation with small code but this is poor for decryption\r
172    so we need to control this with the following VC++ pragmas\r
173 */\r
174 \r
175 #if defined( _MSC_VER ) && !defined( _WIN64 )\r
176 #pragma optimize( "t", on )\r
177 #endif\r
178 \r
179 /* Given the column (c) of the output state variable, the following\r
180    macros give the input state variables which are needed in its\r
181    computation for each row (r) of the state. All the alternative\r
182    macros give the same end values but expand into different ways\r
183    of calculating these values.  In particular the complex macro\r
184    used for dynamically variable block sizes is designed to expand\r
185    to a compile time constant whenever possible but will expand to\r
186    conditional clauses on some branches (I am grateful to Frank\r
187    Yellin for this construction)\r
188 */\r
189 \r
190 #define inv_var(x,r,c)\\r
191  ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\\r
192  : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\\r
193  : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\\r
194  :          ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))\r
195 \r
196 #if defined(IT4_SET)\r
197 #undef  dec_imvars\r
198 #define inv_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))\r
199 #elif defined(IT1_SET)\r
200 #undef  dec_imvars\r
201 #define inv_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))\r
202 #else\r
203 #define inv_rnd(y,x,k,c)    (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)))\r
204 #endif\r
205 \r
206 #if defined(IL4_SET)\r
207 #define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))\r
208 #elif defined(IL1_SET)\r
209 #define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))\r
210 #else\r
211 #define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))\r
212 #endif\r
213 \r
214 /* This code can work with the decryption key schedule in the   */\r
215 /* order that is used for encrytpion (where the 1st decryption  */\r
216 /* round key is at the high end ot the schedule) or with a key  */\r
217 /* schedule that has been reversed to put the 1st decryption    */\r
218 /* round key at the low end of the schedule in memory (when     */\r
219 /* AES_REV_DKS is defined)                                      */\r
220 \r
221 #ifdef AES_REV_DKS\r
222 #define key_ofs     0\r
223 #define rnd_key(n)  (kp + n * N_COLS)\r
224 #else\r
225 #define key_ofs     1\r
226 #define rnd_key(n)  (kp - n * N_COLS)\r
227 #endif\r
228 \r
229 AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1])\r
230 {   uint_32t        locals(b0, b1);\r
231 #if defined( dec_imvars )\r
232     dec_imvars; /* declare variables for inv_mcol() if needed */\r
233 #endif\r
234     const uint_32t *kp;\r
235 \r
236     if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 )\r
237         return EXIT_FAILURE;\r
238 \r
239     kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0);\r
240     state_in(b0, in, kp);\r
241 \r
242 #if (DEC_UNROLL == FULL)\r
243 \r
244     kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2));\r
245     switch(cx->inf.b[0])\r
246     {\r
247     case 14 * 16:\r
248         round(inv_rnd,  b1, b0, rnd_key(-13));\r
249         round(inv_rnd,  b0, b1, rnd_key(-12));\r
250     case 12 * 16:\r
251         round(inv_rnd,  b1, b0, rnd_key(-11));\r
252         round(inv_rnd,  b0, b1, rnd_key(-10));\r
253     case 10 * 16:\r
254         round(inv_rnd,  b1, b0, rnd_key(-9));\r
255         round(inv_rnd,  b0, b1, rnd_key(-8));\r
256         round(inv_rnd,  b1, b0, rnd_key(-7));\r
257         round(inv_rnd,  b0, b1, rnd_key(-6));\r
258         round(inv_rnd,  b1, b0, rnd_key(-5));\r
259         round(inv_rnd,  b0, b1, rnd_key(-4));\r
260         round(inv_rnd,  b1, b0, rnd_key(-3));\r
261         round(inv_rnd,  b0, b1, rnd_key(-2));\r
262         round(inv_rnd,  b1, b0, rnd_key(-1));\r
263         round(inv_lrnd, b0, b1, rnd_key( 0));\r
264     }\r
265 \r
266 #else\r
267 \r
268 #if (DEC_UNROLL == PARTIAL)\r
269     {   uint_32t    rnd;\r
270         for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd)\r
271         {\r
272             kp = rnd_key(1);\r
273             round(inv_rnd, b1, b0, kp);\r
274             kp = rnd_key(1);\r
275             round(inv_rnd, b0, b1, kp);\r
276         }\r
277         kp = rnd_key(1);\r
278         round(inv_rnd, b1, b0, kp);\r
279 #else\r
280     {   uint_32t    rnd;\r
281         for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd)\r
282         {\r
283             kp = rnd_key(1);\r
284             round(inv_rnd, b1, b0, kp);\r
285             l_copy(b0, b1);\r
286         }\r
287 #endif\r
288         kp = rnd_key(1);\r
289         round(inv_lrnd, b0, b1, kp);\r
290         }\r
291 #endif\r
292 \r
293     state_out(out, b0);\r
294     return EXIT_SUCCESS;\r
295 }\r
296 \r
297 #endif\r
298 \r
299 #if defined(__cplusplus)\r
300 }\r
301 #endif\r