Coverage Report

Created: 2025-08-26 06:07

/src/sleuthkit/tsk/base/md5c.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The Sleuth Kit
3
 *
4
 */
5
6
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
7
 */
8
9
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
10
rights reserved.
11
12
License to copy and use this software is granted provided that it
13
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
14
Algorithm" in all material mentioning or referencing this software
15
or this function.
16
17
License is also granted to make and use derivative works provided
18
that such works are identified as "derived from the RSA Data
19
Security, Inc. MD5 Message-Digest Algorithm" in all material
20
mentioning or referencing the derived work.
21
22
RSA Data Security, Inc. makes no representations concerning either
23
the merchantability of this software or the suitability of this
24
software for any particular purpose. It is provided "as is"
25
without express or implied warranty of any kind.
26
27
These notices must be retained in any copies of any part of this
28
documentation and/or software.
29
 */
30
31
/** \file md5c.c
32
 * Local copy of RSA Data Security, Inc. MD5 Message-Digest Algorithm.
33
 */
34
#include "tsk_base_i.h"
35
36
/* Constants for MD5Transform routine.
37
 */
38
#define S11 7
39
#define S12 12
40
#define S13 17
41
#define S14 22
42
#define S21 5
43
#define S22 9
44
#define S23 14
45
#define S24 20
46
#define S31 4
47
#define S32 11
48
#define S33 16
49
#define S34 23
50
#define S41 6
51
#define S42 10
52
#define S43 15
53
#define S44 21
54
55
static void MD5Transform(UINT4[4], const unsigned char[64]);
56
static void Encode(unsigned char *, UINT4 *, unsigned int);
57
static void Decode(UINT4 *, const unsigned char *, unsigned int);
58
static void MD5_memcpy(POINTER, POINTER, unsigned int);
59
static void MD5_memset(POINTER, int, unsigned int);
60
61
static unsigned char PADDING[64] = {
62
    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
65
};
66
67
/* F, G, H and I are basic MD5 functions.
68
 */
69
0
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
70
0
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
71
0
#define H(x, y, z) ((x) ^ (y) ^ (z))
72
0
#define I(x, y, z) ((y) ^ ((x) | (~z)))
73
74
/* ROTATE_LEFT rotates x left n bits.
75
 */
76
0
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
77
78
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
79
Rotation is separate from addition to prevent recomputation.
80
 */
81
0
#define FF(a, b, c, d, x, s, ac) { \
82
0
 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
83
0
 (a) = ROTATE_LEFT ((a), (s)); \
84
0
 (a) += (b); \
85
0
  }
86
0
#define GG(a, b, c, d, x, s, ac) { \
87
0
 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
88
0
 (a) = ROTATE_LEFT ((a), (s)); \
89
0
 (a) += (b); \
90
0
  }
91
0
#define HH(a, b, c, d, x, s, ac) { \
92
0
 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
93
0
 (a) = ROTATE_LEFT ((a), (s)); \
94
0
 (a) += (b); \
95
0
  }
96
0
#define II(a, b, c, d, x, s, ac) { \
97
0
 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
98
0
 (a) = ROTATE_LEFT ((a), (s)); \
99
0
 (a) += (b); \
100
0
  }
101
102
/**
103
 * \ingroup baselib
104
 * Initialize a MD5 context structure so that data can be added to it.
105
 * @param context Pointer to context to initialize
106
 */
107
void
108
TSK_MD5_Init(TSK_MD5_CTX * context)
109
0
{
110
0
    context->count[0] = context->count[1] = 0;
111
    /* Load magic initialization constants.
112
     */
113
0
    context->state[0] = 0x67452301;
114
0
    context->state[1] = 0xefcdab89;
115
0
    context->state[2] = 0x98badcfe;
116
0
    context->state[3] = 0x10325476;
117
0
}
118
119
/**
120
 * \ingroup baselib
121
 * Add data to an initialized MD5 operation.
122
 * @param context Initialized context to add data to
123
 * @param input Buffer of data to process
124
 * @param inputLen Number of bytes in input
125
 */
126
void
127
TSK_MD5_Update(TSK_MD5_CTX * context, const unsigned char *input,
128
    unsigned int inputLen)
129
0
{
130
0
    unsigned int i, index, partLen;
131
132
    /* Compute number of bytes mod 64 */
133
0
    index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
134
135
    /* Update number of bits */
136
0
    if ((context->count[0] += ((UINT4) inputLen << 3))
137
0
        < ((UINT4) inputLen << 3))
138
0
        context->count[1]++;
139
0
    context->count[1] += ((UINT4) inputLen >> 29);
140
141
0
    partLen = 64 - index;
142
143
    /* Transform as many times as possible.
144
     */
145
0
    if (inputLen >= partLen) {
146
0
        MD5_memcpy
147
0
            ((POINTER) & context->buffer[index], (POINTER) input, partLen);
148
0
        MD5Transform(context->state, context->buffer);
149
150
0
        for (i = partLen; i + 63 < inputLen; i += 64)
151
0
            MD5Transform(context->state, &input[i]);
152
153
0
        index = 0;
154
0
    }
155
0
    else
156
0
        i = 0;
157
158
    /* Buffer remaining input */
159
0
    MD5_memcpy
160
0
        ((POINTER) & context->buffer[index], (POINTER) & input[i],
161
0
        inputLen - i);
162
0
}
163
164
/**
165
 * \ingroup baselib
166
 * Calculate the MD5 hash of the data added to this context.   Context
167
 * will be zeroed after this call.
168
 * @param context Context that has data added to it.
169
 * @param digest Buffer to store MD5 value in.
170
 */
