2 * Fast implementation of the MD5 message-digest algorithm as per RFC
3 * (see http://tools.ietf.org/html/rfc1321)
5 * Author: Joao Inacio <jcinacio at gmail.com>
6 * License: Use and share as you wish at your own risk, please keep this header ;)
9 * - For lengths < 16, transformation steps are "unrolled" using macros/defines
10 * - Constants used whenever possible, it's the compiler's job to sort them out
11 * - Padding is done on 4-byte words, and memory copied as last resort.
15 typedef unsigned int UINT4;
18 /* MD5 defines as per RFC reference implementation */
20 #define AC1 0xd76aa478
21 #define AC2 0xe8c7b756
22 #define AC3 0x242070db
23 #define AC4 0xc1bdceee
24 #define AC5 0xf57c0faf
25 #define AC6 0x4787c62a
26 #define AC7 0xa8304613
27 #define AC8 0xfd469501
28 #define AC9 0x698098d8
29 #define AC10 0x8b44f7af
30 #define AC11 0xffff5bb1
31 #define AC12 0x895cd7be
32 #define AC13 0x6b901122
33 #define AC14 0xfd987193
34 #define AC15 0xa679438e
35 #define AC16 0x49b40821
36 #define AC17 0xf61e2562
37 #define AC18 0xc040b340
38 #define AC19 0x265e5a51
39 #define AC20 0xe9b6c7aa
40 #define AC21 0xd62f105d
41 #define AC22 0x02441453
42 #define AC23 0xd8a1e681
43 #define AC24 0xe7d3fbc8
44 #define AC25 0x21e1cde6
45 #define AC26 0xc33707d6
46 #define AC27 0xf4d50d87
47 #define AC28 0x455a14ed
48 #define AC29 0xa9e3e905
49 #define AC30 0xfcefa3f8
50 #define AC31 0x676f02d9
51 #define AC32 0x8d2a4c8a
52 #define AC33 0xfffa3942
53 #define AC34 0x8771f681
54 #define AC35 0x6d9d6122
55 #define AC36 0xfde5380c
56 #define AC37 0xa4beea44
57 #define AC38 0x4bdecfa9
58 #define AC39 0xf6bb4b60
59 #define AC40 0xbebfbc70
60 #define AC41 0x289b7ec6
61 #define AC42 0xeaa127fa
62 #define AC43 0xd4ef3085
63 #define AC44 0x04881d05
64 #define AC45 0xd9d4d039
65 #define AC46 0xe6db99e5
66 #define AC47 0x1fa27cf8
67 #define AC48 0xc4ac5665
68 #define AC49 0xf4292244
69 #define AC50 0x432aff97
70 #define AC51 0xab9423a7
71 #define AC52 0xfc93a039
72 #define AC53 0x655b59c3
73 #define AC54 0x8f0ccc92
74 #define AC55 0xffeff47d
75 #define AC56 0x85845dd1
76 #define AC57 0x6fa87e4f
77 #define AC58 0xfe2ce6e0
78 #define AC59 0xa3014314
79 #define AC60 0x4e0811a1
80 #define AC61 0xf7537e82
81 #define AC62 0xbd3af235
82 #define AC63 0x2ad7d2bb
83 #define AC64 0xeb86d391
102 #define Ca 0x67452301
103 #define Cb 0xefcdab89
104 #define Cc 0x98badcfe
105 #define Cd 0x10325476
108 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
109 #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
110 //#define G(x, y, z) F((z), (x), (y))
111 #define H(x, y, z) ((x) ^ (y) ^ (z))
112 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
114 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
117 #define MD5STEP(f, a, b, c, d, AC, x, s) { \
118 (a) += f ((b), (c), (d)); \
120 (a) = ROTATE_LEFT ((a), (s)); \
124 // full MD5 transformation
125 #define MD5_steps(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { \
127 MD5STEP(F, a, b, c, d, AC1, w0, S11);\
128 MD5STEP(F, d, a, b, c, AC2, w1, S12);\
129 MD5STEP(F, c, d, a, b, AC3, w2, S13);\
130 MD5STEP(F, b, c, d, a, AC4, w3, S14);\
131 MD5STEP(F, a, b, c, d, AC5, w4, S11);\
132 MD5STEP(F, d, a, b, c, AC6, w5, S12);\
133 MD5STEP(F, c, d, a, b, AC7, w6, S13);\
134 MD5STEP(F, b, c, d, a, AC8, w7, S14);\
135 MD5STEP(F, a, b, c, d, AC9, w8, S11);\
136 MD5STEP(F, d, a, b, c, AC10, w9, S12);\
137 MD5STEP(F, c, d, a, b, AC11, w10, S13);\
138 MD5STEP(F, b, c, d, a, AC12, w11, S14);\
139 MD5STEP(F, a, b, c, d, AC13, w12, S11);\
140 MD5STEP(F, d, a, b, c, AC14, w13, S12);\
141 MD5STEP(F, c, d, a, b, AC15, w14, S13);\
142 MD5STEP(F, b, c, d, a, AC16, w15, S14);\
144 MD5STEP(G, a, b, c, d, AC17, w1, S21);\
145 MD5STEP(G, d, a, b, c, AC18, w6, S22);\
146 MD5STEP(G, c, d, a, b, AC19, w11, S23);\
147 MD5STEP(G, b, c, d, a, AC20, w0, S24);\
148 MD5STEP(G, a, b, c, d, AC21, w5, S21);\
149 MD5STEP(G, d, a, b, c, AC22, w10, S22);\
150 MD5STEP(G, c, d, a, b, AC23, w15, S23);\
151 MD5STEP(G, b, c, d, a, AC24, w4, S24);\
152 MD5STEP(G, a, b, c, d, AC25, w9, S21);\
153 MD5STEP(G, d, a, b, c, AC26, w14, S22);\
154 MD5STEP(G, c, d, a, b, AC27, w3, S23);\
155 MD5STEP(G, b, c, d, a, AC28, w8, S24);\
156 MD5STEP(G, a, b, c, d, AC29, w13, S21);\
157 MD5STEP(G, d, a, b, c, AC30, w2, S22);\
158 MD5STEP(G, c, d, a, b, AC31, w7, S23);\
159 MD5STEP(G, b, c, d, a, AC32, w12, S24);\
161 MD5STEP(H, a, b, c, d, AC33, w5, S31);\
162 MD5STEP(H, d, a, b, c, AC34, w8, S32);\
163 MD5STEP(H, c, d, a, b, AC35, w11, S33);\
164 MD5STEP(H, b, c, d, a, AC36, w14, S34);\
165 MD5STEP(H, a, b, c, d, AC37, w1, S31);\
166 MD5STEP(H, d, a, b, c, AC38, w4, S32);\
167 MD5STEP(H, c, d, a, b, AC39, w7, S33);\
168 MD5STEP(H, b, c, d, a, AC40, w10, S34);\
169 MD5STEP(H, a, b, c, d, AC41, w13, S31);\
170 MD5STEP(H, d, a, b, c, AC42, w0, S32);\
171 MD5STEP(H, c, d, a, b, AC43, w3, S33);\
172 MD5STEP(H, b, c, d, a, AC44, w6, S34);\
173 MD5STEP(H, a, b, c, d, AC45, w9, S31);\
174 MD5STEP(H, d, a, b, c, AC46, w12, S32);\
175 MD5STEP(H, c, d, a, b, AC47, w15, S33);\
176 MD5STEP(H, b, c, d, a, AC48, w2, S34);\
178 MD5STEP(I, a, b, c, d, AC49, w0, S41);\
179 MD5STEP(I, d, a, b, c, AC50, w7, S42);\
180 MD5STEP(I, c, d, a, b, AC51, w14, S43);\
181 MD5STEP(I, b, c, d, a, AC52, w5, S44);\
182 MD5STEP(I, a, b, c, d, AC53, w12, S41);\
183 MD5STEP(I, d, a, b, c, AC54, w3, S42);\
184 MD5STEP(I, c, d, a, b, AC55, w10, S43);\
185 MD5STEP(I, b, c, d, a, AC56, w1, S44);\
186 MD5STEP(I, a, b, c, d, AC57, w8, S41);\
187 MD5STEP(I, d, a, b, c, AC58, w15, S42);\
188 MD5STEP(I, c, d, a, b, AC59, w6, S43);\
189 MD5STEP(I, b, c, d, a, AC60, w13, S44);\
190 MD5STEP(I, a, b, c, d, AC61, w4, S41);\
191 MD5STEP(I, d, a, b, c, AC62, w11, S42);\
192 MD5STEP(I, c, d, a, b, AC63, w2, S43);\
193 MD5STEP(I, b, c, d, a, AC64, w9, S44);\
197 #define MD5_transform_add(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { \
199 a = wOut[0]; b = wOut[1]; c = wOut[2]; d = wOut[3];\
201 MD5_steps(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15);\
203 wOut[0] += a; wOut[1] += b; wOut[2] += c; wOut[3] += d;\
207 #define MD5_transform_single(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { \
209 a = CC[0]; b=CC[1]; c=CC[2]; d=CC[3];\
211 MD5_steps(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15);\
213 wOut[0] = a+Ca; wOut[1] = b+Cb; wOut[2] = c+Cc; wOut[3] = d+Cd;\
217 #define MD5_transform_16(w0, w1, w2, w3, w14) \
218 MD5_transform_single(w0, w1, w2, w3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, w14, 0);
221 // pad word and append 0x80 at appropriate location
222 #define MD5_pad_w0() (0x00000080)
223 #define MD5_pad_w1(data) (((data) & 0x000000FF) | 0x00008000)
224 #define MD5_pad_w2(data) (((data) & 0x0000FFFF) | 0x00800000)
225 #define MD5_pad_w3(data) (((data) & 0x00FFFFFF) | 0x80000000)
229 static inline UINT4 MD5_pad_w1(UINT4 data)
232 "movb %%al, %%cl \n\t"
234 "orb $128, %%ah \n\t"
235 "movb %%cl, %%al \n\t"
246 static inline UINT4 MD5_pad_w3(UINT4 data)
250 "movb $128, %%al \n\t"
261 static inline void MD5_copy_pad_block(UINT4 *dData, UINT4 *wIn, int blocklen, int len)
266 for (cl = 0; cl < blocklen; cl++)
270 switch (len & 0x03) {
272 dData[cl] = MD5_pad_w0();
275 dData[cl] = MD5_pad_w1(wIn[cl]);
278 dData[cl] = MD5_pad_w2(wIn[cl]);
281 dData[cl] = MD5_pad_w3(wIn[cl]);
285 for (cl++; cl < 14; cl++)
288 dData[cl++] = (len << 3);
289 dData[cl] = (len >> 29);
292 // fast initializer array
293 //__attribute__((aligned(16)))
294 //__declspec(align(16))
295 static const UINT4 CC[4] = {Ca, Cb, Cc, Cd};
303 void fast_MD5(unsigned char *pData, int len, unsigned char *pDigest)
305 #define wIn ((UINT4 *)pData)
306 #define wOut ((UINT4 *)pDigest)
315 MD5_transform_16(MD5_pad_w0(), 0, 0, 0, 8*0);
318 MD5_transform_16(MD5_pad_w1(wIn[0]), 0, 0, 0, 8*1);
321 MD5_transform_16(MD5_pad_w2(wIn[0]), 0, 0, 0, 8*2);
324 MD5_transform_16(MD5_pad_w3(wIn[0]), 0, 0, 0, 8*3);
327 MD5_transform_16(wIn[0], MD5_pad_w0(), 0, 0, 8*4);
330 MD5_transform_16(wIn[0], MD5_pad_w1(wIn[1]), 0, 0, 8*5);
333 MD5_transform_16(wIn[0], MD5_pad_w2(wIn[1]), 0, 0, 8*6);
336 MD5_transform_16(wIn[0], MD5_pad_w3(wIn[1]), 0, 0, 8*7);
339 MD5_transform_16(wIn[0], wIn[1], MD5_pad_w0(), 0, 8*8);
342 MD5_transform_16(wIn[0], wIn[1], MD5_pad_w1(wIn[2]), 0, 8*9);
345 MD5_transform_16(wIn[0], wIn[1], MD5_pad_w2(wIn[2]), 0, 8*10);
348 MD5_transform_16(wIn[0], wIn[1], MD5_pad_w3(wIn[2]), 0, 8*11);
351 MD5_transform_16(wIn[0], wIn[1], wIn[2], MD5_pad_w0(), 8*12);
354 MD5_transform_16(wIn[0], wIn[1], wIn[2], MD5_pad_w1(wIn[3]), 8*13);
357 MD5_transform_16(wIn[0], wIn[1], wIn[2], MD5_pad_w2(wIn[3]), 8*14)
360 MD5_transform_16(wIn[0], wIn[1], wIn[2], MD5_pad_w3(wIn[3]), 8*15)
364 // data block used for padding
370 MD5_copy_pad_block(dData, wIn, (len >> 2), len);
372 // redefine data input, point to padded data
376 MD5_transform_single (
377 wIn[ 0], wIn[ 1], wIn[ 2], wIn[ 3], wIn[ 4], wIn[ 5], wIn[ 6], wIn[ 7],
378 wIn[ 8], wIn[ 9], wIn[10], wIn[11], wIn[12], wIn[13], wIn[14], wIn[15]
386 #define wIn ((UINT4 *)pData)
391 // init digest for long lens
392 wOut[0] = Ca; wOut[1] = Cb; wOut[2] = Cc; wOut[3] = Cd;
395 // Process 64-byte chunks
397 wIn[ 0], wIn[ 1], wIn[ 2], wIn[ 3], wIn[ 4], wIn[ 5], wIn[ 6], wIn[ 7],
398 wIn[ 8], wIn[ 9], wIn[10], wIn[11], wIn[12], wIn[13], wIn[14], wIn[15]
406 // Process > 56-byte chunk
408 int cl = (tlen >> 2);
409 // perform padding on last 2 byte
415 // copy 1 word with padding byte
416 switch (len & 0x03) {
418 dData[cl] = MD5_pad_w0();
421 dData[cl] = MD5_pad_w1(wIn[cl]);
424 dData[cl] = MD5_pad_w2(wIn[cl]);
427 dData[cl] = MD5_pad_w3(wIn[cl]);
433 wIn[ 0], wIn[ 1], wIn[ 2], wIn[ 3], wIn[ 4], wIn[ 5], wIn[ 6], wIn[ 7],
434 wIn[ 8], wIn[ 9], wIn[10], wIn[11], wIn[12], wIn[13], dData[14], dData[15]
437 #define w14 (len << 3)
438 #define w15 (len >> 29)
440 0, 0, 0, 0, 0, 0, 0, 0,
441 0, 0, 0, 0, 0, 0, w14, w15
449 MD5_copy_pad_block(dData, wIn, (tlen >> 2), len);
456 wIn[ 0], wIn[ 1], wIn[ 2], wIn[ 3], wIn[ 4], wIn[ 5], wIn[ 6], wIn[ 7],
457 wIn[ 8], wIn[ 9], wIn[10], wIn[11], wIn[12], wIn[13], wIn[14], wIn[15]
461 #define wIn ((UINT4 *)pData)
466 /* end of fast_MD5() */