Back to index

tor  0.2.3.19-rc
sha256.c
Go to the documentation of this file.
00001 /* Copyright (c) 2009-2012, The Tor Project, Inc. */
00002 /* See LICENSE for licensing information */
00003 /* This SHA256 implementation is adapted from the public domain one in
00004    LibTomCrypt, version 1.6.  Tor uses it on platforms where OpenSSL doesn't
00005    have a SHA256. */
00006 
00007 
00008 typedef struct sha256_state {
00009     uint64_t length;
00010     uint32_t state[8], curlen;
00011     unsigned char buf[64];
00012 } sha256_state;
00013 
00014 #define CRYPT_OK 0
00015 #define CRYPT_NOP -1
00016 #define CRYPT_INVALID_ARG -2
00017 
00018 #define LOAD32H(x,y) STMT_BEGIN x = ntohl(get_uint32((const char*)y)); STMT_END
00019 #define STORE32H(x,y) STMT_BEGIN set_uint32((char*)y, htonl(x)); STMT_END
00020 #define STORE64H(x,y) STMT_BEGIN                                \
00021   set_uint32((char*)y, htonl((uint32_t)((x)>>32)));             \
00022   set_uint32(((char*)y)+4, htonl((uint32_t)((x)&0xffffffff)));  \
00023   STMT_END
00024 #define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
00025 #ifndef MIN
00026    #define MIN(x, y) ( ((x)<(y))?(x):(y) )
00027 #endif
00028 
00029 
00030 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
00031  *
00032  * LibTomCrypt is a library that provides various cryptographic
00033  * algorithms in a highly modular and flexible manner.
00034  *
00035  * The library is free for all purposes without any express
00036  * guarantee it works.
00037  *
00038  * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
00039  */
00040 
00047 #ifdef LTC_SMALL_CODE
00048 /* the K array */
00049 static const uint32_t K[64] = {
00050     0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
00051     0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
00052     0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
00053     0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
00054     0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
00055     0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
00056     0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
00057     0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
00058     0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
00059     0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
00060     0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
00061     0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
00062     0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
00063 };
00064 #endif
00065 
00066 /* Various logical functions */
00067 #define Ch(x,y,z)       (z ^ (x & (y ^ z)))
00068 #define Maj(x,y,z)      (((x | y) & z) | (x & y))
00069 #define S(x, n)         RORc((x),(n))
00070 #define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
00071 #define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
00072 #define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
00073 #define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
00074 #define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
00075 
00076 /* compress 512-bits */
00077 #ifdef LTC_CLEAN_STACK
00078 static int _sha256_compress(sha256_state * md, unsigned char *buf)
00079 #else
00080 static int  sha256_compress(sha256_state * md, unsigned char *buf)
00081 #endif
00082 {
00083     uint32_t S[8], W[64], t0, t1;
00084 #ifdef LTC_SMALL_CODE
00085     uint32_t t;
00086 #endif
00087     int i;
00088 
00089     /* copy state into S */
00090     for (i = 0; i < 8; i++) {
00091         S[i] = md->state[i];
00092     }
00093 
00094     /* copy the state into 512-bits into W[0..15] */
00095     for (i = 0; i < 16; i++) {
00096         LOAD32H(W[i], buf + (4*i));
00097     }
00098 
00099     /* fill W[16..63] */
00100     for (i = 16; i < 64; i++) {
00101         W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
00102     }
00103 
00104     /* Compress */
00105 #ifdef LTC_SMALL_CODE
00106 #define RND(a,b,c,d,e,f,g,h,i)                         \
00107      t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
00108      t1 = Sigma0(a) + Maj(a, b, c);                    \
00109      d += t0;                                          \
00110      h  = t0 + t1;
00111 
00112      for (i = 0; i < 64; ++i) {
00113          RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);
00114          t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
00115          S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
00116      }
00117 #else
00118 #define RND(a,b,c,d,e,f,g,h,i,ki)                    \
00119      t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i];   \
00120      t1 = Sigma0(a) + Maj(a, b, c);                  \
00121      d += t0;                                        \
00122      h  = t0 + t1;
00123 
00124     RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
00125     RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
00126     RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
00127     RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
00128     RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
00129     RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
00130     RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
00131     RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
00132     RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
00133     RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
00134     RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
00135     RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
00136     RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
00137     RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
00138     RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
00139     RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
00140     RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
00141     RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
00142     RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
00143     RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
00144     RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
00145     RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
00146     RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
00147     RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
00148     RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
00149     RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
00150     RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
00151     RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
00152     RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
00153     RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
00154     RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
00155     RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
00156     RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
00157     RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
00158     RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
00159     RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
00160     RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
00161     RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
00162     RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
00163     RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
00164     RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
00165     RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
00166     RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
00167     RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
00168     RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
00169     RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
00170     RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
00171     RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
00172     RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
00173     RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
00174     RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
00175     RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
00176     RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
00177     RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
00178     RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
00179     RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
00180     RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
00181     RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
00182     RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
00183     RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
00184     RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
00185     RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
00186     RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
00187     RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
00188 
00189 #undef RND
00190 
00191 #endif
00192 
00193     /* feedback */
00194     for (i = 0; i < 8; i++) {
00195         md->state[i] = md->state[i] + S[i];
00196     }
00197     return CRYPT_OK;
00198 }
00199 
00200 #ifdef LTC_CLEAN_STACK
00201 static int sha256_compress(sha256_state * md, unsigned char *buf)
00202 {
00203     int err;
00204     err = _sha256_compress(md, buf);
00205     burn_stack(sizeof(uint32_t) * 74);
00206     return err;
00207 }
00208 #endif
00209 
00215 static int sha256_init(sha256_state * md)
00216 {
00217     LTC_ARGCHK(md != NULL);
00218 
00219     md->curlen = 0;
00220     md->length = 0;
00221     md->state[0] = 0x6A09E667UL;
00222     md->state[1] = 0xBB67AE85UL;
00223     md->state[2] = 0x3C6EF372UL;
00224     md->state[3] = 0xA54FF53AUL;
00225     md->state[4] = 0x510E527FUL;
00226     md->state[5] = 0x9B05688CUL;
00227     md->state[6] = 0x1F83D9ABUL;
00228     md->state[7] = 0x5BE0CD19UL;
00229     return CRYPT_OK;
00230 }
00231 
00239 static int sha256_process (sha256_state * md, const unsigned char *in, unsigned long inlen)
00240 {
00241     unsigned long n;
00242     int           err;
00243     LTC_ARGCHK(md != NULL);
00244     LTC_ARGCHK(in != NULL);
00245     if (md->curlen > sizeof(md->buf)) {
00246        return CRYPT_INVALID_ARG;
00247     }
00248     while (inlen > 0) {
00249         if (md->curlen == 0 && inlen >= 64) {
00250            if ((err = sha256_compress (md, (unsigned char *)in)) != CRYPT_OK) {
00251               return err;
00252            }
00253            md->length += 64 * 8;
00254            in             += 64;
00255            inlen          -= 64;
00256         } else {
00257            n = MIN(inlen, (64 - md->curlen));
00258            memcpy(md->buf + md->curlen, in, (size_t)n);
00259            md->curlen += n;
00260            in             += n;
00261            inlen          -= n;
00262            if (md->curlen == 64) {
00263               if ((err = sha256_compress (md, md->buf)) != CRYPT_OK) {
00264                  return err;
00265               }
00266               md->length += 8*64;
00267               md->curlen = 0;
00268            }
00269        }
00270     }
00271     return CRYPT_OK;
00272 }
00273 
00280 static int sha256_done(sha256_state * md, unsigned char *out)
00281 {
00282     int i;
00283 
00284     LTC_ARGCHK(md  != NULL);
00285     LTC_ARGCHK(out != NULL);
00286 
00287     if (md->curlen >= sizeof(md->buf)) {
00288        return CRYPT_INVALID_ARG;
00289     }
00290 
00291 
00292     /* increase the length of the message */
00293     md->length += md->curlen * 8;
00294 
00295     /* append the '1' bit */
00296     md->buf[md->curlen++] = (unsigned char)0x80;
00297 
00298     /* if the length is currently above 56 bytes we append zeros
00299      * then compress.  Then we can fall back to padding zeros and length
00300      * encoding like normal.
00301      */
00302     if (md->curlen > 56) {
00303         while (md->curlen < 64) {
00304             md->buf[md->curlen++] = (unsigned char)0;
00305         }
00306         sha256_compress(md, md->buf);
00307         md->curlen = 0;
00308     }
00309 
00310     /* pad upto 56 bytes of zeroes */
00311     while (md->curlen < 56) {
00312         md->buf[md->curlen++] = (unsigned char)0;
00313     }
00314 
00315     /* store length */
00316     STORE64H(md->length, md->buf+56);
00317     sha256_compress(md, md->buf);
00318 
00319     /* copy output */
00320     for (i = 0; i < 8; i++) {
00321         STORE32H(md->state[i], out+(4*i));
00322     }
00323 #ifdef LTC_CLEAN_STACK
00324     zeromem(md, sizeof(sha256_state));
00325 #endif
00326     return CRYPT_OK;
00327 }
00328 
00329 /* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha256.c,v $ */
00330 /* $Revision: 1.9 $ */
00331 /* $Date: 2006/11/01 09:28:17 $ */