xref: /plan9-contrib/sys/src/cmd/unix/drawterm/libsec/sha1.c (revision 9b943567965ba040fd275927fbe088656eb8ce4f)
1*9b943567SDavid du Colombier #include "../lib9.h"
2*9b943567SDavid du Colombier #include "../libsec/libsec.h"
3*9b943567SDavid du Colombier 
4*9b943567SDavid du Colombier static void encode(uchar*, u32int*, ulong);
5*9b943567SDavid du Colombier 
6*9b943567SDavid du Colombier extern void _sha1block(uchar*, ulong, u32int*);
7*9b943567SDavid du Colombier 
8*9b943567SDavid du Colombier /*
9*9b943567SDavid du Colombier  *  we require len to be a multiple of 64 for all but
10*9b943567SDavid du Colombier  *  the last call.  There must be room in the input buffer
11*9b943567SDavid du Colombier  *  to pad.
12*9b943567SDavid du Colombier  */
13*9b943567SDavid du Colombier SHA1state*
14*9b943567SDavid du Colombier sha1(uchar *p, ulong len, uchar *digest, SHA1state *s)
15*9b943567SDavid du Colombier {
16*9b943567SDavid du Colombier 	uchar buf[128];
17*9b943567SDavid du Colombier 	u32int x[16];
18*9b943567SDavid du Colombier 	int i;
19*9b943567SDavid du Colombier 	uchar *e;
20*9b943567SDavid du Colombier 
21*9b943567SDavid du Colombier 	if(s == nil){
22*9b943567SDavid du Colombier 		s = malloc(sizeof(*s));
23*9b943567SDavid du Colombier 		if(s == nil)
24*9b943567SDavid du Colombier 			return nil;
25*9b943567SDavid du Colombier 		memset(s, 0, sizeof(*s));
26*9b943567SDavid du Colombier 		s->malloced = 1;
27*9b943567SDavid du Colombier 	}
28*9b943567SDavid du Colombier 
29*9b943567SDavid du Colombier 	if(s->seeded == 0){
30*9b943567SDavid du Colombier 		/* seed the state, these constants would look nicer big-endian */
31*9b943567SDavid du Colombier 		s->state[0] = 0x67452301;
32*9b943567SDavid du Colombier 		s->state[1] = 0xefcdab89;
33*9b943567SDavid du Colombier 		s->state[2] = 0x98badcfe;
34*9b943567SDavid du Colombier 		s->state[3] = 0x10325476;
35*9b943567SDavid du Colombier 		s->state[4] = 0xc3d2e1f0;
36*9b943567SDavid du Colombier 		s->seeded = 1;
37*9b943567SDavid du Colombier 	}
38*9b943567SDavid du Colombier 
39*9b943567SDavid du Colombier 	/* fill out the partial 64 byte block from previous calls */
40*9b943567SDavid du Colombier 	if(s->blen){
41*9b943567SDavid du Colombier 		i = 64 - s->blen;
42*9b943567SDavid du Colombier 		if(len < i)
43*9b943567SDavid du Colombier 			i = len;
44*9b943567SDavid du Colombier 		memmove(s->buf + s->blen, p, i);
45*9b943567SDavid du Colombier 		len -= i;
46*9b943567SDavid du Colombier 		s->blen += i;
47*9b943567SDavid du Colombier 		p += i;
48*9b943567SDavid du Colombier 		if(s->blen == 64){
49*9b943567SDavid du Colombier 			_sha1block(s->buf, s->blen, s->state);
50*9b943567SDavid du Colombier 			s->len += s->blen;
51*9b943567SDavid du Colombier 			s->blen = 0;
52*9b943567SDavid du Colombier 		}
53*9b943567SDavid du Colombier 	}
54*9b943567SDavid du Colombier 
55*9b943567SDavid du Colombier 	/* do 64 byte blocks */
56*9b943567SDavid du Colombier 	i = len & ~0x3f;
57*9b943567SDavid du Colombier 	if(i){
58*9b943567SDavid du Colombier 		_sha1block(p, i, s->state);
59*9b943567SDavid du Colombier 		s->len += i;
60*9b943567SDavid du Colombier 		len -= i;
61*9b943567SDavid du Colombier 		p += i;
62*9b943567SDavid du Colombier 	}
63*9b943567SDavid du Colombier 
64*9b943567SDavid du Colombier 	/* save the left overs if not last call */
65*9b943567SDavid du Colombier 	if(digest == 0){
66*9b943567SDavid du Colombier 		if(len){
67*9b943567SDavid du Colombier 			memmove(s->buf, p, len);
68*9b943567SDavid du Colombier 			s->blen += len;
69*9b943567SDavid du Colombier 		}
70*9b943567SDavid du Colombier 		return s;
71*9b943567SDavid du Colombier 	}
72*9b943567SDavid du Colombier 
73*9b943567SDavid du Colombier 	/*
74*9b943567SDavid du Colombier 	 *  this is the last time through, pad what's left with 0x80,
75*9b943567SDavid du Colombier 	 *  0's, and the input count to create a multiple of 64 bytes
76*9b943567SDavid du Colombier 	 */
77*9b943567SDavid du Colombier 	if(s->blen){
78*9b943567SDavid du Colombier 		p = s->buf;
79*9b943567SDavid du Colombier 		len = s->blen;
80*9b943567SDavid du Colombier 	} else {
81*9b943567SDavid du Colombier 		memmove(buf, p, len);
82*9b943567SDavid du Colombier 		p = buf;
83*9b943567SDavid du Colombier 	}
84*9b943567SDavid du Colombier 	s->len += len;
85*9b943567SDavid du Colombier 	e = p + len;
86*9b943567SDavid du Colombier 	if(len < 56)
87*9b943567SDavid du Colombier 		i = 56 - len;
88*9b943567SDavid du Colombier 	else
89*9b943567SDavid du Colombier 		i = 120 - len;
90*9b943567SDavid du Colombier 	memset(e, 0, i);
91*9b943567SDavid du Colombier 	*e = 0x80;
92*9b943567SDavid du Colombier 	len += i;
93*9b943567SDavid du Colombier 
94*9b943567SDavid du Colombier 	/* append the count */
95*9b943567SDavid du Colombier 	x[0] = s->len>>29;
96*9b943567SDavid du Colombier 	x[1] = s->len<<3;
97*9b943567SDavid du Colombier 	encode(p+len, x, 8);
98*9b943567SDavid du Colombier 
99*9b943567SDavid du Colombier 	/* digest the last part */
100*9b943567SDavid du Colombier 	_sha1block(p, len+8, s->state);
101*9b943567SDavid du Colombier 	s->len += len+8;
102*9b943567SDavid du Colombier 
103*9b943567SDavid du Colombier 	/* return result and free state */
104*9b943567SDavid du Colombier 	encode(digest, s->state, SHA1dlen);
105*9b943567SDavid du Colombier 	if(s->malloced == 1)
106*9b943567SDavid du Colombier 		free(s);
107*9b943567SDavid du Colombier 	return nil;
108*9b943567SDavid du Colombier }
109*9b943567SDavid du Colombier 
110*9b943567SDavid du Colombier /*
111*9b943567SDavid du Colombier  *	encodes input (ulong) into output (uchar). Assumes len is
112*9b943567SDavid du Colombier  *	a multiple of 4.
113*9b943567SDavid du Colombier  */
114*9b943567SDavid du Colombier static void
115*9b943567SDavid du Colombier encode(uchar *output, u32int *input, ulong len)
116*9b943567SDavid du Colombier {
117*9b943567SDavid du Colombier 	u32int x;
118*9b943567SDavid du Colombier 	uchar *e;
119*9b943567SDavid du Colombier 
120*9b943567SDavid du Colombier 	for(e = output + len; output < e;) {
121*9b943567SDavid du Colombier 		x = *input++;
122*9b943567SDavid du Colombier 		*output++ = x >> 24;
123*9b943567SDavid du Colombier 		*output++ = x >> 16;
124*9b943567SDavid du Colombier 		*output++ = x >> 8;
125*9b943567SDavid du Colombier 		*output++ = x;
126*9b943567SDavid du Colombier 	}
127*9b943567SDavid du Colombier }
128