xref: /plan9/sys/src/libsec/port/sha2_128.c (revision 7bc319fb0923feebf3ecec8ba4171959fa2265e2)
1*7bc319fbSDavid du Colombier /*
2*7bc319fbSDavid du Colombier  * sha2 128-bit
3*7bc319fbSDavid du Colombier  */
4*7bc319fbSDavid du Colombier #include <u.h>
5*7bc319fbSDavid du Colombier #include <libc.h>
6*7bc319fbSDavid du Colombier #include <libsec.h>
7*7bc319fbSDavid du Colombier 
8*7bc319fbSDavid du Colombier static void encode64(uchar*, u64int*, ulong);
9*7bc319fbSDavid du Colombier static DigestState* sha2_128(uchar *, ulong, uchar *, SHA2_256state *, int);
10*7bc319fbSDavid du Colombier 
11*7bc319fbSDavid du Colombier extern void _sha2block128(uchar*, ulong, u64int*);
12*7bc319fbSDavid du Colombier 
13*7bc319fbSDavid du Colombier /*
14*7bc319fbSDavid du Colombier  *  for sha2_384 and sha2_512, len must be multiple of 128 for all but
15*7bc319fbSDavid du Colombier  *  the last call.  There must be room in the input buffer to pad.
16*7bc319fbSDavid du Colombier  *
17*7bc319fbSDavid du Colombier  *  Note: sha2_384 calls sha2_512block as sha2_384; it just uses a different
18*7bc319fbSDavid du Colombier  *  initial seed to produce a truncated 384b hash result.  otherwise
19*7bc319fbSDavid du Colombier  *  it's the same as sha2_512.
20*7bc319fbSDavid du Colombier  */
21*7bc319fbSDavid du Colombier SHA2_384state*
sha2_384(uchar * p,ulong len,uchar * digest,SHA2_384state * s)22*7bc319fbSDavid du Colombier sha2_384(uchar *p, ulong len, uchar *digest, SHA2_384state *s)
23*7bc319fbSDavid du Colombier {
24*7bc319fbSDavid du Colombier 	if(s == nil) {
25*7bc319fbSDavid du Colombier 		s = mallocz(sizeof(*s), 1);
26*7bc319fbSDavid du Colombier 		if(s == nil)
27*7bc319fbSDavid du Colombier 			return nil;
28*7bc319fbSDavid du Colombier 		s->malloced = 1;
29*7bc319fbSDavid du Colombier 	}
30*7bc319fbSDavid du Colombier 	if(s->seeded == 0){
31*7bc319fbSDavid du Colombier 		/*
32*7bc319fbSDavid du Colombier 		 * seed the state with the first 64 bits of the fractional
33*7bc319fbSDavid du Colombier 		 * parts of the square roots of the 9th thru 16th primes.
34*7bc319fbSDavid du Colombier 		 */
35*7bc319fbSDavid du Colombier  		s->bstate[0] = 0xcbbb9d5dc1059ed8LL;
36*7bc319fbSDavid du Colombier 		s->bstate[1] = 0x629a292a367cd507LL;
37*7bc319fbSDavid du Colombier 		s->bstate[2] = 0x9159015a3070dd17LL;
38*7bc319fbSDavid du Colombier 		s->bstate[3] = 0x152fecd8f70e5939LL;
39*7bc319fbSDavid du Colombier 		s->bstate[4] = 0x67332667ffc00b31LL;
40*7bc319fbSDavid du Colombier 		s->bstate[5] = 0x8eb44a8768581511LL;
41*7bc319fbSDavid du Colombier 		s->bstate[6] = 0xdb0c2e0d64f98fa7LL;
42*7bc319fbSDavid du Colombier 		s->bstate[7] = 0x47b5481dbefa4fa4LL;
43*7bc319fbSDavid du Colombier 		s->seeded = 1;
44*7bc319fbSDavid du Colombier 	}
45*7bc319fbSDavid du Colombier 	return sha2_128(p, len, digest, s, SHA2_384dlen);
46*7bc319fbSDavid du Colombier }
47*7bc319fbSDavid du Colombier 
48*7bc319fbSDavid du Colombier SHA2_512state*
sha2_512(uchar * p,ulong len,uchar * digest,SHA2_512state * s)49*7bc319fbSDavid du Colombier sha2_512(uchar *p, ulong len, uchar *digest, SHA2_512state *s)
50*7bc319fbSDavid du Colombier {
51*7bc319fbSDavid du Colombier 
52*7bc319fbSDavid du Colombier 	if(s == nil) {
53*7bc319fbSDavid du Colombier 		s = mallocz(sizeof(*s), 1);
54*7bc319fbSDavid du Colombier 		if(s == nil)
55*7bc319fbSDavid du Colombier 			return nil;
56*7bc319fbSDavid du Colombier 		s->malloced = 1;
57*7bc319fbSDavid du Colombier 	}
58*7bc319fbSDavid du Colombier 	if(s->seeded == 0){
59*7bc319fbSDavid du Colombier 		/*
60*7bc319fbSDavid du Colombier 		 * seed the state with the first 64 bits of the fractional
61*7bc319fbSDavid du Colombier 		 * parts of the square roots of the first 8 primes 2..19).
62*7bc319fbSDavid du Colombier 		 */
63*7bc319fbSDavid du Colombier  		s->bstate[0] = 0x6a09e667f3bcc908LL;
64*7bc319fbSDavid du Colombier 		s->bstate[1] = 0xbb67ae8584caa73bLL;
65*7bc319fbSDavid du Colombier 		s->bstate[2] = 0x3c6ef372fe94f82bLL;
66*7bc319fbSDavid du Colombier 		s->bstate[3] = 0xa54ff53a5f1d36f1LL;
67*7bc319fbSDavid du Colombier 		s->bstate[4] = 0x510e527fade682d1LL;
68*7bc319fbSDavid du Colombier 		s->bstate[5] = 0x9b05688c2b3e6c1fLL;
69*7bc319fbSDavid du Colombier 		s->bstate[6] = 0x1f83d9abfb41bd6bLL;
70*7bc319fbSDavid du Colombier 		s->bstate[7] = 0x5be0cd19137e2179LL;
71*7bc319fbSDavid du Colombier 		s->seeded = 1;
72*7bc319fbSDavid du Colombier 	}
73*7bc319fbSDavid du Colombier 	return sha2_128(p, len, digest, s, SHA2_512dlen);
74*7bc319fbSDavid du Colombier }
75*7bc319fbSDavid du Colombier 
76*7bc319fbSDavid du Colombier /* common 128 byte block padding and count code for SHA2_384 and SHA2_512 */
77*7bc319fbSDavid du Colombier static DigestState*
sha2_128(uchar * p,ulong len,uchar * digest,SHA2_512state * s,int dlen)78*7bc319fbSDavid du Colombier sha2_128(uchar *p, ulong len, uchar *digest, SHA2_512state *s, int dlen)
79*7bc319fbSDavid du Colombier {
80*7bc319fbSDavid du Colombier 	int i;
81*7bc319fbSDavid du Colombier 	u64int x[16];
82*7bc319fbSDavid du Colombier 	uchar buf[256];
83*7bc319fbSDavid du Colombier 	uchar *e;
84*7bc319fbSDavid du Colombier 
85*7bc319fbSDavid du Colombier 	/* fill out the partial 128 byte block from previous calls */
86*7bc319fbSDavid du Colombier 	if(s->blen){
87*7bc319fbSDavid du Colombier 		i = 128 - s->blen;
88*7bc319fbSDavid du Colombier 		if(len < i)
89*7bc319fbSDavid du Colombier 			i = len;
90*7bc319fbSDavid du Colombier 		memmove(s->buf + s->blen, p, i);
91*7bc319fbSDavid du Colombier 		len -= i;
92*7bc319fbSDavid du Colombier 		s->blen += i;
93*7bc319fbSDavid du Colombier 		p += i;
94*7bc319fbSDavid du Colombier 		if(s->blen == 128){
95*7bc319fbSDavid du Colombier 			_sha2block128(s->buf, s->blen, s->bstate);
96*7bc319fbSDavid du Colombier 			s->len += s->blen;
97*7bc319fbSDavid du Colombier 			s->blen = 0;
98*7bc319fbSDavid du Colombier 		}
99*7bc319fbSDavid du Colombier 	}
100*7bc319fbSDavid du Colombier 
101*7bc319fbSDavid du Colombier 	/* do 128 byte blocks */
102*7bc319fbSDavid du Colombier 	i = len & ~(128-1);
103*7bc319fbSDavid du Colombier 	if(i){
104*7bc319fbSDavid du Colombier 		_sha2block128(p, i, s->bstate);
105*7bc319fbSDavid du Colombier 		s->len += i;
106*7bc319fbSDavid du Colombier 		len -= i;
107*7bc319fbSDavid du Colombier 		p += i;
108*7bc319fbSDavid du Colombier 	}
109*7bc319fbSDavid du Colombier 
110*7bc319fbSDavid du Colombier 	/* save the left overs if not last call */
111*7bc319fbSDavid du Colombier 	if(digest == 0){
112*7bc319fbSDavid du Colombier 		if(len){
113*7bc319fbSDavid du Colombier 			memmove(s->buf, p, len);
114*7bc319fbSDavid du Colombier 			s->blen += len;
115*7bc319fbSDavid du Colombier 		}
116*7bc319fbSDavid du Colombier 		return s;
117*7bc319fbSDavid du Colombier 	}
118*7bc319fbSDavid du Colombier 
119*7bc319fbSDavid du Colombier 	/*
120*7bc319fbSDavid du Colombier 	 *  this is the last time through, pad what's left with 0x80,
121*7bc319fbSDavid du Colombier 	 *  0's, and the input count to create a multiple of 128 bytes.
122*7bc319fbSDavid du Colombier 	 */
123*7bc319fbSDavid du Colombier 	if(s->blen){
124*7bc319fbSDavid du Colombier 		p = s->buf;
125*7bc319fbSDavid du Colombier 		len = s->blen;
126*7bc319fbSDavid du Colombier 	} else {
127*7bc319fbSDavid du Colombier 		memmove(buf, p, len);
128*7bc319fbSDavid du Colombier 		p = buf;
129*7bc319fbSDavid du Colombier 	}
130*7bc319fbSDavid du Colombier 	s->len += len;
131*7bc319fbSDavid du Colombier 	e = p + len;
132*7bc319fbSDavid du Colombier 	if(len < 112)
133*7bc319fbSDavid du Colombier 		i = 112 - len;
134*7bc319fbSDavid du Colombier 	else
135*7bc319fbSDavid du Colombier 		i = 240 - len;
136*7bc319fbSDavid du Colombier 	memset(e, 0, i);
137*7bc319fbSDavid du Colombier 	*e = 0x80;
138*7bc319fbSDavid du Colombier 	len += i;
139*7bc319fbSDavid du Colombier 
140*7bc319fbSDavid du Colombier 	/* append the count */
141*7bc319fbSDavid du Colombier 	x[0] = 0;			/* assume 32b length, i.e. < 4GB */
142*7bc319fbSDavid du Colombier 	x[1] = s->len<<3;
143*7bc319fbSDavid du Colombier 	encode64(p+len, x, 16);
144*7bc319fbSDavid du Colombier 
145*7bc319fbSDavid du Colombier 	/* digest the last part */
146*7bc319fbSDavid du Colombier 	_sha2block128(p, len+16, s->bstate);
147*7bc319fbSDavid du Colombier 	s->len += len+16;
148*7bc319fbSDavid du Colombier 
149*7bc319fbSDavid du Colombier 	/* return result and free state */
150*7bc319fbSDavid du Colombier 	encode64(digest, s->bstate, dlen);
151*7bc319fbSDavid du Colombier 	if(s->malloced == 1)
152*7bc319fbSDavid du Colombier 		free(s);
153*7bc319fbSDavid du Colombier 	return nil;
154*7bc319fbSDavid du Colombier }
155*7bc319fbSDavid du Colombier 
156*7bc319fbSDavid du Colombier /*
157*7bc319fbSDavid du Colombier  * Encodes input (ulong long) into output (uchar).
158*7bc319fbSDavid du Colombier  * Assumes len is a multiple of 8.
159*7bc319fbSDavid du Colombier  */
160*7bc319fbSDavid du Colombier static void
encode64(uchar * output,u64int * input,ulong len)161*7bc319fbSDavid du Colombier encode64(uchar *output, u64int *input, ulong len)
162*7bc319fbSDavid du Colombier {
163*7bc319fbSDavid du Colombier 	u64int x;
164*7bc319fbSDavid du Colombier 	uchar *e;
165*7bc319fbSDavid du Colombier 
166*7bc319fbSDavid du Colombier 	for(e = output + len; output < e;) {
167*7bc319fbSDavid du Colombier 		x = *input++;
168*7bc319fbSDavid du Colombier 		*output++ = x >> 56;
169*7bc319fbSDavid du Colombier 		*output++ = x >> 48;
170*7bc319fbSDavid du Colombier 		*output++ = x >> 40;
171*7bc319fbSDavid du Colombier 		*output++ = x >> 32;
172*7bc319fbSDavid du Colombier 		*output++ = x >> 24;
173*7bc319fbSDavid du Colombier 		*output++ = x >> 16;
174*7bc319fbSDavid du Colombier 		*output++ = x >> 8;
175*7bc319fbSDavid du Colombier 		*output++ = x;
176*7bc319fbSDavid du Colombier 	}
177*7bc319fbSDavid du Colombier }
178*7bc319fbSDavid du Colombier 
179*7bc319fbSDavid du Colombier DigestState*
hmac_sha2_384(uchar * p,ulong len,uchar * key,ulong klen,uchar * digest,DigestState * s)180*7bc319fbSDavid du Colombier hmac_sha2_384(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
181*7bc319fbSDavid du Colombier 	DigestState *s)
182*7bc319fbSDavid du Colombier {
183*7bc319fbSDavid du Colombier 	return hmac_x(p, len, key, klen, digest, s, sha2_384, SHA2_384dlen);
184*7bc319fbSDavid du Colombier }
185*7bc319fbSDavid du Colombier 
186*7bc319fbSDavid du Colombier DigestState*
hmac_sha2_512(uchar * p,ulong len,uchar * key,ulong klen,uchar * digest,DigestState * s)187*7bc319fbSDavid du Colombier hmac_sha2_512(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest,
188*7bc319fbSDavid du Colombier 	DigestState *s)
189*7bc319fbSDavid du Colombier {
190*7bc319fbSDavid du Colombier 	return hmac_x(p, len, key, klen, digest, s, sha2_512, SHA2_512dlen);
191*7bc319fbSDavid du Colombier }
192