md5.cpp

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 <ace/config-all.h>
00041 
00042 #include <string.h>
00043 
00044 #include "md5.h"
00045 
00046 /*
00047  * The basic MD5 functions.
00048  *
00049  * F and G are optimized compared to their RFC 1321 definitions for
00050  * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
00051  * implementation.
00052  */
00053 #define F(x, y, z)                      ((z) ^ ((x) & ((y) ^ (z))))
00054 #define G(x, y, z)                      ((y) ^ ((z) & ((x) ^ (y))))
00055 #define H(x, y, z)                      ((x) ^ (y) ^ (z))
00056 #define I(x, y, z)                      ((y) ^ ((x) | ~(z)))
00057 
00058 /*
00059  * The MD5 transformation for all four rounds.
00060  */
00061 #define STEP(f, a, b, c, d, x, t, s) \
00062         (a) += f((b), (c), (d)) + (x) + (t); \
00063         (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
00064         (a) += (b);
00065 
00066 /*
00067  * SET reads 4 input bytes in little-endian byte order and stores them
00068  * in a properly aligned word in host byte order.
00069  *
00070  * The check for little-endian architectures that tolerate unaligned
00071  * memory accesses is just an optimization.  Nothing will break if it
00072  * doesn't work.
00073  */
00074 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
00075 #define SET(n) \
00076         (*(MD5_u32plus *)&ptr[(n) * 4])
00077 #define GET(n) \
00078         SET(n)
00079 #else
00080 #define SET(n) \
00081         (ctx->block[(n)] = \
00082         (MD5_u32plus)ptr[(n) * 4] | \
00083         ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
00084         ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
00085         ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
00086 #define GET(n) \
00087         (ctx->block[(n)])
00088 #endif
00089 
00090 /*
00091  * This processes one or more 64-byte data blocks, but does NOT update
00092  * the bit counters.  There are no alignment requirements.
00093  */
00094 static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
00095 {
00096         const unsigned char *ptr;
00097         MD5_u32plus a, b, c, d;
00098         MD5_u32plus saved_a, saved_b, saved_c, saved_d;
00099 
00100         ptr = (const unsigned char *) data;
00101 
00102         a = ctx->a;
00103         b = ctx->b;
00104         c = ctx->c;
00105         d = ctx->d;
00106 
00107         do {
00108                 saved_a = a;
00109                 saved_b = b;
00110                 saved_c = c;
00111                 saved_d = d;
00112 
00113 /* Round 1 */
00114                 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
00115                 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
00116                 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
00117                 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
00118                 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
00119                 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
00120                 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
00121                 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
00122                 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
00123                 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
00124                 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
00125                 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
00126                 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
00127                 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
00128                 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
00129                 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
00130 
00131 /* Round 2 */
00132                 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
00133                 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
00134                 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
00135                 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
00136                 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
00137                 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
00138                 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
00139                 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
00140                 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
00141                 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
00142                 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
00143                 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
00144                 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
00145                 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
00146                 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
00147                 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
00148 
00149 /* Round 3 */
00150                 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
00151                 STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
00152                 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
00153                 STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
00154                 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
00155                 STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
00156                 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
00157                 STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
00158                 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
00159                 STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
00160                 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
00161                 STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
00162                 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
00163                 STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
00164                 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
00165                 STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
00166 
00167 /* Round 4 */
00168                 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
00169                 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
00170                 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
00171                 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
00172                 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
00173                 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
00174                 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
00175                 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
00176                 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
00177                 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
00178                 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
00179                 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
00180                 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
00181                 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
00182                 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
00183                 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
00184 
00185                 a += saved_a;
00186                 b += saved_b;
00187                 c += saved_c;
00188                 d += saved_d;
00189 
00190                 ptr += 64;
00191         } while (size -= 64);
00192 
00193         ctx->a = a;
00194         ctx->b = b;
00195         ctx->c = c;
00196         ctx->d = d;
00197 
00198         return ptr;
00199 }
00200 
00201 void MD5_Init(MD5_CTX *ctx)
00202 {
00203         ctx->a = 0x67452301;
00204         ctx->b = 0xefcdab89;
00205         ctx->c = 0x98badcfe;
00206         ctx->d = 0x10325476;
00207 
00208         ctx->lo = 0;
00209         ctx->hi = 0;
00210 }
00211 
00212 void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
00213 {
00214         MD5_u32plus saved_lo;
00215         unsigned long used;
00216 
00217         saved_lo = ctx->lo;
00218         if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
00219                 ctx->hi++;
00220         ctx->hi += size >> 29;
00221 
00222         used = saved_lo & 0x3f;
00223 
00224         if (used) {
00225                 unsigned long free = 64 - used;
00226 
00227                 if (size < free) {
00228                         memcpy(&ctx->buffer[used], data, size);
00229                         return;
00230                 }
00231 
00232                 memcpy(&ctx->buffer[used], data, free);
00233                 data = (unsigned char *)data + free;
00234                 size -= free;
00235                 body(ctx, ctx->buffer, 64);
00236         }
00237 
00238         if (size >= 64) {
00239                 data = body(ctx, data, size & ~(unsigned long)0x3f);
00240                 size &= 0x3f;
00241         }
00242 
00243         memcpy(ctx->buffer, data, size);
00244 }
00245 
00246 void MD5_Final(unsigned char *result, MD5_CTX *ctx)
00247 {
00248         unsigned long used, free;
00249 
00250         used = ctx->lo & 0x3f;
00251 
00252         ctx->buffer[used++] = 0x80;
00253 
00254         free = 64 - used;
00255 
00256         if (free < 8) {
00257                 memset(&ctx->buffer[used], 0, free);
00258                 body(ctx, ctx->buffer, 64);
00259                 used = 0;
00260                 free = 64;
00261         }
00262 
00263         memset(&ctx->buffer[used], 0, free - 8);
00264 
00265         ctx->lo <<= 3;
00266         ctx->buffer[56] = ctx->lo;
00267         ctx->buffer[57] = ctx->lo >> 8;
00268         ctx->buffer[58] = ctx->lo >> 16;
00269         ctx->buffer[59] = ctx->lo >> 24;
00270         ctx->buffer[60] = ctx->hi;
00271         ctx->buffer[61] = ctx->hi >> 8;
00272         ctx->buffer[62] = ctx->hi >> 16;
00273         ctx->buffer[63] = ctx->hi >> 24;
00274 
00275         body(ctx, ctx->buffer, 64);
00276 
00277         result[0] = ctx->a;
00278         result[1] = ctx->a >> 8;
00279         result[2] = ctx->a >> 16;
00280         result[3] = ctx->a >> 24;
00281         result[4] = ctx->b;
00282         result[5] = ctx->b >> 8;
00283         result[6] = ctx->b >> 16;
00284         result[7] = ctx->b >> 24;
00285         result[8] = ctx->c;
00286         result[9] = ctx->c >> 8;
00287         result[10] = ctx->c >> 16;
00288         result[11] = ctx->c >> 24;
00289         result[12] = ctx->d;
00290         result[13] = ctx->d >> 8;
00291         result[14] = ctx->d >> 16;
00292         result[15] = ctx->d >> 24;
00293 
00294         memset(ctx, 0, sizeof(*ctx));
00295 }
00296 
00297 #endif

Generated on Fri Feb 12 20:05:23 2016 for OpenDDS by  doxygen 1.4.7