#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"
#include "sha1.h"
void SHA1_Init(SHA1_CONTEXT *p)
{
p->H[0] = 0x67452301;
p->H[1] = 0xEFCDAB89;
p->H[2] = 0x98BADCFE;
p->H[3] = 0x10325476;
p->H[4] = 0xC3D2E1F0;
p->nTotal = 0;
p->nblock = 0;
}
#ifdef WIN32
#define ROTL(d,n) _lrotl(d,n)
#else // WIN32
#define ROTL(d,n) (((d) << (n)) | ((d) >> (32-(n))))
#endif // WIN32
#define Ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define Parity(x,y,z) ((x) ^ (y) ^ (z))
#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
void SHA1_HashBlock(SHA1_CONTEXT *p)
{
int t;
UINT32 W[80];
// Prepare Message Schedule, {W sub t}.
//
int j;
for (t = 0, j = 0; t <= 15; t++, j += 4)
{
W[t] = (p->block[j ] << 24)
| (p->block[j+1] << 16)
| (p->block[j+2] << 8)
| (p->block[j+3] );
}
for (t = 16; t <= 79; t++)
{
W[t] = ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
}
UINT32 a = p->H[0];
UINT32 b = p->H[1];
UINT32 c = p->H[2];
UINT32 d = p->H[3];
UINT32 e = p->H[4];
UINT32 T;
for (t = 0; t <= 19; t++)
{
T = ROTL(a,5) + Ch(b,c,d) + e + 0x5A827999 + W[t];
e = d;
d = c;
c = ROTL(b,30);
b = a;
a = T;
}
for (t = 20; t <= 39; t++)
{
T = ROTL(a,5) + Parity(b,c,d) + e + 0x6ED9EBA1 + W[t];
e = d;
d = c;
c = ROTL(b,30);
b = a;
a = T;
}
for (t = 40; t <= 59; t++)
{
T = ROTL(a,5) + Maj(b,c,d) + e + 0x8F1BBCDC + W[t];
e = d;
d = c;
c = ROTL(b,30);
b = a;
a = T;
}
for (t = 60; t <= 79; t++)
{
T = ROTL(a,5) + Parity(b,c,d) + e + 0xCA62C1D6 + W[t];
e = d;
d = c;
c = ROTL(b,30);
b = a;
a = T;
}
p->H[0] += a;
p->H[1] += b;
p->H[2] += c;
p->H[3] += d;
p->H[4] += e;
}
void SHA1_Compute(SHA1_CONTEXT *p, size_t n, const char *buf)
{
while (n)
{
size_t m = sizeof(p->block) - p->nblock;
if (n < m)
{
m = n;
}
memcpy(p->block + p->nblock, buf, m);
buf += m;
n -= m;
p->nblock += m;
p->nTotal += m;
if (p->nblock == sizeof(p->block))
{
SHA1_HashBlock(p);
p->nblock = 0;
}
}
}
void SHA1_Final(SHA1_CONTEXT *p)
{
p->block[p->nblock++] = 0x80;
if (sizeof(p->block) - sizeof(UINT64) <= p->nblock)
{
memset(p->block + p->nblock, 0, sizeof(p->block) - p->nblock);
SHA1_HashBlock(p);
memset(p->block, 0, sizeof(p->block) - sizeof(UINT64));
}
else
{
memset(p->block + p->nblock, 0, sizeof(p->block) - p->nblock - sizeof(UINT64));
}
p->nTotal *= 8;
p->block[sizeof(p->block) - 8] = (UINT8)(p->nTotal >> 56) & 0xFF;
p->block[sizeof(p->block) - 7] = (UINT8)(p->nTotal >> 48) & 0xFF;
p->block[sizeof(p->block) - 6] = (UINT8)(p->nTotal >> 40) & 0xFF;
p->block[sizeof(p->block) - 5] = (UINT8)(p->nTotal >> 32) & 0xFF;
p->block[sizeof(p->block) - 4] = (UINT8)(p->nTotal >> 24) & 0xFF;
p->block[sizeof(p->block) - 3] = (UINT8)(p->nTotal >> 16) & 0xFF;
p->block[sizeof(p->block) - 2] = (UINT8)(p->nTotal >> 8) & 0xFF;
p->block[sizeof(p->block) - 1] = (UINT8)(p->nTotal ) & 0xFF;
SHA1_HashBlock(p);
}
#if 0
//#define TEST_STRING "abc"
#define TEST_STRING "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
int main(int argc, char *argv[])
{
char buffer[] = TEST_STRING;
SHA1_CONTEXT shac;
SHA1_Init(&shac);
SHA1_Compute(&shac, strlen(TEST_STRING), buffer);
SHA1_Final(&shac);
int i;
for (i = 0; i < 5; i++)
{
printf("%08X", shac.H[i]);
}
return 1;
}
#endif