md5.c

Go to the documentation of this file.
00001 /*
00002  * This is an OpenSSL-compatible implementation of the RSA Data Security,
00003  * Inc. MD5 Message-Digest Algorithm.
00004  *
00005  * Written by Solar Designer <solar@openwall.com> in 2001, and placed in
00006  * the public domain.  There's absolutely no warranty.
00007  *
00008  * This differs from Colin Plumb's older public domain implementation in
00009  * that no 32-bit integer data type is required, there's no compile-time
00010  * endianness configuration, and the function prototypes match OpenSSL's.
00011  * The primary goals are portability and ease of use.
00012  *
00013  * This implementation is meant to be fast, but not as fast as possible.
00014  * Some known optimizations are not included to reduce source code size
00015  * and avoid compile-time configuration.
00016  */
00017 
00018 #include <string.h>
00019 #include "md5.h"
00020 
00021 /*
00022  * The basic MD5 functions.
00023  *
00024  * F is optimized compared to its RFC 1321 definition just like in Colin
00025  * Plumb's implementation.
00026  */
00027 #define F(x, y, z)                      ((z) ^ ((x) & ((y) ^ (z))))
00028 #define G(x, y, z)                      ((y) ^ ((z) & ((x) ^ (y))))
00029 #define H(x, y, z)                      ((x) ^ (y) ^ (z))
00030 #define I(x, y, z)                      ((y) ^ ((x) | ~(z)))
00031 
00032 /*
00033  * The MD5 transformation for all four rounds.
00034  */
00035 #define STEP(f, a, b, c, d, x, t, s) \
00036         (a) += f((b), (c), (d)) + (x) + (t); \
00037         (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
00038         (a) += (b);
00039 
00040 /*
00041  * SET reads 4 input bytes in little-endian byte order and stores them
00042  * in a properly aligned word in host byte order.
00043  *
00044  * The check for little-endian architectures which tolerate unaligned
00045  * memory accesses is just an optimization.  Nothing will break if it
00046  * doesn't work.
00047  */
00048 #if defined(__i386__) || defined(__vax__)
00049 #define SET(n) \
00050         (*(MD5_u32plus *)&ptr[(n) * 4])
00051 #define GET(n) \
00052         SET(n)
00053 #else
00054 #define SET(n) \
00055         (ctx->block[(n)] = \
00056         (MD5_u32plus)ptr[(n) * 4] | \
00057         ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
00058         ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
00059         ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
00060 #define GET(n) \
00061         (ctx->block[(n)])
00062 #endif
00063 
00064 /*
00065  * This processes one or more 64-byte data blocks, but does NOT update
00066  * the bit counters.  There're no alignment requirements.
00067  */
00068 static void *body(MD5_CTX *ctx, void *data, unsigned long size)
00069 {
00070         unsigned char *ptr;
00071         MD5_u32plus a, b, c, d;
00072         MD5_u32plus saved_a, saved_b, saved_c, saved_d;
00073 
00074         ptr = data;
00075 
00076         a = ctx->a;
00077         b = ctx->b;
00078         c = ctx->c;
00079         d = ctx->d;
00080 
00081         do {
00082                 saved_a = a;
00083                 saved_b = b;
00084                 saved_c = c;
00085                 saved_d = d;
00086 
00087 /* Round 1 */
00088                 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
00089                 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
00090                 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
00091                 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
00092                 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
00093                 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
00094                 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
00095                 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
00096                 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
00097                 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
00098                 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
00099                 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
00100                 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
00101                 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
00102                 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
00103                 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
00104 
00105 /* Round 2 */
00106                 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
00107                 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
00108                 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
00109                 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
00110                 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
00111                 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
00112                 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
00113                 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
00114                 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
00115                 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
00116                 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
00117                 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
00118                 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
00119                 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
00120                 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
00121                 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
00122 
00123 /* Round 3 */
00124                 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
00125                 STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
00126                 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
00127                 STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
00128                 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
00129                 STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
00130                 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
00131                 STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
00132                 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
00133                 STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
00134                 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
00135                 STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
00136                 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
00137                 STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
00138                 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
00139                 STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
00140 
00141 /* Round 4 */
00142                 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
00143                 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
00144                 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
00145                 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
00146                 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
00147                 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
00148                 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
00149                 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
00150                 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
00151                 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
00152                 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
00153                 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
00154                 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
00155                 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
00156                 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
00157                 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
00158 
00159                 a += saved_a;
00160                 b += saved_b;
00161                 c += saved_c;
00162                 d += saved_d;
00163 
00164                 ptr += 64;
00165         } while (size -= 64);
00166 
00167         ctx->a = a;
00168         ctx->b = b;
00169         ctx->c = c;
00170         ctx->d = d;
00171 
00172         return ptr;
00173 }
00174 
00175 void MD5_Init(MD5_CTX *ctx)
00176 {
00177         ctx->a = 0x67452301;
00178         ctx->b = 0xefcdab89;
00179         ctx->c = 0x98badcfe;
00180         ctx->d = 0x10325476;
00181 
00182         ctx->lo = 0;
00183         ctx->hi = 0;
00184 }
00185 
00186 void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
00187 {
00188         MD5_u32plus saved_lo;
00189         unsigned long used, free;
00190 
00191         saved_lo = ctx->lo;
00192         if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
00193                 ctx->hi++;
00194         ctx->hi += size >> 29;
00195 
00196         used = saved_lo & 0x3f;
00197 
00198         if (used) {
00199                 free = 64 - used;
00200 
00201                 if (size < free) {
00202                         memcpy(&ctx->buffer[used], data, size);
00203                         return;
00204                 }
00205 
00206                 memcpy(&ctx->buffer[used], data, free);
00207                 data = (unsigned char *)data + free;
00208                 size -= free;
00209                 body(ctx, ctx->buffer, 64);
00210         }
00211 
00212         if (size >= 64) {
00213                 data = body(ctx, data, size & ~(unsigned long)0x3f);
00214                 size &= 0x3f;
00215         }
00216 
00217         memcpy(ctx->buffer, data, size);
00218 }
00219 
00220 void MD5_Final(unsigned char *result, MD5_CTX *ctx)
00221 {
00222         unsigned long used, free;
00223 
00224         used = ctx->lo & 0x3f;
00225 
00226         ctx->buffer[used++] = 0x80;
00227 
00228         free = 64 - used;
00229 
00230         if (free < 8) {
00231                 memset(&ctx->buffer[used], 0, free);
00232                 body(ctx, ctx->buffer, 64);
00233                 used = 0;
00234                 free = 64;
00235         }
00236 
00237         memset(&ctx->buffer[used], 0, free - 8);
00238 
00239         ctx->lo <<= 3;
00240         ctx->buffer[56] = ctx->lo;
00241         ctx->buffer[57] = ctx->lo >> 8;
00242         ctx->buffer[58] = ctx->lo >> 16;
00243         ctx->buffer[59] = ctx->lo >> 24;
00244         ctx->buffer[60] = ctx->hi;
00245         ctx->buffer[61] = ctx->hi >> 8;
00246         ctx->buffer[62] = ctx->hi >> 16;
00247         ctx->buffer[63] = ctx->hi >> 24;
00248 
00249         body(ctx, ctx->buffer, 64);
00250 
00251         result[0] = ctx->a;
00252         result[1] = ctx->a >> 8;
00253         result[2] = ctx->a >> 16;
00254         result[3] = ctx->a >> 24;
00255         result[4] = ctx->b;
00256         result[5] = ctx->b >> 8;
00257         result[6] = ctx->b >> 16;
00258         result[7] = ctx->b >> 24;
00259         result[8] = ctx->c;
00260         result[9] = ctx->c >> 8;
00261         result[10] = ctx->c >> 16;
00262         result[11] = ctx->c >> 24;
00263         result[12] = ctx->d;
00264         result[13] = ctx->d >> 8;
00265         result[14] = ctx->d >> 16;
00266         result[15] = ctx->d >> 24;
00267 
00268         memset(ctx, 0, sizeof(ctx));
00269 }
00270 
00271 /*
00272 #else
00273 #include "struct.h"
00274 #include "common.h"
00275 #endif
00276 */
00284 /*
00285 void DoMD5(unsigned char *mdout, unsigned char *src, unsigned long n)
00286 {
00287 MD5_CTX hash;
00288 
00289         MD5_Init(&hash);
00290         MD5_Update(&hash, src, n);
00291         MD5_Final(mdout, &hash);
00292 }
00293 
00294 */
00295 

Generated on Thu Jul 19 13:36:09 2007 for libv by  doxygen 1.5.1-p1. Thank you, SourceForge.net Logo