Coverage Report

Created: 2024-11-21 07:03

/src/SymCrypt/lib/md2.c
Line
Count
Source (jump to first uncovered line)
1
//
2
// Md2.c
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
//
7
// This module contains the routines to implement MD2 from RFC 1319
8
//
9
// This is a new implementation, NOT based on the existing one in RSA32.lib,
10
// which is the one from RSA data security.
11
//
12
// The implementation had to be refreshed anyway to conform to our coding
13
// guidelines for cryptographic functions.
14
// Re-implementing the function along the lines of our SHA-family implementations
15
// was easy, and it removes a file with RSA copyright from our system.
16
//
17
// The only data copied for this implementation is the S table from the
18
// RFC.
19
//
20
21
#include "precomp.h"
22
23
//
24
// See the symcrypt.h file for documentation on what the various functions do.
25
//
26
27
const SYMCRYPT_HASH SymCryptMd2Algorithm_default = {
28
    &SymCryptMd2Init,
29
    &SymCryptMd2Append,
30
    &SymCryptMd2Result,
31
    &SymCryptMd2AppendBlocks,
32
    &SymCryptMd2StateCopy,
33
    sizeof( SYMCRYPT_MD2_STATE ),
34
    SYMCRYPT_MD2_RESULT_SIZE,
35
    SYMCRYPT_MD2_INPUT_BLOCK_SIZE,
36
    SYMCRYPT_FIELD_OFFSET( SYMCRYPT_MD2_STATE, chain ),
37
    SYMCRYPT_FIELD_SIZE( SYMCRYPT_MD2_STATE, chain ),
38
};
39
40
const PCSYMCRYPT_HASH SymCryptMd2Algorithm = &SymCryptMd2Algorithm_default;
41
42
//
43
// These entries are called S[i] in RFC1319
44
//
45
const BYTE SymCryptMd2STable[256] = {
46
    41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
47
    19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
48
    76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
49
    138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
50
    245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
51
    148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
52
    39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
53
    181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
54
    150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
55
    112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
56
    96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
57
    85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
58
    234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
59
    129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
60
    8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
61
    203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
62
    166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
63
    31, 26, 219, 153, 141, 51, 159, 17, 131, 20
64
};
65
66
67
//
68
// SymCryptMd2
69
//
70
#define ALG MD2
71
#define Alg Md2
72
#include "hash_pattern.c"
73
#undef ALG
74
#undef Alg
75
76
77
//
78
// SymCryptMd2Init
79
//
80
VOID
81
SYMCRYPT_CALL
82
SymCryptMd2Init( _Out_ PSYMCRYPT_MD2_STATE  pState )
83
216
{
84
    //
85
    // We use the secure wipe as the init routine is also used to re-initialize
86
    // (and wipe) the state after a hash computation.
87
    // In that case the compiler might conclude that this wipe can be optimized
88
    // away, and that would leak data.
89
    //
90
216
    SymCryptWipeKnownSize( pState, sizeof( *pState ) );
91
216
    SYMCRYPT_SET_MAGIC( pState );
92
216
}
93
94
95
//
96
// SymCryptMd2Append
97
//
98
VOID
99
SYMCRYPT_CALL
100
SymCryptMd2Append( _Inout_              PSYMCRYPT_MD2_STATE    pState,
101
                   _In_reads_( cbData ) PCBYTE                 pbData,
102
                                        SIZE_T                 cbData )
103
12.5k
{
104
12.5k
    SymCryptHashAppendInternal( SymCryptMd2Algorithm, (PSYMCRYPT_COMMON_HASH_STATE)pState, pbData, cbData );
105
12.5k
}
106
107
108
//
109
// SymCryptMd2Result
110
//
111
VOID
112
SYMCRYPT_CALL
113
SymCryptMd2Result(  _Inout_                                 PSYMCRYPT_MD2_STATE state,
114
                   _Out_writes_( SYMCRYPT_MD2_RESULT_SIZE ) PBYTE               pbResult )
