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 Fri Feb 27 12:19:40 2004 for Asterisk by doxygen 1.3.5