From: John Kohl Date: Tue, 26 Feb 1991 13:31:30 +0000 (+0000) Subject: updated code from RFC X-Git-Tag: krb5-1.0-alpha4~190 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=470e0f4bd271b10122d349c0afb44d9c23c13dcd;p=krb5.git updated code from RFC git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@1782 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/crypto/md4/md4.c b/src/lib/crypto/md4/md4.c index 038f2d52f..feed466c4 100644 --- a/src/lib/crypto/md4/md4.c +++ b/src/lib/crypto/md4/md4.c @@ -1,322 +1,230 @@ /* - * $Source$ - * $Author$ - * $Id$ + ********************************************************************** + ** md4.c ** + ** RSA Data Security, Inc. MD4 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** + ********************************************************************** */ /* - * md4.c from RFC1186 - * - * $Log$ - * Revision 5.2 1991/01/17 11:39:34 jtkohl - * fix problem with referencing past end of array on byte-aligned - * input - * - * Revision 5.1 90/11/08 11:32:24 jtkohl - * change to copy onto stack to avoid modifying input in MDupdate - * add Kerberos byte-order detection - * some compilers will require the "L" qualifier on long constants. - * - * Revision 5.0 90/11/07 14:12:04 jtkohl - * Initial code from RFC - * + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD4 Message ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD4 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. ** + ********************************************************************** */ -/* -** ******************************************************************** -** md4.c -- Implementation of MD4 Message Digest Algorithm ** -** Updated: 2/16/90 by Ronald L. Rivest ** -** (C) 1990 RSA Data Security, Inc. ** -** ******************************************************************** -*/ +#include "md4.h" -/* -** To use MD4: -** -- 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 -** MDupdate(&MD,X,512) -** (512 is the number of bits in a full block.) -** -- For the last block (less than 64 bytes) you wish to process, -** MDupdate(&MD,X,n) -** 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) -*/ +/* forward declaration */ +static void Transform (); -/* Implementation notes: -** This implementation assumes that ints are 32-bit quantities. -** If the machine stores the least-significant byte of an int in the -** least-addressed byte (e.g., VAX and 8086), then LOWBYTEFIRST -** should be set to TRUE. Otherwise (e.g., SUNS), LOWBYTEFIRST -** should be set to FALSE. -*/ -#define TRUE 1 -#define FALSE 0 -#ifdef LSBFIRST -#define LOWBYTEFIRST TRUE -#endif -#ifdef MSBFIRST -#define LOWBYTEFIRST FALSE -#endif -#ifndef LOWBYTEFIRST - error: you must define MSBFIRST or LSBFIRST; -#endif +static unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; -/* Compile-time includes -*/ -#include -#include -#include +/* F, G and H are basic MD4 functions: selection, majority, parity */ +#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)) -/* Compile-time declarations of MD4 "magic constants". -*/ -#define I0 0x67452301L /* Initial values for MD buffer */ -#define I1 0xefcdab89L -#define I2 0x98badcfeL -#define I3 0x10325476L -#define C2 013240474631L /* round 2 constant = sqrt(2) in octal */ -#define C3 015666365641L /* 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. -** Table 2, page 660. -*/ +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) -#define fs1 3 /* round 1 shift amounts */ -#define fs2 7 -#define fs3 11 -#define fs4 19 -#define gs1 3 /* round 2 shift amounts */ -#define gs2 5 -#define gs3 9 -#define gs4 13 -#define hs1 3 /* round 3 shift amounts */ -#define hs2 9 -#define hs3 11 -#define hs4 15 +/* FF, GG and HH are MD4 transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s) \ + {(a) += F ((b), (c), (d)) + (x); \ + (a) = ROTATE_LEFT ((a), (s));} +#define GG(a, b, c, d, x, s) \ + {(a) += G ((b), (c), (d)) + (x) + (UINT4)013240474631; \ + (a) = ROTATE_LEFT ((a), (s));} +#define HH(a, b, c, d, x, s) \ + {(a) += H ((b), (c), (d)) + (x) + (UINT4)015666365641; \ + (a) = ROTATE_LEFT ((a), (s));} -/* Compile-time macro declarations for MD4. -** Note: The "rot" operator uses the variable "tmp". -** It assumes tmp is declared as unsigned int, 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 h(X,Y,Z) (X^Y^Z) -#define rot(X,S) (tmp=X,(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 MD4Init (mdContext) +MD4_CTX *mdContext; +{ + mdContext->i[0] = mdContext->i[1] = (UINT4)0; -/* MDprint(MDp) -** 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. -*/ -void -MDprint(MDp) -MDptr MDp; -{ int i,j; - for (i=0;i<4;i++) - for (j=0;j<32;j=j+8) - printf("%02x",(MDp->buffer[i]>>j) & 0xFF); + /* Load magic initialization constants. + */ + mdContext->buf[0] = (UINT4)0x67452301; + mdContext->buf[1] = (UINT4)0xefcdab89; + mdContext->buf[2] = (UINT4)0x98badcfe; + mdContext->buf[3] = (UINT4)0x10325476; } -/* MDbegin(MDp) -** Initialize message digest buffer MDp. -** This is a user-callable routine. -*/ -void -MDbegin(MDp) -MDptr MDp; -{ int i; - MDp->buffer[0] = I0; - MDp->buffer[1] = I1; - MDp->buffer[2] = I2; - MDp->buffer[3] = I3; - for (i=0;i<8;i++) MDp->count[i] = 0; - MDp->done = 0; -} +void MD4Update (mdContext, inBuf, inLen) +MD4_CTX *mdContext; +unsigned char *inBuf; +unsigned int inLen; +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((UINT4)inLen << 3); + mdContext->i[1] += ((UINT4)inLen >> 29); -/* MDreverse(X) -** Reverse the byte-ordering of every int in X. -** Assumes X is an array of 16 ints. -** The macro revx reverses the byte-ordering of the next word of X. -*/ -#define revx { t = (*X << 16) | (*X >> 16); \ - *X++ = ((t & 0xFF00FF00L) >> 8) | ((t & 0x00FF00FFL) << 8); } -void -MDreverse(X) -unsigned int *X; -{ register unsigned int t; - revx; revx; revx; revx; revx; revx; revx; revx; - revx; revx; revx; revx; revx; revx; revx; revx; + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); + mdi = 0; + } + } } -/* MDblock(MDp,X) -** 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. -*/ -static void -MDblock(MDp,X) -MDptr MDp; -unsigned int *X; +void MD4Final (mdContext) +MD4_CTX *mdContext; { - register unsigned int tmp, A, B, C, D; -#if LOWBYTEFIRST == FALSE - unsigned int Xtmp[16]; - memcpy(Xtmp, X, sizeof(Xtmp)); - X = Xtmp; - MDreverse(X); -#endif + UINT4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD4Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); - A = MDp->buffer[0]; - B = MDp->buffer[1]; - C = MDp->buffer[2]; - D = MDp->buffer[3]; - /* Update the message digest buffer */ - ff(A , B , C , D , 0 , fs1); /* Round 1 */ - ff(D , A , B , C , 1 , fs2); - ff(C , D , A , B , 2 , fs3); - ff(B , C , D , A , 3 , fs4); - ff(A , B , C , D , 4 , fs1); - ff(D , A , B , C , 5 , fs2); - ff(C , D , A , B , 6 , fs3); - ff(B , C , D , A , 7 , fs4); - ff(A , B , C , D , 8 , fs1); - ff(D , A , B , C , 9 , fs2); - ff(C , D , A , B , 10 , fs3); - ff(B , C , D , A , 11 , fs4); - ff(A , B , C , D , 12 , fs1); - ff(D , A , B , C , 13 , fs2); - ff(C , D , A , B , 14 , fs3); - ff(B , C , D , A , 15 , fs4); - gg(A , B , C , D , 0 , gs1); /* Round 2 */ - gg(D , A , B , C , 4 , gs2); - gg(C , D , A , B , 8 , gs3); - gg(B , C , D , A , 12 , gs4); - gg(A , B , C , D , 1 , gs1); - gg(D , A , B , C , 5 , gs2); - gg(C , D , A , B , 9 , gs3); - gg(B , C , D , A , 13 , gs4); - gg(A , B , C , D , 2 , gs1); - gg(D , A , B , C , 6 , gs2); - gg(C , D , A , B , 10 , gs3); - gg(B , C , D , A , 14 , gs4); - gg(A , B , C , D , 3 , gs1); - gg(D , A , B , C , 7 , gs2); - gg(C , D , A , B , 11 , gs3); - gg(B , C , D , A , 15 , gs4); - hh(A , B , C , D , 0 , hs1); /* Round 3 */ - hh(D , A , B , C , 8 , hs2); - hh(C , D , A , B , 4 , hs3); - hh(B , C , D , A , 12 , hs4); - hh(A , B , C , D , 2 , hs1); - hh(D , A , B , C , 10 , hs2); - hh(C , D , A , B , 6 , hs3); - hh(B , C , D , A , 14 , hs4); - hh(A , B , C , D , 1 , hs1); - hh(D , A , B , C , 9 , hs2); - hh(C , D , A , B , 5 , hs3); - hh(B , C , D , A , 13 , hs4); - hh(A , B , C , D , 3 , hs1); - hh(D , A , B , C , 11 , hs2); - hh(C , D , A , B , 7 , hs3); - hh(B , C , D , A , 15 , hs4); - MDp->buffer[0] += A; - MDp->buffer[1] += B; - MDp->buffer[2] += C; - MDp->buffer[3] += D; + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } } -/* MDupdate(MDp,X,count) -** Input: MDp -- an MDptr -** 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. -*/ -void -MDupdate(MDp,X,count) -MDptr MDp; -unsigned char *X; -unsigned int count; -{ unsigned int i, tmp, bit, byte, mask; - unsigned char XX[64]; - unsigned char *p; - /* return with no error if this is a courtesy close with count - ** zero and MDp->done is true. - */ - if (count == 0 && MDp->done) return; - /* check to see if MD is already done and report error */ - if (MDp->done) - { printf("\nError: MDupdate MD already done."); return; } - /* Add count to MDp->count */ - tmp = count; - p = MDp->count; - while (tmp) - { tmp += *p; - *p++ = (unsigned char) tmp; - tmp = tmp >> 8; - } - /* Process data */ - if (count == 512) - { /* Full block of data to handle */ - MDblock(MDp,(unsigned int *)X); - } - else if (count > 512) /* Check for count too large */ - { printf("\nError: MDupdate called with illegal count value %d." - ,count); - return; - } - else /* partial block -- must be last block so finish up */ - { /* Find out how many bytes and residual bits there are */ - byte = count >> 3; - bit = count & 7; - /* Copy X into XX since we need to modify it */ - for (i=0;icount[i]; - MDblock(MDp,(unsigned int *)XX); - } - else /* need to do two blocks to finish up */ - { MDblock(MDp,(unsigned int *)XX); - for (i=0;i<56;i++) XX[i] = 0; - for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; - MDblock(MDp,(unsigned int *)XX); - } - /* Set flag saying we're done with MD computation */ - MDp->done = 1; - } +/* Basic MD4 step. Transform buf based on in. + */ +static void Transform (buf, in) +UINT4 *buf; +UINT4 *in; +{ + UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ + 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); + + /* Round 2 */ + 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); + + /* Round 3 */ + 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; } /* -** End of md4.c -*/ + ********************************************************************** + ** End of md4.c ** + ******************************* (cut) ******************************** + */