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>