Fri Jul 24 00:40:37 2009

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

Generated on Fri Jul 24 00:40:37 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7