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