/* 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) /* 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_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: */ #ifdef WORDS_BIGENDIAN #define BIG_ENDIAN #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 sh_word32 tiger_table[4*256][2]; #define t1 (tiger_table) #define t2 (tiger_table+256) #define t3 (tiger_table+256*2) #define t4 (tiger_table+256*3) #define sh_sub64(s0, s1, p0, p1) \ temps0 = (p0); \ tcarry = s0 < temps0; \ s0 -= temps0; \ s1 -= (p1) + tcarry; #define sh_add64(s0, s1, p0, p1) \ temps0 = (p0); \ s0 += temps0; \ tcarry = s0 < temps0; \ s1 += (p1) + tcarry; #define sh_xor64(s0, s1, p0, p1) \ s0 ^= (p0); \ s1 ^= (p1); #define sh_mul5(s0, s1) \ tempt0 = s0<<2; \ tempt1 = (s1<<2)|(s0>>30); \ sh_add64(s0, s1, tempt0, tempt1); #define sh_mul7(s0, s1) \ tempt0 = s0<<3; \ tempt1 = (s1<<3)|(s0>>29); \ sh_sub64(tempt0, tempt1, s0, s1); \ s0 = tempt0; \ s1 = tempt1; #define sh_mul9(s0, s1) \ tempt0 = s0<<3; \ tempt1 = (s1<<3)|(s0>>29); \ sh_add64(s0, s1, tempt0, tempt1); #define sh_save_abc \ aa0 = a0; \ aa1 = a1; \ bb0 = b0; \ bb1 = b1; \ cc0 = c0; \ cc1 = c1; #define sh_round(a0,a1,b0,b1,c0,c1,x0,x1,mul) \ sh_xor64(c0, c1, x0, x1); \ temp0 = t1[((c0)>>(0*8))&0xFF][0] ; \ temp1 = t1[((c0)>>(0*8))&0xFF][1] ; \ temp0 ^= t2[((c0)>>(2*8))&0xFF][0] ; \ temp1 ^= t2[((c0)>>(2*8))&0xFF][1] ; \ temp0 ^= t3[((c1)>>(0*8))&0xFF][0] ; \ temp1 ^= t3[((c1)>>(0*8))&0xFF][1] ; \ temp0 ^= t4[((c1)>>(2*8))&0xFF][0] ; \ temp1 ^= t4[((c1)>>(2*8))&0xFF][1] ; \ sh_sub64(a0, a1, temp0, temp1); \ temp0 = t4[((c0)>>(1*8))&0xFF][0] ; \ temp1 = t4[((c0)>>(1*8))&0xFF][1] ; \ temp0 ^= t3[((c0)>>(3*8))&0xFF][0] ; \ temp1 ^= t3[((c0)>>(3*8))&0xFF][1] ; \ temp0 ^= t2[((c1)>>(1*8))&0xFF][0] ; \ temp1 ^= t2[((c1)>>(1*8))&0xFF][1] ; \ temp0 ^= t1[((c1)>>(3*8))&0xFF][0] ; \ temp1 ^= t1[((c1)>>(3*8))&0xFF][1] ; \ sh_add64(b0, b1, temp0, temp1); \ if((mul)==5) \ {sh_mul5(b0, b1);} \ else \ if((mul)==7) \ {sh_mul7(b0, b1);} \ else \ {sh_mul9(b0, b1)}; #define sh_pass(a0,a1,b0,b1,c0,c1,mul) \ sh_round(a0,a1,b0,b1,c0,c1,x00,x01,mul); \ sh_round(b0,b1,c0,c1,a0,a1,x10,x11,mul); \ sh_round(c0,c1,a0,a1,b0,b1,x20,x21,mul); \ sh_round(a0,a1,b0,b1,c0,c1,x30,x31,mul); \ sh_round(b0,b1,c0,c1,a0,a1,x40,x41,mul); \ sh_round(c0,c1,a0,a1,b0,b1,x50,x51,mul); \ sh_round(a0,a1,b0,b1,c0,c1,x60,x61,mul); \ sh_round(b0,b1,c0,c1,a0,a1,x70,x71,mul); #define sh_key_schedule \ sh_sub64(x00, x01, x70^0xA5A5A5A5, x71^0xA5A5A5A5); \ sh_xor64(x10, x11, x00, x01); \ sh_add64(x20, x21, x10, x11); \ sh_sub64(x30, x31, x20^((~x10)<<19), ~x21^(((x11)<<19)|((x10)>>13))); \ sh_xor64(x40, x41, x30, x31); \ sh_add64(x50, x51, x40, x41); \ sh_sub64(x60, x61, ~x50^(((x40)>>23)|((x41)<<9)), x51^((~x41)>>23)); \ sh_xor64(x70, x71, x60, x61); \ sh_add64(x00, x01, x70, x71); \ sh_sub64(x10, x11, x00^((~x70)<<19), ~x01^(((x71)<<19)|((x70)>>13))); \ sh_xor64(x20, x21, x10, x11); \ sh_add64(x30, x31, x20, x21); \ sh_sub64(x40, x41, ~x30^(((x20)>>23)|((x21)<<9)), x31^((~x21)>>23)); \ sh_xor64(x50, x51, x40, x41); \ sh_add64(x60, x61, x50, x51); \ sh_sub64(x70, x71, x60^0x89ABCDEF, x61^0x01234567); #define sh_feedforward \ sh_xor64(a0, a1, aa0, aa1); \ sh_sub64(b0, b1, bb0, bb1); \ sh_add64(c0, c1, cc0, cc1); #ifdef UNROLL_COMPRESS #define sh_compress \ sh_save_abc \ sh_pass(a0,a1,b0,b1,c0,c1,5); \ sh_key_schedule; \ sh_pass(c0,c1,a0,a1,b0,b1,7); \ sh_key_schedule; \ sh_pass(b0,b1,c0,c1,a0,a1,9); \ for(pass_no=3; pass_no=64; i-=64) { #ifdef BIG_ENDIAN for(j=0; j<64; j++) temp[j^3] = ((sh_byte*)str)[j]; tiger_compress(((sh_word32*)temp), res); #else tiger_compress(str, res); #endif str += 16; } } void tiger(sh_word32 *str, sh_word32 length, sh_word32 res[6]) { register sh_word32 i, j; sh_byte temp[64]; for(i=length; i>=64; i-=64) { #ifdef BIG_ENDIAN for(j=0; j<64; j++) temp[j^3] = ((sh_byte*)str)[j]; tiger_compress(((sh_word32*)temp), res); #else tiger_compress(str, res); #endif str += 16; } #ifdef BIG_ENDIAN for(j=0; j56) { for(; j<64; j++) temp[j] = 0; tiger_compress(((sh_word32*)temp), res); j=0; } for(; j<56; j++) temp[j] = 0; ((sh_word32*)(&(temp[56])))[0] = ((sh_word32)length)<<3; ((sh_word32*)(&(temp[56])))[1] = 0; tiger_compress(((sh_word32*)temp), res); } #else void dummy_1 (int a) { (void) a; return; } #endif