xref: /curl/lib/md5.c (revision c074ba64)
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 are 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 is 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 is 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 MD5_F(x, y, z)                  ((z) ^ ((x) & ((y) ^ (z))))
308 #define MD5_G(x, y, z)                  ((y) ^ ((z) & ((x) ^ (y))))
309 #define MD5_H(x, y, z)                  (((x) ^ (y)) ^ (z))
310 #define MD5_H2(x, y, z)                 ((x) ^ ((y) ^ (z)))
311 #define MD5_I(x, y, z)                  ((y) ^ ((x) | ~(z)))
312 
313 /*
314  * The MD5 transformation for all four rounds.
315  */
316 #define MD5_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  * does not work.
328  */
329 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
330 #define MD5_SET(n) \
331         (*(MD5_u32plus *)(void *)&ptr[(n) * 4])
332 #define MD5_GET(n) \
333         MD5_SET(n)
334 #else
335 #define MD5_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 MD5_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  */
my_md5_body(my_md5_ctx * ctx,const void * data,unsigned long size)349 static const void *my_md5_body(my_md5_ctx *ctx,
350                                const void *data, unsigned long size)
351 {
352   const unsigned char *ptr;
353   MD5_u32plus a, b, c, d;
354 
355   ptr = (const unsigned char *)data;
356 
357   a = ctx->a;
358   b = ctx->b;
359   c = ctx->c;
360   d = ctx->d;
361 
362   do {
363     MD5_u32plus saved_a, saved_b, saved_c, saved_d;
364 
365     saved_a = a;
366     saved_b = b;
367     saved_c = c;
368     saved_d = d;
369 
370 /* Round 1 */
371     MD5_STEP(MD5_F, a, b, c, d, MD5_SET(0), 0xd76aa478, 7)
372     MD5_STEP(MD5_F, d, a, b, c, MD5_SET(1), 0xe8c7b756, 12)
373     MD5_STEP(MD5_F, c, d, a, b, MD5_SET(2), 0x242070db, 17)
374     MD5_STEP(MD5_F, b, c, d, a, MD5_SET(3), 0xc1bdceee, 22)
375     MD5_STEP(MD5_F, a, b, c, d, MD5_SET(4), 0xf57c0faf, 7)
376     MD5_STEP(MD5_F, d, a, b, c, MD5_SET(5), 0x4787c62a, 12)
377     MD5_STEP(MD5_F, c, d, a, b, MD5_SET(6), 0xa8304613, 17)
378     MD5_STEP(MD5_F, b, c, d, a, MD5_SET(7), 0xfd469501, 22)
379     MD5_STEP(MD5_F, a, b, c, d, MD5_SET(8), 0x698098d8, 7)
380     MD5_STEP(MD5_F, d, a, b, c, MD5_SET(9), 0x8b44f7af, 12)
381     MD5_STEP(MD5_F, c, d, a, b, MD5_SET(10), 0xffff5bb1, 17)
382     MD5_STEP(MD5_F, b, c, d, a, MD5_SET(11), 0x895cd7be, 22)
383     MD5_STEP(MD5_F, a, b, c, d, MD5_SET(12), 0x6b901122, 7)
384     MD5_STEP(MD5_F, d, a, b, c, MD5_SET(13), 0xfd987193, 12)
385     MD5_STEP(MD5_F, c, d, a, b, MD5_SET(14), 0xa679438e, 17)
386     MD5_STEP(MD5_F, b, c, d, a, MD5_SET(15), 0x49b40821, 22)
387 
388 /* Round 2 */
389     MD5_STEP(MD5_G, a, b, c, d, MD5_GET(1), 0xf61e2562, 5)
390     MD5_STEP(MD5_G, d, a, b, c, MD5_GET(6), 0xc040b340, 9)
391     MD5_STEP(MD5_G, c, d, a, b, MD5_GET(11), 0x265e5a51, 14)
392     MD5_STEP(MD5_G, b, c, d, a, MD5_GET(0), 0xe9b6c7aa, 20)
393     MD5_STEP(MD5_G, a, b, c, d, MD5_GET(5), 0xd62f105d, 5)
394     MD5_STEP(MD5_G, d, a, b, c, MD5_GET(10), 0x02441453, 9)
395     MD5_STEP(MD5_G, c, d, a, b, MD5_GET(15), 0xd8a1e681, 14)
396     MD5_STEP(MD5_G, b, c, d, a, MD5_GET(4), 0xe7d3fbc8, 20)
397     MD5_STEP(MD5_G, a, b, c, d, MD5_GET(9), 0x21e1cde6, 5)
398     MD5_STEP(MD5_G, d, a, b, c, MD5_GET(14), 0xc33707d6, 9)
399     MD5_STEP(MD5_G, c, d, a, b, MD5_GET(3), 0xf4d50d87, 14)
400     MD5_STEP(MD5_G, b, c, d, a, MD5_GET(8), 0x455a14ed, 20)
401     MD5_STEP(MD5_G, a, b, c, d, MD5_GET(13), 0xa9e3e905, 5)
402     MD5_STEP(MD5_G, d, a, b, c, MD5_GET(2), 0xfcefa3f8, 9)
403     MD5_STEP(MD5_G, c, d, a, b, MD5_GET(7), 0x676f02d9, 14)
404     MD5_STEP(MD5_G, b, c, d, a, MD5_GET(12), 0x8d2a4c8a, 20)
405 
406 /* Round 3 */
407     MD5_STEP(MD5_H, a, b, c, d, MD5_GET(5), 0xfffa3942, 4)
408     MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(8), 0x8771f681, 11)
409     MD5_STEP(MD5_H, c, d, a, b, MD5_GET(11), 0x6d9d6122, 16)
410     MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(14), 0xfde5380c, 23)
411     MD5_STEP(MD5_H, a, b, c, d, MD5_GET(1), 0xa4beea44, 4)
412     MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(4), 0x4bdecfa9, 11)
413     MD5_STEP(MD5_H, c, d, a, b, MD5_GET(7), 0xf6bb4b60, 16)
414     MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(10), 0xbebfbc70, 23)
415     MD5_STEP(MD5_H, a, b, c, d, MD5_GET(13), 0x289b7ec6, 4)
416     MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(0), 0xeaa127fa, 11)
417     MD5_STEP(MD5_H, c, d, a, b, MD5_GET(3), 0xd4ef3085, 16)
418     MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(6), 0x04881d05, 23)
419     MD5_STEP(MD5_H, a, b, c, d, MD5_GET(9), 0xd9d4d039, 4)
420     MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(12), 0xe6db99e5, 11)
421     MD5_STEP(MD5_H, c, d, a, b, MD5_GET(15), 0x1fa27cf8, 16)
422     MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(2), 0xc4ac5665, 23)
423 
424 /* Round 4 */
425     MD5_STEP(MD5_I, a, b, c, d, MD5_GET(0), 0xf4292244, 6)
426     MD5_STEP(MD5_I, d, a, b, c, MD5_GET(7), 0x432aff97, 10)
427     MD5_STEP(MD5_I, c, d, a, b, MD5_GET(14), 0xab9423a7, 15)
428     MD5_STEP(MD5_I, b, c, d, a, MD5_GET(5), 0xfc93a039, 21)
429     MD5_STEP(MD5_I, a, b, c, d, MD5_GET(12), 0x655b59c3, 6)
430     MD5_STEP(MD5_I, d, a, b, c, MD5_GET(3), 0x8f0ccc92, 10)
431     MD5_STEP(MD5_I, c, d, a, b, MD5_GET(10), 0xffeff47d, 15)
432     MD5_STEP(MD5_I, b, c, d, a, MD5_GET(1), 0x85845dd1, 21)
433     MD5_STEP(MD5_I, a, b, c, d, MD5_GET(8), 0x6fa87e4f, 6)
434     MD5_STEP(MD5_I, d, a, b, c, MD5_GET(15), 0xfe2ce6e0, 10)
435     MD5_STEP(MD5_I, c, d, a, b, MD5_GET(6), 0xa3014314, 15)
436     MD5_STEP(MD5_I, b, c, d, a, MD5_GET(13), 0x4e0811a1, 21)
437     MD5_STEP(MD5_I, a, b, c, d, MD5_GET(4), 0xf7537e82, 6)
438     MD5_STEP(MD5_I, d, a, b, c, MD5_GET(11), 0xbd3af235, 10)
439     MD5_STEP(MD5_I, c, d, a, b, MD5_GET(2), 0x2ad7d2bb, 15)
440     MD5_STEP(MD5_I, b, c, d, a, MD5_GET(9), 0xeb86d391, 21)
441 
442     a += saved_a;
443     b += saved_b;
444     c += saved_c;
445     d += saved_d;
446 
447     ptr += 64;
448   } while(size -= 64);
449 
450   ctx->a = a;
451   ctx->b = b;
452   ctx->c = c;
453   ctx->d = d;
454 
455   return ptr;
456 }
457 
my_md5_init(my_md5_ctx * ctx)458 static CURLcode my_md5_init(my_md5_ctx *ctx)
459 {
460   ctx->a = 0x67452301;
461   ctx->b = 0xefcdab89;
462   ctx->c = 0x98badcfe;
463   ctx->d = 0x10325476;
464 
465   ctx->lo = 0;
466   ctx->hi = 0;
467 
468   return CURLE_OK;
469 }
470 
my_md5_update(my_md5_ctx * ctx,const void * data,unsigned long size)471 static void my_md5_update(my_md5_ctx *ctx, const void *data,
472                           unsigned long size)
473 {
474   MD5_u32plus saved_lo;
475   unsigned long used;
476 
477   saved_lo = ctx->lo;
478   ctx->lo = (saved_lo + size) & 0x1fffffff;
479   if(ctx->lo < saved_lo)
480     ctx->hi++;
481   ctx->hi += (MD5_u32plus)size >> 29;
482 
483   used = saved_lo & 0x3f;
484 
485   if(used) {
486     unsigned long available = 64 - used;
487 
488     if(size < available) {
489       memcpy(&ctx->buffer[used], data, size);
490       return;
491     }
492 
493     memcpy(&ctx->buffer[used], data, available);
494     data = (const unsigned char *)data + available;
495     size -= available;
496     my_md5_body(ctx, ctx->buffer, 64);
497   }
498 
499   if(size >= 64) {
500     data = my_md5_body(ctx, data, size & ~(unsigned long)0x3f);
501     size &= 0x3f;
502   }
503 
504   memcpy(ctx->buffer, data, size);
505 }
506 
my_md5_final(unsigned char * result,my_md5_ctx * ctx)507 static void my_md5_final(unsigned char *result, my_md5_ctx *ctx)
508 {
509   unsigned long used, available;
510 
511   used = ctx->lo & 0x3f;
512 
513   ctx->buffer[used++] = 0x80;
514 
515   available = 64 - used;
516 
517   if(available < 8) {
518     memset(&ctx->buffer[used], 0, available);
519     my_md5_body(ctx, ctx->buffer, 64);
520     used = 0;
521     available = 64;
522   }
523 
524   memset(&ctx->buffer[used], 0, available - 8);
525 
526   ctx->lo <<= 3;
527   ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
528   ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
529   ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
530   ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24);
531   ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
532   ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
533   ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
534   ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
535 
536   my_md5_body(ctx, ctx->buffer, 64);
537 
538   result[0] = curlx_ultouc((ctx->a)&0xff);
539   result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
540   result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
541   result[3] = curlx_ultouc(ctx->a >> 24);
542   result[4] = curlx_ultouc((ctx->b)&0xff);
543   result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
544   result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
545   result[7] = curlx_ultouc(ctx->b >> 24);
546   result[8] = curlx_ultouc((ctx->c)&0xff);
547   result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
548   result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
549   result[11] = curlx_ultouc(ctx->c >> 24);
550   result[12] = curlx_ultouc((ctx->d)&0xff);
551   result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
552   result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
553   result[15] = curlx_ultouc(ctx->d >> 24);
554 
555   memset(ctx, 0, sizeof(*ctx));
556 }
557 
558 #endif /* CRYPTO LIBS */
559 
560 const struct HMAC_params Curl_HMAC_MD5[] = {
561   {
562     /* Hash initialization function. */
563     CURLX_FUNCTION_CAST(HMAC_hinit_func, my_md5_init),
564     /* Hash update function. */
565     CURLX_FUNCTION_CAST(HMAC_hupdate_func, my_md5_update),
566     /* Hash computation end function. */
567     CURLX_FUNCTION_CAST(HMAC_hfinal_func, my_md5_final),
568     /* Size of hash context structure. */
569     sizeof(my_md5_ctx),
570     /* Maximum key length. */
571     64,
572     /* Result size. */
573     16
574   }
575 };
576 
577 const struct MD5_params Curl_DIGEST_MD5[] = {
578   {
579     /* Digest initialization function */
580     CURLX_FUNCTION_CAST(Curl_MD5_init_func, my_md5_init),
581     /* Digest update function */
582     CURLX_FUNCTION_CAST(Curl_MD5_update_func, my_md5_update),
583     /* Digest computation end function */
584     CURLX_FUNCTION_CAST(Curl_MD5_final_func, my_md5_final),
585     /* Size of digest context struct */
586     sizeof(my_md5_ctx),
587     /* Result size */
588     16
589   }
590 };
591 
592 /*
593  * @unittest: 1601
594  * Returns CURLE_OK on success.
595  */
Curl_md5it(unsigned char * outbuffer,const unsigned char * input,const size_t len)596 CURLcode Curl_md5it(unsigned char *outbuffer, const unsigned char *input,
597                     const size_t len)
598 {
599   CURLcode result;
600   my_md5_ctx ctx;
601 
602   result = my_md5_init(&ctx);
603   if(!result) {
604     my_md5_update(&ctx, input, curlx_uztoui(len));
605     my_md5_final(outbuffer, &ctx);
606   }
607   return result;
608 }
609 
Curl_MD5_init(const struct MD5_params * md5params)610 struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params)
611 {
612   struct MD5_context *ctxt;
613 
614   /* Create MD5 context */
615   ctxt = malloc(sizeof(*ctxt));
616 
617   if(!ctxt)
618     return ctxt;
619 
620   ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize);
621 
622   if(!ctxt->md5_hashctx) {
623     free(ctxt);
624     return NULL;
625   }
626 
627   ctxt->md5_hash = md5params;
628 
629   if((*md5params->md5_init_func)(ctxt->md5_hashctx)) {
630     free(ctxt->md5_hashctx);
631     free(ctxt);
632     return NULL;
633   }
634 
635   return ctxt;
636 }
637 
Curl_MD5_update(struct MD5_context * context,const unsigned char * data,unsigned int len)638 CURLcode Curl_MD5_update(struct MD5_context *context,
639                          const unsigned char *data,
640                          unsigned int len)
641 {
642   (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
643 
644   return CURLE_OK;
645 }
646 
Curl_MD5_final(struct MD5_context * context,unsigned char * result)647 CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
648 {
649   (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
650 
651   free(context->md5_hashctx);
652   free(context);
653 
654   return CURLE_OK;
655 }
656 
657 #endif /* Using NTLM (without SSPI) || Digest */
658