xref: /inferno-os/libsec/port/sha2.c (revision e57c7e16a3789cd4de1a3c2560d49b1ee39cd10a)
1 #include "os.h"
2 #include <libsec.h>
3 
4 extern void _sha256block(SHA256state*, uchar*);
5 extern void _sha512block(SHA512state*, uchar*);
6 
7 u32int sha224h0[] = {
8 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
9 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
10 };
11 u32int sha256h0[] = {
12 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
13 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
14 };
15 
16 u64int sha384h0[] = {
17 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
18 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL,
19 };
20 u64int sha512h0[] = {
21 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
22 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL,
23 };
24 
25 
26 static SHA256state *
27 sha256init(void)
28 {
29 	SHA256state *s;
30 
31 	s = malloc(sizeof(*s));
32 	if(s == nil)
33 		return nil;
34 	s->malloced = 1;
35 	s->seeded = 0;
36 	s->len = 0;
37 	s->blen = 0;
38 
39 	return s;
40 }
41 
42 static void
43 p32(u32int v, uchar *p)
44 {
45 	p[0] = v>>24;
46 	p[1] = v>>16;
47 	p[2] = v>>8;
48 	p[3] = v>>0;
49 }
50 
51 static void
52 p64(u64int v, uchar *p)
53 {
54 	p32(v>>32, p);
55 	p32(v, p+4);
56 }
57 
58 enum {
59 	HI	= 0,
60 	LO	= 1,
61 };
62 static void
63 p128(u64int v[2], uchar *p)
64 {
65 	p64(v[HI], p);
66 	p64(v[LO], p+8);
67 }
68 
69 static void
70 uvvadd(u64int v[2], int n)
71 {
72 	v[LO] += n;
73 	if(v[LO] < n)  /* overflow */
74 		v[HI]++;
75 }
76 
77 static void
78 uvvmult8(u64int v[2])
79 {
80 	v[HI] = (v[HI]<<3) | (v[LO] >> (64-3));
81 	v[LO] <<= 3;
82 }
83 
84 
85 static void
86 _sha256(uchar *p, ulong len, SHA256state *s)
87 {
88 	u32int take;
89 
90 	/* complete possible partial block from last time */
91 	if(s->blen > 0 && s->blen+len >= SHA256bsize) {
92 		take = SHA256bsize-s->blen;
93 		memmove(s->buf+s->blen, p, take);
94 		p += take;
95 		len -= take;
96 		_sha256block(s, s->buf);
97 		s->len += SHA256bsize;
98 		s->blen = 0;
99 		memset(s->buf, 0, SHA256bsize);
100 	}
101 	/* whole blocks */
102 	while(len >= SHA256bsize) {
103 		_sha256block(s, p);
104 		s->len += SHA256bsize;
105 		p += SHA256bsize;
106 		len -= SHA256bsize;
107 	}
108 	/* keep possible leftover bytes */
109 	if(len > 0) {
110 		memmove(s->buf+s->blen, p, len);
111 		s->blen += len;
112 	}
113 }
114 
115 static void
116 sha256finish(SHA256state *s, uchar *digest, int smaller)
117 {
118 	int i;
119 	uchar end[SHA256bsize+8];
120 	u32int nzero, nb, nd;
121 
122 	nzero = (2*SHA256bsize - s->blen - 1 - 8) % SHA256bsize;
123 	end[0] = 0x80;
124 	memset(end+1, 0, nzero);
125 	nb = 8*(s->len+s->blen);
126 	p64(nb, end+1+nzero);
127 	_sha256(end, 1+nzero+8, s);
128 
129 	nd = SHA256dlen/4;
130 	if(smaller)
131 		nd = SHA224dlen/4;
132 	for(i = 0; i < nd; i++, digest += 4)
133 		p32(s->h32[i], digest);
134 }
135 
136 static SHA256state*
137 sha256x(uchar *p, ulong len, uchar *digest, SHA256state *s, int smaller)
138 {
139 	if(s == nil) {
140 		s = sha256init();
141 		if(s == nil)
142 			return nil;
143 	}
144 
145 	if(s->seeded == 0){
146 		memmove(s->h32, smaller? sha224h0: sha256h0, sizeof s->h32);
147 		s->seeded = 1;
148 	}
149 
150 	_sha256(p, len, s);
151 
152 	if(digest == 0)
153 		return s;
154 
155 	sha256finish(s, digest, smaller);
156 	if(s->malloced == 1)
157 		free(s);
158 	return nil;
159 }
160 
161 SHA256state*
162 sha224(uchar *p, ulong len, uchar *digest, SHA256state *s)
163 {
164 	return sha256x(p, len, digest, s, 1);
165 }
166 
167 SHA256state*
168 sha256(uchar *p, ulong len, uchar *digest, SHA256state *s)
169 {
170 	return sha256x(p, len, digest, s, 0);
171 }
172 
173 
174 static SHA512state *
175 sha512init(void)
176 {
177 	SHA512state *s;
178 
179 	s = malloc(sizeof(*s));
180 	if(s == nil)
181 		return nil;
182 	s->malloced = 1;
183 	s->seeded = 0;
184 	s->nb128[HI] = 0;
185 	s->nb128[LO] = 0;
186 	s->blen = 0;
187 
188 	return s;
189 }
190 
191 static void
192 _sha512(uchar *p, ulong len, SHA512state *s)
193 {
194 	u32int take;
195 
196 	/* complete possible partial block from last time */
197 	if(s->blen > 0 && s->blen+len >= SHA512bsize) {
198 		take = SHA512bsize-s->blen;
199 		memmove(s->buf+s->blen, p, take);
200 		p += take;
201 		len -= take;
202 		_sha512block(s, s->buf);
203 		uvvadd(s->nb128, SHA512bsize);
204 		s->blen = 0;
205 		memset(s->buf, 0, SHA512bsize);
206 	}
207 	/* whole blocks */
208 	while(len >= SHA512bsize) {
209 		_sha512block(s, p);
210 		uvvadd(s->nb128, SHA512bsize);
211 		p += SHA512bsize;
212 		len -= SHA512bsize;
213 	}
214 	/* keep possible leftover bytes */
215 	if(len > 0) {
216 		memmove(s->buf+s->blen, p, len);
217 		s->blen += len;
218 	}
219 }
220 
221 void
222 sha512finish(SHA512state *s, uchar *digest, int smaller)
223 {
224 	int i;
225 	uchar end[SHA512bsize+16];
226 	u32int nzero, n;
227 	u64int nb[2];
228 
229 	nzero = (2*SHA512bsize - s->blen - 1 - 16) % SHA512bsize;
230 	end[0] = 0x80;
231 	memset(end+1, 0, nzero);
232 	nb[0] = s->nb128[0];
233 	nb[1] = s->nb128[1];
234 	uvvadd(nb, s->blen);
235 	uvvmult8(nb);
236 	p128(nb, end+1+nzero);
237 	_sha512(end, 1+nzero+16, s);
238 
239 	n = SHA512dlen/8;
240 	if(smaller)
241 		n = SHA384dlen/8;
242 	for(i = 0; i < n; i++, digest += 8)
243 		p64(s->h64[i], digest);
244 }
245 
246 static SHA512state*
247 sha512x(uchar *p, ulong len, uchar *digest, SHA512state *s, int smaller)
248 {
249 	if(s == nil) {
250 		s = sha512init();
251 		if(s == nil)
252 			return nil;
253 	}
254 
255 	if(s->seeded == 0){
256 		memmove(s->h64, smaller? sha384h0: sha512h0, sizeof s->h64);
257 		s->seeded = 1;
258 	}
259 
260 	_sha512(p, len, s);
261 
262 	if(digest == 0)
263 		return s;
264 
265 	sha512finish(s, digest, smaller);
266 	if(s->malloced == 1)
267 		free(s);
268 	return nil;
269 }
270 
271 SHA512state*
272 sha384(uchar *p, ulong len, uchar *digest, SHA512state *s)
273 {
274 	return sha512x(p, len, digest, s, 1);
275 }
276 
277 SHA512state*
278 sha512(uchar *p, ulong len, uchar *digest, SHA512state *s)
279 {
280 	return sha512x(p, len, digest, s, 0);
281 }
282