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)); \
45 void MD4_NEW( unsigned char * pData, int length, unsigned char * pDigest)
47 // For the hash working space
48 UINT4 b0,b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15;
50 // For the output result
70 // LOAD DATA INTO b0 ... whatever here.
76 memcpy(in, pData, length);
79 UINT4 * pUiIn = (UINT4 *) in;
86 memcpy(in, pData, length);
87 UINT4 * pUiIn = (UINT4 *) in;
95 memcpy(in, pData, length);
98 UINT4 * pUiIn = (UINT4 *) in;
106 memcpy(in, pData, length);
107 UINT4 * pUiIn = (UINT4 *) in;
115 unsigned char in[12];
116 memcpy(in, pData, length);
119 UINT4 * pUiIn = (UINT4 *) in;
127 unsigned char in[32];
128 memcpy(in, pData, length);
130 memset(in + length + 1, 0, 32 - length - 1);
131 UINT4 * pUiIn = (UINT4 *) in;
139 b7 = pUiIn[7]; // max 14 2byte chars (ntlm)
153 FF (a, b, c, d, b0, S11); /* 1 */
154 FF (d, a, b, c, b1, S12); /* 2 */
155 FF (c, d, a, b, b2, S13); /* 3 */
156 FF (b, c, d, a, b3, S14); /* 4 */
157 FF (a, b, c, d, b4, S11); /* 5 */
158 FF (d, a, b, c, b5, S12); /* 6 */
159 FF (c, d, a, b, b6, S13); /* 7 */
160 FF (b, c, d, a, b7, S14); /* 8 */
161 FF (a, b, c, d, 0, S11); /* 9 */
162 FF (d, a, b, c, 0, S12); /* 10 */
163 FF (c, d, a, b, 0, S13); /* 11 */
164 FF (b, c, d, a, 0, S14); /* 12 */
165 FF (a, b, c, d, 0, S11); /* 13 */
166 FF (d, a, b, c, 0, S12); /* 14 */
167 FF (c, d, a, b, b14, S13); /* 15 */
168 FF (b, c, d, a, 0, S14); /* 16 */
171 GG (a, b, c, d, b0, S21); /* 17 */
172 GG (d, a, b, c, b4, S22); /* 18 */
173 GG (c, d, a, b, 0, S23); /* 19 */
174 GG (b, c, d, a, 0, S24); /* 20 */
175 GG (a, b, c, d, b1, S21); /* 21 */
176 GG (d, a, b, c, b5, S22); /* 22 */
177 GG (c, d, a, b, 0, S23); /* 23 */
178 GG (b, c, d, a, 0, S24); /* 24 */
179 GG (a, b, c, d, b2, S21); /* 25 */
180 GG (d, a, b, c, b6, S22); /* 26 */
181 GG (c, d, a, b, 0, S23); /* 27 */
182 GG (b, c, d, a, b14, S24); /* 28 */
183 GG (a, b, c, d, b3, S21); /* 29 */
184 GG (d, a, b, c, b7, S22); /* 30 */
185 GG (c, d, a, b, 0, S23); /* 31 */
186 GG (b, c, d, a, 0, S24); /* 32 */
189 HH (a, b, c, d, b0, S31); /* 33 */
190 HH (d, a, b, c, 0, S32); /* 34 */
191 HH (c, d, a, b, b4, S33); /* 35 */
192 HH (b, c, d, a, 0, S34); /* 36 */
193 HH (a, b, c, d, b2, S31); /* 37 */
194 HH (d, a, b, c, 0, S32); /* 38 */
195 HH (c, d, a, b, b6, S33); /* 39 */
196 HH (b, c, d, a, b14, S34); /* 40 */
197 HH (a, b, c, d, b1, S31); /* 41 */
198 HH (d, a, b, c, 0, S32); /* 42 */
199 HH (c, d, a, b, b5, S33); /* 43 */
200 HH (b, c, d, a, 0, S34); /* 44 */
201 HH (a, b, c, d, b3, S31); /* 45 */
202 HH (d, a, b, c, 0, S32); /* 46 */
203 HH (c, d, a, b, b7, S33); /* 47 */
204 HH (b, c, d, a, 0, S34); /* 48 */
206 // Finally, add initial values, as this is the only pass we make.
212 UINT4 buf[4] = { a, b, c, d};
213 memcpy(pDigest, buf, 16);