/thirdparty/liblastfm2/src/fingerprint/Sha256.cpp
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 */