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 ); +} |
