00001
00002
00003
00004 #include "pch.h"
00005 #include "3way.h"
00006
00007 NAMESPACE_BEGIN(CryptoPP)
00008
00009 static const word32 START_E = 0x0b0b;
00010 static const word32 START_D = 0xb1b1;
00011
00012 static inline word32 reverseBits(word32 a)
00013 {
00014 a = ((a & 0xAAAAAAAA) >> 1) | ((a & 0x55555555) << 1);
00015 a = ((a & 0xCCCCCCCC) >> 2) | ((a & 0x33333333) << 2);
00016 return ((a & 0xF0F0F0F0) >> 4) | ((a & 0x0F0F0F0F) << 4);
00017 }
00018
00019 #define mu(a0, a1, a2) \
00020 { \
00021 a1 = reverseBits(a1); \
00022 word32 t = reverseBits(a0); \
00023 a0 = reverseBits(a2); \
00024 a2 = t; \
00025 }
00026
00027 #define pi_gamma_pi(a0, a1, a2) \
00028 { \
00029 word32 b0, b2; \
00030 b2 = rotlFixed(a2, 1U); \
00031 b0 = rotlFixed(a0, 22U); \
00032 a0 = rotlFixed(b0 ^ (a1|(~b2)), 1U); \
00033 a2 = rotlFixed(b2 ^ (b0|(~a1)), 22U);\
00034 a1 ^= (b2|(~b0)); \
00035 }
00036
00037
00038 #define theta(a0, a1, a2) \
00039 { \
00040 word32 b0, b1, c; \
00041 c = a0 ^ a1 ^ a2; \
00042 c = rotlFixed(c, 16U) ^ rotlFixed(c, 8U); \
00043 b0 = (a0 << 24) ^ (a2 >> 8) ^ (a1 << 8) ^ (a0 >> 24); \
00044 b1 = (a1 << 24) ^ (a0 >> 8) ^ (a2 << 8) ^ (a1 >> 24); \
00045 a0 ^= c ^ b0; \
00046 a1 ^= c ^ b1; \
00047 a2 ^= c ^ (b0 >> 16) ^ (b1 << 16); \
00048 }
00049
00050 #define rho(a0, a1, a2) \
00051 { \
00052 theta(a0, a1, a2); \
00053 pi_gamma_pi(a0, a1, a2); \
00054 }
00055
00056 static void GenerateRoundConstants(word32 strt, word32 *rtab, unsigned int rounds)
00057 {
00058 for(unsigned i=0; i<=rounds; i++)
00059 {
00060 rtab[i] = strt;
00061 strt <<= 1;
00062 if (strt&0x10000) strt ^= 0x11011;
00063 }
00064 }
00065
00066 ThreeWayEncryption::ThreeWayEncryption(const byte *uk, unsigned int keylength, unsigned int rounds)
00067 : rounds(rounds), rc(rounds+1)
00068 {
00069 assert(keylength == 0 || keylength == KEYLENGTH);
00070 GenerateRoundConstants(START_E, rc, rounds);
00071 for (int i=0; i<3; i++)
00072 k[i] = (word32)uk[4*i+3] | ((word32)uk[4*i+2]<<8) | ((word32)uk[4*i+1]<<16) | ((word32)uk[4*i]<<24);
00073 }
00074
00075 ThreeWayEncryption::~ThreeWayEncryption()
00076 {
00077 k[0]=k[1]=k[2]=0;
00078 }
00079
00080 void ThreeWayEncryption::ProcessBlock(const byte *in, byte * out) const
00081 {
00082 word32 a0, a1, a2;
00083
00084 #ifdef IS_LITTLE_ENDIAN
00085 a0 = byteReverse(*(word32 *)in);
00086 a1 = byteReverse(*(word32 *)(in+4));
00087 a2 = byteReverse(*(word32 *)(in+8));
00088 #else
00089 a0 = *(word32 *)in;
00090 a1 = *(word32 *)(in+4);
00091 a2 = *(word32 *)(in+8);
00092 #endif
00093
00094 for(unsigned i=0; i<rounds; i++)
00095 {
00096 a0 ^= k[0] ^ (rc[i]<<16);
00097 a1 ^= k[1];
00098 a2 ^= k[2] ^ rc[i];
00099 rho(a0, a1, a2);
00100 }
00101 a0 ^= k[0] ^ (rc[rounds]<<16);
00102 a1 ^= k[1];
00103 a2 ^= k[2] ^ rc[rounds];
00104 theta(a0, a1, a2);
00105
00106 #ifdef IS_LITTLE_ENDIAN
00107 *(word32 *)out = byteReverse(a0);
00108 *(word32 *)(out+4) = byteReverse(a1);
00109 *(word32 *)(out+8) = byteReverse(a2);
00110 #else
00111 *(word32 *)out = a0;
00112 *(word32 *)(out+4) = a1;
00113 *(word32 *)(out+8) = a2;
00114 #endif
00115 }
00116
00117 ThreeWayDecryption::ThreeWayDecryption(const byte *uk, unsigned int keylength, unsigned int rounds)
00118 : rounds(rounds), rc(rounds+1)
00119 {
00120 assert(keylength == 0 || keylength == KEYLENGTH);
00121 GenerateRoundConstants(START_D, rc, rounds);
00122 for (int i=0; i<3; i++)
00123 k[i] = (word32)uk[4*i+3] | ((word32)uk[4*i+2]<<8) | ((word32)uk[4*i+1]<<16) | ((word32)uk[4*i]<<24);
00124 theta(k[0], k[1], k[2]);
00125 mu(k[0], k[1], k[2]);
00126 k[0] = byteReverse(k[0]);
00127 k[1] = byteReverse(k[1]);
00128 k[2] = byteReverse(k[2]);
00129 }
00130
00131 ThreeWayDecryption::~ThreeWayDecryption()
00132 {
00133 k[0]=k[1]=k[2]=0;
00134 }
00135
00136 void ThreeWayDecryption::ProcessBlock(const byte *in, byte * out) const
00137 {
00138 word32 a0, a1, a2;
00139
00140 #ifndef IS_LITTLE_ENDIAN
00141 a0 = byteReverse(*(word32 *)in);
00142 a1 = byteReverse(*(word32 *)(in+4));
00143 a2 = byteReverse(*(word32 *)(in+8));
00144 #else
00145 a0 = *(word32 *)in;
00146 a1 = *(word32 *)(in+4);
00147 a2 = *(word32 *)(in+8);
00148 #endif
00149
00150 mu(a0, a1, a2);
00151 for(unsigned i=0; i<rounds; i++)
00152 {
00153 a0 ^= k[0] ^ (rc[i]<<16);
00154 a1 ^= k[1];
00155 a2 ^= k[2] ^ rc[i];
00156 rho(a0, a1, a2);
00157 }
00158 a0 ^= k[0] ^ (rc[rounds]<<16);
00159 a1 ^= k[1];
00160 a2 ^= k[2] ^ rc[rounds];
00161 theta(a0, a1, a2);
00162 mu(a0, a1, a2);
00163
00164 #ifndef IS_LITTLE_ENDIAN
00165 *(word32 *)out = byteReverse(a0);
00166 *(word32 *)(out+4) = byteReverse(a1);
00167 *(word32 *)(out+8) = byteReverse(a2);
00168 #else
00169 *(word32 *)out = a0;
00170 *(word32 *)(out+4) = a1;
00171 *(word32 *)(out+8) = a2;
00172 #endif
00173 }
00174
00175 NAMESPACE_END