Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:47 2009

## Asterisk developer's documentation

- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Directories

# 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