Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // Md5.c |
3 | | // |
4 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
5 | | // |
6 | | |
7 | | // |
8 | | // This module contains the routines to implement MD5 from RFC 1321 |
9 | | // |
10 | | // |
11 | | // This is a new implementation, NOT based on the existing one in RSA32.lib, |
12 | | // which is the one from RSA data security. RFC-1321 also contains code that |
13 | | // at a glance looks very similar to the RSA32.lib code. |
14 | | // |
15 | | // The implementation had to be refreshed anyway to conform to our coding |
16 | | // guidelines for cryptographic functions. |
17 | | // Re-implementing the function along the lines of our SHA-family implementations |
18 | | // was easy, and it removes one file with RSA copyright from our system. |
19 | | // |
20 | | // The only data copied for this implementation is the round constant values |
21 | | // which were copied from the RFC. |
22 | | // |
23 | | |
24 | | #include "precomp.h" |
25 | | |
26 | | // |
27 | | // See the symcrypt.h file for documentation on what the various functions do. |
28 | | // |
29 | | |
30 | | const SYMCRYPT_HASH SymCryptMd5Algorithm_default = { |
31 | | &SymCryptMd5Init, |
32 | | &SymCryptMd5Append, |
33 | | &SymCryptMd5Result, |
34 | | &SymCryptMd5AppendBlocks, |
35 | | &SymCryptMd5StateCopy, |
36 | | sizeof( SYMCRYPT_MD5_STATE ), |
37 | | SYMCRYPT_MD5_RESULT_SIZE, |
38 | | SYMCRYPT_MD5_INPUT_BLOCK_SIZE, |
39 | | SYMCRYPT_FIELD_OFFSET( SYMCRYPT_MD5_STATE, chain ), |
40 | | SYMCRYPT_FIELD_SIZE( SYMCRYPT_MD5_STATE, chain ), |
41 | | }; |
42 | | |
43 | | const PCSYMCRYPT_HASH SymCryptMd5Algorithm = &SymCryptMd5Algorithm_default; |
44 | | |
45 | | // |
46 | | // The round constants used by MD5 |
47 | | // |
48 | | // These are called T[i] in RFC1321 although T[i] uses the range [1..64] and we use [0..63] |
49 | | // This array should be optimized away by the compiler as all values are inlined. |
50 | | // |
51 | | static const UINT32 md5Const[64] = { |
52 | | 0xd76aa478UL, |
53 | | 0xe8c7b756UL, |
54 | | 0x242070dbUL, |
55 | | 0xc1bdceeeUL, |
56 | | 0xf57c0fafUL, |
57 | | 0x4787c62aUL, |
58 | | 0xa8304613UL, |
59 | | 0xfd469501UL, |
60 | | 0x698098d8UL, |
61 | | 0x8b44f7afUL, |
62 | | 0xffff5bb1UL, |
63 | | 0x895cd7beUL, |
64 | | 0x6b901122UL, |
65 | | 0xfd987193UL, |
66 | | 0xa679438eUL, |
67 | | 0x49b40821UL, |
68 | | 0xf61e2562UL, |
69 | | 0xc040b340UL, |
70 | | 0x265e5a51UL, |
71 | | 0xe9b6c7aaUL, |
72 | | 0xd62f105dUL, |
73 | | 0x02441453UL, |
74 | | 0xd8a1e681UL, |
75 | | 0xe7d3fbc8UL, |
76 | | 0x21e1cde6UL, |
77 | | 0xc33707d6UL, |
78 | | 0xf4d50d87UL, |
79 | | 0x455a14edUL, |
80 | | 0xa9e3e905UL, |
81 | | 0xfcefa3f8UL, |
82 | | 0x676f02d9UL, |
83 | | 0x8d2a4c8aUL, |
84 | | 0xfffa3942UL, |
85 | | 0x8771f681UL, |
86 | | 0x6d9d6122UL, |
87 | | 0xfde5380cUL, |
88 | | 0xa4beea44UL, |
89 | | 0x4bdecfa9UL, |
90 | | 0xf6bb4b60UL, |
91 | | 0xbebfbc70UL, |
92 | | 0x289b7ec6UL, |
93 | | 0xeaa127faUL, |
94 | | 0xd4ef3085UL, |
95 | | 0x04881d05UL, |
96 | | 0xd9d4d039UL, |
97 | | 0xe6db99e5UL, |
98 | | 0x1fa27cf8UL, |
99 | | 0xc4ac5665UL, |
100 | | 0xf4292244UL, |
101 | | 0x432aff97UL, |
102 | | 0xab9423a7UL, |
103 | | 0xfc93a039UL, |
104 | | 0x655b59c3UL, |
105 | | 0x8f0ccc92UL, |
106 | | 0xffeff47dUL, |
107 | | 0x85845dd1UL, |
108 | | 0x6fa87e4fUL, |
109 | | 0xfe2ce6e0UL, |
110 | | 0xa3014314UL, |
111 | | 0x4e0811a1UL, |
112 | | 0xf7537e82UL, |
113 | | 0xbd3af235UL, |
114 | | 0x2ad7d2bbUL, |
115 | | 0xeb86d391UL, |
116 | | }; |
117 | | |
118 | | // |
119 | | // Round rotation amounts. This array is optimized away by the compiler |
120 | | // as we inline all our rotations. |
121 | | // |
122 | | static const int md5Rotate[64] = { |
123 | | 7, 12, 17, 22, |
124 | | 7, 12, 17, 22, |
125 | | 7, 12, 17, 22, |
126 | | 7, 12, 17, 22, |
127 | | |
128 | | 5, 9, 14, 20, |
129 | | 5, 9, 14, 20, |
130 | | 5, 9, 14, 20, |
131 | | 5, 9, 14, 20, |
132 | | |
133 | | 4, 11, 16, 23, |
134 | | 4, 11, 16, 23, |
135 | | 4, 11, 16, 23, |
136 | | 4, 11, 16, 23, |
137 | | |
138 | | 6, 10, 15, 21, |
139 | | 6, 10, 15, 21, |
140 | | 6, 10, 15, 21, |
141 | | 6, 10, 15, 21, |
142 | | }; |
143 | | |
144 | | // |
145 | | // Message word index table. This array is optimized away by the compiler |
146 | | // as we inline all our accesses. |
147 | | // |
148 | | static const int md5MsgIndex[64] = { |
149 | | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
150 | | 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, |
151 | | 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, |
152 | | 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, |
153 | | }; |
154 | | |
155 | | // |
156 | | // Initial state |
157 | | // |
158 | | static const UINT32 md5InitialState[4] = { |
159 | | 0x67452301UL, |
160 | | 0xefcdab89UL, |
161 | | 0x98badcfeUL, |
162 | | 0x10325476UL, |
163 | | }; |
164 | | |
165 | | // |
166 | | // SymCryptMd5 |
167 | | // |
168 | | #define ALG MD5 |
169 | | #define Alg Md5 |
170 | | #include "hash_pattern.c" |
171 | | #undef ALG |
172 | | #undef Alg |
173 | | |
174 | | |
175 | | |
176 | | |
177 | | // |
178 | | // SymCryptMd5Init |
179 | | // |
180 | | VOID |
181 | | SYMCRYPT_CALL |
182 | | SymCryptMd5Init( _Out_ PSYMCRYPT_MD5_STATE pState ) |
183 | 23.2k | { |
184 | 23.2k | SYMCRYPT_SET_MAGIC( pState ); |
185 | | |
186 | 23.2k | pState->dataLengthL = 0; |
187 | 23.2k | pState->dataLengthH = 0; |
188 | 23.2k | pState->bytesInBuffer = 0; |
189 | | |
190 | 23.2k | memcpy( &pState->chain.H[0], &md5InitialState[0], sizeof( md5InitialState ) ); |
191 | | |
192 | | // |
193 | | // There is no need to initialize the buffer part of the state as that will be |
194 | | // filled before it is used. |
195 | | // |
196 | 23.2k | } |
197 | | |
198 | | |
199 | | // |
200 | | // SymCryptMd5Append |
201 | | // |
202 | | VOID |
203 | | SYMCRYPT_CALL |
204 | | SymCryptMd5Append( |
205 | | _Inout_ PSYMCRYPT_MD5_STATE pState, |
206 | | _In_reads_( cbData ) PCBYTE pbData, |
207 | | SIZE_T cbData ) |
208 | 58.2k | { |
209 | 58.2k | SymCryptHashAppendInternal( SymCryptMd5Algorithm, (PSYMCRYPT_COMMON_HASH_STATE)pState, pbData, cbData ); |
210 | 58.2k | } |
211 | | |
212 | | // |
213 | | // SymCryptMd5Result |
214 | | // |
215 | | VOID |
216 | | SYMCRYPT_CALL |
217 | | SymCryptMd5Result( |
218 | | _Inout_ PSYMCRYPT_MD5_STATE pState, |
219 | | _Out_writes_( SYMCRYPT_MD5_RESULT_SIZE ) PBYTE pbResult ) |
220 | 22.9k | { |
221 | 22.9k | SymCryptHashCommonPaddingMd4Style( SymCryptMd5Algorithm, (PSYMCRYPT_COMMON_HASH_STATE) pState ); |
222 | | |
223 | | // |
224 | | // Write the output in the correct byte order |
225 | | // |
226 | 22.9k | SymCryptUint32ToLsbFirst( &pState->chain.H[0], pbResult, 4 ); |
227 | | |
228 | | // |
229 | | // Wipe & re-initialize |
230 | | // We have to wipe the whole state because the Init call |
231 | | // might be optimized away by a smart compiler. |
232 | | // And we need to wipe old data. |
233 | | // |
234 | 22.9k | SymCryptWipeKnownSize( pState, sizeof( *pState ) ); |
235 | 22.9k | SymCryptMd5Init( pState ); |
236 | 22.9k | } |
237 | | |
238 | | |
239 | | // |
240 | | // For documentation on these function see rfc-1321 |
241 | | // |
242 | | //#define F( x, y, z ) (((x) & (y)) ^ ((~(x)) & (z))) |
243 | | #define F( x, y, z ) ((((z) ^ (y)) & (x)) ^ (z)) |
244 | | #define G( x, y, z ) F( (z), (x), (y) ) |
245 | | #define H( x, y, z ) ((x) ^ (y) ^ (z) ) |
246 | | #define I( x, y, z ) ((y) ^ ((x) | ~(z))) |
247 | | |
248 | | // |
249 | | // The values a-d are stored in an array called ad. |
250 | | // We have unrolled the code completely. This makes both the indices into |
251 | | // the ad array constant, and it makes the message addressing constant. |
252 | | // |
253 | | // We copy the message into our own buffer to obey the read-once rule. |
254 | | // Memory is sometimes aliased so that multiple threads or processes can access |
255 | | // the same memory at the same time. With MD5 there is a danger that some other |
256 | | // process could modify the memory while the computation is ongoing and introduce |
257 | | // changes in the computation not envisioned by the designers or cryptanalysts. |
258 | | // At this level in the library we cannot guarantee that this is not the case, |
259 | | // and we can't trust the higher layers to respect a don't-change-it-while-computing-md5 |
260 | | // restriction. (In practice, such restrictions are lost through the many |
261 | | // layers in the stack.) |
262 | | // |
263 | | // |
264 | | // Initial round macro |
265 | | // |
266 | | // r is the round number |
267 | | // ad[(r+0)%4] = a; |
268 | | // ad[(r+1)%4] = d; |
269 | | // ad[(r+2)%4] = c; |
270 | | // ad[(r+3)%4] = b; |
271 | | // |
272 | | // When r increments the register re-naming is automatically correct. |
273 | | // |
274 | 58.4M | #define CROUND( r, Func ) { \ |
275 | 58.4M | ad[r%4] = ad[(r+3)%4] + ROL32( ad[r%4] + Func(ad[(r+3)%4], ad[(r+2)%4], ad[(r+1)%4]) + Wt + md5Const[r], md5Rotate[r] ); \ |
276 | 58.4M | } |
277 | | |
278 | 14.6M | #define IROUND( r, Func ) { \ |
279 | 14.6M | Wt = SYMCRYPT_LOAD_LSBFIRST32( &pbData[ 4*md5MsgIndex[r] ] ); \ |
280 | 14.6M | W[r] = Wt; \ |
281 | 14.6M | CROUND( r, Func ); \ |
282 | 14.6M | } |
283 | | |
284 | | // |
285 | | // Subsequent rounds. |
286 | | // This is the same as the IROUND except that it uses the copied message. |
287 | | // |
288 | 43.8M | #define FROUND( r, Func ) { \ |
289 | 43.8M | Wt = W[md5MsgIndex[r]];\ |
290 | 43.8M | CROUND( r, Func ); \ |
291 | 43.8M | } |
292 | | |
293 | | VOID |
294 | | SYMCRYPT_CALL |
295 | | SymCryptMd5AppendBlocks( |
296 | | _Inout_ SYMCRYPT_MD5_CHAINING_STATE * pChain, |
297 | | _In_reads_( cbData ) PCBYTE pbData, |
298 | | SIZE_T cbData, |
299 | | _Out_ SIZE_T * pcbRemaining ) |
300 | 50.5k | { |
301 | | |
302 | 50.5k | UINT32 W[16]; |
303 | 50.5k | UINT32 ad[4]; |
304 | 50.5k | UINT32 Wt; |
305 | | |
306 | 50.5k | ad[0] = pChain->H[0]; |
307 | 50.5k | ad[1] = pChain->H[3]; |
308 | 50.5k | ad[2] = pChain->H[2]; |
309 | 50.5k | ad[3] = pChain->H[1]; |
310 | | |
311 | 963k | while( cbData >= 64 ) |
312 | 912k | { |
313 | | // |
314 | | // initial rounds 1 to 16 |
315 | | // |
316 | | |
317 | 912k | IROUND( 0, F ); |
318 | 912k | IROUND( 1, F ); |
319 | 912k | IROUND( 2, F ); |
320 | 912k | IROUND( 3, F ); |
321 | 912k | IROUND( 4, F ); |
322 | 912k | IROUND( 5, F ); |
323 | 912k | IROUND( 6, F ); |
324 | 912k | IROUND( 7, F ); |
325 | 912k | IROUND( 8, F ); |
326 | 912k | IROUND( 9, F ); |
327 | 912k | IROUND( 10, F ); |
328 | 912k | IROUND( 11, F ); |
329 | 912k | IROUND( 12, F ); |
330 | 912k | IROUND( 13, F ); |
331 | 912k | IROUND( 14, F ); |
332 | 912k | IROUND( 15, F ); |
333 | | |
334 | 912k | FROUND( 16, G ); |
335 | 912k | FROUND( 17, G ); |
336 | 912k | FROUND( 18, G ); |
337 | 912k | FROUND( 19, G ); |
338 | 912k | FROUND( 20, G ); |
339 | 912k | FROUND( 21, G ); |
340 | 912k | FROUND( 22, G ); |
341 | 912k | FROUND( 23, G ); |
342 | 912k | FROUND( 24, G ); |
343 | 912k | FROUND( 25, G ); |
344 | 912k | FROUND( 26, G ); |
345 | 912k | FROUND( 27, G ); |
346 | 912k | FROUND( 28, G ); |
347 | 912k | FROUND( 29, G ); |
348 | 912k | FROUND( 30, G ); |
349 | 912k | FROUND( 31, G ); |
350 | | |
351 | 912k | FROUND( 32, H ); |
352 | 912k | FROUND( 33, H ); |
353 | 912k | FROUND( 34, H ); |
354 | 912k | FROUND( 35, H ); |
355 | 912k | FROUND( 36, H ); |
356 | 912k | FROUND( 37, H ); |
357 | 912k | FROUND( 38, H ); |
358 | 912k | FROUND( 39, H ); |
359 | 912k | FROUND( 40, H ); |
360 | 912k | FROUND( 41, H ); |
361 | 912k | FROUND( 42, H ); |
362 | 912k | FROUND( 43, H ); |
363 | 912k | FROUND( 44, H ); |
364 | 912k | FROUND( 45, H ); |
365 | 912k | FROUND( 46, H ); |
366 | 912k | FROUND( 47, H ); |
367 | | |
368 | 912k | FROUND( 48, I ); |
369 | 912k | FROUND( 49, I ); |
370 | 912k | FROUND( 50, I ); |
371 | 912k | FROUND( 51, I ); |
372 | 912k | FROUND( 52, I ); |
373 | 912k | FROUND( 53, I ); |
374 | 912k | FROUND( 54, I ); |
375 | 912k | FROUND( 55, I ); |
376 | 912k | FROUND( 56, I ); |
377 | 912k | FROUND( 57, I ); |
378 | 912k | FROUND( 58, I ); |
379 | 912k | FROUND( 59, I ); |
380 | 912k | FROUND( 60, I ); |
381 | 912k | FROUND( 61, I ); |
382 | 912k | FROUND( 62, I ); |
383 | 912k | FROUND( 63, I ); |
384 | | |
385 | 912k | pChain->H[0] = ad[0] = ad[0] + pChain->H[0]; |
386 | 912k | pChain->H[3] = ad[1] = ad[1] + pChain->H[3]; |
387 | 912k | pChain->H[2] = ad[2] = ad[2] + pChain->H[2]; |
388 | 912k | pChain->H[1] = ad[3] = ad[3] + pChain->H[1]; |
389 | | |
390 | 912k | pbData += 64; |
391 | 912k | cbData -= 64; |
392 | 912k | } |
393 | | |
394 | 50.5k | *pcbRemaining = cbData; |
395 | | |
396 | | // |
397 | | // Wipe the variables; |
398 | | // |
399 | 50.5k | SymCryptWipeKnownSize( ad, sizeof( ad ) ); |
400 | 50.5k | SymCryptWipeKnownSize( W, sizeof( W ) ); |
401 | 50.5k | SymCryptWipeKnownSize( &Wt, sizeof( Wt ) ); |
402 | 50.5k | } |
403 | | |
404 | | VOID |
405 | | SYMCRYPT_CALL |
406 | | SymCryptMd5StateExport( |
407 | | _In_ PCSYMCRYPT_MD5_STATE pState, |
408 | | _Out_writes_bytes_( SYMCRYPT_MD5_STATE_EXPORT_SIZE ) PBYTE pbBlob ) |
409 | 0 | { |
410 | 0 | SYMCRYPT_MD5_STATE_EXPORT_BLOB blob; // local copy to have proper alignment. |
411 | 0 | C_ASSERT( sizeof( blob ) == SYMCRYPT_MD5_STATE_EXPORT_SIZE ); |
412 | |
|
413 | 0 | SYMCRYPT_CHECK_MAGIC( pState ); |
414 | |
|
415 | 0 | SymCryptWipeKnownSize( &blob, sizeof( blob ) ); // wipe to avoid any data leakage |
416 | |
|
417 | 0 | blob.header.magic = SYMCRYPT_BLOB_MAGIC; |
418 | 0 | blob.header.size = SYMCRYPT_MD5_STATE_EXPORT_SIZE; |
419 | 0 | blob.header.type = SymCryptBlobTypeMd5State; |
420 | | |
421 | | // |
422 | | // Copy the relevant data. Buffer will be 0-padded. |
423 | | // |
424 | |
|
425 | 0 | SymCryptUint32ToLsbFirst( &pState->chain.H[0], &blob.chain[0], 4 ); |
426 | 0 | blob.dataLength = pState->dataLengthL; |
427 | 0 | memcpy( &blob.buffer[0], &pState->buffer[0], blob.dataLength & 0x3f ); |
428 | |
|
429 | 0 | SYMCRYPT_ASSERT( (PCBYTE) &blob + sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ) == (PCBYTE) &blob.trailer ); |
430 | 0 | SymCryptMarvin32( SymCryptMarvin32DefaultSeed, (PCBYTE) &blob, sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ), &blob.trailer.checksum[0] ); |
431 | |
|
432 | 0 | memcpy( pbBlob, &blob, sizeof( blob ) ); |
433 | | |
434 | | //cleanup: |
435 | 0 | SymCryptWipeKnownSize( &blob, sizeof( blob ) ); |
436 | 0 | return; |
437 | 0 | } |
438 | | |
439 | | SYMCRYPT_ERROR |
440 | | SYMCRYPT_CALL |
441 | | SymCryptMd5StateImport( |
442 | | _Out_ PSYMCRYPT_MD5_STATE pState, |
443 | | _In_reads_bytes_( SYMCRYPT_MD5_STATE_EXPORT_SIZE) PCBYTE pbBlob ) |
444 | 0 | { |
445 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
446 | 0 | SYMCRYPT_MD5_STATE_EXPORT_BLOB blob; // local copy to have proper alignment. |
447 | 0 | BYTE checksum[8]; |
448 | |
|
449 | 0 | C_ASSERT( sizeof( blob ) == SYMCRYPT_MD5_STATE_EXPORT_SIZE ); |
450 | 0 | memcpy( &blob, pbBlob, sizeof( blob ) ); |
451 | |
|
452 | 0 | if( blob.header.magic != SYMCRYPT_BLOB_MAGIC || |
453 | 0 | blob.header.size != SYMCRYPT_MD5_STATE_EXPORT_SIZE || |
454 | 0 | blob.header.type != SymCryptBlobTypeMd5State ) |
455 | 0 | { |
456 | 0 | scError = SYMCRYPT_INVALID_BLOB; |
457 | 0 | goto cleanup; |
458 | 0 | } |
459 | | |
460 | 0 | SymCryptMarvin32( SymCryptMarvin32DefaultSeed, (PCBYTE) &blob, sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ), checksum ); |
461 | 0 | if( memcmp( checksum, &blob.trailer.checksum[0], 8 ) != 0 ) |
462 | 0 | { |
463 | 0 | scError = SYMCRYPT_INVALID_BLOB; |
464 | 0 | goto cleanup; |
465 | 0 | } |
466 | | |
467 | 0 | SymCryptLsbFirstToUint32( &blob.chain[0], &pState->chain.H[0], 4 ); |
468 | 0 | pState->dataLengthL = blob.dataLength; |
469 | 0 | pState->dataLengthH = 0; |
470 | 0 | pState->bytesInBuffer = blob.dataLength & 0x3f; |
471 | 0 | memcpy( &pState->buffer[0], &blob.buffer[0], pState->bytesInBuffer ); |
472 | |
|
473 | 0 | SYMCRYPT_SET_MAGIC( pState ); |
474 | |
|
475 | 0 | cleanup: |
476 | 0 | SymCryptWipeKnownSize( &blob, sizeof(blob) ); |
477 | 0 | return scError; |
478 | 0 | } |
479 | | |
480 | | |
481 | | // |
482 | | // Simple test vector for FIPS module testing |
483 | | // |
484 | | |
485 | | static const BYTE md5KATAnswer[ 16 ] = { |
486 | | 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, |
487 | | 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72, |
488 | | } ; |
489 | | |
490 | | VOID |
491 | | SYMCRYPT_CALL |
492 | | SymCryptMd5Selftest(void) |
493 | 0 | { |
494 | 0 | BYTE result[SYMCRYPT_MD5_RESULT_SIZE]; |
495 | |
|
496 | 0 | SymCryptMd5( SymCryptTestMsg3, sizeof( SymCryptTestMsg3 ), result ); |
497 | |
|
498 | 0 | SymCryptInjectError( result, sizeof( result ) ); |
499 | |
|
500 | 0 | if( memcmp( result, md5KATAnswer, sizeof( result ) ) != 0 ) { |
501 | 0 | SymCryptFatal( 'MD5t' ); |
502 | 0 | } |
503 | 0 | } |
504 | | |
505 | | |