Sat Aug 6 00:39:19 2011

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 
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

Generated on Sat Aug 6 00:39:19 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7