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