Coverage Report

Created: 2026-04-01 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-heapmath/wolfcrypt/src/md5.c
Line
Count
Source
1
/* md5.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
/*
23
 * MD5 Build Options:
24
 *
25
 * NO_MD5:                   Disable MD5 support entirely          default: off
26
 * HAVE_MD5_CUST_API:        Enable custom MD5 API                 default: off
27
 * STM32_NOMD5:              Disable STM32 hardware MD5            default: off
28
 *
29
 * Hardware Acceleration (MD5-specific):
30
 * WC_ASYNC_ENABLE_MD5:      Enable async MD5 operations           default: off
31
 */
32
33
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
34
35
#if !defined(NO_MD5)
36
37
#if defined(WOLFSSL_TI_HASH)
38
/* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */
39
40
#else
41
42
#include <wolfssl/wolfcrypt/md5.h>
43
#include <wolfssl/wolfcrypt/hash.h>
44
45
#ifdef NO_INLINE
46
#include <wolfssl/wolfcrypt/misc.h>
47
#else
48
#define WOLFSSL_MISC_INCLUDED
49
#include <wolfcrypt/src/misc.c>
50
#endif
51
52
53
/* Hardware Acceleration */
54
#if defined(STM32_HASH) && !defined(STM32_NOMD5)
55
56
/* Supports CubeMX HAL or Standard Peripheral Library */
57
#define HAVE_MD5_CUST_API
58
59
int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId)
60
{
61
    if (md5 == NULL) {
62
        return BAD_FUNC_ARG;
63
    }
64
65
    (void)devId;
66
    (void)heap;
67
68
    wc_Stm32_Hash_Init(&md5->stmCtx);
69
70
    return 0;
71
}
72
73
int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len)
74
{
75
    int ret;
76
77
    if (md5 == NULL || (data == NULL && len > 0)) {
78
        return BAD_FUNC_ARG;
79
    }
80
81
    ret = wolfSSL_CryptHwMutexLock();
82
    if (ret == 0) {
83
        ret = wc_Stm32_Hash_Update(&md5->stmCtx, HASH_AlgoSelection_MD5,
84
                                   data, len, WC_MD5_BLOCK_SIZE);
85
        wolfSSL_CryptHwMutexUnLock();
86
    }
87
    return ret;
88
}
89
90
int wc_Md5Final(wc_Md5* md5, byte* hash)
91
{
92
    int ret;
93
94
    if (md5 == NULL || hash == NULL) {
95
        return BAD_FUNC_ARG;
96
    }
97
98
    ret = wolfSSL_CryptHwMutexLock();
99
    if (ret == 0) {
100
        ret = wc_Stm32_Hash_Final(&md5->stmCtx, HASH_AlgoSelection_MD5,
101
                                  hash, WC_MD5_DIGEST_SIZE);
102
        wolfSSL_CryptHwMutexUnLock();
103
    }
104
105
    (void)wc_InitMd5(md5);  /* reset state */
106
107
    return ret;
108
}
109
110
#elif defined(FREESCALE_MMCAU_SHA)
111
112
#ifdef FREESCALE_MMCAU_CLASSIC_SHA
113
    #include "cau_api.h"
114
#else
115
    #include "fsl_mmcau.h"
116
#endif
117
118
#define XTRANSFORM(S,B)       Transform((S), (B))
119
#define XTRANSFORM_LEN(S,B,L) Transform_Len((S), (B), (L))
120
121
#ifndef WC_HASH_DATA_ALIGNMENT
122
    /* these hardware API's require 4 byte (word32) alignment */
123
    #define WC_HASH_DATA_ALIGNMENT 4
