1/* crypto/sha/sha1dgst.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the routines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <sys/types.h>
60
61#include <stdio.h>
62#include <string.h>
63
64#if 0
65#include <machine/ansi.h>	/* we use the __ variants of bit-sized types */
66#endif
67#include <machine/endian.h>
68
69#undef  SHA_0
70#define SHA_1
71#include "sha.h"
72#include "sha_locl.h"
73
74/*
75 * The assembly-language code is not position-independent, so don't
76 * try to use it in a shared library.
77 */
78#ifdef PIC
79#undef SHA1_ASM
80#endif
81
82char *SHA1_version="SHA1 part of SSLeay 0.9.0b 11-Oct-1998";
83
84/* Implemented from SHA-1 document - The Secure Hash Algorithm
85 */
86
87#define INIT_DATA_h0 (unsigned long)0x67452301L
88#define INIT_DATA_h1 (unsigned long)0xefcdab89L
89#define INIT_DATA_h2 (unsigned long)0x98badcfeL
90#define INIT_DATA_h3 (unsigned long)0x10325476L
91#define INIT_DATA_h4 (unsigned long)0xc3d2e1f0L
92
93#define K_00_19	0x5a827999L
94#define K_20_39 0x6ed9eba1L
95#define K_40_59 0x8f1bbcdcL
96#define K_60_79 0xca62c1d6L
97
98#ifndef NOPROTO
99#  ifdef SHA1_ASM
100     void sha1_block_x86(SHA_CTX *c, const u_int32_t *p, int num);
101#    define sha1_block sha1_block_x86
102#  else
103     void sha1_block(SHA_CTX *c, const u_int32_t *p, int num);
104#  endif
105#else
106#  ifdef SHA1_ASM
107     void sha1_block_x86();
108#    define sha1_block sha1_block_x86
109#  else
110     void sha1_block();
111#  endif
112#endif
113
114
115#if BYTE_ORDER == LITTLE_ENDIAN && defined(SHA1_ASM)
116#  define	M_c2nl 		c2l
117#  define	M_p_c2nl 	p_c2l
118#  define	M_c2nl_p	c2l_p
119#  define	M_p_c2nl_p	p_c2l_p
120#  define	M_nl2c		l2c
121#else
122#  define	M_c2nl 		c2nl
123#  define	M_p_c2nl	p_c2nl
124#  define	M_c2nl_p	c2nl_p
125#  define	M_p_c2nl_p	p_c2nl_p
126#  define	M_nl2c		nl2c
127#endif
128
129void SHA1_Init(SHA_CTX *c)
130	{
131	c->h0=INIT_DATA_h0;
132	c->h1=INIT_DATA_h1;
133	c->h2=INIT_DATA_h2;
134	c->h3=INIT_DATA_h3;
135	c->h4=INIT_DATA_h4;
136	c->Nl=0;
137	c->Nh=0;
138	c->num=0;
139	}
140
141void
142SHA1_Update(SHA_CTX *c, const void *in, size_t len)
143{
144	u_int32_t *p;
145	int ew,ec,sw,sc;
146	u_int32_t l;
147	const unsigned char *data = in;
148
149	if (len == 0) return;
150
151	l=(c->Nl+(len<<3))&0xffffffffL;
152	if (l < c->Nl) /* overflow */
153		c->Nh++;
154	c->Nh+=(len>>29);
155	c->Nl=l;
156
157	if (c->num != 0)
158		{
159		p=c->data;
160		sw=c->num>>2;
161		sc=c->num&0x03;
162
163		if ((c->num+len) >= SHA_CBLOCK)
164			{
165			l= p[sw];
166			M_p_c2nl(data,l,sc);
167			p[sw++]=l;
168			for (; sw<SHA_LBLOCK; sw++)
169				{
170				M_c2nl(data,l);
171				p[sw]=l;
172				}
173			len-=(SHA_CBLOCK-c->num);
174
175			sha1_block(c,p,64);
176			c->num=0;
177			/* drop through and do the rest */
178			}
179		else
180			{
181			c->num+=(int)len;
182			if ((sc+len) < 4) /* ugly, add char's to a word */
183				{
184				l= p[sw];
185				M_p_c2nl_p(data,l,sc,len);
186				p[sw]=l;
187				}
188			else
189				{
190				ew=(c->num>>2);
191				ec=(c->num&0x03);
192				l= p[sw];
193				M_p_c2nl(data,l,sc);
194				p[sw++]=l;
195				for (; sw < ew; sw++)
196					{ M_c2nl(data,l); p[sw]=l; }
197				if (ec)
198					{
199					M_c2nl_p(data,l,ec);
200					p[sw]=l;
201					}
202				}
203			return;
204			}
205		}
206	/* We can only do the following code for assember, the reason
207	 * being that the sha1_block 'C' version changes the values
208	 * in the 'data' array.  The assember code avoids this and
209	 * copies it to a local array.  I should be able to do this for
210	 * the C version as well....
211	 */
212#if 1
213#if BYTE_ORDER == BIG_ENDIAN || defined(SHA1_ASM)
214	if ((((unsigned int)data)%sizeof(u_int32_t)) == 0)
215		{
216		sw=len/SHA_CBLOCK;
217		if (sw)
218			{
219			sw*=SHA_CBLOCK;
220			sha1_block(c,(u_int32_t *)data,sw);
221			data+=sw;
222			len-=sw;
223			}
224		}
225#endif
226#endif
227	/* we now can process the input data in blocks of SHA_CBLOCK
228	 * chars and save the leftovers to c->data. */
229	p=c->data;
230	while (len >= SHA_CBLOCK)
231		{
232#if BYTE_ORDER == BIG_ENDIAN || BYTE_ORDER == LITTLE_ENDIAN
233		if (p != (u_int32_t *)data)
234			memcpy(p,data,SHA_CBLOCK);
235		data+=SHA_CBLOCK;
236#  if BYTE_ORDER == LITTLE_ENDIAN
237#    ifndef SHA1_ASM /* Will not happen */
238		for (sw=(SHA_LBLOCK/4); sw; sw--)
239			{
240			Endian_Reverse32(p[0]);
241			Endian_Reverse32(p[1]);
242			Endian_Reverse32(p[2]);
243			Endian_Reverse32(p[3]);
244			p+=4;
245			}
246		p=c->data;
247#    endif
248#  endif
249#else
250		for (sw=(SHA_BLOCK/4); sw; sw--)
251			{
252			M_c2nl(data,l); *(p++)=l;
253			M_c2nl(data,l); *(p++)=l;
254			M_c2nl(data,l); *(p++)=l;
255			M_c2nl(data,l); *(p++)=l;
256			}
257		p=c->data;
258#endif
259		sha1_block(c,p,64);
260		len-=SHA_CBLOCK;
261		}
262	ec=(int)len;
263	c->num=ec;
264	ew=(ec>>2);
265	ec&=0x03;
266
267	for (sw=0; sw < ew; sw++)
268		{ M_c2nl(data,l); p[sw]=l; }
269	M_c2nl_p(data,l,ec);
270	p[sw]=l;
271	}
272
273void SHA1_Transform(SHA_CTX *c, unsigned char *b)
274	{
275	u_int32_t p[16];
276#if BYTE_ORDER != BIG_ENDIAN
277	u_int32_t *q;
278	int i;
279#endif
280
281#if BYTE_ORDER == BIG_ENDIAN || BYTE_ORDER == LITTLE_ENDIAN
282	memcpy(p,b,64);
283#if BYTE_ORDER == LITTLE_ENDIAN
284	q=p;
285	for (i=(SHA_LBLOCK/4); i; i--)
286		{
287		Endian_Reverse32(q[0]);
288		Endian_Reverse32(q[1]);
289		Endian_Reverse32(q[2]);
290		Endian_Reverse32(q[3]);
291		q+=4;
292		}
293#endif
294#else
295	q=p;
296	for (i=(SHA_LBLOCK/4); i; i--)
297		{
298		u_int32_t l;
299		c2nl(b,l); *(q++)=l;
300		c2nl(b,l); *(q++)=l;
301		c2nl(b,l); *(q++)=l;
302		c2nl(b,l); *(q++)=l;
303		}
304#endif
305	sha1_block(c,p,64);
306	}
307
308#ifndef SHA1_ASM
309
310void
311sha1_block(SHA_CTX *c, const u_int32_t *W, int num)
312{
313	u_int32_t A,B,C,D,E,T;
314	u_int32_t X[16];
315
316	A=c->h0;
317	B=c->h1;
318	C=c->h2;
319	D=c->h3;
320	E=c->h4;
321
322	for (;;)
323		{
324	BODY_00_15( 0,A,B,C,D,E,T,W);
325	BODY_00_15( 1,T,A,B,C,D,E,W);
326	BODY_00_15( 2,E,T,A,B,C,D,W);
327	BODY_00_15( 3,D,E,T,A,B,C,W);
328	BODY_00_15( 4,C,D,E,T,A,B,W);
329	BODY_00_15( 5,B,C,D,E,T,A,W);
330	BODY_00_15( 6,A,B,C,D,E,T,W);
331	BODY_00_15( 7,T,A,B,C,D,E,W);
332	BODY_00_15( 8,E,T,A,B,C,D,W);
333	BODY_00_15( 9,D,E,T,A,B,C,W);
334	BODY_00_15(10,C,D,E,T,A,B,W);
335	BODY_00_15(11,B,C,D,E,T,A,W);
336	BODY_00_15(12,A,B,C,D,E,T,W);
337	BODY_00_15(13,T,A,B,C,D,E,W);
338	BODY_00_15(14,E,T,A,B,C,D,W);
339	BODY_00_15(15,D,E,T,A,B,C,W);
340	BODY_16_19(16,C,D,E,T,A,B,W,W,W,W);
341	BODY_16_19(17,B,C,D,E,T,A,W,W,W,W);
342	BODY_16_19(18,A,B,C,D,E,T,W,W,W,W);
343	BODY_16_19(19,T,A,B,C,D,E,W,W,W,X);
344
345	BODY_20_31(20,E,T,A,B,C,D,W,W,W,X);
346	BODY_20_31(21,D,E,T,A,B,C,W,W,W,X);
347	BODY_20_31(22,C,D,E,T,A,B,W,W,W,X);
348	BODY_20_31(23,B,C,D,E,T,A,W,W,W,X);
349	BODY_20_31(24,A,B,C,D,E,T,W,W,X,X);
350	BODY_20_31(25,T,A,B,C,D,E,W,W,X,X);
351	BODY_20_31(26,E,T,A,B,C,D,W,W,X,X);
352	BODY_20_31(27,D,E,T,A,B,C,W,W,X,X);
353	BODY_20_31(28,C,D,E,T,A,B,W,W,X,X);
354	BODY_20_31(29,B,C,D,E,T,A,W,W,X,X);
355	BODY_20_31(30,A,B,C,D,E,T,W,X,X,X);
356	BODY_20_31(31,T,A,B,C,D,E,W,X,X,X);
357	BODY_32_39(32,E,T,A,B,C,D,X);
358	BODY_32_39(33,D,E,T,A,B,C,X);
359	BODY_32_39(34,C,D,E,T,A,B,X);
360	BODY_32_39(35,B,C,D,E,T,A,X);
361	BODY_32_39(36,A,B,C,D,E,T,X);
362	BODY_32_39(37,T,A,B,C,D,E,X);
363	BODY_32_39(38,E,T,A,B,C,D,X);
364	BODY_32_39(39,D,E,T,A,B,C,X);
365
366	BODY_40_59(40,C,D,E,T,A,B,X);
367	BODY_40_59(41,B,C,D,E,T,A,X);
368	BODY_40_59(42,A,B,C,D,E,T,X);
369	BODY_40_59(43,T,A,B,C,D,E,X);
370	BODY_40_59(44,E,T,A,B,C,D,X);
371	BODY_40_59(45,D,E,T,A,B,C,X);
372	BODY_40_59(46,C,D,E,T,A,B,X);
373	BODY_40_59(47,B,C,D,E,T,A,X);
374	BODY_40_59(48,A,B,C,D,E,T,X);
375	BODY_40_59(49,T,A,B,C,D,E,X);
376	BODY_40_59(50,E,T,A,B,C,D,X);
377	BODY_40_59(51,D,E,T,A,B,C,X);
378	BODY_40_59(52,C,D,E,T,A,B,X);
379	BODY_40_59(53,B,C,D,E,T,A,X);
380	BODY_40_59(54,A,B,C,D,E,T,X);
381	BODY_40_59(55,T,A,B,C,D,E,X);
382	BODY_40_59(56,E,T,A,B,C,D,X);
383	BODY_40_59(57,D,E,T,A,B,C,X);
384	BODY_40_59(58,C,D,E,T,A,B,X);
385	BODY_40_59(59,B,C,D,E,T,A,X);
386
387	BODY_60_79(60,A,B,C,D,E,T,X);
388	BODY_60_79(61,T,A,B,C,D,E,X);
389	BODY_60_79(62,E,T,A,B,C,D,X);
390	BODY_60_79(63,D,E,T,A,B,C,X);
391	BODY_60_79(64,C,D,E,T,A,B,X);
392	BODY_60_79(65,B,C,D,E,T,A,X);
393	BODY_60_79(66,A,B,C,D,E,T,X);
394	BODY_60_79(67,T,A,B,C,D,E,X);
395	BODY_60_79(68,E,T,A,B,C,D,X);
396	BODY_60_79(69,D,E,T,A,B,C,X);
397	BODY_60_79(70,C,D,E,T,A,B,X);
398	BODY_60_79(71,B,C,D,E,T,A,X);
399	BODY_60_79(72,A,B,C,D,E,T,X);
400	BODY_60_79(73,T,A,B,C,D,E,X);
401	BODY_60_79(74,E,T,A,B,C,D,X);
402	BODY_60_79(75,D,E,T,A,B,C,X);
403	BODY_60_79(76,C,D,E,T,A,B,X);
404	BODY_60_79(77,B,C,D,E,T,A,X);
405	BODY_60_79(78,A,B,C,D,E,T,X);
406	BODY_60_79(79,T,A,B,C,D,E,X);
407
408	c->h0=(c->h0+E)&0xffffffffL;
409	c->h1=(c->h1+T)&0xffffffffL;
410	c->h2=(c->h2+A)&0xffffffffL;
411	c->h3=(c->h3+B)&0xffffffffL;
412	c->h4=(c->h4+C)&0xffffffffL;
413
414	num-=64;
415	if (num <= 0) break;
416
417	A=c->h0;
418	B=c->h1;
419	C=c->h2;
420	D=c->h3;
421	E=c->h4;
422
423	W+=16;
424		}
425	}
426#endif
427
428void SHA1_Final(unsigned char *md, SHA_CTX *c)
429	{
430	int i,j;
431	u_int32_t l;
432	u_int32_t *p;
433	static unsigned char end[4]={0x80,0x00,0x00,0x00};
434	unsigned char *cp=end;
435
436	/* c->num should definitly have room for at least one more byte. */
437	p=c->data;
438	j=c->num;
439	i=j>>2;
440#ifdef PURIFY
441	if ((j&0x03) == 0) p[i]=0;
442#endif
443	l=p[i];
444	M_p_c2nl(cp,l,j&0x03);
445	p[i]=l;
446	i++;
447	/* i is the next 'undefined word' */
448	if (c->num >= SHA_LAST_BLOCK)
449		{
450		for (; i<SHA_LBLOCK; i++)
451			p[i]=0;
452		sha1_block(c,p,64);
453		i=0;
454		}
455	for (; i<(SHA_LBLOCK-2); i++)
456		p[i]=0;
457	p[SHA_LBLOCK-2]=c->Nh;
458	p[SHA_LBLOCK-1]=c->Nl;
459#if BYTE_ORDER == LITTLE_ENDIAN && defined(SHA1_ASM)
460	Endian_Reverse32(p[SHA_LBLOCK-2]);
461	Endian_Reverse32(p[SHA_LBLOCK-1]);
462#endif
463	sha1_block(c,p,64);
464	cp=md;
465	l=c->h0; nl2c(l,cp);
466	l=c->h1; nl2c(l,cp);
467	l=c->h2; nl2c(l,cp);
468	l=c->h3; nl2c(l,cp);
469	l=c->h4; nl2c(l,cp);
470
471	/* Clear the context state */
472	explicit_bzero(&c, sizeof(c));
473	}
474
475#ifdef WEAK_REFS
476/* When building libmd, provide weak references. Note: this is not
477   activated in the context of compiling these sources for internal
478   use in libcrypt.
479 */
480#undef SHA_Init
481__weak_reference(_libmd_SHA_Init, SHA_Init);
482#undef SHA_Update
483__weak_reference(_libmd_SHA_Update, SHA_Update);
484#undef SHA_Final
485__weak_reference(_libmd_SHA_Final, SHA_Final);
486#undef SHA_Transform
487__weak_reference(_libmd_SHA_Transform, SHA_Transform);
488#undef SHA_version
489__weak_reference(_libmd_SHA_version, SHA_version);
490#undef sha_block
491__weak_reference(_libmd_sha_block, sha_block);
492#undef SHA1_Init
493__weak_reference(_libmd_SHA1_Init, SHA1_Init);
494#undef SHA1_Update
495__weak_reference(_libmd_SHA1_Update, SHA1_Update);
496#undef SHA1_Final
497__weak_reference(_libmd_SHA1_Final, SHA1_Final);
498#undef SHA1_Transform
499__weak_reference(_libmd_SHA1_Transform, SHA1_Transform);
500#undef SHA1_version
501__weak_reference(_libmd_SHA1_version, SHA1_version);
502#undef sha1_block
503__weak_reference(_libmd_sha1_block, sha1_block);
504#endif
505