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 #ifndef CURL_DISABLE_CRYPTO_AUTH
28
29 #include <string.h>
30 #include <curl/curl.h>
31
32 #include "curl_md5.h"
33 #include "curl_hmac.h"
34 #include "warnless.h"
35
36 #ifdef USE_MBEDTLS
37 #include <mbedtls/version.h>
38
39 #if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \
40 (MBEDTLS_VERSION_NUMBER < 0x03000000)
41 #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
42 #endif
43 #endif /* USE_MBEDTLS */
44
45 #ifdef USE_OPENSSL
46 #include <openssl/opensslconf.h>
47 #if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_DEPRECATED_3_0)
48 #define USE_OPENSSL_MD5
49 #endif
50 #endif
51
52 #ifdef USE_WOLFSSL
53 #include <wolfssl/options.h>
54 #ifndef NO_MD5
55 #define USE_WOLFSSL_MD5
56 #endif
57 #endif
58
59 #if defined(USE_GNUTLS)
60 #include <nettle/md5.h>
61 #elif defined(USE_OPENSSL_MD5)
62 #include <openssl/md5.h>
63 #elif defined(USE_WOLFSSL_MD5)
64 #include <wolfssl/openssl/md5.h>
65 #elif defined(USE_MBEDTLS)
66 #include <mbedtls/md5.h>
67 #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
68 (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
69 defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
70 (__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
71 (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
72 (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
73 #define AN_APPLE_OS
74 #include <CommonCrypto/CommonDigest.h>
75 #elif defined(USE_WIN32_CRYPTO)
76 #include <wincrypt.h>
77 #endif
78
79 /* The last 3 #include files should be in this order */
80 #include "curl_printf.h"
81 #include "curl_memory.h"
82 #include "memdebug.h"
83
84 #if defined(USE_GNUTLS)
85
86 typedef struct md5_ctx my_md5_ctx;
87
my_md5_init(my_md5_ctx * ctx)88 static CURLcode my_md5_init(my_md5_ctx *ctx)
89 {
90 md5_init(ctx);
91 return CURLE_OK;
92 }
93
my_md5_update(my_md5_ctx * ctx,const unsigned char * input,unsigned int inputLen)94 static void my_md5_update(my_md5_ctx *ctx,
95 const unsigned char *input,
96 unsigned int inputLen)
97 {
98 md5_update(ctx, inputLen, input);
99 }
100
my_md5_final(unsigned char * digest,my_md5_ctx * ctx)101 static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
102 {
103 md5_digest(ctx, 16, digest);
104 }
105
106 #elif defined(USE_OPENSSL_MD5) || defined(USE_WOLFSSL_MD5)
107
108 typedef MD5_CTX my_md5_ctx;
109
my_md5_init(my_md5_ctx * ctx)110 static CURLcode my_md5_init(my_md5_ctx *ctx)
111 {
112 if(!MD5_Init(ctx))
113 return CURLE_OUT_OF_MEMORY;
114
115 return CURLE_OK;
116 }
117
my_md5_update(my_md5_ctx * ctx,const unsigned char * input,unsigned int len)118 static void my_md5_update(my_md5_ctx *ctx,
119 const unsigned char *input,
120 unsigned int len)
121 {
122 (void)MD5_Update(ctx, input, len);
123 }
124
my_md5_final(unsigned char * digest,my_md5_ctx * ctx)125 static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
126 {
127 (void)MD5_Final(digest, ctx);
128 }
129
130 #elif defined(USE_MBEDTLS)
131
132 typedef mbedtls_md5_context my_md5_ctx;
133
my_md5_init(my_md5_ctx * ctx)134 static CURLcode my_md5_init(my_md5_ctx *ctx)
135 {
136 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
137 if(mbedtls_md5_starts(ctx))
138 return CURLE_OUT_OF_MEMORY;
139 #elif defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
140 if(mbedtls_md5_starts_ret(ctx))
141 return CURLE_OUT_OF_MEMORY;
142 #else
143 (void)mbedtls_md5_starts(ctx);
144 #endif
145 return CURLE_OK;
146 }
147
my_md5_update(my_md5_ctx * ctx,const unsigned char * data,unsigned int length)148 static void my_md5_update(my_md5_ctx *ctx,
149 const unsigned char *data,
150 unsigned int length)
151 {
152 #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
153 (void) mbedtls_md5_update(ctx, data, length);
154 #else
155 (void) mbedtls_md5_update_ret(ctx, data, length);
156 #endif
157 }
158
my_md5_final(unsigned char * digest,my_md5_ctx * ctx)159 static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
160 {
161 #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
162 (void) mbedtls_md5_finish(ctx, digest);
163 #else
164 (void) mbedtls_md5_finish_ret(ctx, digest);
165 #endif
166 }
167
168 #elif defined(AN_APPLE_OS)
169
170 /* For Apple operating systems: CommonCrypto has the functions we need.
171 These functions are available on Tiger and later, as well as iOS 2.0
172 and later. If you're building for an older cat, well, sorry.
173
174 Declaring the functions as static like this seems to be a bit more
175 reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */
176 # define my_md5_ctx CC_MD5_CTX
177
my_md5_init(my_md5_ctx * ctx)178 static CURLcode my_md5_init(my_md5_ctx *ctx)
179 {
180 if(!CC_MD5_Init(ctx))
181 return CURLE_OUT_OF_MEMORY;
182
183 return CURLE_OK;
184 }
185
my_md5_update(my_md5_ctx * ctx,const unsigned char * input,unsigned int inputLen)186 static void my_md5_update(my_md5_ctx *ctx,
187 const unsigned char *input,
188 unsigned int inputLen)
189 {
190 CC_MD5_Update(ctx, input, inputLen);
191 }
192
my_md5_final(unsigned char * digest,my_md5_ctx * ctx)193 static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
194 {
195 CC_MD5_Final(digest, ctx);
196 }
197
198 #elif defined(USE_WIN32_CRYPTO)
199
200 struct md5_ctx {
201 HCRYPTPROV hCryptProv;
202 HCRYPTHASH hHash;
203 };
204 typedef struct md5_ctx my_md5_ctx;
205
my_md5_init(my_md5_ctx * ctx)206 static CURLcode my_md5_init(my_md5_ctx *ctx)
207 {
208 if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
209 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
210 return CURLE_OUT_OF_MEMORY;
211
212 if(!CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash)) {
213 CryptReleaseContext(ctx->hCryptProv, 0);
214 return CURLE_OUT_OF_MEMORY;
215 }
216
217 return CURLE_OK;
218 }
219
my_md5_update(my_md5_ctx * ctx,const unsigned char * input,unsigned int inputLen)220 static void my_md5_update(my_md5_ctx *ctx,
221 const unsigned char *input,
222 unsigned int inputLen)
223 {
224 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
225 }
226
my_md5_final(unsigned char * digest,my_md5_ctx * ctx)227 static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
228 {
229 unsigned long length = 0;
230 CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
231 if(length == 16)
232 CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
233 if(ctx->hHash)
234 CryptDestroyHash(ctx->hHash);
235 if(ctx->hCryptProv)
236 CryptReleaseContext(ctx->hCryptProv, 0);
237 }
238
239 #else
240
241 /* When no other crypto library is available we use this code segment */
242
243 /*
244 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
245 * MD5 Message-Digest Algorithm (RFC 1321).
246 *
247 * Homepage:
248 https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
249 *
250 * Author:
251 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
252 *
253 * This software was written by Alexander Peslyak in 2001. No copyright is
254 * claimed, and the software is hereby placed in the public domain.
255 * In case this attempt to disclaim copyright and place the software in the
256 * public domain is deemed null and void, then the software is
257 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
258 * general public under the following terms:
259 *
260 * Redistribution and use in source and binary forms, with or without
261 * modification, are permitted.
262 *
263 * There's ABSOLUTELY NO WARRANTY, express or implied.
264 *
265 * (This is a heavily cut-down "BSD license".)
266 *
267 * This differs from Colin Plumb's older public domain implementation in that
268 * no exactly 32-bit integer data type is required (any 32-bit or wider
269 * unsigned integer data type will do), there's no compile-time endianness
270 * configuration, and the function prototypes match OpenSSL's. No code from
271 * Colin Plumb's implementation has been reused; this comment merely compares
272 * the properties of the two independent implementations.
273 *
274 * The primary goals of this implementation are portability and ease of use.
275 * It is meant to be fast, but not as fast as possible. Some known
276 * optimizations are not included to reduce source code size and avoid
277 * compile-time configuration.
278 */
279
280 /* Any 32-bit or wider unsigned integer data type will do */
281 typedef unsigned int MD5_u32plus;
282
283 struct md5_ctx {
284 MD5_u32plus lo, hi;
285 MD5_u32plus a, b, c, d;
286 unsigned char buffer[64];
287 MD5_u32plus block[16];
288 };
289 typedef struct md5_ctx my_md5_ctx;
290
291 static CURLcode my_md5_init(my_md5_ctx *ctx);
292 static void my_md5_update(my_md5_ctx *ctx, const void *data,
293 unsigned long size);
294 static void my_md5_final(unsigned char *result, my_md5_ctx *ctx);
295
296 /*
297 * The basic MD5 functions.
298 *
299 * F and G are optimized compared to their RFC 1321 definitions for
300 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
301 * implementation.
302 */
303 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
304 #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
305 #define H(x, y, z) (((x) ^ (y)) ^ (z))
306 #define H2(x, y, z) ((x) ^ ((y) ^ (z)))
307 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
308
309 /*
310 * The MD5 transformation for all four rounds.
311 */
312 #define STEP(f, a, b, c, d, x, t, s) \
313 (a) += f((b), (c), (d)) + (x) + (t); \
314 (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
315 (a) += (b);
316
317 /*
318 * SET reads 4 input bytes in little-endian byte order and stores them
319 * in a properly aligned word in host byte order.
320 *
321 * The check for little-endian architectures that tolerate unaligned
322 * memory accesses is just an optimization. Nothing will break if it
323 * doesn't work.
324 */
325 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
326 #define SET(n) \
327 (*(MD5_u32plus *)(void *)&ptr[(n) * 4])
328 #define GET(n) \
329 SET(n)
330 #else
331 #define SET(n) \
332 (ctx->block[(n)] = \
333 (MD5_u32plus)ptr[(n) * 4] | \
334 ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
335 ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
336 ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
337 #define GET(n) \
338 (ctx->block[(n)])
339 #endif
340
341 /*
342 * This processes one or more 64-byte data blocks, but does NOT update
343 * the bit counters. There are no alignment requirements.
344 */
body(my_md5_ctx * ctx,const void * data,unsigned long size)345 static const void *body(my_md5_ctx *ctx, const void *data, unsigned long size)
346 {
347 const unsigned char *ptr;
348 MD5_u32plus a, b, c, d;
349
350 ptr = (const unsigned char *)data;
351
352 a = ctx->a;
353 b = ctx->b;
354 c = ctx->c;
355 d = ctx->d;
356
357 do {
358 MD5_u32plus saved_a, saved_b, saved_c, saved_d;
359
360 saved_a = a;
361 saved_b = b;
362 saved_c = c;
363 saved_d = d;
364
365 /* Round 1 */
366 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
367 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
368 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
369 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
370 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
371 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
372 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
373 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
374 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
375 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
376 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
377 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
378 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
379 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
380 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
381 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
382
383 /* Round 2 */
384 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
385 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
386 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
387 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
388 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
389 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
390 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
391 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
392 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
393 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
394 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
395 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
396 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
397 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
398 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
399 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
400
401 /* Round 3 */
402 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
403 STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
404 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
405 STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
406 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
407 STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
408 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
409 STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
410 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
411 STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
412 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
413 STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
414 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
415 STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
416 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
417 STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
418
419 /* Round 4 */
420 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
421 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
422 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
423 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
424 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
425 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
426 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
427 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
428 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
429 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
430 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
431 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
432 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
433 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
434 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
435 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
436
437 a += saved_a;
438 b += saved_b;
439 c += saved_c;
440 d += saved_d;
441
442 ptr += 64;
443 } while(size -= 64);
444
445 ctx->a = a;
446 ctx->b = b;
447 ctx->c = c;
448 ctx->d = d;
449
450 return ptr;
451 }
452
my_md5_init(my_md5_ctx * ctx)453 static CURLcode my_md5_init(my_md5_ctx *ctx)
454 {
455 ctx->a = 0x67452301;
456 ctx->b = 0xefcdab89;
457 ctx->c = 0x98badcfe;
458 ctx->d = 0x10325476;
459
460 ctx->lo = 0;
461 ctx->hi = 0;
462
463 return CURLE_OK;
464 }
465
my_md5_update(my_md5_ctx * ctx,const void * data,unsigned long size)466 static void my_md5_update(my_md5_ctx *ctx, const void *data,
467 unsigned long size)
468 {
469 MD5_u32plus saved_lo;
470 unsigned long used;
471
472 saved_lo = ctx->lo;
473 ctx->lo = (saved_lo + size) & 0x1fffffff;
474 if(ctx->lo < saved_lo)
475 ctx->hi++;
476 ctx->hi += (MD5_u32plus)size >> 29;
477
478 used = saved_lo & 0x3f;
479
480 if(used) {
481 unsigned long available = 64 - used;
482
483 if(size < available) {
484 memcpy(&ctx->buffer[used], data, size);
485 return;
486 }
487
488 memcpy(&ctx->buffer[used], data, available);
489 data = (const unsigned char *)data + available;
490 size -= available;
491 body(ctx, ctx->buffer, 64);
492 }
493
494 if(size >= 64) {
495 data = body(ctx, data, size & ~(unsigned long)0x3f);
496 size &= 0x3f;
497 }
498
499 memcpy(ctx->buffer, data, size);
500 }
501
my_md5_final(unsigned char * result,my_md5_ctx * ctx)502 static void my_md5_final(unsigned char *result, my_md5_ctx *ctx)
503 {
504 unsigned long used, available;
505
506 used = ctx->lo & 0x3f;
507
508 ctx->buffer[used++] = 0x80;
509
510 available = 64 - used;
511
512 if(available < 8) {
513 memset(&ctx->buffer[used], 0, available);
514 body(ctx, ctx->buffer, 64);
515 used = 0;
516 available = 64;
517 }
518
519 memset(&ctx->buffer[used], 0, available - 8);
520
521 ctx->lo <<= 3;
522 ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
523 ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
524 ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
525 ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24);
526 ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
527 ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
528 ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
529 ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
530
531 body(ctx, ctx->buffer, 64);
532
533 result[0] = curlx_ultouc((ctx->a)&0xff);
534 result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
535 result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
536 result[3] = curlx_ultouc(ctx->a >> 24);
537 result[4] = curlx_ultouc((ctx->b)&0xff);
538 result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
539 result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
540 result[7] = curlx_ultouc(ctx->b >> 24);
541 result[8] = curlx_ultouc((ctx->c)&0xff);
542 result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
543 result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
544 result[11] = curlx_ultouc(ctx->c >> 24);
545 result[12] = curlx_ultouc((ctx->d)&0xff);
546 result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
547 result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
548 result[15] = curlx_ultouc(ctx->d >> 24);
549
550 memset(ctx, 0, sizeof(*ctx));
551 }
552
553 #endif /* CRYPTO LIBS */
554
555 const struct HMAC_params Curl_HMAC_MD5[] = {
556 {
557 /* Hash initialization function. */
558 CURLX_FUNCTION_CAST(HMAC_hinit_func, my_md5_init),
559 /* Hash update function. */
560 CURLX_FUNCTION_CAST(HMAC_hupdate_func, my_md5_update),
561 /* Hash computation end function. */
562 CURLX_FUNCTION_CAST(HMAC_hfinal_func, my_md5_final),
563 /* Size of hash context structure. */
564 sizeof(my_md5_ctx),
565 /* Maximum key length. */
566 64,
567 /* Result size. */
568 16
569 }
570 };
571
572 const struct MD5_params Curl_DIGEST_MD5[] = {
573 {
574 /* Digest initialization function */
575 CURLX_FUNCTION_CAST(Curl_MD5_init_func, my_md5_init),
576 /* Digest update function */
577 CURLX_FUNCTION_CAST(Curl_MD5_update_func, my_md5_update),
578 /* Digest computation end function */
579 CURLX_FUNCTION_CAST(Curl_MD5_final_func, my_md5_final),
580 /* Size of digest context struct */
581 sizeof(my_md5_ctx),
582 /* Result size */
583 16
584 }
585 };
586
587 /*
588 * @unittest: 1601
589 * Returns CURLE_OK on success.
590 */
Curl_md5it(unsigned char * outbuffer,const unsigned char * input,const size_t len)591 CURLcode Curl_md5it(unsigned char *outbuffer, const unsigned char *input,
592 const size_t len)
593 {
594 CURLcode result;
595 my_md5_ctx ctx;
596
597 result = my_md5_init(&ctx);
598 if(!result) {
599 my_md5_update(&ctx, input, curlx_uztoui(len));
600 my_md5_final(outbuffer, &ctx);
601 }
602 return result;
603 }
604
Curl_MD5_init(const struct MD5_params * md5params)605 struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params)
606 {
607 struct MD5_context *ctxt;
608
609 /* Create MD5 context */
610 ctxt = malloc(sizeof(*ctxt));
611
612 if(!ctxt)
613 return ctxt;
614
615 ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize);
616
617 if(!ctxt->md5_hashctx) {
618 free(ctxt);
619 return NULL;
620 }
621
622 ctxt->md5_hash = md5params;
623
624 if((*md5params->md5_init_func)(ctxt->md5_hashctx)) {
625 free(ctxt->md5_hashctx);
626 free(ctxt);
627 return NULL;
628 }
629
630 return ctxt;
631 }
632
Curl_MD5_update(struct MD5_context * context,const unsigned char * data,unsigned int len)633 CURLcode Curl_MD5_update(struct MD5_context *context,
634 const unsigned char *data,
635 unsigned int len)
636 {
637 (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
638
639 return CURLE_OK;
640 }
641
Curl_MD5_final(struct MD5_context * context,unsigned char * result)642 CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
643 {
644 (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
645
646 free(context->md5_hashctx);
647 free(context);
648
649 return CURLE_OK;
650 }
651
652 #endif /* CURL_DISABLE_CRYPTO_AUTH */
653