124
#endif
125
126
static int Transform(wc_Md5* md5, const byte* data)
127
{
128
    int ret = wolfSSL_CryptHwMutexLock();
129
    if (ret == 0) {
130
#ifdef FREESCALE_MMCAU_CLASSIC_SHA
131
        cau_md5_hash_n((byte*)data, 1, (unsigned char*)md5->digest);
132
#else
133
        MMCAU_MD5_HashN((byte*)data, 1, (uint32_t*)md5->digest);
134
#endif
135
        wolfSSL_CryptHwMutexUnLock();
136
    }
137
    return ret;
138
}
139
140
static int Transform_Len(wc_Md5* md5, const byte* data, word32 len)
141
{
142
    int ret = wolfSSL_CryptHwMutexLock();
143
    if (ret == 0) {
144
    #if defined(WC_HASH_DATA_ALIGNMENT) && WC_HASH_DATA_ALIGNMENT > 0
145
        if ((wc_ptr_t)data % WC_HASH_DATA_ALIGNMENT) {
146
            /* data pointer is NOT aligned,
147
             * so copy and perform one block at a time */
148
            byte* local = (byte*)md5->buffer;
149
            while (len >= WC_MD5_BLOCK_SIZE) {
150
                XMEMCPY(local, data, WC_MD5_BLOCK_SIZE);
151
            #ifdef FREESCALE_MMCAU_CLASSIC_SHA
152
                cau_md5_hash_n(local, 1, (unsigned char*)md5->digest);
153
            #else
154
                MMCAU_MD5_HashN(local, 1, (uint32_t*)md5->digest);
155
            #endif
156
                data += WC_MD5_BLOCK_SIZE;
157
                len  -= WC_MD5_BLOCK_SIZE;
158
            }
159
        }
160
        else
161
    #endif
162
        {
163
#ifdef FREESCALE_MMCAU_CLASSIC_SHA
164
        cau_md5_hash_n((byte*)data, len / WC_MD5_BLOCK_SIZE,
165
            (unsigned char*)md5->digest);
166
#else
167
        MMCAU_MD5_HashN((byte*)data, len / WC_MD5_BLOCK_SIZE,
168
            (uint32_t*)md5->digest);
169
#endif
170
        }
171
        wolfSSL_CryptHwMutexUnLock();
172
    }
173
    return ret;
174
}
175
176
#elif defined(WOLFSSL_PIC32MZ_HASH)
177
#include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
178
#define HAVE_MD5_CUST_API
179
180
#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \
181
    !defined(WOLFSSL_QNX_CAAM)
182
/* functions implemented in wolfcrypt/src/port/caam/caam_sha.c */
183
#define HAVE_MD5_CUST_API
184
#else
185
#define NEED_SOFT_MD5
186
#endif /* End Hardware Acceleration */
187
188
#ifdef NEED_SOFT_MD5
189
190
739k
#define XTRANSFORM(S,B)  Transform((S),(B))
191
192
23.6M
#define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
193
11.8M
#define F2(x, y, z) F1(z, x, y)
194
11.8M
#define F3(x, y, z) ((x) ^ (y) ^ (z))
195
11.8M
#define F4(x, y, z) ((y) ^ ((x) | ~(z)))
196
197
#define MD5STEP(f, w, x, y, z, data, s) \
198
47.3M
    (w) = (rotlFixed((w) + f(x, y, z) + (data), s) + (x))
