ReactOS 0.4.17-dev-1005-g171e1de
md5.c
Go to the documentation of this file.
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
36 sizeof( SYMCRYPT_MD5_STATE ),
41};
42
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//
51static 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//
122static 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//
148static 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//
158static 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//
180VOID
183{
185
186 pState->dataLengthL = 0;
187 pState->dataLengthH = 0;
188 pState->bytesInBuffer = 0;
189
190 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}
197
198
199//
200// SymCryptMd5Append
201//
202VOID
207 SIZE_T cbData )
208{
210}
211
212//
213// SymCryptMd5Result
214//
215VOID
220{
222
223 //
224 // Write the output in the correct byte order
225 //
226 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 SymCryptWipeKnownSize( pState, sizeof( *pState ) );
236}
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#define CROUND( r, Func ) { \
275 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}
277
278#define IROUND( r, Func ) { \
279 Wt = SYMCRYPT_LOAD_LSBFIRST32( &pbData[ 4*md5MsgIndex[r] ] ); \
280 W[r] = Wt; \
281 CROUND( r, Func ); \
282}
283
284//
285// Subsequent rounds.
286// This is the same as the IROUND except that it uses the copied message.
287//
288#define FROUND( r, Func ) { \
289 Wt = W[md5MsgIndex[r]];\
290 CROUND( r, Func ); \
291}
292
293VOID
299 _Out_ SIZE_T * pcbRemaining )
300{
301
302 UINT32 W[16];
303 UINT32 ad[4];
304 UINT32 Wt;
305
306 ad[0] = pChain->H[0];
307 ad[1] = pChain->H[3];
308 ad[2] = pChain->H[2];
309 ad[3] = pChain->H[1];
310
311 while( cbData >= 64 )
312 {
313 //
314 // initial rounds 1 to 16
315 //
316
317 IROUND( 0, F );
318 IROUND( 1, F );
319 IROUND( 2, F );
320 IROUND( 3, F );
321 IROUND( 4, F );
322 IROUND( 5, F );
323 IROUND( 6, F );
324 IROUND( 7, F );
325 IROUND( 8, F );
326 IROUND( 9, F );
327 IROUND( 10, F );
328 IROUND( 11, F );
329 IROUND( 12, F );
330 IROUND( 13, F );
331 IROUND( 14, F );
332 IROUND( 15, F );
333
334 FROUND( 16, G );
335 FROUND( 17, G );
336 FROUND( 18, G );
337 FROUND( 19, G );
338 FROUND( 20, G );
339 FROUND( 21, G );
340 FROUND( 22, G );
341 FROUND( 23, G );
342 FROUND( 24, G );
343 FROUND( 25, G );
344 FROUND( 26, G );
345 FROUND( 27, G );
346 FROUND( 28, G );
347 FROUND( 29, G );
348 FROUND( 30, G );
349 FROUND( 31, G );
350
351 FROUND( 32, H );
352 FROUND( 33, H );
353 FROUND( 34, H );
354 FROUND( 35, H );
355 FROUND( 36, H );
356 FROUND( 37, H );
357 FROUND( 38, H );
358 FROUND( 39, H );
359 FROUND( 40, H );
360 FROUND( 41, H );
361 FROUND( 42, H );
362 FROUND( 43, H );
363 FROUND( 44, H );
364 FROUND( 45, H );
365 FROUND( 46, H );
366 FROUND( 47, H );
367
368 FROUND( 48, I );
369 FROUND( 49, I );
370 FROUND( 50, I );
371 FROUND( 51, I );
372 FROUND( 52, I );
373 FROUND( 53, I );
374 FROUND( 54, I );
375 FROUND( 55, I );
376 FROUND( 56, I );
377 FROUND( 57, I );
378 FROUND( 58, I );
379 FROUND( 59, I );
380 FROUND( 60, I );
381 FROUND( 61, I );
382 FROUND( 62, I );
383 FROUND( 63, I );
384
385 pChain->H[0] = ad[0] = ad[0] + pChain->H[0];
386 pChain->H[3] = ad[1] = ad[1] + pChain->H[3];
387 pChain->H[2] = ad[2] = ad[2] + pChain->H[2];
388 pChain->H[1] = ad[3] = ad[3] + pChain->H[1];
389
390 pbData += 64;
391 cbData -= 64;
392 }
393
394 *pcbRemaining = cbData;
395
396 //
397 // Wipe the variables;
398 //
399 SymCryptWipeKnownSize( ad, sizeof( ad ) );
400 SymCryptWipeKnownSize( W, sizeof( W ) );
401 SymCryptWipeKnownSize( &Wt, sizeof( Wt ) );
402}
403
404VOID
409{
410 SYMCRYPT_MD5_STATE_EXPORT_BLOB blob; // local copy to have proper alignment.
412
414
415 SymCryptWipeKnownSize( &blob, sizeof( blob ) ); // wipe to avoid any data leakage
416
417 blob.header.magic = SYMCRYPT_BLOB_MAGIC;
419 blob.header.type = SymCryptBlobTypeMd5State;
420
421 //
422 // Copy the relevant data. Buffer will be 0-padded.
423 //
424
425 SymCryptUint32ToLsbFirst( &pState->chain.H[0], &blob.chain[0], 4 );
426 blob.dataLength = pState->dataLengthL;
427 memcpy( &blob.buffer[0], &pState->buffer[0], blob.dataLength & 0x3f );
428
429 SYMCRYPT_ASSERT( (PCBYTE) &blob + sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ) == (PCBYTE) &blob.trailer );
430 SymCryptMarvin32( SymCryptMarvin32DefaultSeed, (PCBYTE) &blob, sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ), &blob.trailer.checksum[0] );
431
432 memcpy( pbBlob, &blob, sizeof( blob ) );
433
434//cleanup:
435 SymCryptWipeKnownSize( &blob, sizeof( blob ) );
436 return;
437}
438
444{
445 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
446 SYMCRYPT_MD5_STATE_EXPORT_BLOB blob; // local copy to have proper alignment.
447 BYTE checksum[8];
448
450 memcpy( &blob, pbBlob, sizeof( blob ) );
451
452 if( blob.header.magic != SYMCRYPT_BLOB_MAGIC ||
453 blob.header.size != SYMCRYPT_MD5_STATE_EXPORT_SIZE ||
454 blob.header.type != SymCryptBlobTypeMd5State )
455 {
456 scError = SYMCRYPT_INVALID_BLOB;
457 goto cleanup;
458 }
459
461 if( memcmp( checksum, &blob.trailer.checksum[0], 8 ) != 0 )
462 {
463 scError = SYMCRYPT_INVALID_BLOB;
464 goto cleanup;
465 }
466
467 SymCryptLsbFirstToUint32( &blob.chain[0], &pState->chain.H[0], 4 );
468 pState->dataLengthL = blob.dataLength;
469 pState->dataLengthH = 0;
470 pState->bytesInBuffer = blob.dataLength & 0x3f;
471 memcpy( &pState->buffer[0], &blob.buffer[0], pState->bytesInBuffer );
472
474
475cleanup:
476 SymCryptWipeKnownSize( &blob, sizeof(blob) );
477 return scError;
478}
479
480
481//
482// Simple test vector for FIPS module testing
483//
484
485static const BYTE md5KATAnswer[ 16 ] = {
486 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
487 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72,
488} ;
489
490VOID
493{
495
497
498 SymCryptInjectError( result, sizeof( result ) );
499
500 if( memcmp( result, md5KATAnswer, sizeof( result ) ) != 0 ) {
501 SymCryptFatal( 'MD5t' );
502 }
503}
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
static void cleanup(void)
Definition: main.c:1335
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
GLuint64EXT * result
Definition: glext.h:11304
#define C_ASSERT(e)
Definition: intsafe.h:73
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Inout_
Definition: no_sal2.h:162
#define _Out_writes_(s)
Definition: no_sal2.h:176
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
BYTE * PBYTE
Definition: pedump.c:66
#define SYMCRYPT_BLOB_MAGIC
Definition: sc_lib.h:1077
FORCEINLINE VOID SYMCRYPT_CALL SymCryptUint32ToLsbFirst(_In_reads_(cuData) PCUINT32 puData, _Out_writes_(4 *cuData) PBYTE pbResult, SIZE_T cuData)
Definition: sc_lib.h:471
@ SymCryptBlobTypeMd5State
Definition: sc_lib.h:1063
VOID SYMCRYPT_CALL SymCryptInjectError(PBYTE pbData, SIZE_T cbData)
FORCEINLINE VOID SYMCRYPT_CALL SymCryptLsbFirstToUint32(_In_reads_(4 *cuResult) PCBYTE pbData, _Out_writes_(cuResult) PUINT32 puResult, SIZE_T cuResult)
Definition: sc_lib.h:487
const BYTE SymCryptTestMsg3[3]
Definition: selftest.c:8
#define F(x, y, z)
Definition: md5.c:51
#define I(x, y, z)
Definition: md5.c:55
#define G(x, y, z)
Definition: md5.c:52
#define H(x, y, z)
Definition: md5.c:53
VOID SYMCRYPT_CALL SymCryptHashAppendInternal(_In_ PCSYMCRYPT_HASH pHash, _Inout_ PSYMCRYPT_COMMON_HASH_STATE pState, _In_reads_bytes_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: hash.c:10
VOID SYMCRYPT_CALL SymCryptHashCommonPaddingMd4Style(_In_ PCSYMCRYPT_HASH pHash, _Inout_ PSYMCRYPT_COMMON_HASH_STATE pState)
Definition: hash.c:85
static const BYTE md5KATAnswer[16]
Definition: md5.c:485
#define FROUND(r, Func)
Definition: md5.c:288
VOID SYMCRYPT_CALL SymCryptMd5AppendBlocks(_Inout_ SYMCRYPT_MD5_CHAINING_STATE *pChain, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_ SIZE_T *pcbRemaining)
Definition: md5.c:295
const PCSYMCRYPT_HASH SymCryptMd5Algorithm
Definition: md5.c:43
VOID SYMCRYPT_CALL SymCryptMd5Append(_Inout_ PSYMCRYPT_MD5_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: md5.c:204
VOID SYMCRYPT_CALL SymCryptMd5Init(_Out_ PSYMCRYPT_MD5_STATE pState)
Definition: md5.c:182
static const UINT32 md5InitialState[4]
Definition: md5.c:158
VOID SYMCRYPT_CALL SymCryptMd5StateExport(_In_ PCSYMCRYPT_MD5_STATE pState, _Out_writes_bytes_(SYMCRYPT_MD5_STATE_EXPORT_SIZE) PBYTE pbBlob)
Definition: md5.c:406
const SYMCRYPT_HASH SymCryptMd5Algorithm_default
Definition: md5.c:30
static const int md5Rotate[64]
Definition: md5.c:122
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMd5StateImport(_Out_ PSYMCRYPT_MD5_STATE pState, _In_reads_bytes_(SYMCRYPT_MD5_STATE_EXPORT_SIZE) PCBYTE pbBlob)
Definition: md5.c:441
static const UINT32 md5Const[64]
Definition: md5.c:51
VOID SYMCRYPT_CALL SymCryptMd5Selftest(void)
Definition: md5.c:492
static const int md5MsgIndex[64]
Definition: md5.c:148
VOID SYMCRYPT_CALL SymCryptMd5Result(_Inout_ PSYMCRYPT_MD5_STATE pState, _Out_writes_(SYMCRYPT_MD5_RESULT_SIZE) PBYTE pbResult)
Definition: md5.c:217
#define IROUND(r, Func)
Definition: md5.c:278
static const BYTE pbResult[]
Definition: polytest.cpp:36
Definition: image.c:229
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
VOID SYMCRYPT_CALL SymCryptMarvin32(_In_ PCSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_writes_(SYMCRYPT_MARVIN32_RESULT_SIZE) PBYTE pbResult)
Definition: marvin32.c:239
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)
#define SYMCRYPT_MD5_INPUT_BLOCK_SIZE
Definition: symcrypt.h:1018
PCSYMCRYPT_MARVIN32_EXPANDED_SEED const SymCryptMarvin32DefaultSeed
Definition: marvin32.c:29
#define SYMCRYPT_MD5_RESULT_SIZE
Definition: symcrypt.h:1017
VOID SYMCRYPT_CALL SymCryptMd5(_In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_writes_(SYMCRYPT_MD5_RESULT_SIZE) PBYTE pbResult)
SYMCRYPT_ERROR
Definition: symcrypt.h:227
VOID SYMCRYPT_CALL SymCryptMd5StateCopy(_In_ PCSYMCRYPT_MD5_STATE pSrc, _Out_ PSYMCRYPT_MD5_STATE pDst)
#define SYMCRYPT_CALL
struct _SYMCRYPT_HASH SYMCRYPT_HASH
#define SYMCRYPT_FIELD_SIZE(type, field)
const SYMCRYPT_HASH * PCSYMCRYPT_HASH
* PSYMCRYPT_MD5_STATE
PCBYTE PBYTE SIZE_T cbData
#define SYMCRYPT_SET_MAGIC(p)
#define SYMCRYPT_MD5_STATE_EXPORT_SIZE
#define SYMCRYPT_FIELD_OFFSET(type, field)
* PSYMCRYPT_COMMON_HASH_STATE
PSYMCRYPT_COMMON_HASH_STATE pState
const SYMCRYPT_MD5_STATE * PCSYMCRYPT_MD5_STATE
const BYTE * PCBYTE
PCBYTE pbData
#define SYMCRYPT_CHECK_MAGIC(p)
SYMCRYPT_MD5_CHAINING_STATE
SYMCRYPT_MD5_STATE
struct sock * chain
Definition: tcpcore.h:1
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59
unsigned char BYTE
Definition: xxhash.c:193