2 ---------------------------------------------------------------------------
3 Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved.
7 The free distribution and use of this software is allowed (with or without
8 changes) provided that:
10 1. source code distributions include the above copyright notice, this
11 list of conditions and the following disclaimer;
13 2. binary distributions include the above copyright notice, this list
14 of conditions and the following disclaimer in their documentation;
16 3. the name of the copyright holder is not used to endorse products
17 built using this software without specific written permission.
21 This software is provided 'as is' with no explicit or implied warranties
22 in respect of its properties, including, but not limited to, correctness
23 and/or fitness for purpose.
24 ---------------------------------------------------------------------------
25 Issue Date: 20/12/2007
31 #if defined(__cplusplus)
36 #define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
37 #define so(y,x,c) word_out(y, c, s(x,c))
40 #define locals(y,x) x[4],y[4]
42 #define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
45 #define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
46 s(y,2) = s(x,2); s(y,3) = s(x,3);
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)
48 #define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
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)
51 #if ( FUNCS_IN_C & ENCRYPTION_IN_C )
53 /* Visual C++ .Net v7.1 provides the fastest encryption code when using
54 Pentium optimiation with small code but this is poor for decryption
55 so we need to control this with the following VC++ pragmas
58 #if defined( _MSC_VER ) && !defined( _WIN64 )
59 #pragma optimize( "s", on )
62 /* Given the column (c) of the output state variable, the following
63 macros give the input state variables which are needed in its
64 computation for each row (r) of the state. All the alternative
65 macros give the same end values but expand into different ways
66 of calculating these values. In particular the complex macro
67 used for dynamically variable block sizes is designed to expand
68 to a compile time constant whenever possible but will expand to
69 conditional clauses on some branches (I am grateful to Frank
70 Yellin for this construction)
73 #define fwd_var(x,r,c)\
74 ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
75 : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
76 : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
77 : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
81 #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
82 #elif defined(FT1_SET)
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))
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)))
90 #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))
91 #elif defined(FL1_SET)
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))
94 #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c))
97 AES_RETURN
aes_encrypt(const unsigned char *in
, unsigned char *out
, const aes_encrypt_ctx cx
[1])
98 { uint_32t
locals(b0
, b1
);
100 #if defined( dec_fmvars )
101 dec_fmvars
; /* declare variables for fwd_mcol() if needed */
104 #if defined( AES_ERR_CHK )
105 if( cx
->inf
.b
[0] != 10 * 16 && cx
->inf
.b
[0] != 12 * 16 && cx
->inf
.b
[0] != 14 * 16 )
110 state_in(b0
, in
, kp
);
112 #if (ENC_UNROLL == FULL)
117 round(fwd_rnd
, b1
, b0
, kp
+ 1 * N_COLS
);
118 round(fwd_rnd
, b0
, b1
, kp
+ 2 * N_COLS
);
121 round(fwd_rnd
, b1
, b0
, kp
+ 1 * N_COLS
);
122 round(fwd_rnd
, b0
, b1
, kp
+ 2 * N_COLS
);
125 round(fwd_rnd
, b1
, b0
, kp
+ 1 * N_COLS
);
126 round(fwd_rnd
, b0
, b1
, kp
+ 2 * N_COLS
);
127 round(fwd_rnd
, b1
, b0
, kp
+ 3 * N_COLS
);
128 round(fwd_rnd
, b0
, b1
, kp
+ 4 * N_COLS
);
129 round(fwd_rnd
, b1
, b0
, kp
+ 5 * N_COLS
);
130 round(fwd_rnd
, b0
, b1
, kp
+ 6 * N_COLS
);
131 round(fwd_rnd
, b1
, b0
, kp
+ 7 * N_COLS
);
132 round(fwd_rnd
, b0
, b1
, kp
+ 8 * N_COLS
);
133 round(fwd_rnd
, b1
, b0
, kp
+ 9 * N_COLS
);
134 round(fwd_lrnd
, b0
, b1
, kp
+10 * N_COLS
);
139 #if (ENC_UNROLL == PARTIAL)
141 for(rnd
= 0; rnd
< (cx
->inf
.b
[0] >> 5) - 1; ++rnd
)
144 round(fwd_rnd
, b1
, b0
, kp
);
146 round(fwd_rnd
, b0
, b1
, kp
);
149 round(fwd_rnd
, b1
, b0
, kp
);
152 for(rnd
= 0; rnd
< (cx
->inf
.b
[0] >> 4) - 1; ++rnd
)
155 round(fwd_rnd
, b1
, b0
, kp
);
160 round(fwd_lrnd
, b0
, b1
, kp
);
166 #if defined( AES_ERR_CHK )
173 #if ( FUNCS_IN_C & DECRYPTION_IN_C)
175 /* Visual C++ .Net v7.1 provides the fastest encryption code when using
176 Pentium optimiation with small code but this is poor for decryption
177 so we need to control this with the following VC++ pragmas
180 #if defined( _MSC_VER ) && !defined( _WIN64 )
181 #pragma optimize( "t", on )
184 /* Given the column (c) of the output state variable, the following
185 macros give the input state variables which are needed in its
186 computation for each row (r) of the state. All the alternative
187 macros give the same end values but expand into different ways
188 of calculating these values. In particular the complex macro
189 used for dynamically variable block sizes is designed to expand
190 to a compile time constant whenever possible but will expand to
191 conditional clauses on some branches (I am grateful to Frank
192 Yellin for this construction)
195 #define inv_var(x,r,c)\
196 ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
197 : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\
198 : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
199 : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))
203 #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))
204 #elif defined(IT1_SET)
206 #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))
208 #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)))
212 #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))
213 #elif defined(IL1_SET)
214 #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))
216 #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))
219 /* This code can work with the decryption key schedule in the */
220 /* order that is used for encrytpion (where the 1st decryption */
221 /* round key is at the high end ot the schedule) or with a key */
222 /* schedule that has been reversed to put the 1st decryption */
223 /* round key at the low end of the schedule in memory (when */
224 /* AES_REV_DKS is defined) */
228 #define rnd_key(n) (kp + n * N_COLS)
231 #define rnd_key(n) (kp - n * N_COLS)
234 AES_RETURN
aes_decrypt(const unsigned char *in
, unsigned char *out
, const aes_decrypt_ctx cx
[1])
235 { uint_32t
locals(b0
, b1
);
236 #if defined( dec_imvars )
237 dec_imvars
; /* declare variables for inv_mcol() if needed */
241 #if defined( AES_ERR_CHK )
242 if( cx
->inf
.b
[0] != 10 * 16 && cx
->inf
.b
[0] != 12 * 16 && cx
->inf
.b
[0] != 14 * 16 )
246 kp
= cx
->ks
+ (key_ofs
? (cx
->inf
.b
[0] >> 2) : 0);
247 state_in(b0
, in
, kp
);
249 #if (DEC_UNROLL == FULL)
251 kp
= cx
->ks
+ (key_ofs
? 0 : (cx
->inf
.b
[0] >> 2));
255 round(inv_rnd
, b1
, b0
, rnd_key(-13));
256 round(inv_rnd
, b0
, b1
, rnd_key(-12));
258 round(inv_rnd
, b1
, b0
, rnd_key(-11));
259 round(inv_rnd
, b0
, b1
, rnd_key(-10));
261 round(inv_rnd
, b1
, b0
, rnd_key(-9));
262 round(inv_rnd
, b0
, b1
, rnd_key(-8));
263 round(inv_rnd
, b1
, b0
, rnd_key(-7));
264 round(inv_rnd
, b0
, b1
, rnd_key(-6));
265 round(inv_rnd
, b1
, b0
, rnd_key(-5));
266 round(inv_rnd
, b0
, b1
, rnd_key(-4));
267 round(inv_rnd
, b1
, b0
, rnd_key(-3));
268 round(inv_rnd
, b0
, b1
, rnd_key(-2));
269 round(inv_rnd
, b1
, b0
, rnd_key(-1));
270 round(inv_lrnd
, b0
, b1
, rnd_key( 0));
275 #if (DEC_UNROLL == PARTIAL)
277 for(rnd
= 0; rnd
< (cx
->inf
.b
[0] >> 5) - 1; ++rnd
)
280 round(inv_rnd
, b1
, b0
, kp
);
282 round(inv_rnd
, b0
, b1
, kp
);
285 round(inv_rnd
, b1
, b0
, kp
);
288 for(rnd
= 0; rnd
< (cx
->inf
.b
[0] >> 4) - 1; ++rnd
)
291 round(inv_rnd
, b1
, b0
, kp
);
296 round(inv_lrnd
, b0
, b1
, kp
);
302 #if defined( AES_ERR_CHK )
309 #if defined(__cplusplus)