Crypto++
|
00001 // tiger.cpp - written and placed in the public domain by Wei Dai 00002 00003 #include "pch.h" 00004 #include "tiger.h" 00005 #include "misc.h" 00006 #include "cpu.h" 00007 00008 NAMESPACE_BEGIN(CryptoPP) 00009 00010 void Tiger::InitState(HashWordType *state) 00011 { 00012 state[0] = W64LIT(0x0123456789ABCDEF); 00013 state[1] = W64LIT(0xFEDCBA9876543210); 00014 state[2] = W64LIT(0xF096A5B4C3B2E187); 00015 } 00016 00017 void Tiger::TruncatedFinal(byte *hash, size_t size) 00018 { 00019 ThrowIfInvalidTruncatedSize(size); 00020 00021 PadLastBlock(56, 0x01); 00022 CorrectEndianess(m_data, m_data, 56); 00023 00024 m_data[7] = GetBitCountLo(); 00025 00026 Transform(m_state, m_data); 00027 CorrectEndianess(m_state, m_state, DigestSize()); 00028 memcpy(hash, m_state, size); 00029 00030 Restart(); // reinit for next use 00031 } 00032 00033 void Tiger::Transform (word64 *digest, const word64 *X) 00034 { 00035 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 00036 if (HasSSE2()) 00037 { 00038 #ifdef __GNUC__ 00039 __asm__ __volatile__ 00040 ( 00041 ".intel_syntax noprefix;" 00042 AS1( push ebx) 00043 #else 00044 #if _MSC_VER < 1300 00045 const word64 *t = table; 00046 AS2( mov edx, t) 00047 #else 00048 AS2( lea edx, [table]) 00049 #endif 00050 AS2( mov eax, digest) 00051 AS2( mov esi, X) 00052 #endif 00053 AS2( movq mm0, [eax]) 00054 AS2( movq mm1, [eax+1*8]) 00055 AS2( movq mm5, mm1) 00056 AS2( movq mm2, [eax+2*8]) 00057 AS2( movq mm7, [edx+4*2048+0*8]) 00058 AS2( movq mm6, [edx+4*2048+1*8]) 00059 AS2( mov ecx, esp) 00060 AS2( and esp, 0xfffffff0) 00061 AS2( sub esp, 8*8) 00062 AS1( push ecx) 00063 00064 #define SSE2_round(a,b,c,x,mul) \ 00065 AS2( pxor c, [x])\ 00066 AS2( movd ecx, c)\ 00067 AS2( movzx edi, cl)\ 00068 AS2( movq mm3, [edx+0*2048+edi*8])\ 00069 AS2( movzx edi, ch)\ 00070 AS2( movq mm4, [edx+3*2048+edi*8])\ 00071 AS2( shr ecx, 16)\ 00072 AS2( movzx edi, cl)\ 00073 AS2( pxor mm3, [edx+1*2048+edi*8])\ 00074 AS2( movzx edi, ch)\ 00075 AS2( pxor mm4, [edx+2*2048+edi*8])\ 00076 AS3( pextrw ecx, c, 2)\ 00077 AS2( movzx edi, cl)\ 00078 AS2( pxor mm3, [edx+2*2048+edi*8])\ 00079 AS2( movzx edi, ch)\ 00080 AS2( pxor mm4, [edx+1*2048+edi*8])\ 00081 AS3( pextrw ecx, c, 3)\ 00082 AS2( movzx edi, cl)\ 00083 AS2( pxor mm3, [edx+3*2048+edi*8])\ 00084 AS2( psubq a, mm3)\ 00085 AS2( movzx edi, ch)\ 00086 AS2( pxor mm4, [edx+0*2048+edi*8])\ 00087 AS2( paddq b, mm4)\ 00088 SSE2_mul_##mul(b) 00089 00090 #define SSE2_mul_5(b) \ 00091 AS2( movq mm3, b)\ 00092 AS2( psllq b, 2)\ 00093 AS2( paddq b, mm3) 00094 00095 #define SSE2_mul_7(b) \ 00096 AS2( movq mm3, b)\ 00097 AS2( psllq b, 3)\ 00098 AS2( psubq b, mm3) 00099 00100 #define SSE2_mul_9(b) \ 00101 AS2( movq mm3, b)\ 00102 AS2( psllq b, 3)\ 00103 AS2( paddq b, mm3) 00104 00105 #define label2_5 1 00106 #define label2_7 2 00107 #define label2_9 3 00108 00109 #define SSE2_pass(A,B,C,mul,X) \ 00110 AS2( xor ebx, ebx)\ 00111 ASL(mul)\ 00112 SSE2_round(A,B,C,X+0*8+ebx,mul)\ 00113 SSE2_round(B,C,A,X+1*8+ebx,mul)\ 00114 AS2( cmp ebx, 6*8)\ 00115 ASJ( je, label2_##mul, f)\ 00116 SSE2_round(C,A,B,X+2*8+ebx,mul)\ 00117 AS2( add ebx, 3*8)\ 00118 ASJ( jmp, mul, b)\ 00119 ASL(label2_##mul) 00120 00121 #define SSE2_key_schedule(Y,X) \ 00122 AS2( movq mm3, [X+7*8])\ 00123 AS2( pxor mm3, mm6)\ 00124 AS2( movq mm4, [X+0*8])\ 00125 AS2( psubq mm4, mm3)\ 00126 AS2( movq [Y+0*8], mm4)\ 00127 AS2( pxor mm4, [X+1*8])\ 00128 AS2( movq mm3, mm4)\ 00129 AS2( movq [Y+1*8], mm4)\ 00130 AS2( paddq mm4, [X+2*8])\ 00131 AS2( pxor mm3, mm7)\ 00132 AS2( psllq mm3, 19)\ 00133 AS2( movq [Y+2*8], mm4)\ 00134 AS2( pxor mm3, mm4)\ 00135 AS2( movq mm4, [X+3*8])\ 00136 AS2( psubq mm4, mm3)\ 00137 AS2( movq [Y+3*8], mm4)\ 00138 AS2( pxor mm4, [X+4*8])\ 00139 AS2( movq mm3, mm4)\ 00140 AS2( movq [Y+4*8], mm4)\ 00141 AS2( paddq mm4, [X+5*8])\ 00142 AS2( pxor mm3, mm7)\ 00143 AS2( psrlq mm3, 23)\ 00144 AS2( movq [Y+5*8], mm4)\ 00145 AS2( pxor mm3, mm4)\ 00146 AS2( movq mm4, [X+6*8])\ 00147 AS2( psubq mm4, mm3)\ 00148 AS2( movq [Y+6*8], mm4)\ 00149 AS2( pxor mm4, [X+7*8])\ 00150 AS2( movq mm3, mm4)\ 00151 AS2( movq [Y+7*8], mm4)\ 00152 AS2( paddq mm4, [Y+0*8])\ 00153 AS2( pxor mm3, mm7)\ 00154 AS2( psllq mm3, 19)\ 00155 AS2( movq [Y+0*8], mm4)\ 00156 AS2( pxor mm3, mm4)\ 00157 AS2( movq mm4, [Y+1*8])\ 00158 AS2( psubq mm4, mm3)\ 00159 AS2( movq [Y+1*8], mm4)\ 00160 AS2( pxor mm4, [Y+2*8])\ 00161 AS2( movq mm3, mm4)\ 00162 AS2( movq [Y+2*8], mm4)\ 00163 AS2( paddq mm4, [Y+3*8])\ 00164 AS2( pxor mm3, mm7)\ 00165 AS2( psrlq mm3, 23)\ 00166 AS2( movq [Y+3*8], mm4)\ 00167 AS2( pxor mm3, mm4)\ 00168 AS2( movq mm4, [Y+4*8])\ 00169 AS2( psubq mm4, mm3)\ 00170 AS2( movq [Y+4*8], mm4)\ 00171 AS2( pxor mm4, [Y+5*8])\ 00172 AS2( movq [Y+5*8], mm4)\ 00173 AS2( paddq mm4, [Y+6*8])\ 00174 AS2( movq [Y+6*8], mm4)\ 00175 AS2( pxor mm4, [edx+4*2048+2*8])\ 00176 AS2( movq mm3, [Y+7*8])\ 00177 AS2( psubq mm3, mm4)\ 00178 AS2( movq [Y+7*8], mm3) 00179 00180 SSE2_pass(mm0, mm1, mm2, 5, esi) 00181 SSE2_key_schedule(esp+4, esi) 00182 SSE2_pass(mm2, mm0, mm1, 7, esp+4) 00183 SSE2_key_schedule(esp+4, esp+4) 00184 SSE2_pass(mm1, mm2, mm0, 9, esp+4) 00185 00186 AS2( pxor mm0, [eax+0*8]) 00187 AS2( movq [eax+0*8], mm0) 00188 AS2( psubq mm1, mm5) 00189 AS2( movq [eax+1*8], mm1) 00190 AS2( paddq mm2, [eax+2*8]) 00191 AS2( movq [eax+2*8], mm2) 00192 00193 AS1( pop esp) 00194 AS1( emms) 00195 #ifdef __GNUC__ 00196 AS1( pop ebx) 00197 ".att_syntax prefix;" 00198 : 00199 : "a" (digest), "S" (X), "d" (table) 00200 : "%ecx", "%edi", "memory", "cc" 00201 ); 00202 #endif 00203 } 00204 else 00205 #endif 00206 { 00207 word64 a = digest[0]; 00208 word64 b = digest[1]; 00209 word64 c = digest[2]; 00210 word64 Y[8]; 00211 00212 #define t1 (table) 00213 #define t2 (table+256) 00214 #define t3 (table+256*2) 00215 #define t4 (table+256*3) 00216 00217 #define round(a,b,c,x,mul) \ 00218 c ^= x; \ 00219 a -= t1[GETBYTE(c,0)] ^ t2[GETBYTE(c,2)] ^ t3[GETBYTE(c,4)] ^ t4[GETBYTE(c,6)]; \ 00220 b += t4[GETBYTE(c,1)] ^ t3[GETBYTE(c,3)] ^ t2[GETBYTE(c,5)] ^ t1[GETBYTE(c,7)]; \ 00221 b *= mul 00222 00223 #define pass(a,b,c,mul,X) {\ 00224 int i=0;\ 00225 while (true)\ 00226 {\ 00227 round(a,b,c,X[i+0],mul); \ 00228 round(b,c,a,X[i+1],mul); \ 00229 if (i==6)\ 00230 break;\ 00231 round(c,a,b,X[i+2],mul); \ 00232 i+=3;\ 00233 }} 00234 00235 #define key_schedule(Y,X) \ 00236 Y[0] = X[0] - (X[7]^W64LIT(0xA5A5A5A5A5A5A5A5)); \ 00237 Y[1] = X[1] ^ Y[0]; \ 00238 Y[2] = X[2] + Y[1]; \ 00239 Y[3] = X[3] - (Y[2] ^ ((~Y[1])<<19)); \ 00240 Y[4] = X[4] ^ Y[3]; \ 00241 Y[5] = X[5] + Y[4]; \ 00242 Y[6] = X[6] - (Y[5] ^ ((~Y[4])>>23)); \ 00243 Y[7] = X[7] ^ Y[6]; \ 00244 Y[0] += Y[7]; \ 00245 Y[1] -= Y[0] ^ ((~Y[7])<<19); \ 00246 Y[2] ^= Y[1]; \ 00247 Y[3] += Y[2]; \ 00248 Y[4] -= Y[3] ^ ((~Y[2])>>23); \ 00249 Y[5] ^= Y[4]; \ 00250 Y[6] += Y[5]; \ 00251 Y[7] -= Y[6] ^ W64LIT(0x0123456789ABCDEF) 00252 00253 pass(a,b,c,5,X); 00254 key_schedule(Y,X); 00255 pass(c,a,b,7,Y); 00256 key_schedule(Y,Y); 00257 pass(b,c,a,9,Y); 00258 00259 digest[0] = a ^ digest[0]; 00260 digest[1] = b - digest[1]; 00261 digest[2] = c + digest[2]; 00262 } 00263 } 00264 00265 NAMESPACE_END