project_files/frontlib/md5/md5.c
changeset 10017 de822cd3df3a
parent 7269 5b0aeef8ba2a
equal deleted inserted replaced
10015:4feced261c68 10017:de822cd3df3a
    25 /*
    25 /*
    26   Independent implementation of MD5 (RFC 1321).
    26   Independent implementation of MD5 (RFC 1321).
    27 
    27 
    28   This code implements the MD5 Algorithm defined in RFC 1321, whose
    28   This code implements the MD5 Algorithm defined in RFC 1321, whose
    29   text is available at
    29   text is available at
    30 	http://www.ietf.org/rfc/rfc1321.txt
    30     http://www.ietf.org/rfc/rfc1321.txt
    31   The code is derived from the text of the RFC, including the test suite
    31   The code is derived from the text of the RFC, including the test suite
    32   (section A.5) but excluding the rest of Appendix A.  It does not include
    32   (section A.5) but excluding the rest of Appendix A.  It does not include
    33   any code or documentation that is identified in the RFC as being
    33   any code or documentation that is identified in the RFC as being
    34   copyrighted.
    34   copyrighted.
    35 
    35 
    36   The original and principal author of md5.c is L. Peter Deutsch
    36   The original and principal author of md5.c is L. Peter Deutsch
    37   <ghost@aladdin.com>.  Other authors are noted in the change history
    37   <ghost@aladdin.com>.  Other authors are noted in the change history
    38   that follows (in reverse chronological order):
    38   that follows (in reverse chronological order):
    39 
    39 
    40   2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
    40   2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
    41 	either statically or dynamically; added missing #include <string.h>
    41     either statically or dynamically; added missing #include <string.h>
    42 	in library.
    42     in library.
    43   2002-03-11 lpd Corrected argument list for main(), and added int return
    43   2002-03-11 lpd Corrected argument list for main(), and added int return
    44 	type, in test program and T value program.
    44     type, in test program and T value program.
    45   2002-02-21 lpd Added missing #include <stdio.h> in test program.
    45   2002-02-21 lpd Added missing #include <stdio.h> in test program.
    46   2000-07-03 lpd Patched to eliminate warnings about "constant is
    46   2000-07-03 lpd Patched to eliminate warnings about "constant is
    47 	unsigned in ANSI C, signed in traditional"; made test program
    47     unsigned in ANSI C, signed in traditional"; made test program
    48 	self-checking.
    48     self-checking.
    49   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
    49   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
    50   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
    50   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
    51   1999-05-03 lpd Original version.
    51   1999-05-03 lpd Original version.
    52  */
    52  */
    53 
    53 
    54 #include "md5.h"
    54 #include "md5.h"
    55 #include <string.h>
    55 #include <string.h>
    56 
    56 
    57 #undef BYTE_ORDER	/* 1 = big-endian, -1 = little-endian, 0 = unknown */
    57 #undef BYTE_ORDER   /* 1 = big-endian, -1 = little-endian, 0 = unknown */
    58 #ifdef ARCH_IS_BIG_ENDIAN
    58 #ifdef ARCH_IS_BIG_ENDIAN
    59 #  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
    59 #  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
    60 #else
    60 #else
    61 #  define BYTE_ORDER 0
    61 #  define BYTE_ORDER 0
    62 #endif
    62 #endif
   130 
   130 
   131 static void
   131 static void
   132 md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
   132 md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
   133 {
   133 {
   134     md5_word_t
   134     md5_word_t
   135 	a = pms->abcd[0], b = pms->abcd[1],
   135     a = pms->abcd[0], b = pms->abcd[1],
   136 	c = pms->abcd[2], d = pms->abcd[3];
   136     c = pms->abcd[2], d = pms->abcd[3];
   137     md5_word_t t;
   137     md5_word_t t;
   138 #if BYTE_ORDER > 0
   138 #if BYTE_ORDER > 0
   139     /* Define storage only for big-endian CPUs. */
   139     /* Define storage only for big-endian CPUs. */
   140     md5_word_t X[16];
   140     md5_word_t X[16];
   141 #else
   141 #else
   144     const md5_word_t *X;
   144     const md5_word_t *X;
   145 #endif
   145 #endif
   146 
   146 
   147     {
   147     {
   148 #if BYTE_ORDER == 0
   148 #if BYTE_ORDER == 0
   149 	/*
   149     /*
   150 	 * Determine dynamically whether this is a big-endian or
   150      * Determine dynamically whether this is a big-endian or
   151 	 * little-endian machine, since we can use a more efficient
   151      * little-endian machine, since we can use a more efficient
   152 	 * algorithm on the latter.
   152      * algorithm on the latter.
   153 	 */
   153      */
   154 	static const int w = 1;
   154     static const int w = 1;
   155 
   155 
   156 	if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
   156     if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
   157 #endif
   157 #endif
   158 #if BYTE_ORDER <= 0		/* little-endian */
   158 #if BYTE_ORDER <= 0     /* little-endian */
   159 	{
   159     {
   160 	    /*
   160         /*
   161 	     * On little-endian machines, we can process properly aligned
   161          * On little-endian machines, we can process properly aligned
   162 	     * data without copying it.
   162          * data without copying it.
   163 	     */
   163          */
   164 	    if (!((data - (const md5_byte_t *)0) & 3)) {
   164         if (!((data - (const md5_byte_t *)0) & 3)) {
   165 		/* data are properly aligned */
   165         /* data are properly aligned */
   166 		X = (const md5_word_t *)data;
   166         X = (const md5_word_t *)data;
   167 	    } else {
   167         } else {
   168 		/* not aligned */
   168         /* not aligned */
   169 		memcpy(xbuf, data, 64);
   169         memcpy(xbuf, data, 64);
   170 		X = xbuf;
   170         X = xbuf;
   171 	    }
   171         }
   172 	}
   172     }
   173 #endif
   173 #endif
   174 #if BYTE_ORDER == 0
   174 #if BYTE_ORDER == 0
   175 	else			/* dynamic big-endian */
   175     else            /* dynamic big-endian */
   176 #endif
   176 #endif
   177 #if BYTE_ORDER >= 0		/* big-endian */
   177 #if BYTE_ORDER >= 0     /* big-endian */
   178 	{
   178     {
   179 	    /*
   179         /*
   180 	     * On big-endian machines, we must arrange the bytes in the
   180          * On big-endian machines, we must arrange the bytes in the
   181 	     * right order.
   181          * right order.
   182 	     */
   182          */
   183 	    const md5_byte_t *xp = data;
   183         const md5_byte_t *xp = data;
   184 	    int i;
   184         int i;
   185 
   185 
   186 #  if BYTE_ORDER == 0
   186 #  if BYTE_ORDER == 0
   187 	    X = xbuf;		/* (dynamic only) */
   187         X = xbuf;       /* (dynamic only) */
   188 #  else
   188 #  else
   189 #    define xbuf X		/* (static only) */
   189 #    define xbuf X      /* (static only) */
   190 #  endif
   190 #  endif
   191 	    for (i = 0; i < 16; ++i, xp += 4)
   191         for (i = 0; i < 16; ++i, xp += 4)
   192 		xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
   192         xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
   193 	}
   193     }
   194 #endif
   194 #endif
   195     }
   195     }
   196 
   196 
   197 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
   197 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
   198 
   198 
   326     int left = nbytes;
   326     int left = nbytes;
   327     int offset = (pms->count[0] >> 3) & 63;
   327     int offset = (pms->count[0] >> 3) & 63;
   328     md5_word_t nbits = (md5_word_t)(nbytes << 3);
   328     md5_word_t nbits = (md5_word_t)(nbytes << 3);
   329 
   329 
   330     if (nbytes <= 0)
   330     if (nbytes <= 0)
   331 	return;
   331     return;
   332 
   332 
   333     /* Update the message length. */
   333     /* Update the message length. */
   334     pms->count[1] += nbytes >> 29;
   334     pms->count[1] += nbytes >> 29;
   335     pms->count[0] += nbits;
   335     pms->count[0] += nbits;
   336     if (pms->count[0] < nbits)
   336     if (pms->count[0] < nbits)
   337 	pms->count[1]++;
   337     pms->count[1]++;
   338 
   338 
   339     /* Process an initial partial block. */
   339     /* Process an initial partial block. */
   340     if (offset) {
   340     if (offset) {
   341 	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
   341     int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
   342 
   342 
   343 	memcpy(pms->buf + offset, p, copy);
   343     memcpy(pms->buf + offset, p, copy);
   344 	if (offset + copy < 64)
   344     if (offset + copy < 64)
   345 	    return;
   345         return;
   346 	p += copy;
   346     p += copy;
   347 	left -= copy;
   347     left -= copy;
   348 	md5_process(pms, pms->buf);
   348     md5_process(pms, pms->buf);
   349     }
   349     }
   350 
   350 
   351     /* Process full blocks. */
   351     /* Process full blocks. */
   352     for (; left >= 64; p += 64, left -= 64)
   352     for (; left >= 64; p += 64, left -= 64)
   353 	md5_process(pms, p);
   353     md5_process(pms, p);
   354 
   354 
   355     /* Process a final partial block. */
   355     /* Process a final partial block. */
   356     if (left)
   356     if (left)
   357 	memcpy(pms->buf, p, left);
   357     memcpy(pms->buf, p, left);
   358 }
   358 }
   359 
   359 
   360 void
   360 void
   361 md5_finish(md5_state_t *pms, md5_byte_t digest[16])
   361 md5_finish(md5_state_t *pms, md5_byte_t digest[16])
   362 {
   362 {
   363     static const md5_byte_t pad[64] = {
   363     static const md5_byte_t pad[64] = {
   364 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   364     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   365 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   365     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   366 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   366     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   367 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   367     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   368     };
   368     };
   369     md5_byte_t data[8];
   369     md5_byte_t data[8];
   370     int i;
   370     int i;
   371 
   371 
   372     /* Save the length before padding. */
   372     /* Save the length before padding. */
   373     for (i = 0; i < 8; ++i)
   373     for (i = 0; i < 8; ++i)
   374 	data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
   374     data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
   375     /* Pad to 56 bytes mod 64. */
   375     /* Pad to 56 bytes mod 64. */
   376     md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
   376     md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
   377     /* Append the length. */
   377     /* Append the length. */
   378     md5_append(pms, data, 8);
   378     md5_append(pms, data, 8);
   379     for (i = 0; i < 16; ++i)
   379     for (i = 0; i < 16; ++i)
   380 	digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
   380     digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
   381 }
   381 }