1 /*
2  * Copyright (C) 2013 Andrea Mazzoleni
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*
19  * Derivative work from SpookyV2.cpp/h
20  *
21  * WARNING!!!! Note that this implementation doesn't use the short hash optimization
22  * resulting in different hashes for any length shorter than 192 bytes
23  *
24  * SpookyHash
25  * http://burtleburtle.net/bob/hash/spooky.html
26  *
27  * Exact source used as reference:
28  * http://burtleburtle.net/bob/c/SpookyV2.h
29  * http://burtleburtle.net/bob/c/SpookyV2.cpp
30  */
31 
32 // Spooky Hash
33 // A 128-bit noncryptographic hash, for checksums and table lookup
34 // By Bob Jenkins.  Public domain.
35 //   Oct 31 2010: published framework, disclaimer ShortHash isn't right
36 //   Nov 7 2010: disabled ShortHash
37 //   Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again
38 //   April 10 2012: buffer overflow on platforms without unaligned reads
39 //   July 12 2012: was passing out variables in final to in/out in short
40 //   July 30 2012: I reintroduced the buffer overflow
41 //   August 5 2012: SpookyV2: d = should be d += in short hash, and remove extra mix from long hash
42 //
43 // Up to 3 bytes/cycle for long messages.  Reasonably fast for short messages.
44 // All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit.
45 //
46 // This was developed for and tested on 64-bit x86-compatible processors.
47 // It assumes the processor is little-endian.  There is a macro
48 // controlling whether unaligned reads are allowed (by default they are).
49 // This should be an equally good hash on big-endian machines, but it will
50 // compute different results on them than on little-endian machines.
51 //
52 // Google's CityHash has similar specs to SpookyHash, and CityHash is faster
53 // on new Intel boxes.  MD4 and MD5 also have similar specs, but they are orders
54 // of magnitude slower.  CRCs are two or more times slower, but unlike
55 // SpookyHash, they have nice math for combining the CRCs of pieces to form
56 // the CRCs of wholes.  There are also cryptographic hashes, but those are even
57 // slower than MD5.
58 //
59 
60 #define Mix(data, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11) \
61 	s0 += data[0];   s2 ^= s10;  s11 ^= s0;   s0 = util_rotl64(s0, 11);   s11 += s1; \
62 	s1 += data[1];   s3 ^= s11;  s0 ^= s1;   s1 = util_rotl64(s1, 32);   s0 += s2; \
63 	s2 += data[2];   s4 ^= s0;   s1 ^= s2;   s2 = util_rotl64(s2, 43);   s1 += s3; \
64 	s3 += data[3];   s5 ^= s1;   s2 ^= s3;   s3 = util_rotl64(s3, 31);   s2 += s4; \
65 	s4 += data[4];   s6 ^= s2;   s3 ^= s4;   s4 = util_rotl64(s4, 17);   s3 += s5; \
66 	s5 += data[5];   s7 ^= s3;   s4 ^= s5;   s5 = util_rotl64(s5, 28);   s4 += s6; \
67 	s6 += data[6];   s8 ^= s4;   s5 ^= s6;   s6 = util_rotl64(s6, 39);   s5 += s7; \
68 	s7 += data[7];   s9 ^= s5;   s6 ^= s7;   s7 = util_rotl64(s7, 57);   s6 += s8; \
69 	s8 += data[8];   s10 ^= s6;   s7 ^= s8;   s8 = util_rotl64(s8, 55);   s7 += s9; \
70 	s9 += data[9];   s11 ^= s7;   s8 ^= s9;   s9 = util_rotl64(s9, 54);   s8 += s10; \
71 	s10 += data[10];  s0 ^= s8;   s9 ^= s10;  s10 = util_rotl64(s10, 22);  s9 += s11; \
72 	s11 += data[11];  s1 ^= s9;   s10 ^= s11;  s11 = util_rotl64(s11, 46);  s10 += s0;
73 
74 #define EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11) \
75 	h11 += h1;   h2 ^= h11;  h1 = util_rotl64(h1, 44); \
76 	h0 += h2;   h3 ^= h0;   h2 = util_rotl64(h2, 15); \
77 	h1 += h3;   h4 ^= h1;   h3 = util_rotl64(h3, 34); \
78 	h2 += h4;   h5 ^= h2;   h4 = util_rotl64(h4, 21); \
79 	h3 += h5;   h6 ^= h3;   h5 = util_rotl64(h5, 38); \
80 	h4 += h6;   h7 ^= h4;   h6 = util_rotl64(h6, 33); \
81 	h5 += h7;   h8 ^= h5;   h7 = util_rotl64(h7, 10); \
82 	h6 += h8;   h9 ^= h6;   h8 = util_rotl64(h8, 13); \
83 	h7 += h9;   h10 ^= h7;   h9 = util_rotl64(h9, 38); \
84 	h8 += h10;  h11 ^= h8;   h10 = util_rotl64(h10, 53); \
85 	h9 += h11;  h0 ^= h9;   h11 = util_rotl64(h11, 42); \
86 	h10 += h0;   h1 ^= h10;  h0 = util_rotl64(h0, 54);
87 
88 #define End(data, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11) \
89 	h0 += data[0];  h1 += data[1];  h2 += data[2];    h3 += data[3]; \
90 	h4 += data[4];  h5 += data[5];  h6 += data[6];    h7 += data[7]; \
91 	h8 += data[8];  h9 += data[9];  h10 += data[10];   h11 += data[11]; \
92 	EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); \
93 	EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); \
94 	EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
95 
96 // number of uint64_t's in internal state
97 #define sc_numVars 12
98 
99 // size of the internal state
100 #define sc_blockSize (sc_numVars * 8)
101 
102 //
103 // sc_const: a constant which:
104 //  * is not zero
105 //  * is odd
106 //  * is a not-very-regular mix of 1's and 0's
107 //  * does not need any other special mathematical properties
108 //
109 #define sc_const 0xdeadbeefdeadbeefLL
110 
SpookyHash128(const void * data,size_t size,const uint8_t * seed,uint8_t * digest)111 void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest)
112 {
113 	uint64_t h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11;
114 	uint64_t buf[sc_numVars];
115 	size_t nblocks;
116 	const uint64_t* blocks;
117 	const uint64_t* end;
118 	size_t size_remainder;
119 #if WORDS_BIGENDIAN
120 	unsigned i;
121 #endif
122 
123 	h9 = util_read64(seed + 0);
124 	h10 = util_read64(seed + 8);
125 
126 	h0 = h3 = h6 = h9;
127 	h1 = h4 = h7 = h10;
128 	h2 = h5 = h8 = h11 = sc_const;
129 
130 	nblocks = size / sc_blockSize;
131 	blocks = data;
132 	end = blocks + nblocks * sc_numVars;
133 
134 	/* body */
135 	while (blocks < end) {
136 #if WORDS_BIGENDIAN
137 		for (i = 0; i < sc_numVars; ++i)
138 			buf[i] = util_swap64(blocks[i]);
139 		Mix(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
140 #else
141 		Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
142 #endif
143 		blocks += sc_numVars;
144 	}
145 
146 	/* tail */
147 	size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data));
148 	memcpy(buf, end, size_remainder);
149 	memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder);
150 	((uint8_t*)buf)[sc_blockSize - 1] = size_remainder;
151 
152 	/* finalization */
153 #if WORDS_BIGENDIAN
154 	for (i = 0; i < sc_numVars; ++i)
155 		buf[i] = util_swap64(buf[i]);
156 #endif
157 	End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
158 
159 	util_write64(digest + 0, h0);
160 	util_write64(digest + 8, h1);
161 }
162 
163