Sat Mar 24 23:25:58 2007

Asterisk developer's documentation


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

Generated on Sat Mar 24 23:25:58 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.6