#include <sys/types.h>
#include <sys/systm.h>
#include <libkern/crypto/sha1.h>
#define memset(x, y, z) bzero(x, z);
#define memcpy(x, y, z) bcopy(y, x, z)
#define state h.b32
#define bcount c.b32
#define buffer m.b8
#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
#define FETCH_32(p) ({ \
register u_int32_t l = (u_int32_t)*((const u_int32_t *)(p)); \
__asm__ __volatile__("bswap %0" : "=r" (l) : "0" (l)); \
l; \
})
#else
#define FETCH_32(p) \
(((u_int32_t)*((const u_int8_t *)(p) + 3)) | \
(((u_int32_t)*((const u_int8_t *)(p) + 2)) << 8) | \
(((u_int32_t)*((const u_int8_t *)(p) + 1)) << 16) | \
(((u_int32_t)*((const u_int8_t *)(p))) << 24))
#endif
static void
Encode(unsigned char *output, u_int32_t *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j + 3] = input[i] & 0xff;
output[j + 2] = (input[i] >> 8) & 0xff;
output[j + 1] = (input[i] >> 16) & 0xff;
output[j] = (input[i] >> 24) & 0xff;
}
}
static unsigned char PADDING[64] = { 0x80, };
#define K_00_19 0x5a827999UL
#define K_20_39 0x6ed9eba1UL
#define K_40_59 0x8f1bbcdcUL
#define K_60_79 0xca62c1d6UL
#define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d))
#define G(b, c, d) ((b) ^ (c) ^ (d))
#define H(b, c, d) (((b) & (c)) | (((b) | (c)) & (d)))
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
#define R(f, k, v, w, x, y, z, i) { \
(v) = ROTATE_LEFT(w, 5) + f(x, y, z) + (v) + (i) + (k); \
(x) = ROTATE_LEFT(x, 30); \
}
#define R1(v, w, x, y, z, i) R(F, K_00_19, v, w, x, y, z, i)
#define R2(v, w, x, y, z, i) R(G, K_20_39, v, w, x, y, z, i)
#define R3(v, w, x, y, z, i) R(H, K_40_59, v, w, x, y, z, i)
#define R4(v, w, x, y, z, i) R(G, K_60_79, v, w, x, y, z, i)
#define WUPDATE(p, q, r, s) { \
(p) = ((q) ^ (r) ^ (s) ^ (p)); \
(p) = ROTATE_LEFT(p, 1); \
}
static void SHA1Transform(u_int32_t, u_int32_t, u_int32_t, u_int32_t,
u_int32_t, const u_int8_t *, SHA1_CTX *);
void SHA1Final_r(SHA1_CTX *, void *);
void
SHA1Init(SHA1_CTX *context)
{
context->bcount[0] = context->bcount[1] = 0;
context->count = 0;
context->state[0] = 0x67452301UL;
context->state[1] = 0xefcdab89UL;
context->state[2] = 0x98badcfeUL;
context->state[3] = 0x10325476UL;
context->state[4] = 0xc3d2e1f0UL;
}
void
SHA1Update(SHA1_CTX *context, const void *inpp, size_t inputLen)
{
u_int32_t i, index, partLen;
const unsigned char *input = (const unsigned char *)inpp;
if (inputLen == 0)
return;
index = (context->bcount[1] >> 3) & 0x3F;
if ((context->bcount[1] += (inputLen << 3)) < (inputLen << 3))
context->bcount[0]++;
context->bcount[0] += (inputLen >> 29);
partLen = 64 - index;
i = 0;
if (inputLen >= partLen) {
if (index != 0) {
memcpy(&context->buffer[index], input, partLen);
SHA1Transform(context->state[0], context->state[1],
context->state[2], context->state[3],
context->state[4], context->buffer, context);
i = partLen;
}
for (; i + 63 < inputLen; i += 64)
SHA1Transform(context->state[0], context->state[1],
context->state[2], context->state[3],
context->state[4], &input[i], context);
if (inputLen == i)
return;
index = 0;
}
memcpy(&context->buffer[index], &input[i], inputLen - i);
}
void
SHA1Final_r(SHA1_CTX *context, void *digest)
{
SHA1Final(digest, context);
}
void
SHA1Final(void *digest, SHA1_CTX *context)
{
unsigned char bits[8];
u_int32_t index = (context->bcount[1] >> 3) & 0x3f;
Encode(bits, context->bcount, 8);
SHA1Update(context, PADDING, ((index < 56) ? 56 : 120) - index);
SHA1Update(context, bits, 8);
Encode(digest, context->state, 20);
memset(context, 0, sizeof (*context));
}
static void
SHA1Transform(u_int32_t a, u_int32_t b, u_int32_t c, u_int32_t d,
u_int32_t e, const u_int8_t block[64], SHA1_CTX *context)
{
register u_int32_t w0, w1, w2, w3, w4, w5, w6, w7;
register u_int32_t w8, w9, w10, w11, w12, w13, w14, w15;
w15 = FETCH_32(block + 60);
w14 = FETCH_32(block + 56);
w13 = FETCH_32(block + 52);
w12 = FETCH_32(block + 48);
w11 = FETCH_32(block + 44);
w10 = FETCH_32(block + 40);
w9 = FETCH_32(block + 36);
w8 = FETCH_32(block + 32);
w7 = FETCH_32(block + 28);
w6 = FETCH_32(block + 24);
w5 = FETCH_32(block + 20);
w4 = FETCH_32(block + 16);
w3 = FETCH_32(block + 12);
w2 = FETCH_32(block + 8);
w1 = FETCH_32(block + 4);
w0 = FETCH_32(block + 0);
R1(e, a, b, c, d, w0);
R1(d, e, a, b, c, w1);
R1(c, d, e, a, b, w2);
R1(b, c, d, e, a, w3);
R1(a, b, c, d, e, w4);
R1(e, a, b, c, d, w5);
R1(d, e, a, b, c, w6);
R1(c, d, e, a, b, w7);
R1(b, c, d, e, a, w8);
R1(a, b, c, d, e, w9);
R1(e, a, b, c, d, w10);
R1(d, e, a, b, c, w11);
R1(c, d, e, a, b, w12);
R1(b, c, d, e, a, w13);
R1(a, b, c, d, e, w14);
R1(e, a, b, c, d, w15);
WUPDATE( w0, w13, w8, w2); R1(d, e, a, b, c, w0);
WUPDATE( w1, w14, w9, w3); R1(c, d, e, a, b, w1);
WUPDATE( w2, w15, w10, w4); R1(b, c, d, e, a, w2);
WUPDATE( w3, w0, w11, w5); R1(a, b, c, d, e, w3);
WUPDATE( w4, w1, w12, w6); R2(e, a, b, c, d, w4);
WUPDATE( w5, w2, w13, w7); R2(d, e, a, b, c, w5);
WUPDATE( w6, w3, w14, w8); R2(c, d, e, a, b, w6);
WUPDATE( w7, w4, w15, w9); R2(b, c, d, e, a, w7);
WUPDATE( w8, w5, w0, w10); R2(a, b, c, d, e, w8);
WUPDATE( w9, w6, w1, w11); R2(e, a, b, c, d, w9);
WUPDATE(w10, w7, w2, w12); R2(d, e, a, b, c, w10);
WUPDATE(w11, w8, w3, w13); R2(c, d, e, a, b, w11);
WUPDATE(w12, w9, w4, w14); R2(b, c, d, e, a, w12);
WUPDATE(w13, w10, w5, w15); R2(a, b, c, d, e, w13);
WUPDATE(w14, w11, w6, w0); R2(e, a, b, c, d, w14);
WUPDATE(w15, w12, w7, w1); R2(d, e, a, b, c, w15);
WUPDATE( w0, w13, w8, w2); R2(c, d, e, a, b, w0);
WUPDATE( w1, w14, w9, w3); R2(b, c, d, e, a, w1);
WUPDATE( w2, w15, w10, w4); R2(a, b, c, d, e, w2);
WUPDATE( w3, w0, w11, w5); R2(e, a, b, c, d, w3);
WUPDATE( w4, w1, w12, w6); R2(d, e, a, b, c, w4);
WUPDATE( w5, w2, w13, w7); R2(c, d, e, a, b, w5);
WUPDATE( w6, w3, w14, w8); R2(b, c, d, e, a, w6);
WUPDATE( w7, w4, w15, w9); R2(a, b, c, d, e, w7);
WUPDATE( w8, w5, w0, w10); R3(e, a, b, c, d, w8);
WUPDATE( w9, w6, w1, w11); R3(d, e, a, b, c, w9);
WUPDATE(w10, w7, w2, w12); R3(c, d, e, a, b, w10);
WUPDATE(w11, w8, w3, w13); R3(b, c, d, e, a, w11);
WUPDATE(w12, w9, w4, w14); R3(a, b, c, d, e, w12);
WUPDATE(w13, w10, w5, w15); R3(e, a, b, c, d, w13);
WUPDATE(w14, w11, w6, w0); R3(d, e, a, b, c, w14);
WUPDATE(w15, w12, w7, w1); R3(c, d, e, a, b, w15);
WUPDATE( w0, w13, w8, w2); R3(b, c, d, e, a, w0);
WUPDATE( w1, w14, w9, w3); R3(a, b, c, d, e, w1);
WUPDATE( w2, w15, w10, w4); R3(e, a, b, c, d, w2);
WUPDATE( w3, w0, w11, w5); R3(d, e, a, b, c, w3);
WUPDATE( w4, w1, w12, w6); R3(c, d, e, a, b, w4);
WUPDATE( w5, w2, w13, w7); R3(b, c, d, e, a, w5);
WUPDATE( w6, w3, w14, w8); R3(a, b, c, d, e, w6);
WUPDATE( w7, w4, w15, w9); R3(e, a, b, c, d, w7);
WUPDATE( w8, w5, w0, w10); R3(d, e, a, b, c, w8);
WUPDATE( w9, w6, w1, w11); R3(c, d, e, a, b, w9);
WUPDATE(w10, w7, w2, w12); R3(b, c, d, e, a, w10);
WUPDATE(w11, w8, w3, w13); R3(a, b, c, d, e, w11);
WUPDATE(w12, w9, w4, w14); R4(e, a, b, c, d, w12);
WUPDATE(w13, w10, w5, w15); R4(d, e, a, b, c, w13);
WUPDATE(w14, w11, w6, w0); R4(c, d, e, a, b, w14);
WUPDATE(w15, w12, w7, w1); R4(b, c, d, e, a, w15);
WUPDATE( w0, w13, w8, w2); R4(a, b, c, d, e, w0);
WUPDATE( w1, w14, w9, w3); R4(e, a, b, c, d, w1);
WUPDATE( w2, w15, w10, w4); R4(d, e, a, b, c, w2);
WUPDATE( w3, w0, w11, w5); R4(c, d, e, a, b, w3);
WUPDATE( w4, w1, w12, w6); R4(b, c, d, e, a, w4);
WUPDATE( w5, w2, w13, w7); R4(a, b, c, d, e, w5);
WUPDATE( w6, w3, w14, w8); R4(e, a, b, c, d, w6);
WUPDATE( w7, w4, w15, w9); R4(d, e, a, b, c, w7);
WUPDATE( w8, w5, w0, w10); R4(c, d, e, a, b, w8);
WUPDATE( w9, w6, w1, w11); R4(b, c, d, e, a, w9);
WUPDATE(w10, w7, w2, w12); R4(a, b, c, d, e, w10);
WUPDATE(w11, w8, w3, w13); R4(e, a, b, c, d, w11);
WUPDATE(w12, w9, w4, w14); R4(d, e, a, b, c, w12);
WUPDATE(w13, w10, w5, w15); R4(c, d, e, a, b, w13);
WUPDATE(w14, w11, w6, w0); R4(b, c, d, e, a, w14);
WUPDATE(w15, w12, w7, w1); R4(a, b, c, d, e, w15);
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
w15 = w14 = w13 = w12 = w11 = w10 = w9 = w8 = 0;
w7 = w6 = w5 = w4 = w3 = w2 = w1 = w0 = 0;
}