115
108
{
116
    //
117
    // The buffer is never completely full, so it is easy to compute the actual padding.
118
    //
119
108
    SIZE_T tmp;
120
108
    SIZE_T paddingBytes = 16 - state->bytesInBuffer;
121
122
123
108
    SYMCRYPT_CHECK_MAGIC( state );
124
125
108
    memset( &state->buffer[state->bytesInBuffer], (BYTE)paddingBytes, paddingBytes );
126
127
108
    SymCryptMd2AppendBlocks( &state->chain, state->buffer, SYMCRYPT_MD2_INPUT_BLOCK_SIZE, &tmp );
128
129
    //
130
    // Append the checksum
131
    //
132
108
    SymCryptMd2AppendBlocks( &state->chain, state->chain.C, SYMCRYPT_MD2_INPUT_BLOCK_SIZE, &tmp );
133
134
108
    memcpy( pbResult, &state->chain.X[0], SYMCRYPT_MD2_RESULT_SIZE );
135
136
    //
137
    // Wipe & re-initialize
138
    //
139
    // (Our init code wipes the buffer too, so we don't have to.)
140
    //
141
108
    SymCryptMd2Init( state );
142
108
}
143
144
145
VOID
146
SYMCRYPT_CALL
147
SymCryptMd2AppendBlocks(
148
    _Inout_                 PSYMCRYPT_MD2_CHAINING_STATE    pChain,
149
    _In_reads_( cbData )    PCBYTE                          pbData,
150
                            SIZE_T                          cbData,
151
    _Out_                   SIZE_T                        * pcbRemaining )
152
854
{
153
    //
154
    // For variable names see RFC 1319.
155
    //
156
854
    unsigned int t;
157
854
    int j,k;
158
159
142k
    while( cbData >= SYMCRYPT_MD2_INPUT_BLOCK_SIZE )
160
141k
    {
161
141k
        BYTE L;
162
        //
163
        // read the data once into our structure
164
        //
165
141k
        memcpy( &pChain->X[16], pbData, SYMCRYPT_MD2_INPUT_BLOCK_SIZE );
166
167
        //
168
        // Update the checksum block.
169
        // The L value at the end of the previous block is in the last byte of the checksum
170
        //
171
141k
        L = pChain->C[15];
172
173
2.40M
        for( j=0; j<16; j++ )
174
2.26M
        {
175
2.26M
            pChain->C[j] = L = pChain->C[j] ^  SymCryptMd2STable[ L ^ pChain->X[16+j] ];
176
2.26M
        }
177
178
        //
179
        // Now we compute the actual hash
180
        //
181
141k
        SymCryptXorBytes( &pChain->X[0], &pChain->X[16], &pChain->X[32], 16 );
182
183
141k
        t = 0;
184
2.68M
        for( j=0; j<18; j++ )
185
2.54M
        {
186
124M
            for( k=0; k<48; k++ )
187
122M
            {
188
122M
                t = pChain->X[k] ^ SymCryptMd2STable[t];
189
122M
                pChain->X[k] = (BYTE) t;
190
122M
            }
191
2.54M
            t = (t + j)& 0xff;
192
2.54M
        }
193
194
141k
    pbData += SYMCRYPT_MD2_INPUT_BLOCK_SIZE;
195
141k
    cbData -= SYMCRYPT_MD2_INPUT_BLOCK_SIZE;
196
141k
    }
197
198
854
    *pcbRemaining = cbData;
199
854
}
200
201
202
VOID
203
SYMCRYPT_CALL
204
SymCryptMd2StateExport(
205
    _In_                                                    PCSYMCRYPT_MD2_STATE    pState,
206
    _Out_writes_bytes_( SYMCRYPT_MD2_STATE_EXPORT_SIZE )    PBYTE                   pbBlob )
207
0
{
208
0
    SYMCRYPT_ALIGN SYMCRYPT_MD2_STATE_EXPORT_BLOB    blob;           // local copy to have proper alignment.
209
0
    C_ASSERT( sizeof( blob ) == SYMCRYPT_MD2_STATE_EXPORT_SIZE );
210
211
0
    SYMCRYPT_CHECK_MAGIC( pState );
212
213
0
    SymCryptWipeKnownSize( &blob, sizeof( blob ) ); // wipe to avoid any data leakage
214
215
0
    blob.header.magic = SYMCRYPT_BLOB_MAGIC;
216
0
    blob.header.size = SYMCRYPT_MD2_STATE_EXPORT_SIZE;
217
0
    blob.header.type = SymCryptBlobTypeMd2State;
218
219
    //
220
    // Copy the relevant data. Buffer will be 0-padded.
221
    //
222
0
    memcpy( &blob.C[0], &pState->chain.C[0], 16 );
223
0
    memcpy( &blob.X[0], &pState->chain.X[0], 16 );
224
0
    blob.bytesInBuffer = (UINT32) pState->bytesInBuffer;
225
0
    memcpy( &blob.buffer[0], &pState->buffer[0], blob.bytesInBuffer );
226
227
0
    SYMCRYPT_ASSERT( (PCBYTE) &blob + sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ) == (PCBYTE) &blob.trailer );
