Line | Count | Source (jump to first uncovered line) |
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 | | |
33 | | const SYMCRYPT_HASH SymCryptMd4Algorithm_default = { |
34 | | &SymCryptMd4Init, |
35 | | &SymCryptMd4Append, |
36 | | &SymCryptMd4Result, |
37 | | &SymCryptMd4AppendBlocks, |
38 | | &SymCryptMd4StateCopy, |
39 | | sizeof( SYMCRYPT_MD4_STATE ), |
40 | | SYMCRYPT_MD4_RESULT_SIZE, |
41 | | SYMCRYPT_MD4_INPUT_BLOCK_SIZE, |
42 | | SYMCRYPT_FIELD_OFFSET( SYMCRYPT_MD4_STATE, chain ), |
43 | | SYMCRYPT_FIELD_SIZE( SYMCRYPT_MD4_STATE, chain ), |
44 | | }; |
45 | | |
46 | | const PCSYMCRYPT_HASH SymCryptMd4Algorithm = &SymCryptMd4Algorithm_default; |
47 | | |
48 | | // |
49 | | // The round constants used by MD4 |
50 | | // |
51 | | // |
52 | | static 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 | | // |
62 | | static 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 | | // |
84 | | static 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 | | // |
93 | | static 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 | | // |
115 | | VOID |
116 | | SYMCRYPT_CALL |
117 | | SymCryptMd4Init( _Out_ PSYMCRYPT_MD4_STATE pState ) |
118 | 184 | { |
119 | 184 | SYMCRYPT_SET_MAGIC( pState ); |
120 | | |
121 | 184 | pState->dataLengthL = 0; |
122 | 184 | pState->dataLengthH = 0; |
123 | 184 | pState->bytesInBuffer = 0; |
124 | | |
125 | 184 | 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 | 184 | } |
132 | | |
133 | | |
134 | | // |
135 | | // SymCryptMd4Append |
136 | | // |
137 | | VOID |
138 | | SYMCRYPT_CALL |
139 | | SymCryptMd4Append( _Inout_ PSYMCRYPT_MD4_STATE pState, |
140 | | _In_reads_( cbData ) PCBYTE pbData, |
141 | | SIZE_T cbData ) |
142 | 14.4k | { |
143 | 14.4k | SymCryptHashAppendInternal( SymCryptMd4Algorithm, (PSYMCRYPT_COMMON_HASH_STATE)pState, pbData, cbData ); |
144 | 14.4k | } |
145 | | |
146 | | |
147 | | // |
148 | | // SymCryptmd4Result |
149 | | // |
150 | | VOID |
151 | | SYMCRYPT_CALL |
152 | | SymCryptMd4Result( |
153 | | _Inout_ PSYMCRYPT_MD4_STATE pState, |
154 | | _Out_writes_( SYMCRYPT_MD4_RESULT_SIZE ) PBYTE pbResult ) |
155 | 92 | { |
156 | 92 | SymCryptHashCommonPaddingMd4Style( SymCryptMd4Algorithm, (PSYMCRYPT_COMMON_HASH_STATE)pState ); |
157 | | |
158 | | // |
159 | | // Write the output in the correct byte order |
160 | | // |
161 | 92 | 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 | 92 | SymCryptWipeKnownSize( pState, sizeof( *pState )); |
168 | 92 | SymCryptMd4Init( pState ); |
169 | 92 | } |
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 | 2.85M | #define CROUND( r, Func ) { \ |
212 | 2.85M | 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 | 2.85M | } |
214 | | |
215 | | // |
216 | | // IROUND is the initial round that loads the message and copies it into our buffer. |
217 | | // |
218 | 951k | #define IROUND( r, Func ) { \ |
219 | 951k | Wt = SYMCRYPT_LOAD_LSBFIRST32( &pbData[ 4*md4MsgIndex[r] ] ); \ |
220 | 951k | W[r] = Wt; \ |
221 | 951k | CROUND( r, Func ); \ |
222 | 951k | } |
223 | | |
224 | | // |
225 | | // FROUND are the subsequent rounds. |
226 | | // |
227 | 1.90M | #define FROUND( r, Func ) { \ |
228 | 1.90M | Wt = W[md4MsgIndex[r]];\ |
229 | 1.90M | CROUND( r, Func ); \ |
230 | 1.90M | } |
231 | | |
232 | | VOID |
233 | | SYMCRYPT_CALL |
234 | | SymCryptMd4AppendBlocks( |
235 | | _Inout_ PSYMCRYPT_MD4_CHAINING_STATE pChain, |
236 | | _In_reads_( cbData ) PCBYTE pbData, |
237 | | SIZE_T cbData, |
238 | | _Out_ SIZE_T * pcbRemaining ) |
239 | 559 | { |
240 | | |
241 | 559 | SYMCRYPT_ALIGN UINT32 W[16]; |
242 | 559 | SYMCRYPT_ALIGN UINT32 ad[4]; |
243 | 559 | UINT32 Wt; |
244 | | |
245 | 559 | ad[0] = pChain->H[0]; |
246 | 559 | ad[1] = pChain->H[3]; |
247 | 559 | ad[2] = pChain->H[2]; |
248 | 559 | ad[3] = pChain->H[1]; |
249 | | |
250 | 60.0k | while( cbData >= 64 ) |
251 | 59.4k | { |
252 | | // |
253 | | // initial rounds 1 to 16 |
254 | | // |
255 | | |
256 | 59.4k | IROUND( 0, F ); |
257 | 59.4k | IROUND( 1, F ); |
258 | 59.4k | IROUND( 2, F ); |
259 | 59.4k | IROUND( 3, F ); |
260 | 59.4k | IROUND( 4, F ); |
261 | 59.4k | IROUND( 5, F ); |
262 | 59.4k | IROUND( 6, F ); |
263 | 59.4k | IROUND( 7, F ); |
264 | 59.4k | IROUND( 8, F ); |
265 | 59.4k | IROUND( 9, F ); |
266 | 59.4k | IROUND( 10, F ); |
267 | 59.4k | IROUND( 11, F ); |
268 | 59.4k | IROUND( 12, F ); |
269 | 59.4k | IROUND( 13, F ); |
270 | 59.4k | IROUND( 14, F ); |
271 | 59.4k | IROUND( 15, F ); |
272 | | |
273 | 59.4k | FROUND( 16, G ); |
274 | 59.4k | FROUND( 17, G ); |
275 | 59.4k | FROUND( 18, G ); |
276 | 59.4k | FROUND( 19, G ); |
277 | 59.4k | FROUND( 20, G ); |
278 | 59.4k | FROUND( 21, G ); |
279 | 59.4k | FROUND( 22, G ); |
280 | 59.4k | FROUND( 23, G ); |
281 | 59.4k | FROUND( 24, G ); |
282 | 59.4k | FROUND( 25, G ); |
283 | 59.4k | FROUND( 26, G ); |
284 | 59.4k | FROUND( 27, G ); |
285 | 59.4k | FROUND( 28, G ); |
286 | 59.4k | FROUND( 29, G ); |
287 | 59.4k | FROUND( 30, G ); |
288 | 59.4k | FROUND( 31, G ); |
289 | | |
290 | 59.4k | FROUND( 32, H ); |
291 | 59.4k | FROUND( 33, H ); |
292 | 59.4k | FROUND( 34, H ); |
293 | 59.4k | FROUND( 35, H ); |
294 | 59.4k | FROUND( 36, H ); |
295 | 59.4k | FROUND( 37, H ); |
296 | 59.4k | FROUND( 38, H ); |
297 | 59.4k | FROUND( 39, H ); |
298 | 59.4k | FROUND( 40, H ); |
299 | 59.4k | FROUND( 41, H ); |
300 | 59.4k | FROUND( 42, H ); |
301 | 59.4k | FROUND( 43, H ); |
302 | 59.4k | FROUND( 44, H ); |
303 | 59.4k | FROUND( 45, H ); |
304 | 59.4k | FROUND( 46, H ); |
305 | 59.4k | FROUND( 47, H ); |
306 | | |
307 | 59.4k | pChain->H[0] = ad[0] = ad[0] + pChain->H[0]; |
308 | 59.4k | pChain->H[3] = ad[1] = ad[1] + pChain->H[3]; |
309 | 59.4k | pChain->H[2] = ad[2] = ad[2] + pChain->H[2]; |
310 | 59.4k | pChain->H[1] = ad[3] = ad[3] + pChain->H[1]; |
311 | | |
312 | 59.4k | pbData += 64; |
313 | 59.4k | cbData -= 64; |
314 | 59.4k | } |
315 | | |
316 | 559 | *pcbRemaining = cbData; |
317 | | // |
318 | | // Wipe the variables; |
319 | | // |
320 | 559 | SymCryptWipeKnownSize( ad, sizeof( ad ) ); |
321 | 559 | SymCryptWipeKnownSize( W, sizeof( W ) ); |
322 | 559 | SYMCRYPT_FORCE_WRITE32( &Wt, 0 ); |
323 | 559 | } |
324 | | |
325 | | VOID |
326 | | SYMCRYPT_CALL |
327 | | SymCryptMd4StateExport( |
328 | | _In_ PCSYMCRYPT_MD4_STATE pState, |
329 | | _Out_writes_bytes_( SYMCRYPT_MD4_STATE_EXPORT_SIZE ) PBYTE pbBlob ) |
330 | 0 | { |
331 | 0 | SYMCRYPT_ALIGN SYMCRYPT_MD4_STATE_EXPORT_BLOB blob; // local copy to have proper alignment. |
332 | 0 | C_ASSERT( sizeof( blob ) == SYMCRYPT_MD4_STATE_EXPORT_SIZE ); |
333 | |
|
334 | 0 | SYMCRYPT_CHECK_MAGIC( pState ); |
335 | |
|
336 | 0 | SymCryptWipeKnownSize( &blob, sizeof( blob ) ); // wipe to avoid any data leakage |
337 | |
|
338 | 0 | blob.header.magic = SYMCRYPT_BLOB_MAGIC; |
339 | 0 | blob.header.size = SYMCRYPT_MD4_STATE_EXPORT_SIZE; |
340 | 0 | blob.header.type = SymCryptBlobTypeMd4State; |
341 | | |
342 | | // |
343 | | // Copy the relevant data. Buffer will be 0-padded. |
344 | | // |
345 | |
|
346 | 0 | SymCryptUint32ToLsbFirst( &pState->chain.H[0], &blob.chain[0], 4 ); |
347 | 0 | blob.dataLength = pState->dataLengthL; |
348 | 0 | memcpy( &blob.buffer[0], &pState->buffer[0], blob.dataLength & 0x3f ); |
349 | |
|
350 | 0 | SYMCRYPT_ASSERT( (PCBYTE) &blob + sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ) == (PCBYTE) &blob.trailer ); |
351 | 0 | SymCryptMarvin32( SymCryptMarvin32DefaultSeed, (PCBYTE) &blob, sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ), &blob.trailer.checksum[0] ); |
352 | |
|
353 | 0 | memcpy( pbBlob, &blob, sizeof( blob ) ); |
354 | | |
355 | | //cleanup: |
356 | 0 | SymCryptWipeKnownSize( &blob, sizeof( blob ) ); |
357 | 0 | return; |
358 | 0 | } |
359 | | |
360 | | SYMCRYPT_ERROR |
361 | | SYMCRYPT_CALL |
362 | | SymCryptMd4StateImport( |
363 | | _Out_ PSYMCRYPT_MD4_STATE pState, |
364 | | _In_reads_bytes_( SYMCRYPT_MD4_STATE_EXPORT_SIZE) PCBYTE pbBlob ) |
365 | 0 | { |
366 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
367 | 0 | SYMCRYPT_ALIGN SYMCRYPT_MD4_STATE_EXPORT_BLOB blob; // local copy to have proper alignment. |
368 | 0 | BYTE checksum[8]; |
369 | |
|
370 | 0 | C_ASSERT( sizeof( blob ) == SYMCRYPT_MD4_STATE_EXPORT_SIZE ); |
371 | 0 | memcpy( &blob, pbBlob, sizeof( blob ) ); |
372 | |
|
373 | 0 | if( blob.header.magic != SYMCRYPT_BLOB_MAGIC || |
374 | 0 | blob.header.size != SYMCRYPT_MD4_STATE_EXPORT_SIZE || |
375 | 0 | blob.header.type != SymCryptBlobTypeMd4State ) |
376 | 0 | { |
377 | 0 | scError = SYMCRYPT_INVALID_BLOB; |
378 | 0 | goto cleanup; |
379 | 0 | } |
380 | | |
381 | 0 | SymCryptMarvin32( SymCryptMarvin32DefaultSeed, (PCBYTE) &blob, sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ), checksum ); |
382 | 0 | if( memcmp( checksum, &blob.trailer.checksum[0], 8 ) != 0 ) |
383 | 0 | { |
384 | 0 | scError = SYMCRYPT_INVALID_BLOB; |
385 | 0 | goto cleanup; |
386 | 0 | } |
387 | | |
388 | 0 | SymCryptLsbFirstToUint32( &blob.chain[0], &pState->chain.H[0], 4 ); |
389 | 0 | pState->dataLengthL = blob.dataLength; |
390 | 0 | pState->dataLengthH = 0; |
391 | 0 | pState->bytesInBuffer = blob.dataLength & 0x3f; |
392 | 0 | memcpy( &pState->buffer[0], &blob.buffer[0], pState->bytesInBuffer ); |
393 | |
|
394 | 0 | SYMCRYPT_SET_MAGIC( pState ); |
395 | |
|
396 | 0 | cleanup: |
397 | 0 | SymCryptWipeKnownSize( &blob, sizeof(blob) ); |
398 | 0 | return scError; |
399 | 0 | } |
400 | | |
401 | | |
402 | | |
403 | | // |
404 | | // Simple test vector for FIPS module testing |
405 | | // |
406 | | |
407 | | static const BYTE md4KATAnswer[ 16 ] = { |
408 | | 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, |
409 | | 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d, |
410 | | } ; |
411 | | |
412 | | VOID |
413 | | SYMCRYPT_CALL |
414 | | SymCryptMd4Selftest(void) |
415 | 0 | { |
416 | 0 | BYTE result[SYMCRYPT_MD4_RESULT_SIZE]; |
417 | |
|
418 | 0 | SymCryptMd4( SymCryptTestMsg3, sizeof( SymCryptTestMsg3 ), result ); |
419 | |
|
420 | 0 | SymCryptInjectError( result, sizeof( result ) ); |
421 | |
|
422 | 0 | if( memcmp( result, md4KATAnswer, sizeof( result ) ) != 0 ) { |
423 | 0 | SymCryptFatal( 'MD4t' ); |
424 | 0 | } |
425 | 0 | } |
426 | | |
427 | | |