199
200
static int Transform(wc_Md5* md5, const byte* data)
201
739k
{
202
739k
    const word32* buffer = (const word32*)data;
203
    /* Copy context->state[] to working vars  */
204
739k
    word32 a = md5->digest[0];
205
739k
    word32 b = md5->digest[1];
206
739k
    word32 c = md5->digest[2];
207
739k
    word32 d = md5->digest[3];
208
209
739k
    MD5STEP(F1, a, b, c, d, buffer[0]  + 0xd76aa478,  7);
210
739k
    MD5STEP(F1, d, a, b, c, buffer[1]  + 0xe8c7b756, 12);
211
739k
    MD5STEP(F1, c, d, a, b, buffer[2]  + 0x242070db, 17);
212
739k
    MD5STEP(F1, b, c, d, a, buffer[3]  + 0xc1bdceee, 22);
213
739k
    MD5STEP(F1, a, b, c, d, buffer[4]  + 0xf57c0faf,  7);
214
739k
    MD5STEP(F1, d, a, b, c, buffer[5]  + 0x4787c62a, 12);
215
739k
    MD5STEP(F1, c, d, a, b, buffer[6]  + 0xa8304613, 17);
216
739k
    MD5STEP(F1, b, c, d, a, buffer[7]  + 0xfd469501, 22);
217
739k
    MD5STEP(F1, a, b, c, d, buffer[8]  + 0x698098d8,  7);
218
739k
    MD5STEP(F1, d, a, b, c, buffer[9]  + 0x8b44f7af, 12);
219
739k
    MD5STEP(F1, c, d, a, b, buffer[10] + 0xffff5bb1, 17);
220
739k
    MD5STEP(F1, b, c, d, a, buffer[11] + 0x895cd7be, 22);
221
739k
    MD5STEP(F1, a, b, c, d, buffer[12] + 0x6b901122,  7);
222
739k
    MD5STEP(F1, d, a, b, c, buffer[13] + 0xfd987193, 12);
223
739k
    MD5STEP(F1, c, d, a, b, buffer[14] + 0xa679438e, 17);
224
739k
    MD5STEP(F1, b, c, d, a, buffer[15] + 0x49b40821, 22);
225
226
739k
    MD5STEP(F2, a, b, c, d, buffer[1]  + 0xf61e2562,  5);
227
739k
    MD5STEP(F2, d, a, b, c, buffer[6]  + 0xc040b340,  9);
228
739k
    MD5STEP(F2, c, d, a, b, buffer[11] + 0x265e5a51, 14);
229
739k
    MD5STEP(F2, b, c, d, a, buffer[0]  + 0xe9b6c7aa, 20);
230
739k
    MD5STEP(F2, a, b, c, d, buffer[5]  + 0xd62f105d,  5);
231
739k
    MD5STEP(F2, d, a, b, c, buffer[10] + 0x02441453,  9);
232
739k
    MD5STEP(F2, c, d, a, b, buffer[15] + 0xd8a1e681, 14);
233
739k
    MD5STEP(F2, b, c, d, a, buffer[4]  + 0xe7d3fbc8, 20);
234
739k
    MD5STEP(F2, a, b, c, d, buffer[9]  + 0x21e1cde6,  5);
235
739k
    MD5STEP(F2, d, a, b, c, buffer[14] + 0xc33707d6,  9);
236
739k
    MD5STEP(F2, c, d, a, b, buffer[3]  + 0xf4d50d87, 14);
237
739k
    MD5STEP(F2, b, c, d, a, buffer[8]  + 0x455a14ed, 20);
238
739k
    MD5STEP(F2, a, b, c, d, buffer[13] + 0xa9e3e905,  5);
239
739k
    MD5STEP(F2, d, a, b, c, buffer[2]  + 0xfcefa3f8,  9);
240
739k
    MD5STEP(F2, c, d, a, b, buffer[7]  + 0x676f02d9, 14);
241
739k
    MD5STEP(F2, b, c, d, a, buffer[12] + 0x8d2a4c8a, 20);
242
243
739k
    MD5STEP(F3, a, b, c, d, buffer[5]  + 0xfffa3942,  4);
244
739k
    MD5STEP(F3, d, a, b, c, buffer[8]  + 0x8771f681, 11);
245
739k
    MD5STEP(F3, c, d, a, b, buffer[11] + 0x6d9d6122, 16);
246
739k
    MD5STEP(F3, b, c, d, a, buffer[14] + 0xfde5380c, 23);
247
739k
    MD5STEP(F3, a, b, c, d, buffer[1]  + 0xa4beea44,  4);
248
739k
    MD5STEP(F3, d, a, b, c, buffer[4]  + 0x4bdecfa9, 11);
249
739k
    MD5STEP(F3, c, d, a, b, buffer[7]  + 0xf6bb4b60, 16);
250
739k
    MD5STEP(F3, b, c, d, a, buffer[10] + 0xbebfbc70, 23);
251
739k
    MD5STEP(F3, a, b, c, d, buffer[13] + 0x289b7ec6,  4);
252
739k
    MD5STEP(F3, d, a, b, c, buffer[0]  + 0xeaa127fa, 11);
253
739k
    MD5STEP(F3, c, d, a, b, buffer[3]  + 0xd4ef3085, 16);
254
739k
    MD5STEP(F3, b, c, d, a, buffer[6]  + 0x04881d05, 23);
255
739k
    MD5STEP(F3, a, b, c, d, buffer[9]  + 0xd9d4d039,  4);
256
739k
    MD5STEP(F3, d, a, b, c, buffer[12] + 0xe6db99e5, 11);
257
739k
    MD5STEP(F3, c, d, a, b, buffer[15] + 0x1fa27cf8, 16);
258
739k
    MD5STEP(F3, b, c, d, a, buffer[2]  + 0xc4ac5665, 23);
259
260
739k
    MD5STEP(F4, a, b, c, d, buffer[0]  + 0xf4292244,  6);
261
739k
    MD5STEP(F4, d, a, b, c, buffer[7]  + 0x432aff97, 10);
262
739k
    MD5STEP(F4, c, d, a, b, buffer[14] + 0xab9423a7, 15);
263
739k
    MD5STEP(F4, b, c, d, a, buffer[5]  + 0xfc93a039, 21);
264
739k
    MD5STEP(F4, a, b, c, d, buffer[12] + 0x655b59c3,  6);
265
739k
    MD5STEP(F4, d, a, b, c, buffer[3]  + 0x8f0ccc92, 10);
266
739k
    MD5STEP(F4, c, d, a, b, buffer[10] + 0xffeff47d, 15);
267
739k
    MD5STEP(F4, b, c, d, a, buffer[1]  + 0x85845dd1, 21);
268
739k
    MD5STEP(F4, a, b, c, d, buffer[8]  + 0x6fa87e4f,  6);
269
739k
    MD5STEP(F4, d, a, b, c, buffer[15] + 0xfe2ce6e0, 10);
270
739k
    MD5STEP(F4, c, d, a, b, buffer[6]  + 0xa3014314, 15);
271
739k
    MD5STEP(F4, b, c, d, a, buffer[13] + 0x4e0811a1, 21);
272
739k
    MD5STEP(F4, a, b, c, d, buffer[4]  + 0xf7537e82,  6);
273
739k
    MD5STEP(F4, d, a, b, c, buffer[11] + 0xbd3af235, 10);
274
739k
    MD5STEP(F4, c, d, a, b, buffer[2]  + 0x2ad7d2bb, 15);
275
739k
    MD5STEP(F4, b, c, d, a, buffer[9]  + 0xeb86d391, 21);
276
277
    /* Add the working vars back into digest state[]  */
278
739k
    md5->digest[0] += a;
279
739k
    md5->digest[1] += b;
280
739k
    md5->digest[2] += c;
281
739k
    md5->digest[3] += d;
282
283
739k
    return 0;
284
739k
}
285
#endif /* NEED_SOFT_MD5 */
286
287
#ifndef HAVE_MD5_CUST_API
288
289
static WC_INLINE void AddLength(wc_Md5* md5, word32 len)
290
227k
{
291
227k
    word32 tmp = md5->loLen;
292
227k
    if ((md5->loLen += len) < tmp) {
293
0
        md5->hiLen++;                       /* carry low to high */
294
0
    }
295
227k
}
296
297
static int _InitMd5(wc_Md5* md5)
298
130k
{
299
130k
    int ret = 0;
300
301
130k
    md5->digest[0] = 0x67452301L;
302
130k
    md5->digest[1] = 0xefcdab89L;
303
130k
    md5->digest[2] = 0x98badcfeL;
304
130k
    md5->digest[3] = 0x10325476L;
305
306
130k
    md5->buffLen = 0;
307
130k
    md5->loLen   = 0;
308
130k
    md5->hiLen   = 0;
309
130k
#ifdef WOLFSSL_HASH_FLAGS
310
130k
    md5->flags = 0;
311
130k
#endif
312
313
130k
    return ret;
314
130k
}
315
316
int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId)
317
109k
{
318
109k
    int ret = 0;
319
320
109k
    if (md5 == NULL)
321
0
        return BAD_FUNC_ARG;
322
323
109k
    md5->heap = heap;
324
325
109k
    ret = _InitMd5(md5);
326
109k
    if (ret != 0)
327
0
        return ret;
328
329
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
330
    ret = wolfAsync_DevCtxInit(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5,
331
                               md5->heap, devId);
332
#else
333
109k
    (void)devId;
334
109k
#endif
335
109k
    return ret;
336
109k
}
337
338
/* do block size increments/updates */
339
int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len)
340
227k
{
341
227k
    int ret = 0;
342
227k
    word32 blocksLen;
343
227k
    byte* local;
344
345
227k
    if (md5 == NULL || (data == NULL && len > 0)) {
346
0
        return BAD_FUNC_ARG;
347
0
    }
348
349
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
350
    if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) {
351
#if defined(HAVE_INTEL_QA)
352
        return IntelQaSymMd5(&md5->asyncDev, NULL, data, len);
353
#endif
354
    }
