• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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