Back to index

courier  0.68.2
sha1.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2001 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #define       SHA1_INTERNAL
00007 #include      "sha1.h"
00008 
00009 #include      <string.h>
00010 #include      <stdlib.h>
00011 
00012 
00013 #define       K0 0x5A827999
00014 #define       K1 0x6ED9EBA1
00015 #define       K2 0x8F1BBCDC
00016 #define       K3 0XCA62C1D6
00017 
00018 #define       K20(x) x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x
00019 
00020 static SHA1_WORD K[80] = { K20(K0), K20(K1), K20(K2), K20(K3) };
00021 
00022 void sha1_context_init(struct SHA1_CONTEXT *c)
00023 {
00024        if (sizeof(SHA1_WORD) != 4)
00025               abort();
00026 
00027        c->H[0] = 0x67452301;
00028        c->H[1] = 0xEFCDAB89;
00029        c->H[2] = 0x98BADCFE;
00030        c->H[3] = 0x10325476;
00031        c->H[4] = 0xC3D2E1F0;
00032        c->blk_ptr=0;
00033 }
00034 
00035 void sha1_context_hash(struct SHA1_CONTEXT *c,
00036               const unsigned char blk[SHA1_BLOCK_SIZE])
00037 {
00038 SHA1_WORD     A,B,C,D,E;
00039 SHA1_WORD     TEMP;
00040 SHA1_WORD     W[80];
00041 unsigned      i, t;
00042 
00043 #define f(t,B,C,D)   ( \
00044        (t) < 20 ? ( (B) & (C) ) | ( (~(B)) & (D) ) : \
00045        (t) >= 40 && (t) < 60 ? ( (B) & (C) ) | ( (B) & (D) ) | ( (C) & (D) ):\
00046               (B) ^ (C) ^ (D) )
00047 
00048 #define S(a,b) ( ((SHA1_WORD)(a) << (b)) | ((SHA1_WORD)(a) >> (32 - (b))))
00049 
00050        for (i=t=0; t<16; t++)
00051        {
00052               W[t]= blk[i]; i++;
00053               W[t] = (W[t] << 8) | blk[i]; i++;
00054               W[t] = (W[t] << 8) | blk[i]; i++;
00055               W[t] = (W[t] << 8) | blk[i]; i++;
00056        }
00057 
00058        for (t=16; t<80; t++)
00059        {
00060               TEMP= W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
00061               W[t]= S(TEMP, 1);
00062        }
00063 
00064        A=c->H[0];
00065        B=c->H[1];
00066        C=c->H[2];
00067        D=c->H[3];
00068        E=c->H[4];
00069 
00070        for (t=0; t<80; t++)
00071        {
00072               TEMP = S(A,5);
00073               TEMP += f(t, B, C, D);
00074               TEMP += E;
00075               TEMP += W[t];
00076               TEMP += K[t];
00077 
00078               E=D;
00079               D=C;
00080               C= S(B, 30);
00081               B=A;
00082               A=TEMP;
00083        }
00084 
00085        c->H[0] += A;
00086        c->H[1] += B;
00087        c->H[2] += C;
00088        c->H[3] += D;
00089        c->H[4] += E;
00090 }
00091 
00092 void sha1_context_hashstream(struct SHA1_CONTEXT *c, const void *p, unsigned l)
00093 {
00094 const unsigned char *cp=(const unsigned char *)p;
00095 unsigned ll;
00096 
00097        while (l)
00098        {
00099               if (c->blk_ptr == 0 && l >= SHA1_BLOCK_SIZE)
00100               {
00101                      sha1_context_hash(c, cp);
00102                      cp += SHA1_BLOCK_SIZE;
00103                      l -= SHA1_BLOCK_SIZE;
00104                      continue;
00105               }
00106 
00107               ll=l;
00108               if (ll > SHA1_BLOCK_SIZE - c->blk_ptr)
00109                      ll=SHA1_BLOCK_SIZE - c->blk_ptr;
00110               memcpy(c->blk + c->blk_ptr, cp, ll);
00111               c->blk_ptr += ll;
00112               cp += ll;
00113               l -= ll;
00114               if (c->blk_ptr >= SHA1_BLOCK_SIZE)
00115               {
00116                      sha1_context_hash(c, c->blk);
00117                      c->blk_ptr=0;
00118               }
00119        }
00120 }
00121 
00122 void sha1_context_endstream(struct SHA1_CONTEXT *c, unsigned long l)
00123 {
00124        unsigned char buf[8];
00125        static const unsigned char zero[SHA1_BLOCK_SIZE-8];
00126 
00127        buf[0]=0x80;
00128        sha1_context_hashstream(c, &buf, 1);
00129        while (c->blk_ptr != SHA1_BLOCK_SIZE-8)
00130        {
00131               if (c->blk_ptr > SHA1_BLOCK_SIZE-8)
00132               {
00133                      sha1_context_hashstream(c, zero,
00134                             SHA1_BLOCK_SIZE - c->blk_ptr);
00135                      continue;
00136               }
00137               sha1_context_hashstream(c, zero,
00138                      SHA1_BLOCK_SIZE-8-c->blk_ptr);
00139        }
00140 
00141        l *= 8;
00142        buf[7] = l;
00143        buf[6] = (l >>= 8);
00144        buf[5] = (l >>= 8);
00145        buf[4] = (l >> 8);
00146        buf[3]=buf[2]=buf[1]=buf[0]=0;
00147 
00148        sha1_context_hashstream(c, buf, 8);
00149 }
00150 
00151 void sha1_context_digest(struct SHA1_CONTEXT *c, SHA1_DIGEST d)
00152 {
00153 unsigned char *dp=d + SHA1_DIGEST_SIZE;
00154 unsigned i;
00155 
00156        for ( i=5; i; )
00157        {
00158        SHA1_WORD     w=c->H[--i];
00159 
00160               *--dp=w; w >>= 8;
00161               *--dp=w; w >>= 8;
00162               *--dp=w; w >>= 8;
00163               *--dp=w;
00164        }
00165 }
00166 
00167 void sha1_context_restore(struct SHA1_CONTEXT *c, const SHA1_DIGEST d)
00168 {
00169 const unsigned char *dp=d;
00170 unsigned i;
00171 
00172        for (i=0; i<5; i++)
00173        {
00174        SHA1_WORD     w= *dp++;
00175 
00176               w=(w << 8) | *dp++;
00177               w=(w << 8) | *dp++;
00178               w=(w << 8) | *dp++;
00179               c->H[i]=w;
00180        }
00181        c->blk_ptr=0;
00182 }
00183 
00184 void sha1_digest(const void *msg, unsigned len, SHA1_DIGEST d)
00185 {
00186 struct SHA1_CONTEXT c;
00187 
00188        sha1_context_init( &c );
00189        sha1_context_hashstream(&c, msg, len);
00190        sha1_context_endstream(&c, len);
00191        sha1_context_digest( &c, d );
00192 }