Coverage Report

Created: 2025-07-01 06:54

/work/mbedtls-2.28.8/library/md5.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  RFC 1321 compliant MD5 implementation
3
 *
4
 *  Copyright The Mbed TLS Contributors
5
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6
 */
7
/*
8
 *  The MD5 algorithm was designed by Ron Rivest in 1991.
9
 *
10
 *  http://www.ietf.org/rfc/rfc1321.txt
11
 */
12
13
#include "common.h"
14
15
#if defined(MBEDTLS_MD5_C)
16
17
#include "mbedtls/md5.h"
18
#include "mbedtls/platform_util.h"
19
#include "mbedtls/error.h"
20
21
#include <string.h>
22
23
#include "mbedtls/platform.h"
24
25
#if !defined(MBEDTLS_MD5_ALT)
26
27
void mbedtls_md5_init(mbedtls_md5_context *ctx)
28
0
{
29
0
    memset(ctx, 0, sizeof(mbedtls_md5_context));
30
0
}
31
32
void mbedtls_md5_free(mbedtls_md5_context *ctx)
33
0
{
34
0
    if (ctx == NULL) {
35
0
        return;
36
0
    }
37
38
0
    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md5_context));
39
0
}
40
41
void mbedtls_md5_clone(mbedtls_md5_context *dst,
42
                       const mbedtls_md5_context *src)
43
0
{
44
0
    *dst = *src;
45
0
}
46
47
/*
48
 * MD5 context setup
49
 */
50
int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx)
51
0
{
52
0
    ctx->total[0] = 0;
53
0
    ctx->total[1] = 0;
54
55
0
    ctx->state[0] = 0x67452301;
56
0
    ctx->state[1] = 0xEFCDAB89;
57
0
    ctx->state[2] = 0x98BADCFE;
58
0
    ctx->state[3] = 0x10325476;
59
60
0
    return 0;
61
0
}
62
63
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
64
void mbedtls_md5_starts(mbedtls_md5_context *ctx)
65
0
{
66
0
    mbedtls_md5_starts_ret(ctx);
67
0
}
68
#endif
69
70
#if !defined(MBEDTLS_MD5_PROCESS_ALT)
71
int mbedtls_internal_md5_process(mbedtls_md5_context *ctx,
72
                                 const unsigned char data[64])
73
0
{
74
0
    struct {
75
0
        uint32_t X[16], A, B, C, D;
76
0
    } local;
77
78
0
    local.X[0] = MBEDTLS_GET_UINT32_LE(data,  0);
79
0
    local.X[1] = MBEDTLS_GET_UINT32_LE(data,  4);
80
0
    local.X[2] = MBEDTLS_GET_UINT32_LE(data,  8);
81
0
    local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12);
82
0
    local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16);
83
0
    local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20);
84
0
    local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24);
85
0
    local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28);
86
0
    local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32);
87
0
    local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36);
88
0
    local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40);
89
0
    local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44);
90
0
    local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48);
91
0
    local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52);
92
0
    local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56);
93
0
    local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60);
