OSDN Git Service

Add support for 64 bit Windows.
[ffftp/ffftp.git] / putty / SSHSHA.C
1 /*\r
2  * SHA1 hash algorithm. Used in SSH-2 as a MAC, and the transform is\r
3  * also used as a `stirring' function for the PuTTY random number\r
4  * pool. Implemented directly from the specification by Simon\r
5  * Tatham.\r
6  */\r
7 \r
8 #include "ssh.h"\r
9 \r
10 /* ----------------------------------------------------------------------\r
11  * Core SHA algorithm: processes 16-word blocks into a message digest.\r
12  */\r
13 \r
14 #define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) )\r
15 \r
16 static void SHA_Core_Init(uint32 h[5])\r
17 {\r
18     h[0] = 0x67452301;\r
19     h[1] = 0xefcdab89;\r
20     h[2] = 0x98badcfe;\r
21     h[3] = 0x10325476;\r
22     h[4] = 0xc3d2e1f0;\r
23 }\r
24 \r
25 void SHATransform(word32 * digest, word32 * block)\r
26 {\r
27     word32 w[80];\r
28     word32 a, b, c, d, e;\r
29     int t;\r
30 \r
31     for (t = 0; t < 16; t++)\r
32         w[t] = block[t];\r
33 \r
34     for (t = 16; t < 80; t++) {\r
35         word32 tmp = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];\r
36         w[t] = rol(tmp, 1);\r
37     }\r
38 \r
39     a = digest[0];\r
40     b = digest[1];\r
41     c = digest[2];\r
42     d = digest[3];\r
43     e = digest[4];\r
44 \r
45     for (t = 0; t < 20; t++) {\r
46         word32 tmp =\r
47             rol(a, 5) + ((b & c) | (d & ~b)) + e + w[t] + 0x5a827999;\r
48         e = d;\r
49         d = c;\r
50         c = rol(b, 30);\r
51         b = a;\r
52         a = tmp;\r
53     }\r
54     for (t = 20; t < 40; t++) {\r
55         word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0x6ed9eba1;\r
56         e = d;\r
57         d = c;\r
58         c = rol(b, 30);\r
59         b = a;\r
60         a = tmp;\r
61     }\r
62     for (t = 40; t < 60; t++) {\r
63         word32 tmp = rol(a,\r
64                          5) + ((b & c) | (b & d) | (c & d)) + e + w[t] +\r
65             0x8f1bbcdc;\r
66         e = d;\r
67         d = c;\r
68         c = rol(b, 30);\r
69         b = a;\r
70         a = tmp;\r
71     }\r
72     for (t = 60; t < 80; t++) {\r
73         word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0xca62c1d6;\r
74         e = d;\r
75         d = c;\r
76         c = rol(b, 30);\r
77         b = a;\r
78         a = tmp;\r
79     }\r
80 \r
81     digest[0] += a;\r
82     digest[1] += b;\r
83     digest[2] += c;\r
84     digest[3] += d;\r
85     digest[4] += e;\r
86 }\r
87 \r
88 /* ----------------------------------------------------------------------\r
89  * Outer SHA algorithm: take an arbitrary length byte string,\r
90  * convert it into 16-word blocks with the prescribed padding at\r
91  * the end, and pass those blocks to the core SHA algorithm.\r
92  */\r
93 \r
94 void SHA_Init(SHA_State * s)\r
95 {\r
96     SHA_Core_Init(s->h);\r
97     s->blkused = 0;\r
98     s->lenhi = s->lenlo = 0;\r
99 }\r
100 \r
101 void SHA_Bytes(SHA_State * s, void *p, int len)\r
102 {\r
103     unsigned char *q = (unsigned char *) p;\r
104     uint32 wordblock[16];\r
105     uint32 lenw = len;\r
106     int i;\r
107 \r
108     /*\r
109      * Update the length field.\r
110      */\r
111     s->lenlo += lenw;\r
112     s->lenhi += (s->lenlo < lenw);\r
113 \r
114     if (s->blkused && s->blkused + len < 64) {\r
115         /*\r
116          * Trivial case: just add to the block.\r
117          */\r
118         memcpy(s->block + s->blkused, q, len);\r
119         s->blkused += len;\r
120     } else {\r
121         /*\r
122          * We must complete and process at least one block.\r
123          */\r
124         while (s->blkused + len >= 64) {\r
125             memcpy(s->block + s->blkused, q, 64 - s->blkused);\r
126             q += 64 - s->blkused;\r
127             len -= 64 - s->blkused;\r
128             /* Now process the block. Gather bytes big-endian into words */\r
129             for (i = 0; i < 16; i++) {\r
130                 wordblock[i] =\r
131                     (((uint32) s->block[i * 4 + 0]) << 24) |\r
132                     (((uint32) s->block[i * 4 + 1]) << 16) |\r
133                     (((uint32) s->block[i * 4 + 2]) << 8) |\r
134                     (((uint32) s->block[i * 4 + 3]) << 0);\r
135             }\r
136             SHATransform(s->h, wordblock);\r
137             s->blkused = 0;\r
138         }\r
139         memcpy(s->block, q, len);\r
140         s->blkused = len;\r
141     }\r
142 }\r
143 \r
144 void SHA_Final(SHA_State * s, unsigned char *output)\r
145 {\r
146     int i;\r
147     int pad;\r
148     unsigned char c[64];\r
149     uint32 lenhi, lenlo;\r
150 \r
151     if (s->blkused >= 56)\r
152         pad = 56 + 64 - s->blkused;\r
153     else\r
154         pad = 56 - s->blkused;\r
155 \r
156     lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));\r
157     lenlo = (s->lenlo << 3);\r
158 \r
159     memset(c, 0, pad);\r
160     c[0] = 0x80;\r
161     SHA_Bytes(s, &c, pad);\r
162 \r
163     c[0] = (lenhi >> 24) & 0xFF;\r
164     c[1] = (lenhi >> 16) & 0xFF;\r
165     c[2] = (lenhi >> 8) & 0xFF;\r
166     c[3] = (lenhi >> 0) & 0xFF;\r
167     c[4] = (lenlo >> 24) & 0xFF;\r
168     c[5] = (lenlo >> 16) & 0xFF;\r
169     c[6] = (lenlo >> 8) & 0xFF;\r
170     c[7] = (lenlo >> 0) & 0xFF;\r
171 \r
172     SHA_Bytes(s, &c, 8);\r
173 \r
174     for (i = 0; i < 5; i++) {\r
175         output[i * 4] = (s->h[i] >> 24) & 0xFF;\r
176         output[i * 4 + 1] = (s->h[i] >> 16) & 0xFF;\r
177         output[i * 4 + 2] = (s->h[i] >> 8) & 0xFF;\r
178         output[i * 4 + 3] = (s->h[i]) & 0xFF;\r
179     }\r
180 }\r
181 \r
182 void SHA_Simple(void *p, int len, unsigned char *output)\r
183 {\r
184     SHA_State s;\r
185 \r
186     SHA_Init(&s);\r
187     SHA_Bytes(&s, p, len);\r
188     SHA_Final(&s, output);\r
189 }\r
190 \r
191 /*\r
192  * Thin abstraction for things where hashes are pluggable.\r
193  */\r
194 \r
195 static void *sha1_init(void)\r
196 {\r
197     SHA_State *s;\r
198 \r
199     s = snew(SHA_State);\r
200     SHA_Init(s);\r
201     return s;\r
202 }\r
203 \r
204 static void sha1_bytes(void *handle, void *p, int len)\r
205 {\r
206     SHA_State *s = handle;\r
207 \r
208     SHA_Bytes(s, p, len);\r
209 }\r
210 \r
211 static void sha1_final(void *handle, unsigned char *output)\r
212 {\r
213     SHA_State *s = handle;\r
214 \r
215     SHA_Final(s, output);\r
216     sfree(s);\r
217 }\r
218 \r
219 const struct ssh_hash ssh_sha1 = {\r
220     sha1_init, sha1_bytes, sha1_final, 20, "SHA-1"\r
221 };\r
222 \r
223 /* ----------------------------------------------------------------------\r
224  * The above is the SHA-1 algorithm itself. Now we implement the\r
225  * HMAC wrapper on it.\r
226  */\r
227 \r
228 static void *sha1_make_context(void)\r
229 {\r
230     return snewn(3, SHA_State);\r
231 }\r
232 \r
233 static void sha1_free_context(void *handle)\r
234 {\r
235     sfree(handle);\r
236 }\r
237 \r
238 static void sha1_key_internal(void *handle, unsigned char *key, int len)\r
239 {\r
240     SHA_State *keys = (SHA_State *)handle;\r
241     unsigned char foo[64];\r
242     int i;\r
243 \r
244     memset(foo, 0x36, 64);\r
245     for (i = 0; i < len && i < 64; i++)\r
246         foo[i] ^= key[i];\r
247     SHA_Init(&keys[0]);\r
248     SHA_Bytes(&keys[0], foo, 64);\r
249 \r
250     memset(foo, 0x5C, 64);\r
251     for (i = 0; i < len && i < 64; i++)\r
252         foo[i] ^= key[i];\r
253     SHA_Init(&keys[1]);\r
254     SHA_Bytes(&keys[1], foo, 64);\r
255 \r
256     memset(foo, 0, 64);                /* burn the evidence */\r
257 }\r
258 \r
259 static void sha1_key(void *handle, unsigned char *key)\r
260 {\r
261     sha1_key_internal(handle, key, 20);\r
262 }\r
263 \r
264 static void sha1_key_buggy(void *handle, unsigned char *key)\r
265 {\r
266     sha1_key_internal(handle, key, 16);\r
267 }\r
268 \r
269 static void hmacsha1_start(void *handle)\r
270 {\r
271     SHA_State *keys = (SHA_State *)handle;\r
272 \r
273     keys[2] = keys[0];                /* structure copy */\r
274 }\r
275 \r
276 static void hmacsha1_bytes(void *handle, unsigned char const *blk, int len)\r
277 {\r
278     SHA_State *keys = (SHA_State *)handle;\r
279     SHA_Bytes(&keys[2], (void *)blk, len);\r
280 }\r
281 \r
282 static void hmacsha1_genresult(void *handle, unsigned char *hmac)\r
283 {\r
284     SHA_State *keys = (SHA_State *)handle;\r
285     SHA_State s;\r
286     unsigned char intermediate[20];\r
287 \r
288     s = keys[2];                       /* structure copy */\r
289     SHA_Final(&s, intermediate);\r
290     s = keys[1];                       /* structure copy */\r
291     SHA_Bytes(&s, intermediate, 20);\r
292     SHA_Final(&s, hmac);\r
293 }\r
294 \r
295 static void sha1_do_hmac(void *handle, unsigned char *blk, int len,\r
296                          unsigned long seq, unsigned char *hmac)\r
297 {\r
298     unsigned char seqbuf[4];\r
299 \r
300     seqbuf[0] = (unsigned char) ((seq >> 24) & 0xFF);\r
301     seqbuf[1] = (unsigned char) ((seq >> 16) & 0xFF);\r
302     seqbuf[2] = (unsigned char) ((seq >> 8) & 0xFF);\r
303     seqbuf[3] = (unsigned char) ((seq) & 0xFF);\r
304 \r
305     hmacsha1_start(handle);\r
306     hmacsha1_bytes(handle, seqbuf, 4);\r
307     hmacsha1_bytes(handle, blk, len);\r
308     hmacsha1_genresult(handle, hmac);\r
309 }\r
310 \r
311 static void sha1_generate(void *handle, unsigned char *blk, int len,\r
312                           unsigned long seq)\r
313 {\r
314     sha1_do_hmac(handle, blk, len, seq, blk + len);\r
315 }\r
316 \r
317 static int hmacsha1_verresult(void *handle, unsigned char const *hmac)\r
318 {\r
319     unsigned char correct[20];\r
320     hmacsha1_genresult(handle, correct);\r
321     return !memcmp(correct, hmac, 20);\r
322 }\r
323 \r
324 static int sha1_verify(void *handle, unsigned char *blk, int len,\r
325                        unsigned long seq)\r
326 {\r
327     unsigned char correct[20];\r
328     sha1_do_hmac(handle, blk, len, seq, correct);\r
329     return !memcmp(correct, blk + len, 20);\r
330 }\r
331 \r
332 static void hmacsha1_96_genresult(void *handle, unsigned char *hmac)\r
333 {\r
334     unsigned char full[20];\r
335     hmacsha1_genresult(handle, full);\r
336     memcpy(hmac, full, 12);\r
337 }\r
338 \r
339 static void sha1_96_generate(void *handle, unsigned char *blk, int len,\r
340                              unsigned long seq)\r
341 {\r
342     unsigned char full[20];\r
343     sha1_do_hmac(handle, blk, len, seq, full);\r
344     memcpy(blk + len, full, 12);\r
345 }\r
346 \r
347 static int hmacsha1_96_verresult(void *handle, unsigned char const *hmac)\r
348 {\r
349     unsigned char correct[20];\r
350     hmacsha1_genresult(handle, correct);\r
351     return !memcmp(correct, hmac, 12);\r
352 }\r
353 \r
354 static int sha1_96_verify(void *handle, unsigned char *blk, int len,\r
355                        unsigned long seq)\r
356 {\r
357     unsigned char correct[20];\r
358     sha1_do_hmac(handle, blk, len, seq, correct);\r
359     return !memcmp(correct, blk + len, 12);\r
360 }\r
361 \r
362 void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,\r
363                       unsigned char *output) {\r
364     SHA_State states[2];\r
365     unsigned char intermediate[20];\r
366 \r
367     sha1_key_internal(states, key, keylen);\r
368     SHA_Bytes(&states[0], data, datalen);\r
369     SHA_Final(&states[0], intermediate);\r
370 \r
371     SHA_Bytes(&states[1], intermediate, 20);\r
372     SHA_Final(&states[1], output);\r
373 }\r
374 \r
375 const struct ssh_mac ssh_hmac_sha1 = {\r
376     sha1_make_context, sha1_free_context, sha1_key,\r
377     sha1_generate, sha1_verify,\r
378     hmacsha1_start, hmacsha1_bytes, hmacsha1_genresult, hmacsha1_verresult,\r
379     "hmac-sha1",\r
380     20,\r
381     "HMAC-SHA1"\r
382 };\r
383 \r
384 const struct ssh_mac ssh_hmac_sha1_96 = {\r
385     sha1_make_context, sha1_free_context, sha1_key,\r
386     sha1_96_generate, sha1_96_verify,\r
387     hmacsha1_start, hmacsha1_bytes,\r
388     hmacsha1_96_genresult, hmacsha1_96_verresult,\r
389     "hmac-sha1-96",\r
390     12,\r
391     "HMAC-SHA1-96"\r
392 };\r
393 \r
394 const struct ssh_mac ssh_hmac_sha1_buggy = {\r
395     sha1_make_context, sha1_free_context, sha1_key_buggy,\r
396     sha1_generate, sha1_verify,\r
397     hmacsha1_start, hmacsha1_bytes, hmacsha1_genresult, hmacsha1_verresult,\r
398     "hmac-sha1",\r
399     20,\r
400     "bug-compatible HMAC-SHA1"\r
401 };\r
402 \r
403 const struct ssh_mac ssh_hmac_sha1_96_buggy = {\r
404     sha1_make_context, sha1_free_context, sha1_key_buggy,\r
405     sha1_96_generate, sha1_96_verify,\r
406     hmacsha1_start, hmacsha1_bytes,\r
407     hmacsha1_96_genresult, hmacsha1_96_verresult,\r
408     "hmac-sha1-96",\r
409     12,\r
410     "bug-compatible HMAC-SHA1-96"\r
411 };\r