MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
arc4.cpp
1 /*
2  Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to the
15  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16  MA 02110-1301 USA.
17 */
18 
19 /* based on Wei Dai's arc4.cpp from CryptoPP */
20 
21 #include "runtime.hpp"
22 #include "arc4.hpp"
23 
24 
25 #if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM)
26  #define DO_ARC4_ASM
27 #endif
28 
29 
30 namespace TaoCrypt {
31 
32 void ARC4::SetKey(const byte* key, word32 length)
33 {
34  x_ = 1;
35  y_ = 0;
36 
37  word32 i;
38 
39  for (i = 0; i < STATE_SIZE; i++)
40  state_[i] = i;
41 
42  word32 keyIndex = 0, stateIndex = 0;
43 
44  for (i = 0; i < STATE_SIZE; i++) {
45  word32 a = state_[i];
46  stateIndex += key[keyIndex] + a;
47  stateIndex &= 0xFF;
48  state_[i] = state_[stateIndex];
49  state_[stateIndex] = a;
50 
51  if (++keyIndex >= length)
52  keyIndex = 0;
53  }
54 }
55 
56 
57 // local
58 namespace {
59 
60 inline unsigned int MakeByte(word32& x, word32& y, byte* s)
61 {
62  word32 a = s[x];
63  y = (y+a) & 0xff;
64 
65  word32 b = s[y];
66  s[x] = b;
67  s[y] = a;
68  x = (x+1) & 0xff;
69 
70  return s[(a+b) & 0xff];
71 }
72 
73 } // namespace
74 
75 
76 
77 void ARC4::Process(byte* out, const byte* in, word32 length)
78 {
79  if (length == 0) return;
80 
81 #ifdef DO_ARC4_ASM
82  if (isMMX) {
83  AsmProcess(out, in, length);
84  return;
85  }
86 #endif
87 
88  byte *const s = state_;
89  word32 x = x_;
90  word32 y = y_;
91 
92  if (in == out)
93  while (length--)
94  *out++ ^= MakeByte(x, y, s);
95  else
96  while(length--)
97  *out++ = *in++ ^ MakeByte(x, y, s);
98  x_ = x;
99  y_ = y;
100 }
101 
102 
103 
104 #ifdef DO_ARC4_ASM
105 
106 #ifdef _MSC_VER
107  __declspec(naked)
108 #else
109  __attribute__ ((noinline))
110 #endif
111 void ARC4::AsmProcess(byte* out, const byte* in, word32 length)
112 {
113 #ifdef __GNUC__
114  #define AS1(x) asm(#x);
115  #define AS2(x, y) asm(#x ", " #y);
116 
117  #define PROLOG() \
118  asm(".intel_syntax noprefix"); \
119  AS2( movd mm3, edi ) \
120  AS2( movd mm4, ebx ) \
121  AS2( movd mm5, esi ) \
122  AS2( movd mm6, ebp ) \
123  AS2( mov ecx, DWORD PTR [ebp + 8] ) \
124  AS2( mov edi, DWORD PTR [ebp + 12] ) \
125  AS2( mov esi, DWORD PTR [ebp + 16] ) \
126  AS2( mov ebp, DWORD PTR [ebp + 20] )
127 
128  #define EPILOG() \
129  AS2( movd ebp, mm6 ) \
130  AS2( movd esi, mm5 ) \
131  AS2( movd ebx, mm4 ) \
132  AS2( mov esp, ebp ) \
133  AS2( movd edi, mm3 ) \
134  AS1( emms ) \
135  asm(".att_syntax");
136 #else
137  #define AS1(x) __asm x
138  #define AS2(x, y) __asm x, y
139 
140  #define PROLOG() \
141  AS1( push ebp ) \
142  AS2( mov ebp, esp ) \
143  AS2( movd mm3, edi ) \
144  AS2( movd mm4, ebx ) \
145  AS2( movd mm5, esi ) \
146  AS2( movd mm6, ebp ) \
147  AS2( mov edi, DWORD PTR [ebp + 8] ) \
148  AS2( mov esi, DWORD PTR [ebp + 12] ) \
149  AS2( mov ebp, DWORD PTR [ebp + 16] )
150 
151  #define EPILOG() \
152  AS2( movd ebp, mm6 ) \
153  AS2( movd esi, mm5 ) \
154  AS2( movd ebx, mm4 ) \
155  AS2( movd edi, mm3 ) \
156  AS2( mov esp, ebp ) \
157  AS1( pop ebp ) \
158  AS1( emms ) \
159  AS1( ret 12 )
160 
161 #endif
162 
163  PROLOG()
164 
165  AS2( sub esp, 4 ) // make room
166 
167  AS2( cmp ebp, 0 )
168  AS1( jz nothing )
169 
170  AS2( mov [esp], ebp ) // length
171 
172  AS2( movzx edx, BYTE PTR [ecx + 1] ) // y
173  AS2( lea ebp, [ecx + 2] ) // state_
174  AS2( movzx ecx, BYTE PTR [ecx] ) // x
175 
176  // setup loop
177  // a = s[x];
178  AS2( movzx eax, BYTE PTR [ebp + ecx] )
179 
180 
181 AS1( begin: )
182 
183  // y = (y+a) & 0xff;
184  AS2( add edx, eax )
185  AS2( and edx, 255 )
186 
187  // b = s[y];
188  AS2( movzx ebx, BYTE PTR [ebp + edx] )
189 
190  // s[x] = b;
191  AS2( mov [ebp + ecx], bl )
192 
193  // s[y] = a;
194  AS2( mov [ebp + edx], al )
195 
196  // x = (x+1) & 0xff;
197  AS1( inc ecx )
198  AS2( and ecx, 255 )
199 
200  //return s[(a+b) & 0xff];
201  AS2( add eax, ebx )
202  AS2( and eax, 255 )
203 
204  AS2( movzx ebx, BYTE PTR [ebp + eax] )
205 
206  // a = s[x]; for next round
207  AS2( movzx eax, BYTE PTR [ebp + ecx] )
208 
209  // xOr w/ inByte
210  AS2( xor bl, BYTE PTR [esi] )
211  AS1( inc esi )
212 
213  // write to outByte
214  AS2( mov [edi], bl )
215  AS1( inc edi )
216 
217  AS1( dec DWORD PTR [esp] )
218  AS1( jnz begin )
219 
220 
221  // write back to x_ and y_
222  AS2( mov [ebp - 2], cl )
223  AS2( mov [ebp - 1], dl )
224 
225 
226 AS1( nothing: )
227 
228 
229  EPILOG()
230 }
231 
232 #endif // DO_ARC4_ASM
233 
234 
235 } // namespace