94
95
0
#define S(x, n)                                                          \
96
0
    (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
97
98
0
#define P(a, b, c, d, k, s, t)                                                \
99
0
    do                                                                  \
100
0
    {                                                                   \
101
0
        (a) += F((b), (c), (d)) + local.X[(k)] + (t);                     \
102
0
        (a) = S((a), (s)) + (b);                                         \
103
0
    } while (0)
104
105
0
    local.A = ctx->state[0];
106
0
    local.B = ctx->state[1];
107
0
    local.C = ctx->state[2];
108
0
    local.D = ctx->state[3];
109
110
0
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
111
112
0
    P(local.A, local.B, local.C, local.D,  0,  7, 0xD76AA478);
113
0
    P(local.D, local.A, local.B, local.C,  1, 12, 0xE8C7B756);
114
0
    P(local.C, local.D, local.A, local.B,  2, 17, 0x242070DB);
115
0
    P(local.B, local.C, local.D, local.A,  3, 22, 0xC1BDCEEE);
116
0
    P(local.A, local.B, local.C, local.D,  4,  7, 0xF57C0FAF);
117
0
    P(local.D, local.A, local.B, local.C,  5, 12, 0x4787C62A);
118
0
    P(local.C, local.D, local.A, local.B,  6, 17, 0xA8304613);
119
0
    P(local.B, local.C, local.D, local.A,  7, 22, 0xFD469501);
120
0
    P(local.A, local.B, local.C, local.D,  8,  7, 0x698098D8);
121
0
    P(local.D, local.A, local.B, local.C,  9, 12, 0x8B44F7AF);
122
0
    P(local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1);
123
0
    P(local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE);
124
0
    P(local.A, local.B, local.C, local.D, 12,  7, 0x6B901122);
125
0
    P(local.D, local.A, local.B, local.C, 13, 12, 0xFD987193);
126
0
    P(local.C, local.D, local.A, local.B, 14, 17, 0xA679438E);
127
0
    P(local.B, local.C, local.D, local.A, 15, 22, 0x49B40821);
128
129
0
#undef F
130
131
0
#define F(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
132
133
0
    P(local.A, local.B, local.C, local.D,  1,  5, 0xF61E2562);
134
0
    P(local.D, local.A, local.B, local.C,  6,  9, 0xC040B340);
135
0
    P(local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51);
136
0
    P(local.B, local.C, local.D, local.A,  0, 20, 0xE9B6C7AA);
137
0
    P(local.A, local.B, local.C, local.D,  5,  5, 0xD62F105D);
138
0
    P(local.D, local.A, local.B, local.C, 10,  9, 0x02441453);
139
0
    P(local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681);
140
0
    P(local.B, local.C, local.D, local.A,  4, 20, 0xE7D3FBC8);
141
0
    P(local.A, local.B, local.C, local.D,  9,  5, 0x21E1CDE6);
142
0
    P(local.D, local.A, local.B, local.C, 14,  9, 0xC33707D6);
143
0
    P(local.C, local.D, local.A, local.B,  3, 14, 0xF4D50D87);
144
0
    P(local.B, local.C, local.D, local.A,  8, 20, 0x455A14ED);
145
0
    P(local.A, local.B, local.C, local.D, 13,  5, 0xA9E3E905);
146
0
    P(local.D, local.A, local.B, local.C,  2,  9, 0xFCEFA3F8);
147
0
    P(local.C, local.D, local.A, local.B,  7, 14, 0x676F02D9);
148
0
    P(local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A);
149
150
0
#undef F
151
152
0
#define F(x, y, z) ((x) ^ (y) ^ (z))
153
154
0
    P(local.A, local.B, local.C, local.D,  5,  4, 0xFFFA3942);
155
0
    P(local.D, local.A, local.B, local.C,  8, 11, 0x8771F681);
156
0
    P(local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122);
157
0
    P(local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C);
158
0
    P(local.A, local.B, local.C, local.D,  1,  4, 0xA4BEEA44);
159
0
    P(local.D, local.A, local.B, local.C,  4, 11, 0x4BDECFA9);
160
0
    P(local.C, local.D, local.A, local.B,  7, 16, 0xF6BB4B60);
161
0
    P(local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70);
162
0
    P(local.A, local.B, local.C, local.D, 13,  4, 0x289B7EC6);
163
0
    P(local.D, local.A, local.B, local.C,  0, 11, 0xEAA127FA);
164
0
    P(local.C, local.D, local.A, local.B,  3, 16, 0xD4EF3085);
165
0
    P(local.B, local.C, local.D, local.A,  6, 23, 0x04881D05);
166
0
    P(local.A, local.B, local.C, local.D,  9,  4, 0xD9D4D039);
167
0
    P(local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5);
168
0
    P(local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8);
169
0
    P(local.B, local.C, local.D, local.A,  2, 23, 0xC4AC5665);
170
171
0
#undef F
172
173
0
#define F(x, y, z) ((y) ^ ((x) | ~(z)))
174
175
0
    P(local.A, local.B, local.C, local.D,  0,  6, 0xF4292244);
176
0
    P(local.D, local.A, local.B, local.C,  7, 10, 0x432AFF97);
177
0
    P(local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7);
178
0
    P(local.B, local.C, local.D, local.A,  5, 21, 0xFC93A039);
179
0
    P(local.A, local.B, local.C, local.D, 12,  6, 0x655B59C3);
180
0
    P(local.D, local.A, local.B, local.C,  3, 10, 0x8F0CCC92);
181
0
    P(local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D);
182
0
    P(local.B, local.C, local.D, local.A,  1, 21, 0x85845DD1);
183
0
    P(local.A, local.B, local.C, local.D,  8,  6, 0x6FA87E4F);
184
0
    P(local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0);
185
0
    P(local.C, local.D, local.A, local.B,  6, 15, 0xA3014314);
186
0
    P(local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1);
187
0
    P(local.A, local.B, local.C, local.D,  4,  6, 0xF7537E82);
188
0
    P(local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235);
189
0
    P(local.C, local.D, local.A, local.B,  2, 15, 0x2AD7D2BB);
190
0
    P(local.B, local.C, local.D, local.A,  9, 21, 0xEB86D391);
191
192
0
#undef F
193
194
0
    ctx->state[0] += local.A;
195
0
    ctx->state[1] += local.B;
196
0
    ctx->state[2] += local.C;
197
0
    ctx->state[3] += local.D;
198
199
    /* Zeroise variables to clear sensitive data from memory. */
200
0
    mbedtls_platform_zeroize(&local, sizeof(local));
201
202
0
    return 0;
203
0
}
204
205
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
206
void mbedtls_md5_process(mbedtls_md5_context *ctx,
207
                         const unsigned char data[64])
