xref: /plan9/sys/src/libsec/port/sha1.c (revision ff55b41d4e9d2c13b36de2101465a357b4133185)
180ee5cbfSDavid du Colombier #include "os.h"
280ee5cbfSDavid du Colombier #include <libsec.h>
380ee5cbfSDavid du Colombier 
480ee5cbfSDavid du Colombier static void encode(uchar*, u32int*, ulong);
580ee5cbfSDavid du Colombier 
680ee5cbfSDavid du Colombier extern void _sha1block(uchar*, ulong, u32int*);
780ee5cbfSDavid du Colombier 
880ee5cbfSDavid du Colombier /*
980ee5cbfSDavid du Colombier  *  we require len to be a multiple of 64 for all but
1080ee5cbfSDavid du Colombier  *  the last call.  There must be room in the input buffer
1180ee5cbfSDavid du Colombier  *  to pad.
1280ee5cbfSDavid du Colombier  */
1380ee5cbfSDavid du Colombier SHA1state*
sha1(uchar * p,ulong len,uchar * digest,SHA1state * s)1480ee5cbfSDavid du Colombier sha1(uchar *p, ulong len, uchar *digest, SHA1state *s)
1580ee5cbfSDavid du Colombier {
1680ee5cbfSDavid du Colombier 	uchar buf[128];
1780ee5cbfSDavid du Colombier 	u32int x[16];
1880ee5cbfSDavid du Colombier 	int i;
1980ee5cbfSDavid du Colombier 	uchar *e;
2080ee5cbfSDavid du Colombier 
2180ee5cbfSDavid du Colombier 	if(s == nil){
2280ee5cbfSDavid du Colombier 		s = malloc(sizeof(*s));
2380ee5cbfSDavid du Colombier 		if(s == nil)
2480ee5cbfSDavid du Colombier 			return nil;
2580ee5cbfSDavid du Colombier 		memset(s, 0, sizeof(*s));
2680ee5cbfSDavid du Colombier 		s->malloced = 1;
2780ee5cbfSDavid du Colombier 	}
2880ee5cbfSDavid du Colombier 
2980ee5cbfSDavid du Colombier 	if(s->seeded == 0){
3080ee5cbfSDavid du Colombier 		/* seed the state, these constants would look nicer big-endian */
3180ee5cbfSDavid du Colombier 		s->state[0] = 0x67452301;
3280ee5cbfSDavid du Colombier 		s->state[1] = 0xefcdab89;
3380ee5cbfSDavid du Colombier 		s->state[2] = 0x98badcfe;
3480ee5cbfSDavid du Colombier 		s->state[3] = 0x10325476;
3580ee5cbfSDavid du Colombier 		s->state[4] = 0xc3d2e1f0;
3680ee5cbfSDavid du Colombier 		s->seeded = 1;
3780ee5cbfSDavid du Colombier 	}
3880ee5cbfSDavid du Colombier 
3980ee5cbfSDavid du Colombier 	/* fill out the partial 64 byte block from previous calls */
4080ee5cbfSDavid du Colombier 	if(s->blen){
4180ee5cbfSDavid du Colombier 		i = 64 - s->blen;
4280ee5cbfSDavid du Colombier 		if(len < i)
4380ee5cbfSDavid du Colombier 			i = len;
4480ee5cbfSDavid du Colombier 		memmove(s->buf + s->blen, p, i);
4580ee5cbfSDavid du Colombier 		len -= i;
4680ee5cbfSDavid du Colombier 		s->blen += i;
4780ee5cbfSDavid du Colombier 		p += i;
4880ee5cbfSDavid du Colombier 		if(s->blen == 64){
4980ee5cbfSDavid du Colombier 			_sha1block(s->buf, s->blen, s->state);
5080ee5cbfSDavid du Colombier 			s->len += s->blen;
5180ee5cbfSDavid du Colombier 			s->blen = 0;
5280ee5cbfSDavid du Colombier 		}
5380ee5cbfSDavid du Colombier 	}
5480ee5cbfSDavid du Colombier 
5580ee5cbfSDavid du Colombier 	/* do 64 byte blocks */
5680ee5cbfSDavid du Colombier 	i = len & ~0x3f;
5780ee5cbfSDavid du Colombier 	if(i){
5880ee5cbfSDavid du Colombier 		_sha1block(p, i, s->state);
5980ee5cbfSDavid du Colombier 		s->len += i;
6080ee5cbfSDavid du Colombier 		len -= i;
6180ee5cbfSDavid du Colombier 		p += i;
6280ee5cbfSDavid du Colombier 	}
6380ee5cbfSDavid du Colombier 
6480ee5cbfSDavid du Colombier 	/* save the left overs if not last call */
6580ee5cbfSDavid du Colombier 	if(digest == 0){
6680ee5cbfSDavid du Colombier 		if(len){
6780ee5cbfSDavid du Colombier 			memmove(s->buf, p, len);
6880ee5cbfSDavid du Colombier 			s->blen += len;
6980ee5cbfSDavid du Colombier 		}
7080ee5cbfSDavid du Colombier 		return s;
7180ee5cbfSDavid du Colombier 	}
7280ee5cbfSDavid du Colombier 
7380ee5cbfSDavid du Colombier 	/*
7480ee5cbfSDavid du Colombier 	 *  this is the last time through, pad what's left with 0x80,
7580ee5cbfSDavid du Colombier 	 *  0's, and the input count to create a multiple of 64 bytes
7680ee5cbfSDavid du Colombier 	 */
7780ee5cbfSDavid du Colombier 	if(s->blen){
7880ee5cbfSDavid du Colombier 		p = s->buf;
7980ee5cbfSDavid du Colombier 		len = s->blen;
8080ee5cbfSDavid du Colombier 	} else {
8180ee5cbfSDavid du Colombier 		memmove(buf, p, len);
8280ee5cbfSDavid du Colombier 		p = buf;
8380ee5cbfSDavid du Colombier 	}
8480ee5cbfSDavid du Colombier 	s->len += len;
8580ee5cbfSDavid du Colombier 	e = p + len;
8680ee5cbfSDavid du Colombier 	if(len < 56)
8780ee5cbfSDavid du Colombier 		i = 56 - len;
8880ee5cbfSDavid du Colombier 	else
8980ee5cbfSDavid du Colombier 		i = 120 - len;
9080ee5cbfSDavid du Colombier 	memset(e, 0, i);
9180ee5cbfSDavid du Colombier 	*e = 0x80;
9280ee5cbfSDavid du Colombier 	len += i;
9380ee5cbfSDavid du Colombier 
9480ee5cbfSDavid du Colombier 	/* append the count */
9580ee5cbfSDavid du Colombier 	x[0] = s->len>>29;
9680ee5cbfSDavid du Colombier 	x[1] = s->len<<3;
9780ee5cbfSDavid du Colombier 	encode(p+len, x, 8);
9880ee5cbfSDavid du Colombier 
9980ee5cbfSDavid du Colombier 	/* digest the last part */
10080ee5cbfSDavid du Colombier 	_sha1block(p, len+8, s->state);
10180ee5cbfSDavid du Colombier 	s->len += len+8;
10280ee5cbfSDavid du Colombier 
10380ee5cbfSDavid du Colombier 	/* return result and free state */
10480ee5cbfSDavid du Colombier 	encode(digest, s->state, SHA1dlen);
10580ee5cbfSDavid du Colombier 	if(s->malloced == 1)
10680ee5cbfSDavid du Colombier 		free(s);
10780ee5cbfSDavid du Colombier 	return nil;
10880ee5cbfSDavid du Colombier }
10980ee5cbfSDavid du Colombier 
11080ee5cbfSDavid du Colombier /*
11180ee5cbfSDavid du Colombier  *	encodes input (ulong) into output (uchar). Assumes len is
11280ee5cbfSDavid du Colombier  *	a multiple of 4.
11380ee5cbfSDavid du Colombier  */
11480ee5cbfSDavid du Colombier static void
encode(uchar * output,u32int * input,ulong len)11580ee5cbfSDavid du Colombier encode(uchar *output, u32int *input, ulong len)
11680ee5cbfSDavid du Colombier {
11780ee5cbfSDavid du Colombier 	u32int x;
11880ee5cbfSDavid du Colombier 	uchar *e;
11980ee5cbfSDavid du Colombier 
12080ee5cbfSDavid du Colombier 	for(e = output + len; output < e;) {
12180ee5cbfSDavid du Colombier 		x = *input++;
12280ee5cbfSDavid du Colombier 		*output++ = x >> 24;
12380ee5cbfSDavid du Colombier 		*output++ = x >> 16;
12480ee5cbfSDavid du Colombier 		*output++ = x >> 8;
12580ee5cbfSDavid du Colombier 		*output++ = x;
12680ee5cbfSDavid du Colombier 	}
12780ee5cbfSDavid du Colombier }
128*ff55b41dSDavid du Colombier 
129*ff55b41dSDavid du Colombier DigestState*
hmac_sha1(uchar * p,ulong len,uchar * key,ulong klen,uchar * digest,DigestState * s)130*ff55b41dSDavid du Colombier hmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
131*ff55b41dSDavid du Colombier 	DigestState *s)
132*ff55b41dSDavid du Colombier {
133*ff55b41dSDavid du Colombier 	return hmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen);
134*ff55b41dSDavid du Colombier }
135