1139749Simp/*	$NetBSD$	*/
250702Swpaul
350702Swpaul/* crypto/md/md5_dgst.c */
450702Swpaul/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
550702Swpaul * All rights reserved.
650702Swpaul *
750702Swpaul * This package is an SSL implementation written
850702Swpaul * by Eric Young (eay@cryptsoft.com).
950702Swpaul * The implementation was written so as to conform with Netscapes SSL.
1050702Swpaul *
1150702Swpaul * This library is free for commercial and non-commercial use as long as
1250702Swpaul * the following conditions are aheared to.  The following conditions
1350702Swpaul * apply to all code found in this distribution, be it the RC4, RSA,
1450702Swpaul * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1550702Swpaul * included with this distribution is covered by the same copyright terms
1650702Swpaul * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1750702Swpaul *
1850702Swpaul * Copyright remains Eric Young's, and as such any Copyright notices in
1950702Swpaul * the code are not to be removed.
2050702Swpaul * If this package is used in a product, Eric Young should be given attribution
2150702Swpaul * as the author of the parts of the library used.
2250702Swpaul * This can be in the form of a textual message at program startup or
2350702Swpaul * in documentation (online or textual) provided with the package.
2450702Swpaul *
2550702Swpaul * Redistribution and use in source and binary forms, with or without
2650702Swpaul * modification, are permitted provided that the following conditions
2750702Swpaul * are met:
2850702Swpaul * 1. Redistributions of source code must retain the copyright
2950702Swpaul *    notice, this list of conditions and the following disclaimer.
3050702Swpaul * 2. Redistributions in binary form must reproduce the above copyright
3150702Swpaul *    notice, this list of conditions and the following disclaimer in the
3250702Swpaul *    documentation and/or other materials provided with the distribution.
33119418Sobrien * 3. All advertising materials mentioning features or use of this software
34119418Sobrien *    must display the following acknowledgement:
35119418Sobrien *    "This product includes cryptographic software written by
3650702Swpaul *     Eric Young (eay@cryptsoft.com)"
3750702Swpaul *    The word 'cryptographic' can be left out if the rouines from the library
3850702Swpaul *    being used are not cryptographic related :-).
3950702Swpaul * 4. If you include any Windows specific code (or a derivative thereof) from
4050702Swpaul *    the apps directory (application code) you must include an acknowledgement:
4150702Swpaul *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4250702Swpaul *
43129876Sphk * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4450702Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4550702Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4650702Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4750702Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4894149Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4950702Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5050702Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5150702Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5250702Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53109514Sobrien * SUCH DAMAGE.
5450702Swpaul *
5594149Swpaul * The licence and distribution terms for any publically available version or
5694149Swpaul * derivative of this code cannot be changed.  i.e. this code cannot simply be
5794149Swpaul * copied and put under another distribution licence
5850702Swpaul * [including the GNU Public Licence.]
5950702Swpaul */
60105135Salfred
61105135Salfred#ifdef USE_MD5 /*%< Added by ogud@tis.com 1998/1/26 */
6250702Swpaul#include <port_before.h>
6350702Swpaul#ifndef HAVE_MD5
6450702Swpaul#include <stdio.h>
6550702Swpaul#include "md5_locl.h"
6650702Swpaul#include <port_after.h>
6795722Sphk
6850702Swpaulconst char *MD5_version="MD5 part of SSLeay 0.8.1 19-Jul-1997";
69227908Smarius
7050702Swpaul/*! \file
7150702Swpaul * \brief
7250702Swpaul *  Implemented from RFC1321 The MD5 Message-Digest Algorithm
7350702Swpaul */
7450702Swpaul
7550702Swpaul#define INIT_DATA_A (unsigned long)0x67452301L
7650702Swpaul#define INIT_DATA_B (unsigned long)0xefcdab89L
77221407Smarius#define INIT_DATA_C (unsigned long)0x98badcfeL
7850702Swpaul#define INIT_DATA_D (unsigned long)0x10325476L
7950702Swpaul
8050702Swpaul#ifndef NOPROTO
8150702Swpaulstatic void md5_block(MD5_CTX *c, unsigned long *p);
8292739Salfred#else
8394149Swpaulstatic void md5_block();
8450702Swpaul#endif
85165991Smarius
86165991Smariusvoid MD5_Init(c)
87165991SmariusMD5_CTX *c;
88165991Smarius	{
89165991Smarius	c->A=INIT_DATA_A;
90165991Smarius	c->B=INIT_DATA_B;
91165991Smarius	c->C=INIT_DATA_C;
92165991Smarius	c->D=INIT_DATA_D;
93165991Smarius	c->Nl=0;
94164827Smarius	c->Nh=0;
95221407Smarius	c->num=0;
96221407Smarius	}
97221407Smarius
98164827Smariusvoid MD5_Update(c, data, len)
99164827SmariusMD5_CTX *c;
100164827Smariusregister const unsigned char *data;
101221407Smariusunsigned long len;
102221407Smarius	{
103221407Smarius	register ULONG *p;
104221407Smarius	int sw,sc;
105221407Smarius	ULONG l;
106221407Smarius
107105135Salfred	if (len == 0U) return;
108150763Simp
10950702Swpaul	l=(c->Nl+(len<<3))&0xffffffffL;
110164827Smarius	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
111164827Smarius	 * Wei Dai <weidai@eskimo.com> for pointing it out. */
11250702Swpaul	if (l < c->Nl) /*%< overflow */
113164827Smarius		c->Nh++;
114164827Smarius	c->Nh+=(len>>29);
115164827Smarius	c->Nl=l;
11650702Swpaul
117164827Smarius	if (c->num != 0)
118166164Smarius		{
119165991Smarius		p=c->data;
120165991Smarius		sw=c->num>>2;
12150702Swpaul		sc=c->num&0x03;
12250702Swpaul
123105135Salfred		if ((c->num+len) >= (size_t)MD5_CBLOCK)
124150763Simp			{
12550702Swpaul			l= p[sw];
12650702Swpaul			p_c2l(data,l,sc);
127213364Smarius			p[sw++]=l;
128213364Smarius			for (; sw<MD5_LBLOCK; sw++)
129213364Smarius				{
130221407Smarius				c2l(data,l);
131221407Smarius				p[sw]=l;
132164711Smarius				}
13350702Swpaul			len-=(MD5_CBLOCK-c->num);
13450702Swpaul
13584145Sjlemon			md5_block(c,p);
136150763Simp			c->num=0;
13750702Swpaul			/* drop through and do the rest */
13850702Swpaul			}
13950702Swpaul		else
14050702Swpaul			{
14150702Swpaul			int ew,ec;
14250702Swpaul
14350702Swpaul			c->num+=(int)len;
14450702Swpaul			if ((sc+len) < 4U) /*%< ugly, add char's to a word */
14550702Swpaul				{
14650702Swpaul				l= p[sw];
14750702Swpaul				p_c2l_p(data,l,sc,len);
14850702Swpaul				p[sw]=l;
14950702Swpaul				}
150164711Smarius			else
15150702Swpaul				{
15250702Swpaul				ew=(c->num>>2);
15350702Swpaul				ec=(c->num&0x03);
15450702Swpaul				l= p[sw];
15550702Swpaul				p_c2l(data,l,sc);
15650702Swpaul				p[sw++]=l;
15750702Swpaul				for (; sw < ew; sw++)
15850702Swpaul					{ c2l(data,l); p[sw]=l; }
15950702Swpaul				if (ec)
16050702Swpaul					{
16150702Swpaul					c2l_p(data,l,ec);
16250702Swpaul					p[sw]=l;
16350702Swpaul					}
16450702Swpaul				}
16550702Swpaul			return;
16650702Swpaul			}
16750702Swpaul		}
168221407Smarius	/* we now can process the input data in blocks of MD5_CBLOCK
16950702Swpaul	 * chars and save the leftovers to c->data. */
17050702Swpaul	p=c->data;
17184145Sjlemon	while (len >= (size_t)MD5_CBLOCK)
17250702Swpaul		{
17350702Swpaul#if defined(L_ENDIAN) || defined(B_ENDIAN)
17494149Swpaul		memcpy(p,data,MD5_CBLOCK);
175104094Sphk		data+=MD5_CBLOCK;
176150763Simp#ifdef B_ENDIAN
17794149Swpaul		for (sw=(MD5_LBLOCK/4); sw; sw--)
17894149Swpaul			{
179164711Smarius			Endian_Reverse32(p[0]);
18094149Swpaul			Endian_Reverse32(p[1]);
18194149Swpaul			Endian_Reverse32(p[2]);
18294149Swpaul			Endian_Reverse32(p[3]);
18394149Swpaul			p+=4;
18494149Swpaul			}
18594149Swpaul#endif
18694149Swpaul#else
18794149Swpaul		for (sw=(MD5_LBLOCK/4); sw; sw--)
18894149Swpaul			{
18994149Swpaul			c2l(data,l); *(p++)=l;
19094149Swpaul			c2l(data,l); *(p++)=l;
19194149Swpaul			c2l(data,l); *(p++)=l;
19294149Swpaul			c2l(data,l); *(p++)=l;
19394149Swpaul			}
19494149Swpaul#endif
19594149Swpaul		p=c->data;
19694149Swpaul		md5_block(c,p);
19794149Swpaul		len-=MD5_CBLOCK;
19894149Swpaul		}
19994149Swpaul	sc=(int)len;
20094149Swpaul	c->num=sc;
20194149Swpaul	if (sc)
20294149Swpaul		{
20394149Swpaul		sw=sc>>2;	/*%< words to copy */
20494149Swpaul#ifdef L_ENDIAN
20594149Swpaul		p[sw]=0;
20694149Swpaul		memcpy(p,data,sc);
20794149Swpaul#else
20894149Swpaul		sc&=0x03;
20994149Swpaul		for ( ; sw; sw--)
21094149Swpaul			{ c2l(data,l); *(p++)=l; }
21194149Swpaul		c2l_p(data,l,sc);
21294149Swpaul		*p=l;
213173665Syongari#endif
214173665Syongari		}
215173665Syongari	}
216213384Smarius
21794149Swpaulstatic void md5_block(c, X)
218213384SmariusMD5_CTX *c;
21994149Swpaulregister ULONG *X;
22094149Swpaul	{
22194149Swpaul	register ULONG A,B,C,D;
222213384Smarius
22394149Swpaul	A=c->A;
224164711Smarius	B=c->B;
225221407Smarius	C=c->C;
226221407Smarius	D=c->D;
227221407Smarius
22894149Swpaul	/* Round 0 */
22994149Swpaul	R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
23094149Swpaul	R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
23194149Swpaul	R0(C,D,A,B,X[ 2],17,0x242070dbL);
23294149Swpaul	R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
233164711Smarius	R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
23494149Swpaul	R0(D,A,B,C,X[ 5],12,0x4787c62aL);
23594149Swpaul	R0(C,D,A,B,X[ 6],17,0xa8304613L);
23694149Swpaul	R0(B,C,D,A,X[ 7],22,0xfd469501L);
23794149Swpaul	R0(A,B,C,D,X[ 8], 7,0x698098d8L);
23894149Swpaul	R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
23994149Swpaul	R0(C,D,A,B,X[10],17,0xffff5bb1L);
24094149Swpaul	R0(B,C,D,A,X[11],22,0x895cd7beL);
24194149Swpaul	R0(A,B,C,D,X[12], 7,0x6b901122L);
24294149Swpaul	R0(D,A,B,C,X[13],12,0xfd987193L);
24394149Swpaul	R0(C,D,A,B,X[14],17,0xa679438eL);
24494149Swpaul	R0(B,C,D,A,X[15],22,0x49b40821L);
24594149Swpaul	/* Round 1 */
24694149Swpaul	R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
24794149Swpaul	R1(D,A,B,C,X[ 6], 9,0xc040b340L);
248221407Smarius	R1(C,D,A,B,X[11],14,0x265e5a51L);
249221407Smarius	R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
250221407Smarius	R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
251221407Smarius	R1(D,A,B,C,X[10], 9,0x02441453L);
25294149Swpaul	R1(C,D,A,B,X[15],14,0xd8a1e681L);
25394149Swpaul	R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
25494149Swpaul	R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
25594149Swpaul	R1(D,A,B,C,X[14], 9,0xc33707d6L);
25694149Swpaul	R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
257221407Smarius	R1(B,C,D,A,X[ 8],20,0x455a14edL);
25894149Swpaul	R1(A,B,C,D,X[13], 5,0xa9e3e905L);
25994149Swpaul	R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
26094149Swpaul	R1(C,D,A,B,X[ 7],14,0x676f02d9L);
26194149Swpaul	R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
26294149Swpaul	/* Round 2 */
26394149Swpaul	R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
26494149Swpaul	R2(D,A,B,C,X[ 8],11,0x8771f681L);
26594149Swpaul	R2(C,D,A,B,X[11],16,0x6d9d6122L);
26694149Swpaul	R2(B,C,D,A,X[14],23,0xfde5380cL);
26794149Swpaul	R2(A,B,C,D,X[ 1], 4,0xa4beea44L);
26894149Swpaul	R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
269213384Smarius	R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
27094149Swpaul	R2(B,C,D,A,X[10],23,0xbebfbc70L);
271164711Smarius	R2(A,B,C,D,X[13], 4,0x289b7ec6L);
27294149Swpaul	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
303void MD5_Final(md, c)
304unsigned char *md;
305MD5_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@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
360int printit(l)
361unsigned 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