00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <string.h>
00035 #include <sys/types.h>
00036 #ifndef WIN32
00037 #include <netinet/in.h>
00038 #endif
00039
00040 #include "md5digest.h"
00041
00042
00043
00044 void CvtHex(
00045 IN HASH Bin,
00046 OUT HASHHEX Hex
00047 )
00048 {
00049 unsigned short i;
00050 unsigned char j;
00051
00052 for (i = 0; i < HASHLEN; i++)
00053 {
00054 j = (Bin[i] >> 4) & 0xf;
00055 if (j <= 9)
00056 Hex[i*2] = (j + '0');
00057 else
00058 Hex[i*2] = (j + 'a' - 10);
00059 j = Bin[i] & 0xf;
00060 if (j <= 9)
00061 Hex[i*2 + 1] = (j + '0');
00062 else
00063 Hex[i*2 + 1] = (j + 'a' - 10);
00064 }
00065 Hex[HASHHEXLEN] = '\0';
00066 }
00067
00068
00069 void DigestCalcHA1(
00070 IN char * pszAlg,
00071 IN char * pszUserName,
00072 IN char * pszRealm,
00073 IN char * pszPassword,
00074 IN char * pszNonce,
00075 IN char * pszCNonce,
00076 OUT HASHHEX SessionKey
00077 )
00078 {
00079 struct MD5Context Md5Ctx;
00080 HASH HA1;
00081
00082 MD5Init(&Md5Ctx);
00083 MD5Update(&Md5Ctx, (unsigned char*)(pszUserName), strlen(pszUserName));
00084 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00085 MD5Update(&Md5Ctx, (unsigned char*)(pszRealm), strlen(pszRealm));
00086 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00087 MD5Update(&Md5Ctx, (unsigned char*)(pszPassword), strlen(pszPassword));
00088 MD5Final((unsigned char*)(HA1), &Md5Ctx);
00089 if (strcmp(pszAlg, "md5-sess") == 0)
00090 {
00091 MD5Init(&Md5Ctx);
00092 MD5Update(&Md5Ctx, (unsigned char*)(HA1), HASHLEN);
00093 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00094 MD5Update(&Md5Ctx, (unsigned char*)(pszNonce), strlen(pszNonce));
00095 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00096 MD5Update(&Md5Ctx, (unsigned char*)(pszCNonce), strlen(pszCNonce));
00097 MD5Final((unsigned char*)(HA1), &Md5Ctx);
00098 }
00099 CvtHex(HA1, SessionKey);
00100 }
00101
00102
00103 void DigestCalcResponse(
00104 IN HASHHEX HA1,
00105 IN char * pszNonce,
00106 IN char * pszNonceCount,
00107 IN char * pszCNonce,
00108 IN char * pszQop,
00109 IN char * pszMethod,
00110 IN char * pszDigestUri,
00111 IN HASHHEX HEntity,
00112 OUT HASHHEX HA2Hex,
00113 OUT HASHHEX Response
00114 )
00115 {
00116 struct MD5Context Md5Ctx;
00117 HASH HA2;
00118 HASH RespHash;
00119
00120
00121 MD5Init(&Md5Ctx);
00122 MD5Update(&Md5Ctx, (unsigned char*)(pszMethod), strlen(pszMethod));
00123 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00124 MD5Update(&Md5Ctx, (unsigned char*)(pszDigestUri), strlen(pszDigestUri));
00125 if (strcmp(pszQop, "auth-int") == 0)
00126 {
00127 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00128 MD5Update(&Md5Ctx, (unsigned char*)(HEntity), HASHHEXLEN);
00129 }
00130 MD5Final((unsigned char*)(HA2), &Md5Ctx);
00131 CvtHex(HA2, HA2Hex);
00132
00133
00134 MD5Init(&Md5Ctx);
00135 MD5Update(&Md5Ctx, (unsigned char*)(HA1), HASHHEXLEN);
00136 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00137 MD5Update(&Md5Ctx, (unsigned char*)(pszNonce), strlen(pszNonce));
00138 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00139 if (*pszQop)
00140 {
00141 MD5Update(&Md5Ctx, (unsigned char*)(pszNonceCount), strlen(pszNonceCount));
00142 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00143 MD5Update(&Md5Ctx, (unsigned char*)(pszCNonce), strlen(pszCNonce));
00144 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00145 MD5Update(&Md5Ctx, (unsigned char*)(pszQop), strlen(pszQop));
00146 MD5Update(&Md5Ctx, (unsigned char*)(":"), 1);
00147 }
00148 MD5Update(&Md5Ctx, (unsigned char*)(HA2Hex), HASHHEXLEN);
00149 MD5Final((unsigned char*)(RespHash), &Md5Ctx);
00150 CvtHex(RespHash, Response);
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 void
00160 MD5Init(struct MD5Context *ctx)
00161 {
00162 ctx->buf[0] = 0x67452301;
00163 ctx->buf[1] = 0xefcdab89;
00164 ctx->buf[2] = 0x98badcfe;
00165 ctx->buf[3] = 0x10325476;
00166
00167 ctx->bytes[0] = 0;
00168 ctx->bytes[1] = 0;
00169 }
00170
00171
00172
00173
00174
00175 void
00176 MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len)
00177 {
00178 unsigned int t;
00179
00180
00181
00182 t = ctx->bytes[0];
00183 if ((ctx->bytes[0] = t + len) < t)
00184 ctx->bytes[1]++;
00185
00186 t = 64 - (t & 0x3f);
00187 if (t > len)
00188 {
00189 memcpy((md5byte *)ctx->in + 64 - t, buf, len);
00190 return ;
00191 }
00192
00193 memcpy((md5byte *)ctx->in + 64 - t, buf, t);
00194
00195 MD5Transform(ctx->buf, ctx->in);
00196 buf += t;
00197 len -= t;
00198
00199
00200 while (len >= 64)
00201 {
00202 memcpy(ctx->in, buf, 64);
00203
00204 MD5Transform(ctx->buf, ctx->in);
00205 buf += 64;
00206 len -= 64;
00207 }
00208
00209
00210 memcpy(ctx->in, buf, len);
00211 }
00212
00213
00214
00215
00216
00217 void
00218 MD5Final(md5byte digest[16], struct MD5Context *ctx)
00219 {
00220 int count = ctx->bytes[0] & 0x3f;
00221 md5byte *p = (md5byte *)ctx->in + count;
00222
00223
00224 *p++ = 0x80;
00225
00226
00227 count = 56 - 1 - count;
00228
00229 if (count < 0)
00230 {
00231 memset(p, 0, count + 8);
00232
00233 MD5Transform(ctx->buf, ctx->in);
00234 p = (md5byte *)ctx->in;
00235 count = 56;
00236 }
00237 memset(p, 0, count);
00238
00239
00240
00241 ctx->in[14] = ctx->bytes[0] << 3;
00242 ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
00243 MD5Transform(ctx->buf, ctx->in);
00244
00245
00246 memcpy(digest, ctx->buf, 16);
00247 memset(ctx, 0, sizeof(ctx));
00248 }
00249
00250
00251
00252
00253
00254 #define F1(x, y, z) (z ^ (x & (y ^ z)))
00255 #define F2(x, y, z) F1(z, x, y)
00256 #define F3(x, y, z) (x ^ y ^ z)
00257 #define F4(x, y, z) (y ^ (x | ~z))
00258
00259
00260 #define MD5STEP(f,w,x,y,z,in,s) \
00261 (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
00262
00263
00264
00265
00266
00267
00268 void
00269 MD5Transform(unsigned int buf[4], unsigned int const in[16])
00270 {
00271 register unsigned int a, b, c, d;
00272
00273 a = buf[0];
00274 b = buf[1];
00275 c = buf[2];
00276 d = buf[3];
00277
00278 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
00279 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
00280 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
00281 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
00282 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
00283 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
00284 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
00285 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
00286 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
00287 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
00288 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
00289 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
00290 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
00291 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
00292 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
00293 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
00294
00295 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
00296 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
00297 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
00298 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
00299 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
00300 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
00301 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
00302 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
00303 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
00304 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
00305 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
00306 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
00307 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
00308 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
00309 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
00310 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
00311
00312 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
00313 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
00314 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
00315 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
00316 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
00317 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
00318 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
00319 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
00320 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
00321 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
00322 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
00323 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
00324 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
00325 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
00326 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
00327 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
00328
00329 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
00330 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
00331 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
00332 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
00333 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
00334 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
00335 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
00336 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
00337 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
00338 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
00339 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
00340 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
00341 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
00342 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
00343 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
00344 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
00345
00346 buf[0] += a;
00347 buf[1] += b;
00348 buf[2] += c;
00349 buf[3] += d;
00350 }
00351