228
0
    SymCryptMarvin32( SymCryptMarvin32DefaultSeed, (PCBYTE) &blob, sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ), &blob.trailer.checksum[0] );
229
230
0
    memcpy( pbBlob, &blob, sizeof( blob ) );
231
232
//cleanup:
233
0
    SymCryptWipeKnownSize( &blob, sizeof( blob ) );
234
0
    return;
235
0
}
236
237
SYMCRYPT_ERROR
238
SYMCRYPT_CALL
239
SymCryptMd2StateImport(
240
    _Out_                                               PSYMCRYPT_MD2_STATE     pState,
241
    _In_reads_bytes_( SYMCRYPT_MD2_STATE_EXPORT_SIZE)   PCBYTE                  pbBlob )
242
0
{
243
0
    SYMCRYPT_ERROR                  scError = SYMCRYPT_NO_ERROR;
244
0
    SYMCRYPT_ALIGN SYMCRYPT_MD2_STATE_EXPORT_BLOB  blob;                       // local copy to have proper alignment.
245
0
    BYTE                            checksum[8];
246
247
0
    C_ASSERT( sizeof( blob ) == SYMCRYPT_MD2_STATE_EXPORT_SIZE );
248
0
    memcpy( &blob, pbBlob, sizeof( blob ) );
249
250
0
    if( blob.header.magic != SYMCRYPT_BLOB_MAGIC ||
251
0
        blob.header.size != SYMCRYPT_MD2_STATE_EXPORT_SIZE ||
252
0
        blob.header.type != SymCryptBlobTypeMd2State )
253
0
    {
254
0
        scError = SYMCRYPT_INVALID_BLOB;
255
0
        goto cleanup;
256
0
    }
257
258
0
    SymCryptMarvin32( SymCryptMarvin32DefaultSeed, (PCBYTE) &blob, sizeof( blob ) - sizeof( SYMCRYPT_BLOB_TRAILER ), checksum );
259
0
    if( memcmp( checksum, &blob.trailer.checksum[0], 8 ) != 0 )
260
0
    {
261
0
        scError = SYMCRYPT_INVALID_BLOB;
262
0
        goto cleanup;
263
0
    }
264
265
0
    memcpy( &pState->chain.C[0], &blob.C[0], 16 );
266
0
    memcpy( &pState->chain.X[0], &blob.X[0], 16 );
267
0
    memcpy( &pState->buffer[0], &blob.buffer[0], 16 );
268
0
    pState->bytesInBuffer = blob.bytesInBuffer;
269
270
0
    pState->dataLengthL = blob.bytesInBuffer;
271
0
    pState->dataLengthH = 1;
272
273
0
    SYMCRYPT_SET_MAGIC( pState );
274
275
0
cleanup:
276
0
    SymCryptWipeKnownSize( &blob, sizeof(blob) );
277
0
    return scError;
278
0
}
279
280
281
282
283
284
285
//
286
// Simple test vector for FIPS module testing
287
//
288
289
static const BYTE   md2KATAnswer[ 16 ] = {
290
    0xda, 0x85, 0x3b, 0x0d, 0x3f, 0x88, 0xd9, 0x9b,
291
    0x30, 0x28, 0x3a, 0x69, 0xe6, 0xde, 0xd6, 0xbb,
292
} ;
293
294
VOID
295
SYMCRYPT_CALL
296
SymCryptMd2Selftest(void)
297
0
{
298
0
    BYTE result[SYMCRYPT_MD2_RESULT_SIZE];
299
300
0
    SymCryptMd2( SymCryptTestMsg3, sizeof( SymCryptTestMsg3 ), result );
301
302
0
    SymCryptInjectError( result, sizeof( result ) );
303
304
0
    if( memcmp( result, md2KATAnswer, sizeof( result ) ) != 0 ) {
305
0
        SymCryptFatal( 'MD2t' );
306
0
    }
307
0
}
308
309