23 #if defined(TAOCRYPT_KERNEL_MODE)
24 #define DO_TAOCRYPT_KERNEL_MODE
25 #endif // only some modules now support this
27 #include "runtime.hpp"
28 #include "twofish.hpp"
35 #if defined(DO_TWOFISH_ASM)
38 void Twofish::Process(byte* out,
const byte* in, word32 sz)
41 Mode_BASE::Process(out, in, sz);
45 word32 blocks = sz / BLOCK_SIZE;
49 if (dir_ == ENCRYPTION)
57 else if (mode_ == CBC) {
58 if (dir_ == ENCRYPTION)
60 r_[0] ^= *(word32*)in;
61 r_[1] ^= *(word32*)(in + 4);
62 r_[2] ^= *(word32*)(in + 8);
63 r_[3] ^= *(word32*)(in + 12);
65 AsmEncrypt((byte*)r_, (byte*)r_);
66 memcpy(out, r_, BLOCK_SIZE);
75 *(word32*)out ^= r_[0];
76 *(word32*)(out + 4) ^= r_[1];
77 *(word32*)(out + 8) ^= r_[2];
78 *(word32*)(out + 12) ^= r_[3];
80 memcpy(r_, in, BLOCK_SIZE);
88 #endif // DO_TWOFISH_ASM
95 static inline unsigned int Mod(
unsigned int c)
97 static const unsigned int modulus = 0x14d;
98 unsigned int c2 = (c<<1) ^ ((c & 0x80) ? modulus : 0);
99 unsigned int c1 = c2 ^ (c>>1) ^ ((c & 1) ? (modulus>>1) : 0);
100 return c | (c1 << 8) | (c2 << 16) | (c1 << 24);
105 static word32 ReedSolomon(word32 high, word32 low)
107 for (
unsigned int i=0;
i<8;
i++) {
108 high = Mod(high>>24) ^ (high<<8) ^ (low>>24);
118 inline word32 Twofish::h0(word32 x,
const word32* key,
unsigned int kLen)
120 x = x | (x<<8) | (x<<16) | (x<<24);
123 #define Q(a, b, c, d, t) q_[a][GETBYTE(t,0)] ^ (q_[b][GETBYTE(t,1)] << 8) ^ \
124 (q_[c][GETBYTE(t,2)] << 16) ^ (q_[d][GETBYTE(t,3)] << 24)
125 case 4: x = Q(1, 0, 0, 1, x) ^ key[6];
126 case 3: x = Q(1, 1, 0, 0, x) ^ key[4];
127 case 2: x = Q(0, 1, 0, 1, x) ^ key[2];
128 x = Q(0, 0, 1, 1, x) ^ key[0];
133 inline word32 Twofish::h(word32 x,
const word32* key,
unsigned int kLen)
135 x = h0(x, key, kLen);
136 return mds_[0][GETBYTE(x,0)] ^ mds_[1][GETBYTE(x,1)] ^
137 mds_[2][GETBYTE(x,2)] ^ mds_[3][GETBYTE(x,3)];
141 void Twofish::SetKey(
const byte* userKey, word32 keylen, CipherDir )
143 unsigned int len = (keylen <= 16 ? 2 : (keylen <= 24 ? 3 : 4));
145 GetUserKey(LittleEndianOrder, key, len*2, userKey, keylen);
148 for (i=0; i<40; i+=2) {
149 word32 a = h(i, key, len);
150 word32 b = rotlFixed(h(i+1, key+1, len), 8);
152 k_[i+1] = rotlFixed(a+2*b, 9);
156 for (i=0; i<len; i++)
157 svec[2*(len-i-1)] = ReedSolomon(key[2*i+1], key[2*i]);
159 for (i=0; i<256; i++) {
160 word32 t = h0(i, svec, len);
161 s_[0][
i] = mds_[0][GETBYTE(t, 0)];
162 s_[1][
i] = mds_[1][GETBYTE(t, 1)];
163 s_[2][
i] = mds_[2][GETBYTE(t, 2)];
164 s_[3][
i] = mds_[3][GETBYTE(t, 3)];
169 void Twofish::ProcessAndXorBlock(
const byte* in,
const byte* xOr, byte* out)
172 if (dir_ == ENCRYPTION)
173 encrypt(in, xOr, out);
175 decrypt(in, xOr, out);
178 #define G1(x) (s_[0][GETBYTE(x,0)] ^ s_[1][GETBYTE(x,1)] ^ \
179 s_[2][GETBYTE(x,2)] ^ s_[3][GETBYTE(x,3)])
180 #define G2(x) (s_[0][GETBYTE(x,3)] ^ s_[1][GETBYTE(x,0)] ^ \
181 s_[2][GETBYTE(x,1)] ^ s_[3][GETBYTE(x,2)])
183 #define ENCROUND(n, a, b, c, d) \
184 x = G1 (a); y = G2 (b); \
185 x += y; y += x + k[2 * (n) + 1]; \
186 (c) ^= x + k[2 * (n)]; \
187 (c) = rotrFixed(c, 1); \
188 (d) = rotlFixed(d, 1) ^ y
190 #define ENCCYCLE(n) \
191 ENCROUND (2 * (n), a, b, c, d); \
192 ENCROUND (2 * (n) + 1, c, d, a, b)
194 #define DECROUND(n, a, b, c, d) \
195 x = G1 (a); y = G2 (b); \
197 (d) ^= y + k[2 * (n) + 1]; \
198 (d) = rotrFixed(d, 1); \
199 (c) = rotlFixed(c, 1); \
200 (c) ^= (x + k[2 * (n)])
202 #define DECCYCLE(n) \
203 DECROUND (2 * (n) + 1, c, d, a, b); \
204 DECROUND (2 * (n), a, b, c, d)
207 typedef BlockGetAndPut<word32, LittleEndian> gpBlock;
209 void Twofish::encrypt(
const byte* inBlock,
const byte* xorBlock,
210 byte* outBlock)
const
212 word32 x, y, a, b, c, d;
214 gpBlock::Get(inBlock)(a)(b)(c)(d);
221 const word32 *k = k_+8;
237 gpBlock::Put(xorBlock, outBlock)(c)(d)(a)(b);
241 void Twofish::decrypt(
const byte* inBlock,
const byte* xorBlock,
242 byte* outBlock)
const
244 word32 x, y, a, b, c, d;
246 gpBlock::Get(inBlock)(c)(d)(a)(b);
253 const word32 *k = k_+8;
268 gpBlock::Put(xorBlock, outBlock)(a)(b)(c)(d);
273 #if defined(DO_TWOFISH_ASM)
275 #define AS1(x) asm(#x);
276 #define AS2(x, y) asm(#x ", " #y);
279 asm(".intel_syntax noprefix"); \
280 AS2( movd mm3, edi ) \
281 AS2( movd mm4, ebx ) \
282 AS2( movd mm5, esi ) \
283 AS2( movd mm6, ebp ) \
284 AS2( mov edi, DWORD PTR [ebp + 8] ) \
285 AS2( mov esi, DWORD PTR [ebp + 12] )
288 AS2( movd esp, mm6 ) \
289 AS2( movd esi, mm5 ) \
290 AS2( movd ebx, mm4 ) \
291 AS2( movd edi, mm3 ) \
295 #define AS1(x) __asm x
296 #define AS2(x, y) __asm x, y
300 AS2( mov ebp, esp ) \
301 AS2( movd mm3, edi ) \
302 AS2( movd mm4, ebx ) \
303 AS2( movd mm5, esi ) \
304 AS2( movd mm6, ebp ) \
305 AS2( mov edi, ecx ) \
306 AS2( mov esi, DWORD PTR [ebp + 8] )
310 AS2( movd esi, mm5 ) \
311 AS2( movd ebx, mm4 ) \
312 AS2( movd edi, mm3 ) \
313 AS2( mov esp, ebp ) \
331 #define ASMG1(z, zl, zh) \
332 AS2( movd mm2, edx ) \
333 AS2( movzx edi, zl ) \
334 AS2( mov esi, DWORD PTR [ebp + edi*4] ) \
335 AS2( movzx edx, zh ) \
336 AS2( xor esi, DWORD PTR 1024[ebp + edx*4] ) \
340 AS2( movzx edi, dl ) \
341 AS2( xor esi, DWORD PTR 2048[ebp + edi*4] ) \
342 AS2( movzx edx, dh ) \
343 AS2( xor esi, DWORD PTR 3072[ebp + edx*4] ) \
348 #define ASMG2(z, zl, zh) \
349 AS2( movd mm7, ecx ) \
350 AS2( movd mm2, eax ) \
353 AS2( mov ecx, DWORD PTR [ebp + edi*4] ) \
354 AS2( movzx eax, zl ) \
355 AS2( xor ecx, DWORD PTR 1024[ebp + eax*4] ) \
359 AS2( movzx edi, zh ) \
360 AS2( xor ecx, DWORD PTR 2048[ebp + edi*4] ) \
361 AS2( movzx eax, al ) \
362 AS2( xor ecx, DWORD PTR 3072[ebp + eax*4] ) \
370 #define ASMENCROUND(N, A, A2, A3, B, B2, B3, C, D) \
372 AS2( movd ebp, mm1 ) \
376 AS2( movd ebp, mm0 ) \
378 AS2( add esi, ecx ) \
381 AS2( add ecx, esi ) \
383 AS2( add ecx, DWORD PTR [ebp + 8 * N + 4] ) \
386 AS2( movd ecx, mm7 ) \
388 AS2( mov edi, esi ) \
389 AS2( add edi, DWORD PTR [ebp + 8 * N] ) \
398 #define ASMDECROUND(N, A, A2, A3, B, B2, B3, C, D) \
400 AS2( movd ebp, mm1 ) \
404 AS2( movd ebp, mm0 ) \
406 AS2( add esi, ecx ) \
409 AS2( add ecx, esi ) \
411 AS2( mov edi, DWORD PTR [ebp + 8 * N + 4] ) \
412 AS2( add edi, ecx ) \
413 AS2( movd ecx, mm7 ) \
420 AS2( mov edi, esi ) \
421 AS2( add edi, DWORD PTR [ebp + 8 * N] ) \
428 void Twofish::AsmEncrypt(
const byte* inBlock, byte* outBlock)
const
432 #ifdef OLD_GCC_OFFSET
440 AS2( mov eax, DWORD PTR [esi] )
442 AS2( mov ebx, DWORD PTR [esi + 4] )
444 AS2( mov ecx, DWORD PTR [esi + 8] )
446 AS2( mov edx, DWORD PTR [esi + 12] )
448 AS2( xor eax, DWORD PTR [edi] )
449 AS2( xor ebx, DWORD PTR [edi + 4] )
450 AS2( xor ecx, DWORD PTR [edi + 8] )
451 AS2( xor edx, DWORD PTR [edi + 12] )
454 ASMENCROUND( 0, eax, al, ah, ebx, bl, bh, ecx, edx)
455 ASMENCROUND( 1, ecx, cl, ch, edx, dl, dh, eax, ebx)
456 ASMENCROUND( 2, eax, al, ah, ebx, bl, bh, ecx, edx)
457 ASMENCROUND( 3, ecx, cl, ch, edx, dl, dh, eax, ebx)
458 ASMENCROUND( 4, eax, al, ah, ebx, bl, bh, ecx, edx)
459 ASMENCROUND( 5, ecx, cl, ch, edx, dl, dh, eax, ebx)
460 ASMENCROUND( 6, eax, al, ah, ebx, bl, bh, ecx, edx)
461 ASMENCROUND( 7, ecx, cl, ch, edx, dl, dh, eax, ebx)
462 ASMENCROUND( 8, eax, al, ah, ebx, bl, bh, ecx, edx)
463 ASMENCROUND( 9, ecx, cl, ch, edx, dl, dh, eax, ebx)
464 ASMENCROUND(10, eax, al, ah, ebx, bl, bh, ecx, edx)
465 ASMENCROUND(11, ecx, cl, ch, edx, dl, dh, eax, ebx)
466 ASMENCROUND(12, eax, al, ah, ebx, bl, bh, ecx, edx)
467 ASMENCROUND(13, ecx, cl, ch, edx, dl, dh, eax, ebx)
468 ASMENCROUND(14, eax, al, ah, ebx, bl, bh, ecx, edx)
469 ASMENCROUND(15, ecx, cl, ch, edx, dl, dh, eax, ebx)
475 AS2( mov edi, [ebp + 16] )
477 AS2( mov edi, [ebp + 12] )
480 AS2( xor ecx, DWORD PTR [esi + 16] )
481 AS2( xor edx, DWORD PTR [esi + 20] )
482 AS2( xor eax, DWORD PTR [esi + 24] )
483 AS2( xor ebx, DWORD PTR [esi + 28] )
485 AS2( mov [edi], ecx )
486 AS2( mov [edi + 4], edx )
487 AS2( mov [edi + 8], eax )
488 AS2( mov [edi + 12], ebx )
498 void Twofish::AsmDecrypt(
const byte* inBlock, byte* outBlock)
const
502 #ifdef OLD_GCC_OFFSET
510 AS2( mov ecx, DWORD PTR [esi] )
512 AS2( mov edx, DWORD PTR [esi + 4] )
514 AS2( mov eax, DWORD PTR [esi + 8] )
516 AS2( mov ebx, DWORD PTR [esi + 12] )
518 AS2( xor ecx, DWORD PTR [edi + 16] )
519 AS2( xor edx, DWORD PTR [edi + 20] )
520 AS2( xor eax, DWORD PTR [edi + 24] )
521 AS2( xor ebx, DWORD PTR [edi + 28] )
524 ASMDECROUND(15, ecx, cl, ch, edx, dl, dh, eax, ebx)
525 ASMDECROUND(14, eax, al, ah, ebx, bl, bh, ecx, edx)
526 ASMDECROUND(13, ecx, cl, ch, edx, dl, dh, eax, ebx)
527 ASMDECROUND(12, eax, al, ah, ebx, bl, bh, ecx, edx)
528 ASMDECROUND(11, ecx, cl, ch, edx, dl, dh, eax, ebx)
529 ASMDECROUND(10, eax, al, ah, ebx, bl, bh, ecx, edx)
530 ASMDECROUND( 9, ecx, cl, ch, edx, dl, dh, eax, ebx)
531 ASMDECROUND( 8, eax, al, ah, ebx, bl, bh, ecx, edx)
532 ASMDECROUND( 7, ecx, cl, ch, edx, dl, dh, eax, ebx)
533 ASMDECROUND( 6, eax, al, ah, ebx, bl, bh, ecx, edx)
534 ASMDECROUND( 5, ecx, cl, ch, edx, dl, dh, eax, ebx)
535 ASMDECROUND( 4, eax, al, ah, ebx, bl, bh, ecx, edx)
536 ASMDECROUND( 3, ecx, cl, ch, edx, dl, dh, eax, ebx)
537 ASMDECROUND( 2, eax, al, ah, ebx, bl, bh, ecx, edx)
538 ASMDECROUND( 1, ecx, cl, ch, edx, dl, dh, eax, ebx)
539 ASMDECROUND( 0, eax, al, ah, ebx, bl, bh, ecx, edx)
545 AS2( mov edi, [ebp + 16] )
547 AS2( mov edi, [ebp + 12] )
550 AS2( xor eax, DWORD PTR [esi ] )
551 AS2( xor ebx, DWORD PTR [esi + 4] )
552 AS2( xor ecx, DWORD PTR [esi + 8] )
553 AS2( xor edx, DWORD PTR [esi + 12] )
555 AS2( mov [edi], eax )
556 AS2( mov [edi + 4], ebx )
557 AS2( mov [edi + 8], ecx )
558 AS2( mov [edi + 12], edx )
566 #endif // defined(DO_TWOFISH_ASM)