Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/C/Sha1.c
diff options
context:
space:
mode:
Diffstat (limited to 'C/Sha1.c')
-rw-r--r--C/Sha1.c334
1 files changed, 334 insertions, 0 deletions
diff --git a/C/Sha1.c b/C/Sha1.c
new file mode 100644
index 00000000..785c7064
--- /dev/null
+++ b/C/Sha1.c
@@ -0,0 +1,334 @@
+/* Sha1.c -- SHA-1 Hash
+2015-05-10 : Igor Pavlov : Public domain
+This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */
+
+#include "Precomp.h"
+
+#include <string.h>
+
+#include "CpuArch.h"
+#include "RotateDefs.h"
+#include "Sha1.h"
+
+// define it for speed optimization
+// #define _SHA1_UNROLL
+
+#ifdef _SHA1_UNROLL
+ #define kNumW 16
+ #define WW(i) W[(i)&15]
+#else
+ #define kNumW 80
+ #define WW(i) W[i]
+#endif
+
+#define w0(i) (W[i] = data[i])
+
+#define w1(i) (WW(i) = rotlFixed(WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16), 1))
+
+#define f1(x,y,z) (z^(x&(y^z)))
+#define f2(x,y,z) (x^y^z)
+#define f3(x,y,z) ((x&y)|(z&(x|y)))
+#define f4(x,y,z) (x^y^z)
+
+#define RK(a,b,c,d,e, fx, w, k) e += fx(b,c,d) + w + k + rotlFixed(a,5); b = rotlFixed(b,30);
+
+#define R0(a,b,c,d,e, i) RK(a,b,c,d,e, f1, w0(i), 0x5A827999)
+#define R1(a,b,c,d,e, i) RK(a,b,c,d,e, f1, w1(i), 0x5A827999)
+#define R2(a,b,c,d,e, i) RK(a,b,c,d,e, f2, w1(i), 0x6ED9EBA1)
+#define R3(a,b,c,d,e, i) RK(a,b,c,d,e, f3, w1(i), 0x8F1BBCDC)
+#define R4(a,b,c,d,e, i) RK(a,b,c,d,e, f4, w1(i), 0xCA62C1D6)
+
+#define RX_1_4(rx1, rx4, i) \
+ rx1(a,b,c,d,e, i); \
+ rx4(e,a,b,c,d, i+1); \
+ rx4(d,e,a,b,c, i+2); \
+ rx4(c,d,e,a,b, i+3); \
+ rx4(b,c,d,e,a, i+4); \
+
+#define RX_5(rx, i) RX_1_4(rx, rx, i);
+
+#ifdef _SHA1_UNROLL
+
+ #define RX_15 \
+ RX_5(R0, 0); \
+ RX_5(R0, 5); \
+ RX_5(R0, 10);
+
+ #define RX_20(rx, i) \
+ RX_5(rx, i); \
+ RX_5(rx, i + 5); \
+ RX_5(rx, i + 10); \
+ RX_5(rx, i + 15);
+
+#else
+
+#define RX_15 { unsigned i; for (i = 0; i < 15; i += 5) { RX_5(R0, i); } }
+#define RX_20(rx, ii) { unsigned i; i = ii; for (; i < ii + 20; i += 5) { RX_5(rx, i); } }
+
+#endif
+
+
+void Sha1_Init(CSha1 *p)
+{
+ p->state[0] = 0x67452301;
+ p->state[1] = 0xEFCDAB89;
+ p->state[2] = 0x98BADCFE;
+ p->state[3] = 0x10325476;
+ p->state[4] = 0xC3D2E1F0;
+ p->count = 0;
+}
+
+void Sha1_GetBlockDigest(CSha1 *p, const UInt32 *data, UInt32 *destDigest)
+{
+ UInt32 a, b, c, d, e;
+ UInt32 W[kNumW];
+
+ a = p->state[0];
+ b = p->state[1];
+ c = p->state[2];
+ d = p->state[3];
+ e = p->state[4];
+
+ RX_15
+
+ RX_1_4(R0, R1, 15);
+
+ RX_20(R2, 20);
+ RX_20(R3, 40);
+ RX_20(R4, 60);
+
+ destDigest[0] = p->state[0] + a;
+ destDigest[1] = p->state[1] + b;
+ destDigest[2] = p->state[2] + c;
+ destDigest[3] = p->state[3] + d;
+ destDigest[4] = p->state[4] + e;
+}
+
+void Sha1_UpdateBlock_Rar(CSha1 *p, UInt32 *data, int returnRes)
+{
+ UInt32 a, b, c, d, e;
+ UInt32 W[kNumW];
+
+ a = p->state[0];
+ b = p->state[1];
+ c = p->state[2];
+ d = p->state[3];
+ e = p->state[4];
+
+ RX_15
+
+ RX_1_4(R0, R1, 15);
+
+ RX_20(R2, 20);
+ RX_20(R3, 40);
+ RX_20(R4, 60);
+
+ p->state[0] += a;
+ p->state[1] += b;
+ p->state[2] += c;
+ p->state[3] += d;
+ p->state[4] += e;
+
+ if (returnRes)
+ {
+ unsigned i;
+ for (i = 0 ; i < SHA1_NUM_BLOCK_WORDS; i++)
+ data[i] = W[kNumW - SHA1_NUM_BLOCK_WORDS + i];
+ }
+}
+
+#define Sha1_UpdateBlock(p) Sha1_GetBlockDigest(p, p->buffer, p->state)
+
+void Sha1_Update(CSha1 *p, const Byte *data, size_t size)
+{
+ unsigned pos, pos2;
+ if (size == 0)
+ return;
+ pos = (unsigned)p->count & 0x3F;
+ p->count += size;
+ pos2 = pos & 3;
+ pos >>= 2;
+
+ if (pos2 != 0)
+ {
+ UInt32 w = ((UInt32)data[0]) << 24;
+ if (--size && pos2 < 3)
+ {
+ w |= ((UInt32)data[1]) << 16;
+ if (--size && pos2 < 2)
+ {
+ w |= ((UInt32)data[2]) << 8;
+ --size;
+ }
+ }
+ data += 4 - pos2;
+ p->buffer[pos++] |= (w >> (8 * pos2));
+ }
+
+ for (;;)
+ {
+ if (pos == SHA1_NUM_BLOCK_WORDS)
+ {
+ for (;;)
+ {
+ unsigned i;
+ Sha1_UpdateBlock(p);
+ if (size < SHA1_BLOCK_SIZE)
+ break;
+ size -= SHA1_BLOCK_SIZE;
+ for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i += 2)
+ {
+ p->buffer[i ] = GetBe32(data);
+ p->buffer[i + 1] = GetBe32(data + 4);
+ data += 8;
+ }
+ }
+ pos = 0;
+ }
+ if (size < 4)
+ break;
+
+ p->buffer[pos] = GetBe32(data);
+ data += 4;
+ size -= 4;
+ pos++;
+ }
+
+ if (size != 0)
+ {
+ UInt32 w = ((UInt32)data[0]) << 24;
+ if (size > 1)
+ {
+ w |= ((UInt32)data[1]) << 16;
+ if (size > 2)
+ w |= ((UInt32)data[2]) << 8;
+ }
+ p->buffer[pos] = w;
+ }
+}
+
+void Sha1_Update_Rar(CSha1 *p, Byte *data, size_t size, int rar350Mode)
+{
+ int returnRes = False;
+
+ unsigned pos = (unsigned)p->count & 0x3F;
+ p->count += size;
+
+ while (size--)
+ {
+ unsigned pos2 = (pos & 3);
+ UInt32 v = ((UInt32)*data++) << (8 * (3 - pos2));
+ UInt32 *ref = &(p->buffer[pos >> 2]);
+ pos++;
+ if (pos2 == 0)
+ {
+ *ref = v;
+ continue;
+ }
+ *ref |= v;
+
+ if (pos == SHA1_BLOCK_SIZE)
+ {
+ pos = 0;
+ Sha1_UpdateBlock_Rar(p, p->buffer, returnRes);
+ if (returnRes)
+ {
+ unsigned i;
+ for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
+ {
+ UInt32 d = p->buffer[i];
+ Byte *prev = data + i * 4 - SHA1_BLOCK_SIZE;
+ SetUi32(prev, d);
+ }
+ }
+ returnRes = rar350Mode;
+ }
+ }
+}
+
+void Sha1_Final(CSha1 *p, Byte *digest)
+{
+ unsigned pos = (unsigned)p->count & 0x3F;
+ unsigned pos2 = (pos & 3);
+ UInt64 numBits;
+ UInt32 w;
+ unsigned i;
+
+ pos >>= 2;
+
+ w = 0;
+ if (pos2 != 0)
+ w = p->buffer[pos];
+ p->buffer[pos++] = w | (((UInt32)0x80000000) >> (8 * pos2));
+
+ while (pos != (SHA1_NUM_BLOCK_WORDS - 2))
+ {
+ pos &= 0xF;
+ if (pos == 0)
+ Sha1_UpdateBlock(p);
+ p->buffer[pos++] = 0;
+ }
+
+ numBits = (p->count << 3);
+ p->buffer[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32);
+ p->buffer[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits);
+ Sha1_UpdateBlock(p);
+
+ for (i = 0; i < SHA1_NUM_DIGEST_WORDS; i++)
+ {
+ UInt32 v = p->state[i];
+ SetBe32(digest, v);
+ digest += 4;
+ }
+
+ Sha1_Init(p);
+}
+
+
+void Sha1_32_PrepareBlock(const CSha1 *p, UInt32 *block, unsigned size)
+{
+ const UInt64 numBits = (p->count + size) << 5;
+ block[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32);
+ block[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits);
+ block[size++] = 0x80000000;
+ while (size != (SHA1_NUM_BLOCK_WORDS - 2))
+ block[size++] = 0;
+}
+
+void Sha1_32_Update(CSha1 *p, const UInt32 *data, size_t size)
+{
+ unsigned pos = (unsigned)p->count & 0xF;
+ p->count += size;
+ while (size--)
+ {
+ p->buffer[pos++] = *data++;
+ if (pos == SHA1_NUM_BLOCK_WORDS)
+ {
+ pos = 0;
+ Sha1_UpdateBlock(p);
+ }
+ }
+}
+
+void Sha1_32_Final(CSha1 *p, UInt32 *digest)
+{
+ UInt64 numBits;
+ unsigned pos = (unsigned)p->count & 0xF;
+ p->buffer[pos++] = 0x80000000;
+
+ while (pos != (SHA1_NUM_BLOCK_WORDS - 2))
+ {
+ pos &= 0xF;
+ if (pos == 0)
+ Sha1_UpdateBlock(p);
+ p->buffer[pos++] = 0;
+ }
+
+ numBits = (p->count << 5);
+ p->buffer[SHA1_NUM_BLOCK_WORDS - 2] = (UInt32)(numBits >> 32);
+ p->buffer[SHA1_NUM_BLOCK_WORDS - 1] = (UInt32)(numBits);
+
+ Sha1_GetBlockDigest(p, p->buffer, digest);
+
+ Sha1_Init(p);
+}