|  | /* | 
|  | * Copyright (C) 2001 Nikos Mavroyanopoulos | 
|  | * Copyright (C) 2004 Hans Leidekker | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * This code implements the MD4 message-digest algorithm. | 
|  | * It is based on code in the public domain written by Colin | 
|  | * Plumb in 1993. The algorithm is due to Ron Rivest. | 
|  | * | 
|  | * Equivalent code is available from RSA Data Security, Inc. | 
|  | * This code has been tested against that, and is equivalent, | 
|  | * except that you don't need to include two pages of legalese | 
|  | * with every copy. | 
|  | * | 
|  | * To compute the message digest of a chunk of bytes, declare an | 
|  | * MD4_CTX structure, pass it to MD4Init, call MD4Update as | 
|  | * needed on buffers full of bytes, and then call MD4Final, which | 
|  | * will fill a supplied 16-byte array with the digest. | 
|  | */ | 
|  |  | 
|  | #include <stdarg.h> | 
|  |  | 
|  | #include "windef.h" | 
|  |  | 
|  | typedef struct | 
|  | { | 
|  | unsigned int buf[4]; | 
|  | unsigned int i[2]; | 
|  | unsigned char in[64]; | 
|  | unsigned char digest[16]; | 
|  | } MD4_CTX; | 
|  |  | 
|  | static void MD4Transform( unsigned int buf[4], unsigned int const in[16] ); | 
|  |  | 
|  | /* | 
|  | * Note: this code is harmless on little-endian machines. | 
|  | */ | 
|  | static void byteReverse( unsigned char *buf, unsigned longs ) | 
|  | { | 
|  | unsigned int t; | 
|  |  | 
|  | do { | 
|  | t = (unsigned int)((unsigned)buf[3] << 8 | buf[2]) << 16 | | 
|  | ((unsigned)buf[1] << 8 | buf[0]); | 
|  | *(unsigned int *)buf = t; | 
|  | buf += 4; | 
|  | } while (--longs); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Start MD4 accumulation.  Set bit count to 0 and buffer to mysterious | 
|  | * initialization constants. | 
|  | */ | 
|  | VOID WINAPI MD4Init( MD4_CTX *ctx ) | 
|  | { | 
|  | ctx->buf[0] = 0x67452301; | 
|  | ctx->buf[1] = 0xefcdab89; | 
|  | ctx->buf[2] = 0x98badcfe; | 
|  | ctx->buf[3] = 0x10325476; | 
|  |  | 
|  | ctx->i[0] = ctx->i[1] = 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Update context to reflect the concatenation of another buffer full | 
|  | * of bytes. | 
|  | */ | 
|  | VOID WINAPI MD4Update( MD4_CTX *ctx, const unsigned char *buf, unsigned int len ) | 
|  | { | 
|  | register unsigned int t; | 
|  |  | 
|  | /* Update bitcount */ | 
|  | t = ctx->i[0]; | 
|  |  | 
|  | if ((ctx->i[0] = t + ((unsigned int)len << 3)) < t) | 
|  | ctx->i[1]++;        /* Carry from low to high */ | 
|  |  | 
|  | ctx->i[1] += len >> 29; | 
|  | t = (t >> 3) & 0x3f; | 
|  |  | 
|  | /* Handle any leading odd-sized chunks */ | 
|  | if (t) | 
|  | { | 
|  | unsigned char *p = (unsigned char *)ctx->in + t; | 
|  | t = 64 - t; | 
|  |  | 
|  | if (len < t) | 
|  | { | 
|  | memcpy( p, buf, len ); | 
|  | return; | 
|  | } | 
|  |  | 
|  | memcpy( p, buf, t ); | 
|  | byteReverse( ctx->in, 16 ); | 
|  |  | 
|  | MD4Transform( ctx->buf, (unsigned int *)ctx->in ); | 
|  |  | 
|  | buf += t; | 
|  | len -= t; | 
|  | } | 
|  |  | 
|  | /* Process data in 64-byte chunks */ | 
|  | while (len >= 64) | 
|  | { | 
|  | memcpy( ctx->in, buf, 64 ); | 
|  | byteReverse( ctx->in, 16 ); | 
|  |  | 
|  | MD4Transform( ctx->buf, (unsigned int *)ctx->in ); | 
|  |  | 
|  | buf += 64; | 
|  | len -= 64; | 
|  | } | 
|  |  | 
|  | /* Handle any remaining bytes of data. */ | 
|  | memcpy( ctx->in, buf, len ); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Final wrapup - pad to 64-byte boundary with the bit pattern | 
|  | * 1 0* (64-bit count of bits processed, MSB-first) | 
|  | */ | 
|  | VOID WINAPI MD4Final( MD4_CTX *ctx ) | 
|  | { | 
|  | unsigned int count; | 
|  | unsigned char *p; | 
|  |  | 
|  | /* Compute number of bytes mod 64 */ | 
|  | count = (ctx->i[0] >> 3) & 0x3F; | 
|  |  | 
|  | /* Set the first char of padding to 0x80.  This is safe since there is | 
|  | always at least one byte free */ | 
|  | p = ctx->in + count; | 
|  | *p++ = 0x80; | 
|  |  | 
|  | /* Bytes of padding needed to make 64 bytes */ | 
|  | count = 64 - 1 - count; | 
|  |  | 
|  | /* Pad out to 56 mod 64 */ | 
|  | if (count < 8) | 
|  | { | 
|  | /* Two lots of padding:  Pad the first block to 64 bytes */ | 
|  | memset( p, 0, count ); | 
|  | byteReverse( ctx->in, 16 ); | 
|  | MD4Transform( ctx->buf, (unsigned int *)ctx->in ); | 
|  |  | 
|  | /* Now fill the next block with 56 bytes */ | 
|  | memset( ctx->in, 0, 56 ); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Pad block to 56 bytes */ | 
|  | memset( p, 0, count - 8 ); | 
|  | } | 
|  |  | 
|  | byteReverse( ctx->in, 14 ); | 
|  |  | 
|  | /* Append length in bits and transform */ | 
|  | ((unsigned int *)ctx->in)[14] = ctx->i[0]; | 
|  | ((unsigned int *)ctx->in)[15] = ctx->i[1]; | 
|  |  | 
|  | MD4Transform( ctx->buf, (unsigned int *)ctx->in ); | 
|  | byteReverse( (unsigned char *)ctx->buf, 4 ); | 
|  | memcpy( ctx->digest, ctx->buf, 16 ); | 
|  | } | 
|  |  | 
|  | /* The three core functions */ | 
|  |  | 
|  | #define rotl32(x,n)  (((x) << ((unsigned int)(n))) | ((x) >> (32 - (unsigned int)(n)))) | 
|  |  | 
|  | #define F( x, y, z ) (((x) & (y)) | ((~x) & (z))) | 
|  | #define G( x, y, z ) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) | 
|  | #define H( x, y, z ) ((x) ^ (y) ^ (z)) | 
|  |  | 
|  | #define FF( a, b, c, d, x, s ) { \ | 
|  | (a) += F( (b), (c), (d) ) + (x); \ | 
|  | (a) = rotl32( (a), (s) ); \ | 
|  | } | 
|  | #define GG( a, b, c, d, x, s ) { \ | 
|  | (a) += G( (b), (c), (d) ) + (x) + (unsigned int)0x5a827999; \ | 
|  | (a) = rotl32( (a), (s) ); \ | 
|  | } | 
|  | #define HH( a, b, c, d, x, s ) { \ | 
|  | (a) += H( (b), (c), (d) ) + (x) + (unsigned int)0x6ed9eba1; \ | 
|  | (a) = rotl32( (a), (s) ); \ | 
|  | } | 
|  |  | 
|  | /* | 
|  | * The core of the MD4 algorithm | 
|  | */ | 
|  | static void MD4Transform( unsigned int buf[4], const unsigned int in[16] ) | 
|  | { | 
|  | register unsigned int a, b, c, d; | 
|  |  | 
|  | a = buf[0]; | 
|  | b = buf[1]; | 
|  | c = buf[2]; | 
|  | d = buf[3]; | 
|  |  | 
|  | FF( a, b, c, d, in[0], 3 ); | 
|  | FF( d, a, b, c, in[1], 7 ); | 
|  | FF( c, d, a, b, in[2], 11 ); | 
|  | FF( b, c, d, a, in[3], 19 ); | 
|  | FF( a, b, c, d, in[4], 3 ); | 
|  | FF( d, a, b, c, in[5], 7 ); | 
|  | FF( c, d, a, b, in[6], 11 ); | 
|  | FF( b, c, d, a, in[7], 19 ); | 
|  | FF( a, b, c, d, in[8], 3 ); | 
|  | FF( d, a, b, c, in[9], 7 ); | 
|  | FF( c, d, a, b, in[10], 11 ); | 
|  | FF( b, c, d, a, in[11], 19 ); | 
|  | FF( a, b, c, d, in[12], 3 ); | 
|  | FF( d, a, b, c, in[13], 7 ); | 
|  | FF( c, d, a, b, in[14], 11 ); | 
|  | FF( b, c, d, a, in[15], 19 ); | 
|  |  | 
|  | GG( a, b, c, d, in[0], 3 ); | 
|  | GG( d, a, b, c, in[4], 5 ); | 
|  | GG( c, d, a, b, in[8], 9 ); | 
|  | GG( b, c, d, a, in[12], 13 ); | 
|  | GG( a, b, c, d, in[1], 3 ); | 
|  | GG( d, a, b, c, in[5], 5 ); | 
|  | GG( c, d, a, b, in[9], 9 ); | 
|  | GG( b, c, d, a, in[13], 13 ); | 
|  | GG( a, b, c, d, in[2], 3 ); | 
|  | GG( d, a, b, c, in[6], 5 ); | 
|  | GG( c, d, a, b, in[10], 9 ); | 
|  | GG( b, c, d, a, in[14], 13 ); | 
|  | GG( a, b, c, d, in[3], 3 ); | 
|  | GG( d, a, b, c, in[7], 5 ); | 
|  | GG( c, d, a, b, in[11], 9 ); | 
|  | GG( b, c, d, a, in[15], 13 ); | 
|  |  | 
|  | HH( a, b, c, d, in[0], 3 ); | 
|  | HH( d, a, b, c, in[8], 9 ); | 
|  | HH( c, d, a, b, in[4], 11 ); | 
|  | HH( b, c, d, a, in[12], 15 ); | 
|  | HH( a, b, c, d, in[2], 3 ); | 
|  | HH( d, a, b, c, in[10], 9 ); | 
|  | HH( c, d, a, b, in[6], 11 ); | 
|  | HH( b, c, d, a, in[14], 15 ); | 
|  | HH( a, b, c, d, in[1], 3 ); | 
|  | HH( d, a, b, c, in[9], 9 ); | 
|  | HH( c, d, a, b, in[5], 11 ); | 
|  | HH( b, c, d, a, in[13], 15 ); | 
|  | HH( a, b, c, d, in[3], 3 ); | 
|  | HH( d, a, b, c, in[11], 9 ); | 
|  | HH( c, d, a, b, in[7], 11 ); | 
|  | HH( b, c, d, a, in[15], 15 ); | 
|  |  | 
|  | buf[0] += a; | 
|  | buf[1] += b; | 
|  | buf[2] += c; | 
|  | buf[3] += d; | 
|  | } |