mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / extra / yassl / taocrypt / src / blowfish.cpp
blobcedae6af28117147710d163dd6b42e2c022a1f61
1 /*
2 Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
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.
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.
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.
19 /* C++ code based on Wei Dai's blowfish.cpp from CryptoPP */
20 /* x86 asm is original */
23 #if defined(TAOCRYPT_KERNEL_MODE)
24 #define DO_TAOCRYPT_KERNEL_MODE
25 #endif // only some modules now support this
28 #include "runtime.hpp"
29 #include "blowfish.hpp"
35 namespace TaoCrypt {
38 #if defined(DO_BLOWFISH_ASM)
40 // ia32 optimized version
41 void Blowfish::Process(byte* out, const byte* in, word32 sz)
43 if (!isMMX) {
44 Mode_BASE::Process(out, in, sz);
45 return;
48 word32 blocks = sz / BLOCK_SIZE;
50 if (mode_ == ECB)
51 while (blocks--) {
52 AsmProcess(in, out);
53 out += BLOCK_SIZE;
54 in += BLOCK_SIZE;
56 else if (mode_ == CBC) {
57 if (dir_ == ENCRYPTION)
58 while (blocks--) {
59 r_[0] ^= *(word32*)in;
60 r_[1] ^= *(word32*)(in + 4);
62 AsmProcess((byte*)r_, (byte*)r_);
64 memcpy(out, r_, BLOCK_SIZE);
66 out += BLOCK_SIZE;
67 in += BLOCK_SIZE;
69 else
70 while (blocks--) {
71 AsmProcess(in, out);
73 *(word32*)out ^= r_[0];
74 *(word32*)(out + 4) ^= r_[1];
76 memcpy(r_, in, BLOCK_SIZE);
78 out += BLOCK_SIZE;
79 in += BLOCK_SIZE;
84 #endif // DO_BLOWFISH_ASM
87 void Blowfish::SetKey(const byte* key_string, word32 keylength, CipherDir dir)
89 if (keylength < 4)
90 keylength = 4;
91 else if (keylength > 56)
92 keylength = 56;
94 unsigned i, j=0, k;
95 word32 data, dspace[2] = {0, 0};
97 memcpy(pbox_, p_init_, sizeof(p_init_));
98 memcpy(sbox_, s_init_, sizeof(s_init_));
100 // Xor key string into encryption key vector
101 for (i=0 ; i<ROUNDS+2 ; ++i) {
102 data = 0;
103 for (k=0 ; k<4 ; ++k )
104 data = (data << 8) | key_string[j++ % keylength];
105 pbox_[i] ^= data;
108 crypt_block(dspace, pbox_);
110 for (i=0; i<ROUNDS; i+=2)
111 crypt_block(pbox_ + i, pbox_ + i + 2);
113 crypt_block(pbox_ + ROUNDS, sbox_);
115 for (i=0; i < 4*256-2; i+=2)
116 crypt_block(sbox_ + i, sbox_ + i + 2);
118 if (dir==DECRYPTION)
119 for (i=0; i<(ROUNDS+2)/2; i++)
120 STL::swap(pbox_[i], pbox_[ROUNDS+1-i]);
124 #define BFBYTE_0(x) ( x &0xFF)
125 #define BFBYTE_1(x) ((x>> 8)&0xFF)
126 #define BFBYTE_2(x) ((x>>16)&0xFF)
127 #define BFBYTE_3(x) ( x>>24)
130 #define BF_S(Put, Get, I) (\
131 Put ^= p[I], \
132 tmp = p[18 + BFBYTE_3(Get)], \
133 tmp += p[274+ BFBYTE_2(Get)], \
134 tmp ^= p[530+ BFBYTE_1(Get)], \
135 tmp += p[786+ BFBYTE_0(Get)], \
136 Put ^= tmp \
140 #define BF_ROUNDS \
141 BF_S(right, left, 1); \
142 BF_S(left, right, 2); \
143 BF_S(right, left, 3); \
144 BF_S(left, right, 4); \
145 BF_S(right, left, 5); \
146 BF_S(left, right, 6); \
147 BF_S(right, left, 7); \
148 BF_S(left, right, 8); \
149 BF_S(right, left, 9); \
150 BF_S(left, right, 10); \
151 BF_S(right, left, 11); \
152 BF_S(left, right, 12); \
153 BF_S(right, left, 13); \
154 BF_S(left, right, 14); \
155 BF_S(right, left, 15); \
156 BF_S(left, right, 16);
158 #define BF_EXTRA_ROUNDS \
159 BF_S(right, left, 17); \
160 BF_S(left, right, 18); \
161 BF_S(right, left, 19); \
162 BF_S(left, right, 20);
165 // Used by key setup, no byte swapping
166 void Blowfish::crypt_block(const word32 in[2], word32 out[2]) const
168 word32 left = in[0];
169 word32 right = in[1];
171 const word32 *const s = sbox_;
172 const word32* p = pbox_;
174 left ^= p[0];
176 // roll back up and use s and p index instead of just p
177 for (unsigned i = 0; i < ROUNDS / 2; i++) {
178 right ^= (((s[GETBYTE(left,3)] + s[256+GETBYTE(left,2)])
179 ^ s[2*256+GETBYTE(left,1)]) + s[3*256+GETBYTE(left,0)])
180 ^ p[2*i+1];
182 left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)])
183 ^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)])
184 ^ p[2*i+2];
187 right ^= p[ROUNDS + 1];
189 out[0] = right;
190 out[1] = left;
194 typedef BlockGetAndPut<word32, BigEndian> gpBlock;
196 void Blowfish::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out)
197 const
199 word32 left, right;
200 const word32 *const s = sbox_;
201 const word32* p = pbox_;
203 gpBlock::Get(in)(left)(right);
204 left ^= p[0];
206 // roll back up and use s and p index instead of just p
207 for (unsigned i = 0; i < ROUNDS / 2; i++) {
208 right ^= (((s[GETBYTE(left,3)] + s[256+GETBYTE(left,2)])
209 ^ s[2*256+GETBYTE(left,1)]) + s[3*256+GETBYTE(left,0)])
210 ^ p[2*i+1];
212 left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)])
213 ^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)])
214 ^ p[2*i+2];
217 right ^= p[ROUNDS + 1];
219 gpBlock::Put(xOr, out)(right)(left);
223 #if defined(DO_BLOWFISH_ASM)
224 #ifdef __GNUC__
225 #define AS1(x) asm(#x);
226 #define AS2(x, y) asm(#x ", " #y);
228 #define PROLOG() \
229 asm(".intel_syntax noprefix"); \
230 AS2( movd mm3, edi ) \
231 AS2( movd mm4, ebx ) \
232 AS2( movd mm5, esi ) \
233 AS2( mov ecx, DWORD PTR [ebp + 8] ) \
234 AS2( mov esi, DWORD PTR [ebp + 12] )
236 #define EPILOG() \
237 AS2( movd esi, mm5 ) \
238 AS2( movd ebx, mm4 ) \
239 AS2( movd edi, mm3 ) \
240 AS1( emms ) \
241 asm(".att_syntax");
242 #else
243 #define AS1(x) __asm x
244 #define AS2(x, y) __asm x, y
246 #define PROLOG() \
247 AS1( push ebp ) \
248 AS2( mov ebp, esp ) \
249 AS2( movd mm3, edi ) \
250 AS2( movd mm4, ebx ) \
251 AS2( movd mm5, esi ) \
252 AS2( mov esi, DWORD PTR [ebp + 8] )
254 #define EPILOG() \
255 AS2( movd esi, mm5 ) \
256 AS2( movd ebx, mm4 ) \
257 AS2( movd edi, mm3 ) \
258 AS2( mov esp, ebp ) \
259 AS1( pop ebp ) \
260 AS1( emms ) \
261 AS1( ret 8 )
263 #endif
266 #define BF_ROUND(P, G, I) \
267 /* Put ^= p[I] */ \
268 AS2( xor P, [edi + I*4] ) \
269 /* tmp = p[18 + BFBYTE_3(Get)] */ \
270 AS2( mov ecx, G ) \
271 AS2( shr ecx, 16 ) \
272 AS2( movzx edx, ch ) \
273 AS2( mov esi, [edi + edx*4 + 72] ) \
274 /* tmp += p[274+ BFBYTE_2(Get)] */ \
275 AS2( movzx ecx, cl ) \
276 AS2( add esi, [edi + ecx*4 + 1096] ) \
277 /* tmp ^= p[530+ BFBYTE_1(Get)] */ \
278 AS2( mov ecx, G ) \
279 AS2( movzx edx, ch ) \
280 AS2( xor esi, [edi + edx*4 + 2120] ) \
281 /* tmp += p[786+ BFBYTE_0(Get)] */ \
282 AS2( movzx ecx, cl ) \
283 AS2( add esi, [edi + ecx*4 + 3144] ) \
284 /* Put ^= tmp */ \
285 AS2( xor P, esi )
288 #ifdef _MSC_VER
289 __declspec(naked)
290 #endif
291 void Blowfish::AsmProcess(const byte* inBlock, byte* outBlock) const
293 PROLOG()
295 #ifdef OLD_GCC_OFFSET
296 AS2( lea edi, [ecx + 60] ) // pbox
297 #else
298 AS2( lea edi, [ecx + 56] ) // pbox
299 #endif
301 AS2( mov eax, DWORD PTR [esi] )
302 AS2( mov edx, DWORD PTR [edi] )
303 AS1( bswap eax )
305 AS2( mov ebx, DWORD PTR [esi + 4] )
306 AS2( xor eax, edx ) // left
307 AS1( bswap ebx ) // right
310 BF_ROUND(ebx, eax, 1)
311 BF_ROUND(eax, ebx, 2)
312 BF_ROUND(ebx, eax, 3)
313 BF_ROUND(eax, ebx, 4)
314 BF_ROUND(ebx, eax, 5)
315 BF_ROUND(eax, ebx, 6)
316 BF_ROUND(ebx, eax, 7)
317 BF_ROUND(eax, ebx, 8)
318 BF_ROUND(ebx, eax, 9)
319 BF_ROUND(eax, ebx, 10)
320 BF_ROUND(ebx, eax, 11)
321 BF_ROUND(eax, ebx, 12)
322 BF_ROUND(ebx, eax, 13)
323 BF_ROUND(eax, ebx, 14)
324 BF_ROUND(ebx, eax, 15)
325 BF_ROUND(eax, ebx, 16)
326 #if ROUNDS == 20
327 BF_ROUND(ebx, eax, 17)
328 BF_ROUND(eax, ebx, 18)
329 BF_ROUND(ebx, eax, 19)
330 BF_ROUND(eax, ebx, 20)
332 AS2( xor ebx, [edi + 84] ) // 20 + 1 (x4)
333 #else
334 AS2( xor ebx, [edi + 68] ) // 16 + 1 (x4)
335 #endif
337 #ifdef __GNUC__
338 AS2( mov edi, [ebp + 16] ) // outBlock
339 #else
340 AS2( mov edi, [ebp + 12] ) // outBlock
341 #endif
343 AS1( bswap ebx )
344 AS1( bswap eax )
346 AS2( mov [edi] , ebx )
347 AS2( mov [edi + 4], eax )
349 EPILOG()
353 #endif // DO_BLOWFISH_ASM
356 } // namespace