1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 * SPDX-License-Identifier: curl
23 ***************************************************************************/
25 #include "curl_setup.h"
27 #ifndef CURL_DISABLE_CRYPTO_AUTH
29 #include <curl/curl.h>
32 #include "curl_hmac.h"
36 #include <mbedtls/version.h>
38 #if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \
39 (MBEDTLS_VERSION_NUMBER < 0x03000000)
40 #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
42 #endif /* USE_MBEDTLS */
45 #include <openssl/opensslconf.h>
46 #if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_DEPRECATED_3_0)
47 #define USE_OPENSSL_MD5
52 #include <wolfssl/options.h>
54 #define USE_WOLFSSL_MD5
58 #if defined(USE_GNUTLS)
60 #include <nettle/md5.h>
61 #include "curl_memory.h"
62 /* The last #include file should be: */
65 typedef struct md5_ctx my_md5_ctx;
67 static CURLcode my_md5_init(my_md5_ctx *ctx)
73 static void my_md5_update(my_md5_ctx *ctx,
74 const unsigned char *input,
75 unsigned int inputLen)
77 md5_update(ctx, inputLen, input);
80 static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
82 md5_digest(ctx, 16, digest);
85 #elif defined(USE_OPENSSL_MD5) || defined(USE_WOLFSSL_MD5)
87 /* When OpenSSL or wolfSSL is available, we use their MD5 functions. */
88 #if defined(USE_OPENSSL_MD5)
89 #include <openssl/md5.h>
90 #elif defined(USE_WOLFSSL_MD5)
91 #include <wolfssl/openssl/md5.h>
94 #include "curl_memory.h"
95 /* The last #include file should be: */
98 typedef MD5_CTX my_md5_ctx;
100 static CURLcode my_md5_init(my_md5_ctx *ctx)
103 return CURLE_OUT_OF_MEMORY;
108 static void my_md5_update(my_md5_ctx *ctx,
109 const unsigned char *input,
112 (void)MD5_Update(ctx, input, len);
115 static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
117 (void)MD5_Final(digest, ctx);
120 #elif defined(USE_MBEDTLS)
122 #include <mbedtls/md5.h>
124 #include "curl_memory.h"
126 /* The last #include file should be: */
127 #include "memdebug.h"
129 typedef mbedtls_md5_context my_md5_ctx;
131 static CURLcode my_md5_init(my_md5_ctx *ctx)
133 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
134 if(mbedtls_md5_starts(ctx))
135 return CURLE_OUT_OF_MEMORY;
136 #elif defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
137 if(mbedtls_md5_starts_ret(ctx))
138 return CURLE_OUT_OF_MEMORY;
140 (void)mbedtls_md5_starts(ctx);
145 static void my_md5_update(my_md5_ctx *ctx,
146 const unsigned char *data,
149 #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
150 (void) mbedtls_md5_update(ctx, data, length);
152 (void) mbedtls_md5_update_ret(ctx, data, length);
156 static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
158 #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
159 (void) mbedtls_md5_finish(ctx, digest);
161 (void) mbedtls_md5_finish_ret(ctx, digest);
165 #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
166 (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
167 defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
168 (__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
169 (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
170 (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
172 /* For Apple operating systems: CommonCrypto has the functions we need.
173 These functions are available on Tiger and later, as well as iOS 2.0
174 and later. If you're building for an older cat, well, sorry.
176 Declaring the functions as static like this seems to be a bit more
177 reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */
178 # include <CommonCrypto/CommonDigest.h>
179 # define my_md5_ctx CC_MD5_CTX
180 #include "curl_memory.h"
181 /* The last #include file should be: */
182 #include "memdebug.h"
184 static CURLcode my_md5_init(my_md5_ctx *ctx)
186 if(!CC_MD5_Init(ctx))
187 return CURLE_OUT_OF_MEMORY;
192 static void my_md5_update(my_md5_ctx *ctx,
193 const unsigned char *input,
194 unsigned int inputLen)
196 CC_MD5_Update(ctx, input, inputLen);
199 static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
201 CC_MD5_Final(digest, ctx);
204 #elif defined(USE_WIN32_CRYPTO)
206 #include <wincrypt.h>
207 #include "curl_memory.h"
208 /* The last #include file should be: */
209 #include "memdebug.h"
212 HCRYPTPROV hCryptProv;
215 typedef struct md5_ctx my_md5_ctx;
217 static CURLcode my_md5_init(my_md5_ctx *ctx)
219 if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
220 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
221 return CURLE_OUT_OF_MEMORY;
223 if(!CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash)) {
224 CryptReleaseContext(ctx->hCryptProv, 0);
225 return CURLE_OUT_OF_MEMORY;
231 static void my_md5_update(my_md5_ctx *ctx,
232 const unsigned char *input,
233 unsigned int inputLen)
235 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
238 static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
240 unsigned long length = 0;
241 CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
243 CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
245 CryptDestroyHash(ctx->hHash);
247 CryptReleaseContext(ctx->hCryptProv, 0);
252 /* When no other crypto library is available we use this code segment */
255 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
256 * MD5 Message-Digest Algorithm (RFC 1321).
259 https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
262 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
264 * This software was written by Alexander Peslyak in 2001. No copyright is
265 * claimed, and the software is hereby placed in the public domain.
266 * In case this attempt to disclaim copyright and place the software in the
267 * public domain is deemed null and void, then the software is
268 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
269 * general public under the following terms:
271 * Redistribution and use in source and binary forms, with or without
272 * modification, are permitted.
274 * There's ABSOLUTELY NO WARRANTY, express or implied.
276 * (This is a heavily cut-down "BSD license".)
278 * This differs from Colin Plumb's older public domain implementation in that
279 * no exactly 32-bit integer data type is required (any 32-bit or wider
280 * unsigned integer data type will do), there's no compile-time endianness
281 * configuration, and the function prototypes match OpenSSL's. No code from
282 * Colin Plumb's implementation has been reused; this comment merely compares
283 * the properties of the two independent implementations.
285 * The primary goals of this implementation are portability and ease of use.
286 * It is meant to be fast, but not as fast as possible. Some known
287 * optimizations are not included to reduce source code size and avoid
288 * compile-time configuration.
293 /* The last #include files should be: */
294 #include "curl_memory.h"
295 #include "memdebug.h"
297 /* Any 32-bit or wider unsigned integer data type will do */
298 typedef unsigned int MD5_u32plus;
302 MD5_u32plus a, b, c, d;
303 unsigned char buffer[64];
304 MD5_u32plus block[16];
306 typedef struct md5_ctx my_md5_ctx;
308 static CURLcode my_md5_init(my_md5_ctx *ctx);
309 static void my_md5_update(my_md5_ctx *ctx, const void *data,
311 static void my_md5_final(unsigned char *result, my_md5_ctx *ctx);
314 * The basic MD5 functions.
316 * F and G are optimized compared to their RFC 1321 definitions for
317 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
320 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
321 #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
322 #define H(x, y, z) (((x) ^ (y)) ^ (z))
323 #define H2(x, y, z) ((x) ^ ((y) ^ (z)))
324 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
327 * The MD5 transformation for all four rounds.
329 #define STEP(f, a, b, c, d, x, t, s) \
330 (a) += f((b), (c), (d)) + (x) + (t); \
331 (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
335 * SET reads 4 input bytes in little-endian byte order and stores them
336 * in a properly aligned word in host byte order.
338 * The check for little-endian architectures that tolerate unaligned
339 * memory accesses is just an optimization. Nothing will break if it
342 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
344 (*(MD5_u32plus *)(void *)&ptr[(n) * 4])
350 (MD5_u32plus)ptr[(n) * 4] | \
351 ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
352 ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
353 ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
359 * This processes one or more 64-byte data blocks, but does NOT update
360 * the bit counters. There are no alignment requirements.
362 static const void *body(my_md5_ctx *ctx, const void *data, unsigned long size)
364 const unsigned char *ptr;
365 MD5_u32plus a, b, c, d;
367 ptr = (const unsigned char *)data;
375 MD5_u32plus saved_a, saved_b, saved_c, saved_d;
383 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
384 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
385 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
386 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
387 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
388 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
389 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
390 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
391 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
392 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
393 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
394 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
395 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
396 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
397 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
398 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
401 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
402 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
403 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
404 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
405 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
406 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
407 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
408 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
409 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
410 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
411 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
412 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
413 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
414 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
415 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
416 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
419 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
420 STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
421 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
422 STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
423 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
424 STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
425 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
426 STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
427 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
428 STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
429 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
430 STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
431 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
432 STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
433 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
434 STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
437 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
438 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
439 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
440 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
441 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
442 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
443 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
444 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
445 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
446 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
447 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
448 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
449 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
450 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
451 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
452 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
470 static CURLcode my_md5_init(my_md5_ctx *ctx)
483 static void my_md5_update(my_md5_ctx *ctx, const void *data,
486 MD5_u32plus saved_lo;
490 ctx->lo = (saved_lo + size) & 0x1fffffff;
491 if(ctx->lo < saved_lo)
493 ctx->hi += (MD5_u32plus)size >> 29;
495 used = saved_lo & 0x3f;
498 unsigned long available = 64 - used;
500 if(size < available) {
501 memcpy(&ctx->buffer[used], data, size);
505 memcpy(&ctx->buffer[used], data, available);
506 data = (const unsigned char *)data + available;
508 body(ctx, ctx->buffer, 64);
512 data = body(ctx, data, size & ~(unsigned long)0x3f);
516 memcpy(ctx->buffer, data, size);
519 static void my_md5_final(unsigned char *result, my_md5_ctx *ctx)
521 unsigned long used, available;
523 used = ctx->lo & 0x3f;
525 ctx->buffer[used++] = 0x80;
527 available = 64 - used;
530 memset(&ctx->buffer[used], 0, available);
531 body(ctx, ctx->buffer, 64);
536 memset(&ctx->buffer[used], 0, available - 8);
539 ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
540 ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
541 ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
542 ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24);
543 ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
544 ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
545 ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
546 ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
548 body(ctx, ctx->buffer, 64);
550 result[0] = curlx_ultouc((ctx->a)&0xff);
551 result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
552 result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
553 result[3] = curlx_ultouc(ctx->a >> 24);
554 result[4] = curlx_ultouc((ctx->b)&0xff);
555 result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
556 result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
557 result[7] = curlx_ultouc(ctx->b >> 24);
558 result[8] = curlx_ultouc((ctx->c)&0xff);
559 result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
560 result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
561 result[11] = curlx_ultouc(ctx->c >> 24);
562 result[12] = curlx_ultouc((ctx->d)&0xff);
563 result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
564 result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
565 result[15] = curlx_ultouc(ctx->d >> 24);
567 memset(ctx, 0, sizeof(*ctx));
570 #endif /* CRYPTO LIBS */
572 const struct HMAC_params Curl_HMAC_MD5[] = {
574 /* Hash initialization function. */
575 CURLX_FUNCTION_CAST(HMAC_hinit_func, my_md5_init),
576 /* Hash update function. */
577 CURLX_FUNCTION_CAST(HMAC_hupdate_func, my_md5_update),
578 /* Hash computation end function. */
579 CURLX_FUNCTION_CAST(HMAC_hfinal_func, my_md5_final),
580 /* Size of hash context structure. */
582 /* Maximum key length. */
589 const struct MD5_params Curl_DIGEST_MD5[] = {
591 /* Digest initialization function */
592 CURLX_FUNCTION_CAST(Curl_MD5_init_func, my_md5_init),
593 /* Digest update function */
594 CURLX_FUNCTION_CAST(Curl_MD5_update_func, my_md5_update),
595 /* Digest computation end function */
596 CURLX_FUNCTION_CAST(Curl_MD5_final_func, my_md5_final),
597 /* Size of digest context struct */
606 * Returns CURLE_OK on success.
608 CURLcode Curl_md5it(unsigned char *outbuffer, const unsigned char *input,
614 result = my_md5_init(&ctx);
616 my_md5_update(&ctx, input, curlx_uztoui(len));
617 my_md5_final(outbuffer, &ctx);
622 struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params)
624 struct MD5_context *ctxt;
626 /* Create MD5 context */
627 ctxt = malloc(sizeof(*ctxt));
632 ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize);
634 if(!ctxt->md5_hashctx) {
639 ctxt->md5_hash = md5params;
641 if((*md5params->md5_init_func)(ctxt->md5_hashctx)) {
642 free(ctxt->md5_hashctx);
650 CURLcode Curl_MD5_update(struct MD5_context *context,
651 const unsigned char *data,
654 (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
659 CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
661 (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
663 free(context->md5_hashctx);
669 #endif /* CURL_DISABLE_CRYPTO_AUTH */