355
#endif /* WOLFSSL_ASYNC_CRYPT */
356
357
    /* check that internal buffLen is valid */
358
227k
    if (md5->buffLen >= WC_MD5_BLOCK_SIZE)
359
0
        return BUFFER_E;
360
361
227k
    if (data == NULL && len == 0) {
362
        /* valid, but do nothing */
363
58
        return 0;
364
58
    }
365
366
    /* add length for final */
367
227k
    AddLength(md5, len);
368
369
227k
    local = (byte*)md5->buffer;
370
371
    /* process any remainder from previous operation */
372
227k
    if (md5->buffLen > 0) {
373
141k
        blocksLen = min(len, WC_MD5_BLOCK_SIZE - md5->buffLen);
374
141k
        XMEMCPY(&local[md5->buffLen], data, blocksLen);
375
376
141k
        md5->buffLen += blocksLen;
377
141k
        data         += blocksLen;
378
141k
        len          -= blocksLen;
379
380
141k
        if (md5->buffLen == WC_MD5_BLOCK_SIZE) {
381
        #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
382
            ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE);
383
        #endif
384
385
70.9k
            ret = XTRANSFORM(md5, (const byte*)local);
386
70.9k
            if (ret != 0)
387
0
                return ret;
388
389
70.9k
            md5->buffLen = 0;
390
70.9k
        }
