/ added parameter to change ec suppresion threshhold from config
[asterisk/asterisk.git] / aescrypt.c
1 /*
2  ---------------------------------------------------------------------------
3  Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
4  All rights reserved.
5
6  LICENSE TERMS
7
8  The free distribution and use of this software in both source and binary
9  form is allowed (with or without changes) provided that:
10
11    1. distributions of this source code include the above copyright
12       notice, this list of conditions and the following disclaimer;
13
14    2. distributions in binary form include the above copyright
15       notice, this list of conditions and the following disclaimer
16       in the documentation and/or other associated materials;
17
18    3. the copyright holder's name is not used to endorse products
19       built using this software without specific written permission.
20
21  ALTERNATIVELY, provided that this notice is retained in full, this product
22  may be distributed under the terms of the GNU General Public License (GPL),
23  in which case the provisions of the GPL apply INSTEAD OF those given above.
24
25  DISCLAIMER
26
27  This software is provided 'as is' with no explicit or implied warranties
28  in respect of its properties, including, but not limited to, correctness
29  and/or fitness for purpose.
30  ---------------------------------------------------------------------------
31  Issue Date: 26/08/2003
32
33  This file contains the code for implementing encryption and decryption
34  for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
35  can optionally be replaced by code written in assembler using NASM. For
36  further details see the file aesopt.h
37 */
38
39 #include "aesopt.h"
40
41 #if defined(__cplusplus)
42 extern "C"
43 {
44 #endif
45
46 #define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
47 #define so(y,x,c)   word_out(y, c, s(x,c))
48
49 #if defined(ARRAYS)
50 #define locals(y,x)     x[4],y[4]
51 #else
52 #define locals(y,x)     x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
53 #endif
54
55 #define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
56                         s(y,2) = s(x,2); s(y,3) = s(x,3);
57 #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)
58 #define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
59 #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)
60
61 #if defined(ENCRYPTION) && !defined(AES_ASM)
62
63 /* Visual C++ .Net v7.1 provides the fastest encryption code when using
64    Pentium optimiation with small code but this is poor for decryption
65    so we need to control this with the following VC++ pragmas
66 */
67
68 #if defined(_MSC_VER)
69 #pragma optimize( "s", on )
70 #endif
71
72 /* Given the column (c) of the output state variable, the following
73    macros give the input state variables which are needed in its
74    computation for each row (r) of the state. All the alternative
75    macros give the same end values but expand into different ways
76    of calculating these values.  In particular the complex macro
77    used for dynamically variable block sizes is designed to expand
78    to a compile time constant whenever possible but will expand to
79    conditional clauses on some branches (I am grateful to Frank
80    Yellin for this construction)
81 */
82
83 #define fwd_var(x,r,c)\
84  ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
85  : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
86  : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
87  :          ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
88
89 #if defined(FT4_SET)
90 #undef  dec_fmvars
91 #define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
92 #elif defined(FT1_SET)
93 #undef  dec_fmvars
94 #define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c))
95 #else
96 #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)))
97 #endif
98
99 #if defined(FL4_SET)
100 #define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))
101 #elif defined(FL1_SET)
102 #define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c))
103 #else
104 #define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c))
105 #endif
106
107 aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx[1])
108 {   aes_32t         locals(b0, b1);
109     const aes_32t   *kp = cx->ks;
110 #ifdef dec_fmvars
111     dec_fmvars; /* declare variables for fwd_mcol() if needed */
112 #endif
113
114     aes_32t nr = (kp[45] ^ kp[52] ^ kp[53] ? kp[52] : 14);
115
116 #ifdef AES_ERR_CHK
117     if(   (nr != 10 || !(kp[0] | kp[3] | kp[4])) 
118        && (nr != 12 || !(kp[0] | kp[5] | kp[6]))
119        && (nr != 14 || !(kp[0] | kp[7] | kp[8])) )
120         return aes_error;
121 #endif
122
123     state_in(b0, in_blk, kp);
124
125 #if (ENC_UNROLL == FULL)
126
127     switch(nr)
128     {
129     case 14:
130         round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);
131         round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);
132         kp += 2 * N_COLS;
133     case 12:
134         round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);
135         round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);
136         kp += 2 * N_COLS;
137     case 10:
138         round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);
139         round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);
140         round(fwd_rnd,  b1, b0, kp + 3 * N_COLS);
141         round(fwd_rnd,  b0, b1, kp + 4 * N_COLS);
142         round(fwd_rnd,  b1, b0, kp + 5 * N_COLS);
143         round(fwd_rnd,  b0, b1, kp + 6 * N_COLS);
144         round(fwd_rnd,  b1, b0, kp + 7 * N_COLS);
145         round(fwd_rnd,  b0, b1, kp + 8 * N_COLS);
146         round(fwd_rnd,  b1, b0, kp + 9 * N_COLS);
147         round(fwd_lrnd, b0, b1, kp +10 * N_COLS);
148     }
149
150 #else
151
152 #if (ENC_UNROLL == PARTIAL)
153     {   aes_32t    rnd;
154         for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd)
155         {
156             kp += N_COLS;
157             round(fwd_rnd, b1, b0, kp);
158             kp += N_COLS;
159             round(fwd_rnd, b0, b1, kp);
160         }
161         kp += N_COLS;
162         round(fwd_rnd,  b1, b0, kp);
163 #else
164     {   aes_32t    rnd;
165         for(rnd = 0; rnd < nr - 1; ++rnd)
166         {
167             kp += N_COLS;
168             round(fwd_rnd, b1, b0, kp);
169             l_copy(b0, b1);
170         }
171 #endif
172         kp += N_COLS;
173         round(fwd_lrnd, b0, b1, kp);
174     }
175 #endif
176
177     state_out(out_blk, b0);
178 #ifdef AES_ERR_CHK
179     return aes_good;
180 #endif
181 }
182
183 #endif
184
185 #if defined(DECRYPTION) && !defined(AES_ASM)
186
187 /* Visual C++ .Net v7.1 provides the fastest encryption code when using
188    Pentium optimiation with small code but this is poor for decryption
189    so we need to control this with the following VC++ pragmas
190 */
191
192 #if defined(_MSC_VER)
193 #pragma optimize( "t", on )
194 #endif
195
196 /* Given the column (c) of the output state variable, the following
197    macros give the input state variables which are needed in its
198    computation for each row (r) of the state. All the alternative
199    macros give the same end values but expand into different ways
200    of calculating these values.  In particular the complex macro
201    used for dynamically variable block sizes is designed to expand
202    to a compile time constant whenever possible but will expand to
203    conditional clauses on some branches (I am grateful to Frank
204    Yellin for this construction)
205 */
206
207 #define inv_var(x,r,c)\
208  ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
209  : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\
210  : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
211  :          ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))
212
213 #if defined(IT4_SET)
214 #undef  dec_imvars
215 #define inv_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))
216 #elif defined(IT1_SET)
217 #undef  dec_imvars
218 #define inv_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))
219 #else
220 #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)))
221 #endif
222
223 #if defined(IL4_SET)
224 #define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))
225 #elif defined(IL1_SET)
226 #define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))
227 #else
228 #define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))
229 #endif
230
231 aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1])
232 {   aes_32t        locals(b0, b1);
233 #ifdef dec_imvars
234     dec_imvars; /* declare variables for inv_mcol() if needed */
235 #endif
236
237     aes_32t nr = (cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] ? cx->ks[52] : 14);
238     const aes_32t *kp = cx->ks + nr * N_COLS;
239
240 #ifdef AES_ERR_CHK
241     if(   (nr != 10 || !(cx->ks[0] | cx->ks[3] | cx->ks[4])) 
242        && (nr != 12 || !(cx->ks[0] | cx->ks[5] | cx->ks[6]))
243        && (nr != 14 || !(cx->ks[0] | cx->ks[7] | cx->ks[8])) )
244         return aes_error;
245 #endif
246
247     state_in(b0, in_blk, kp);
248
249 #if (DEC_UNROLL == FULL)
250
251     switch(nr)
252     {
253     case 14:
254         round(inv_rnd,  b1, b0, kp -  1 * N_COLS);
255         round(inv_rnd,  b0, b1, kp -  2 * N_COLS);
256         kp -= 2 * N_COLS;
257     case 12:
258         round(inv_rnd,  b1, b0, kp -  1 * N_COLS);
259         round(inv_rnd,  b0, b1, kp -  2 * N_COLS);
260         kp -= 2 * N_COLS;
261     case 10:
262         round(inv_rnd,  b1, b0, kp -  1 * N_COLS);
263         round(inv_rnd,  b0, b1, kp -  2 * N_COLS);
264         round(inv_rnd,  b1, b0, kp -  3 * N_COLS);
265         round(inv_rnd,  b0, b1, kp -  4 * N_COLS);
266         round(inv_rnd,  b1, b0, kp -  5 * N_COLS);
267         round(inv_rnd,  b0, b1, kp -  6 * N_COLS);
268         round(inv_rnd,  b1, b0, kp -  7 * N_COLS);
269         round(inv_rnd,  b0, b1, kp -  8 * N_COLS);
270         round(inv_rnd,  b1, b0, kp -  9 * N_COLS);
271         round(inv_lrnd, b0, b1, kp - 10 * N_COLS);
272     }
273
274 #else
275
276 #if (DEC_UNROLL == PARTIAL)
277     {   aes_32t    rnd;
278         for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd)
279         {
280             kp -= N_COLS;
281             round(inv_rnd, b1, b0, kp);
282             kp -= N_COLS;
283             round(inv_rnd, b0, b1, kp);
284         }
285         kp -= N_COLS;
286         round(inv_rnd, b1, b0, kp);
287 #else
288     {   aes_32t    rnd;
289         for(rnd = 0; rnd < nr - 1; ++rnd)
290         {
291             kp -= N_COLS;
292             round(inv_rnd, b1, b0, kp);
293             l_copy(b0, b1);
294         }
295 #endif
296         kp -= N_COLS;
297         round(inv_lrnd, b0, b1, kp);
298     }
299 #endif
300
301     state_out(out_blk, b0);
302 #ifdef AES_ERR_CHK
303     return aes_good;
304 #endif
305 }
306
307 #endif
308
309 #if defined(__cplusplus)
310 }
311 #endif