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