391
141k
    }
392
393
    /* process blocks */
394
#ifdef XTRANSFORM_LEN
395
    /* get number of blocks */
396
    /* 64-1 = 0x3F (~ Inverted = 0xFFFFFFC0) */
397
    /* len (masked by 0xFFFFFFC0) returns block aligned length */
398
    blocksLen = len & ~(WC_MD5_BLOCK_SIZE-1);
399
    if (blocksLen > 0) {
400
        /* Byte reversal performed in function if required. */
401
        XTRANSFORM_LEN(md5, data, blocksLen);
402
        data += blocksLen;
403
        len  -= blocksLen;
404
    }
405
#else
406
873k
    while (len >= WC_MD5_BLOCK_SIZE) {
407
646k
        word32* local32 = md5->buffer;
408
        /* optimization to avoid memcpy if data pointer is properly aligned */
409
        /* Big Endian requires byte swap, so can't use data directly */
410
    #if defined(WC_HASH_DATA_ALIGNMENT) && !defined(BIG_ENDIAN_ORDER)
411
        if (((wc_ptr_t)data % WC_HASH_DATA_ALIGNMENT) == 0) {
412
            local32 = (word32*)data;
413
        }
414
        else
415
    #endif
416
646k
        {
417
646k
            XMEMCPY(local32, data, WC_MD5_BLOCK_SIZE);
418
646k
        }
419
420
646k
        data += WC_MD5_BLOCK_SIZE;
421
646k
        len  -= WC_MD5_BLOCK_SIZE;
422
423
    #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
424
        ByteReverseWords(local32, local32, WC_MD5_BLOCK_SIZE);
425
    #endif
426
427
646k
        ret = XTRANSFORM(md5, (const byte*)local32);
428
646k
    }
