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"
38 #if defined(DO_BLOWFISH_ASM)
41 void Blowfish::Process(byte* out,
const byte* in, word32 sz)
44 Mode_BASE::Process(out, in, sz);
48 word32 blocks = sz / BLOCK_SIZE;
56 else if (mode_ == CBC) {
57 if (dir_ == ENCRYPTION)
59 r_[0] ^= *(word32*)in;
60 r_[1] ^= *(word32*)(in + 4);
62 AsmProcess((byte*)r_, (byte*)r_);
64 memcpy(out, r_, BLOCK_SIZE);
73 *(word32*)out ^= r_[0];
74 *(word32*)(out + 4) ^= r_[1];
76 memcpy(r_, in, BLOCK_SIZE);
84 #endif // DO_BLOWFISH_ASM
87 void Blowfish::SetKey(
const byte* key_string, word32 keylength, CipherDir dir)
91 else if (keylength > 56)
95 word32 data, dspace[2] = {0, 0};
97 memcpy(pbox_, p_init_,
sizeof(p_init_));
98 memcpy(sbox_, s_init_,
sizeof(s_init_));
101 for (i=0 ; i<ROUNDS+2 ; ++
i) {
103 for (k=0 ; k<4 ; ++k )
104 data = (data << 8) | key_string[j++ % keylength];
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);
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) (\
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)], \
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);
166 void Blowfish::crypt_block(
const word32 in[2], word32 out[2])
const
169 word32 right = in[1];
171 const word32 *
const s = sbox_;
172 const word32* p = pbox_;
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)])
182 left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)])
183 ^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)])
187 right ^= p[ROUNDS + 1];
194 typedef BlockGetAndPut<word32, BigEndian> gpBlock;
196 void Blowfish::ProcessAndXorBlock(
const byte* in,
const byte* xOr, byte* out)
200 const word32 *
const s = sbox_;
201 const word32* p = pbox_;
203 gpBlock::Get(in)(left)(right);
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)])
212 left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)])
213 ^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)])
217 right ^= p[ROUNDS + 1];
219 gpBlock::Put(xOr, out)(right)(left);
223 #if defined(DO_BLOWFISH_ASM)
225 #define AS1(x) asm(#x);
226 #define AS2(x, y) asm(#x ", " #y);
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] )
237 AS2( movd esi, mm5 ) \
238 AS2( movd ebx, mm4 ) \
239 AS2( movd edi, mm3 ) \
243 #define AS1(x) __asm x
244 #define AS2(x, y) __asm x, y
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] )
255 AS2( movd esi, mm5 ) \
256 AS2( movd ebx, mm4 ) \
257 AS2( movd edi, mm3 ) \
258 AS2( mov esp, ebp ) \
266 #define BF_ROUND(P, G, I) \
268 AS2( xor P, [edi + I*4] ) \
272 AS2( movzx edx, ch ) \
273 AS2( mov esi, [edi + edx*4 + 72] ) \
275 AS2( movzx ecx, cl ) \
276 AS2( add esi, [edi + ecx*4 + 1096] ) \
279 AS2( movzx edx, ch ) \
280 AS2( xor esi, [edi + edx*4 + 2120] ) \
282 AS2( movzx ecx, cl ) \
283 AS2( add esi, [edi + ecx*4 + 3144] ) \
291 void Blowfish::AsmProcess(
const byte* inBlock, byte* outBlock)
const
295 #ifdef OLD_GCC_OFFSET
296 AS2( lea edi, [ecx + 60] )
298 AS2( lea edi, [ecx + 56] )
301 AS2( mov eax, DWORD PTR [esi] )
302 AS2( mov edx, DWORD PTR [edi] )
305 AS2( mov ebx, DWORD PTR [esi + 4] )
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)
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] )
334 AS2( xor ebx, [edi + 68] )
338 AS2( mov edi, [ebp + 16] )
340 AS2( mov edi, [ebp + 12] )
346 AS2( mov [edi] , ebx )
347 AS2( mov [edi + 4], eax )
353 #endif // DO_BLOWFISH_ASM