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(void * ctx)91 static CURLcode my_md5_init(void *ctx)
92 {
93 md5_init(ctx);
94 return CURLE_OK;
95 }
96
my_md5_update(void * ctx,const unsigned char * input,unsigned int inputLen)97 static void my_md5_update(void *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,void * ctx)104 static void my_md5_final(unsigned char *digest, void *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(void * ctx)113 static CURLcode my_md5_init(void *ctx)
114 {
115 if(!MD5_Init(ctx))
116 return CURLE_OUT_OF_MEMORY;
117
118 return CURLE_OK;
119 }
120
my_md5_update(void * ctx,const unsigned char * input,unsigned int len)121 static void my_md5_update(void *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,void * ctx)128 static void my_md5_final(unsigned char *digest, void *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(void * ctx)137 static CURLcode my_md5_init(void *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(void * ctx,const unsigned char * data,unsigned int length)151 static void my_md5_update(void *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,void * ctx)162 static void my_md5_final(unsigned char *digest, void *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(void * ctx)181 static CURLcode my_md5_init(void *ctx)
182 {
183 if(!CC_MD5_Init(ctx))
184 return CURLE_OUT_OF_MEMORY;
185
186 return CURLE_OK;
187 }
188
my_md5_update(void * ctx,const unsigned char * input,unsigned int inputLen)189 static void my_md5_update(void *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,void * ctx)196 static void my_md5_final(unsigned char *digest, void *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(void * in)209 static CURLcode my_md5_init(void *in)
210 {
211 my_md5_ctx *ctx = (my_md5_ctx *)in;
212 if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
213 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
214 return CURLE_OUT_OF_MEMORY;
215
216 if(!CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash)) {
217 CryptReleaseContext(ctx->hCryptProv, 0);
218 ctx->hCryptProv = 0;
219 return CURLE_FAILED_INIT;
220 }
221
222 return CURLE_OK;
223 }
224
my_md5_update(void * in,const unsigned char * input,unsigned int inputLen)225 static void my_md5_update(void *in,
226 const unsigned char *input,
227 unsigned int inputLen)
228 {
229 my_md5_ctx *ctx = in;
230 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
231 }
232
my_md5_final(unsigned char * digest,void * in)233 static void my_md5_final(unsigned char *digest, void *in)
234 {
235 my_md5_ctx *ctx = (my_md5_ctx *)in;
236 unsigned long length = 0;
237 CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
238 if(length == 16)
239 CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
240 if(ctx->hHash)
241 CryptDestroyHash(ctx->hHash);
242 if(ctx->hCryptProv)
243 CryptReleaseContext(ctx->hCryptProv, 0);
244 }
245
246 #else
247
248 /* When no other crypto library is available we use this code segment */
249
250 /*
251 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
252 * MD5 Message-Digest Algorithm (RFC 1321).
253 *
254 * Homepage:
255 https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
256 *
257 * Author:
258 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
259 *
260 * This software was written by Alexander Peslyak in 2001. No copyright is
261 * claimed, and the software is hereby placed in the public domain.
262 * In case this attempt to disclaim copyright and place the software in the
263 * public domain is deemed null and void, then the software is
264 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
265 * general public under the following terms:
266 *
267 * Redistribution and use in source and binary forms, with or without
268 * modification, are permitted.
269 *
270 * There is ABSOLUTELY NO WARRANTY, express or implied.
271 *
272 * (This is a heavily cut-down "BSD license".)
273 *
274 * This differs from Colin Plumb's older public domain implementation in that
275 * no exactly 32-bit integer data type is required (any 32-bit or wider
276 * unsigned integer data type will do), there is no compile-time endianness
277 * configuration, and the function prototypes match OpenSSL's. No code from
278 * Colin Plumb's implementation has been reused; this comment merely compares
279 * the properties of the two independent implementations.
280 *
281 * The primary goals of this implementation are portability and ease of use.
282 * It is meant to be fast, but not as fast as possible. Some known
283 * optimizations are not included to reduce source code size and avoid
284 * compile-time configuration.
285 */
286
287 /* Any 32-bit or wider unsigned integer data type will do */
288 typedef unsigned int MD5_u32plus;
289
290 struct md5_ctx {
291 MD5_u32plus lo, hi;
292 MD5_u32plus a, b, c, d;
293 unsigned char buffer[64];
294 MD5_u32plus block[16];
295 };
296 typedef struct md5_ctx my_md5_ctx;
297
298 static CURLcode my_md5_init(void *ctx);
299 static void my_md5_update(void *ctx, const unsigned char *data,
300 unsigned int size);
301 static void my_md5_final(unsigned char *result, void *ctx);
302
303 /*
304 * The basic MD5 functions.
305 *
306 * F and G are optimized compared to their RFC 1321 definitions for
307 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
308 * implementation.
309 */
310 #define MD5_F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
311 #define MD5_G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
312 #define MD5_H(x, y, z) (((x) ^ (y)) ^ (z))
313 #define MD5_H2(x, y, z) ((x) ^ ((y) ^ (z)))
314 #define MD5_I(x, y, z) ((y) ^ ((x) | ~(z)))
315
316 /*
317 * The MD5 transformation for all four rounds.
318 */
319 #define MD5_STEP(f, a, b, c, d, x, t, s) \
320 (a) += f((b), (c), (d)) + (x) + (t); \
321 (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
322 (a) += (b);
323
324 /*
325 * SET reads 4 input bytes in little-endian byte order and stores them
326 * in a properly aligned word in host byte order.
327 *
328 * The check for little-endian architectures that tolerate unaligned
329 * memory accesses is just an optimization. Nothing will break if it
330 * does not work.
331 */
332 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
333 #define MD5_SET(n) \
334 (*(MD5_u32plus *)(void *)&ptr[(n) * 4])
335 #define MD5_GET(n) \
336 MD5_SET(n)
337 #else
338 #define MD5_SET(n) \
339 (ctx->block[(n)] = \
340 (MD5_u32plus)ptr[(n) * 4] | \
341 ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
342 ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
343 ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
344 #define MD5_GET(n) \
345 (ctx->block[(n)])
346 #endif
347
348 /*
349 * This processes one or more 64-byte data blocks, but does NOT update
350 * the bit counters. There are no alignment requirements.
351 */
my_md5_body(my_md5_ctx * ctx,const void * data,unsigned long size)352 static const void *my_md5_body(my_md5_ctx *ctx,
353 const void *data, unsigned long size)
354 {
355 const unsigned char *ptr;
356 MD5_u32plus a, b, c, d;
357
358 ptr = (const unsigned char *)data;
359
360 a = ctx->a;
361 b = ctx->b;
362 c = ctx->c;
363 d = ctx->d;
364
365 do {
366 MD5_u32plus saved_a, saved_b, saved_c, saved_d;
367
368 saved_a = a;
369 saved_b = b;
370 saved_c = c;
371 saved_d = d;
372
373 /* Round 1 */
374 MD5_STEP(MD5_F, a, b, c, d, MD5_SET(0), 0xd76aa478, 7)
375 MD5_STEP(MD5_F, d, a, b, c, MD5_SET(1), 0xe8c7b756, 12)
376 MD5_STEP(MD5_F, c, d, a, b, MD5_SET(2), 0x242070db, 17)
377 MD5_STEP(MD5_F, b, c, d, a, MD5_SET(3), 0xc1bdceee, 22)
378 MD5_STEP(MD5_F, a, b, c, d, MD5_SET(4), 0xf57c0faf, 7)
379 MD5_STEP(MD5_F, d, a, b, c, MD5_SET(5), 0x4787c62a, 12)
380 MD5_STEP(MD5_F, c, d, a, b, MD5_SET(6), 0xa8304613, 17)
381 MD5_STEP(MD5_F, b, c, d, a, MD5_SET(7), 0xfd469501, 22)
382 MD5_STEP(MD5_F, a, b, c, d, MD5_SET(8), 0x698098d8, 7)
383 MD5_STEP(MD5_F, d, a, b, c, MD5_SET(9), 0x8b44f7af, 12)
384 MD5_STEP(MD5_F, c, d, a, b, MD5_SET(10), 0xffff5bb1, 17)
385 MD5_STEP(MD5_F, b, c, d, a, MD5_SET(11), 0x895cd7be, 22)
386 MD5_STEP(MD5_F, a, b, c, d, MD5_SET(12), 0x6b901122, 7)
387 MD5_STEP(MD5_F, d, a, b, c, MD5_SET(13), 0xfd987193, 12)
388 MD5_STEP(MD5_F, c, d, a, b, MD5_SET(14), 0xa679438e, 17)
389 MD5_STEP(MD5_F, b, c, d, a, MD5_SET(15), 0x49b40821, 22)
390
391 /* Round 2 */
392 MD5_STEP(MD5_G, a, b, c, d, MD5_GET(1), 0xf61e2562, 5)
393 MD5_STEP(MD5_G, d, a, b, c, MD5_GET(6), 0xc040b340, 9)
394 MD5_STEP(MD5_G, c, d, a, b, MD5_GET(11), 0x265e5a51, 14)
395 MD5_STEP(MD5_G, b, c, d, a, MD5_GET(0), 0xe9b6c7aa, 20)
396 MD5_STEP(MD5_G, a, b, c, d, MD5_GET(5), 0xd62f105d, 5)
397 MD5_STEP(MD5_G, d, a, b, c, MD5_GET(10), 0x02441453, 9)
398 MD5_STEP(MD5_G, c, d, a, b, MD5_GET(15), 0xd8a1e681, 14)
399 MD5_STEP(MD5_G, b, c, d, a, MD5_GET(4), 0xe7d3fbc8, 20)
400 MD5_STEP(MD5_G, a, b, c, d, MD5_GET(9), 0x21e1cde6, 5)
401 MD5_STEP(MD5_G, d, a, b, c, MD5_GET(14), 0xc33707d6, 9)
402 MD5_STEP(MD5_G, c, d, a, b, MD5_GET(3), 0xf4d50d87, 14)
403 MD5_STEP(MD5_G, b, c, d, a, MD5_GET(8), 0x455a14ed, 20)
404 MD5_STEP(MD5_G, a, b, c, d, MD5_GET(13), 0xa9e3e905, 5)
405 MD5_STEP(MD5_G, d, a, b, c, MD5_GET(2), 0xfcefa3f8, 9)
406 MD5_STEP(MD5_G, c, d, a, b, MD5_GET(7), 0x676f02d9, 14)
407 MD5_STEP(MD5_G, b, c, d, a, MD5_GET(12), 0x8d2a4c8a, 20)
408
409 /* Round 3 */
410 MD5_STEP(MD5_H, a, b, c, d, MD5_GET(5), 0xfffa3942, 4)
411 MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(8), 0x8771f681, 11)
412 MD5_STEP(MD5_H, c, d, a, b, MD5_GET(11), 0x6d9d6122, 16)
413 MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(14), 0xfde5380c, 23)
414 MD5_STEP(MD5_H, a, b, c, d, MD5_GET(1), 0xa4beea44, 4)
415 MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(4), 0x4bdecfa9, 11)
416 MD5_STEP(MD5_H, c, d, a, b, MD5_GET(7), 0xf6bb4b60, 16)
417 MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(10), 0xbebfbc70, 23)
418 MD5_STEP(MD5_H, a, b, c, d, MD5_GET(13), 0x289b7ec6, 4)
419 MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(0), 0xeaa127fa, 11)
420 MD5_STEP(MD5_H, c, d, a, b, MD5_GET(3), 0xd4ef3085, 16)
421 MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(6), 0x04881d05, 23)
422 MD5_STEP(MD5_H, a, b, c, d, MD5_GET(9), 0xd9d4d039, 4)
423 MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(12), 0xe6db99e5, 11)
424 MD5_STEP(MD5_H, c, d, a, b, MD5_GET(15), 0x1fa27cf8, 16)
425 MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(2), 0xc4ac5665, 23)
426
427 /* Round 4 */
428 MD5_STEP(MD5_I, a, b, c, d, MD5_GET(0), 0xf4292244, 6)
429 MD5_STEP(MD5_I, d, a, b, c, MD5_GET(7), 0x432aff97, 10)
430 MD5_STEP(MD5_I, c, d, a, b, MD5_GET(14), 0xab9423a7, 15)
431 MD5_STEP(MD5_I, b, c, d, a, MD5_GET(5), 0xfc93a039, 21)
432 MD5_STEP(MD5_I, a, b, c, d, MD5_GET(12), 0x655b59c3, 6)
433 MD5_STEP(MD5_I, d, a, b, c, MD5_GET(3), 0x8f0ccc92, 10)
434 MD5_STEP(MD5_I, c, d, a, b, MD5_GET(10), 0xffeff47d, 15)
435 MD5_STEP(MD5_I, b, c, d, a, MD5_GET(1), 0x85845dd1, 21)
436 MD5_STEP(MD5_I, a, b, c, d, MD5_GET(8), 0x6fa87e4f, 6)
437 MD5_STEP(MD5_I, d, a, b, c, MD5_GET(15), 0xfe2ce6e0, 10)
438 MD5_STEP(MD5_I, c, d, a, b, MD5_GET(6), 0xa3014314, 15)
439 MD5_STEP(MD5_I, b, c, d, a, MD5_GET(13), 0x4e0811a1, 21)
440 MD5_STEP(MD5_I, a, b, c, d, MD5_GET(4), 0xf7537e82, 6)
441 MD5_STEP(MD5_I, d, a, b, c, MD5_GET(11), 0xbd3af235, 10)
442 MD5_STEP(MD5_I, c, d, a, b, MD5_GET(2), 0x2ad7d2bb, 15)
443 MD5_STEP(MD5_I, b, c, d, a, MD5_GET(9), 0xeb86d391, 21)
444
445 a += saved_a;
446 b += saved_b;
447 c += saved_c;
448 d += saved_d;
449
450 ptr += 64;
451 } while(size -= 64);
452
453 ctx->a = a;
454 ctx->b = b;
455 ctx->c = c;
456 ctx->d = d;
457
458 return ptr;
459 }
460
my_md5_init(void * in)461 static CURLcode my_md5_init(void *in)
462 {
463 my_md5_ctx *ctx = (my_md5_ctx *)in;
464 ctx->a = 0x67452301;
465 ctx->b = 0xefcdab89;
466 ctx->c = 0x98badcfe;
467 ctx->d = 0x10325476;
468
469 ctx->lo = 0;
470 ctx->hi = 0;
471
472 return CURLE_OK;
473 }
474
my_md5_update(void * in,const unsigned char * data,unsigned int size)475 static void my_md5_update(void *in, const unsigned char *data,
476 unsigned int size)
477 {
478 MD5_u32plus saved_lo;
479 unsigned int used;
480 my_md5_ctx *ctx = (my_md5_ctx *)in;
481
482 saved_lo = ctx->lo;
483 ctx->lo = (saved_lo + size) & 0x1fffffff;
484 if(ctx->lo < saved_lo)
485 ctx->hi++;
486 ctx->hi += (MD5_u32plus)size >> 29;
487
488 used = saved_lo & 0x3f;
489
490 if(used) {
491 unsigned int available = 64 - used;
492
493 if(size < available) {
494 memcpy(&ctx->buffer[used], data, size);
495 return;
496 }
497
498 memcpy(&ctx->buffer[used], data, available);
499 data = (const unsigned char *)data + available;
500 size -= available;
501 my_md5_body(ctx, ctx->buffer, 64);
502 }
503
504 if(size >= 64) {
505 data = my_md5_body(ctx, data, size & ~(unsigned long)0x3f);
506 size &= 0x3f;
507 }
508
509 memcpy(ctx->buffer, data, size);
510 }
511
my_md5_final(unsigned char * result,void * in)512 static void my_md5_final(unsigned char *result, void *in)
513 {
514 unsigned int used, available;
515 my_md5_ctx *ctx = (my_md5_ctx *)in;
516
517 used = ctx->lo & 0x3f;
518
519 ctx->buffer[used++] = 0x80;
520
521 available = 64 - used;
522
523 if(available < 8) {
524 memset(&ctx->buffer[used], 0, available);
525 my_md5_body(ctx, ctx->buffer, 64);
526 used = 0;
527 available = 64;
528 }
529
530 memset(&ctx->buffer[used], 0, available - 8);
531
532 ctx->lo <<= 3;
533 ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
534 ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
535 ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
536 ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24);
537 ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
538 ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
539 ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
540 ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
541
542 my_md5_body(ctx, ctx->buffer, 64);
543
544 result[0] = curlx_ultouc((ctx->a)&0xff);
545 result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
546 result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
547 result[3] = curlx_ultouc(ctx->a >> 24);
548 result[4] = curlx_ultouc((ctx->b)&0xff);
549 result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
550 result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
551 result[7] = curlx_ultouc(ctx->b >> 24);
552 result[8] = curlx_ultouc((ctx->c)&0xff);
553 result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
554 result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
555 result[11] = curlx_ultouc(ctx->c >> 24);
556 result[12] = curlx_ultouc((ctx->d)&0xff);
557 result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
558 result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
559 result[15] = curlx_ultouc(ctx->d >> 24);
560
561 memset(ctx, 0, sizeof(*ctx));
562 }
563
564 #endif /* CRYPTO LIBS */
565
566 const struct HMAC_params Curl_HMAC_MD5 = {
567 my_md5_init, /* Hash initialization function. */
568 my_md5_update, /* Hash update function. */
569 my_md5_final, /* Hash computation end function. */
570 sizeof(my_md5_ctx), /* Size of hash context structure. */
571 64, /* Maximum key length. */
572 16 /* Result size. */
573 };
574
575 const struct MD5_params Curl_DIGEST_MD5 = {
576 my_md5_init, /* Digest initialization function */
577 my_md5_update, /* Digest update function */
578 my_md5_final, /* Digest computation end function */
579 sizeof(my_md5_ctx), /* Size of digest context struct */
580 16 /* Result size */
581 };
582
583 /*
584 * @unittest: 1601
585 * Returns CURLE_OK on success.
586 */
Curl_md5it(unsigned char * outbuffer,const unsigned char * input,const size_t len)587 CURLcode Curl_md5it(unsigned char *outbuffer, const unsigned char *input,
588 const size_t len)
589 {
590 CURLcode result;
591 my_md5_ctx ctx;
592
593 result = my_md5_init(&ctx);
594 if(!result) {
595 my_md5_update(&ctx, input, curlx_uztoui(len));
596 my_md5_final(outbuffer, &ctx);
597 }
598 return result;
599 }
600
Curl_MD5_init(const struct MD5_params * md5params)601 struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params)
602 {
603 struct MD5_context *ctxt;
604
605 /* Create MD5 context */
606 ctxt = malloc(sizeof(*ctxt));
607
608 if(!ctxt)
609 return ctxt;
610
611 ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize);
612
613 if(!ctxt->md5_hashctx) {
614 free(ctxt);
615 return NULL;
616 }
617
618 ctxt->md5_hash = md5params;
619
620 if((*md5params->md5_init_func)(ctxt->md5_hashctx)) {
621 free(ctxt->md5_hashctx);
622 free(ctxt);
623 return NULL;
624 }
625
626 return ctxt;
627 }
628
Curl_MD5_update(struct MD5_context * context,const unsigned char * data,unsigned int len)629 CURLcode Curl_MD5_update(struct MD5_context *context,
630 const unsigned char *data,
631 unsigned int len)
632 {
633 (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
634
635 return CURLE_OK;
636 }
637
Curl_MD5_final(struct MD5_context * context,unsigned char * result)638 CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
639 {
640 (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
641
642 free(context->md5_hashctx);
643 free(context);
644
645 return CURLE_OK;
646 }
647
648 #endif /* Using NTLM (without SSPI) || Digest */
649