429
227k
#endif /* XTRANSFORM_LEN */
430
431
    /* save remainder */
432
227k
    if (len > 0) {
433
138k
        XMEMCPY(local, data, len);
434
138k
        md5->buffLen = len;
435
138k
    }
436
437
227k
    return ret;
438
227k
}
439
440
int wc_Md5Final(wc_Md5* md5, byte* hash)
441
21.1k
{
442
21.1k
    byte* local;
443
444
21.1k
    if (md5 == NULL || hash == NULL) {
445
0
        return BAD_FUNC_ARG;
446
0
    }
447
448
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
449
    if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) {
450
#if defined(HAVE_INTEL_QA)
451
        return IntelQaSymMd5(&md5->asyncDev, hash, NULL, WC_MD5_DIGEST_SIZE);
452
#endif
453
    }
454
#endif /* WOLFSSL_ASYNC_CRYPT */
455
456
21.1k
    local = (byte*)md5->buffer; /* buffer allocated in word32 size */
457
458
    /* ensure we have a valid buffer length; (-1 to append a byte to length) */
459
21.1k
    if (md5->buffLen > WC_MD5_BLOCK_SIZE - 1) {
460
        /* some places consider this BAD_STATE_E */
461
0
        return BUFFER_E;
462
0
    }
463
464
21.1k
    local[md5->buffLen++] = 0x80;  /* add 1 */
465
466
    /* pad with zeros */
467
21.1k
    if (md5->buffLen > WC_MD5_PAD_SIZE) {
468
1.30k
        if (md5->buffLen < WC_MD5_BLOCK_SIZE) {
469
987
            XMEMSET(&local[md5->buffLen], 0, WC_MD5_BLOCK_SIZE - md5->buffLen);
470
987
        }
471
1.30k
        md5->buffLen += WC_MD5_BLOCK_SIZE - md5->buffLen;
472
473
#if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
474
        ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE);
475
#endif
476
1.30k
        XTRANSFORM(md5, local);
477
1.30k
        md5->buffLen = 0;
478
1.30k
    }
479
21.1k
    XMEMSET(&local[md5->buffLen], 0, WC_MD5_PAD_SIZE - md5->buffLen);
480
481
#if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
482
    ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE);
483
#endif
484
485
    /* put lengths in bits */
486
21.1k
    md5->hiLen = (md5->loLen >> (8 * sizeof(md5->loLen) - 3)) +
487
21.1k
                 (md5->hiLen << 3);
488
21.1k
    md5->loLen = md5->loLen << 3;
489
490
    /* store lengths */
491
    /* ! length ordering dependent on digest endian type ! */
492
21.1k
    XMEMCPY(&local[WC_MD5_PAD_SIZE], &md5->loLen, sizeof(word32));
493
21.1k
    XMEMCPY(&local[WC_MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32));
494
495
    /* final transform and result to hash */
496
21.1k
    XTRANSFORM(md5, local);
497
#ifdef BIG_ENDIAN_ORDER
498
    ByteReverseWords(md5->digest, md5->digest, WC_MD5_DIGEST_SIZE);
499
#endif
500
21.1k
    XMEMCPY(hash, md5->digest, WC_MD5_DIGEST_SIZE);
