master xplshn/aruu / shared / libutil / sha1.c
  1/* public domain sha1 implementation based on rfc3174 and libtomcrypt */
  2#include <stdint.h>
  3#include <string.h>
  4
  5#include "../sha1.h"
  6
  7static uint32_t rol(uint32_t n, int k) { return (n << k) | (n >> (32-k)); }
  8#define F0(b,c,d) (d ^ (b & (c ^ d)))
  9#define F1(b,c,d) (b ^ c ^ d)
 10#define F2(b,c,d) ((b & c) | (d & (b | c)))
 11#define F3(b,c,d) (b ^ c ^ d)
 12#define G0(a,b,c,d,e,i) e += rol(a,5)+F0(b,c,d)+W[i]+0x5A827999; b = rol(b,30)
 13#define G1(a,b,c,d,e,i) e += rol(a,5)+F1(b,c,d)+W[i]+0x6ED9EBA1; b = rol(b,30)
 14#define G2(a,b,c,d,e,i) e += rol(a,5)+F2(b,c,d)+W[i]+0x8F1BBCDC; b = rol(b,30)
 15#define G3(a,b,c,d,e,i) e += rol(a,5)+F3(b,c,d)+W[i]+0xCA62C1D6; b = rol(b,30)
 16
 17static void
 18processblock(struct sha1 *s, const uint8_t *buf)
 19{
 20	uint32_t W[80], a, b, c, d, e;
 21	int i;
 22
 23	for (i = 0; i < 16; i++) {
 24		W[i] = (uint32_t)buf[4*i]<<24;
 25		W[i] |= (uint32_t)buf[4*i+1]<<16;
 26		W[i] |= (uint32_t)buf[4*i+2]<<8;
 27		W[i] |= buf[4*i+3];
 28	}
 29	for (; i < 80; i++)
 30		W[i] = rol(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
 31	a = s->h[0];
 32	b = s->h[1];
 33	c = s->h[2];
 34	d = s->h[3];
 35	e = s->h[4];
 36	for (i = 0; i < 20; ) {
 37		G0(a,b,c,d,e,i++);
 38		G0(e,a,b,c,d,i++);
 39		G0(d,e,a,b,c,i++);
 40		G0(c,d,e,a,b,i++);
 41		G0(b,c,d,e,a,i++);
 42	}
 43	while (i < 40) {
 44		G1(a,b,c,d,e,i++);
 45		G1(e,a,b,c,d,i++);
 46		G1(d,e,a,b,c,i++);
 47		G1(c,d,e,a,b,i++);
 48		G1(b,c,d,e,a,i++);
 49	}
 50	while (i < 60) {
 51		G2(a,b,c,d,e,i++);
 52		G2(e,a,b,c,d,i++);
 53		G2(d,e,a,b,c,i++);
 54		G2(c,d,e,a,b,i++);
 55		G2(b,c,d,e,a,i++);
 56	}
 57	while (i < 80) {
 58		G3(a,b,c,d,e,i++);
 59		G3(e,a,b,c,d,i++);
 60		G3(d,e,a,b,c,i++);
 61		G3(c,d,e,a,b,i++);
 62		G3(b,c,d,e,a,i++);
 63	}
 64	s->h[0] += a;
 65	s->h[1] += b;
 66	s->h[2] += c;
 67	s->h[3] += d;
 68	s->h[4] += e;
 69}
 70
 71static void
 72pad(struct sha1 *s)
 73{
 74	unsigned r = s->len % 64;
 75
 76	s->buf[r++] = 0x80;
 77	if (r > 56) {
 78		memset(s->buf + r, 0, 64 - r);
 79		r = 0;
 80		processblock(s, s->buf);
 81	}
 82	memset(s->buf + r, 0, 56 - r);
 83	s->len *= 8;
 84	s->buf[56] = s->len >> 56;
 85	s->buf[57] = s->len >> 48;
 86	s->buf[58] = s->len >> 40;
 87	s->buf[59] = s->len >> 32;
 88	s->buf[60] = s->len >> 24;
 89	s->buf[61] = s->len >> 16;
 90	s->buf[62] = s->len >> 8;
 91	s->buf[63] = s->len;
 92	processblock(s, s->buf);
 93}
 94
 95void
 96sha1_init(void *ctx)
 97{
 98	struct sha1 *s = ctx;
 99
100	s->len = 0;
101	s->h[0] = 0x67452301;
102	s->h[1] = 0xEFCDAB89;
103	s->h[2] = 0x98BADCFE;
104	s->h[3] = 0x10325476;
105	s->h[4] = 0xC3D2E1F0;
106}
107
108void
109sha1_sum(void *ctx, uint8_t md[SHA1_DIGEST_LENGTH])
110{
111	struct sha1 *s = ctx;
112	int i;
113
114	pad(s);
115	for (i = 0; i < 5; i++) {
116		md[4*i] = s->h[i] >> 24;
117		md[4*i+1] = s->h[i] >> 16;
118		md[4*i+2] = s->h[i] >> 8;
119		md[4*i+3] = s->h[i];
120	}
121}
122
123void
124sha1_update(void *ctx, const void *m, unsigned long len)
125{
126	struct sha1 *s = ctx;
127	const uint8_t *p = m;
128	unsigned r = s->len % 64;
129
130	s->len += len;
131	if (r) {
132		if (len < 64 - r) {
133			memcpy(s->buf + r, p, len);
134			return;
135		}
136		memcpy(s->buf + r, p, 64 - r);
137		len -= 64 - r;
138		p += 64 - r;
139		processblock(s, s->buf);
140	}
141	for (; len >= 64; len -= 64, p += 64)
142		processblock(s, p);
143	memcpy(s->buf, p, len);
144}