27
27
28
28
#include " md5_hash.hpp"
29
29
30
- #ifdef WORDS_BIGENDIAN
31
- #define HIGHFIRST 1
32
- #endif
30
+ #include < string.h> // memcpy()
31
+ #include < my_compiler.h> // likely
32
+ #include < my_config.h> // big/little endian
33
+
33
34
34
35
/*
35
36
* This code implements the MD5 message-digest algorithm.
48
49
* is returned as the hash value.
49
50
*/
50
51
51
- #ifndef HIGHFIRST
52
- #define byteReverse (buf, len ) /* Nothing */
53
- #else
54
- void byteReverse (unsigned char *buf, unsigned longs);
55
- /*
56
- * Note: this code is harmless on little-endian machines.
57
- */
58
- void byteReverse (unsigned char *buf, unsigned longs)
59
- {
60
- Uint32 t;
61
- do {
62
- t = (Uint32) ((unsigned ) buf[3 ] << 8 | buf[2 ]) << 16 |
63
- ((unsigned ) buf[1 ] << 8 | buf[0 ]);
64
- *(Uint32 *) buf = t;
65
- buf += 4 ;
66
- } while (--longs);
67
- }
68
- #endif
69
-
70
52
/* The four core functions - F1 is optimized somewhat */
71
53
72
54
/* #define F1(x, y, z) (x & y | ~x & z) */
@@ -168,47 +150,46 @@ static void MD5Transform(Uint32 buf[4], Uint32 const in[16])
168
150
}
169
151
170
152
/*
171
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
153
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
172
154
* initialization constants.
173
155
*/
174
- void md5_hash (Uint32 result[4 ], const Uint64* keybuf, Uint32 no_of_32_words)
156
+ void md5_hash (Uint32 result[4 ],
157
+ const char * keybuf,
158
+ Uint32 no_of_bytes)
175
159
{
176
- /* *
177
- * This is the external interface of the module
178
- * It is assumed that keybuf is placed on 8 byte
179
- * alignment.
180
- */
181
- Uint32 i;
182
160
Uint32 buf[4 ];
183
161
union {
184
162
Uint64 transform64_buf[8 ];
185
163
Uint32 transform32_buf[16 ];
186
164
};
187
- Uint32 len = no_of_32_words << 2 ;
188
- const Uint64* key64buf = ( const Uint64*)keybuf;
189
- const Uint32* key32buf = (const Uint32*)keybuf ;
165
+
166
+ // Round up to full word length
167
+ const Uint32 len = (no_of_bytes + 3 ) & ~ 3 ;
190
168
191
169
buf[0 ] = 0x67452301 ;
192
170
buf[1 ] = 0xefcdab89 ;
193
171
buf[2 ] = 0x98badcfe ;
194
172
buf[3 ] = 0x10325476 ;
195
173
196
- while (no_of_32_words >= 16 ) {
197
- transform64_buf[0 ] = key64buf[0 ];
198
- transform64_buf[1 ] = key64buf[1 ];
199
- transform64_buf[2 ] = key64buf[2 ];
200
- transform64_buf[3 ] = key64buf[3 ];
201
- transform64_buf[4 ] = key64buf[4 ];
202
- transform64_buf[5 ] = key64buf[5 ];
203
- transform64_buf[6 ] = key64buf[6 ];
204
- transform64_buf[7 ] = key64buf[7 ];
205
- no_of_32_words -= 16 ;
206
- key64buf += 8 ;
207
- byteReverse ((unsigned char *)transform32_buf, 16 );
174
+ while (no_of_bytes >= 64 ) {
175
+ memcpy (transform32_buf, keybuf, 64 );
176
+ keybuf += 64 ;
177
+ no_of_bytes -= 64 ;
178
+ MD5Transform (buf, transform32_buf);
179
+ }
180
+
181
+ if (unlikely (no_of_bytes >= 61 )) { // Will be a full frame when padded
182
+ // Last word written will not be a full word -> zero pad before memcpy over
183
+ transform32_buf[15 ] = 0 ;
184
+ memcpy (transform32_buf, keybuf, no_of_bytes);
185
+ keybuf += no_of_bytes;
186
+ no_of_bytes = 0 ;
208
187
MD5Transform (buf, transform32_buf);
209
188
}
210
189
211
- key32buf = (const Uint32*)key64buf;
190
+ // Remaining words, including zero padding, to get to a word-aligned size.
191
+ const Uint32 no_of_32_words = (no_of_bytes + 3 ) >> 2 ;
192
+
212
193
transform64_buf[0 ] = 0 ;
213
194
transform64_buf[1 ] = 0 ;
214
195
transform64_buf[2 ] = 0 ;
@@ -218,35 +199,47 @@ void md5_hash(Uint32 result[4], const Uint64* keybuf, Uint32 no_of_32_words)
218
199
transform64_buf[6 ] = 0 ;
219
200
transform64_buf[7 ] = (Uint64)len;
220
201
221
- for (i = 0 ; i < no_of_32_words; i++)
222
- transform32_buf[i] = key32buf[i];
202
+ // 0x800... Is used as an end / length mark, possibly overwriting the 'len'.
223
203
transform32_buf[no_of_32_words] = 0x80000000 ;
224
204
225
- if (no_of_32_words < 14 ) {
226
- byteReverse ((unsigned char *)transform32_buf, 16 );
227
- MD5Transform (buf, transform32_buf);
228
- } else {
229
- if (no_of_32_words == 14 )
230
- transform32_buf[15 ] = 0 ;
231
- MD5Transform (buf, transform32_buf);
232
- transform64_buf[0 ] = 0 ;
233
- transform64_buf[1 ] = 0 ;
234
- transform64_buf[2 ] = 0 ;
235
- transform64_buf[3 ] = 0 ;
236
- transform64_buf[4 ] = 0 ;
237
- transform64_buf[5 ] = 0 ;
238
- transform64_buf[6 ] = 0 ;
239
- transform64_buf[7 ] = (Uint64)len;
240
- byteReverse ((unsigned char *)transform32_buf, 16 );
241
- MD5Transform (buf, transform32_buf);
205
+ if (likely (no_of_32_words > 0 )) {
206
+ // Last word written may not be a full word -> zero pad before memcpy over
207
+ transform32_buf[no_of_32_words-1 ] = 0 ;
208
+ memcpy (transform32_buf, keybuf, no_of_bytes);
209
+
210
+ if (unlikely (no_of_32_words >= 14 )) {
211
+ // On a little endian platform the memcpy() + 0x800.. wrote over 'len'
212
+ // located at 32_buf[14], 32_buf[15] was already zero.
213
+ // On a big endian, len is written to 32_buf[15] and not written over
214
+ // if '#32_words == 14' -> We clear it as it is set in next frame instead.
215
+ #ifdef WORDS_BIGENDIAN
216
+ if (no_of_32_words == 14 )
217
+ transform32_buf[15 ] = 0 ;
218
+ #endif
219
+ // Note: 'len' should have been written to 32_buf[15] for both
220
+ // big/little endian.
221
+ // For backward bug compatability it is too late to fix it now.
222
+ MD5Transform (buf, transform32_buf);
223
+ transform64_buf[0 ] = 0 ;
224
+ transform64_buf[1 ] = 0 ;
225
+ transform64_buf[2 ] = 0 ;
226
+ transform64_buf[3 ] = 0 ;
227
+ transform64_buf[4 ] = 0 ;
228
+ transform64_buf[5 ] = 0 ;
229
+ transform64_buf[6 ] = 0 ;
230
+ transform64_buf[7 ] = (Uint64)len;
231
+ }
242
232
}
233
+ MD5Transform (buf, transform32_buf);
243
234
244
235
result[0 ] = buf[0 ];
245
236
result[1 ] = buf[1 ];
246
237
result[2 ] = buf[2 ];
247
238
result[3 ] = buf[3 ];
248
239
}
249
240
241
+
242
+
250
243
// ////////////////////////////////////////////////
251
244
// ////////////////////////////////////////////////
252
245
// ////////////////////////////////////////////////
@@ -371,27 +364,6 @@ test_sample test_samples[] = {
371
364
};
372
365
#endif
373
366
374
-
375
- /* *
376
- * Glue function for allowing to test non-word-aligned 'no_of_bytes'.
377
- * Will zero-pad the 'key' to a word aligned length before hashing.
378
- */
379
- void md5_hash (Uint32 result[4 ],
380
- const char * keybuf,
381
- Uint32 no_of_bytes)
382
- {
383
- union {
384
- char tmp[MAX_TEST_SAMPLE_WORDS*4 ];
385
- Uint64 _align;
386
- };
387
- memcpy (tmp, keybuf, no_of_bytes);
388
- while (no_of_bytes & 3 ) {
389
- tmp[no_of_bytes++] = 0 ;
390
- }
391
- md5_hash (result, (Uint64*)tmp, no_of_bytes / 4 );
392
- }
393
-
394
-
395
367
int main ()
396
368
{
397
369
Uint32 test_data[MAX_TEST_SAMPLE_WORDS];
0 commit comments