1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <[email protected]>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24
25#include "curl_setup.h"
26
27#ifndef CURL_DISABLE_CRYPTO_AUTH
28
29#include <curl/curl.h>
30
31#include "curl_md5.h"
32#include "curl_hmac.h"
33#include "warnless.h"
34
35#ifdef USE_MBEDTLS
36#include <mbedtls/version.h>
37
38#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \
39 (MBEDTLS_VERSION_NUMBER < 0x03000000)
40 #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
41#endif
42#endif /* USE_MBEDTLS */
43
44#ifdef USE_OPENSSL
45 #include <openssl/opensslconf.h>
46 #if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_DEPRECATED_3_0)
47 #define USE_OPENSSL_MD5
48 #endif
49#endif
50
51#ifdef USE_WOLFSSL
52 #include <wolfssl/options.h>
53 #ifndef NO_MD5
54 #define USE_WOLFSSL_MD5
55 #endif
56#endif
57
58#if defined(USE_GNUTLS)
59
60#include <nettle/md5.h>
61#include "curl_memory.h"
62/* The last #include file should be: */
63#include "memdebug.h"
64
65typedef struct md5_ctx my_md5_ctx;
66
67static CURLcode my_md5_init(my_md5_ctx *ctx)
68{
69 md5_init(ctx);
70 return CURLE_OK;
71}
72
73static void my_md5_update(my_md5_ctx *ctx,
74 const unsigned char *input,
75 unsigned int inputLen)
76{
77 md5_update(ctx, inputLen, input);
78}
79
80static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
81{
82 md5_digest(ctx, 16, digest);
83}
84
85#elif defined(USE_OPENSSL_MD5) || defined(USE_WOLFSSL_MD5)
86
87/* When OpenSSL or wolfSSL is available, we use their MD5 functions. */
88#if defined(USE_OPENSSL_MD5)
89#include <openssl/md5.h>
90#elif defined(USE_WOLFSSL_MD5)
91#include <wolfssl/openssl/md5.h>
92#endif
93
94#include "curl_memory.h"
95/* The last #include file should be: */
96#include "memdebug.h"
97
98typedef MD5_CTX my_md5_ctx;
99
100static CURLcode my_md5_init(my_md5_ctx *ctx)
101{
102 if(!MD5_Init(ctx))
103 return CURLE_OUT_OF_MEMORY;
104
105 return CURLE_OK;
106}
107
108static void my_md5_update(my_md5_ctx *ctx,
109 const unsigned char *input,
110 unsigned int len)
111{
112 (void)MD5_Update(ctx, input, len);
113}
114
115static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
116{
117 (void)MD5_Final(digest, ctx);
118}
119
120#elif defined(USE_MBEDTLS)
121
122#include <mbedtls/md5.h>
123
124#include "curl_memory.h"
125
126/* The last #include file should be: */
127#include "memdebug.h"
128
129typedef mbedtls_md5_context my_md5_ctx;
130
131static CURLcode my_md5_init(my_md5_ctx *ctx)
132{
133#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
134 if(mbedtls_md5_starts(ctx))
135 return CURLE_OUT_OF_MEMORY;
136#elif defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
137 if(mbedtls_md5_starts_ret(ctx))
138 return CURLE_OUT_OF_MEMORY;
139#else
140 (void)mbedtls_md5_starts(ctx);
141#endif
142 return CURLE_OK;
143}
144
145static void my_md5_update(my_md5_ctx *ctx,
146 const unsigned char *data,
147 unsigned int length)
148{
149#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
150 (void) mbedtls_md5_update(ctx, data, length);
151#else
152 (void) mbedtls_md5_update_ret(ctx, data, length);
153#endif
154}
155
156static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
157{
158#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
159 (void) mbedtls_md5_finish(ctx, digest);
160#else
161 (void) mbedtls_md5_finish_ret(ctx, digest);
162#endif
163}
164
165#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
166 (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
167 defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
168 (__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
169 (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
170 (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
171
172/* For Apple operating systems: CommonCrypto has the functions we need.
173 These functions are available on Tiger and later, as well as iOS 2.0
174 and later. If you're building for an older cat, well, sorry.
175
176 Declaring the functions as static like this seems to be a bit more
177 reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */
178# include <CommonCrypto/CommonDigest.h>
179# define my_md5_ctx CC_MD5_CTX
180#include "curl_memory.h"
181/* The last #include file should be: */
182#include "memdebug.h"
183
184static CURLcode my_md5_init(my_md5_ctx *ctx)
185{
186 if(!CC_MD5_Init(ctx))
187 return CURLE_OUT_OF_MEMORY;
188
189 return CURLE_OK;
190}
191
192static void my_md5_update(my_md5_ctx *ctx,
193 const unsigned char *input,
194 unsigned int inputLen)
195{
196 CC_MD5_Update(ctx, input, inputLen);
197}
198
199static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
200{
201 CC_MD5_Final(digest, ctx);
202}
203
204#elif defined(USE_WIN32_CRYPTO)
205
206#include <wincrypt.h>
207#include "curl_memory.h"
208/* The last #include file should be: */
209#include "memdebug.h"
210
211struct md5_ctx {
212 HCRYPTPROV hCryptProv;
213 HCRYPTHASH hHash;
214};
215typedef struct md5_ctx my_md5_ctx;
216
217static CURLcode my_md5_init(my_md5_ctx *ctx)
218{
219 if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
220 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
221 return CURLE_OUT_OF_MEMORY;
222
223 if(!CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash)) {
224 CryptReleaseContext(ctx->hCryptProv, 0);
225 return CURLE_OUT_OF_MEMORY;
226 }
227
228 return CURLE_OK;
229}
230
231static void my_md5_update(my_md5_ctx *ctx,
232 const unsigned char *input,
233 unsigned int inputLen)
234{
235 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
236}
237
238static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
239{
240 unsigned long length = 0;
241 CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
242 if(length == 16)
243 CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
244 if(ctx->hHash)
245 CryptDestroyHash(ctx->hHash);
246 if(ctx->hCryptProv)
247 CryptReleaseContext(ctx->hCryptProv, 0);
248}
249
250#else
251
252/* When no other crypto library is available we use this code segment */
253
254/*
255 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
256 * MD5 Message-Digest Algorithm (RFC 1321).
257 *
258 * Homepage:
259 https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
260 *
261 * Author:
262 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
263 *
264 * This software was written by Alexander Peslyak in 2001. No copyright is
265 * claimed, and the software is hereby placed in the public domain.
266 * In case this attempt to disclaim copyright and place the software in the
267 * public domain is deemed null and void, then the software is
268 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
269 * general public under the following terms:
270 *
271 * Redistribution and use in source and binary forms, with or without
272 * modification, are permitted.
273 *
274 * There's ABSOLUTELY NO WARRANTY, express or implied.
275 *
276 * (This is a heavily cut-down "BSD license".)
277 *
278 * This differs from Colin Plumb's older public domain implementation in that
279 * no exactly 32-bit integer data type is required (any 32-bit or wider
280 * unsigned integer data type will do), there's no compile-time endianness
281 * configuration, and the function prototypes match OpenSSL's. No code from
282 * Colin Plumb's implementation has been reused; this comment merely compares
283 * the properties of the two independent implementations.
284 *
285 * The primary goals of this implementation are portability and ease of use.
286 * It is meant to be fast, but not as fast as possible. Some known
287 * optimizations are not included to reduce source code size and avoid
288 * compile-time configuration.
289 */
290
291#include <string.h>
292
293/* The last #include files should be: */
294#include "curl_memory.h"
295#include "memdebug.h"
296
297/* Any 32-bit or wider unsigned integer data type will do */
298typedef unsigned int MD5_u32plus;
299
300struct md5_ctx {
301 MD5_u32plus lo, hi;
302 MD5_u32plus a, b, c, d;
303 unsigned char buffer[64];
304 MD5_u32plus block[16];
305};
306typedef struct md5_ctx my_md5_ctx;
307
308static CURLcode my_md5_init(my_md5_ctx *ctx);
309static void my_md5_update(my_md5_ctx *ctx, const void *data,
310 unsigned long size);
311static void my_md5_final(unsigned char *result, my_md5_ctx *ctx);
312
313/*
314 * The basic MD5 functions.
315 *
316 * F and G are optimized compared to their RFC 1321 definitions for
317 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
318 * implementation.
319 */
320#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
321#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
322#define H(x, y, z) (((x) ^ (y)) ^ (z))
323#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
324#define I(x, y, z) ((y) ^ ((x) | ~(z)))
325
326/*
327 * The MD5 transformation for all four rounds.
328 */
329#define STEP(f, a, b, c, d, x, t, s) \
330 (a) += f((b), (c), (d)) + (x) + (t); \
331 (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
332 (a) += (b);
333
334/*
335 * SET reads 4 input bytes in little-endian byte order and stores them
336 * in a properly aligned word in host byte order.
337 *
338 * The check for little-endian architectures that tolerate unaligned
339 * memory accesses is just an optimization. Nothing will break if it
340 * doesn't work.
341 */
342#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
343#define SET(n) \
344 (*(MD5_u32plus *)(void *)&ptr[(n) * 4])
345#define GET(n) \
346 SET(n)
347#else
348#define SET(n) \
349 (ctx->block[(n)] = \
350 (MD5_u32plus)ptr[(n) * 4] | \
351 ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
352 ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
353 ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
354#define GET(n) \
355 (ctx->block[(n)])
356#endif
357
358/*
359 * This processes one or more 64-byte data blocks, but does NOT update
360 * the bit counters. There are no alignment requirements.
361 */
362static const void *body(my_md5_ctx *ctx, const void *data, unsigned long size)
363{
364 const unsigned char *ptr;
365 MD5_u32plus a, b, c, d;
366
367 ptr = (const unsigned char *)data;
368
369 a = ctx->a;
370 b = ctx->b;
371 c = ctx->c;
372 d = ctx->d;
373
374 do {
375 MD5_u32plus saved_a, saved_b, saved_c, saved_d;
376
377 saved_a = a;
378 saved_b = b;
379 saved_c = c;
380 saved_d = d;
381
382/* Round 1 */
383 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
384 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
385 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
386 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
387 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
388 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
389 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
390 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
391 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
392 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
393 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
394 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
395 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
396 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
397 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
398 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
399
400/* Round 2 */
401 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
402 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
403 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
404 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
405 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
406 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
407 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
408 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
409 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
410 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
411 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
412 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
413 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
414 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
415 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
416 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
417
418/* Round 3 */
419 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
420 STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
421 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
422 STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
423 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
424 STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
425 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
426 STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
427 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
428 STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
429 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
430 STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
431 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
432 STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
433 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
434 STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
435
436/* Round 4 */
437 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
438 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
439 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
440 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
441 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
442 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
443 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
444 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
445 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
446 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
447 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
448 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
449 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
450 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
451 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
452 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
453
454 a += saved_a;
455 b += saved_b;
456 c += saved_c;
457 d += saved_d;
458
459 ptr += 64;
460 } while(size -= 64);
461
462 ctx->a = a;
463 ctx->b = b;
464 ctx->c = c;
465 ctx->d = d;
466
467 return ptr;
468}
469
470static CURLcode my_md5_init(my_md5_ctx *ctx)
471{
472 ctx->a = 0x67452301;
473 ctx->b = 0xefcdab89;
474 ctx->c = 0x98badcfe;
475 ctx->d = 0x10325476;
476
477 ctx->lo = 0;
478 ctx->hi = 0;
479
480 return CURLE_OK;
481}
482
483static void my_md5_update(my_md5_ctx *ctx, const void *data,
484 unsigned long size)
485{
486 MD5_u32plus saved_lo;
487 unsigned long used;
488
489 saved_lo = ctx->lo;
490 ctx->lo = (saved_lo + size) & 0x1fffffff;
491 if(ctx->lo < saved_lo)
492 ctx->hi++;
493 ctx->hi += (MD5_u32plus)size >> 29;
494
495 used = saved_lo & 0x3f;
496
497 if(used) {
498 unsigned long available = 64 - used;
499
500 if(size < available) {
501 memcpy(&ctx->buffer[used], data, size);
502 return;
503 }
504
505 memcpy(&ctx->buffer[used], data, available);
506 data = (const unsigned char *)data + available;
507 size -= available;
508 body(ctx, ctx->buffer, 64);
509 }
510
511 if(size >= 64) {
512 data = body(ctx, data, size & ~(unsigned long)0x3f);
513 size &= 0x3f;
514 }
515
516 memcpy(ctx->buffer, data, size);
517}
518
519static void my_md5_final(unsigned char *result, my_md5_ctx *ctx)
520{
521 unsigned long used, available;
522
523 used = ctx->lo & 0x3f;
524
525 ctx->buffer[used++] = 0x80;
526
527 available = 64 - used;
528
529 if(available < 8) {
530 memset(&ctx->buffer[used], 0, available);
531 body(ctx, ctx->buffer, 64);
532 used = 0;
533 available = 64;
534 }
535
536 memset(&ctx->buffer[used], 0, available - 8);
537
538 ctx->lo <<= 3;
539 ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
540 ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
541 ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
542 ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24);
543 ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
544 ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
545 ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
546 ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
547
548 body(ctx, ctx->buffer, 64);
549
550 result[0] = curlx_ultouc((ctx->a)&0xff);
551 result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
552 result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
553 result[3] = curlx_ultouc(ctx->a >> 24);
554 result[4] = curlx_ultouc((ctx->b)&0xff);
555 result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
556 result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
557 result[7] = curlx_ultouc(ctx->b >> 24);
558 result[8] = curlx_ultouc((ctx->c)&0xff);
559 result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
560 result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
561 result[11] = curlx_ultouc(ctx->c >> 24);
562 result[12] = curlx_ultouc((ctx->d)&0xff);
563 result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
564 result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
565 result[15] = curlx_ultouc(ctx->d >> 24);
566
567 memset(ctx, 0, sizeof(*ctx));
568}
569
570#endif /* CRYPTO LIBS */
571
572const struct HMAC_params Curl_HMAC_MD5[] = {
573 {
574 /* Hash initialization function. */
575 CURLX_FUNCTION_CAST(HMAC_hinit_func, my_md5_init),
576 /* Hash update function. */
577 CURLX_FUNCTION_CAST(HMAC_hupdate_func, my_md5_update),
578 /* Hash computation end function. */
579 CURLX_FUNCTION_CAST(HMAC_hfinal_func, my_md5_final),
580 /* Size of hash context structure. */
581 sizeof(my_md5_ctx),
582 /* Maximum key length. */
583 64,
584 /* Result size. */
585 16
586 }
587};
588
589const struct MD5_params Curl_DIGEST_MD5[] = {
590 {
591 /* Digest initialization function */
592 CURLX_FUNCTION_CAST(Curl_MD5_init_func, my_md5_init),
593 /* Digest update function */
594 CURLX_FUNCTION_CAST(Curl_MD5_update_func, my_md5_update),
595 /* Digest computation end function */
596 CURLX_FUNCTION_CAST(Curl_MD5_final_func, my_md5_final),
597 /* Size of digest context struct */
598 sizeof(my_md5_ctx),
599 /* Result size */
600 16
601 }
602};
603
604/*
605 * @unittest: 1601
606 * Returns CURLE_OK on success.
607 */
608CURLcode Curl_md5it(unsigned char *outbuffer, const unsigned char *input,
609 const size_t len)
610{
611 CURLcode result;
612 my_md5_ctx ctx;
613
614 result = my_md5_init(&ctx);
615 if(!result) {
616 my_md5_update(&ctx, input, curlx_uztoui(len));
617 my_md5_final(outbuffer, &ctx);
618 }
619 return result;
620}
621
622struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params)
623{
624 struct MD5_context *ctxt;
625
626 /* Create MD5 context */
627 ctxt = malloc(sizeof(*ctxt));
628
629 if(!ctxt)
630 return ctxt;
631
632 ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize);
633
634 if(!ctxt->md5_hashctx) {
635 free(ctxt);
636 return NULL;
637 }
638
639 ctxt->md5_hash = md5params;
640
641 if((*md5params->md5_init_func)(ctxt->md5_hashctx)) {
642 free(ctxt->md5_hashctx);
643 free(ctxt);
644 return NULL;
645 }
646
647 return ctxt;
648}
649
650CURLcode Curl_MD5_update(struct MD5_context *context,
651 const unsigned char *data,
652 unsigned int len)
653{
654 (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
655
656 return CURLE_OK;
657}
658
659CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
660{
661 (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
662
663 free(context->md5_hashctx);
664 free(context);
665
666 return CURLE_OK;
667}
668
669#endif /* CURL_DISABLE_CRYPTO_AUTH */
670