diff options
Diffstat (limited to 'C/Sha1.c')
-rw-r--r-- | C/Sha1.c | 334 |
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); +} |