Back to index

courier  0.68.2
md5.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2000 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #define       MD5_INTERNAL
00007 #include      "md5.h"
00008 #include      <string.h>
00009 #include      <stdlib.h>
00010 
00011 
00012 #define       MD5_BYTE      unsigned char
00013 
00014 #define       MD5_ROL(w,n)  \
00015               ( (w) << (n) | ( (w) >> (32-(n)) ) )
00016 
00017 static MD5_WORD      T[64]={
00018 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
00019 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
00020 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
00021 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
00022 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
00023 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
00024 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
00025 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
00026 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
00027 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
00028 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
00029 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
00030 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
00031 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
00032 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
00033 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
00034 
00035 void md5_context_init(struct MD5_CONTEXT *c)
00036 {
00037        if (sizeof(MD5_WORD) != 4)  abort();
00038 
00039        c->A=0x67452301;
00040        c->B=0xefcdab89;
00041        c->C=0x98badcfe;
00042        c->D=0x10325476;
00043 
00044        c->blk_ptr=0;
00045 }
00046 
00047 void md5_context_hash(struct MD5_CONTEXT *c,
00048        const unsigned char blk[MD5_BLOCK_SIZE])
00049 {
00050 MD5_WORD      x[16];
00051 unsigned      i, j;
00052 MD5_WORD      A, B, C, D;
00053 MD5_WORD      zz;
00054 
00055        for (i=j=0; i<16; i++)
00056        {
00057        MD5_WORD      w=(MD5_WORD)blk[j++];
00058 
00059               w |= (MD5_WORD)blk[j++] << 8;
00060               w |= (MD5_WORD)blk[j++] << 16;
00061               w |= (MD5_WORD)blk[j++] << 24;
00062               x[i]= w;
00063        }
00064 
00065 #define       F(X,Y,Z)      ( ((X) & (Y)) | ( (~(X)) & (Z)))
00066 #define       G(X,Y,Z)      ( ((X) & (Z)) | ( (Y) & (~(Z))))
00067 #define       H(X,Y,Z)      ( (X) ^ (Y) ^ (Z) )
00068 #define       I(X,Y,Z)      ( (Y) ^ ( (X) | (~(Z))))
00069 
00070        A=c->A;
00071        B=c->B;
00072        C=c->C;
00073        D=c->D;
00074 
00075 #define       ROUND1(a,b,c,d,k,s,i)       \
00076        { zz=(a + F(b,c,d) + x[k] + T[i]); a=b+MD5_ROL(zz,s); }
00077 
00078        ROUND1(A,B,C,D,0,7,0);
00079        ROUND1(D,A,B,C,1,12,1);
00080        ROUND1(C,D,A,B,2,17,2);
00081        ROUND1(B,C,D,A,3,22,3);
00082        ROUND1(A,B,C,D,4,7,4);
00083        ROUND1(D,A,B,C,5,12,5);
00084        ROUND1(C,D,A,B,6,17,6);
00085        ROUND1(B,C,D,A,7,22,7);
00086        ROUND1(A,B,C,D,8,7,8);
00087        ROUND1(D,A,B,C,9,12,9);
00088        ROUND1(C,D,A,B,10,17,10);
00089        ROUND1(B,C,D,A,11,22,11);
00090        ROUND1(A,B,C,D,12,7,12);
00091        ROUND1(D,A,B,C,13,12,13);
00092        ROUND1(C,D,A,B,14,17,14);
00093        ROUND1(B,C,D,A,15,22,15);
00094 
00095 #define       ROUND2(a,b,c,d,k,s,i)       \
00096        { zz=(a + G(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); }
00097 
00098        ROUND2(A,B,C,D,1,5,16);
00099        ROUND2(D,A,B,C,6,9,17);
00100        ROUND2(C,D,A,B,11,14,18);
00101        ROUND2(B,C,D,A,0,20,19);
00102        ROUND2(A,B,C,D,5,5,20);
00103        ROUND2(D,A,B,C,10,9,21);
00104        ROUND2(C,D,A,B,15,14,22);
00105        ROUND2(B,C,D,A,4,20,23);
00106        ROUND2(A,B,C,D,9,5,24);
00107        ROUND2(D,A,B,C,14,9,25);
00108        ROUND2(C,D,A,B,3,14,26);
00109        ROUND2(B,C,D,A,8,20,27);
00110        ROUND2(A,B,C,D,13,5,28);
00111        ROUND2(D,A,B,C,2,9,29);
00112        ROUND2(C,D,A,B,7,14,30);
00113        ROUND2(B,C,D,A,12,20,31);
00114 
00115 #define       ROUND3(a,b,c,d,k,s,i)       \
00116        { zz=(a + H(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); }
00117 
00118        ROUND3(A,B,C,D,5,4,32);
00119        ROUND3(D,A,B,C,8,11,33);
00120        ROUND3(C,D,A,B,11,16,34);
00121        ROUND3(B,C,D,A,14,23,35);
00122        ROUND3(A,B,C,D,1,4,36);
00123        ROUND3(D,A,B,C,4,11,37);
00124        ROUND3(C,D,A,B,7,16,38);
00125        ROUND3(B,C,D,A,10,23,39);
00126        ROUND3(A,B,C,D,13,4,40);
00127        ROUND3(D,A,B,C,0,11,41);
00128        ROUND3(C,D,A,B,3,16,42);
00129        ROUND3(B,C,D,A,6,23,43);
00130        ROUND3(A,B,C,D,9,4,44);
00131        ROUND3(D,A,B,C,12,11,45);
00132        ROUND3(C,D,A,B,15,16,46);
00133        ROUND3(B,C,D,A,2,23,47);
00134 
00135 #define       ROUND4(a,b,c,d,k,s,i)       \
00136        { zz=(a + I(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); }
00137 
00138        ROUND4(A,B,C,D,0,6,48);
00139        ROUND4(D,A,B,C,7,10,49);
00140        ROUND4(C,D,A,B,14,15,50);
00141        ROUND4(B,C,D,A,5,21,51);
00142        ROUND4(A,B,C,D,12,6,52);
00143        ROUND4(D,A,B,C,3,10,53);
00144        ROUND4(C,D,A,B,10,15,54);
00145        ROUND4(B,C,D,A,1,21,55);
00146        ROUND4(A,B,C,D,8,6,56);
00147        ROUND4(D,A,B,C,15,10,57);
00148        ROUND4(C,D,A,B,6,15,58);
00149        ROUND4(B,C,D,A,13,21,59);
00150        ROUND4(A,B,C,D,4,6,60);
00151        ROUND4(D,A,B,C,11,10,61);
00152        ROUND4(C,D,A,B,2,15,62);
00153        ROUND4(B,C,D,A,9,21,63);
00154 
00155        c->A += A;
00156        c->B += B;
00157        c->C += C;
00158        c->D += D;
00159 }
00160 
00161 void md5_context_hashstream(struct MD5_CONTEXT *c, const void *p, unsigned l)
00162 {
00163 const unsigned char *cp=(const unsigned char *)p;
00164 unsigned ll;
00165 
00166        while (l)
00167        {
00168               if (c->blk_ptr == 0 && l >= MD5_BLOCK_SIZE)
00169               {
00170                      md5_context_hash(c, cp);
00171                      cp += MD5_BLOCK_SIZE;
00172                      l -= MD5_BLOCK_SIZE;
00173                      continue;
00174               }
00175 
00176               ll=l;
00177               if (ll > MD5_BLOCK_SIZE - c->blk_ptr)
00178                      ll=MD5_BLOCK_SIZE - c->blk_ptr;
00179               memcpy(c->blk + c->blk_ptr, cp, ll);
00180               c->blk_ptr += ll;
00181               cp += ll;
00182               l -= ll;
00183               if (c->blk_ptr >= MD5_BLOCK_SIZE)
00184               {
00185                      md5_context_hash(c, c->blk);
00186                      c->blk_ptr=0;
00187               }
00188        }
00189 }
00190 
00191 void md5_context_endstream(struct MD5_CONTEXT *c, unsigned long ll)
00192 {
00193 unsigned char buf[8];
00194 
00195 static unsigned char zero[MD5_BLOCK_SIZE-8];
00196 MD5_WORD      l;
00197 
00198        buf[0]=0x80;
00199        md5_context_hashstream(c, buf, 1);
00200        while (c->blk_ptr != MD5_BLOCK_SIZE - 8)
00201        {
00202               if (c->blk_ptr > MD5_BLOCK_SIZE - 8)
00203               {
00204                      md5_context_hashstream(c, zero,
00205                             MD5_BLOCK_SIZE - c->blk_ptr);
00206                      continue;
00207               }
00208               md5_context_hashstream(c, zero,
00209                      MD5_BLOCK_SIZE - 8 - c->blk_ptr);
00210        }
00211 
00212        l= ll;
00213 
00214        l <<= 3;
00215 
00216        buf[0]=l;
00217        l >>= 8;
00218        buf[1]=l;
00219        l >>= 8;
00220        buf[2]=l;
00221        l >>= 8;
00222        buf[3]=l;
00223 
00224        l= ll;
00225        l >>= 29;
00226        buf[4]=l;
00227        l >>= 8;
00228        buf[5]=l;
00229        l >>= 8;
00230        buf[6]=l;
00231        l >>= 8;
00232        buf[7]=l;
00233 
00234        md5_context_hashstream(c, buf, 8);
00235 }
00236 
00237 void md5_context_digest(struct MD5_CONTEXT *c, MD5_DIGEST d)
00238 {
00239 unsigned char *dp=d;
00240 MD5_WORD      w;
00241 
00242 #define       PUT(c) (w=(c), *dp++ = w, w >>= 8, *dp++ = w, w >>= 8, *dp++ = w, w >>= 8, *dp++ = w)
00243 
00244        PUT(c->A);
00245        PUT(c->B);
00246        PUT(c->C);
00247        PUT(c->D);
00248 #undef PUT
00249 }
00250 
00251 void md5_context_restore(struct MD5_CONTEXT *c, const MD5_DIGEST d)
00252 {
00253 const unsigned char *dp=(unsigned char *)d+MD5_DIGEST_SIZE;
00254 MD5_WORD      w;
00255 
00256 #define       GET    \
00257        w=*--dp; w=(w << 8) | *--dp; w=(w << 8) | *--dp; w=(w << 8) | *--dp;
00258 
00259        GET
00260        c->D=w;
00261        GET
00262        c->C=w;
00263        GET
00264        c->B=w;
00265        GET
00266        c->A=w;
00267        c->blk_ptr=0;
00268 }
00269 
00270 void md5_digest(const void *msg, unsigned int len, MD5_DIGEST d)
00271 {
00272 struct MD5_CONTEXT   c;
00273 
00274        md5_context_init(&c);
00275        md5_context_hashstream(&c, msg, len);
00276        md5_context_endstream(&c, len);
00277        md5_context_digest(&c, d);
00278 }