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