• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
89 typedef struct md5_ctx my_md5_ctx;
90 
my_md5_init(my_md5_ctx * ctx)91 static CURLcode my_md5_init(my_md5_ctx *ctx)
92 {
93   md5_init(ctx);
94   return CURLE_OK;
95 }
96 
my_md5_update(my_md5_ctx * ctx,const unsigned char * input,unsigned int inputLen)97 static 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 
my_md5_final(unsigned char * digest,my_md5_ctx * ctx)104 static 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 
111 typedef MD5_CTX my_md5_ctx;
112 
my_md5_init(my_md5_ctx * ctx)113 static 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 
my_md5_update(my_md5_ctx * ctx,const unsigned char * input,unsigned int len)121 static 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 
my_md5_final(unsigned char * digest,my_md5_ctx * ctx)128 static 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 
135 typedef mbedtls_md5_context my_md5_ctx;
136 
my_md5_init(my_md5_ctx * ctx)137 static 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 
my_md5_update(my_md5_ctx * ctx,const unsigned char * data,unsigned int length)151 static 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 
my_md5_final(unsigned char * digest,my_md5_ctx * ctx)162 static 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 
my_md5_init(my_md5_ctx * ctx)181 static 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 
my_md5_update(my_md5_ctx * ctx,const unsigned char * input,unsigned int inputLen)189 static 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 
my_md5_final(unsigned char * digest,my_md5_ctx * ctx)196 static 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 
203 struct md5_ctx {
204   HCRYPTPROV hCryptProv;
205   HCRYPTHASH hHash;
206 };
207 typedef struct md5_ctx my_md5_ctx;
208 
my_md5_init(my_md5_ctx * ctx)209 static 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 
my_md5_update(my_md5_ctx * ctx,const unsigned char * input,unsigned int inputLen)224 static 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 
my_md5_final(unsigned char * digest,my_md5_ctx * ctx)231 static 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 */
285 typedef unsigned int MD5_u32plus;
286 
287 struct 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 };
293 typedef struct md5_ctx my_md5_ctx;
294 
295 static CURLcode my_md5_init(my_md5_ctx *ctx);
296 static void my_md5_update(my_md5_ctx *ctx, const void *data,
297                           unsigned long size);
298 static 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  */
body(my_md5_ctx * ctx,const void * data,unsigned long size)349 static 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 
my_md5_init(my_md5_ctx * ctx)457 static 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 
my_md5_update(my_md5_ctx * ctx,const void * data,unsigned long size)470 static 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 
my_md5_final(unsigned char * result,my_md5_ctx * ctx)506 static 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 
559 const 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 
576 const 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  */
Curl_md5it(unsigned char * outbuffer,const unsigned char * input,const size_t len)595 CURLcode 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 
Curl_MD5_init(const struct MD5_params * md5params)609 struct 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 
Curl_MD5_update(struct MD5_context * context,const unsigned char * data,unsigned int len)637 CURLcode 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 
Curl_MD5_final(struct MD5_context * context,unsigned char * result)646 CURLcode 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