masqmail-0.2

annotate src/md5/md5.c @ 162:52c82d755215

replaced the MD5 implementation with the one of Solar Designer Until now, the sample code of RFC 1321 was used. It had an ugly license. Now we use the implementation of Solar Designer, which is in the Public Domain. http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
author meillo@marmaro.de
date Sun, 18 Jul 2010 22:01:04 +0200
parents
children
rev   line source
meillo@162 1 /*
meillo@162 2 * This is an OpenSSL-compatible implementation of the RSA Data Security,
meillo@162 3 * Inc. MD5 Message-Digest Algorithm (RFC 1321).
meillo@162 4 *
meillo@162 5 * Written by Solar Designer <solar at openwall.com> in 2001, and placed
meillo@162 6 * in the public domain. There's absolutely no warranty.
meillo@162 7 *
meillo@162 8 * This differs from Colin Plumb's older public domain implementation in
meillo@162 9 * that no 32-bit integer data type is required, there's no compile-time
meillo@162 10 * endianness configuration, and the function prototypes match OpenSSL's.
meillo@162 11 * The primary goals are portability and ease of use.
meillo@162 12 *
meillo@162 13 * This implementation is meant to be fast, but not as fast as possible.
meillo@162 14 * Some known optimizations are not included to reduce source code size
meillo@162 15 * and avoid compile-time configuration.
meillo@162 16 */
meillo@162 17
meillo@162 18 #ifndef HAVE_OPENSSL
meillo@162 19
meillo@162 20 #include <string.h>
meillo@162 21
meillo@162 22 #include "md5.h"
meillo@162 23
meillo@162 24 /*
meillo@162 25 * The basic MD5 functions.
meillo@162 26 *
meillo@162 27 * F and G are optimized compared to their RFC 1321 definitions for
meillo@162 28 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
meillo@162 29 * implementation.
meillo@162 30 */
meillo@162 31 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
meillo@162 32 #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
meillo@162 33 #define H(x, y, z) ((x) ^ (y) ^ (z))
meillo@162 34 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
meillo@162 35
meillo@162 36 /*
meillo@162 37 * The MD5 transformation for all four rounds.
meillo@162 38 */
meillo@162 39 #define STEP(f, a, b, c, d, x, t, s) \
meillo@162 40 (a) += f((b), (c), (d)) + (x) + (t); \
meillo@162 41 (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
meillo@162 42 (a) += (b);
meillo@162 43
meillo@162 44 /*
meillo@162 45 * SET reads 4 input bytes in little-endian byte order and stores them
meillo@162 46 * in a properly aligned word in host byte order.
meillo@162 47 *
meillo@162 48 * The check for little-endian architectures that tolerate unaligned
meillo@162 49 * memory accesses is just an optimization. Nothing will break if it
meillo@162 50 * doesn't work.
meillo@162 51 */
meillo@162 52 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
meillo@162 53 #define SET(n) \
meillo@162 54 (*(MD5_u32plus *)&ptr[(n) * 4])
meillo@162 55 #define GET(n) \
meillo@162 56 SET(n)
meillo@162 57 #else
meillo@162 58 #define SET(n) \
meillo@162 59 (ctx->block[(n)] = \
meillo@162 60 (MD5_u32plus)ptr[(n) * 4] | \
meillo@162 61 ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
meillo@162 62 ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
meillo@162 63 ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
meillo@162 64 #define GET(n) \
meillo@162 65 (ctx->block[(n)])
meillo@162 66 #endif
meillo@162 67
meillo@162 68 /*
meillo@162 69 * This processes one or more 64-byte data blocks, but does NOT update
meillo@162 70 * the bit counters. There are no alignment requirements.
meillo@162 71 */
meillo@162 72 static void *body(MD5_CTX *ctx, void *data, unsigned long size)
meillo@162 73 {
meillo@162 74 unsigned char *ptr;
meillo@162 75 MD5_u32plus a, b, c, d;
meillo@162 76 MD5_u32plus saved_a, saved_b, saved_c, saved_d;
meillo@162 77
meillo@162 78 ptr = data;
meillo@162 79
meillo@162 80 a = ctx->a;
meillo@162 81 b = ctx->b;
meillo@162 82 c = ctx->c;
meillo@162 83 d = ctx->d;
meillo@162 84
meillo@162 85 do {
meillo@162 86 saved_a = a;
meillo@162 87 saved_b = b;
meillo@162 88 saved_c = c;
meillo@162 89 saved_d = d;
meillo@162 90
meillo@162 91 /* Round 1 */
meillo@162 92 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
meillo@162 93 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
meillo@162 94 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
meillo@162 95 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
meillo@162 96 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
meillo@162 97 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
meillo@162 98 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
meillo@162 99 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
meillo@162 100 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
meillo@162 101 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
meillo@162 102 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
meillo@162 103 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
meillo@162 104 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
meillo@162 105 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
meillo@162 106 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
meillo@162 107 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
meillo@162 108
meillo@162 109 /* Round 2 */
meillo@162 110 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
meillo@162 111 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
meillo@162 112 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
meillo@162 113 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
meillo@162 114 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
meillo@162 115 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
meillo@162 116 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
meillo@162 117 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
meillo@162 118 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
meillo@162 119 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
meillo@162 120 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
meillo@162 121 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
meillo@162 122 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
meillo@162 123 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
meillo@162 124 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
meillo@162 125 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
meillo@162 126
meillo@162 127 /* Round 3 */
meillo@162 128 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
meillo@162 129 STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
meillo@162 130 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
meillo@162 131 STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
meillo@162 132 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
meillo@162 133 STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
meillo@162 134 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
meillo@162 135 STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
meillo@162 136 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
meillo@162 137 STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
meillo@162 138 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
meillo@162 139 STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
meillo@162 140 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
meillo@162 141 STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
meillo@162 142 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
meillo@162 143 STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
meillo@162 144
meillo@162 145 /* Round 4 */
meillo@162 146 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
meillo@162 147 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
meillo@162 148 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
meillo@162 149 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
meillo@162 150 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
meillo@162 151 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
meillo@162 152 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
meillo@162 153 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
meillo@162 154 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
meillo@162 155 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
meillo@162 156 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
meillo@162 157 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
meillo@162 158 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
meillo@162 159 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
meillo@162 160 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
meillo@162 161 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
meillo@162 162
meillo@162 163 a += saved_a;
meillo@162 164 b += saved_b;
meillo@162 165 c += saved_c;
meillo@162 166 d += saved_d;
meillo@162 167
meillo@162 168 ptr += 64;
meillo@162 169 } while (size -= 64);
meillo@162 170
meillo@162 171 ctx->a = a;
meillo@162 172 ctx->b = b;
meillo@162 173 ctx->c = c;
meillo@162 174 ctx->d = d;
meillo@162 175
meillo@162 176 return ptr;
meillo@162 177 }
meillo@162 178
meillo@162 179 void MD5_Init(MD5_CTX *ctx)
meillo@162 180 {
meillo@162 181 ctx->a = 0x67452301;
meillo@162 182 ctx->b = 0xefcdab89;
meillo@162 183 ctx->c = 0x98badcfe;
meillo@162 184 ctx->d = 0x10325476;
meillo@162 185
meillo@162 186 ctx->lo = 0;
meillo@162 187 ctx->hi = 0;
meillo@162 188 }
meillo@162 189
meillo@162 190 void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
meillo@162 191 {
meillo@162 192 MD5_u32plus saved_lo;
meillo@162 193 unsigned long used, free;
meillo@162 194
meillo@162 195 saved_lo = ctx->lo;
meillo@162 196 if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
meillo@162 197 ctx->hi++;
meillo@162 198 ctx->hi += size >> 29;
meillo@162 199
meillo@162 200 used = saved_lo & 0x3f;
meillo@162 201
meillo@162 202 if (used) {
meillo@162 203 free = 64 - used;
meillo@162 204
meillo@162 205 if (size < free) {
meillo@162 206 memcpy(&ctx->buffer[used], data, size);
meillo@162 207 return;
meillo@162 208 }
meillo@162 209
meillo@162 210 memcpy(&ctx->buffer[used], data, free);
meillo@162 211 data = (unsigned char *)data + free;
meillo@162 212 size -= free;
meillo@162 213 body(ctx, ctx->buffer, 64);
meillo@162 214 }
meillo@162 215
meillo@162 216 if (size >= 64) {
meillo@162 217 data = body(ctx, data, size & ~(unsigned long)0x3f);
meillo@162 218 size &= 0x3f;
meillo@162 219 }
meillo@162 220
meillo@162 221 memcpy(ctx->buffer, data, size);
meillo@162 222 }
meillo@162 223
meillo@162 224 void MD5_Final(unsigned char *result, MD5_CTX *ctx)
meillo@162 225 {
meillo@162 226 unsigned long used, free;
meillo@162 227
meillo@162 228 used = ctx->lo & 0x3f;
meillo@162 229
meillo@162 230 ctx->buffer[used++] = 0x80;
meillo@162 231
meillo@162 232 free = 64 - used;
meillo@162 233
meillo@162 234 if (free < 8) {
meillo@162 235 memset(&ctx->buffer[used], 0, free);
meillo@162 236 body(ctx, ctx->buffer, 64);
meillo@162 237 used = 0;
meillo@162 238 free = 64;
meillo@162 239 }
meillo@162 240
meillo@162 241 memset(&ctx->buffer[used], 0, free - 8);
meillo@162 242
meillo@162 243 ctx->lo <<= 3;
meillo@162 244 ctx->buffer[56] = ctx->lo;
meillo@162 245 ctx->buffer[57] = ctx->lo >> 8;
meillo@162 246 ctx->buffer[58] = ctx->lo >> 16;
meillo@162 247 ctx->buffer[59] = ctx->lo >> 24;
meillo@162 248 ctx->buffer[60] = ctx->hi;
meillo@162 249 ctx->buffer[61] = ctx->hi >> 8;
meillo@162 250 ctx->buffer[62] = ctx->hi >> 16;
meillo@162 251 ctx->buffer[63] = ctx->hi >> 24;
meillo@162 252
meillo@162 253 body(ctx, ctx->buffer, 64);
meillo@162 254
meillo@162 255 result[0] = ctx->a;
meillo@162 256 result[1] = ctx->a >> 8;
meillo@162 257 result[2] = ctx->a >> 16;
meillo@162 258 result[3] = ctx->a >> 24;
meillo@162 259 result[4] = ctx->b;
meillo@162 260 result[5] = ctx->b >> 8;
meillo@162 261 result[6] = ctx->b >> 16;
meillo@162 262 result[7] = ctx->b >> 24;
meillo@162 263 result[8] = ctx->c;
meillo@162 264 result[9] = ctx->c >> 8;
meillo@162 265 result[10] = ctx->c >> 16;
meillo@162 266 result[11] = ctx->c >> 24;
meillo@162 267 result[12] = ctx->d;
meillo@162 268 result[13] = ctx->d >> 8;
meillo@162 269 result[14] = ctx->d >> 16;
meillo@162 270 result[15] = ctx->d >> 24;
meillo@162 271
meillo@162 272 memset(ctx, 0, sizeof(*ctx));
meillo@162 273 }
meillo@162 274
meillo@162 275 #endif