Annotation of embedaddon/curl/lib/md4.c, revision 1.1.1.1
1.1 misho 1: /***************************************************************************
2: * _ _ ____ _
3: * Project ___| | | | _ \| |
4: * / __| | | | |_) | |
5: * | (__| |_| | _ <| |___
6: * \___|\___/|_| \_\_____|
7: *
8: * Copyright (C) 1998 - 2020, 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.haxx.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: ***************************************************************************/
22:
23: #include "curl_setup.h"
24:
25: #if !defined(CURL_DISABLE_CRYPTO_AUTH)
26:
27: #include "curl_md4.h"
28: #include "warnless.h"
29:
30: #ifdef USE_OPENSSL
31: #include <openssl/opensslconf.h>
32: #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
33: /* OpenSSL 3.0.0 marks the MD4 functions as deprecated */
34: #define OPENSSL_NO_MD4
35: #endif
36: #endif /* USE_OPENSSL */
37:
38: #ifdef USE_MBEDTLS
39: #include <mbedtls/config.h>
40: #include <mbedtls/version.h>
41:
42: #if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
43: #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
44: #endif
45: #endif /* USE_MBEDTLS */
46:
47: #if defined(USE_GNUTLS_NETTLE)
48:
49: #include <nettle/md4.h>
50:
51: #include "curl_memory.h"
52:
53: /* The last #include file should be: */
54: #include "memdebug.h"
55:
56: typedef struct md4_ctx MD4_CTX;
57:
58: static void MD4_Init(MD4_CTX *ctx)
59: {
60: md4_init(ctx);
61: }
62:
63: static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
64: {
65: md4_update(ctx, size, data);
66: }
67:
68: static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
69: {
70: md4_digest(ctx, MD4_DIGEST_SIZE, result);
71: }
72:
73: #elif defined(USE_GNUTLS)
74:
75: #include <gcrypt.h>
76:
77: #include "curl_memory.h"
78:
79: /* The last #include file should be: */
80: #include "memdebug.h"
81:
82: typedef gcry_md_hd_t MD4_CTX;
83:
84: static void MD4_Init(MD4_CTX *ctx)
85: {
86: gcry_md_open(ctx, GCRY_MD_MD4, 0);
87: }
88:
89: static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
90: {
91: gcry_md_write(*ctx, data, size);
92: }
93:
94: static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
95: {
96: memcpy(result, gcry_md_read(*ctx, 0), MD4_DIGEST_LENGTH);
97: gcry_md_close(*ctx);
98: }
99:
100: #elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
101: /* When OpenSSL is available we use the MD4-functions from OpenSSL */
102: #include <openssl/md4.h>
103:
104: #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
105: (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
106: (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
107: (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
108:
109: #include <CommonCrypto/CommonDigest.h>
110:
111: #include "curl_memory.h"
112:
113: /* The last #include file should be: */
114: #include "memdebug.h"
115:
116: typedef CC_MD4_CTX MD4_CTX;
117:
118: static void MD4_Init(MD4_CTX *ctx)
119: {
120: (void)CC_MD4_Init(ctx);
121: }
122:
123: static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
124: {
125: (void)CC_MD4_Update(ctx, data, (CC_LONG)size);
126: }
127:
128: static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
129: {
130: (void)CC_MD4_Final(result, ctx);
131: }
132:
133: #elif defined(USE_WIN32_CRYPTO)
134:
135: #include <wincrypt.h>
136:
137: #include "curl_memory.h"
138:
139: /* The last #include file should be: */
140: #include "memdebug.h"
141:
142: typedef struct {
143: HCRYPTPROV hCryptProv;
144: HCRYPTHASH hHash;
145: } MD4_CTX;
146:
147: static void MD4_Init(MD4_CTX *ctx)
148: {
149: ctx->hCryptProv = 0;
150: ctx->hHash = 0;
151:
152: if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
153: CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
154: CryptCreateHash(ctx->hCryptProv, CALG_MD4, 0, 0, &ctx->hHash);
155: }
156: }
157:
158: static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
159: {
160: CryptHashData(ctx->hHash, (BYTE *)data, (unsigned int) size, 0);
161: }
162:
163: static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
164: {
165: unsigned long length = 0;
166:
167: CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
168: if(length == MD4_DIGEST_LENGTH)
169: CryptGetHashParam(ctx->hHash, HP_HASHVAL, result, &length, 0);
170:
171: if(ctx->hHash)
172: CryptDestroyHash(ctx->hHash);
173:
174: if(ctx->hCryptProv)
175: CryptReleaseContext(ctx->hCryptProv, 0);
176: }
177:
178: #elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
179:
180: #include <mbedtls/md4.h>
181:
182: #include "curl_memory.h"
183:
184: /* The last #include file should be: */
185: #include "memdebug.h"
186:
187: typedef struct {
188: void *data;
189: unsigned long size;
190: } MD4_CTX;
191:
192: static void MD4_Init(MD4_CTX *ctx)
193: {
194: ctx->data = NULL;
195: ctx->size = 0;
196: }
197:
198: static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
199: {
200: if(ctx->data == NULL) {
201: ctx->data = malloc(size);
202: if(ctx->data != NULL) {
203: memcpy(ctx->data, data, size);
204: ctx->size = size;
205: }
206: }
207: }
208:
209: static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
210: {
211: if(ctx->data != NULL) {
212: #if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
213: mbedtls_md4(ctx->data, ctx->size, result);
214: #else
215: (void) mbedtls_md4_ret(ctx->data, ctx->size, result);
216: #endif
217:
218: Curl_safefree(ctx->data);
219: ctx->size = 0;
220: }
221: }
222:
223: #else
224: /* When no other crypto library is available, or the crypto library doesn't
225: * support MD4, we use this code segment this implementation of it
226: *
227: * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
228: * MD4 Message-Digest Algorithm (RFC 1320).
229: *
230: * Homepage:
231: https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
232: *
233: * Author:
234: * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
235: *
236: * This software was written by Alexander Peslyak in 2001. No copyright is
237: * claimed, and the software is hereby placed in the public domain. In case
238: * this attempt to disclaim copyright and place the software in the public
239: * domain is deemed null and void, then the software is Copyright (c) 2001
240: * Alexander Peslyak and it is hereby released to the general public under the
241: * following terms:
242: *
243: * Redistribution and use in source and binary forms, with or without
244: * modification, are permitted.
245: *
246: * There's ABSOLUTELY NO WARRANTY, express or implied.
247: *
248: * (This is a heavily cut-down "BSD license".)
249: *
250: * This differs from Colin Plumb's older public domain implementation in that
251: * no exactly 32-bit integer data type is required (any 32-bit or wider
252: * unsigned integer data type will do), there's no compile-time endianness
253: * configuration, and the function prototypes match OpenSSL's. No code from
254: * Colin Plumb's implementation has been reused; this comment merely compares
255: * the properties of the two independent implementations.
256: *
257: * The primary goals of this implementation are portability and ease of use.
258: * It is meant to be fast, but not as fast as possible. Some known
259: * optimizations are not included to reduce source code size and avoid
260: * compile-time configuration.
261: */
262:
263:
264: #include <string.h>
265:
266: /* Any 32-bit or wider unsigned integer data type will do */
267: typedef unsigned int MD4_u32plus;
268:
269: typedef struct {
270: MD4_u32plus lo, hi;
271: MD4_u32plus a, b, c, d;
272: unsigned char buffer[64];
273: MD4_u32plus block[16];
274: } MD4_CTX;
275:
276: static void MD4_Init(MD4_CTX *ctx);
277: static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
278: static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
279:
280: /*
281: * The basic MD4 functions.
282: *
283: * F and G are optimized compared to their RFC 1320 definitions, with the
284: * optimization for F borrowed from Colin Plumb's MD5 implementation.
285: */
286: #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
287: #define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
288: #define H(x, y, z) ((x) ^ (y) ^ (z))
289:
290: /*
291: * The MD4 transformation for all three rounds.
292: */
293: #define STEP(f, a, b, c, d, x, s) \
294: (a) += f((b), (c), (d)) + (x); \
295: (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
296:
297: /*
298: * SET reads 4 input bytes in little-endian byte order and stores them
299: * in a properly aligned word in host byte order.
300: *
301: * The check for little-endian architectures that tolerate unaligned
302: * memory accesses is just an optimization. Nothing will break if it
303: * doesn't work.
304: */
305: #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
306: #define SET(n) \
307: (*(MD4_u32plus *)(void *)&ptr[(n) * 4])
308: #define GET(n) \
309: SET(n)
310: #else
311: #define SET(n) \
312: (ctx->block[(n)] = \
313: (MD4_u32plus)ptr[(n) * 4] | \
314: ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
315: ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
316: ((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
317: #define GET(n) \
318: (ctx->block[(n)])
319: #endif
320:
321: /*
322: * This processes one or more 64-byte data blocks, but does NOT update
323: * the bit counters. There are no alignment requirements.
324: */
325: static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
326: {
327: const unsigned char *ptr;
328: MD4_u32plus a, b, c, d;
329:
330: ptr = (const unsigned char *)data;
331:
332: a = ctx->a;
333: b = ctx->b;
334: c = ctx->c;
335: d = ctx->d;
336:
337: do {
338: MD4_u32plus saved_a, saved_b, saved_c, saved_d;
339:
340: saved_a = a;
341: saved_b = b;
342: saved_c = c;
343: saved_d = d;
344:
345: /* Round 1 */
346: STEP(F, a, b, c, d, SET(0), 3)
347: STEP(F, d, a, b, c, SET(1), 7)
348: STEP(F, c, d, a, b, SET(2), 11)
349: STEP(F, b, c, d, a, SET(3), 19)
350: STEP(F, a, b, c, d, SET(4), 3)
351: STEP(F, d, a, b, c, SET(5), 7)
352: STEP(F, c, d, a, b, SET(6), 11)
353: STEP(F, b, c, d, a, SET(7), 19)
354: STEP(F, a, b, c, d, SET(8), 3)
355: STEP(F, d, a, b, c, SET(9), 7)
356: STEP(F, c, d, a, b, SET(10), 11)
357: STEP(F, b, c, d, a, SET(11), 19)
358: STEP(F, a, b, c, d, SET(12), 3)
359: STEP(F, d, a, b, c, SET(13), 7)
360: STEP(F, c, d, a, b, SET(14), 11)
361: STEP(F, b, c, d, a, SET(15), 19)
362:
363: /* Round 2 */
364: STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3)
365: STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5)
366: STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9)
367: STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13)
368: STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3)
369: STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5)
370: STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9)
371: STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13)
372: STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3)
373: STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5)
374: STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9)
375: STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13)
376: STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3)
377: STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5)
378: STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9)
379: STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13)
380:
381: /* Round 3 */
382: STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3)
383: STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9)
384: STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11)
385: STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15)
386: STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3)
387: STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9)
388: STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11)
389: STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15)
390: STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3)
391: STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9)
392: STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11)
393: STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15)
394: STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3)
395: STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9)
396: STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11)
397: STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15)
398:
399: a += saved_a;
400: b += saved_b;
401: c += saved_c;
402: d += saved_d;
403:
404: ptr += 64;
405: } while(size -= 64);
406:
407: ctx->a = a;
408: ctx->b = b;
409: ctx->c = c;
410: ctx->d = d;
411:
412: return ptr;
413: }
414:
415: static void MD4_Init(MD4_CTX *ctx)
416: {
417: ctx->a = 0x67452301;
418: ctx->b = 0xefcdab89;
419: ctx->c = 0x98badcfe;
420: ctx->d = 0x10325476;
421:
422: ctx->lo = 0;
423: ctx->hi = 0;
424: }
425:
426: static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
427: {
428: MD4_u32plus saved_lo;
429: unsigned long used;
430:
431: saved_lo = ctx->lo;
432: ctx->lo = (saved_lo + size) & 0x1fffffff;
433: if(ctx->lo < saved_lo)
434: ctx->hi++;
435: ctx->hi += (MD4_u32plus)size >> 29;
436:
437: used = saved_lo & 0x3f;
438:
439: if(used) {
440: unsigned long available = 64 - used;
441:
442: if(size < available) {
443: memcpy(&ctx->buffer[used], data, size);
444: return;
445: }
446:
447: memcpy(&ctx->buffer[used], data, available);
448: data = (const unsigned char *)data + available;
449: size -= available;
450: body(ctx, ctx->buffer, 64);
451: }
452:
453: if(size >= 64) {
454: data = body(ctx, data, size & ~(unsigned long)0x3f);
455: size &= 0x3f;
456: }
457:
458: memcpy(ctx->buffer, data, size);
459: }
460:
461: static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
462: {
463: unsigned long used, available;
464:
465: used = ctx->lo & 0x3f;
466:
467: ctx->buffer[used++] = 0x80;
468:
469: available = 64 - used;
470:
471: if(available < 8) {
472: memset(&ctx->buffer[used], 0, available);
473: body(ctx, ctx->buffer, 64);
474: used = 0;
475: available = 64;
476: }
477:
478: memset(&ctx->buffer[used], 0, available - 8);
479:
480: ctx->lo <<= 3;
481: ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
482: ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
483: ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
484: ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff);
485: ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
486: ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
487: ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
488: ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
489:
490: body(ctx, ctx->buffer, 64);
491:
492: result[0] = curlx_ultouc((ctx->a)&0xff);
493: result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
494: result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
495: result[3] = curlx_ultouc(ctx->a >> 24);
496: result[4] = curlx_ultouc((ctx->b)&0xff);
497: result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
498: result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
499: result[7] = curlx_ultouc(ctx->b >> 24);
500: result[8] = curlx_ultouc((ctx->c)&0xff);
501: result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
502: result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
503: result[11] = curlx_ultouc(ctx->c >> 24);
504: result[12] = curlx_ultouc((ctx->d)&0xff);
505: result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
506: result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
507: result[15] = curlx_ultouc(ctx->d >> 24);
508:
509: memset(ctx, 0, sizeof(*ctx));
510: }
511:
512: #endif /* CRYPTO LIBS */
513:
514: void Curl_md4it(unsigned char *output, const unsigned char *input,
515: const size_t len)
516: {
517: MD4_CTX ctx;
518:
519: MD4_Init(&ctx);
520: MD4_Update(&ctx, input, curlx_uztoui(len));
521: MD4_Final(output, &ctx);
522: }
523:
524: #endif /* CURL_DISABLE_CRYPTO_AUTH */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>