Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:18

0001 /*
0002 ** ********************************************************************
0003 ** md4.c -- Implementation of MD4 Message Digest Algorithm           **
0004 ** Updated: 2/16/90 by Ronald L. Rivest                              **
0005 ** (C) 1990 RSA Data Security, Inc.                                  **
0006 ** ********************************************************************
0007 */
0008 
0009 /*
0010 ** To use MD4:
0011 **   -- Include md4.h in your program
0012 **   -- Declare an MDstruct MD to hold the state of the digest
0013 **          computation.
0014 **   -- Initialize MD using MDbegin(&MD)
0015 **   -- For each full block (64 bytes) X you wish to process, call
0016 **          MD4Update(&MD,X,512)
0017 **      (512 is the number of bits in a full block.)
0018 **   -- For the last block (less than 64 bytes) you wish to process,
0019 **          MD4Update(&MD,X,n)
0020 **      where n is the number of bits in the partial block. A partial
0021 **      block terminates the computation, so every MD computation
0022 **      should terminate by processing a partial block, even if it
0023 **      has n = 0.
0024 **   -- The message digest is available in MD.buffer[0] ...
0025 **      MD.buffer[3].  (Least-significant byte of each word
0026 **      should be output first.)
0027 **   -- You can print out the digest using MDprint(&MD)
0028 */
0029 
0030 #ifdef HAVE_CONFIG_H
0031 #include "config.h"
0032 #endif
0033 
0034 /* Implementation notes:
0035 ** This implementation assumes that ints are 32-bit quantities.
0036 */
0037 
0038 /* Compile-time includes
0039 */
0040 #include <stdio.h>
0041 #include "md4.h"
0042 
0043 #include <inttypes.h>
0044 
0045 /* Compile-time declarations of MD4 "magic constants".
0046 */
0047 #define I0  0x67452301L       /* Initial values for MD buffer */
0048 #define I1  0xefcdab89L
0049 #define I2  0x98badcfeL
0050 #define I3  0x10325476L
0051 #define C2  013240474631L     /* round 2 constant = sqrt(2) in octal */
0052 #define C3  015666365641L     /* round 3 constant = sqrt(3) in octal */
0053 /* C2 and C3 are from Knuth, The Art of Programming, Volume 2
0054 ** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
0055 ** Table 2, page 660.
0056 */
0057 
0058 #define fs1  3               /* round 1 shift amounts */
0059 #define fs2  7
0060 #define fs3 11
0061 #define fs4 19
0062 #define gs1  3               /* round 2 shift amounts */
0063 #define gs2  5
0064 #define gs3  9
0065 #define gs4 13
0066 #define hs1  3               /* round 3 shift amounts */
0067 #define hs2  9
0068 #define hs3 11
0069 #define hs4 15
0070 
0071 /* Compile-time macro declarations for MD4.
0072 ** Note: The "rot" operator uses the variable "tmp".
0073 ** It assumes tmp is declared as unsigned int, so that the >>
0074 ** operator will shift in zeros rather than extending the sign bit.
0075 */
0076 #define f(X,Y,Z)             ((X&Y) | ((~X)&Z))
0077 #define g(X,Y,Z)             ((X&Y) | (X&Z) | (Y&Z))
0078 #define h(X,Y,Z)             (X^Y^Z)
0079 #define rot(X,S)             (tmp=X,(tmp<<S) | (tmp>>(32-S)))
0080 #define ff(A,B,C,D,i,s)      A = rot((A + f(B,C,D) + X[i]),s)
0081 #define gg(A,B,C,D,i,s)      A = rot((A + g(B,C,D) + X[i] + C2),s)
0082 #define hh(A,B,C,D,i,s)      A = rot((A + h(B,C,D) + X[i] + C3),s)
0083 
0084 /* MD4print(MDp)
0085 ** Print message digest buffer MDp as 32 hexadecimal digits.
0086 ** Order is from low-order byte of buffer[0] to high-order byte of
0087 ** buffer[3].
0088 ** Each byte is printed with high-order hexadecimal digit first.
0089 ** This is a user-callable routine.
0090 */
0091 void
0092 MD4Print(
0093   MD4_CTX *MDp)
0094 {
0095   int i,j;
0096   for (i=0;i<4;i++)
0097     for (j=0;j<32;j=j+8)
0098       printf("%02" PRIx32,(MDp->buffer[i]>>j) & 0xFF);
0099 }
0100 
0101 /* MD4Init(MDp)
0102 ** Initialize message digest buffer MDp.
0103 ** This is a user-callable routine.
0104 */
0105 void
0106 MD4Init(
0107   MD4_CTX *MDp)
0108 {
0109   int i;
0110   MDp->buffer[0] = I0;
0111   MDp->buffer[1] = I1;
0112   MDp->buffer[2] = I2;
0113   MDp->buffer[3] = I3;
0114   for (i=0;i<8;i++) MDp->count[i] = 0;
0115   MDp->done = 0;
0116 }
0117 
0118 /* MDblock(MDp,X)
0119 ** Update message digest buffer MDp->buffer using 16-word data block X.
0120 ** Assumes all 16 words of X are full of data.
0121 ** Does not update MDp->count.
0122 ** This routine is not user-callable.
0123 */
0124 static void
0125 MDblock(
0126   MD4_CTX *MDp,
0127   unsigned char *Xb)
0128 {
0129   register uint32_t tmp, A, B, C, D;
0130   uint32_t X[16];
0131   int i;
0132 
0133   for (i = 0; i < 16; ++i) {
0134     X[i] = Xb[0] + ((uint32_t)Xb[1] << 8) +
0135            ((uint32_t)Xb[2] << 16) + ((uint32_t)Xb[3] << 24);
0136     Xb += 4;
0137   }
0138 
0139   A = MDp->buffer[0];
0140   B = MDp->buffer[1];
0141   C = MDp->buffer[2];
0142   D = MDp->buffer[3];
0143   /* Update the message digest buffer */
0144   ff(A , B , C , D ,  0 , fs1); /* Round 1 */
0145   ff(D , A , B , C ,  1 , fs2);
0146   ff(C , D , A , B ,  2 , fs3);
0147   ff(B , C , D , A ,  3 , fs4);
0148   ff(A , B , C , D ,  4 , fs1);
0149   ff(D , A , B , C ,  5 , fs2);
0150   ff(C , D , A , B ,  6 , fs3);
0151   ff(B , C , D , A ,  7 , fs4);
0152   ff(A , B , C , D ,  8 , fs1);
0153   ff(D , A , B , C ,  9 , fs2);
0154   ff(C , D , A , B , 10 , fs3);
0155   ff(B , C , D , A , 11 , fs4);
0156   ff(A , B , C , D , 12 , fs1);
0157   ff(D , A , B , C , 13 , fs2);
0158   ff(C , D , A , B , 14 , fs3);
0159   ff(B , C , D , A , 15 , fs4);
0160   gg(A , B , C , D ,  0 , gs1); /* Round 2 */
0161   gg(D , A , B , C ,  4 , gs2);
0162   gg(C , D , A , B ,  8 , gs3);
0163   gg(B , C , D , A , 12 , gs4);
0164   gg(A , B , C , D ,  1 , gs1);
0165   gg(D , A , B , C ,  5 , gs2);
0166   gg(C , D , A , B ,  9 , gs3);
0167   gg(B , C , D , A , 13 , gs4);
0168   gg(A , B , C , D ,  2 , gs1);
0169   gg(D , A , B , C ,  6 , gs2);
0170   gg(C , D , A , B , 10 , gs3);
0171   gg(B , C , D , A , 14 , gs4);
0172   gg(A , B , C , D ,  3 , gs1);
0173   gg(D , A , B , C ,  7 , gs2);
0174   gg(C , D , A , B , 11 , gs3);
0175   gg(B , C , D , A , 15 , gs4);
0176   hh(A , B , C , D ,  0 , hs1); /* Round 3 */
0177   hh(D , A , B , C ,  8 , hs2);
0178   hh(C , D , A , B ,  4 , hs3);
0179   hh(B , C , D , A , 12 , hs4);
0180   hh(A , B , C , D ,  2 , hs1);
0181   hh(D , A , B , C , 10 , hs2);
0182   hh(C , D , A , B ,  6 , hs3);
0183   hh(B , C , D , A , 14 , hs4);
0184   hh(A , B , C , D ,  1 , hs1);
0185   hh(D , A , B , C ,  9 , hs2);
0186   hh(C , D , A , B ,  5 , hs3);
0187   hh(B , C , D , A , 13 , hs4);
0188   hh(A , B , C , D ,  3 , hs1);
0189   hh(D , A , B , C , 11 , hs2);
0190   hh(C , D , A , B ,  7 , hs3);
0191   hh(B , C , D , A , 15 , hs4);
0192   MDp->buffer[0] += A;
0193   MDp->buffer[1] += B;
0194   MDp->buffer[2] += C;
0195   MDp->buffer[3] += D;
0196 }
0197 
0198 /* MD4Update(MDp,X,count)
0199 ** Input: X -- a pointer to an array of unsigned characters.
0200 **        count -- the number of bits of X to use.
0201 **          (if not a multiple of 8, uses high bits of last byte.)
0202 ** Update MDp using the number of bits of X given by count.
0203 ** This is the basic input routine for an MD4 user.
0204 ** The routine completes the MD computation when count < 512, so
0205 ** every MD computation should end with one call to MD4Update with a
0206 ** count less than 512.  A call with count 0 will be ignored if the
0207 ** MD has already been terminated (done != 0), so an extra call with
0208 ** count 0 can be given as a "courtesy close" to force termination
0209 ** if desired.
0210 */
0211 void
0212 MD4Update(
0213   MD4_CTX *MDp,
0214   unsigned char *X,
0215   unsigned int count )
0216 {
0217   unsigned int i, tmp, bit, byte, mask;
0218   unsigned char XX[64];
0219   unsigned char *p;
0220 
0221   /* return with no error if this is a courtesy close with count
0222   ** zero and MDp->done is true.
0223   */
0224   if (count == 0 && MDp->done) return;
0225   /* check to see if MD is already done and report error */
0226   if (MDp->done)
0227   { printf("\nError: MD4Update MD already done."); return; }
0228 
0229   /* Add count to MDp->count */
0230   tmp = count;
0231   p = MDp->count;
0232   while (tmp)
0233   { tmp += *p;
0234   *p++ = tmp;
0235   tmp = tmp >> 8;
0236   }
0237 
0238   /* Process data */
0239   if (count == 512)
0240   { /* Full block of data to handle */
0241     MDblock(MDp,X);
0242   }
0243   else if (count > 512) /* Check for count too large */
0244   {
0245     printf("\nError: MD4Update called with illegal count value %d.",
0246        count);
0247     return;
0248   }
0249   else /* partial block -- must be last block so finish up */
0250   {
0251     /* Find out how many bytes and residual bits there are */
0252     byte = count >> 3;
0253     bit =  count & 7;
0254     /* Copy X into XX since we need to modify it */
0255     for (i=0;i<=byte;i++)   XX[i] = X[i];
0256     for (i=byte+1;i<64;i++) XX[i] = 0;
0257     /* Add padding '1' bit and low-order zeros in last byte */
0258     mask = 1 << (7 - bit);
0259     XX[byte] = (XX[byte] | mask) & ~( mask - 1);
0260     /* If room for bit count, finish up with this block */
0261     if (byte <= 55)
0262     {
0263       for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
0264       MDblock(MDp,XX);
0265     }
0266     else /* need to do two blocks to finish up */
0267     {
0268       MDblock(MDp,XX);
0269       for (i=0;i<56;i++) XX[i] = 0;
0270       for (i=0;i<8;i++)  XX[56+i] = MDp->count[i];
0271       MDblock(MDp,XX);
0272     }
0273     /* Set flag saying we're done with MD computation */
0274     MDp->done = 1;
0275   }
0276 }
0277 
0278 /*
0279 ** Finish up MD4 computation and return message digest.
0280 */
0281 void
0282 MD4Final(
0283   unsigned char *buf,
0284   MD4_CTX *MD)
0285 {
0286   int i, j;
0287   unsigned int w;
0288 
0289   MD4Update(MD, NULL, 0);
0290   for (i = 0; i < 4; ++i) {
0291     w = MD->buffer[i];
0292     for (j = 0; j < 4; ++j) {
0293       *buf++ = w;
0294       w >>= 8;
0295     }
0296   }
0297 }
0298 
0299 /*
0300 ** End of md4.c
0301 ****************************(cut)***********************************/