Coverage Report

Created: 2024-11-21 07:03

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