Home | History | Annotate | Line # | Download | only in dst
      1 /*	$NetBSD: md5_dgst.c,v 1.1.1.1 2009/04/12 15:33:31 christos Exp $	*/
      2 
      3 /* crypto/md/md5_dgst.c */
      4 /* Copyright (C) 1995-1997 Eric Young (eay (at) cryptsoft.com)
      5  * All rights reserved.
      6  *
      7  * This package is an SSL implementation written
      8  * by Eric Young (eay (at) cryptsoft.com).
      9  * The implementation was written so as to conform with Netscapes SSL.
     10  *
     11  * This library is free for commercial and non-commercial use as long as
     12  * the following conditions are aheared to.  The following conditions
     13  * apply to all code found in this distribution, be it the RC4, RSA,
     14  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
     15  * included with this distribution is covered by the same copyright terms
     16  * except that the holder is Tim Hudson (tjh (at) cryptsoft.com).
     17  *
     18  * Copyright remains Eric Young's, and as such any Copyright notices in
     19  * the code are not to be removed.
     20  * If this package is used in a product, Eric Young should be given attribution
     21  * as the author of the parts of the library used.
     22  * This can be in the form of a textual message at program startup or
     23  * in documentation (online or textual) provided with the package.
     24  *
     25  * Redistribution and use in source and binary forms, with or without
     26  * modification, are permitted provided that the following conditions
     27  * are met:
     28  * 1. Redistributions of source code must retain the copyright
     29  *    notice, this list of conditions and the following disclaimer.
     30  * 2. Redistributions in binary form must reproduce the above copyright
     31  *    notice, this list of conditions and the following disclaimer in the
     32  *    documentation and/or other materials provided with the distribution.
     33  * 3. All advertising materials mentioning features or use of this software
     34  *    must display the following acknowledgement:
     35  *    "This product includes cryptographic software written by
     36  *     Eric Young (eay (at) cryptsoft.com)"
     37  *    The word 'cryptographic' can be left out if the rouines from the library
     38  *    being used are not cryptographic related :-).
     39  * 4. If you include any Windows specific code (or a derivative thereof) from
     40  *    the apps directory (application code) you must include an acknowledgement:
     41  *    "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)"
     42  *
     43  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
     44  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     45  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     46  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     47  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     48  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     49  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     50  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     51  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     52  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     53  * SUCH DAMAGE.
     54  *
     55  * The licence and distribution terms for any publically available version or
     56  * derivative of this code cannot be changed.  i.e. this code cannot simply be
     57  * copied and put under another distribution licence
     58  * [including the GNU Public Licence.]
     59  */
     60 
     61 #ifdef USE_MD5 /*%< Added by ogud (at) tis.com 1998/1/26 */
     62 #include <port_before.h>
     63 #ifndef HAVE_MD5
     64 #include <stdio.h>
     65 #include "md5_locl.h"
     66 #include <port_after.h>
     67 
     68 const char *MD5_version="MD5 part of SSLeay 0.8.1 19-Jul-1997";
     69 
     70 /*! \file
     71  * \brief
     72  *  Implemented from RFC1321 The MD5 Message-Digest Algorithm
     73  */
     74 
     75 #define INIT_DATA_A (unsigned long)0x67452301L
     76 #define INIT_DATA_B (unsigned long)0xefcdab89L
     77 #define INIT_DATA_C (unsigned long)0x98badcfeL
     78 #define INIT_DATA_D (unsigned long)0x10325476L
     79 
     80 #ifndef NOPROTO
     81 static void md5_block(MD5_CTX *c, unsigned long *p);
     82 #else
     83 static void md5_block();
     84 #endif
     85 
     86 void MD5_Init(c)
     87 MD5_CTX *c;
     88 	{
     89 	c->A=INIT_DATA_A;
     90 	c->B=INIT_DATA_B;
     91 	c->C=INIT_DATA_C;
     92 	c->D=INIT_DATA_D;
     93 	c->Nl=0;
     94 	c->Nh=0;
     95 	c->num=0;
     96 	}
     97 
     98 void MD5_Update(c, data, len)
     99 MD5_CTX *c;
    100 register const unsigned char *data;
    101 unsigned long len;
    102 	{
    103 	register ULONG *p;
    104 	int sw,sc;
    105 	ULONG l;
    106 
    107 	if (len == 0U) return;
    108 
    109 	l=(c->Nl+(len<<3))&0xffffffffL;
    110 	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
    111 	 * Wei Dai <weidai (at) eskimo.com> for pointing it out. */
    112 	if (l < c->Nl) /*%< overflow */
    113 		c->Nh++;
    114 	c->Nh+=(len>>29);
    115 	c->Nl=l;
    116 
    117 	if (c->num != 0)
    118 		{
    119 		p=c->data;
    120 		sw=c->num>>2;
    121 		sc=c->num&0x03;
    122 
    123 		if ((c->num+len) >= (size_t)MD5_CBLOCK)
    124 			{
    125 			l= p[sw];
    126 			p_c2l(data,l,sc);
    127 			p[sw++]=l;
    128 			for (; sw<MD5_LBLOCK; sw++)
    129 				{
    130 				c2l(data,l);
    131 				p[sw]=l;
    132 				}
    133 			len-=(MD5_CBLOCK-c->num);
    134 
    135 			md5_block(c,p);
    136 			c->num=0;
    137 			/* drop through and do the rest */
    138 			}
    139 		else
    140 			{
    141 			int ew,ec;
    142 
    143 			c->num+=(int)len;
    144 			if ((sc+len) < 4U) /*%< ugly, add char's to a word */
    145 				{
    146 				l= p[sw];
    147 				p_c2l_p(data,l,sc,len);
    148 				p[sw]=l;
    149 				}
    150 			else
    151 				{
    152 				ew=(c->num>>2);
    153 				ec=(c->num&0x03);
    154 				l= p[sw];
    155 				p_c2l(data,l,sc);
    156 				p[sw++]=l;
    157 				for (; sw < ew; sw++)
    158 					{ c2l(data,l); p[sw]=l; }
    159 				if (ec)
    160 					{
    161 					c2l_p(data,l,ec);
    162 					p[sw]=l;
    163 					}
    164 				}
    165 			return;
    166 			}
    167 		}
    168 	/* we now can process the input data in blocks of MD5_CBLOCK
    169 	 * chars and save the leftovers to c->data. */
    170 	p=c->data;
    171 	while (len >= (size_t)MD5_CBLOCK)
    172 		{
    173 #if defined(L_ENDIAN) || defined(B_ENDIAN)
    174 		memcpy(p,data,MD5_CBLOCK);
    175 		data+=MD5_CBLOCK;
    176 #ifdef B_ENDIAN
    177 		for (sw=(MD5_LBLOCK/4); sw; sw--)
    178 			{
    179 			Endian_Reverse32(p[0]);
    180 			Endian_Reverse32(p[1]);
    181 			Endian_Reverse32(p[2]);
    182 			Endian_Reverse32(p[3]);
    183 			p+=4;
    184 			}
    185 #endif
    186 #else
    187 		for (sw=(MD5_LBLOCK/4); sw; sw--)
    188 			{
    189 			c2l(data,l); *(p++)=l;
    190 			c2l(data,l); *(p++)=l;
    191 			c2l(data,l); *(p++)=l;
    192 			c2l(data,l); *(p++)=l;
    193 			}
    194 #endif
    195 		p=c->data;
    196 		md5_block(c,p);
    197 		len-=MD5_CBLOCK;
    198 		}
    199 	sc=(int)len;
    200 	c->num=sc;
    201 	if (sc)
    202 		{
    203 		sw=sc>>2;	/*%< words to copy */
    204 #ifdef L_ENDIAN
    205 		p[sw]=0;
    206 		memcpy(p,data,sc);
    207 #else
    208 		sc&=0x03;
    209 		for ( ; sw; sw--)
    210 			{ c2l(data,l); *(p++)=l; }
    211 		c2l_p(data,l,sc);
    212 		*p=l;
    213 #endif
    214 		}
    215 	}
    216 
    217 static void md5_block(c, X)
    218 MD5_CTX *c;
    219 register ULONG *X;
    220 	{
    221 	register ULONG A,B,C,D;
    222 
    223 	A=c->A;
    224 	B=c->B;
    225 	C=c->C;
    226 	D=c->D;
    227 
    228 	/* Round 0 */
    229 	R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
    230 	R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
    231 	R0(C,D,A,B,X[ 2],17,0x242070dbL);
    232 	R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
    233 	R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
    234 	R0(D,A,B,C,X[ 5],12,0x4787c62aL);
    235 	R0(C,D,A,B,X[ 6],17,0xa8304613L);
    236 	R0(B,C,D,A,X[ 7],22,0xfd469501L);
    237 	R0(A,B,C,D,X[ 8], 7,0x698098d8L);
    238 	R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
    239 	R0(C,D,A,B,X[10],17,0xffff5bb1L);
    240 	R0(B,C,D,A,X[11],22,0x895cd7beL);
    241 	R0(A,B,C,D,X[12], 7,0x6b901122L);
    242 	R0(D,A,B,C,X[13],12,0xfd987193L);
    243 	R0(C,D,A,B,X[14],17,0xa679438eL);
    244 	R0(B,C,D,A,X[15],22,0x49b40821L);
    245 	/* Round 1 */
    246 	R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
    247 	R1(D,A,B,C,X[ 6], 9,0xc040b340L);
    248 	R1(C,D,A,B,X[11],14,0x265e5a51L);
    249 	R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
    250 	R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
    251 	R1(D,A,B,C,X[10], 9,0x02441453L);
    252 	R1(C,D,A,B,X[15],14,0xd8a1e681L);
    253 	R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
    254 	R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
    255 	R1(D,A,B,C,X[14], 9,0xc33707d6L);
    256 	R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
    257 	R1(B,C,D,A,X[ 8],20,0x455a14edL);
    258 	R1(A,B,C,D,X[13], 5,0xa9e3e905L);
    259 	R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
    260 	R1(C,D,A,B,X[ 7],14,0x676f02d9L);
    261 	R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
    262 	/* Round 2 */
    263 	R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
    264 	R2(D,A,B,C,X[ 8],11,0x8771f681L);
    265 	R2(C,D,A,B,X[11],16,0x6d9d6122L);
    266 	R2(B,C,D,A,X[14],23,0xfde5380cL);
    267 	R2(A,B,C,D,X[ 1], 4,0xa4beea44L);
    268 	R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
    269 	R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
    270 	R2(B,C,D,A,X[10],23,0xbebfbc70L);
    271 	R2(A,B,C,D,X[13], 4,0x289b7ec6L);
    272 	R2(D,A,B,C,X[ 0],11,0xeaa127faL);
    273 	R2(C,D,A,B,X[ 3],16,0xd4ef3085L);
    274 	R2(B,C,D,A,X[ 6],23,0x04881d05L);
    275 	R2(A,B,C,D,X[ 9], 4,0xd9d4d039L);
    276 	R2(D,A,B,C,X[12],11,0xe6db99e5L);
    277 	R2(C,D,A,B,X[15],16,0x1fa27cf8L);
    278 	R2(B,C,D,A,X[ 2],23,0xc4ac5665L);
    279 	/* Round 3 */
    280 	R3(A,B,C,D,X[ 0], 6,0xf4292244L);
    281 	R3(D,A,B,C,X[ 7],10,0x432aff97L);
    282 	R3(C,D,A,B,X[14],15,0xab9423a7L);
    283 	R3(B,C,D,A,X[ 5],21,0xfc93a039L);
    284 	R3(A,B,C,D,X[12], 6,0x655b59c3L);
    285 	R3(D,A,B,C,X[ 3],10,0x8f0ccc92L);
    286 	R3(C,D,A,B,X[10],15,0xffeff47dL);
    287 	R3(B,C,D,A,X[ 1],21,0x85845dd1L);
    288 	R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);
    289 	R3(D,A,B,C,X[15],10,0xfe2ce6e0L);
    290 	R3(C,D,A,B,X[ 6],15,0xa3014314L);
    291 	R3(B,C,D,A,X[13],21,0x4e0811a1L);
    292 	R3(A,B,C,D,X[ 4], 6,0xf7537e82L);
    293 	R3(D,A,B,C,X[11],10,0xbd3af235L);
    294 	R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);
    295 	R3(B,C,D,A,X[ 9],21,0xeb86d391L);
    296 
    297 	c->A+=A&0xffffffffL;
    298 	c->B+=B&0xffffffffL;
    299 	c->C+=C&0xffffffffL;
    300 	c->D+=D&0xffffffffL;
    301 	}
    302 
    303 void MD5_Final(md, c)
    304 unsigned char *md;
    305 MD5_CTX *c;
    306 	{
    307 	register int i,j;
    308 	register ULONG l;
    309 	register ULONG *p;
    310 	static unsigned char end[4]={0x80,0x00,0x00,0x00};
    311 	unsigned char *cp=end;
    312 
    313 	/* c->num should definitly have room for at least one more byte. */
    314 	p=c->data;
    315 	j=c->num;
    316 	i=j>>2;
    317 
    318 	/* purify often complains about the following line as an
    319 	 * Uninitialized Memory Read.  While this can be true, the
    320 	 * following p_c2l macro will reset l when that case is true.
    321 	 * This is because j&0x03 contains the number of 'valid' bytes
    322 	 * already in p[i].  If and only if j&0x03 == 0, the UMR will
    323 	 * occur but this is also the only time p_c2l will do
    324 	 * l= *(cp++) instead of l|= *(cp++)
    325 	 * Many thanks to Alex Tang <altitude (at) cic.net> for pickup this
    326 	 * 'potential bug' */
    327 #ifdef PURIFY
    328 	if ((j&0x03) == 0) p[i]=0;
    329 #endif
    330 	l=p[i];
    331 	p_c2l(cp,l,j&0x03);
    332 	p[i]=l;
    333 	i++;
    334 	/* i is the next 'undefined word' */
    335 	if (c->num >= MD5_LAST_BLOCK)
    336 		{
    337 		for (; i<MD5_LBLOCK; i++)
    338 			p[i]=0;
    339 		md5_block(c,p);
    340 		i=0;
    341 		}
    342 	for (; i<(MD5_LBLOCK-2); i++)
    343 		p[i]=0;
    344 	p[MD5_LBLOCK-2]=c->Nl;
    345 	p[MD5_LBLOCK-1]=c->Nh;
    346 	md5_block(c,p);
    347 	cp=md;
    348 	l=c->A; l2c(l,cp);
    349 	l=c->B; l2c(l,cp);
    350 	l=c->C; l2c(l,cp);
    351 	l=c->D; l2c(l,cp);
    352 
    353 	/* clear stuff, md5_block may be leaving some stuff on the stack
    354 	 * but I'm not worried :-) */
    355 	c->num=0;
    356 /*	memset((char *)&c,0,sizeof(c));*/
    357 	}
    358 
    359 #ifdef undef
    360 int printit(l)
    361 unsigned long *l;
    362 	{
    363 	int i,ii;
    364 
    365 	for (i=0; i<2; i++)
    366 		{
    367 		for (ii=0; ii<8; ii++)
    368 			{
    369 			fprintf(stderr,"%08lx ",l[i*8+ii]);
    370 			}
    371 		fprintf(stderr,"\n");
    372 		}
    373 	}
    374 #endif
    375 #endif /* HAVE_MD5 */
    376 #endif /* USE_MD5 */
    377