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