00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00058 #include <stdint.h>
00059 #include <string.h>
00060
00061 #include "sha512.h"
00062
00066 #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00067 #define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
00068 #define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
00069 #define ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
00070
00071 #define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
00072 #define Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
00073 #define SIGMA0(x) (ROTR64((x), 28) ^ ROTR64((x), 34) ^ ROTR64((x), 39))
00074 #define SIGMA1(x) (ROTR64((x), 14) ^ ROTR64((x), 18) ^ ROTR64((x), 41))
00075 #define sigma0(x) (ROTR64((x), 1) ^ ROTR64((x), 8) ^ ((x) >> 7))
00076 #define sigma1(x) (ROTR64((x), 19) ^ ROTR64((x), 61) ^ ((x) >> 6))
00077
00078 #define DO_ROUND() { \
00079 t1 = h + SIGMA1(e) + Ch(e, f, g) + *(Kp++) + *(W++); \
00080 t2 = SIGMA0(a) + Maj(a, b, c); \
00081 h = g; \
00082 g = f; \
00083 f = e; \
00084 e = d + t1; \
00085 d = c; \
00086 c = b; \
00087 b = a; \
00088 a = t1 + t2; \
00089 }
00090
00091 static const uint64_t K[80] = {
00092 0x428a2f98d728ae22LL, 0x7137449123ef65cdLL,
00093 0xb5c0fbcfec4d3b2fLL, 0xe9b5dba58189dbbcLL,
00094 0x3956c25bf348b538LL, 0x59f111f1b605d019LL,
00095 0x923f82a4af194f9bLL, 0xab1c5ed5da6d8118LL,
00096 0xd807aa98a3030242LL, 0x12835b0145706fbeLL,
00097 0x243185be4ee4b28cLL, 0x550c7dc3d5ffb4e2LL,
00098 0x72be5d74f27b896fLL, 0x80deb1fe3b1696b1LL,
00099 0x9bdc06a725c71235LL, 0xc19bf174cf692694LL,
00100 0xe49b69c19ef14ad2LL, 0xefbe4786384f25e3LL,
00101 0x0fc19dc68b8cd5b5LL, 0x240ca1cc77ac9c65LL,
00102 0x2de92c6f592b0275LL, 0x4a7484aa6ea6e483LL,
00103 0x5cb0a9dcbd41fbd4LL, 0x76f988da831153b5LL,
00104 0x983e5152ee66dfabLL, 0xa831c66d2db43210LL,
00105 0xb00327c898fb213fLL, 0xbf597fc7beef0ee4LL,
00106 0xc6e00bf33da88fc2LL, 0xd5a79147930aa725LL,
00107 0x06ca6351e003826fLL, 0x142929670a0e6e70LL,
00108 0x27b70a8546d22ffcLL, 0x2e1b21385c26c926LL,
00109 0x4d2c6dfc5ac42aedLL, 0x53380d139d95b3dfLL,
00110 0x650a73548baf63deLL, 0x766a0abb3c77b2a8LL,
00111 0x81c2c92e47edaee6LL, 0x92722c851482353bLL,
00112 0xa2bfe8a14cf10364LL, 0xa81a664bbc423001LL,
00113 0xc24b8b70d0f89791LL, 0xc76c51a30654be30LL,
00114 0xd192e819d6ef5218LL, 0xd69906245565a910LL,
00115 0xf40e35855771202aLL, 0x106aa07032bbd1b8LL,
00116 0x19a4c116b8d2d0c8LL, 0x1e376c085141ab53LL,
00117 0x2748774cdf8eeb99LL, 0x34b0bcb5e19b48a8LL,
00118 0x391c0cb3c5c95a63LL, 0x4ed8aa4ae3418acbLL,
00119 0x5b9cca4f7763e373LL, 0x682e6ff3d6b2b8a3LL,
00120 0x748f82ee5defb2fcLL, 0x78a5636f43172f60LL,
00121 0x84c87814a1f0ab72LL, 0x8cc702081a6439ecLL,
00122 0x90befffa23631e28LL, 0xa4506cebde82bde9LL,
00123 0xbef9a3f7b2c67915LL, 0xc67178f2e372532bLL,
00124 0xca273eceea26619cLL, 0xd186b8c721c0c207LL,
00125 0xeada7dd6cde0eb1eLL, 0xf57d4f7fee6ed178LL,
00126 0x06f067aa72176fbaLL, 0x0a637dc5a2c898a6LL,
00127 0x113f9804bef90daeLL, 0x1b710b35131c471bLL,
00128 0x28db77f523047d84LL, 0x32caab7b40c72493LL,
00129 0x3c9ebe0a15c9bebcLL, 0x431d67c49c100d4cLL,
00130 0x4cc5d4becb3e42b6LL, 0x597f299cfc657e2aLL,
00131 0x5fcb6fab3ad6faecLL, 0x6c44198c4a475817LL
00132 };
00133
00134 #ifndef RUNTIME_ENDIAN
00135
00136 #ifdef WORDS_BIGENDIAN
00137
00138 #define BYTESWAP(x) (x)
00139 #define BYTESWAP64(x) (x)
00140
00141 #else
00142
00143 #define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \
00144 (ROTL((x), 8) & 0x00ff00ffL))
00145 #define BYTESWAP64(x) _byteswap64(x)
00146
00147 static inline uint64_t _byteswap64(uint64_t x)
00148 {
00149 uint32_t a = x >> 32;
00150 uint32_t b = (uint32_t) x;
00151 return ((uint64_t) BYTESWAP(b) << 32) | (uint64_t) BYTESWAP(a);
00152 }
00153
00154 #endif
00155
00156 #else
00157
00158 #define BYTESWAP(x) _byteswap(sc->littleEndian, x)
00159 #define BYTESWAP64(x) _byteswap64(sc->littleEndian, x)
00160
00161 #define _BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \
00162 (ROTL((x), 8) & 0x00ff00ffL))
00163 #define _BYTESWAP64(x) __byteswap64(x)
00164
00170 static inline uint64_t __byteswap64(uint64_t x)
00171 {
00172 uint32_t a = x >> 32;
00173 uint32_t b = (uint32_t) x;
00174 return ((uint64_t) _BYTESWAP(b) << 32) | (uint64_t) _BYTESWAP(a);
00175 }
00176
00177 static inline uint32_t _byteswap(int littleEndian, uint32_t x)
00178 {
00179 if (!littleEndian)
00180 return x;
00181 else
00182 return _BYTESWAP(x);
00183 }
00184
00185 static inline uint64_t _byteswap64(int littleEndian, uint64_t x)
00186 {
00187 if (!littleEndian)
00188 return x;
00189 else
00190 return _BYTESWAP64(x);
00191 }
00192
00193 static inline void setEndian(int *littleEndianp)
00194 {
00195 union {
00196 uint32_t w;
00197 uint8_t b[4];
00198 } endian;
00199
00200 endian.w = 1L;
00201 *littleEndianp = endian.b[0] != 0;
00202 }
00203
00204 #endif
00205
00206 static const uint8_t padding[128] = {
00207 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00223 };
00224
00230 void
00231 SHA512Init (SHA512Context *sc)
00232 {
00233 #ifdef RUNTIME_ENDIAN
00234 setEndian (&sc->littleEndian);
00235 #endif
00236
00237 sc->totalLength[0] = 0LL;
00238 sc->totalLength[1] = 0LL;
00239 sc->hash[0] = 0x6a09e667f3bcc908LL;
00240 sc->hash[1] = 0xbb67ae8584caa73bLL;
00241 sc->hash[2] = 0x3c6ef372fe94f82bLL;
00242 sc->hash[3] = 0xa54ff53a5f1d36f1LL;
00243 sc->hash[4] = 0x510e527fade682d1LL;
00244 sc->hash[5] = 0x9b05688c2b3e6c1fLL;
00245 sc->hash[6] = 0x1f83d9abfb41bd6bLL;
00246 sc->hash[7] = 0x5be0cd19137e2179LL;
00247 sc->bufferLength = 0L;
00248 }
00249
00250 static void
00251 burnStack (int size)
00252 {
00253 char buf[128];
00254
00255 memset (buf, 0, sizeof (buf));
00256 size -= sizeof (buf);
00257 if (size > 0)
00258 burnStack (size);
00259 }
00260
00261 static void
00262 SHA512Guts (SHA512Context *sc, const uint64_t *cbuf)
00263 {
00264 uint64_t buf[80];
00265 uint64_t *W, *W2, *W7, *W15, *W16;
00266 uint64_t a, b, c, d, e, f, g, h;
00267 uint64_t t1, t2;
00268 const uint64_t *Kp;
00269 int i;
00270
00271 W = buf;
00272
00273 for (i = 15; i >= 0; i--) {
00274 *(W++) = BYTESWAP64(*cbuf);
00275 cbuf++;
00276 }
00277
00278 W16 = &buf[0];
00279 W15 = &buf[1];
00280 W7 = &buf[9];
00281 W2 = &buf[14];
00282
00283 for (i = 63; i >= 0; i--) {
00284 *(W++) = sigma1(*W2) + *(W7++) + sigma0(*W15) + *(W16++);
00285 W2++;
00286 W15++;
00287 }
00288
00289 a = sc->hash[0];
00290 b = sc->hash[1];
00291 c = sc->hash[2];
00292 d = sc->hash[3];
00293 e = sc->hash[4];
00294 f = sc->hash[5];
00295 g = sc->hash[6];
00296 h = sc->hash[7];
00297
00298 Kp = K;
00299 W = buf;
00300
00301 for (i = 79; i >= 0; i--)
00302 DO_ROUND();
00303
00304 sc->hash[0] += a;
00305 sc->hash[1] += b;
00306 sc->hash[2] += c;
00307 sc->hash[3] += d;
00308 sc->hash[4] += e;
00309 sc->hash[5] += f;
00310 sc->hash[6] += g;
00311 sc->hash[7] += h;
00312 }
00313
00314
00322 void
00323 SHA512Update (SHA512Context *sc, const void *vdata, uint32_t len)
00324 {
00325 const uint8_t *data = vdata;
00326 uint32_t bufferBytesLeft;
00327 uint32_t bytesToCopy;
00328 uint64_t carryCheck;
00329 int needBurn = 0;
00330
00331 #ifdef SHA512_FAST_COPY
00332 if (sc->bufferLength) {
00333 bufferBytesLeft = 128L - sc->bufferLength;
00334
00335 bytesToCopy = bufferBytesLeft;
00336 if (bytesToCopy > len)
00337 bytesToCopy = len;
00338
00339 memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
00340
00341 carryCheck = sc->totalLength[1];
00342 sc->totalLength[1] += bytesToCopy * 8L;
00343 if (sc->totalLength[1] < carryCheck)
00344 sc->totalLength[0]++;
00345
00346 sc->bufferLength += bytesToCopy;
00347 data += bytesToCopy;
00348 len -= bytesToCopy;
00349
00350 if (sc->bufferLength == 128L) {
00351 SHA512Guts (sc, sc->buffer.words);
00352 needBurn = 1;
00353 sc->bufferLength = 0L;
00354 }
00355 }
00356
00357 while (len > 127) {
00358 carryCheck = sc->totalLength[1];
00359 sc->totalLength[1] += 1024L;
00360 if (sc->totalLength[1] < carryCheck)
00361 sc->totalLength[0]++;
00362
00363 SHA512Guts (sc, data);
00364 needBurn = 1;
00365
00366 data += 128L;
00367 len -= 128L;
00368 }
00369
00370 if (len) {
00371 memcpy (&sc->buffer.bytes[sc->bufferLength], data, len);
00372
00373 carryCheck = sc->totalLength[1];
00374 sc->totalLength[1] += len * 8L;
00375 if (sc->totalLength[1] < carryCheck)
00376 sc->totalLength[0]++;
00377
00378 sc->bufferLength += len;
00379 }
00380 #else
00381 while (len) {
00382 bufferBytesLeft = 128L - sc->bufferLength;
00383
00384 bytesToCopy = bufferBytesLeft;
00385 if (bytesToCopy > len)
00386 bytesToCopy = len;
00387
00388 memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
00389
00390 carryCheck = sc->totalLength[1];
00391 sc->totalLength[1] += bytesToCopy * 8L;
00392 if (sc->totalLength[1] < carryCheck)
00393 sc->totalLength[0]++;
00394
00395 sc->bufferLength += bytesToCopy;
00396 data += bytesToCopy;
00397 len -= bytesToCopy;
00398
00399 if (sc->bufferLength == 128L) {
00400 SHA512Guts (sc, sc->buffer.words);
00401 needBurn = 1;
00402 sc->bufferLength = 0L;
00403 }
00404 }
00405 #endif
00406
00407 if (needBurn)
00408 burnStack (sizeof (uint64_t[90]) + sizeof (uint64_t *[6]) + sizeof (int));
00409 }
00410
00411
00418 void SHA512Final (SHA512Context *sc, uint8_t hash[SHA512_HASH_SIZE])
00419 {
00420 uint32_t bytesToPad;
00421 uint64_t lengthPad[2];
00422 int i;
00423
00424 bytesToPad = 240L - sc->bufferLength;
00425 if (bytesToPad > 128L)
00426 bytesToPad -= 128L;
00427
00428 lengthPad[0] = BYTESWAP64(sc->totalLength[0]);
00429 lengthPad[1] = BYTESWAP64(sc->totalLength[1]);
00430
00431 SHA512Update (sc, padding, bytesToPad);
00432 SHA512Update (sc, lengthPad, 16L);
00433
00434 if (hash) {
00435 for (i = 0; i < SHA512_HASH_WORDS; i++) {
00436 #ifdef SHA384_FAST_COPY
00437 *((uint64_t *) hash) = BYTESWAP64(sc->hash[i]);
00438 #else
00439 hash[0] = (uint8_t) (sc->hash[i] >> 56);
00440 hash[1] = (uint8_t) (sc->hash[i] >> 48);
00441 hash[2] = (uint8_t) (sc->hash[i] >> 40);
00442 hash[3] = (uint8_t) (sc->hash[i] >> 32);
00443 hash[4] = (uint8_t) (sc->hash[i] >> 24);
00444 hash[5] = (uint8_t) (sc->hash[i] >> 16);
00445 hash[6] = (uint8_t) (sc->hash[i] >> 8);
00446 hash[7] = (uint8_t) sc->hash[i];
00447 #endif
00448 hash += 8;
00449 }
00450 }
00451 }
00452
00453 #ifdef SHA512_TEST
00454
00455 #include <stdio.h>
00456 #include <stdlib.h>
00457 #include <string.h>
00458
00459 int
00460 main (int argc, char *argv[])
00461 {
00462 SHA512Context foo;
00463 uint8_t hash[SHA512_HASH_SIZE];
00464 char buf[1000];
00465 int i;
00466
00467 SHA512Init (&foo);
00468 SHA512Update (&foo, "abc", 3);
00469 SHA512Final (&foo, hash);
00470
00471 for (i = 0; i < SHA512_HASH_SIZE;) {
00472 printf ("%02x", hash[i++]);
00473 if (!(i % 8))
00474 printf (" ");
00475 if (!(i % 32))
00476 printf ("\n");
00477 }
00478
00479 SHA512Init (&foo);
00480 SHA512Update (&foo,
00481 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
00482 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
00483 112);
00484 SHA512Final (&foo, hash);
00485
00486 for (i = 0; i < SHA512_HASH_SIZE;) {
00487 printf ("%02x", hash[i++]);
00488 if (!(i % 8))
00489 printf (" ");
00490 if (!(i % 32))
00491 printf ("\n");
00492 }
00493
00494 SHA512Init (&foo);
00495 memset (buf, 'a', sizeof (buf));
00496 for (i = 0; i < 1000; i++)
00497 SHA512Update (&foo, buf, sizeof (buf));
00498 SHA512Final (&foo, hash);
00499
00500 for (i = 0; i < SHA512_HASH_SIZE;) {
00501 printf ("%02x", hash[i++]);
00502 if (!(i % 8))
00503 printf (" ");
00504 if (!(i % 32))
00505 printf ("\n");
00506 }
00507
00508 exit (0);
00509 }
00510
00511 #endif