/* Do not include ANY system headers here. The implementation is */ /* somehow flawed - maybe something gets overlayed by definitions */ /* in the system headers. Results will become incorrect. */ #include "config_xor.h" #if defined(HAVE_LONG_64) || defined(HAVE_LONG_LONG_64) /*@-incondefs -macroparens -macroassign -macroparams -macrostmt @*/ /*@-fixedformalarray +charindex -type -paramuse -predboolint -exportlocal@*/ /* Big endian: */ #ifdef WORDS_BIGENDIAN #define BIG_ENDIAN #endif /* Tiger: A Fast New Hash Function * * Ross Anderson and Eli Biham * * From the homepage (http://www.cs.technion.ac.il/~biham/Reports/Tiger/): * * Tiger has no usage restrictions nor patents. It can be used freely, * with the reference implementation, with other implementations or with * a modification to the reference implementation (as long as it still * implements Tiger). We only ask you to let us know about your * implementation and to cite the origin of Tiger and of the reference * implementation. * * * The authors' home pages can be found both in * http://www.cs.technion.ac.il/~biham/ and in * http://www.cl.cam.ac.uk/users/rja14/. * The authors' email addresses are biham@cs.technion.ac.il * and rja14@cl.cam.ac.uk. */ #if defined(HAVE_LONG_64) typedef unsigned long int word64; #else typedef unsigned long long int word64; #endif #if defined(HAVE_INT_32) typedef unsigned int sh_word32; #elif defined(HAVE_LONG_32) typedef unsigned long sh_word32; #elif defined(HAVE_SHORT_32) typedef unsigned short sh_word32; #else #error No 32 byte type found ! #endif typedef unsigned char sh_byte; /* Big endian: #if !(defined(__alpha)||defined(__i386__)||defined(__vax__)) #define BIG_ENDIAN #endif */ /* The following macro denotes that an optimization */ /* for Alpha is required. It is used only for */ /* optimization of time. Otherwise it does nothing. */ #ifdef __alpha #define OPTIMIZE_FOR_ALPHA #endif /* NOTE that this code is NOT FULLY OPTIMIZED for any */ /* machine. Assembly code might be much faster on some */ /* machines, especially if the code is compiled with */ /* gcc. */ /* The number of passes of the hash function. */ /* Three passes are recommended. */ /* Use four passes when you need extra security. */ /* Must be at least three. */ #define PASSES 3 extern word64 tiger_table[4*256]; #define t1 (tiger_table) #define t2 (tiger_table+256) #define t3 (tiger_table+256*2) #define t4 (tiger_table+256*3) #define save_abc \ aa = a; \ bb = b; \ cc = c; #ifdef OPTIMIZE_FOR_ALPHA /* This is the official definition of round */ #define round(a,b,c,x,mul) \ c ^= x; \ a -= t1[((c)>>(0*8))&0xFF] ^ t2[((c)>>(2*8))&0xFF] ^ \ t3[((c)>>(4*8))&0xFF] ^ t4[((c)>>(6*8))&0xFF] ; \ b += t4[((c)>>(1*8))&0xFF] ^ t3[((c)>>(3*8))&0xFF] ^ \ t2[((c)>>(5*8))&0xFF] ^ t1[((c)>>(7*8))&0xFF] ; \ b *= mul; #else /* This code works faster when compiled on 32-bit machines */ /* (but works slower on Alpha) */ #define round(a,b,c,x,mul) \ c ^= x; \ a -= t1[(sh_byte)(c)] ^ \ t2[(sh_byte)(((sh_word32)(c))>>(2*8))] ^ \ t3[(sh_byte)((c)>>(4*8))] ^ \ t4[(sh_byte)(((sh_word32)((c)>>(4*8)))>>(2*8))] ; \ b += t4[(sh_byte)(((sh_word32)(c))>>(1*8))] ^ \ t3[(sh_byte)(((sh_word32)(c))>>(3*8))] ^ \ t2[(sh_byte)(((sh_word32)((c)>>(4*8)))>>(1*8))] ^ \ t1[(sh_byte)(((sh_word32)((c)>>(4*8)))>>(3*8))]; \ b *= mul; #endif #define pass(a,b,c,mul) \ round(a,b,c,x0,mul) \ round(b,c,a,x1,mul) \ round(c,a,b,x2,mul) \ round(a,b,c,x3,mul) \ round(b,c,a,x4,mul) \ round(c,a,b,x5,mul) \ round(a,b,c,x6,mul) \ round(b,c,a,x7,mul) #define key_schedule \ x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5LL; \ x1 ^= x0; \ x2 += x1; \ x3 -= x2 ^ ((~x1)<<19); \ x4 ^= x3; \ x5 += x4; \ x6 -= x5 ^ ((~x4)>>23); \ x7 ^= x6; \ x0 += x7; \ x1 -= x0 ^ ((~x7)<<19); \ x2 ^= x1; \ x3 += x2; \ x4 -= x3 ^ ((~x2)>>23); \ x5 ^= x4; \ x6 += x5; \ x7 -= x6 ^ 0x0123456789ABCDEFLL; #define feedforward \ a ^= aa; \ b -= bb; \ c += cc; #ifdef OPTIMIZE_FOR_ALPHA /* The loop is unrolled: works better on Alpha */ #define compress \ save_abc \ pass(a,b,c,5) \ key_schedule \ pass(c,a,b,7) \ key_schedule \ pass(b,c,a,9) \ for(pass_no=3; pass_no=64; i-=64) { #ifdef BIG_ENDIAN for(j=0; j<64; j++) temp[j^7] = ((sh_byte*)str)[j]; tiger_compress(((word64*)temp), res); #else tiger_compress(str, res); #endif str += 8; } } void tiger(word64 *str, word64 length, word64 res[3]) { register word64 i; register word64 j = 0; unsigned char temp[64]; /* res[0]=0x0123456789ABCDEFLL; res[1]=0xFEDCBA9876543210LL; res[2]=0xF096A5B4C3B2E187LL; */ for(i=length; i>=64; i-=64) { #ifdef BIG_ENDIAN for(j=0; j<64; j++) temp[j^7] = ((sh_byte*)str)[j]; tiger_compress(((word64*)temp), res); #else tiger_compress(str, res); #endif str += 8; } #ifdef BIG_ENDIAN for(j=0; j56) { for(; j<64; j++) temp[j] = 0; tiger_compress(((word64*)temp), res); j=0; } for(; j<56; j++) temp[j] = 0; ((word64*)(&(temp[56])))[0] = ((word64)length)<<3; tiger_compress(((word64*)temp), res); } #else void dummy_1_64 (int a) { (void) a; return; } #endif