208
0
{
209
0
    mbedtls_internal_md5_process(ctx, data);
210
0
}
211
#endif
212
#endif /* !MBEDTLS_MD5_PROCESS_ALT */
213
214
/*
215
 * MD5 process buffer
216
 */
217
int mbedtls_md5_update_ret(mbedtls_md5_context *ctx,
218
                           const unsigned char *input,
219
                           size_t ilen)
220
0
{
221
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
222
0
    size_t fill;
223
0
    uint32_t left;
224
225
0
    if (ilen == 0) {
226
0
        return 0;
227
0
    }
228
229
0
    left = ctx->total[0] & 0x3F;
230
0
    fill = 64 - left;
231
232
0
    ctx->total[0] += (uint32_t) ilen;
233
0
    ctx->total[0] &= 0xFFFFFFFF;
234
235
0
    if (ctx->total[0] < (uint32_t) ilen) {
236
0
        ctx->total[1]++;
237
0
    }
238
239
0
    if (left && ilen >= fill) {
240
0
        memcpy((void *) (ctx->buffer + left), input, fill);
241
0
        if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
242
0
            return ret;
243
0
        }
244
245
0
        input += fill;
246
0
        ilen  -= fill;
247
0
        left = 0;
248
0
    }
249
250
0
    while (ilen >= 64) {
251
0
        if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0) {
252
0
            return ret;
253
0
        }
254
255
0
        input += 64;
256
0
        ilen  -= 64;
257
0
    }
258
259
0
    if (ilen > 0) {
260
0
        memcpy((void *) (ctx->buffer + left), input, ilen);
261
0
    }
262
263
0
    return 0;
264
0
}
265
266
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
267
void mbedtls_md5_update(mbedtls_md5_context *ctx,
268
                        const unsigned char *input,
269
                        size_t ilen)
270
0
{
271
0
    mbedtls_md5_update_ret(ctx, input, ilen);
272
0
}
273
#endif
274
275
/*
276
 * MD5 final digest
277
 */
278
int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx,
279
                           unsigned char output[16])
280
0
{
281
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
282
0
    uint32_t used;
283
0
    uint32_t high, low;
284
285
    /*
286
     * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
287
     */
288
0
    used = ctx->total[0] & 0x3F;
289
290
0
    ctx->buffer[used++] = 0x80;
291
292
0
    if (used <= 56) {
293
        /* Enough room for padding + length in current block */
294
0
        memset(ctx->buffer + used, 0, 56 - used);
295
0
    } else {
296
        /* We'll need an extra block */
297
0
        memset(ctx->buffer + used, 0, 64 - used);
298
299
0
        if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
300
0
            return ret;
301
0
        }
302
303
0
        memset(ctx->buffer, 0, 56);
304
0
    }
305
306
    /*
307
     * Add message length
308
     */
309
0
    high = (ctx->total[0] >> 29)
310
0
           | (ctx->total[1] <<  3);
311
0
    low  = (ctx->total[0] <<  3);
312
313
0
    MBEDTLS_PUT_UINT32_LE(low,  ctx->buffer, 56);
