PageRenderTime 236ms CodeModel.GetById 60ms app.highlight 105ms RepoModel.GetById 66ms app.codeStats 0ms

/thirdparty/liblastfm2/src/fingerprint/Sha256.cpp

http://github.com/tomahawk-player/tomahawk
C++ | 480 lines | 367 code | 76 blank | 37 comment | 41 complexity | db89fdfafce54100e04eefc9e69d9804 MD5 | raw file
  1/*-
  2 * Copyright (c) 2001-2003 Allan Saddi <allan@saddi.com>
  3 * All rights reserved.
  4 *
  5 * Redistribution and use in source and binary forms, with or without
  6 * modification, are permitted provided that the following conditions
  7 * are met:
  8 * 1. Redistributions of source code must retain the above copyright
  9 *    notice, this list of conditions and the following disclaimer.
 10 * 2. Redistributions in binary form must reproduce the above copyright
 11 *    notice, this list of conditions and the following disclaimer in the
 12 *    documentation and/or other materials provided with the distribution.
 13 *
 14 * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS CONTRIBUTORS ``AS IS''
 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 17 * ARE DISCLAIMED.  IN NO EVENT SHALL ALLAN SADDI OR HIS CONTRIBUTORS BE
 18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 24 * POSSIBILITY OF SUCH DAMAGE.
 25 *
 26 * $Id: sha256.c 680 2003-07-25 21:57:49Z asaddi $
 27 */
 28
 29/*
 30 * Define WORDS_BIGENDIAN if compiling on a big-endian architecture.
 31 *
 32 * Define SHA256_TEST to test the implementation using the NIST's
 33 * sample messages. The output should be:
 34 *
 35 *   ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad
 36 *   248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
 37 *   cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0
 38 */
 39
 40#ifdef HAVE_CONFIG_H
 41#include <config.h>
 42#endif /* HAVE_CONFIG_H */
 43
 44#if HAVE_INTTYPES_H
 45# include <inttypes.h>
 46#else
 47# if HAVE_STDINT_H
 48#  include <stdint.h>
 49# endif
 50#endif
 51
 52#include <string.h>
 53
 54#include "Sha256.h"
 55
 56#ifndef lint
 57static const char rcsid[] =
 58    "$Id: sha256.c 680 2003-07-25 21:57:49Z asaddi $";
 59#endif /* !lint */
 60
 61#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
 62#define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
 63
 64#define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
 65#define Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
 66#define SIGMA0(x) (ROTR((x), 2) ^ ROTR((x), 13) ^ ROTR((x), 22))
 67#define SIGMA1(x) (ROTR((x), 6) ^ ROTR((x), 11) ^ ROTR((x), 25))
 68#define sigma0(x) (ROTR((x), 7) ^ ROTR((x), 18) ^ ((x) >> 3))
 69#define sigma1(x) (ROTR((x), 17) ^ ROTR((x), 19) ^ ((x) >> 10))
 70
 71#define DO_ROUND() { \
 72  t1 = h + SIGMA1(e) + Ch(e, f, g) + *(Kp++) + *(W++); \
 73  t2 = SIGMA0(a) + Maj(a, b, c); \
 74  h = g; \
 75  g = f; \
 76  f = e; \
 77  e = d + t1; \
 78  d = c; \
 79  c = b; \
 80  b = a; \
 81  a = t1 + t2; \
 82}
 83
 84static const uint32_t K[64] = {
 85  0x428a2f98L, 0x71374491L, 0xb5c0fbcfL, 0xe9b5dba5L,
 86  0x3956c25bL, 0x59f111f1L, 0x923f82a4L, 0xab1c5ed5L,
 87  0xd807aa98L, 0x12835b01L, 0x243185beL, 0x550c7dc3L,
 88  0x72be5d74L, 0x80deb1feL, 0x9bdc06a7L, 0xc19bf174L,
 89  0xe49b69c1L, 0xefbe4786L, 0x0fc19dc6L, 0x240ca1ccL,
 90  0x2de92c6fL, 0x4a7484aaL, 0x5cb0a9dcL, 0x76f988daL,
 91  0x983e5152L, 0xa831c66dL, 0xb00327c8L, 0xbf597fc7L,
 92  0xc6e00bf3L, 0xd5a79147L, 0x06ca6351L, 0x14292967L,
 93  0x27b70a85L, 0x2e1b2138L, 0x4d2c6dfcL, 0x53380d13L,
 94  0x650a7354L, 0x766a0abbL, 0x81c2c92eL, 0x92722c85L,
 95  0xa2bfe8a1L, 0xa81a664bL, 0xc24b8b70L, 0xc76c51a3L,
 96  0xd192e819L, 0xd6990624L, 0xf40e3585L, 0x106aa070L,
 97  0x19a4c116L, 0x1e376c08L, 0x2748774cL, 0x34b0bcb5L,
 98  0x391c0cb3L, 0x4ed8aa4aL, 0x5b9cca4fL, 0x682e6ff3L,
 99  0x748f82eeL, 0x78a5636fL, 0x84c87814L, 0x8cc70208L,
100  0x90befffaL, 0xa4506cebL, 0xbef9a3f7L, 0xc67178f2L
101};
102
103#ifndef RUNTIME_ENDIAN
104
105#ifdef WORDS_BIGENDIAN
106
107#define BYTESWAP(x) (x)
108#define BYTESWAP64(x) (x)
109
110#else /* WORDS_BIGENDIAN */
111
112#define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \
113             (ROTL((x), 8) & 0x00ff00ffL))
114#define BYTESWAP64(x) _byteswap64(x)
115
116static inline uint64_t _byteswap64(uint64_t x)
117{
118  uint32_t a = x >> 32;
119  uint32_t b = (uint32_t) x;
120  return ((uint64_t) BYTESWAP(b) << 32) | (uint64_t) BYTESWAP(a);
121}
122
123#endif /* WORDS_BIGENDIAN */
124
125#else /* !RUNTIME_ENDIAN */
126
127#define BYTESWAP(x) _byteswap(sc->littleEndian, x)
128#define BYTESWAP64(x) _byteswap64(sc->littleEndian, x)
129
130#define _BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \
131              (ROTL((x), 8) & 0x00ff00ffL))
132#define _BYTESWAP64(x) __byteswap64(x)
133
134static inline uint64_t __byteswap64(uint64_t x)
135{
136  uint32_t a = x >> 32;
137  uint32_t b = (uint32_t) x;
138  return ((uint64_t) _BYTESWAP(b) << 32) | (uint64_t) _BYTESWAP(a);
139}
140
141static inline uint32_t _byteswap(int littleEndian, uint32_t x)
142{
143  if (!littleEndian)
144    return x;
145  else
146    return _BYTESWAP(x);
147}
148
149static inline uint64_t _byteswap64(int littleEndian, uint64_t x)
150{
151  if (!littleEndian)
152    return x;
153  else
154    return _BYTESWAP64(x);
155}
156
157static inline void setEndian(int *littleEndianp)
158{
159  union {
160    uint32_t w;
161    uint8_t b[4];
162  } endian;
163
164  endian.w = 1L;
165  *littleEndianp = endian.b[0] != 0;
166}
167
168#endif /* !RUNTIME_ENDIAN */
169
170static const uint8_t padding[64] = {
171  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
179};
180
181void
182SHA256Init (SHA256Context *sc)
183{
184#ifdef RUNTIME_ENDIAN
185  setEndian (&sc->littleEndian);
186#endif /* RUNTIME_ENDIAN */
187
188  sc->totalLength = 0LL;
189  sc->hash[0] = 0x6a09e667L;
190  sc->hash[1] = 0xbb67ae85L;
191  sc->hash[2] = 0x3c6ef372L;
192  sc->hash[3] = 0xa54ff53aL;
193  sc->hash[4] = 0x510e527fL;
194  sc->hash[5] = 0x9b05688cL;
195  sc->hash[6] = 0x1f83d9abL;
196  sc->hash[7] = 0x5be0cd19L;
197  sc->bufferLength = 0L;
198}
199
200static void
201burnStack (int size)
202{
203  char buf[128];
204
205  memset (buf, 0, sizeof (buf));
206  size -= sizeof (buf);
207  if (size > 0)
208    burnStack (size);
209}
210
211static void
212SHA256Guts (SHA256Context *sc, const uint32_t *cbuf)
213{
214  uint32_t buf[64];
215  uint32_t *W, *W2, *W7, *W15, *W16;
216  uint32_t a, b, c, d, e, f, g, h;
217  uint32_t t1, t2;
218  const uint32_t *Kp;
219  int i;
220
221  W = buf;
222
223  for (i = 15; i >= 0; i--) {
224    *(W++) = BYTESWAP(*cbuf);
225    cbuf++;
226  }
227
228  W16 = &buf[0];
229  W15 = &buf[1];
230  W7 = &buf[9];
231  W2 = &buf[14];
232
233  for (i = 47; i >= 0; i--) {
234    *(W++) = sigma1(*W2) + *(W7++) + sigma0(*W15) + *(W16++);
235    W2++;
236    W15++;
237  }
238
239  a = sc->hash[0];
240  b = sc->hash[1];
241  c = sc->hash[2];
242  d = sc->hash[3];
243  e = sc->hash[4];
244  f = sc->hash[5];
245  g = sc->hash[6];
246  h = sc->hash[7];
247
248  Kp = K;
249  W = buf;
250
251#ifndef SHA256_UNROLL
252#define SHA256_UNROLL 1
253#endif /* !SHA256_UNROLL */
254
255#if SHA256_UNROLL == 1
256  for (i = 63; i >= 0; i--)
257    DO_ROUND();
258#elif SHA256_UNROLL == 2
259  for (i = 31; i >= 0; i--) {
260    DO_ROUND(); DO_ROUND();
261  }
262#elif SHA256_UNROLL == 4
263  for (i = 15; i >= 0; i--) {
264    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
265  }
266#elif SHA256_UNROLL == 8
267  for (i = 7; i >= 0; i--) {
268    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
269    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
270  }
271#elif SHA256_UNROLL == 16
272  for (i = 3; i >= 0; i--) {
273    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
274    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
275    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
276    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
277  }
278#elif SHA256_UNROLL == 32
279  for (i = 1; i >= 0; i--) {
280    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
281    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
282    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
283    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
284    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
285    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
286    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
287    DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
288  }
289#elif SHA256_UNROLL == 64
290  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
291  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
292  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
293  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
294  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
295  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
296  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
297  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
298  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
299  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
300  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
301  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
302  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
303  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
304  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
305  DO_ROUND(); DO_ROUND(); DO_ROUND(); DO_ROUND();
306#else
307#error "SHA256_UNROLL must be 1, 2, 4, 8, 16, 32, or 64!"
308#endif
309
310  sc->hash[0] += a;
311  sc->hash[1] += b;
312  sc->hash[2] += c;
313  sc->hash[3] += d;
314  sc->hash[4] += e;
315  sc->hash[5] += f;
316  sc->hash[6] += g;
317  sc->hash[7] += h;
318}
319
320void
321SHA256Update (SHA256Context *sc, const void *vdata, uint32_t len)
322{
323  const uint8_t *data = (const uint8_t*)vdata;
324  uint32_t bufferBytesLeft;
325  uint32_t bytesToCopy;
326  int needBurn = 0;
327
328#ifdef SHA256_FAST_COPY
329  if (sc->bufferLength) {
330    bufferBytesLeft = 64L - sc->bufferLength;
331
332    bytesToCopy = bufferBytesLeft;
333    if (bytesToCopy > len)
334      bytesToCopy = len;
335
336    memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
337
338    sc->totalLength += bytesToCopy * 8L;
339
340    sc->bufferLength += bytesToCopy;
341    data += bytesToCopy;
342    len -= bytesToCopy;
343
344    if (sc->bufferLength == 64L) {
345      SHA256Guts (sc, sc->buffer.words);
346      needBurn = 1;
347      sc->bufferLength = 0L;
348    }
349  }
350
351  while (len > 63L) {
352    sc->totalLength += 512L;
353
354    SHA256Guts (sc, data);
355    needBurn = 1;
356
357    data += 64L;
358    len -= 64L;
359  }
360
361  if (len) {
362    memcpy (&sc->buffer.bytes[sc->bufferLength], data, len);
363
364    sc->totalLength += len * 8L;
365
366    sc->bufferLength += len;
367  }
368#else /* SHA256_FAST_COPY */
369  while (len) {
370    bufferBytesLeft = 64L - sc->bufferLength;
371
372    bytesToCopy = bufferBytesLeft;
373    if (bytesToCopy > len)
374      bytesToCopy = len;
375
376    memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
377
378    sc->totalLength += bytesToCopy * 8L;
379
380    sc->bufferLength += bytesToCopy;
381    data += bytesToCopy;
382    len -= bytesToCopy;
383
384    if (sc->bufferLength == 64L) {
385      SHA256Guts (sc, sc->buffer.words);
386      needBurn = 1;
387      sc->bufferLength = 0L;
388    }
389  }
390#endif /* SHA256_FAST_COPY */
391
392  if (needBurn)
393    burnStack (sizeof (uint32_t[74]) + sizeof (uint32_t *[6]) + sizeof (int));
394}
395
396void
397SHA256Final (SHA256Context *sc, uint8_t hash[SHA256_HASH_SIZE])
398{
399  uint32_t bytesToPad;
400  uint64_t lengthPad;
401  int i;
402
403  bytesToPad = 120L - sc->bufferLength;
404  if (bytesToPad > 64L)
405    bytesToPad -= 64L;
406
407  lengthPad = BYTESWAP64(sc->totalLength);
408
409  SHA256Update (sc, padding, bytesToPad);
410  SHA256Update (sc, &lengthPad, 8L);
411
412  if (hash) {
413    for (i = 0; i < SHA256_HASH_WORDS; i++) {
414#ifdef SHA256_FAST_COPY
415      *((uint32_t *) hash) = BYTESWAP(sc->hash[i]);
416#else /* SHA256_FAST_COPY */
417      hash[0] = (uint8_t) (sc->hash[i] >> 24);
418      hash[1] = (uint8_t) (sc->hash[i] >> 16);
419      hash[2] = (uint8_t) (sc->hash[i] >> 8);
420      hash[3] = (uint8_t) sc->hash[i];
421#endif /* SHA256_FAST_COPY */
422      hash += 4;
423    }
424  }
425}
426
427#ifdef SHA256_TEST
428
429#include <stdio.h>
430#include <stdlib.h>
431
432int
433main (int argc, char *argv[])
434{
435  SHA256Context foo;
436  uint8_t hash[SHA256_HASH_SIZE];
437  char buf[1000];
438  int i;
439
440  SHA256Init (&foo);
441  SHA256Update (&foo, "abc", 3);
442  SHA256Final (&foo, hash);
443
444  for (i = 0; i < SHA256_HASH_SIZE;) {
445    printf ("%02x", hash[i++]);
446    if (!(i % 4))
447      printf (" ");
448  }
449  printf ("\n");
450
451  SHA256Init (&foo);
452  SHA256Update (&foo,
453        "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
454        56);
455  SHA256Final (&foo, hash);
456
457  for (i = 0; i < SHA256_HASH_SIZE;) {
458    printf ("%02x", hash[i++]);
459    if (!(i % 4))
460      printf (" ");
461  }
462  printf ("\n");
463
464  SHA256Init (&foo);
465  memset (buf, 'a', sizeof (buf));
466  for (i = 0; i < 1000; i++)
467    SHA256Update (&foo, buf, sizeof (buf));
468  SHA256Final (&foo, hash);
469
470  for (i = 0; i < SHA256_HASH_SIZE;) {
471    printf ("%02x", hash[i++]);
472    if (!(i % 4))
473      printf (" ");
474  }
475  printf ("\n");
476
477  exit (0);
478}
479
480#endif /* SHA256_TEST */