md4.c
Go to the documentation of this file.
00001 /*
00002  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
00003  * MD4 Message-Digest Algorithm (RFC 1320).
00004  *
00005  * Homepage:
00006  http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
00007  *
00008  * Author:
00009  * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
00010  *
00011  * This software was written by Alexander Peslyak in 2001.  No copyright is
00012  * claimed, and the software is hereby placed in the public domain.  In case
00013  * this attempt to disclaim copyright and place the software in the public
00014  * domain is deemed null and void, then the software is Copyright (c) 2001
00015  * Alexander Peslyak and it is hereby released to the general public under the
00016  * following terms:
00017  *
00018  * Redistribution and use in source and binary forms, with or without
00019  * modification, are permitted.
00020  *
00021  * There's ABSOLUTELY NO WARRANTY, express or implied.
00022  *
00023  * (This is a heavily cut-down "BSD license".)
00024  *
00025  * This differs from Colin Plumb's older public domain implementation in that
00026  * no exactly 32-bit integer data type is required (any 32-bit or wider
00027  * unsigned integer data type will do), there's no compile-time endianness
00028  * configuration, and the function prototypes match OpenSSL's.  No code from
00029  * Colin Plumb's implementation has been reused; this comment merely compares
00030  * the properties of the two independent implementations.
00031  *
00032  * The primary goals of this implementation are portability and ease of use.
00033  * It is meant to be fast, but not as fast as possible.  Some known
00034  * optimizations are not included to reduce source code size and avoid
00035  * compile-time configuration.
00036  */
00037 
00038 #include "curl_setup.h"
00039 
00040 /* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so
00041  * that we have a local implementation of it */
00042 #if defined(USE_NSS) || defined(USE_OS400CRYPTO)
00043 
00044 #include "curl_md4.h"
00045 #include "warnless.h"
00046 
00047 #ifndef HAVE_OPENSSL
00048 
00049 #include <string.h>
00050 
00051 /* Any 32-bit or wider unsigned integer data type will do */
00052 typedef unsigned int MD4_u32plus;
00053 
00054 typedef struct {
00055   MD4_u32plus lo, hi;
00056   MD4_u32plus a, b, c, d;
00057   unsigned char buffer[64];
00058   MD4_u32plus block[16];
00059 } MD4_CTX;
00060 
00061 static void MD4_Init(MD4_CTX *ctx);
00062 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
00063 static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
00064 
00065 /*
00066  * The basic MD4 functions.
00067  *
00068  * F and G are optimized compared to their RFC 1320 definitions, with the
00069  * optimization for F borrowed from Colin Plumb's MD5 implementation.
00070  */
00071 #define F(x, y, z)                      ((z) ^ ((x) & ((y) ^ (z))))
00072 #define G(x, y, z)                      (((x) & ((y) | (z))) | ((y) & (z)))
00073 #define H(x, y, z)                      ((x) ^ (y) ^ (z))
00074 
00075 /*
00076  * The MD4 transformation for all three rounds.
00077  */
00078 #define STEP(f, a, b, c, d, x, s) \
00079         (a) += f((b), (c), (d)) + (x); \
00080         (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
00081 
00082 /*
00083  * SET reads 4 input bytes in little-endian byte order and stores them
00084  * in a properly aligned word in host byte order.
00085  *
00086  * The check for little-endian architectures that tolerate unaligned
00087  * memory accesses is just an optimization.  Nothing will break if it
00088  * doesn't work.
00089  */
00090 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
00091 #define SET(n) \
00092         (*(MD4_u32plus *)&ptr[(n) * 4])
00093 #define GET(n) \
00094         SET(n)
00095 #else
00096 #define SET(n) \
00097         (ctx->block[(n)] = \
00098         (MD4_u32plus)ptr[(n) * 4] | \
00099         ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
00100         ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
00101         ((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
00102 #define GET(n) \
00103         (ctx->block[(n)])
00104 #endif
00105 
00106 /*
00107  * This processes one or more 64-byte data blocks, but does NOT update
00108  * the bit counters.  There are no alignment requirements.
00109  */
00110 static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
00111 {
00112   const unsigned char *ptr;
00113   MD4_u32plus a, b, c, d;
00114   MD4_u32plus saved_a, saved_b, saved_c, saved_d;
00115 
00116   ptr = (const unsigned char *)data;
00117 
00118   a = ctx->a;
00119   b = ctx->b;
00120   c = ctx->c;
00121   d = ctx->d;
00122 
00123   do {
00124     saved_a = a;
00125     saved_b = b;
00126     saved_c = c;
00127     saved_d = d;
00128 
00129 /* Round 1 */
00130     STEP(F, a, b, c, d, SET(0), 3)
00131       STEP(F, d, a, b, c, SET(1), 7)
00132       STEP(F, c, d, a, b, SET(2), 11)
00133       STEP(F, b, c, d, a, SET(3), 19)
00134       STEP(F, a, b, c, d, SET(4), 3)
00135       STEP(F, d, a, b, c, SET(5), 7)
00136       STEP(F, c, d, a, b, SET(6), 11)
00137       STEP(F, b, c, d, a, SET(7), 19)
00138       STEP(F, a, b, c, d, SET(8), 3)
00139       STEP(F, d, a, b, c, SET(9), 7)
00140       STEP(F, c, d, a, b, SET(10), 11)
00141       STEP(F, b, c, d, a, SET(11), 19)
00142       STEP(F, a, b, c, d, SET(12), 3)
00143       STEP(F, d, a, b, c, SET(13), 7)
00144       STEP(F, c, d, a, b, SET(14), 11)
00145       STEP(F, b, c, d, a, SET(15), 19)
00146 
00147 /* Round 2 */
00148       STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3)
00149       STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5)
00150       STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9)
00151       STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13)
00152       STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3)
00153       STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5)
00154       STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9)
00155       STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13)
00156       STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3)
00157       STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5)
00158       STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9)
00159       STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13)
00160       STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3)
00161       STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5)
00162       STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9)
00163       STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13)
00164 
00165 /* Round 3 */
00166       STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3)
00167       STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9)
00168       STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11)
00169       STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15)
00170       STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3)
00171       STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9)
00172       STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11)
00173       STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15)
00174       STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3)
00175       STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9)
00176       STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11)
00177       STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15)
00178       STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3)
00179       STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9)
00180       STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11)
00181       STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15)
00182 
00183       a += saved_a;
00184     b += saved_b;
00185     c += saved_c;
00186     d += saved_d;
00187 
00188     ptr += 64;
00189   } while(size -= 64);
00190 
00191   ctx->a = a;
00192   ctx->b = b;
00193   ctx->c = c;
00194   ctx->d = d;
00195 
00196   return ptr;
00197 }
00198 
00199 static void MD4_Init(MD4_CTX *ctx)
00200 {
00201   ctx->a = 0x67452301;
00202   ctx->b = 0xefcdab89;
00203   ctx->c = 0x98badcfe;
00204   ctx->d = 0x10325476;
00205 
00206   ctx->lo = 0;
00207   ctx->hi = 0;
00208 }
00209 
00210 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
00211 {
00212   MD4_u32plus saved_lo;
00213   unsigned long used, available;
00214 
00215   saved_lo = ctx->lo;
00216   ctx->lo = (saved_lo + size) & 0x1fffffff;
00217   if(ctx->lo < saved_lo)
00218     ctx->hi++;
00219   ctx->hi += (MD4_u32plus)size >> 29;
00220 
00221   used = saved_lo & 0x3f;
00222 
00223   if(used) {
00224     available = 64 - used;
00225 
00226     if(size < available) {
00227       memcpy(&ctx->buffer[used], data, size);
00228       return;
00229     }
00230 
00231     memcpy(&ctx->buffer[used], data, available);
00232     data = (const unsigned char *)data + available;
00233     size -= available;
00234     body(ctx, ctx->buffer, 64);
00235   }
00236 
00237   if(size >= 64) {
00238     data = body(ctx, data, size & ~(unsigned long)0x3f);
00239     size &= 0x3f;
00240   }
00241 
00242   memcpy(ctx->buffer, data, size);
00243 }
00244 
00245 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
00246 {
00247   unsigned long used, available;
00248 
00249   used = ctx->lo & 0x3f;
00250 
00251   ctx->buffer[used++] = 0x80;
00252 
00253   available = 64 - used;
00254 
00255   if(available < 8) {
00256     memset(&ctx->buffer[used], 0, available);
00257     body(ctx, ctx->buffer, 64);
00258     used = 0;
00259     available = 64;
00260   }
00261 
00262   memset(&ctx->buffer[used], 0, available - 8);
00263 
00264   ctx->lo <<= 3;
00265   ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
00266   ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
00267   ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
00268   ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff);
00269   ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
00270   ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
00271   ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
00272   ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
00273 
00274   body(ctx, ctx->buffer, 64);
00275 
00276   result[0] = curlx_ultouc((ctx->a)&0xff);
00277   result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
00278   result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
00279   result[3] = curlx_ultouc(ctx->a >> 24);
00280   result[4] = curlx_ultouc((ctx->b)&0xff);
00281   result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
00282   result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
00283   result[7] = curlx_ultouc(ctx->b >> 24);
00284   result[8] = curlx_ultouc((ctx->c)&0xff);
00285   result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
00286   result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
00287   result[11] = curlx_ultouc(ctx->c >> 24);
00288   result[12] = curlx_ultouc((ctx->d)&0xff);
00289   result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
00290   result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
00291   result[15] = curlx_ultouc(ctx->d >> 24);
00292 
00293   memset(ctx, 0, sizeof(*ctx));
00294 }
00295 
00296 #endif
00297 
00298 void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
00299 {
00300   MD4_CTX ctx;
00301   MD4_Init(&ctx);
00302   MD4_Update(&ctx, input, curlx_uztoui(len));
00303   MD4_Final(output, &ctx);
00304 }
00305 #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:05