diff options
Diffstat (limited to 'sha1/sha1.c')
| -rw-r--r-- | sha1/sha1.c | 192 | 
1 files changed, 192 insertions, 0 deletions
| diff --git a/sha1/sha1.c b/sha1/sha1.c new file mode 100644 index 0000000..089ca3a --- /dev/null +++ b/sha1/sha1.c @@ -0,0 +1,192 @@ +/* +** Copyright 2001 Double Precision, Inc. +** See COPYING for distribution information. +*/ + +#define	SHA1_INTERNAL +#include	"sha1.h" + +#include	<string.h> +#include	<stdlib.h> + + +#define	K0 0x5A827999 +#define	K1 0x6ED9EBA1 +#define	K2 0x8F1BBCDC +#define	K3 0XCA62C1D6 + +#define	K20(x)	x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x + +static SHA1_WORD K[80] = { K20(K0), K20(K1), K20(K2), K20(K3) }; + +void sha1_context_init(struct SHA1_CONTEXT *c) +{ +	if (sizeof(SHA1_WORD) != 4) +		abort(); + +	c->H[0] = 0x67452301; +	c->H[1] = 0xEFCDAB89; +	c->H[2] = 0x98BADCFE; +	c->H[3] = 0x10325476; +	c->H[4] = 0xC3D2E1F0; +	c->blk_ptr=0; +} + +void sha1_context_hash(struct SHA1_CONTEXT *c, +		const unsigned char blk[SHA1_BLOCK_SIZE]) +{ +SHA1_WORD	A,B,C,D,E; +SHA1_WORD	TEMP; +SHA1_WORD	W[80]; +unsigned	i, t; + +#define f(t,B,C,D)	( \ +	(t) < 20 ? ( (B) & (C) ) | ( (~(B)) & (D) ) : \ +	(t) >= 40 && (t) < 60 ? ( (B) & (C) ) | ( (B) & (D) ) | ( (C) & (D) ):\ +		(B) ^ (C) ^ (D) ) + +#define S(a,b) ( ((SHA1_WORD)(a) << (b)) | ((SHA1_WORD)(a) >> (32 - (b)))) + +	for (i=t=0; t<16; t++) +	{ +		W[t]= blk[i]; i++; +		W[t] = (W[t] << 8) | blk[i]; i++; +		W[t] = (W[t] << 8) | blk[i]; i++; +		W[t] = (W[t] << 8) | blk[i]; i++; +	} + +	for (t=16; t<80; t++) +	{ +		TEMP= W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]; +		W[t]= S(TEMP, 1); +	} + +	A=c->H[0]; +	B=c->H[1]; +	C=c->H[2]; +	D=c->H[3]; +	E=c->H[4]; + +	for (t=0; t<80; t++) +	{ +		TEMP = S(A,5); +		TEMP += f(t, B, C, D); +		TEMP += E; +		TEMP += W[t]; +		TEMP += K[t]; + +		E=D; +		D=C; +		C= S(B, 30); +		B=A; +		A=TEMP; +	} + +	c->H[0] += A; +	c->H[1] += B; +	c->H[2] += C; +	c->H[3] += D; +	c->H[4] += E; +} + +void sha1_context_hashstream(struct SHA1_CONTEXT *c, const void *p, unsigned l) +{ +const unsigned char *cp=(const unsigned char *)p; +unsigned ll; + +	while (l) +	{ +		if (c->blk_ptr == 0 && l >= SHA1_BLOCK_SIZE) +		{ +			sha1_context_hash(c, cp); +			cp += SHA1_BLOCK_SIZE; +			l -= SHA1_BLOCK_SIZE; +			continue; +		} + +		ll=l; +		if (ll > SHA1_BLOCK_SIZE - c->blk_ptr) +			ll=SHA1_BLOCK_SIZE - c->blk_ptr; +		memcpy(c->blk + c->blk_ptr, cp, ll); +		c->blk_ptr += ll; +		cp += ll; +		l -= ll; +		if (c->blk_ptr >= SHA1_BLOCK_SIZE) +		{ +			sha1_context_hash(c, c->blk); +			c->blk_ptr=0; +		} +	} +} + +void sha1_context_endstream(struct SHA1_CONTEXT *c, unsigned long l) +{ +	unsigned char buf[8]; +	static const unsigned char zero[SHA1_BLOCK_SIZE-8]; + +	buf[0]=0x80; +	sha1_context_hashstream(c, &buf, 1); +	while (c->blk_ptr != SHA1_BLOCK_SIZE-8) +	{ +		if (c->blk_ptr > SHA1_BLOCK_SIZE-8) +		{ +			sha1_context_hashstream(c, zero, +				SHA1_BLOCK_SIZE - c->blk_ptr); +			continue; +		} +		sha1_context_hashstream(c, zero, +			SHA1_BLOCK_SIZE-8-c->blk_ptr); +	} + +	l *= 8; +	buf[7] = l; +	buf[6] = (l >>= 8); +	buf[5] = (l >>= 8); +	buf[4] = (l >> 8); +	buf[3]=buf[2]=buf[1]=buf[0]=0; + +	sha1_context_hashstream(c, buf, 8); +} + +void sha1_context_digest(struct SHA1_CONTEXT *c, SHA1_DIGEST d) +{ +unsigned char *dp=d + SHA1_DIGEST_SIZE; +unsigned i; + +	for ( i=5; i; ) +	{ +	SHA1_WORD	w=c->H[--i]; + +		*--dp=w; w >>= 8; +		*--dp=w; w >>= 8; +		*--dp=w; w >>= 8; +		*--dp=w; +	} +} + +void sha1_context_restore(struct SHA1_CONTEXT *c, const SHA1_DIGEST d) +{ +const unsigned char *dp=d; +unsigned i; + +	for (i=0; i<5; i++) +	{ +	SHA1_WORD	w= *dp++; + +		w=(w << 8) | *dp++; +		w=(w << 8) | *dp++; +		w=(w << 8) | *dp++; +		c->H[i]=w; +	} +	c->blk_ptr=0; +} + +void sha1_digest(const void *msg, unsigned len, SHA1_DIGEST d) +{ +struct SHA1_CONTEXT c; + +	sha1_context_init( &c ); +	sha1_context_hashstream(&c, msg, len); +	sha1_context_endstream(&c, len); +	sha1_context_digest( &c, d ); +} | 
