2 * This code implements the MD4 message-digest algorithm.
3 * "Just the reference implementation, single stage. Hardly "optimized." Though a good bit faster than libssl's MD4, as it isn't doing nearly the same amount of work." - Bitweasil
5 * little bit optimized (or at least attempted) for NTLM (unicode) by neinbrucke
13 /* MD4 Defines as per RFC reference implementation */
14 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
15 #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
16 #define H(x, y, z) ((x) ^ (y) ^ (z))
17 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
18 #define FF(a, b, c, d, x, s) { \
19 (a) += F ((b), (c), (d)) + (x); \
20 (a) = ROTATE_LEFT ((a), (s)); \
22 #define GG(a, b, c, d, x, s) { \
23 (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
24 (a) = ROTATE_LEFT ((a), (s)); \
26 #define HH(a, b, c, d, x, s) { \
27 (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
28 (a) = ROTATE_LEFT ((a), (s)); \
44 void MD4_NEW( unsigned char * pData, int length, unsigned char * pDigest)
46 // access data as 4-byte word
47 #define uData ((UINT4 *)pData)
48 #define uDigest ((UINT4 *)pDigest)
50 // pad word and append bit at appropriate location
51 #define MD4_pad_w0() (0x00000080)
52 #define MD4_pad_w1(data) (((data) & 0x000000FF) | 0x00008000)
53 #define MD4_pad_w2(data) (((data) & 0x0000FFFF) | 0x00800000)
54 #define MD4_pad_w3(data) (((data) & 0x00FFFFFF) | 0x80000000)
56 // For the hash working space
57 //__attribute__((aligned(16))) UINT4 data[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
58 //__declspec(align(16)) UINT4 data[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
59 UINT4 data[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
61 // For the output result
68 data[ 0] = MD4_pad_w0();
75 data[ 0] = MD4_pad_w1(uData[0]);
82 data[ 0] = MD4_pad_w2(uData[0]);
89 data[ 0] = MD4_pad_w3(uData[0]);
97 data[ 1] = MD4_pad_w0();
105 data[ 1] = MD4_pad_w1(uData[1]);
113 data[ 1] = MD4_pad_w2(uData[1]);
121 data[ 1] = MD4_pad_w3(uData[1]);
130 data[ 2] = MD4_pad_w0();
139 data[ 2] = MD4_pad_w1(uData[2]);
148 data[ 2] = MD4_pad_w2(uData[2]);
157 data[ 2] = MD4_pad_w3(uData[2]);
167 data[ 3] = MD4_pad_w0();
177 data[ 3] = MD4_pad_w1(uData[3]);
187 data[ 3] = MD4_pad_w2(uData[3]);
197 data[ 3] = MD4_pad_w3(uData[3]);
205 length = length % 32; // lenght >= 32 not suported
207 int word = length >> 2;
215 switch (length & 0x3) {
218 data[word] = MD4_pad_w0();
223 data[word] = MD4_pad_w1(uData[word]);
228 data[word] = MD4_pad_w2(uData[word]);
233 data[word] = MD4_pad_w3(uData[word]);
238 data[14] = length << 3;
249 FF (a, b, c, d, data[ 0], S11); /* 1 */
250 FF (d, a, b, c, data[ 1], S12); /* 2 */
251 FF (c, d, a, b, data[ 2], S13); /* 3 */
252 FF (b, c, d, a, data[ 3], S14); /* 4 */
253 FF (a, b, c, d, data[ 4], S11); /* 5 */
254 FF (d, a, b, c, data[ 5], S12); /* 6 */
255 FF (c, d, a, b, data[ 6], S13); /* 7 */
256 FF (b, c, d, a, data[ 7], S14); /* 8 */
257 FF (a, b, c, d, 0, S11); /* 9 */
258 FF (d, a, b, c, 0, S12); /* 10 */
259 FF (c, d, a, b, 0, S13); /* 11 */
260 FF (b, c, d, a, 0, S14); /* 12 */
261 FF (a, b, c, d, 0, S11); /* 13 */
262 FF (d, a, b, c, 0, S12); /* 14 */
263 FF (c, d, a, b, data[14], S13); /* 15 */
264 FF (b, c, d, a, 0, S14); /* 16 */
267 GG (a, b, c, d, data[ 0], S21); /* 17 */
268 GG (d, a, b, c, data[ 4], S22); /* 18 */
269 GG (c, d, a, b, 0, S23); /* 19 */
270 GG (b, c, d, a, 0, S24); /* 20 */
271 GG (a, b, c, d, data[ 1], S21); /* 21 */
272 GG (d, a, b, c, data[ 5], S22); /* 22 */
273 GG (c, d, a, b, 0, S23); /* 23 */
274 GG (b, c, d, a, 0, S24); /* 24 */
275 GG (a, b, c, d, data[ 2], S21); /* 25 */
276 GG (d, a, b, c, data[ 6], S22); /* 26 */
277 GG (c, d, a, b, 0, S23); /* 27 */
278 GG (b, c, d, a, data[14], S24); /* 28 */
279 GG (a, b, c, d, data[ 3], S21); /* 29 */
280 GG (d, a, b, c, data[ 7], S22); /* 30 */
281 GG (c, d, a, b, 0, S23); /* 31 */
282 GG (b, c, d, a, 0, S24); /* 32 */
285 HH (a, b, c, d, data[ 0], S31); /* 33 */
286 HH (d, a, b, c, 0, S32); /* 34 */
287 HH (c, d, a, b, data[ 4], S33); /* 35 */
288 HH (b, c, d, a, 0, S34); /* 36 */
289 HH (a, b, c, d, data[ 2], S31); /* 37 */
290 HH (d, a, b, c, 0, S32); /* 38 */
291 HH (c, d, a, b, data[ 6], S33); /* 39 */
292 HH (b, c, d, a, data[14], S34); /* 40 */
293 HH (a, b, c, d, data[ 1], S31); /* 41 */
294 HH (d, a, b, c, 0, S32); /* 42 */
295 HH (c, d, a, b, data[ 5], S33); /* 43 */
296 HH (b, c, d, a, 0, S34); /* 44 */
297 HH (a, b, c, d, data[ 3], S31); /* 45 */
298 HH (d, a, b, c, 0, S32); /* 46 */
299 HH (c, d, a, b, data[ 7], S33); /* 47 */
300 HH (b, c, d, a, 0, S34); /* 48 */
302 // Finally, add initial values, as this is the only pass we make.
314 //void MD4_NEW( unsigned char * pData, int length, unsigned char * pDigest)
316 // // For the hash working space
317 // UINT4 b0,b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15;
319 // // For the output result
339 // // LOAD DATA INTO b0 ... whatever here.
344 // unsigned char in[4];
345 // memcpy(in, pData, length);
348 // UINT4 * pUiIn = (UINT4 *) in;
354 // unsigned char in[4];
355 // memcpy(in, pData, length);
356 // UINT4 * pUiIn = (UINT4 *) in;
363 // unsigned char in[8];
364 // memcpy(in, pData, length);
367 // UINT4 * pUiIn = (UINT4 *) in;
374 // unsigned char in[8];
375 // memcpy(in, pData, length);
376 // UINT4 * pUiIn = (UINT4 *) in;
384 // unsigned char in[12];
385 // memcpy(in, pData, length);
388 // UINT4 * pUiIn = (UINT4 *) in;
396 // unsigned char in[32];
397 // memcpy(in, pData, length);
398 // in[length] = 0x80;
399 // memset(in + length + 1, 0, 32 - length - 1);
400 // UINT4 * pUiIn = (UINT4 *) in;
408 // b7 = pUiIn[7]; // max 14 2byte chars (ntlm)
414 // b14 = length << 3;
422 // FF (a, b, c, d, b0, S11); /* 1 */
423 // FF (d, a, b, c, b1, S12); /* 2 */
424 // FF (c, d, a, b, b2, S13); /* 3 */
425 // FF (b, c, d, a, b3, S14); /* 4 */
426 // FF (a, b, c, d, b4, S11); /* 5 */
427 // FF (d, a, b, c, b5, S12); /* 6 */
428 // FF (c, d, a, b, b6, S13); /* 7 */
429 // FF (b, c, d, a, b7, S14); /* 8 */
430 // FF (a, b, c, d, 0, S11); /* 9 */
431 // FF (d, a, b, c, 0, S12); /* 10 */
432 // FF (c, d, a, b, 0, S13); /* 11 */
433 // FF (b, c, d, a, 0, S14); /* 12 */
434 // FF (a, b, c, d, 0, S11); /* 13 */
435 // FF (d, a, b, c, 0, S12); /* 14 */
436 // FF (c, d, a, b, b14, S13); /* 15 */
437 // FF (b, c, d, a, 0, S14); /* 16 */
440 // GG (a, b, c, d, b0, S21); /* 17 */
441 // GG (d, a, b, c, b4, S22); /* 18 */
442 // GG (c, d, a, b, 0, S23); /* 19 */
443 // GG (b, c, d, a, 0, S24); /* 20 */
444 // GG (a, b, c, d, b1, S21); /* 21 */
445 // GG (d, a, b, c, b5, S22); /* 22 */
446 // GG (c, d, a, b, 0, S23); /* 23 */
447 // GG (b, c, d, a, 0, S24); /* 24 */
448 // GG (a, b, c, d, b2, S21); /* 25 */
449 // GG (d, a, b, c, b6, S22); /* 26 */
450 // GG (c, d, a, b, 0, S23); /* 27 */
451 // GG (b, c, d, a, b14, S24); /* 28 */
452 // GG (a, b, c, d, b3, S21); /* 29 */
453 // GG (d, a, b, c, b7, S22); /* 30 */
454 // GG (c, d, a, b, 0, S23); /* 31 */
455 // GG (b, c, d, a, 0, S24); /* 32 */
458 // HH (a, b, c, d, b0, S31); /* 33 */
459 // HH (d, a, b, c, 0, S32); /* 34 */
460 // HH (c, d, a, b, b4, S33); /* 35 */
461 // HH (b, c, d, a, 0, S34); /* 36 */
462 // HH (a, b, c, d, b2, S31); /* 37 */
463 // HH (d, a, b, c, 0, S32); /* 38 */
464 // HH (c, d, a, b, b6, S33); /* 39 */
465 // HH (b, c, d, a, b14, S34); /* 40 */
466 // HH (a, b, c, d, b1, S31); /* 41 */
467 // HH (d, a, b, c, 0, S32); /* 42 */
468 // HH (c, d, a, b, b5, S33); /* 43 */
469 // HH (b, c, d, a, 0, S34); /* 44 */
470 // HH (a, b, c, d, b3, S31); /* 45 */
471 // HH (d, a, b, c, 0, S32); /* 46 */
472 // HH (c, d, a, b, b7, S33); /* 47 */
473 // HH (b, c, d, a, 0, S34); /* 48 */
475 // // Finally, add initial values, as this is the only pass we make.
481 // UINT4 buf[4] = { a, b, c, d};
482 // memcpy(pDigest, buf, 16);