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