171
void
172
TSK_MD5_Final(TSK_MD5_CTX * context, unsigned char digest[16])
173
0
{
174
0
    unsigned char bits[8];
175
0
    unsigned int index, padLen;
176
177
    /* Save number of bits */
178
0
    Encode(bits, context->count, 8);
179
180
    /* Pad out to 56 mod 64.
181
     */
182
0
    index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
183
0
    padLen = (index < 56) ? (56 - index) : (120 - index);
184
0
    TSK_MD5_Update(context, PADDING, padLen);
185
186
    /* Append length (before padding) */
187
0
    TSK_MD5_Update(context, bits, 8);
188
    /* Store state in digest */
189
0
    Encode(digest, context->state, 16);
190
191
    /* Zeroize sensitive information.
192
     */
193
0
    MD5_memset((POINTER) context, 0, sizeof(*context));
194
0
}
195
196
/* MD5 basic transformation. Transforms state based on block.
197
 */
198
static void
199
MD5Transform(UINT4 state[4], const unsigned char block[64])
200
0
{
201
0
    UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
202
203
0
    Decode(x, block, 64);
204
205
    /* Round 1 */
206
0
    FF(a, b, c, d, x[0], S11, 0xd76aa478);      /* 1 */
207
0
    FF(d, a, b, c, x[1], S12, 0xe8c7b756);      /* 2 */
208
0
    FF(c, d, a, b, x[2], S13, 0x242070db);      /* 3 */
209
0
    FF(b, c, d, a, x[3], S14, 0xc1bdceee);      /* 4 */
210
0
    FF(a, b, c, d, x[4], S11, 0xf57c0faf);      /* 5 */
211
0
    FF(d, a, b, c, x[5], S12, 0x4787c62a);      /* 6 */
212
0
    FF(c, d, a, b, x[6], S13, 0xa8304613);      /* 7 */
213
0
    FF(b, c, d, a, x[7], S14, 0xfd469501);      /* 8 */
214
0
    FF(a, b, c, d, x[8], S11, 0x698098d8);      /* 9 */
215
0
    FF(d, a, b, c, x[9], S12, 0x8b44f7af);      /* 10 */
216
0
    FF(c, d, a, b, x[10], S13, 0xffff5bb1);     /* 11 */
217
0
    FF(b, c, d, a, x[11], S14, 0x895cd7be);     /* 12 */
218
0
    FF(a, b, c, d, x[12], S11, 0x6b901122);     /* 13 */
219
0
    FF(d, a, b, c, x[13], S12, 0xfd987193);     /* 14 */
220
0
    FF(c, d, a, b, x[14], S13, 0xa679438e);     /* 15 */
221
0
    FF(b, c, d, a, x[15], S14, 0x49b40821);     /* 16 */
222
223
    /* Round 2 */
224
0
    GG(a, b, c, d, x[1], S21, 0xf61e2562);      /* 17 */
225
0
    GG(d, a, b, c, x[6], S22, 0xc040b340);      /* 18 */
226
0
    GG(c, d, a, b, x[11], S23, 0x265e5a51);     /* 19 */
227
0
    GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);      /* 20 */
228
0
    GG(a, b, c, d, x[5], S21, 0xd62f105d);      /* 21 */
229
0
    GG(d, a, b, c, x[10], S22, 0x2441453);      /* 22 */
230
0
    GG(c, d, a, b, x[15], S23, 0xd8a1e681);     /* 23 */
231
0
    GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);      /* 24 */
232
0
    GG(a, b, c, d, x[9], S21, 0x21e1cde6);      /* 25 */
233
0
    GG(d, a, b, c, x[14], S22, 0xc33707d6);     /* 26 */
234
0
    GG(c, d, a, b, x[3], S23, 0xf4d50d87);      /* 27 */
235
0
    GG(b, c, d, a, x[8], S24, 0x455a14ed);      /* 28 */
236
0
    GG(a, b, c, d, x[13], S21, 0xa9e3e905);     /* 29 */
237
0
    GG(d, a, b, c, x[2], S22, 0xfcefa3f8);      /* 30 */
238
0
    GG(c, d, a, b, x[7], S23, 0x676f02d9);      /* 31 */
239
0
    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);     /* 32 */
240
241
    /* Round 3 */
242
0
    HH(a, b, c, d, x[5], S31, 0xfffa3942);      /* 33 */
