Coverage Report

Created: 2024-11-21 07:03

/src/SymCrypt/lib/md4.c
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