sha512.c

Go to the documentation of this file.
00001 /*-
00002  *
00003  * This code is extracted from the SourceForce.net project found at:
00004  *
00005  *     https://sourceforge.net/projects/sha/
00006  *
00007  *
00008  * Copyright (c) 2001-2003 Allan Saddi <allan@saddi.com>
00009  * All rights reserved.
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  * 1. Redistributions of source code must retain the above copyright
00015  *    notice, this list of conditions and the following disclaimer.
00016  * 2. Redistributions in binary form must reproduce the above copyright
00017  *    notice, this list of conditions and the following disclaimer in the
00018  *    documentation and/or other materials provided with the distribution.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS CONTRIBUTORS ``AS IS''
00021  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00022  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00023  * ARE DISCLAIMED.  IN NO EVENT SHALL ALLAN SADDI OR HIS CONTRIBUTORS BE
00024  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00025  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00026  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00027  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00028  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00029  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030  * POSSIBILITY OF SUCH DAMAGE.
00031  *
00032  * $Id: sha512.c 680 2003-07-25 21:58:07Z asaddi $
00033  */
00034 
00035 /*
00036  * Define WORDS_BIGENDIAN if compiling on a big-endian architecture.
00037  *
00038  * Define SHA512_TEST to test the implementation using the NIST's
00039  * sample messages. The output should be:
00040  *
00041  *   ddaf35a193617aba cc417349ae204131 12e6fa4e89a97ea2 0a9eeee64b55d39a
00042  *   2192992a274fc1a8 36ba3c23a3feebbd 454d4423643ce80e 2a9ac94fa54ca49f
00043  *   8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018
00044  *   501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909
00045  *   e718483d0ce76964 4e2e42c7bc15b463 8e1f98b13b204428 5632a803afa973eb
00046  *   de0ff244877ea60a 4cb0432ce577c31b eb009c5c2c49aa2e 4eadb217ad8cc09b
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 /* WORDS_BIGENDIAN */
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 /* WORDS_BIGENDIAN */
00155 
00156 #else /* !RUNTIME_ENDIAN */
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 /* !RUNTIME_ENDIAN */
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 /* RUNTIME_ENDIAN */
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 /* SHA512_FAST_COPY */
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 /* SHA512_FAST_COPY */
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 /* SHA384_FAST_COPY */
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 /* SHA384_FAST_COPY */
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 /* SHA512_TEST */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines