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 89typedef struct md5_ctx my_md5_ctx; 90 91static CURLcode my_md5_init(my_md5_ctx *ctx) 92{ 93 md5_init(ctx); 94 return CURLE_OK; 95} 96 97static 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 104static 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 111typedef MD5_CTX my_md5_ctx; 112 113static 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 121static 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 128static 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 135typedef mbedtls_md5_context my_md5_ctx; 136 137static 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 151static 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 162static 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 181static 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 189static 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 196static 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 203struct md5_ctx { 204 HCRYPTPROV hCryptProv; 205 HCRYPTHASH hHash; 206}; 207typedef struct md5_ctx my_md5_ctx; 208 209static 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 224static 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 231static 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 */ 285typedef unsigned int MD5_u32plus; 286 287struct 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}; 293typedef struct md5_ctx my_md5_ctx; 294 295static CURLcode my_md5_init(my_md5_ctx *ctx); 296static void my_md5_update(my_md5_ctx *ctx, const void *data, 297 unsigned long size); 298static 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 */ 349static 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 457static 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 470static 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 506static 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 559const 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 576const 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 */ 595CURLcode 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 609struct 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 637CURLcode 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 646CURLcode 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