* md4.c -- Implementation of MD4 Message Digest Algorithm
* Updated: 2/16/90 by Ronald L. Rivest
* Portability nits fixed and reformatted - 2/12/91 Phil Karn
* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
* License to copy and use this software is granted provided that it
* is identified as the "RSA Data Security, Inc. MD5 Message-Digest
* Algorithm" in all material mentioning or referencing this software
* License is also granted to make and use derivative works provided
* that such works are identified as "derived from the RSA Data
* Security, Inc. MD5 Message-Digest Algorithm" in all material
* mentioning or referencing the derived work.
* RSA Data Security, Inc. makes no representations concerning either
* the merchantability of this software or the suitability of this
* software for any particular purpose. It is provided "as is"
* without express or implied warranty of any kind.
* These notices must be retained in any copies of any part of this
* documentation and/or software.
* -- Include md4.h in your program
* -- Declare an MDstruct MD to hold the state of the digest computation.
* -- Initialize MD using MDbegin(&MD)
* -- For each full block (64 bytes) X you wish to process, call
* (512 is the number of bits in a full block.)
* -- For the last block (less than 64 bytes) you wish to process,
* where n is the number of bits in the partial block. A partial
* block terminates the computation, so every MD computation should
* terminate by processing a partial block, even if it has n = 0.
* -- The message digest is available in MD.buffer[0] ... MD.buffer[3].
* (Least-significant byte of each word should be output first.)
* -- You can print out the digest using MDprint(&MD)
* This implementation assumes that longs are 32-bit quantities.
* If the machine stores the least-significant byte of an long in the
* least-addressed byte (eg., VAX and 8086), then LOWBYTEFIRST should be
* set to TRUE. Otherwise (eg., SUNS), LOWBYTEFIRST should be set to
* FALSE. Note that on machines with LOWBYTEFIRST FALSE the routine
* MDupdate modifies has a side-effect on its input array (the order of bytes
* in each word are reversed). If this is undesired a call to MDreverse(X) can
* reverse the bytes of X back into order after each call to MDupdate.
#if (defined(__MSDOS__) || defined(MPU8086) || defined(MPU8080) \
|| defined(vax) || defined (MIPSEL))
#define LOWBYTEFIRST TRUE /* Low order bytes are first in memory */
#else /* Almost all other machines are big-endian */
#define LOWBYTEFIRST FALSE
/* Compile-time includes */
/* Compile-time declarations of MD4 ``magic constants'' */
#define I0 0x67452301 /* Initial values for MD buffer */
#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
* (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
#define fs1 3 /* round 1 shift amounts */
#define gs1 3 /* round 2 shift amounts */
#define hs1 3 /* round 3 shift amounts */
/* Compile-time macro declarations for MD4.
* Note: The ``rot'' operator uses the variable ``tmp''.
* It assumes tmp is declared as unsigned long, so that the >>
* operator will shift in zeros rather than extending the sign bit.
#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
void MDreverse
__ARGS((unsigned long *X
));
* Print message digest buffer MDp as 32 hexadecimal digits.
* Order is from low-order byte of buffer[0] to high-order byte of buffer[3].
* Each byte is printed with high-order hexadecimal digit first.
* This is a user-callable routine.
printf("%02lx",(MDp
->buffer
[i
]>>j
) & 0xFF);
* Initialize message digest buffer MDp.
* This is a user-callable routine.
* Reverse the byte-ordering of every long in X.
* Assumes X is an array of 16 longs.
* The macro revx reverses the byte-ordering of the next word of X.
#define revx { t = (*X << 16) | (*X >> 16); \
*X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); }
register unsigned long t
;
* Update message digest buffer MDp->buffer using 16-word data block X.
* Assumes all 16 words of X are full of data.
* Does not update MDp->count.
* This routine is not user-callable.
register unsigned long tmp
, A
, B
, C
, D
;
#if LOWBYTEFIRST == FALSE
/* Update the message digest buffer */
ff(A
,B
,C
,D
,0,fs1
); /* Round 1 */
gg(A
,B
,C
,D
,0,gs1
); /* Round 2 */
hh(A
,B
,C
,D
,0,hs1
); /* Round 3 */
* X -- a pointer to an array of unsigned characters.
* count -- the number of bits of X to use.
* (if not a multiple of 8, uses high bits of last byte.)
* Update MDp using the number of bits of X given by count.
* This is the basic input routine for an MD4 user.
* The routine completes the MD computation when count < 512, so
* every MD computation should end with one call to MDupdate with a
* count less than 512. A call with count 0 will be ignored if the
* MD has already been terminated (done != 0), so an extra call with count
* 0 can be given as a ``courtesy close'' to force termination if desired.
/* return with no error if this is a courtesy close with count
* zero and MDp->done is true.
if(count
== 0 && MDp
->done
)
/* check to see if MD is already done and report error */
printf("\nError: MDupdate MD already done.");
/* Add count to MDp->count */
/* Full block of data to handle */
MDblock(MDp
,(unsigned long *)X
);
/* Check for count too large */
printf("\nError: MDupdate called with illegal count value %ld.",count
);
/* partial block -- must be last block so finish up
* Find out how many bytes and residual bits there are
/* Copy X into XX since we need to modify it */
/* Add padding '1' bit and low-order zeros in last byte */
XX
[byte
] = (XX
[byte
] | mask
) & ~( mask
- 1);
/* If room for bit count, finish up with this block */
XX
[56+i
] = MDp
->count
[i
];
MDblock(MDp
,(unsigned long *)XX
);
/* need to do two blocks to finish up */
MDblock(MDp
,(unsigned long *)XX
);
XX
[56+i
] = MDp
->count
[i
];
MDblock(MDp
,(unsigned long *)XX
);
/* Set flag saying we're done with MD computation */