|
|
1.1 root 1: /*
2: ---------------------------------------------------------------------------
3: Copyright (c) 2003, Dr 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 28/01/2004
31:
32: This file contains the code for implementing encryption and decryption
33: for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
34: can optionally be replaced by code written in assembler using NASM. For
35: further details see the file aesopt.h
36: */
37:
38: #include "aesopt.h"
39: #include "aestab.h"
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 defined(ENCRYPTION) && !defined(AES_ASM)
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)
1.1.1.2 ! root 69: //#pragma optimize( "s", on )
1.1 root 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_rval aes_encrypt(const unsigned char *in,
108: unsigned char *out, const aes_encrypt_ctx cx[1])
109: { aes_32t locals(b0, b1);
110: const aes_32t *kp = cx->ks;
111: #if defined( dec_fmvars )
112: dec_fmvars; /* declare variables for fwd_mcol() if needed */
113: #endif
114:
115: #if defined( AES_ERR_CHK )
116: if( cx->rn != 10 && cx->rn != 12 && cx->rn != 14 )
117: return aes_error;
118: #endif
119:
120: state_in(b0, in, kp);
121:
122: #if (ENC_UNROLL == FULL)
123:
124: switch(cx->rn)
125: {
126: case 14:
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:
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:
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: { aes_32t rnd;
151: for(rnd = 0; rnd < (cx->rn >> 1) - 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: { aes_32t rnd;
162: for(rnd = 0; rnd < cx->rn - 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: #if defined( AES_ERR_CHK )
176: return aes_good;
177: #endif
178: }
179:
180: #endif
181:
182: #if defined(DECRYPTION) && !defined(AES_ASM)
183:
184: /* Visual C++ .Net v7.1 provides the fastest encryption code when using
185: Pentium optimiation with small code but this is poor for decryption
186: so we need to control this with the following VC++ pragmas
187: */
188:
189: #if defined(_MSC_VER)
1.1.1.2 ! root 190: //#pragma optimize( "t", on )
1.1 root 191: #endif
192:
193: /* Given the column (c) of the output state variable, the following
194: macros give the input state variables which are needed in its
195: computation for each row (r) of the state. All the alternative
196: macros give the same end values but expand into different ways
197: of calculating these values. In particular the complex macro
198: used for dynamically variable block sizes is designed to expand
199: to a compile time constant whenever possible but will expand to
200: conditional clauses on some branches (I am grateful to Frank
201: Yellin for this construction)
202: */
203:
204: #define inv_var(x,r,c)\
205: ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
206: : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\
207: : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
208: : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))
209:
210: #if defined(IT4_SET)
211: #undef dec_imvars
212: #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))
213: #elif defined(IT1_SET)
214: #undef dec_imvars
215: #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))
216: #else
217: #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)))
218: #endif
219:
220: #if defined(IL4_SET)
221: #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))
222: #elif defined(IL1_SET)
223: #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))
224: #else
225: #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))
226: #endif
227:
228: aes_rval aes_decrypt(const unsigned char *in,
229: unsigned char *out, const aes_decrypt_ctx cx[1])
230: { aes_32t locals(b0, b1);
231: #if defined( dec_imvars )
232: dec_imvars; /* declare variables for inv_mcol() if needed */
233: #endif
234: const aes_32t *kp = cx->ks + cx->rn * N_COLS;
235:
236: #if defined( AES_ERR_CHK )
237: if( cx->rn != 10 && cx->rn != 12 && cx->rn != 14 )
238: return aes_error;
239: #endif
240:
241: state_in(b0, in, kp);
242:
243: #if (DEC_UNROLL == FULL)
244:
245: switch(cx->rn)
246: {
247: case 14:
248: round(inv_rnd, b1, b0, kp - 1 * N_COLS);
249: round(inv_rnd, b0, b1, kp - 2 * N_COLS);
250: kp -= 2 * N_COLS;
251: case 12:
252: round(inv_rnd, b1, b0, kp - 1 * N_COLS);
253: round(inv_rnd, b0, b1, kp - 2 * N_COLS);
254: kp -= 2 * N_COLS;
255: case 10:
256: round(inv_rnd, b1, b0, kp - 1 * N_COLS);
257: round(inv_rnd, b0, b1, kp - 2 * N_COLS);
258: round(inv_rnd, b1, b0, kp - 3 * N_COLS);
259: round(inv_rnd, b0, b1, kp - 4 * N_COLS);
260: round(inv_rnd, b1, b0, kp - 5 * N_COLS);
261: round(inv_rnd, b0, b1, kp - 6 * N_COLS);
262: round(inv_rnd, b1, b0, kp - 7 * N_COLS);
263: round(inv_rnd, b0, b1, kp - 8 * N_COLS);
264: round(inv_rnd, b1, b0, kp - 9 * N_COLS);
265: round(inv_lrnd, b0, b1, kp - 10 * N_COLS);
266: }
267:
268: #else
269:
270: #if (DEC_UNROLL == PARTIAL)
271: { aes_32t rnd;
272: for(rnd = 0; rnd < (cx->rn >> 1) - 1; ++rnd)
273: {
274: kp -= N_COLS;
275: round(inv_rnd, b1, b0, kp);
276: kp -= N_COLS;
277: round(inv_rnd, b0, b1, kp);
278: }
279: kp -= N_COLS;
280: round(inv_rnd, b1, b0, kp);
281: #else
282: { aes_32t rnd;
283: for(rnd = 0; rnd < cx->rn - 1; ++rnd)
284: {
285: kp -= N_COLS;
286: round(inv_rnd, b1, b0, kp);
287: l_copy(b0, b1);
288: }
289: #endif
290: kp -= N_COLS;
291: round(inv_lrnd, b0, b1, kp);
292: }
293: #endif
294:
295: state_out(out, b0);
296: #if defined( AES_ERR_CHK )
297: return aes_good;
298: #endif
299: }
300:
301: #endif
302:
303: #if defined(__cplusplus)
304: }
305: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.