00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <string.h>
00019
00020 #include "md5.h"
00021 #include "compat/compat.h"
00022
00023
00024
00025
00026
00027
00028
00029 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
00030 #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
00031 #define H(x, y, z) ((x) ^ (y) ^ (z))
00032 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00033
00034
00035
00036
00037 #define STEP(f, a, b, c, d, x, t, s) \
00038 (a) += f((b), (c), (d)) + (x) + (t); \
00039 (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
00040 (a) += (b);
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #if defined(__i386__) || defined(__vax__)
00051 #define SET(n) \
00052 (*(MD5_u32plus *)&ptr[(n) * 4])
00053 #define GET(n) \
00054 SET(n)
00055 #else
00056 #define SET(n) \
00057 (ctx->block[(n)] = \
00058 (MD5_u32plus)ptr[(n) * 4] | \
00059 ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
00060 ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
00061 ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
00062 #define GET(n) \
00063 (ctx->block[(n)])
00064 #endif
00065
00066
00067
00068
00069
00070 static void *body(MD5_CTX *ctx, void *data, unsigned long size)
00071 {
00072 unsigned char *ptr;
00073 MD5_u32plus a, b, c, d;
00074 MD5_u32plus saved_a, saved_b, saved_c, saved_d;
00075
00076 ptr = data;
00077
00078 a = ctx->a;
00079 b = ctx->b;
00080 c = ctx->c;
00081 d = ctx->d;
00082
00083 do {
00084 saved_a = a;
00085 saved_b = b;
00086 saved_c = c;
00087 saved_d = d;
00088
00089
00090 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
00091 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
00092 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
00093 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
00094 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
00095 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
00096 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
00097 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
00098 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
00099 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
00100 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
00101 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
00102 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
00103 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
00104 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
00105 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
00106
00107
00108 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
00109 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
00110 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
00111 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
00112 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
00113 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
00114 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
00115 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
00116 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
00117 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
00118 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
00119 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
00120 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
00121 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
00122 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
00123 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
00124
00125
00126 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
00127 STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
00128 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
00129 STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
00130 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
00131 STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
00132 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
00133 STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
00134 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
00135 STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
00136 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
00137 STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
00138 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
00139 STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
00140 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
00141 STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
00142
00143
00144 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
00145 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
00146 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
00147 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
00148 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
00149 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
00150 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
00151 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
00152 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
00153 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
00154 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
00155 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
00156 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
00157 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
00158 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
00159 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
00160
00161 a += saved_a;
00162 b += saved_b;
00163 c += saved_c;
00164 d += saved_d;
00165
00166 ptr += 64;
00167 } while (size -= 64);
00168
00169 ctx->a = a;
00170 ctx->b = b;
00171 ctx->c = c;
00172 ctx->d = d;
00173
00174 return ptr;
00175 }
00176
00177 void MD5_Init(MD5_CTX *ctx)
00178 {
00179 ctx->a = 0x67452301;
00180 ctx->b = 0xefcdab89;
00181 ctx->c = 0x98badcfe;
00182 ctx->d = 0x10325476;
00183
00184 ctx->lo = 0;
00185 ctx->hi = 0;
00186 }
00187
00188 void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
00189 {
00190 MD5_u32plus saved_lo;
00191 unsigned long used, free;
00192
00193 saved_lo = ctx->lo;
00194 if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
00195 ctx->hi++;
00196 ctx->hi += size >> 29;
00197
00198 used = saved_lo & 0x3f;
00199
00200 if (used) {
00201 free = 64 - used;
00202
00203 if (size < free) {
00204 egg_memcpy(&ctx->buffer[used], data, size);
00205 return;
00206 }
00207
00208 egg_memcpy(&ctx->buffer[used], data, free);
00209 data = ((unsigned char *)data) + free;
00210 size -= free;
00211 body(ctx, ctx->buffer, 64);
00212 }
00213
00214 if (size >= 64) {
00215 data = body(ctx, data, size & ~(unsigned long)0x3f);
00216 size &= 0x3f;
00217 }
00218
00219 egg_memcpy(ctx->buffer, data, size);
00220 }
00221
00222 void MD5_Final(unsigned char *result, MD5_CTX *ctx)
00223 {
00224 unsigned long used, free;
00225
00226 used = ctx->lo & 0x3f;
00227
00228 ctx->buffer[used++] = 0x80;
00229
00230 free = 64 - used;
00231
00232 if (free < 8) {
00233 egg_memset(&ctx->buffer[used], 0, free);
00234 body(ctx, ctx->buffer, 64);
00235 used = 0;
00236 free = 64;
00237 }
00238
00239 egg_memset(&ctx->buffer[used], 0, free - 8);
00240
00241 ctx->lo <<= 3;
00242 ctx->buffer[56] = ctx->lo;
00243 ctx->buffer[57] = ctx->lo >> 8;
00244 ctx->buffer[58] = ctx->lo >> 16;
00245 ctx->buffer[59] = ctx->lo >> 24;
00246 ctx->buffer[60] = ctx->hi;
00247 ctx->buffer[61] = ctx->hi >> 8;
00248 ctx->buffer[62] = ctx->hi >> 16;
00249 ctx->buffer[63] = ctx->hi >> 24;
00250
00251 body(ctx, ctx->buffer, 64);
00252
00253 result[0] = ctx->a;
00254 result[1] = ctx->a >> 8;
00255 result[2] = ctx->a >> 16;
00256 result[3] = ctx->a >> 24;
00257 result[4] = ctx->b;
00258 result[5] = ctx->b >> 8;
00259 result[6] = ctx->b >> 16;
00260 result[7] = ctx->b >> 24;
00261 result[8] = ctx->c;
00262 result[9] = ctx->c >> 8;
00263 result[10] = ctx->c >> 16;
00264 result[11] = ctx->c >> 24;
00265 result[12] = ctx->d;
00266 result[13] = ctx->d >> 8;
00267 result[14] = ctx->d >> 16;
00268 result[15] = ctx->d >> 24;
00269
00270 egg_memset(ctx, 0, sizeof(ctx));
00271 }