xref: /netbsd-src/external/bsd/libbind/dist/dst/md5_dgst.c (revision b5677b36047b601b9addaaa494a58ceae82c2a6c)
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@cryptsoft.com)
5  * All rights reserved.
6  *
7  * This package is an SSL implementation written
8  * by Eric Young (eay@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@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@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@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@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 
MD5_Init(c)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 
MD5_Update(c,data,len)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@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 
md5_block(c,X)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 
MD5_Final(md,c)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@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
printit(l)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