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
00035
00056 #include <stdint.h>
00057 #include <string.h>
00058 #include <gorp/md5.h>
00059
00064
00065 #ifndef __BIG_ENDIAN__
00066 #define byteReverse(buf, len)
00067 #else
00068
00069
00070
00071 static void byteReverse(uint8_t *buf, size_t longs)
00072 {
00073 uint32_t t;
00074 do {
00075 t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]);
00076 *(uint32_t *) buf = t;
00077 buf += 4;
00078 } while (--longs);
00079 }
00080 #endif
00081
00082
00083
00084
00085 #define F1(x, y, z) (z ^ (x & (y ^ z)))
00086 #define F2(x, y, z) F1(z, x, y)
00087 #define F3(x, y, z) (x ^ y ^ z)
00088 #define F4(x, y, z) (y ^ (x | ~z))
00089
00090
00091 #define MD5STEP(f, w, x, y, z, data, s) \
00092 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
00093
00094
00095
00096
00097
00098
00099 static void NutMD5Transform(uint32_t buf[4], uint32_t CONST in[16])
00100 {
00101 register uint32_t a, b, c, d;
00102
00103 a = buf[0];
00104 b = buf[1];
00105 c = buf[2];
00106 d = buf[3];
00107
00108 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
00109 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
00110 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
00111 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
00112 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
00113 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
00114 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
00115 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
00116 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
00117 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
00118 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
00119 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
00120 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
00121 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
00122 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
00123 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
00124
00125 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
00126 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
00127 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
00128 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
00129 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
00130 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
00131 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
00132 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
00133 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
00134 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
00135 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
00136 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
00137 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
00138 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
00139 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
00140 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
00141
00142 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
00143 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
00144 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
00145 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
00146 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
00147 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
00148 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
00149 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
00150 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
00151 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
00152 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
00153 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
00154 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
00155 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
00156 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
00157 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
00158
00159 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
00160 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
00161 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
00162 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
00163 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
00164 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
00165 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
00166 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
00167 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
00168 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
00169 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
00170 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
00171 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
00172 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
00173 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
00174 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
00175
00176 buf[0] += a;
00177 buf[1] += b;
00178 buf[2] += c;
00179 buf[3] += d;
00180 }
00181
00192 void NutMD5Init(MD5CONTEXT *context)
00193 {
00194 context->buf[0] = 0x67452301;
00195 context->buf[1] = 0xefcdab89;
00196 context->buf[2] = 0x98badcfe;
00197 context->buf[3] = 0x10325476;
00198
00199 context->bits[0] = 0;
00200 context->bits[1] = 0;
00201 }
00202
00213 void NutMD5Update(MD5CONTEXT *context, uint8_t CONST *buf, uint32_t len)
00214 {
00215 uint32_t t;
00216
00217
00218
00219 t = context->bits[0];
00220 if ((context->bits[0] = t + ((uint32_t) len << 3)) < t) {
00221 context->bits[1]++;
00222 }
00223
00224 context->bits[1] += len >> 29;
00225
00226 t = (t >> 3) & 0x3f;
00227
00228
00229
00230 if (t) {
00231 uint8_t *p = (uint8_t *) context->in + t;
00232
00233 t = 64 - t;
00234 if (len < t) {
00235 memcpy(p, buf, len);
00236 return;
00237 }
00238 memcpy(p, buf, t);
00239 byteReverse(context->in, 16);
00240 NutMD5Transform(context->buf, (uint32_t *) context->in);
00241 buf += t;
00242 len -= t;
00243 }
00244
00245
00246
00247 while (len >= 64) {
00248 memcpy(context->in, buf, 64);
00249 byteReverse(context->in, 16);
00250 NutMD5Transform(context->buf, (uint32_t *) context->in);
00251 buf += 64;
00252 len -= 64;
00253 }
00254
00255
00256
00257 memcpy(context->in, buf, len);
00258 }
00259
00260
00261
00262
00263
00275 void NutMD5Final(MD5CONTEXT *context, uint8_t digest[16])
00276 {
00277 unsigned int count;
00278 uint8_t *p;
00279
00280
00281 count = (context->bits[0] >> 3) & 0x3F;
00282
00283
00284
00285 p = context->in + count;
00286 *p++ = 0x80;
00287
00288
00289 count = 64 - 1 - count;
00290
00291
00292 if (count < 8) {
00293
00294 memset(p, 0, count);
00295 byteReverse(context->in, 16);
00296 NutMD5Transform(context->buf, (uint32_t *) context->in);
00297
00298
00299 memset(context->in, 0, 56);
00300 } else {
00301
00302 memset(p, 0, count - 8);
00303 }
00304 byteReverse(context->in, 14);
00305
00306
00307 memcpy(context->in + 56, &context->bits[0], sizeof(context->bits[0]));
00308 memcpy(context->in + 60, &context->bits[1], sizeof(context->bits[1]));
00309
00310 NutMD5Transform(context->buf, (uint32_t *) context->in);
00311 byteReverse((unsigned char *) context->buf, 4);
00312 memcpy(digest, context->buf, 16);
00313 memset(context, 0, sizeof(MD5CONTEXT));
00314 }
00315