Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

aescrypt.c

Go to the documentation of this file.
00001 /* 00002 --------------------------------------------------------------------------- 00003 Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK. 00004 All rights reserved. 00005 00006 LICENSE TERMS 00007 00008 The free distribution and use of this software in both source and binary 00009 form is allowed (with or without changes) provided that: 00010 00011 1. distributions of this source code include the above copyright 00012 notice, this list of conditions and the following disclaimer; 00013 00014 2. distributions in binary form include the above copyright 00015 notice, this list of conditions and the following disclaimer 00016 in the documentation and/or other associated materials; 00017 00018 3. the copyright holder's name is not used to endorse products 00019 built using this software without specific written permission. 00020 00021 ALTERNATIVELY, provided that this notice is retained in full, this product 00022 may be distributed under the terms of the GNU General Public License (GPL), 00023 in which case the provisions of the GPL apply INSTEAD OF those given above. 00024 00025 DISCLAIMER 00026 00027 This software is provided 'as is' with no explicit or implied warranties 00028 in respect of its properties, including, but not limited to, correctness 00029 and/or fitness for purpose. 00030 --------------------------------------------------------------------------- 00031 Issue Date: 26/08/2003 00032 00033 This file contains the code for implementing encryption and decryption 00034 for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It 00035 can optionally be replaced by code written in assembler using NASM. For 00036 further details see the file aesopt.h 00037 */ 00038 00039 #include "aesopt.h" 00040 00041 #if defined(__cplusplus) 00042 extern "C" 00043 { 00044 #endif 00045 00046 #define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) 00047 #define so(y,x,c) word_out(y, c, s(x,c)) 00048 00049 #if defined(ARRAYS) 00050 #define locals(y,x) x[4],y[4] 00051 #else 00052 #define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 00053 #endif 00054 00055 #define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ 00056 s(y,2) = s(x,2); s(y,3) = s(x,3); 00057 #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) 00058 #define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) 00059 #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) 00060 00061 #if defined(ENCRYPTION) && !defined(AES_ASM) 00062 00063 /* Visual C++ .Net v7.1 provides the fastest encryption code when using 00064 Pentium optimiation with small code but this is poor for decryption 00065 so we need to control this with the following VC++ pragmas 00066 */ 00067 00068 #if defined(_MSC_VER) 00069 #pragma optimize( "s", on ) 00070 #endif 00071 00072 /* Given the column (c) of the output state variable, the following 00073 macros give the input state variables which are needed in its 00074 computation for each row (r) of the state. All the alternative 00075 macros give the same end values but expand into different ways 00076 of calculating these values. In particular the complex macro 00077 used for dynamically variable block sizes is designed to expand 00078 to a compile time constant whenever possible but will expand to 00079 conditional clauses on some branches (I am grateful to Frank 00080 Yellin for this construction) 00081 */ 00082 00083 #define fwd_var(x,r,c)\ 00084 ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ 00085 : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ 00086 : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ 00087 : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) 00088 00089 #if defined(FT4_SET) 00090 #undef dec_fmvars 00091 #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) 00092 #elif defined(FT1_SET) 00093 #undef dec_fmvars 00094 #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) 00095 #else 00096 #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))) 00097 #endif 00098 00099 #if defined(FL4_SET) 00100 #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) 00101 #elif defined(FL1_SET) 00102 #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) 00103 #else 00104 #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c)) 00105 #endif 00106 00107 aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx[1]) 00108 { aes_32t locals(b0, b1); 00109 const aes_32t *kp = cx->ks; 00110 #ifdef dec_fmvars 00111 dec_fmvars; /* declare variables for fwd_mcol() if needed */ 00112 #endif 00113 00114 aes_32t nr = (kp[45] ^ kp[52] ^ kp[53] ? kp[52] : 14); 00115 00116 #ifdef AES_ERR_CHK 00117 if( (nr != 10 || !(kp[0] | kp[3] | kp[4])) 00118 && (nr != 12 || !(kp[0] | kp[5] | kp[6])) 00119 && (nr != 14 || !(kp[0] | kp[7] | kp[8])) ) 00120 return aes_error; 00121 #endif 00122 00123 state_in(b0, in_blk, kp); 00124 00125 #if (ENC_UNROLL == FULL) 00126 00127 switch(nr) 00128 { 00129 case 14: 00130 round(fwd_rnd, b1, b0, kp + 1 * N_COLS); 00131 round(fwd_rnd, b0, b1, kp + 2 * N_COLS); 00132 kp += 2 * N_COLS; 00133 case 12: 00134 round(fwd_rnd, b1, b0, kp + 1 * N_COLS); 00135 round(fwd_rnd, b0, b1, kp + 2 * N_COLS); 00136 kp += 2 * N_COLS; 00137 case 10: 00138 round(fwd_rnd, b1, b0, kp + 1 * N_COLS); 00139 round(fwd_rnd, b0, b1, kp + 2 * N_COLS); 00140 round(fwd_rnd, b1, b0, kp + 3 * N_COLS); 00141 round(fwd_rnd, b0, b1, kp + 4 * N_COLS); 00142 round(fwd_rnd, b1, b0, kp + 5 * N_COLS); 00143 round(fwd_rnd, b0, b1, kp + 6 * N_COLS); 00144 round(fwd_rnd, b1, b0, kp + 7 * N_COLS); 00145 round(fwd_rnd, b0, b1, kp + 8 * N_COLS); 00146 round(fwd_rnd, b1, b0, kp + 9 * N_COLS); 00147 round(fwd_lrnd, b0, b1, kp +10 * N_COLS); 00148 } 00149 00150 #else 00151 00152 #if (ENC_UNROLL == PARTIAL) 00153 { aes_32t rnd; 00154 for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd) 00155 { 00156 kp += N_COLS; 00157 round(fwd_rnd, b1, b0, kp); 00158 kp += N_COLS; 00159 round(fwd_rnd, b0, b1, kp); 00160 } 00161 kp += N_COLS; 00162 round(fwd_rnd, b1, b0, kp); 00163 #else 00164 { aes_32t rnd; 00165 for(rnd = 0; rnd < nr - 1; ++rnd) 00166 { 00167 kp += N_COLS; 00168 round(fwd_rnd, b1, b0, kp); 00169 l_copy(b0, b1); 00170 } 00171 #endif 00172 kp += N_COLS; 00173 round(fwd_lrnd, b0, b1, kp); 00174 } 00175 #endif 00176 00177 state_out(out_blk, b0); 00178 #ifdef AES_ERR_CHK 00179 return aes_good; 00180 #endif 00181 } 00182 00183 #endif 00184 00185 #if defined(DECRYPTION) && !defined(AES_ASM) 00186 00187 /* Visual C++ .Net v7.1 provides the fastest encryption code when using 00188 Pentium optimiation with small code but this is poor for decryption 00189 so we need to control this with the following VC++ pragmas 00190 */ 00191 00192 #if defined(_MSC_VER) 00193 #pragma optimize( "t", on ) 00194 #endif 00195 00196 /* Given the column (c) of the output state variable, the following 00197 macros give the input state variables which are needed in its 00198 computation for each row (r) of the state. All the alternative 00199 macros give the same end values but expand into different ways 00200 of calculating these values. In particular the complex macro 00201 used for dynamically variable block sizes is designed to expand 00202 to a compile time constant whenever possible but will expand to 00203 conditional clauses on some branches (I am grateful to Frank 00204 Yellin for this construction) 00205 */ 00206 00207 #define inv_var(x,r,c)\ 00208 ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ 00209 : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\ 00210 : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ 00211 : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))) 00212 00213 #if defined(IT4_SET) 00214 #undef dec_imvars 00215 #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) 00216 #elif defined(IT1_SET) 00217 #undef dec_imvars 00218 #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) 00219 #else 00220 #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))) 00221 #endif 00222 00223 #if defined(IL4_SET) 00224 #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) 00225 #elif defined(IL1_SET) 00226 #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) 00227 #else 00228 #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)) 00229 #endif 00230 00231 aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1]) 00232 { aes_32t locals(b0, b1); 00233 #ifdef dec_imvars 00234 dec_imvars; /* declare variables for inv_mcol() if needed */ 00235 #endif 00236 00237 aes_32t nr = (cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] ? cx->ks[52] : 14); 00238 const aes_32t *kp = cx->ks + nr * N_COLS; 00239 00240 #ifdef AES_ERR_CHK 00241 if( (nr != 10 || !(cx->ks[0] | cx->ks[3] | cx->ks[4])) 00242 && (nr != 12 || !(cx->ks[0] | cx->ks[5] | cx->ks[6])) 00243 && (nr != 14 || !(cx->ks[0] | cx->ks[7] | cx->ks[8])) ) 00244 return aes_error; 00245 #endif 00246 00247 state_in(b0, in_blk, kp); 00248 00249 #if (DEC_UNROLL == FULL) 00250 00251 switch(nr) 00252 { 00253 case 14: 00254 round(inv_rnd, b1, b0, kp - 1 * N_COLS); 00255 round(inv_rnd, b0, b1, kp - 2 * N_COLS); 00256 kp -= 2 * N_COLS; 00257 case 12: 00258 round(inv_rnd, b1, b0, kp - 1 * N_COLS); 00259 round(inv_rnd, b0, b1, kp - 2 * N_COLS); 00260 kp -= 2 * N_COLS; 00261 case 10: 00262 round(inv_rnd, b1, b0, kp - 1 * N_COLS); 00263 round(inv_rnd, b0, b1, kp - 2 * N_COLS); 00264 round(inv_rnd, b1, b0, kp - 3 * N_COLS); 00265 round(inv_rnd, b0, b1, kp - 4 * N_COLS); 00266 round(inv_rnd, b1, b0, kp - 5 * N_COLS); 00267 round(inv_rnd, b0, b1, kp - 6 * N_COLS); 00268 round(inv_rnd, b1, b0, kp - 7 * N_COLS); 00269 round(inv_rnd, b0, b1, kp - 8 * N_COLS); 00270 round(inv_rnd, b1, b0, kp - 9 * N_COLS); 00271 round(inv_lrnd, b0, b1, kp - 10 * N_COLS); 00272 } 00273 00274 #else 00275 00276 #if (DEC_UNROLL == PARTIAL) 00277 { aes_32t rnd; 00278 for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd) 00279 { 00280 kp -= N_COLS; 00281 round(inv_rnd, b1, b0, kp); 00282 kp -= N_COLS; 00283 round(inv_rnd, b0, b1, kp); 00284 } 00285 kp -= N_COLS; 00286 round(inv_rnd, b1, b0, kp); 00287 #else 00288 { aes_32t rnd; 00289 for(rnd = 0; rnd < nr - 1; ++rnd) 00290 { 00291 kp -= N_COLS; 00292 round(inv_rnd, b1, b0, kp); 00293 l_copy(b0, b1); 00294 } 00295 #endif 00296 kp -= N_COLS; 00297 round(inv_lrnd, b0, b1, kp); 00298 } 00299 #endif 00300 00301 state_out(out_blk, b0); 00302 #ifdef AES_ERR_CHK 00303 return aes_good; 00304 #endif 00305 } 00306 00307 #endif 00308 00309 #if defined(__cplusplus) 00310 } 00311 #endif

Generated on Sat Jun 12 16:40:57 2004 for Asterisk by doxygen 1.3.7