314
0
    MBEDTLS_PUT_UINT32_LE(high, ctx->buffer, 60);
315
316
0
    if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
317
0
        return ret;
318
0
    }
319
320
    /*
321
     * Output final state
322
     */
323
0
    MBEDTLS_PUT_UINT32_LE(ctx->state[0], output,  0);
324
0
    MBEDTLS_PUT_UINT32_LE(ctx->state[1], output,  4);
325
0
    MBEDTLS_PUT_UINT32_LE(ctx->state[2], output,  8);
326
0
    MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);
327
328
0
    return 0;
329
0
}
330
331
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
332
void mbedtls_md5_finish(mbedtls_md5_context *ctx,
333
                        unsigned char output[16])
334
0
{
335
0
    mbedtls_md5_finish_ret(ctx, output);
336
0
}
337
#endif
338
339
#endif /* !MBEDTLS_MD5_ALT */
340
341
/*
342
 * output = MD5( input buffer )
343
 */
344
int mbedtls_md5_ret(const unsigned char *input,
345
                    size_t ilen,
346
                    unsigned char output[16])
347
0
{
348
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
349
0
    mbedtls_md5_context ctx;
350
351
0
    mbedtls_md5_init(&ctx);
352
353
0
    if ((ret = mbedtls_md5_starts_ret(&ctx)) != 0) {
354
0
        goto exit;
355
0
    }
356
357
0
    if ((ret = mbedtls_md5_update_ret(&ctx, input, ilen)) != 0) {
358
0
        goto exit;
359
0
    }
360
361
0
    if ((ret = mbedtls_md5_finish_ret(&ctx, output)) != 0) {
362
0
        goto exit;
363
0
    }
364
365
0
exit:
366
0
    mbedtls_md5_free(&ctx);
367
368
0
    return ret;
369
0
}
370
371
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
372
void mbedtls_md5(const unsigned char *input,
373
                 size_t ilen,
374
                 unsigned char output[16])
375
0
{
376
0
    mbedtls_md5_ret(input, ilen, output);
377
0
}
378
#endif
379
380
#if defined(MBEDTLS_SELF_TEST)
381
/*
382
 * RFC 1321 test vectors
383
 */
384
static const unsigned char md5_test_buf[7][81] =
385
{
386
    { "" },
387
    { "a" },
388
    { "abc" },
389
    { "message digest" },
390
    { "abcdefghijklmnopqrstuvwxyz" },
391
    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
392
    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
393
};
394
395
static const size_t md5_test_buflen[7] =
396
{
397
    0, 1, 3, 14, 26, 62, 80
398
};
399
400
static const unsigned char md5_test_sum[7][16] =
401
{
402
    { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
403
      0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
404
    { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
405
      0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
406
    { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
407
      0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
408
    { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
409
      0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
410
    { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
411
      0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
412
    { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
413
      0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
414
    { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
415
      0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
416
};
417
418
/*
419
 * Checkup routine
420
 */
421
int mbedtls_md5_self_test(int verbose)
422
0
{
423
0
    int i, ret = 0;
424
0
    unsigned char md5sum[16];
425
426
0
    for (i = 0; i < 7; i++) {
427
0
        if (verbose != 0) {
428
0
            mbedtls_printf("  MD5 test #%d: ", i + 1);
429
0
        }
430
431
0
        ret = mbedtls_md5_ret(md5_test_buf[i], md5_test_buflen[i], md5sum);
432
0
        if (ret != 0) {
433
0
            goto fail;
434
0
        }
435
436
0
        if (memcmp(md5sum, md5_test_sum[i], 16) != 0) {
437
0
            ret = 1;
438
0
            goto fail;
439
0
        }
440
441
0
        if (verbose != 0) {
442
0
            mbedtls_printf("passed\n");
443
0
        }
444
0
    }
445
446
0
    if (verbose != 0) {
447
0
        mbedtls_printf("\n");
448
0
    }
449
450
0
    return 0;
451
452
0
fail:
453
0
    if (verbose != 0) {
454
0
        mbedtls_printf("failed\n");
455
0
    }
456
457
0
    return ret;
458
0
}
459
460
#endif /* MBEDTLS_SELF_TEST */
461
462
#endif /* MBEDTLS_MD5_C */