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