Coverage Report

Created: 2024-06-28 06:19

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