501
502
21.1k
    return _InitMd5(md5); /* reset state */
503
21.1k
}
504
#endif /* !HAVE_MD5_CUST_API */
505
506
507
int wc_InitMd5(wc_Md5* md5)
508
130
{
509
130
    if (md5 == NULL) {
510
0
        return BAD_FUNC_ARG;
511
0
    }
512
130
    return wc_InitMd5_ex(md5, NULL, INVALID_DEVID);
513
130
}
514
515
void wc_Md5Free(wc_Md5* md5)
516
111k
{
517
111k
    if (md5 == NULL)
518
0
        return;
519
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
520
    wolfAsync_DevCtxFree(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5);
521
#endif /* WOLFSSL_ASYNC_CRYPT */
522
523
#ifdef WOLFSSL_PIC32MZ_HASH
524
    wc_Md5Pic32Free(md5);
525
#endif
526
111k
}
527
528
int wc_Md5GetHash(wc_Md5* md5, byte* hash)
529
1.54k
{
530
1.54k
    int ret;
531
1.54k
    wc_Md5 tmpMd5;
532
533
1.54k
    if (md5 == NULL || hash == NULL)
534
0
        return BAD_FUNC_ARG;
535
536
1.54k
    XMEMSET(&tmpMd5, 0, sizeof(tmpMd5));
537
1.54k
    ret = wc_Md5Copy(md5, &tmpMd5);
538
1.54k
    if (ret == 0) {
539
1.54k
        ret = wc_Md5Final(&tmpMd5, hash);
540
1.54k
    }
541
542
1.54k
    return ret;
543
1.54k
}
544
545
int wc_Md5Copy(wc_Md5* src, wc_Md5* dst)
546
1.58k
{
547
1.58k
    int ret = 0;
548
549
1.58k
    if (src == NULL || dst == NULL)
550
0
        return BAD_FUNC_ARG;
551
552
    /* Free dst resources before copy to prevent memory leaks (e.g.,
553
     * hardware contexts). XMEMCPY overwrites dst. */
554
1.58k
    wc_Md5Free(dst);
555
1.58k
    XMEMCPY(dst, src, sizeof(wc_Md5));
556
557
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5)
558
    ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
559
#endif
560
#ifdef WOLFSSL_PIC32MZ_HASH
561
    ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
562
#endif
563
1.58k
#ifdef WOLFSSL_HASH_FLAGS
564
1.58k
    dst->flags |= WC_HASH_FLAG_ISCOPY;
565
1.58k
#endif
566
567
1.58k
    return ret;
568
1.58k
}
569
570
#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL)
571
/* Apply MD5 transformation to the data                   */
572
/* @param md5  a pointer to wc_MD5 structure              */
573
/* @param data data to be applied MD5 transformation      */
574
/* @return 0 on successful, otherwise non-zero on failure */
575
int wc_Md5Transform(wc_Md5* md5, const byte* data)
576
{
577
    /* sanity check */
578
    if (md5 == NULL || data == NULL) {
579
        return BAD_FUNC_ARG;
580
    }
581
#ifndef HAVE_MD5_CUST_API
582
    return Transform(md5, data);
583
#else
584
    return NOT_COMPILED_IN;
585
#endif
586
}
587
#endif /* OPENSSL_EXTRA */
588
589
#ifdef WOLFSSL_HASH_FLAGS
590
int wc_Md5SetFlags(wc_Md5* md5, word32 flags)
591
104k
{
592
104k
    if (md5) {
593
104k
        md5->flags = flags;
594
104k
    }
595
104k
    return 0;
596
104k
}
597
int wc_Md5GetFlags(wc_Md5* md5, word32* flags)
598
0
{
599
0
    if (md5 && flags) {
600
0
        *flags = md5->flags;
601
0
    }
602
0
    return 0;
603
0
}
604
#endif
605
606
#endif /* WOLFSSL_TI_HASH */
607
#endif /* NO_MD5 */