ReactOS 0.4.17-dev-1005-g171e1de
md4.c
Go to the documentation of this file.
1//
2// Md4.c
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6
7//
8// This module contains the routines to implement MD4 from RFC 1320
9//
10//
11// This is a new implementation, NOT based on the existing ones in RSA32.lib.
12// There are 2 versions in RSA32.lib, one from RSA data security and one from
13// Scott Fields.
14//
15// MD4 and MD5 are extremely similar. Having already done a new MD5 implementation it
16// was very little work to copy the code & turn it into an MD4 implementation.
17// In fact, it was easier than reviewing & modifying the old code to bring it up to
18// the current implementation guidelines.
19//
20// This also ensures that this file is not a derived work from RSA data security
21// code which simplifies the copyright situation.
22//
23// We dropped the assembler implementation. MD4 is so weak that it should be removed
24// from use, not sped up.
25//
26
27#include "precomp.h"
28
29//
30// See the symcrypt.h file for documentation on what the various functions do.
31//
32
39 sizeof( SYMCRYPT_MD4_STATE ),
44};
45
47
48//
49// The round constants used by MD4
50//
51//
52static const UINT32 md4Const[3] = {
53 0x00000000UL,
54 0x5A827999UL,
55 0x6ED9EBA1UL,
56 };
57
58//
59// Round rotation amounts. This array is optimized away by the compiler
60// as we inline all our rotations.
61//
62static const int md4Rotate[48] = {
63 3, 7, 11, 19,
64 3, 7, 11, 19,
65 3, 7, 11, 19,
66 3, 7, 11, 19,
67
68 3, 5, 9, 13,
69 3, 5, 9, 13,
70 3, 5, 9, 13,
71 3, 5, 9, 13,
72
73 3, 9, 11, 15,
74 3, 9, 11, 15,
75 3, 9, 11, 15,
76 3, 9, 11, 15,
77
78};
79
80//
81// Message word index table. This array is optimized away by the compiler
82// as we inline all our accesses.
83//
84static const int md4MsgIndex[48] = {
85 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
86 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15,
87 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15,
88};
89
90//
91// Initial state
92//
93static const UINT32 md4InitialState[4] = {
94 0x67452301UL,
95 0xefcdab89UL,
96 0x98badcfeUL,
97 0x10325476UL,
98};
99
100
101//
102// SymCryptMd4
103//
104#define ALG MD4
105#define Alg Md4
106#include "hash_pattern.c"
107#undef ALG
108#undef Alg
109
110
111
112//
113// SymCryptmd4Init
114//
115VOID
118{
120
121 pState->dataLengthL = 0;
122 pState->dataLengthH = 0;
123 pState->bytesInBuffer = 0;
124
125 memcpy( &pState->chain.H[0], &md4InitialState[0], sizeof( md4InitialState ) );
126
127 //
128 // There is no need to initialize the buffer part of the state as that will be
129 // filled before it is used.
130 //
131}
132
133
134//
135// SymCryptMd4Append
136//
137VOID
141 SIZE_T cbData )
142{
144}
145
146
147//
148// SymCryptmd4Result
149//
150VOID
155{
157
158 //
159 // Write the output in the correct byte order
160 //
161 SymCryptUint32ToLsbFirst( &pState->chain.H[0], pbResult, 4 );
162
163 //
164 // Wipe & re-initialize
165 // We have to wipe the whole state as the initialization might be optimized away.
166 //
167 SymCryptWipeKnownSize( pState, sizeof( *pState ));
169 }
170
171
172//
173// For documentation on these function see rfc-1320
174//
175//#define F( x, y, z ) (((x) & (y)) | ((~(x)) & (z)))
176//#define G( x, y, z ) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
177
178#define F( x, y, z ) ((((z) ^ (y)) & (x)) ^ (z))
179#define G( x, y, z ) ((((x) | (y)) & (z) ) | ((x) & (y)))
180#define H( x, y, z ) ((x) ^ (y) ^ (z) )
181
182//
183// The values a-d are stored in an array called ad.
184// We have unrolled the code completely. This makes both the indices into
185// the ad array constant, and it makes the message addressing constant.
186//
187// We copy the message into our own buffer to obey the read-once rule.
188// Memory is sometimes aliased so that multiple threads or processes can access
189// the same memory at the same time. With MD4 there is a danger that some other
190// process could modify the memory while the computation is ongoing and introduce
191// changes in the computation not envisioned by the designers or cryptanalists.
192// At this level in the library we cannot guarantee that this is not the case,
193// and we can't trust the higher layers to respect a don't-change-it-while-computing-md4
194// restriction. (In practice, such restrictions are lost through the many
195// layers in the stack.)
196//
197
198//
199// r is the round number
200// ad[(r+0)%4] = a;
201// ad[(r+1)%4] = d;
202// ad[(r+2)%4] = c;
203// ad[(r+3)%4] = b;
204//
205// When r increments the register re-naming is automatically correct.
206//
207
208//
209// CROUND is the core round function
210//
211#define CROUND( r, Func ) { \
212 ad[r%4] = ROL32( ad[r%4] + Func(ad[(r+3)%4], ad[(r+2)%4], ad[(r+1)%4]) + Wt + md4Const[r/16], md4Rotate[r] ); \
213}
214
215//
216// IROUND is the initial round that loads the message and copies it into our buffer.
217//
218#define IROUND( r, Func ) { \
219 Wt = SYMCRYPT_LOAD_LSBFIRST32( &pbData[ 4*md4MsgIndex[r] ] ); \
220 W[r] = Wt; \
221 CROUND( r, Func ); \
222}
223
224//
225// FROUND are the subsequent rounds.
226//
227#define FROUND( r, Func ) { \
228 Wt = W[md4MsgIndex[r]];\
229 CROUND( r, Func ); \
230}
231
232VOID
238 _Out_ SIZE_T * pcbRemaining )
239{
240
243 UINT32 Wt;
244
245 ad[0] = pChain->H[0];
246 ad[1] = pChain->H[3];
247 ad[2] = pChain->H[2];
248 ad[3] = pChain->H[1];
249
250 while( cbData >= 64 )
251 {
252 //
253 // initial rounds 1 to 16
254 //
255
256 IROUND( 0, F );
257 IROUND( 1, F );
258 IROUND( 2, F );
259 IROUND( 3, F );
260 IROUND( 4, F );
261 IROUND( 5, F );
262 IROUND( 6, F );
263 IROUND( 7, F );
264 IROUND( 8, F );
265 IROUND( 9, F );
266 IROUND( 10, F );
267 IROUND( 11, F );
268 IROUND( 12, F );
269 IROUND( 13, F );
270 IROUND( 14, F );
271 IROUND( 15, F );
272
273 FROUND( 16, G );
274 FROUND( 17, G );
275 FROUND( 18, G );
276 FROUND( 19, G );
277 FROUND( 20, G );
278 FROUND( 21, G );
279 FROUND( 22, G );
280 FROUND( 23, G );
281 FROUND( 24, G );
282 FROUND( 25, G );
283 FROUND( 26, G );
284 FROUND( 27, G );
285 FROUND( 28, G );
286 FROUND( 29, G );
287 FROUND( 30, G );
288 FROUND( 31, G );
289
290 FROUND( 32, H );
291 FROUND( 33, H );
292 FROUND( 34, H );
293 FROUND( 35, H );
294 FROUND( 36, H );
295 FROUND( 37, H );
296 FROUND( 38, H );
297 FROUND( 39, H );
298 FROUND( 40, H );
299 FROUND( 41, H );
300 FROUND( 42, H );
301 FROUND( 43, H );
302 FROUND( 44, H );
303 FROUND( 45, H );
304 FROUND( 46, H );
305 FROUND( 47, H );
306
307 pChain->H[0] = ad[0] = ad[0] + pChain->H[0];
308 pChain->H[3] = ad[1] = ad[1] + pChain->H[3];
309 pChain->H[2] = ad[2] = ad[2] + pChain->H[2];
310 pChain->H[1] = ad[3] = ad[3] + pChain->H[1];
311
312 pbData += 64;
313 cbData -= 64;
314 }
315
316 *pcbRemaining = cbData;
317 //
318 // Wipe the variables;
319 //
320 SymCryptWipeKnownSize( ad, sizeof( ad ) );
321 SymCryptWipeKnownSize( W, sizeof( W ) );
322 SYMCRYPT_FORCE_WRITE32( &Wt, 0 );
323}
324
325VOID
330{
331 SYMCRYPT_ALIGN SYMCRYPT_MD4_STATE_EXPORT_BLOB blob; // local copy to have proper alignment.
333
335
336 SymCryptWipeKnownSize( &blob, sizeof( blob ) ); // wipe to avoid any data leakage
337
338 blob.header.magic = SYMCRYPT_BLOB_MAGIC;
340 blob.header.type = SymCryptBlobTypeMd4State;
341
342 //
343 // Copy the relevant data. Buffer will be 0-padded.
344 //
345
346 SymCryptUint32ToLsbFirst( &pState->chain.H[0], &blob.chain[0], 4 );
347 blob.dataLength = pState->dataLengthL;
348 memcpy( &blob.buffer[0], &pState->buffer[0], blob.dataLength & 0x3f );
349
350 SYMCRYPT_ASSERT( (PCBYTE) &blob + sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ) == (PCBYTE) &blob.trailer );
351 SymCryptMarvin32( SymCryptMarvin32DefaultSeed, (PCBYTE) &blob, sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ), &blob.trailer.checksum[0] );
352
353 memcpy( pbBlob, &blob, sizeof( blob ) );
354
355//cleanup:
356 SymCryptWipeKnownSize( &blob, sizeof( blob ) );
357 return;
358}
359
365{
366 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
367 SYMCRYPT_ALIGN SYMCRYPT_MD4_STATE_EXPORT_BLOB blob; // local copy to have proper alignment.
368 BYTE checksum[8];
369
371 memcpy( &blob, pbBlob, sizeof( blob ) );
372
373 if( blob.header.magic != SYMCRYPT_BLOB_MAGIC ||
374 blob.header.size != SYMCRYPT_MD4_STATE_EXPORT_SIZE ||
375 blob.header.type != SymCryptBlobTypeMd4State )
376 {
377 scError = SYMCRYPT_INVALID_BLOB;
378 goto cleanup;
379 }
380
382 if( memcmp( checksum, &blob.trailer.checksum[0], 8 ) != 0 )
383 {
384 scError = SYMCRYPT_INVALID_BLOB;
385 goto cleanup;
386 }
387
388 SymCryptLsbFirstToUint32( &blob.chain[0], &pState->chain.H[0], 4 );
389 pState->dataLengthL = blob.dataLength;
390 pState->dataLengthH = 0;
391 pState->bytesInBuffer = blob.dataLength & 0x3f;
392 memcpy( &pState->buffer[0], &blob.buffer[0], pState->bytesInBuffer );
393
395
396cleanup:
397 SymCryptWipeKnownSize( &blob, sizeof(blob) );
398 return scError;
399}
400
401
402
403//
404// Simple test vector for FIPS module testing
405//
406
407static const BYTE md4KATAnswer[ 16 ] = {
408 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
409 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d,
410} ;
411
412VOID
415{
417
419
420 SymCryptInjectError( result, sizeof( result ) );
421
422 if( memcmp( result, md4KATAnswer, sizeof( result ) ) != 0 ) {
423 SymCryptFatal( 'MD4t' );
424 }
425}
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
@ SymCryptBlobTypeMd4State
Definition: sc_lib.h:1062
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
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
VOID SYMCRYPT_CALL SymCryptMd4Result(_Inout_ PSYMCRYPT_MD4_STATE pState, _Out_writes_(SYMCRYPT_MD4_RESULT_SIZE) PBYTE pbResult)
Definition: md4.c:152
VOID SYMCRYPT_CALL SymCryptMd4StateExport(_In_ PCSYMCRYPT_MD4_STATE pState, _Out_writes_bytes_(SYMCRYPT_MD4_STATE_EXPORT_SIZE) PBYTE pbBlob)
Definition: md4.c:327
VOID SYMCRYPT_CALL SymCryptMd4AppendBlocks(_Inout_ PSYMCRYPT_MD4_CHAINING_STATE pChain, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_ SIZE_T *pcbRemaining)
Definition: md4.c:234
const SYMCRYPT_HASH SymCryptMd4Algorithm_default
Definition: md4.c:33
#define FROUND(r, Func)
Definition: md4.c:227
VOID SYMCRYPT_CALL SymCryptMd4Selftest(void)
Definition: md4.c:414
static const UINT32 md4InitialState[4]
Definition: md4.c:93
static const UINT32 md4Const[3]
Definition: md4.c:52
#define F(x, y, z)
Definition: md4.c:178
static const BYTE md4KATAnswer[16]
Definition: md4.c:407
VOID SYMCRYPT_CALL SymCryptMd4Init(_Out_ PSYMCRYPT_MD4_STATE pState)
Definition: md4.c:117
static const int md4Rotate[48]
Definition: md4.c:62
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMd4StateImport(_Out_ PSYMCRYPT_MD4_STATE pState, _In_reads_bytes_(SYMCRYPT_MD4_STATE_EXPORT_SIZE) PCBYTE pbBlob)
Definition: md4.c:362
static const int md4MsgIndex[48]
Definition: md4.c:84
#define G(x, y, z)
Definition: md4.c:179
#define H(x, y, z)
Definition: md4.c:180
const PCSYMCRYPT_HASH SymCryptMd4Algorithm
Definition: md4.c:46
VOID SYMCRYPT_CALL SymCryptMd4Append(_Inout_ PSYMCRYPT_MD4_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: md4.c:139
#define IROUND(r, Func)
Definition: md4.c:218
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)
VOID SYMCRYPT_CALL SymCryptMd4StateCopy(_In_ PCSYMCRYPT_MD4_STATE pSrc, _Out_ PSYMCRYPT_MD4_STATE pDst)
#define SYMCRYPT_MD4_INPUT_BLOCK_SIZE
Definition: symcrypt.h:955
VOID SYMCRYPT_CALL SymCryptMd4(_In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_writes_(SYMCRYPT_MD4_RESULT_SIZE) PBYTE pbResult)
#define SYMCRYPT_FORCE_WRITE32(_p, _v)
Definition: symcrypt.h:423
PCSYMCRYPT_MARVIN32_EXPANDED_SEED const SymCryptMarvin32DefaultSeed
Definition: marvin32.c:29
#define SYMCRYPT_MD4_RESULT_SIZE
Definition: symcrypt.h:954
SYMCRYPT_ERROR
Definition: symcrypt.h:227
#define SYMCRYPT_ALIGN
#define SYMCRYPT_CALL
struct _SYMCRYPT_HASH SYMCRYPT_HASH
#define SYMCRYPT_FIELD_SIZE(type, field)
* PSYMCRYPT_MD4_CHAINING_STATE
SYMCRYPT_MD4_STATE
const SYMCRYPT_HASH * PCSYMCRYPT_HASH
PCBYTE PBYTE SIZE_T cbData
#define SYMCRYPT_SET_MAGIC(p)
#define SYMCRYPT_FIELD_OFFSET(type, field)
* PSYMCRYPT_COMMON_HASH_STATE
PSYMCRYPT_COMMON_HASH_STATE pState
#define SYMCRYPT_MD4_STATE_EXPORT_SIZE
const BYTE * PCBYTE
PCBYTE pbData
* PSYMCRYPT_MD4_STATE
#define SYMCRYPT_CHECK_MAGIC(p)
const SYMCRYPT_MD4_STATE * PCSYMCRYPT_MD4_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