The Pedigree Project  0.1
spooky.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 // Spooky Hash
21 // A 128-bit noncryptographic hash, for checksums and table lookup
22 // By Bob Jenkins. Public domain.
23 // Oct 31 2010: published framework, disclaimer ShortHash isn't right
24 // Nov 7 2010: disabled ShortHash
25 // Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again
26 // April 10 2012: buffer overflow on platforms without unaligned reads
27 // July 12 2012: was passing out variables in final to in/out in short
28 // July 30 2012: I reintroduced the buffer overflow
29 // August 5 2012: SpookyV2: d = should be d += in short hash, and remove extra mix from long hash
30 
31 #include <memory.h>
32 #include "pedigree/kernel/utilities/spooky/SpookyV2.h"
33 
34 #define ALLOW_UNALIGNED_READS 1
35 
36 //
37 // short hash ... it could be used on any message,
38 // but it's used by Spooky just for short messages.
39 //
40 void SpookyHash::Short(
41  const void *message,
42  size_t length,
43  uint64 *hash1,
44  uint64 *hash2)
45 {
46  uint64 buf[2*sc_numVars];
47  union
48  {
49  const uint8 *p8;
50  uint32 *p32;
51  uint64 *p64;
52  size_t i;
53  } u;
54 
55  u.p8 = (const uint8 *)message;
56 
57  if (!ALLOW_UNALIGNED_READS && (u.i & 0x7))
58  {
59  memcpy(buf, message, length);
60  u.p64 = buf;
61  }
62 
63  size_t remainder = length%32;
64  uint64 a=*hash1;
65  uint64 b=*hash2;
66  uint64 c=sc_const;
67  uint64 d=sc_const;
68 
69  if (length > 15)
70  {
71  const uint64 *end = u.p64 + (length/32)*4;
72 
73  // handle all complete sets of 32 bytes
74  for (; u.p64 < end; u.p64 += 4)
75  {
76  c += u.p64[0];
77  d += u.p64[1];
78  ShortMix(a,b,c,d);
79  a += u.p64[2];
80  b += u.p64[3];
81  }
82 
83  //Handle the case of 16+ remaining bytes.
84  if (remainder >= 16)
85  {
86  c += u.p64[0];
87  d += u.p64[1];
88  ShortMix(a,b,c,d);
89  u.p64 += 2;
90  remainder -= 16;
91  }
92  }
93 
94  // Handle the last 0..15 bytes, and its length
95  d += ((uint64)length) << 56;
96  switch (remainder)
97  {
98  case 15:
99  d += ((uint64)u.p8[14]) << 48;
100  case 14:
101  d += ((uint64)u.p8[13]) << 40;
102  case 13:
103  d += ((uint64)u.p8[12]) << 32;
104  case 12:
105  d += u.p32[2];
106  c += u.p64[0];
107  break;
108  case 11:
109  d += ((uint64)u.p8[10]) << 16;
110  case 10:
111  d += ((uint64)u.p8[9]) << 8;
112  case 9:
113  d += (uint64)u.p8[8];
114  case 8:
115  c += u.p64[0];
116  break;
117  case 7:
118  c += ((uint64)u.p8[6]) << 48;
119  case 6:
120  c += ((uint64)u.p8[5]) << 40;
121  case 5:
122  c += ((uint64)u.p8[4]) << 32;
123  case 4:
124  c += u.p32[0];
125  break;
126  case 3:
127  c += ((uint64)u.p8[2]) << 16;
128  case 2:
129  c += ((uint64)u.p8[1]) << 8;
130  case 1:
131  c += (uint64)u.p8[0];
132  break;
133  case 0:
134  c += sc_const;
135  d += sc_const;
136  }
137  ShortEnd(a,b,c,d);
138  *hash1 = a;
139  *hash2 = b;
140 }
141 
142 
143 
144 
145 // do the whole hash in one call
146 void SpookyHash::Hash128(
147  const void *message,
148  size_t length,
149  uint64 *hash1,
150  uint64 *hash2)
151 {
152  if (length < sc_bufSize)
153  {
154  Short(message, length, hash1, hash2);
155  return;
156  }
157 
158  uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
159  uint64 buf[sc_numVars];
160  uint64 *end;
161  union
162  {
163  const uint8 *p8;
164  uint64 *p64;
165  size_t i;
166  } u;
167  size_t remainder;
168 
169  h0=h3=h6=h9 = *hash1;
170  h1=h4=h7=h10 = *hash2;
171  h2=h5=h8=h11 = sc_const;
172 
173  u.p8 = (const uint8 *)message;
174  end = u.p64 + (length/sc_blockSize)*sc_numVars;
175 
176  // handle all whole sc_blockSize blocks of bytes
177  if (ALLOW_UNALIGNED_READS || ((u.i & 0x7) == 0))
178  {
179  while (u.p64 < end)
180  {
181  Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
182  u.p64 += sc_numVars;
183  }
184  }
185  else
186  {
187  while (u.p64 < end)
188  {
189  memcpy(buf, u.p64, sc_blockSize);
190  Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
191  u.p64 += sc_numVars;
192  }
193  }
194 
195  // handle the last partial block of sc_blockSize bytes
196  remainder = (length - ((const uint8 *)end-(const uint8 *)message));
197  memcpy(buf, end, remainder);
198  memset(((uint8 *)buf)+remainder, 0, sc_blockSize-remainder);
199  ((uint8 *)buf)[sc_blockSize-1] = remainder;
200 
201  // do some final mixing
202  End(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
203  *hash1 = h0;
204  *hash2 = h1;
205 }
206 
207 
208 
209 // init spooky state
210 void SpookyHash::Init(uint64 seed1, uint64 seed2)
211 {
212  m_length = 0;
213  m_remainder = 0;
214  m_state[0] = seed1;
215  m_state[1] = seed2;
216 }
217 
218 
219 // add a message fragment to the state
220 void SpookyHash::Update(const void *message, size_t length)
221 {
222  uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
223  size_t newLength = length + m_remainder;
224  uint8 remainder;
225  union
226  {
227  const uint8 *p8;
228  uint64 *p64;
229  size_t i;
230  } u;
231  const uint64 *end;
232 
233  // Is this message fragment too short? If it is, stuff it away.
234  if (newLength < sc_bufSize)
235  {
236  memcpy(&((uint8 *)m_data)[m_remainder], message, length);
237  m_length = length + m_length;
238  m_remainder = (uint8)newLength;
239  return;
240  }
241 
242  // init the variables
243  if (m_length < sc_bufSize)
244  {
245  h0=h3=h6=h9 = m_state[0];
246  h1=h4=h7=h10 = m_state[1];
247  h2=h5=h8=h11 = sc_const;
248  }
249  else
250  {
251  h0 = m_state[0];
252  h1 = m_state[1];
253  h2 = m_state[2];
254  h3 = m_state[3];
255  h4 = m_state[4];
256  h5 = m_state[5];
257  h6 = m_state[6];
258  h7 = m_state[7];
259  h8 = m_state[8];
260  h9 = m_state[9];
261  h10 = m_state[10];
262  h11 = m_state[11];
263  }
264  m_length = length + m_length;
265 
266  // if we've got anything stuffed away, use it now
267  if (m_remainder)
268  {
269  uint8 prefix = sc_bufSize-m_remainder;
270  memcpy(&(((uint8 *)m_data)[m_remainder]), message, prefix);
271  u.p64 = m_data;
272  Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
273  Mix(&u.p64[sc_numVars], h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
274  u.p8 = ((const uint8 *)message) + prefix;
275  length -= prefix;
276  }
277  else
278  {
279  u.p8 = (const uint8 *)message;
280  }
281 
282  // handle all whole blocks of sc_blockSize bytes
283  end = u.p64 + (length/sc_blockSize)*sc_numVars;
284  remainder = (uint8)(length-((const uint8 *)end-u.p8));
285  if (ALLOW_UNALIGNED_READS || (u.i & 0x7) == 0)
286  {
287  while (u.p64 < end)
288  {
289  Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
290  u.p64 += sc_numVars;
291  }
292  }
293  else
294  {
295  while (u.p64 < end)
296  {
297  memcpy(m_data, u.p8, sc_blockSize);
298  Mix(m_data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
299  u.p64 += sc_numVars;
300  }
301  }
302 
303  // stuff away the last few bytes
304  m_remainder = remainder;
305  memcpy(m_data, end, remainder);
306 
307  // stuff away the variables
308  m_state[0] = h0;
309  m_state[1] = h1;
310  m_state[2] = h2;
311  m_state[3] = h3;
312  m_state[4] = h4;
313  m_state[5] = h5;
314  m_state[6] = h6;
315  m_state[7] = h7;
316  m_state[8] = h8;
317  m_state[9] = h9;
318  m_state[10] = h10;
319  m_state[11] = h11;
320 }
321 
322 
323 // report the hash for the concatenation of all message fragments so far
324 void SpookyHash::Final(uint64 *hash1, uint64 *hash2)
325 {
326  // init the variables
327  if (m_length < sc_bufSize)
328  {
329  *hash1 = m_state[0];
330  *hash2 = m_state[1];
331  Short( m_data, m_length, hash1, hash2);
332  return;
333  }
334 
335  const uint64 *data = (const uint64 *)m_data;
336  uint8 remainder = m_remainder;
337 
338  uint64 h0 = m_state[0];
339  uint64 h1 = m_state[1];
340  uint64 h2 = m_state[2];
341  uint64 h3 = m_state[3];
342  uint64 h4 = m_state[4];
343  uint64 h5 = m_state[5];
344  uint64 h6 = m_state[6];
345  uint64 h7 = m_state[7];
346  uint64 h8 = m_state[8];
347  uint64 h9 = m_state[9];
348  uint64 h10 = m_state[10];
349  uint64 h11 = m_state[11];
350 
351  if (remainder >= sc_blockSize)
352  {
353  // m_data can contain two blocks; handle any whole first block
354  Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
355  data += sc_numVars;
356  remainder -= sc_blockSize;
357  }
358 
359  // mix in the last partial block, and the length mod sc_blockSize
360  memset(&((uint8 *)data)[remainder], 0, (sc_blockSize-remainder));
361 
362  ((uint8 *)data)[sc_blockSize-1] = remainder;
363 
364  // do some final mixing
365  End(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
366 
367  *hash1 = h0;
368  *hash2 = h1;
369 }