243
0
    HH(d, a, b, c, x[8], S32, 0x8771f681);      /* 34 */
244
0
    HH(c, d, a, b, x[11], S33, 0x6d9d6122);     /* 35 */
245
0
    HH(b, c, d, a, x[14], S34, 0xfde5380c);     /* 36 */
246
0
    HH(a, b, c, d, x[1], S31, 0xa4beea44);      /* 37 */
247
0
    HH(d, a, b, c, x[4], S32, 0x4bdecfa9);      /* 38 */
248
0
    HH(c, d, a, b, x[7], S33, 0xf6bb4b60);      /* 39 */
249
0
    HH(b, c, d, a, x[10], S34, 0xbebfbc70);     /* 40 */
250
0
    HH(a, b, c, d, x[13], S31, 0x289b7ec6);     /* 41 */
251
0
    HH(d, a, b, c, x[0], S32, 0xeaa127fa);      /* 42 */
252
0
    HH(c, d, a, b, x[3], S33, 0xd4ef3085);      /* 43 */
253
0
    HH(b, c, d, a, x[6], S34, 0x4881d05);       /* 44 */
254
0
    HH(a, b, c, d, x[9], S31, 0xd9d4d039);      /* 45 */
255
0
    HH(d, a, b, c, x[12], S32, 0xe6db99e5);     /* 46 */
256
0
    HH(c, d, a, b, x[15], S33, 0x1fa27cf8);     /* 47 */
257
0
    HH(b, c, d, a, x[2], S34, 0xc4ac5665);      /* 48 */
258
259
    /* Round 4 */
260
0
    II(a, b, c, d, x[0], S41, 0xf4292244);      /* 49 */
261
0
    II(d, a, b, c, x[7], S42, 0x432aff97);      /* 50 */
262
0
    II(c, d, a, b, x[14], S43, 0xab9423a7);     /* 51 */
263
0
    II(b, c, d, a, x[5], S44, 0xfc93a039);      /* 52 */
264
0
    II(a, b, c, d, x[12], S41, 0x655b59c3);     /* 53 */
265
0
    II(d, a, b, c, x[3], S42, 0x8f0ccc92);      /* 54 */
266
0
    II(c, d, a, b, x[10], S43, 0xffeff47d);     /* 55 */
267
0
    II(b, c, d, a, x[1], S44, 0x85845dd1);      /* 56 */
268
0
    II(a, b, c, d, x[8], S41, 0x6fa87e4f);      /* 57 */
269
0
    II(d, a, b, c, x[15], S42, 0xfe2ce6e0);     /* 58 */
270
0
    II(c, d, a, b, x[6], S43, 0xa3014314);      /* 59 */
271
0
    II(b, c, d, a, x[13], S44, 0x4e0811a1);     /* 60 */
272
0
    II(a, b, c, d, x[4], S41, 0xf7537e82);      /* 61 */
273
0
    II(d, a, b, c, x[11], S42, 0xbd3af235);     /* 62 */
274
0
    II(c, d, a, b, x[2], S43, 0x2ad7d2bb);      /* 63 */
275
0
    II(b, c, d, a, x[9], S44, 0xeb86d391);      /* 64 */
276
277
0
    state[0] += a;
278
0
    state[1] += b;
279
0
    state[2] += c;
280
0
    state[3] += d;
281
282
    /* Zeroize sensitive information.
283
     */
284
0
    MD5_memset((POINTER) x, 0, sizeof(x));
285
0
}
286
287
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
288
  a multiple of 4.
289
 */
290
static void
291
Encode(unsigned char *output, UINT4 *input, unsigned int len)
292
0
{
293
0
    unsigned int i, j;
294
295
0
    for (i = 0, j = 0; j < len; i++, j += 4) {
296
0
        output[j] = (unsigned char) (input[i] & 0xff);
297
0
        output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
298
0
        output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
299
0
        output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
300
0
    }
301
0
}
302
303
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
304
  a multiple of 4.
305
 */
306
static void
307
Decode(UINT4 *output,  const unsigned char *input,   unsigned int len)
308
0
{
309
0
    unsigned int i, j;
310
311
0
    for (i = 0, j = 0; j < len; i++, j += 4)
312
0
        output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
313
0
            (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) <<
314
0
            24);
315
0
}
316
317
/* Note: Replace "for loop" with standard memcpy if possible.
318
 */
319
320
static void
321
MD5_memcpy(POINTER output,   POINTER input,   unsigned int len)
322
0
{
323
0
    unsigned int i;
324
325
0
    for (i = 0; i < len; i++)
326
0
        output[i] = input[i];
327
0
}
328
329
/* Note: Replace "for loop" with standard memset if possible.
330
 */
331
static void
332
MD5_memset(POINTER output,   int value,   unsigned int len)
333
0
{
334
0
    unsigned int i;
335
336
0
    for (i = 0; i < len; i++)
337
0
        ((char *) output)[i] = (char) value;
338
0
}