// serpent.cpp - written and placed in the public domain by Wei Dai /* Adapted for TrueCrypt */ /* Adapted for VeraCrypt */ #ifdef TC_WINDOWS_BOOT #pragma optimize ("t", on) #endif #include "Serpent.h" #include "Common/Endian.h" #ifdef TC_WINDOWS_BOOT #include <stdlib.h> #pragma intrinsic(_lrotr,_lrotl) #define rotr32(x,n) _lrotr(x, n) #define rotl32(x,n) _lrotl(x, n) #else #include "Crypto/misc.h" #endif #include <memory.h> // linear transformation #define LT(i,a,b,c,d,e) {\ a = rotl32(a, 13); \ c = rotl32(c, 3); \ d = rotl32(d ^ c ^ (a << 3), 7); \ b = rotl32(b ^ a ^ c, 1); \ a = rotl32(a ^ b ^ d, 5); \ c = rotl32(c ^ d ^ (b << 7), 22);} // inverse linear transformation #define ILT(i,a,b,c,d,e) {\ c = rotr32(c, 22); \ a = rotr32(a, 5); \ c ^= d ^ (b << 7); \ a ^= b ^ d; \ b = rotr32(b, 1); \ d = rotr32(d, 7) ^ c ^ (a << 3); \ b ^= a ^ c; \ c = rotr32(c, 3); \ a = rotr32(a, 13);} // order of output from S-box functions #define beforeS0(f) f(0,a,b,c,d,e) #define afterS0(f) f(1,b,e,c,a,d) #define afterS1(f) f(2,c,b,a,e,d) #define afterS2(f) f(3,a,e,b,d,c) #define afterS3(f) f(4,e,b,d,c,a) #define afterS4(f) f(5,b,a,e,c,d) #define afterS5(f) f(6,a,c,b,e,d) #define afterS6(f) f(7,a,c,d,b,e) #define afterS7(f) f(8,d,e,b,a,c) // order of output from inverse S-box functions #define beforeI7(f) f(8,a,b,c,d,e) #define afterI7(f) f(7,d,a,b,e,c) #define afterI6(f) f(6,a,b,c,e,d) #define afterI5(f) f(5,b,d,e,c,a) #define afterI4(f) f(4,b,c,e,a,d) #define afterI3(f) f(3,a,b,e,c,d) #define afterI2(f) f(2,b,d,e,c,a) #define afterI1(f) f(1,a,b,c,e,d) #define afterI0(f) f(0,a,d,b,e,c) // The instruction sequences for the S-box functions // come from Dag Arne Osvik's paper "Speeding up Serpent". #define S0(i, r0, r1, r2, r3, r4) \ { \ r3 ^= r0; \ r4 = r1; \ r1 &= r3; \ r4 ^= r2; \ r1 ^= r0; \ r0 |= r3; \ r0 ^= r4; \ r4 ^= r3; \ r3 ^= r2; \ r2 |= r1; \ r2 ^= r4; \ r4 = ~r4; \ r4 |= r1; \ r1 ^= r3; \ r1 ^= r4; \ r3 |= r0; \ r1 ^= r3; \ r4 ^= r3; \ } #define I0(i, r0, r1, r2, r3, r4) \ { \ r2 = ~r2; \ r4 = r1; \ r1 |= r0; \ r4 = ~r4; \ r1 ^= r2; \ r2 |= r4; \ r1 ^= r3; \ r0 ^= r4; \ r2 ^= r0; \ r0 &= r3; \ r4 ^= r0; \ r0 |= r1; \ r0 ^= r2; \ r3 ^= r4; \ r2 ^= r1; \ r3 ^= r0; \ r3 ^= r1; \ r2 &= r3; \ r4 ^= r2; \ } #define S1(i, r0, r1, r2, r3, r4) \ { \ r0 = ~r0; \ r2 = ~r2; \ r4 = r0; \ r0 &= r1; \ r2 ^= r0; \ r0 |= r3; \ r3 ^= r2; \ r1 ^= r0; \ r0 ^= r4; \ r4 |= r1; \ r1 ^= r3; \ r2 |= r0; \ r2 &= r4; \ r0 ^= r1; \ r1 &= r2; \ r1 ^= r0; \ r0 &= r2; \ r0 ^= r4; \ } #define I1(i, r0, r1, r2, r3, r4) \ { \ r4 = r1; \ r1 ^= r3; \ r3 &= r1; \ r4 ^= r2; \ r3 ^= r0; \ r0 |= r1; \ r2 ^= r3; \ r0 ^= r4; \ r0 |= r2; \ r1 ^= r3; \ r0 ^= r1; \ r1 |= r3; \ r1 ^= r0; \ r4 = ~r4; \ r4 ^= r1; \ r1 |= r0; \ r1 ^= r0; \ r1 |= r4; \ r3 ^= r1; \ } #define S2(i, r0, r1, r2, r3, r4) \ { \ r4 = r0; \ r0 &= r2; \ r0 ^= r3; \ r2 ^= r1; \ r2 ^= r0; \ r3 |= r4; \ r3 ^= r1; \ r4 ^= r2; \ r1 = r3; \ r3 |= r4; \ r3 ^= r0; \ r0 &= r1; \ r4 ^= r0; \ r1 ^= r3; \ r1 ^= r4; \ r4 = ~r4; \ } #define I2(i, r0, r1, r2, r3, r4) \ { \ r2 ^= r3; \ r3 ^= r0; \ r4 = r3; \ r3 &= r2; \ r3 ^= r1; \ r1 |= r2; \ r1 ^= r4; \ r4 &= r3; \ r2 ^= r3; \ r4 &= r0; \ r4 ^= r2; \ r2 &= r1; \ r2 |= r0; \ r3 = ~r3; \ r2 ^= r3; \ r0 ^= r3; \ r0 &= r1; \ r3 ^= r4; \ r3 ^= r0; \ } #define S3(i, r0, r1, r2, r3, r4) \ { \ r4 = r0; \ r0 |= r3; \ r3 ^= r1; \ r1 &= r4; \ r4 ^= r2; \ r2 ^= r3; \ r3 &= r0; \ r4 |= r1; \ r3 ^= r4; \ r0 ^= r1; \ r4 &= r0; \ r1 ^= r3; \ r4 ^= r2; \ r1 |= r0; \ r1 ^= r2; \ r0 ^= r3; \ r2 = r1; \ r1 |= r3; \ r1 ^= r0; \ } #define I3(i, r0, r1, r2, r3, r4) \ { \ r4 = r2; \ r2 ^= r1; \ r1 &= r2; \ r1 ^= r0; \ r0 &= r4; \ r4 ^= r3; \ r3 |= r1; \ r3 ^= r2; \ r0 ^= r4; \ r2 ^= r0; \ r0 |= r3; \ r0 ^= r1; \ r4 ^= r2; \ r2 &= r3; \ r1 |= r3; \ r1 ^= r2; \ r4 ^= r0; \ r2 ^= r4; \ } #define S4(i, r0, r1, r2, r3, r4) \ { \ r1 ^= r3; \ r3 = ~r3; \ r2 ^= r3; \ r3 ^= r0; \ r4 = r1; \ r1 &= r3; \ r1 ^= r2; \ r4 ^= r3; \ r0 ^= r4; \ r2 &= r4; \ r2 ^= r0; \ r0 &= r1; \ r3 ^= r0; \ r4 |= r1; \ r4 ^= r0; \ r0 |= r3; \ r0 ^= r2; \ r2 &= r3; \ r0 = ~r0; \ r4 ^= r2; \ } #define I4(i, r0, r1, r2, r3, r4) \ { \ r4 = r2; \ r2 &= r3; \ r2 ^= r1; \ r1 |= r3; \ r1 &= r0; \ r4 ^= r2; \ r4 ^= r1; \ r1 &= r2; \ r0 = ~r0; \ r3 ^= r4; \ r1 ^= r3; \ r3 &= r0; \ r3 ^= r2; \ r0 ^= r1; \ r2 &= r0; \ r3 ^= r0; \ r2 ^= r4; \ r2 |= r3; \ r3 ^= r0; \ r2 ^= r1; \ } #define S5(i, r0, r1, r2, r3, r4) \ { \ r0 ^= r1; \ r1 ^= r3; \ r3 = ~r3; \ r4 = r1; \ r1 &= r0; \ r2 ^= r3; \ r1 ^= r2; \ r2 |= r4; \ r4 ^= r3; \ r3 &= r1; \ r3 ^= r0; \ r4 ^= r1; \ r4 ^= r2; \ r2 ^= r0; \ r0 &= r3; \ r2 = ~r2; \ r0 ^= r4; \ r4 |= r3; \ r2 ^= r4; \ } #define I5(i, r0, r1, r2, r3, r4) \ { \ r1 = ~r1; \ r4 = r3; \ r2 ^= r1; \ r3 |= r0; \ r3 ^= r2; \ r2 |= r1; \ r2 &= r0; \ r4 ^= r3; \ r2 ^= r4; \ r4 |= r0; \ r4 ^= r1; \ r1 &= r2; \ r1 ^= r3; \ r4 ^= r2; \ r3 &= r4; \ r4 ^= r1; \ r3 ^= r0; \ r3 ^= r4; \ r4 = ~r4; \ } #define S6(i, r0, r1, r2, r3, r4) \ { \ r2 = ~r2; \ r4 = r3; \ r3 &= r0; \ r0 ^= r4; \ r3 ^= r2; \ r2 |= r4; \ r1 ^= r3; \ r2 ^= r0; \ r0 |= r1; \ r2 ^= r1; \ r4 ^= r0; \ r0 |= r3; \ r0 ^= r2; \ r4 ^= r3; \ r4 ^= r0; \ r3 = ~r3; \ r2 &= r4; \ r2 ^= r3; \ } #define I6(i, r0, r1, r2, r3, r4) \ { \ r0 ^= r2; \ r4 = r2; \ r2 &= r0; \ r4 ^= r3; \ r2 = ~r2; \ r3 ^= r1; \ r2 ^= r3; \ r4 |= r0; \ r0 ^= r2; \ r3 ^= r4; \ r4 ^= r1; \ r1 &= r3; \ r1 ^= r0; \ r0 ^= r3; \ r0 |= r2; \ r3 ^= r1; \ r4 ^= r0; \ } #define S7(i, r0, r1, r2, r3, r4) \ { \ r4 = r2; \ r2 &= r1; \ r2 ^= r3; \ r3 &= r1; \ r4 ^= r2; \ r2 ^= r1; \ r1 ^= r0; \ r0 |= r4; \ r0 ^= r2; \ r3 ^= r1; \ r2 ^= r3; \ r3 &= r0; \ r3 ^= r4; \ r4 ^= r2; \ r2 &= r0; \ r4 = ~r4; \ r2 ^= r4; \ r4 &= r0; \ r1 ^= r3; \ r4 ^= r1; \ } #define I7(i, r0, r1, r2, r3, r4) \ { \ r4 = r2; \ r2 ^= r0; \ r0 &= r3; \ r2 = ~r2; \ r4 |= r3; \ r3 ^= r1; \ r1 |= r0; \ r0 ^= r2; \ r2 &= r4; \ r1 ^= r2; \ r2 ^= r0; \ r0 |= r2; \ r3 &= r4; \ r0 ^= r3; \ r4 ^= r1; \ r3 ^= r4; \ r4 |= r0; \ r3 ^= r2; \ r4 ^= r2; \ } // key xor #define KX(r, a, b, c, d, e) {\ a ^= k[4 * r + 0]; \ b ^= k[4 * r + 1]; \ c ^= k[4 * r + 2]; \ d ^= k[4 * r + 3];} #ifdef TC_MINIMIZE_CODE_SIZE static void S0f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) { *r3 ^= *r0; *r4 = *r1; *r1 &= *r3; *r4 ^= *r2; *r1 ^= *r0; *r0 |= *r3; *r0 ^= *r4; *r4 ^= *r3; *r3 ^= *r2; *r2 |= *r1; *r2 ^= *r4; *r4 = ~*r4; *r4 |= *r1; *r1 ^= *r3; *r1 ^= *r4; *r3 |= *r0; *r1 ^= *r3; *r4 ^= *r3; } static void S1f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) { *r0 = ~*r0; *r2 = ~*r2; *r4 = *r0; *r0 &= *r1; *r2 ^= *r0; *r0 |= *r3; *r3 ^= *r2; *r1 ^= *r0; *r0 ^= *r4; *r4 |= *r1; *r1 ^= *r3; *r2 |= *r0; *r2 &= *r4; *r0 ^= *r1; *r1 &= *r2; *r1 ^= *r0; *r0 &= *r2; *r0 ^= *r4; } static void S2f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) { *r4 = *r0; *r0 &= *r2; *r0 ^= *r3; *r2 ^= *r1; *r2 ^= *r0; *r3 |= *r4; *r3 ^= *r1; *r4 ^= *r2; *r1 = *r3; *r3 |= *r4; *r3 ^= *r0; *r0 &= *r1; *r4 ^= *r0; *r1 ^= *r3; *r1 ^= *r4; *r4 = ~*r4; } static void S3f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) { *r4 = *r0; *r0 |= *r3; *r3 ^= *r1; *r1 &= *r4; *r4 ^= *r2; *r2 ^= *r3; *r3 &= *r0; *r4 |= *r1; *r3 ^= *r4; *r0 ^= *r1; *r4 &= *r0; *r1 ^= *r3; *r4 ^= *r2; *r1 |= *r0; *r1 ^= *r2; *r0 ^= *r3; *r2 = *r1; *r1 |= *r3; *r1 ^= *r0; } static void S4f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) { *r1 ^= *r3; *r3 = ~*r3; *r2 ^= *r3; *r3 ^= *r0; *r4 = *r1; *r1 &= *r3; *r1 ^= *r2; *r4 ^= *r3; *r0 ^= *r4; *r2 &= *r4; *r2 ^= *r0; *r0 &= *r1; *r3 ^= *r0; *r4 |= *r1; *r4 ^= *r0; *r0 |= *r3; *r0 ^= *r2; *r2 &= *r3; *r0 = ~*r0; *r4 ^= *r2; } static void S5f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) { *r0 ^= *r1; *r1 ^= *r3; *r3 = ~*r3; *r4 = *r1; *r1 &= *r0; *r2 ^= *r3; *r1 ^= *r2; *r2 |= *r4; *r4 ^= *r3; *r3 &= *r1; *r3 ^= *r0; *r4 ^= *r1; *r4 ^= *r2; *r2 ^= *r0; *r0 &= *r3; *r2 = ~*r2; *r0 ^= *r4; *r4 |= *r3; *r2 ^= *r4; } static void S6f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) { *r2 = ~*r2; *r4 = *r3; *r3 &= *r0; *r0 ^= *r4; *r3 ^= *r2; *r2 |= *r4; *r1 ^= *r3; *r2 ^= *r0; *r0 |= *r1; *r2 ^= *r1; *r4 ^= *r0; *r0 |= *r3; *r0 ^= *r2; *r4 ^= *r3; *r4 ^= *r0; *r3 = ~*r3; *r2 &= *r4; *r2 ^= *r3; } static void S7f (unsigned __int32 *r0, unsigned __int32 *r1, unsigned __int32 *r2, unsigned __int32 *r3, unsigned __int32 *r4) { *r4 = *r2; *r2 &= *r1; *r2 ^= *r3; *r3 &= *r1; *r4 ^= *r2; *r2 ^= *r1; *r1 ^= *r0; *r0 |= *r4; *r0 ^= *r2; *r3 ^= *r1; *r2 ^= *r3; *r3 &= *r0; *r3 ^= *r4; *r4 ^= *r2; *r2 &= *r0; *r4 = ~*r4; *r2 ^= *r4; *r4 &= *r0; *r1 ^= *r3; *r4 ^= *r1; } static void KXf (const unsigned __int32 *k, unsigned int r, unsigned __int32 *a, unsigned __int32 *b, unsigned __int32 *c, unsigned __int32 *d) { *a ^= k[r]; *b ^= k[r + 1]; *c ^= k[r + 2]; *d ^= k[r + 3]; } #endif // TC_MINIMIZE_CODE_SIZE #ifndef TC_MINIMIZE_CODE_SIZE void serpent_set_key(const unsigned __int8 userKey[],unsigned __int8 *ks) { unsigned __int32 a,b,c,d,e; unsigned __int32 *k = (unsigned __int32 *)ks; unsigned __int32 t; int i; for (i = 0; i < 8; i++) k[i] = LE32(((unsigned __int32*)userKey)[i]); k += 8; t = k[-1]; for (i = 0; i < 132; ++i) k[i] = t = rotl32(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); k -= 20; #define LK(r, a, b, c, d, e) {\ a = k[(8-r)*4 + 0]; \ b = k[(8-r)*4 + 1]; \ c = k[(8-r)*4 + 2]; \ d = k[(8-r)*4 + 3];} #define SK(r, a, b, c, d, e) {\ k[(8-r)*4 + 4] = a; \ k[(8-r)*4 + 5] = b; \ k[(8-r)*4 + 6] = c; \ k[(8-r)*4 + 7] = d;} \ for (i=0; i<4; i++) { afterS2(LK); afterS2(S3); afterS3(SK); afterS1(LK); afterS1(S2); afterS2(SK); afterS0(LK); afterS0(S1); afterS1(SK); beforeS0(LK); beforeS0(S0); afterS0(SK); k += 8*4; afterS6(LK); afterS6(S7); afterS7(SK); afterS5(LK); afterS5(S6); afterS6(SK); afterS4(LK); afterS4(S5); afterS5(SK); afterS3(LK); afterS3(S4); afterS4(SK); } afterS2(LK); afterS2(S3); afterS3(SK); } #else // TC_MINIMIZE_CODE_SIZE static void LKf (unsigned __int32 *k, unsigned int r, unsigned __int32 *a, unsigned __int32 *b, unsigned __int32 *c, unsigned __int32 *d) { *a = k[r]; *b = k[r + 1]; *c = k[r + 2]; *d = k[r + 3]; } static void SKf (unsigned __int32 *k, unsigned int r, unsigned __int32 *a, unsigned __int32 *b, unsigned __int32 *c, unsigned __int32 *d) { k[r + 4] = *a; k[r + 5] = *b; k[r + 6] = *c; k[r + 7] = *d; } void serpent_set_key(const unsigned __int8 userKey[], unsigned __int8 *ks) { unsigned __int32 a,b,c,d,e; unsigned __int32 *k = (unsigned __int32 *)ks; unsigned __int32 t; int i; for (i = 0; i < 8; i++) k[i] = LE32(((unsigned __int32*)userKey)[i]); k += 8; t = k[-1]; for (i = 0; i < 132; ++i) k[i] = t = rotl32(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); k -= 20; for (i=0; i<4; i++) { LKf (k, 20, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); SKf (k, 16, &e, &b, &d, &c); LKf (k, 24, &c, &b, &a, &e); S2f (&c, &b, &a, &e, &d); SKf (k, 20, &a, &e, &b, &d); LKf (k, 28, &b, &e, &c, &a); S1f (&b, &e, &c, &a, &d); SKf (k, 24, &c, &b, &a, &e); LKf (k, 32, &a, &b, &c, &d); S0f (&a, &b, &c, &d, &e); SKf (k, 28, &b, &e, &c, &a); k += 8*4; LKf (k, 4, &a, &c, &d, &b); S7f (&a, &c, &d, &b, &e); SKf (k, 0, &d, &e, &b, &a); LKf (k, 8, &a, &c, &b, &e); S6f (&a, &c, &b, &e, &d); SKf (k, 4, &a, &c, &d, &b); LKf (k, 12, &b, &a, &e, &c); S5f (&b, &a, &e, &c, &d); SKf (k, 8, &a, &c, &b, &e); LKf (k, 16, &e, &b, &d, &c); S4f (&e, &b, &d, &c, &a); SKf (k, 12, &b, &a, &e, &c); } LKf (k, 20, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); SKf (k, 16, &e, &b, &d, &c); } #endif // TC_MINIMIZE_CODE_SIZE #ifndef TC_MINIMIZE_CODE_SIZE void serpent_encrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) { unsigned __int32 a, b, c, d, e; unsigned int i=1; const unsigned __int32 *k = (unsigned __int32 *)ks + 8; unsigned __int32 *in = (unsigned __int32 *) inBlock; unsigned __int32 *out = (unsigned __int32 *) outBlock; a = LE32(in[0]); b = LE32(in[1]); c = LE32(in[2]); d = LE32(in[3]); do { beforeS0(KX); beforeS0(S0); afterS0(LT); afterS0(KX); afterS0(S1); afterS1(LT); afterS1(KX); afterS1(S2); afterS2(LT); afterS2(KX); afterS2(S3); afterS3(LT); afterS3(KX); afterS3(S4); afterS4(LT); afterS4(KX); afterS4(S5); afterS5(LT); afterS5(KX); afterS5(S6); afterS6(LT); afterS6(KX); afterS6(S7); if (i == 4) break; ++i; c = b; b = e; e = d; d = a; a = e; k += 32; beforeS0(LT); } while (1); afterS7(KX); out[0] = LE32(d); out[1] = LE32(e); out[2] = LE32(b); out[3] = LE32(a); } #else // TC_MINIMIZE_CODE_SIZE typedef unsigned __int32 uint32; static void LTf (uint32 *a, uint32 *b, uint32 *c, uint32 *d) { *a = rotl32(*a, 13); *c = rotl32(*c, 3); *d = rotl32(*d ^ *c ^ (*a << 3), 7); *b = rotl32(*b ^ *a ^ *c, 1); *a = rotl32(*a ^ *b ^ *d, 5); *c = rotl32(*c ^ *d ^ (*b << 7), 22); } void serpent_encrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) { unsigned __int32 a, b, c, d, e; unsigned int i=1; const unsigned __int32 *k = (unsigned __int32 *)ks + 8; unsigned __int32 *in = (unsigned __int32 *) inBlock; unsigned __int32 *out = (unsigned __int32 *) outBlock; a = LE32(in[0]); b = LE32(in[1]); c = LE32(in[2]); d = LE32(in[3]); do { KXf (k, 0, &a, &b, &c, &d); S0f (&a, &b, &c, &d, &e); LTf (&b, &e, &c, &a); KXf (k, 4, &b, &e, &c, &a); S1f (&b, &e, &c, &a, &d); LTf (&c, &b, &a, &e); KXf (k, 8, &c, &b, &a, &e); S2f (&c, &b, &a, &e, &d); LTf (&a, &e, &b, &d); KXf (k, 12, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); LTf (&e, &b, &d, &c); KXf (k, 16, &e, &b, &d, &c); S4f (&e, &b, &d, &c, &a); LTf (&b, &a, &e, &c); KXf (k, 20, &b, &a, &e, &c); S5f (&b, &a, &e, &c, &d); LTf (&a, &c, &b, &e); KXf (k, 24, &a, &c, &b, &e); S6f (&a, &c, &b, &e, &d); LTf (&a, &c, &d, &b); KXf (k, 28, &a, &c, &d, &b); S7f (&a, &c, &d, &b, &e); if (i == 4) break; ++i; c = b; b = e; e = d; d = a; a = e; k += 32; LTf (&a,&b,&c,&d); } while (1); KXf (k, 32, &d, &e, &b, &a); out[0] = LE32(d); out[1] = LE32(e); out[2] = LE32(b); out[3] = LE32(a); } #endif // TC_MINIMIZE_CODE_SIZE #if !defined (TC_MINIMIZE_CODE_SIZE) void serpent_decrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) { unsigned __int32 a, b, c, d, e; const unsigned __int32 *k = (unsigned __int32 *)ks + 104; unsigned int i=4; unsigned __int32 *in = (unsigned __int32 *) inBlock; unsigned __int32 *out = (unsigned __int32 *) outBlock; a = LE32(in[0]); b = LE32(in[1]); c = LE32(in[2]); d = LE32(in[3]); beforeI7(KX); goto start; do { c = b; b = d; d = e; k -= 32; beforeI7(ILT); start: beforeI7(I7); afterI7(KX); afterI7(ILT); afterI7(I6); afterI6(KX); afterI6(ILT); afterI6(I5); afterI5(KX); afterI5(ILT); afterI5(I4); afterI4(KX); afterI4(ILT); afterI4(I3); afterI3(KX); afterI3(ILT); afterI3(I2); afterI2(KX); afterI2(ILT); afterI2(I1); afterI1(KX); afterI1(ILT); afterI1(I0); afterI0(KX); } while (--i != 0); out[0] = LE32(a); out[1] = LE32(d); out[2] = LE32(b); out[3] = LE32(e); } #else // TC_MINIMIZE_CODE_SIZE static void ILTf (uint32 *a, uint32 *b, uint32 *c, uint32 *d) { *c = rotr32(*c, 22); *a = rotr32(*a, 5); *c ^= *d ^ (*b << 7); *a ^= *b ^ *d; *b = rotr32(*b, 1); *d = rotr32(*d, 7) ^ *c ^ (*a << 3); *b ^= *a ^ *c; *c = rotr32(*c, 3); *a = rotr32(*a, 13); } void serpent_decrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) { unsigned __int32 a, b, c, d, e; const unsigned __int32 *k = (unsigned __int32 *)ks + 104; unsigned int i=4; unsigned __int32 *in = (unsigned __int32 *) inBlock; unsigned __int32 *out = (unsigned __int32 *) outBlock; a = LE32(in[0]); b = LE32(in[1]); c = LE32(in[2]); d = LE32(in[3]); KXf (k, 32, &a, &b, &c, &d); goto start; do { c = b; b = d; d = e; k -= 32; beforeI7(ILT); start: beforeI7(I7); KXf (k, 28, &d, &a, &b, &e); ILTf (&d, &a, &b, &e); afterI7(I6); KXf (k, 24, &a, &b, &c, &e); ILTf (&a, &b, &c, &e); afterI6(I5); KXf (k, 20, &b, &d, &e, &c); ILTf (&b, &d, &e, &c); afterI5(I4); KXf (k, 16, &b, &c, &e, &a); ILTf (&b, &c, &e, &a); afterI4(I3); KXf (k, 12, &a, &b, &e, &c); ILTf (&a, &b, &e, &c); afterI3(I2); KXf (k, 8, &b, &d, &e, &c); ILTf (&b, &d, &e, &c); afterI2(I1); KXf (k, 4, &a, &b, &c, &e); ILTf (&a, &b, &c, &e); afterI1(I0); KXf (k, 0, &a, &d, &b, &e); } while (--i != 0); out[0] = LE32(a); out[1] = LE32(d); out[2] = LE32(b); out[3] = LE32(e); } #endif // TC_MINIMIZE_CODE_SIZE