summaryrefslogtreecommitdiffstats
path: root/sha1/sha1.c
diff options
context:
space:
mode:
Diffstat (limited to 'sha1/sha1.c')
-rw-r--r--sha1/sha1.c192
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 );
+}