xref: /third_party/curl/lib/md5.c (revision 13498266)
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(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(ctx, input, len);
126}
127
128static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
129{
130  (void)MD5_Final(digest, 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);
602  if(!result) {
603    my_md5_update(&ctx, input, curlx_uztoui(len));
604    my_md5_final(outbuffer, &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