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