| 1 | /* | 
| 2 |  * MD4 (RFC-1320) message digest. | 
| 3 |  * Modified from MD5 code by Andrey Panin <pazke@donpac.ru> | 
| 4 |  * | 
| 5 |  * Written by Solar Designer <solar@openwall.com> in 2001, and placed in | 
| 6 |  * the public domain.  There's absolutely no warranty. | 
| 7 |  * | 
| 8 |  * This differs from Colin Plumb's older public domain implementation in | 
| 9 |  * that no 32-bit integer data type is required, there's no compile-time | 
| 10 |  * endianness configuration, and the function prototypes match OpenSSL's. | 
| 11 |  * The primary goals are portability and ease of use. | 
| 12 |  * | 
| 13 |  * This implementation is meant to be fast, but not as fast as possible. | 
| 14 |  * Some known optimizations are not included to reduce source code size | 
| 15 |  * and avoid compile-time configuration. | 
| 16 |  */ | 
| 17 |  | 
| 18 | #include "md4.h" | 
| 19 |  | 
| 20 | #include <string.h> | 
| 21 |  | 
| 22 | QT_BEGIN_NAMESPACE | 
| 23 |  | 
| 24 | /* | 
| 25 |  * The basic MD4 functions. | 
| 26 |  */ | 
| 27 | #define F(x, y, z)	((z) ^ ((x) & ((y) ^ (z)))) | 
| 28 | #define G(x, y, z)	(((x) & (y)) | ((x) & (z)) | ((y) & (z))) | 
| 29 | #define H(x, y, z)	((x) ^ (y) ^ (z)) | 
| 30 |  | 
| 31 | /* | 
| 32 |  * The MD4 transformation for all four rounds. | 
| 33 |  */ | 
| 34 | #define STEP(f, a, b, c, d, x, s) \ | 
| 35 | 	(a) += f((b), (c), (d)) + (x);	 \ | 
| 36 | 	(a) = ((a) << (s)) | ((a) >> (32 - (s))) | 
| 37 |  | 
| 38 |  | 
| 39 | /* | 
| 40 |  * SET reads 4 input bytes in little-endian byte order and stores them | 
| 41 |  * in a properly aligned word in host byte order. | 
| 42 |  * | 
| 43 |  * The check for little-endian architectures which tolerate unaligned | 
| 44 |  * memory accesses is just an optimization.  Nothing will break if it | 
| 45 |  * doesn't work. | 
| 46 |  */ | 
| 47 | #if defined(__i386__) || defined(__x86_64__) | 
| 48 | #define SET(n) \ | 
| 49 | 	(*(const quint32 *)&ptr[(n) * 4]) | 
| 50 | #define GET(n) \ | 
| 51 | 	SET(n) | 
| 52 | #else | 
| 53 | #define SET(n) \ | 
| 54 | 	(ctx->block[(n)] = \ | 
| 55 | 	(quint32)ptr[(n) * 4] | \ | 
| 56 | 	((quint32)ptr[(n) * 4 + 1] << 8) | \ | 
| 57 | 	((quint32)ptr[(n) * 4 + 2] << 16) | \ | 
| 58 | 	((quint32)ptr[(n) * 4 + 3] << 24)) | 
| 59 | #define GET(n) \ | 
| 60 | 	(ctx->block[(n)]) | 
| 61 | #endif | 
| 62 |  | 
| 63 | /* | 
| 64 |  * This processes one or more 64-byte data blocks, but does NOT update | 
| 65 |  * the bit counters.  There're no alignment requirements. | 
| 66 |  */ | 
| 67 | static const unsigned char *body(struct md4_context *ctx, const unsigned char *data, size_t size) | 
| 68 | { | 
| 69 | 	const unsigned char *ptr; | 
| 70 | 	quint32 a, b, c, d; | 
| 71 | 	quint32 saved_a, saved_b, saved_c, saved_d; | 
| 72 |  | 
| 73 | 	ptr = data; | 
| 74 |  | 
| 75 | 	a = ctx->a; | 
| 76 | 	b = ctx->b; | 
| 77 | 	c = ctx->c; | 
| 78 | 	d = ctx->d; | 
| 79 |  | 
| 80 | 	do { | 
| 81 | 		saved_a = a; | 
| 82 | 		saved_b = b; | 
| 83 | 		saved_c = c; | 
| 84 | 		saved_d = d; | 
| 85 |  | 
| 86 | /* Round 1 */ | 
| 87 | 		STEP(F, a, b, c, d, SET( 0),  3); | 
| 88 | 		STEP(F, d, a, b, c, SET( 1),  7); | 
| 89 | 		STEP(F, c, d, a, b, SET( 2), 11); | 
| 90 | 		STEP(F, b, c, d, a, SET( 3), 19); | 
| 91 |  | 
| 92 | 		STEP(F, a, b, c, d, SET( 4),  3); | 
| 93 | 		STEP(F, d, a, b, c, SET( 5),  7); | 
| 94 | 		STEP(F, c, d, a, b, SET( 6), 11); | 
| 95 | 		STEP(F, b, c, d, a, SET( 7), 19); | 
| 96 |  | 
| 97 | 		STEP(F, a, b, c, d, SET( 8),  3); | 
| 98 | 		STEP(F, d, a, b, c, SET( 9),  7); | 
| 99 | 		STEP(F, c, d, a, b, SET(10), 11); | 
| 100 | 		STEP(F, b, c, d, a, SET(11), 19); | 
| 101 |  | 
| 102 | 		STEP(F, a, b, c, d, SET(12),  3); | 
| 103 | 		STEP(F, d, a, b, c, SET(13),  7); | 
| 104 | 		STEP(F, c, d, a, b, SET(14), 11); | 
| 105 | 		STEP(F, b, c, d, a, SET(15), 19); | 
| 106 | /* Round 2 */ | 
| 107 | 		STEP(G, a, b, c, d, GET( 0) + 0x5A827999,  3); | 
| 108 | 		STEP(G, d, a, b, c, GET( 4) + 0x5A827999,  5); | 
| 109 | 		STEP(G, c, d, a, b, GET( 8) + 0x5A827999,  9); | 
| 110 | 		STEP(G, b, c, d, a, GET(12) + 0x5A827999, 13); | 
| 111 |  | 
| 112 | 		STEP(G, a, b, c, d, GET( 1) + 0x5A827999,  3); | 
| 113 | 		STEP(G, d, a, b, c, GET( 5) + 0x5A827999,  5); | 
| 114 | 		STEP(G, c, d, a, b, GET( 9) + 0x5A827999,  9); | 
| 115 | 		STEP(G, b, c, d, a, GET(13) + 0x5A827999, 13); | 
| 116 |  | 
| 117 | 		STEP(G, a, b, c, d, GET( 2) + 0x5A827999,  3); | 
| 118 | 		STEP(G, d, a, b, c, GET( 6) + 0x5A827999,  5); | 
| 119 | 		STEP(G, c, d, a, b, GET(10) + 0x5A827999,  9); | 
| 120 | 		STEP(G, b, c, d, a, GET(14) + 0x5A827999, 13); | 
| 121 |  | 
| 122 | 		STEP(G, a, b, c, d, GET( 3) + 0x5A827999,  3); | 
| 123 | 		STEP(G, d, a, b, c, GET( 7) + 0x5A827999,  5); | 
| 124 | 		STEP(G, c, d, a, b, GET(11) + 0x5A827999,  9); | 
| 125 | 		STEP(G, b, c, d, a, GET(15) + 0x5A827999, 13); | 
| 126 | /* Round 3 */ | 
| 127 | 		STEP(H, a, b, c, d, GET( 0) + 0x6ED9EBA1,  3); | 
| 128 | 		STEP(H, d, a, b, c, GET( 8) + 0x6ED9EBA1,  9); | 
| 129 | 		STEP(H, c, d, a, b, GET( 4) + 0x6ED9EBA1, 11); | 
| 130 | 		STEP(H, b, c, d, a, GET(12) + 0x6ED9EBA1, 15); | 
| 131 |  | 
| 132 | 		STEP(H, a, b, c, d, GET( 2) + 0x6ED9EBA1,  3); | 
| 133 | 		STEP(H, d, a, b, c, GET(10) + 0x6ED9EBA1,  9); | 
| 134 | 		STEP(H, c, d, a, b, GET( 6) + 0x6ED9EBA1, 11); | 
| 135 | 		STEP(H, b, c, d, a, GET(14) + 0x6ED9EBA1, 15); | 
| 136 |  | 
| 137 | 		STEP(H, a, b, c, d, GET( 1) + 0x6ED9EBA1,  3); | 
| 138 | 		STEP(H, d, a, b, c, GET( 9) + 0x6ED9EBA1,  9); | 
| 139 | 		STEP(H, c, d, a, b, GET( 5) + 0x6ED9EBA1, 11); | 
| 140 | 		STEP(H, b, c, d, a, GET(13) + 0x6ED9EBA1, 15); | 
| 141 |  | 
| 142 | 		STEP(H, a, b, c, d, GET( 3) + 0x6ED9EBA1,  3); | 
| 143 | 		STEP(H, d, a, b, c, GET(11) + 0x6ED9EBA1,  9); | 
| 144 | 		STEP(H, c, d, a, b, GET( 7) + 0x6ED9EBA1, 11); | 
| 145 | 		STEP(H, b, c, d, a, GET(15) + 0x6ED9EBA1, 15); | 
| 146 |  | 
| 147 | 		a += saved_a; | 
| 148 | 		b += saved_b; | 
| 149 | 		c += saved_c; | 
| 150 | 		d += saved_d; | 
| 151 |  | 
| 152 | 		ptr += 64; | 
| 153 | 	} while (size -= 64); | 
| 154 |  | 
| 155 | 	ctx->a = a; | 
| 156 | 	ctx->b = b; | 
| 157 | 	ctx->c = c; | 
| 158 | 	ctx->d = d; | 
| 159 |  | 
| 160 | 	return ptr; | 
| 161 | } | 
| 162 |  | 
| 163 | static void md4_init(struct md4_context *ctx) | 
| 164 | { | 
| 165 | 	ctx->a = 0x67452301; | 
| 166 | 	ctx->b = 0xefcdab89; | 
| 167 | 	ctx->c = 0x98badcfe; | 
| 168 | 	ctx->d = 0x10325476; | 
| 169 |  | 
| 170 | 	ctx->lo = 0; | 
| 171 | 	ctx->hi = 0; | 
| 172 | } | 
| 173 |  | 
| 174 | static void md4_update(struct md4_context *ctx, const unsigned char *data, size_t size) | 
| 175 | { | 
| 176 | 	/* @UNSAFE */ | 
| 177 | 	quint32 saved_lo; | 
| 178 | 	unsigned long used, free; | 
| 179 |  | 
| 180 | 	saved_lo = ctx->lo; | 
| 181 | 	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) | 
| 182 | 		ctx->hi++; | 
| 183 | 	ctx->hi += (quint32)(size >> 29); | 
| 184 |  | 
| 185 | 	used = saved_lo & 0x3f; | 
| 186 |  | 
| 187 | 	if (used) { | 
| 188 | 		free = 64 - used; | 
| 189 |  | 
| 190 | 		if (size < free) { | 
| 191 | 			memcpy(dest: &ctx->buffer[used], src: data, n: size); | 
| 192 | 			return; | 
| 193 | 		} | 
| 194 |  | 
| 195 | 		memcpy(dest: &ctx->buffer[used], src: data, n: free); | 
| 196 | 		data = (const unsigned char *) data + free; | 
| 197 | 		size -= free; | 
| 198 | 		body(ctx, data: ctx->buffer, size: 64); | 
| 199 | 	} | 
| 200 |  | 
| 201 | 	if (size >= 64) { | 
| 202 | 		data = body(ctx, data, size: size & ~(unsigned long)0x3f); | 
| 203 | 		size &= 0x3f; | 
| 204 | 	} | 
| 205 |  | 
| 206 | 	memcpy(dest: ctx->buffer, src: data, n: size); | 
| 207 | } | 
| 208 |  | 
| 209 | static void md4_final(struct md4_context *ctx, unsigned char result[MD4_RESULTLEN]) | 
| 210 | { | 
| 211 | 	/* @UNSAFE */ | 
| 212 | 	unsigned long used, free; | 
| 213 |  | 
| 214 | 	used = ctx->lo & 0x3f; | 
| 215 |  | 
| 216 | 	ctx->buffer[used++] = 0x80; | 
| 217 |  | 
| 218 | 	free = 64 - used; | 
| 219 |  | 
| 220 | 	if (free < 8) { | 
| 221 | 		memset(s: &ctx->buffer[used], c: 0, n: free); | 
| 222 | 		body(ctx, data: ctx->buffer, size: 64); | 
| 223 | 		used = 0; | 
| 224 | 		free = 64; | 
| 225 | 	} | 
| 226 |  | 
| 227 | 	memset(s: &ctx->buffer[used], c: 0, n: free - 8); | 
| 228 |  | 
| 229 | 	ctx->lo <<= 3; | 
| 230 | 	ctx->buffer[56] = ctx->lo; | 
| 231 | 	ctx->buffer[57] = ctx->lo >> 8; | 
| 232 | 	ctx->buffer[58] = ctx->lo >> 16; | 
| 233 | 	ctx->buffer[59] = ctx->lo >> 24; | 
| 234 | 	ctx->buffer[60] = ctx->hi; | 
| 235 | 	ctx->buffer[61] = ctx->hi >> 8; | 
| 236 | 	ctx->buffer[62] = ctx->hi >> 16; | 
| 237 | 	ctx->buffer[63] = ctx->hi >> 24; | 
| 238 |  | 
| 239 | 	body(ctx, data: ctx->buffer, size: 64); | 
| 240 |  | 
| 241 | 	result[0] = ctx->a; | 
| 242 | 	result[1] = ctx->a >> 8; | 
| 243 | 	result[2] = ctx->a >> 16; | 
| 244 | 	result[3] = ctx->a >> 24; | 
| 245 | 	result[4] = ctx->b; | 
| 246 | 	result[5] = ctx->b >> 8; | 
| 247 | 	result[6] = ctx->b >> 16; | 
| 248 | 	result[7] = ctx->b >> 24; | 
| 249 | 	result[8] = ctx->c; | 
| 250 | 	result[9] = ctx->c >> 8; | 
| 251 | 	result[10] = ctx->c >> 16; | 
| 252 | 	result[11] = ctx->c >> 24; | 
| 253 | 	result[12] = ctx->d; | 
| 254 | 	result[13] = ctx->d >> 8; | 
| 255 | 	result[14] = ctx->d >> 16; | 
| 256 | 	result[15] = ctx->d >> 24; | 
| 257 |  | 
| 258 | 	memset(s: ctx, c: 0, n: sizeof(*ctx)); | 
| 259 | } | 
| 260 |  | 
| 261 | #undef F | 
| 262 | #undef G | 
| 263 | #undef H | 
| 264 |  | 
| 265 | QT_END_NAMESPACE | 
| 266 |  |