/* tigersum - a command line utility to calculate the tiger hash from input.
Copyright (C) 2014 Michele "King_DuckZ" Santullo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
typedef unsigned long long int word64;
typedef unsigned long word32;
typedef unsigned char 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 table[4*256];
union RawAccessULL4 {
word64 ull[8];
unsigned char raw[64];
};
#define t1 (table)
#define t2 (table+256)
#define t3 (table+256*2)
#define t4 (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[(byte)(c)] ^ \
t2[(byte)(((word32)(c))>>(2*8))] ^ \
t3[(byte)((c)>>(4*8))] ^ \
t4[(byte)(((word32)((c)>>(4*8)))>>(2*8))] ; \
b += t4[(byte)(((word32)(c))>>(1*8))] ^ \
t3[(byte)(((word32)(c))>>(3*8))] ^ \
t2[(byte)(((word32)((c)>>(4*8)))>>(1*8))] ^ \
t1[(byte)(((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] = ((byte*)str)[j];
tiger_compress(((word64*)temp), res);
#else
tiger_compress(str, res);
#endif
str += 8;
}
}
void tiger_last_chunk(word64 *str, word64 length, word64 reallength, word64 res[3], byte pad)
{
const word64 i = length & 0x3f;
register word64 j;
union RawAccessULL4 temp;
#ifdef BIG_ENDIAN
for(j=0; j56)
{
for(; j<64; j++)
temp.raw[j] = 0;
tiger_compress((temp.ull), res);
j=0;
}
for(; j<56; j++)
temp.raw[j] = 0;
temp.ull[7] = reallength<<3;
tiger_compress((temp.ull), res);
}
void tiger(word64 *str, word64 length, word64 res[3], byte pad)
{
const word64 proc_length = length & ~0x3fULL;
tiger_init(res);
tiger_chunk(str, proc_length, res);
tiger_last_chunk(str + (proc_length / 8), length - proc_length, length, res, pad);
}