tsha1.c - libeech - bittorrent library
 (HTM) git clone git://z3bra.org/libeech.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tsha1.c (8538B)
       ---
            1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
            2  *
            3  * LibTomCrypt is a library that provides various cryptographic
            4  * algorithms in a highly modular and flexible manner.
            5  *
            6  * The library is free for all purposes without any express
            7  * guarantee it works.
            8  */
            9 
           10 #include <stddef.h>
           11 #include <stdint.h>
           12 
           13 #include "sha1.h"
           14 
           15 #define F0(x,y,z)  (z ^ (x & (y ^ z)))
           16 #define F1(x,y,z)  (x ^ y ^ z)
           17 #define F2(x,y,z)  ((x & y) | (z & (x | y)))
           18 #define F3(x,y,z)  (x ^ y ^ z)
           19 
           20 #define ROL(x,n) ( (((x)<<(n))&(UINT32_MAX))|(((x)>>(sizeof(x)*8-(n)))&(UINT32_MAX)) )
           21 
           22 #define MAX(x, y) ( ((x)>(y))?(x):(y) )
           23 #define MIN(x, y) ( ((x)<(y))?(x):(y) )
           24 
           25 #define STORE32L(x, y)                                                                     \
           26   do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
           27        (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
           28 
           29 #define LOAD32L(x, y)                            \
           30   do { x = ((uint32_t)((y)[3] & 255)<<24) | \
           31            ((uint32_t)((y)[2] & 255)<<16) | \
           32            ((uint32_t)((y)[1] & 255)<<8)  | \
           33            ((uint32_t)((y)[0] & 255)); } while(0)
           34 
           35 #define STORE64L(x, y)                                                                     \
           36   do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255);   \
           37        (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255);   \
           38        (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
           39        (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
           40 
           41 #define LOAD64L(x, y)                                                       \
           42   do { x = (((uint64_t)((y)[7] & 255))<<56)|(((uint64_t)((y)[6] & 255))<<48)| \
           43            (((uint64_t)((y)[5] & 255))<<40)|(((uint64_t)((y)[4] & 255))<<32)| \
           44            (((uint64_t)((y)[3] & 255))<<24)|(((uint64_t)((y)[2] & 255))<<16)| \
           45            (((uint64_t)((y)[1] & 255))<<8)|(((uint64_t)((y)[0] & 255))); } while(0)
           46 
           47 #define STORE32H(x, y)                                                                     \
           48   do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255);   \
           49        (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
           50 
           51 #define LOAD32H(x, y)                            \
           52   do { x = ((uint32_t)((y)[0] & 255)<<24) | \
           53            ((uint32_t)((y)[1] & 255)<<16) | \
           54            ((uint32_t)((y)[2] & 255)<<8)  | \
           55            ((uint32_t)((y)[3] & 255)); } while(0)
           56 
           57 #define STORE64H(x, y)                                                                     \
           58 do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);     \
           59      (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);     \
           60      (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);     \
           61      (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
           62 
           63 #define LOAD64H(x, y)                                                      \
           64 do { x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \
           65          (((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \
           66          (((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \
           67          (((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); } while(0)
           68 
           69 static int  sha1_compress(sha1_context *md, unsigned char *buf)
           70 {
           71     uint32_t a,b,c,d,e,W[80],i;
           72 
           73     /* copy the state into 512-bits into W[0..15] */
           74     for (i = 0; i < 16; i++) {
           75         LOAD32H(W[i], buf + (4*i));
           76     }
           77 
           78     /* copy state */
           79     a = md->state[0];
           80     b = md->state[1];
           81     c = md->state[2];
           82     d = md->state[3];
           83     e = md->state[4];
           84 
           85     /* expand it */
           86     for (i = 16; i < 80; i++) {
           87         W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
           88     }
           89 
           90     /* compress */
           91     /* round one */
           92     #define FF0(a,b,c,d,e,i) e = (ROL(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROL(b, 30);
           93     #define FF1(a,b,c,d,e,i) e = (ROL(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROL(b, 30);
           94     #define FF2(a,b,c,d,e,i) e = (ROL(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROL(b, 30);
           95     #define FF3(a,b,c,d,e,i) e = (ROL(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROL(b, 30);
           96 
           97     for (i = 0; i < 20; ) {
           98        FF0(a,b,c,d,e,i++);
           99        FF0(e,a,b,c,d,i++);
          100        FF0(d,e,a,b,c,i++);
          101        FF0(c,d,e,a,b,i++);
          102        FF0(b,c,d,e,a,i++);
          103     }
          104 
          105     /* round two */
          106     for (; i < 40; )  {
          107        FF1(a,b,c,d,e,i++);
          108        FF1(e,a,b,c,d,i++);
          109        FF1(d,e,a,b,c,i++);
          110        FF1(c,d,e,a,b,i++);
          111        FF1(b,c,d,e,a,i++);
          112     }
          113 
          114     /* round three */
          115     for (; i < 60; )  {
          116        FF2(a,b,c,d,e,i++);
          117        FF2(e,a,b,c,d,i++);
          118        FF2(d,e,a,b,c,i++);
          119        FF2(c,d,e,a,b,i++);
          120        FF2(b,c,d,e,a,i++);
          121     }
          122 
          123     /* round four */
          124     for (; i < 80; )  {
          125        FF3(a,b,c,d,e,i++);
          126        FF3(e,a,b,c,d,i++);
          127        FF3(d,e,a,b,c,i++);
          128        FF3(c,d,e,a,b,i++);
          129        FF3(b,c,d,e,a,i++);
          130     }
          131 
          132     #undef FF0
          133     #undef FF1
          134     #undef FF2
          135     #undef FF3
          136 
          137     /* store */
          138     md->state[0] = md->state[0] + a;
          139     md->state[1] = md->state[1] + b;
          140     md->state[2] = md->state[2] + c;
          141     md->state[3] = md->state[3] + d;
          142     md->state[4] = md->state[4] + e;
          143 
          144     return 0;
          145 }
          146 
          147 /**
          148    Initialize the hash state
          149    @param md   The hash state you wish to initialize
          150    @return 0 if successful
          151 */
          152 int sha1_init(sha1_context * md)
          153 {
          154    if (md == NULL) return 1;
          155    md->state[0] = 0x67452301UL;
          156    md->state[1] = 0xefcdab89UL;
          157    md->state[2] = 0x98badcfeUL;
          158    md->state[3] = 0x10325476UL;
          159    md->state[4] = 0xc3d2e1f0UL;
          160    md->curlen = 0;
          161    md->length = 0;
          162    return 0;
          163 }
          164 
          165 /**
          166    Process a block of memory though the hash
          167    @param md     The hash state
          168    @param in     The data to hash
          169    @param inlen  The length of the data (octets)
          170    @return 0 if successful
          171 */
          172 int sha1_process (sha1_context * md, const unsigned char *in, unsigned long inlen)
          173 {
          174     size_t n;
          175     size_t i;
          176     int    err;
          177     if (md == NULL) return 1;
          178     if (in == NULL) return 1;
          179     if (md->curlen > sizeof(md->buf)) {
          180        return 1;
          181     }
          182     if ((md->length + inlen) < md->length) {
          183       return 1;
          184     }
          185     while (inlen > 0) {
          186         if (md->curlen == 0 && inlen >= 64) {
          187            if ((err = sha1_compress (md, (unsigned char *)in)) != 0) {
          188               return err;
          189            }
          190            md->length += 64 * 8;
          191            in             += 64;
          192            inlen          -= 64;
          193         } else {
          194            n = MIN(inlen, (64 - md->curlen));
          195            for (i = 0; i < n; i++) {
          196                md->buf[md->curlen + i] = in[i];
          197            }
          198            md->curlen += n;
          199            in             += n;
          200            inlen          -= n;
          201            if (md->curlen == 64) {
          202               if ((err = sha1_compress (md, md->buf)) != 0) {
          203                  return err;
          204               }
          205               md->length += 8*64;
          206               md->curlen = 0;
          207            }
          208        }
          209     }
          210     return 0;
          211 }
          212 
          213 /**
          214    Terminate the hash to get the digest
          215    @param md  The hash state
          216    @param out [out] The destination of the hash (20 bytes)
          217    @return 0 if successful
          218 */
          219 int sha1_done(sha1_context * md, unsigned char *out)
          220 {
          221     int i;
          222 
          223     if (md  == NULL) return 1;
          224     if (out == NULL) return 1;
          225 
          226     if (md->curlen >= sizeof(md->buf)) {
          227        return 1;
          228     }
          229 
          230     /* increase the length of the message */
          231     md->length += md->curlen * 8;
          232 
          233     /* append the '1' bit */
          234     md->buf[md->curlen++] = (unsigned char)0x80;
          235 
          236     /* if the length is currently above 56 bytes we append zeros
          237      * then compress.  Then we can fall back to padding zeros and length
          238      * encoding like normal.
          239      */
          240     if (md->curlen > 56) {
          241         while (md->curlen < 64) {
          242             md->buf[md->curlen++] = (unsigned char)0;
          243         }
          244         sha1_compress(md, md->buf);
          245         md->curlen = 0;
          246     }
          247 
          248     /* pad upto 56 bytes of zeroes */
          249     while (md->curlen < 56) {
          250         md->buf[md->curlen++] = (unsigned char)0;
          251     }
          252 
          253     /* store length */
          254     STORE64H(md->length, md->buf+56);
          255     sha1_compress(md, md->buf);
          256 
          257     /* copy output */
          258     for (i = 0; i < 5; i++) {
          259         STORE32H(md->state[i], out+(4*i));
          260     }
          261     return 0;
          262 }
          263 
          264 int sha1(const char *msg, size_t len, char *hash)
          265 {
          266         sha1_context ctx;
          267         int ret;
          268         if ((ret = sha1_init(&ctx))) return ret;
          269         if ((ret = sha1_process(&ctx, (const unsigned char *)msg, len))) return ret;
          270         if ((ret = sha1_done(&ctx, (unsigned char *)hash))) return ret;
          271         return 0;
          272 }