Sebastian Kuschel reports that pfd_closing can be called for a socket
[u/mdw/putty] / sshsh256.c
CommitLineData
062e5811 1/*
2 * SHA-256 algorithm as described at
3 *
4 * http://csrc.nist.gov/cryptval/shs.html
5 */
6
7#include "ssh.h"
8
9/* ----------------------------------------------------------------------
10 * Core SHA256 algorithm: processes 16-word blocks into a message digest.
11 */
12
13#define ror(x,y) ( ((x) << (32-y)) | (((uint32)(x)) >> (y)) )
14#define shr(x,y) ( (((uint32)(x)) >> (y)) )
15#define Ch(x,y,z) ( ((x) & (y)) ^ (~(x) & (z)) )
16#define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) )
17#define bigsigma0(x) ( ror((x),2) ^ ror((x),13) ^ ror((x),22) )
18#define bigsigma1(x) ( ror((x),6) ^ ror((x),11) ^ ror((x),25) )
19#define smallsigma0(x) ( ror((x),7) ^ ror((x),18) ^ shr((x),3) )
20#define smallsigma1(x) ( ror((x),17) ^ ror((x),19) ^ shr((x),10) )
21
22void SHA256_Core_Init(SHA256_State *s) {
23 s->h[0] = 0x6a09e667;
24 s->h[1] = 0xbb67ae85;
25 s->h[2] = 0x3c6ef372;
26 s->h[3] = 0xa54ff53a;
27 s->h[4] = 0x510e527f;
28 s->h[5] = 0x9b05688c;
29 s->h[6] = 0x1f83d9ab;
30 s->h[7] = 0x5be0cd19;
31}
32
33void SHA256_Block(SHA256_State *s, uint32 *block) {
34 uint32 w[80];
35 uint32 a,b,c,d,e,f,g,h;
36 static const int k[] = {
37 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
38 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
39 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
40 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
41 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
42 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
43 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
44 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
45 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
46 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
47 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
48 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
49 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
50 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
51 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
52 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
53 };
54
55 int t;
56
57 for (t = 0; t < 16; t++)
58 w[t] = block[t];
59
60 for (t = 16; t < 64; t++)
61 w[t] = smallsigma1(w[t-2]) + w[t-7] + smallsigma0(w[t-15]) + w[t-16];
62
63 a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3];
64 e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7];
65
66 for (t = 0; t < 64; t+=8) {
67 uint32 t1, t2;
68
69#define ROUND(j,a,b,c,d,e,f,g,h) \
70 t1 = h + bigsigma1(e) + Ch(e,f,g) + k[j] + w[j]; \
71 t2 = bigsigma0(a) + Maj(a,b,c); \
72 d = d + t1; h = t1 + t2;
73
74 ROUND(t+0, a,b,c,d,e,f,g,h);
75 ROUND(t+1, h,a,b,c,d,e,f,g);
76 ROUND(t+2, g,h,a,b,c,d,e,f);
77 ROUND(t+3, f,g,h,a,b,c,d,e);
78 ROUND(t+4, e,f,g,h,a,b,c,d);
79 ROUND(t+5, d,e,f,g,h,a,b,c);
80 ROUND(t+6, c,d,e,f,g,h,a,b);
81 ROUND(t+7, b,c,d,e,f,g,h,a);
82 }
83
84 s->h[0] += a; s->h[1] += b; s->h[2] += c; s->h[3] += d;
85 s->h[4] += e; s->h[5] += f; s->h[6] += g; s->h[7] += h;
86}
87
88/* ----------------------------------------------------------------------
89 * Outer SHA256 algorithm: take an arbitrary length byte string,
90 * convert it into 16-word blocks with the prescribed padding at
91 * the end, and pass those blocks to the core SHA256 algorithm.
92 */
93
94#define BLKSIZE 64
95
96void SHA256_Init(SHA256_State *s) {
97 SHA256_Core_Init(s);
98 s->blkused = 0;
99 s->lenhi = s->lenlo = 0;
100}
101
102void SHA256_Bytes(SHA256_State *s, const void *p, int len) {
103 unsigned char *q = (unsigned char *)p;
104 uint32 wordblock[16];
105 uint32 lenw = len;
106 int i;
107
108 /*
109 * Update the length field.
110 */
111 s->lenlo += lenw;
112 s->lenhi += (s->lenlo < lenw);
113
114 if (s->blkused && s->blkused+len < BLKSIZE) {
115 /*
116 * Trivial case: just add to the block.
117 */
118 memcpy(s->block + s->blkused, q, len);
119 s->blkused += len;
120 } else {
121 /*
122 * We must complete and process at least one block.
123 */
124 while (s->blkused + len >= BLKSIZE) {
125 memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
126 q += BLKSIZE - s->blkused;
127 len -= BLKSIZE - s->blkused;
128 /* Now process the block. Gather bytes big-endian into words */
129 for (i = 0; i < 16; i++) {
130 wordblock[i] =
131 ( ((uint32)s->block[i*4+0]) << 24 ) |
132 ( ((uint32)s->block[i*4+1]) << 16 ) |
133 ( ((uint32)s->block[i*4+2]) << 8 ) |
134 ( ((uint32)s->block[i*4+3]) << 0 );
135 }
136 SHA256_Block(s, wordblock);
137 s->blkused = 0;
138 }
139 memcpy(s->block, q, len);
140 s->blkused = len;
141 }
142}
143
144void SHA256_Final(SHA256_State *s, unsigned char *digest) {
145 int i;
146 int pad;
147 unsigned char c[64];
148 uint32 lenhi, lenlo;
149
150 if (s->blkused >= 56)
151 pad = 56 + 64 - s->blkused;
152 else
153 pad = 56 - s->blkused;
154
155 lenhi = (s->lenhi << 3) | (s->lenlo >> (32-3));
156 lenlo = (s->lenlo << 3);
157
158 memset(c, 0, pad);
159 c[0] = 0x80;
160 SHA256_Bytes(s, &c, pad);
161
162 c[0] = (lenhi >> 24) & 0xFF;
163 c[1] = (lenhi >> 16) & 0xFF;
164 c[2] = (lenhi >> 8) & 0xFF;
165 c[3] = (lenhi >> 0) & 0xFF;
166 c[4] = (lenlo >> 24) & 0xFF;
167 c[5] = (lenlo >> 16) & 0xFF;
168 c[6] = (lenlo >> 8) & 0xFF;
169 c[7] = (lenlo >> 0) & 0xFF;
170
171 SHA256_Bytes(s, &c, 8);
172
173 for (i = 0; i < 8; i++) {
174 digest[i*4+0] = (s->h[i] >> 24) & 0xFF;
175 digest[i*4+1] = (s->h[i] >> 16) & 0xFF;
176 digest[i*4+2] = (s->h[i] >> 8) & 0xFF;
177 digest[i*4+3] = (s->h[i] >> 0) & 0xFF;
178 }
179}
180
181void SHA256_Simple(const void *p, int len, unsigned char *output) {
182 SHA256_State s;
183
184 SHA256_Init(&s);
185 SHA256_Bytes(&s, p, len);
186 SHA256_Final(&s, output);
187}
188
189/*
190 * Thin abstraction for things where hashes are pluggable.
191 */
192
193static void *sha256_init(void)
194{
195 SHA256_State *s;
196
197 s = snew(SHA256_State);
198 SHA256_Init(s);
199 return s;
200}
201
202static void sha256_bytes(void *handle, void *p, int len)
203{
204 SHA256_State *s = handle;
205
206 SHA256_Bytes(s, p, len);
207}
208
209static void sha256_final(void *handle, unsigned char *output)
210{
211 SHA256_State *s = handle;
212
213 SHA256_Final(s, output);
214 sfree(s);
215}
216
217const struct ssh_hash ssh_sha256 = {
c6daaa1a 218 sha256_init, sha256_bytes, sha256_final, 32, "SHA-256"
062e5811 219};
220
23159902 221/* ----------------------------------------------------------------------
222 * The above is the SHA-256 algorithm itself. Now we implement the
223 * HMAC wrapper on it.
224 */
225
226static void *sha256_make_context(void)
227{
228 return snewn(3, SHA256_State);
229}
230
231static void sha256_free_context(void *handle)
232{
233 sfree(handle);
234}
235
236static void sha256_key_internal(void *handle, unsigned char *key, int len)
237{
238 SHA256_State *keys = (SHA256_State *)handle;
239 unsigned char foo[64];
240 int i;
241
242 memset(foo, 0x36, 64);
243 for (i = 0; i < len && i < 64; i++)
244 foo[i] ^= key[i];
245 SHA256_Init(&keys[0]);
246 SHA256_Bytes(&keys[0], foo, 64);
247
248 memset(foo, 0x5C, 64);
249 for (i = 0; i < len && i < 64; i++)
250 foo[i] ^= key[i];
251 SHA256_Init(&keys[1]);
252 SHA256_Bytes(&keys[1], foo, 64);
253
254 smemclr(foo, 64); /* burn the evidence */
255}
256
257static void sha256_key(void *handle, unsigned char *key)
258{
259 sha256_key_internal(handle, key, 32);
260}
261
262static void hmacsha256_start(void *handle)
263{
264 SHA256_State *keys = (SHA256_State *)handle;
265
266 keys[2] = keys[0]; /* structure copy */
267}
268
269static void hmacsha256_bytes(void *handle, unsigned char const *blk, int len)
270{
271 SHA256_State *keys = (SHA256_State *)handle;
272 SHA256_Bytes(&keys[2], (void *)blk, len);
273}
274
275static void hmacsha256_genresult(void *handle, unsigned char *hmac)
276{
277 SHA256_State *keys = (SHA256_State *)handle;
278 SHA256_State s;
279 unsigned char intermediate[32];
280
281 s = keys[2]; /* structure copy */
282 SHA256_Final(&s, intermediate);
283 s = keys[1]; /* structure copy */
284 SHA256_Bytes(&s, intermediate, 32);
285 SHA256_Final(&s, hmac);
286}
287
288static void sha256_do_hmac(void *handle, unsigned char *blk, int len,
289 unsigned long seq, unsigned char *hmac)
290{
291 unsigned char seqbuf[4];
292
293 PUT_32BIT_MSB_FIRST(seqbuf, seq);
294 hmacsha256_start(handle);
295 hmacsha256_bytes(handle, seqbuf, 4);
296 hmacsha256_bytes(handle, blk, len);
297 hmacsha256_genresult(handle, hmac);
298}
299
300static void sha256_generate(void *handle, unsigned char *blk, int len,
301 unsigned long seq)
302{
303 sha256_do_hmac(handle, blk, len, seq, blk + len);
304}
305
306static int hmacsha256_verresult(void *handle, unsigned char const *hmac)
307{
308 unsigned char correct[32];
309 hmacsha256_genresult(handle, correct);
310 return !memcmp(correct, hmac, 32);
311}
312
313static int sha256_verify(void *handle, unsigned char *blk, int len,
314 unsigned long seq)
315{
316 unsigned char correct[32];
317 sha256_do_hmac(handle, blk, len, seq, correct);
318 return !memcmp(correct, blk + len, 32);
319}
320
321const struct ssh_mac ssh_hmac_sha256 = {
322 sha256_make_context, sha256_free_context, sha256_key,
323 sha256_generate, sha256_verify,
324 hmacsha256_start, hmacsha256_bytes,
325 hmacsha256_genresult, hmacsha256_verresult,
326 "hmac-sha2-256",
327 32,
328 "HMAC-SHA-256"
329};
330
062e5811 331#ifdef TEST
332
333#include <stdio.h>
334#include <stdlib.h>
335#include <assert.h>
336
337int main(void) {
338 unsigned char digest[32];
339 int i, j, errors;
340
341 struct {
342 const char *teststring;
343 unsigned char digest[32];
344 } tests[] = {
345 { "abc", {
346 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
347 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
348 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
349 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
350 } },
351 { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", {
352 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
353 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
354 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
355 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
356 } },
357 };
358
359 errors = 0;
360
361 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
362 SHA256_Simple(tests[i].teststring,
363 strlen(tests[i].teststring), digest);
364 for (j = 0; j < 32; j++) {
365 if (digest[j] != tests[i].digest[j]) {
366 fprintf(stderr,
367 "\"%s\" digest byte %d should be 0x%02x, is 0x%02x\n",
368 tests[i].teststring, j, tests[i].digest[j], digest[j]);
369 errors++;
370 }
371 }
372 }
373
374 printf("%d errors\n", errors);
375
376 return 0;
377}
378
379#endif