Fixed issue #2495: "Show Reflog" dialog shows empty action for "push" entries
[TortoiseGit.git] / src / TortoisePlink / SSHSHA.C
blob8d8b5e2d70066eb62541b060561954037130133f
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
14 #define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) )\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
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
31 #ifdef RANDOM_DIAGNOSTICS\r
32     {\r
33         extern int random_diagnostics;\r
34         if (random_diagnostics) {\r
35             int i;\r
36             printf("SHATransform:");\r
37             for (i = 0; i < 5; i++)\r
38                 printf(" %08x", digest[i]);\r
39             printf(" +");\r
40             for (i = 0; i < 16; i++)\r
41                 printf(" %08x", block[i]);\r
42         }\r
43     }\r
44 #endif\r
46     for (t = 0; t < 16; t++)\r
47         w[t] = block[t];\r
49     for (t = 16; t < 80; t++) {\r
50         word32 tmp = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];\r
51         w[t] = rol(tmp, 1);\r
52     }\r
54     a = digest[0];\r
55     b = digest[1];\r
56     c = digest[2];\r
57     d = digest[3];\r
58     e = digest[4];\r
60     for (t = 0; t < 20; t++) {\r
61         word32 tmp =\r
62             rol(a, 5) + ((b & c) | (d & ~b)) + e + w[t] + 0x5a827999;\r
63         e = d;\r
64         d = c;\r
65         c = rol(b, 30);\r
66         b = a;\r
67         a = tmp;\r
68     }\r
69     for (t = 20; t < 40; t++) {\r
70         word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0x6ed9eba1;\r
71         e = d;\r
72         d = c;\r
73         c = rol(b, 30);\r
74         b = a;\r
75         a = tmp;\r
76     }\r
77     for (t = 40; t < 60; t++) {\r
78         word32 tmp = rol(a,\r
79                          5) + ((b & c) | (b & d) | (c & d)) + e + w[t] +\r
80             0x8f1bbcdc;\r
81         e = d;\r
82         d = c;\r
83         c = rol(b, 30);\r
84         b = a;\r
85         a = tmp;\r
86     }\r
87     for (t = 60; t < 80; t++) {\r
88         word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0xca62c1d6;\r
89         e = d;\r
90         d = c;\r
91         c = rol(b, 30);\r
92         b = a;\r
93         a = tmp;\r
94     }\r
96     digest[0] += a;\r
97     digest[1] += b;\r
98     digest[2] += c;\r
99     digest[3] += d;\r
100     digest[4] += e;\r
102 #ifdef RANDOM_DIAGNOSTICS\r
103     {\r
104         extern int random_diagnostics;\r
105         if (random_diagnostics) {\r
106             int i;\r
107             printf(" =");\r
108             for (i = 0; i < 5; i++)\r
109                 printf(" %08x", digest[i]);\r
110             printf("\n");\r
111         }\r
112     }\r
113 #endif\r
116 /* ----------------------------------------------------------------------\r
117  * Outer SHA algorithm: take an arbitrary length byte string,\r
118  * convert it into 16-word blocks with the prescribed padding at\r
119  * the end, and pass those blocks to the core SHA algorithm.\r
120  */\r
122 void SHA_Init(SHA_State * s)\r
124     SHA_Core_Init(s->h);\r
125     s->blkused = 0;\r
126     s->lenhi = s->lenlo = 0;\r
129 void SHA_Bytes(SHA_State * s, const void *p, int len)\r
131     const unsigned char *q = (const unsigned char *) p;\r
132     uint32 wordblock[16];\r
133     uint32 lenw = len;\r
134     int i;\r
136     /*\r
137      * Update the length field.\r
138      */\r
139     s->lenlo += lenw;\r
140     s->lenhi += (s->lenlo < lenw);\r
142     if (s->blkused && s->blkused + len < 64) {\r
143         /*\r
144          * Trivial case: just add to the block.\r
145          */\r
146         memcpy(s->block + s->blkused, q, len);\r
147         s->blkused += len;\r
148     } else {\r
149         /*\r
150          * We must complete and process at least one block.\r
151          */\r
152         while (s->blkused + len >= 64) {\r
153             memcpy(s->block + s->blkused, q, 64 - s->blkused);\r
154             q += 64 - s->blkused;\r
155             len -= 64 - s->blkused;\r
156             /* Now process the block. Gather bytes big-endian into words */\r
157             for (i = 0; i < 16; i++) {\r
158                 wordblock[i] =\r
159                     (((uint32) s->block[i * 4 + 0]) << 24) |\r
160                     (((uint32) s->block[i * 4 + 1]) << 16) |\r
161                     (((uint32) s->block[i * 4 + 2]) << 8) |\r
162                     (((uint32) s->block[i * 4 + 3]) << 0);\r
163             }\r
164             SHATransform(s->h, wordblock);\r
165             s->blkused = 0;\r
166         }\r
167         memcpy(s->block, q, len);\r
168         s->blkused = len;\r
169     }\r
172 void SHA_Final(SHA_State * s, unsigned char *output)\r
174     int i;\r
175     int pad;\r
176     unsigned char c[64];\r
177     uint32 lenhi, lenlo;\r
179     if (s->blkused >= 56)\r
180         pad = 56 + 64 - s->blkused;\r
181     else\r
182         pad = 56 - s->blkused;\r
184     lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));\r
185     lenlo = (s->lenlo << 3);\r
187     memset(c, 0, pad);\r
188     c[0] = 0x80;\r
189     SHA_Bytes(s, &c, pad);\r
191     c[0] = (lenhi >> 24) & 0xFF;\r
192     c[1] = (lenhi >> 16) & 0xFF;\r
193     c[2] = (lenhi >> 8) & 0xFF;\r
194     c[3] = (lenhi >> 0) & 0xFF;\r
195     c[4] = (lenlo >> 24) & 0xFF;\r
196     c[5] = (lenlo >> 16) & 0xFF;\r
197     c[6] = (lenlo >> 8) & 0xFF;\r
198     c[7] = (lenlo >> 0) & 0xFF;\r
200     SHA_Bytes(s, &c, 8);\r
202     for (i = 0; i < 5; i++) {\r
203         output[i * 4] = (s->h[i] >> 24) & 0xFF;\r
204         output[i * 4 + 1] = (s->h[i] >> 16) & 0xFF;\r
205         output[i * 4 + 2] = (s->h[i] >> 8) & 0xFF;\r
206         output[i * 4 + 3] = (s->h[i]) & 0xFF;\r
207     }\r
210 void SHA_Simple(const void *p, int len, unsigned char *output)\r
212     SHA_State s;\r
214     SHA_Init(&s);\r
215     SHA_Bytes(&s, p, len);\r
216     SHA_Final(&s, output);\r
219 /*\r
220  * Thin abstraction for things where hashes are pluggable.\r
221  */\r
223 static void *sha1_init(void)\r
225     SHA_State *s;\r
227     s = snew(SHA_State);\r
228     SHA_Init(s);\r
229     return s;\r
232 static void sha1_bytes(void *handle, void *p, int len)\r
234     SHA_State *s = handle;\r
236     SHA_Bytes(s, p, len);\r
239 static void sha1_final(void *handle, unsigned char *output)\r
241     SHA_State *s = handle;\r
243     SHA_Final(s, output);\r
244     sfree(s);\r
247 const struct ssh_hash ssh_sha1 = {\r
248     sha1_init, sha1_bytes, sha1_final, 20, "SHA-1"\r
249 };\r
251 /* ----------------------------------------------------------------------\r
252  * The above is the SHA-1 algorithm itself. Now we implement the\r
253  * HMAC wrapper on it.\r
254  */\r
256 static void *sha1_make_context(void)\r
258     return snewn(3, SHA_State);\r
261 static void sha1_free_context(void *handle)\r
263     sfree(handle);\r
266 static void sha1_key_internal(void *handle, unsigned char *key, int len)\r
268     SHA_State *keys = (SHA_State *)handle;\r
269     unsigned char foo[64];\r
270     int i;\r
272     memset(foo, 0x36, 64);\r
273     for (i = 0; i < len && i < 64; i++)\r
274         foo[i] ^= key[i];\r
275     SHA_Init(&keys[0]);\r
276     SHA_Bytes(&keys[0], foo, 64);\r
278     memset(foo, 0x5C, 64);\r
279     for (i = 0; i < len && i < 64; i++)\r
280         foo[i] ^= key[i];\r
281     SHA_Init(&keys[1]);\r
282     SHA_Bytes(&keys[1], foo, 64);\r
284     smemclr(foo, 64);                  /* burn the evidence */\r
287 static void sha1_key(void *handle, unsigned char *key)\r
289     sha1_key_internal(handle, key, 20);\r
292 static void sha1_key_buggy(void *handle, unsigned char *key)\r
294     sha1_key_internal(handle, key, 16);\r
297 static void hmacsha1_start(void *handle)\r
299     SHA_State *keys = (SHA_State *)handle;\r
301     keys[2] = keys[0];                /* structure copy */\r
304 static void hmacsha1_bytes(void *handle, unsigned char const *blk, int len)\r
306     SHA_State *keys = (SHA_State *)handle;\r
307     SHA_Bytes(&keys[2], (void *)blk, len);\r
310 static void hmacsha1_genresult(void *handle, unsigned char *hmac)\r
312     SHA_State *keys = (SHA_State *)handle;\r
313     SHA_State s;\r
314     unsigned char intermediate[20];\r
316     s = keys[2];                       /* structure copy */\r
317     SHA_Final(&s, intermediate);\r
318     s = keys[1];                       /* structure copy */\r
319     SHA_Bytes(&s, intermediate, 20);\r
320     SHA_Final(&s, hmac);\r
323 static void sha1_do_hmac(void *handle, unsigned char *blk, int len,\r
324                          unsigned long seq, unsigned char *hmac)\r
326     unsigned char seqbuf[4];\r
328     PUT_32BIT_MSB_FIRST(seqbuf, seq);\r
329     hmacsha1_start(handle);\r
330     hmacsha1_bytes(handle, seqbuf, 4);\r
331     hmacsha1_bytes(handle, blk, len);\r
332     hmacsha1_genresult(handle, hmac);\r
335 static void sha1_generate(void *handle, unsigned char *blk, int len,\r
336                           unsigned long seq)\r
338     sha1_do_hmac(handle, blk, len, seq, blk + len);\r
341 static int hmacsha1_verresult(void *handle, unsigned char const *hmac)\r
343     unsigned char correct[20];\r
344     hmacsha1_genresult(handle, correct);\r
345     return !memcmp(correct, hmac, 20);\r
348 static int sha1_verify(void *handle, unsigned char *blk, int len,\r
349                        unsigned long seq)\r
351     unsigned char correct[20];\r
352     sha1_do_hmac(handle, blk, len, seq, correct);\r
353     return !memcmp(correct, blk + len, 20);\r
356 static void hmacsha1_96_genresult(void *handle, unsigned char *hmac)\r
358     unsigned char full[20];\r
359     hmacsha1_genresult(handle, full);\r
360     memcpy(hmac, full, 12);\r
363 static void sha1_96_generate(void *handle, unsigned char *blk, int len,\r
364                              unsigned long seq)\r
366     unsigned char full[20];\r
367     sha1_do_hmac(handle, blk, len, seq, full);\r
368     memcpy(blk + len, full, 12);\r
371 static int hmacsha1_96_verresult(void *handle, unsigned char const *hmac)\r
373     unsigned char correct[20];\r
374     hmacsha1_genresult(handle, correct);\r
375     return !memcmp(correct, hmac, 12);\r
378 static int sha1_96_verify(void *handle, unsigned char *blk, int len,\r
379                        unsigned long seq)\r
381     unsigned char correct[20];\r
382     sha1_do_hmac(handle, blk, len, seq, correct);\r
383     return !memcmp(correct, blk + len, 12);\r
386 void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,\r
387                       unsigned char *output) {\r
388     SHA_State states[2];\r
389     unsigned char intermediate[20];\r
391     sha1_key_internal(states, key, keylen);\r
392     SHA_Bytes(&states[0], data, datalen);\r
393     SHA_Final(&states[0], intermediate);\r
395     SHA_Bytes(&states[1], intermediate, 20);\r
396     SHA_Final(&states[1], output);\r
399 const struct ssh_mac ssh_hmac_sha1 = {\r
400     sha1_make_context, sha1_free_context, sha1_key,\r
401     sha1_generate, sha1_verify,\r
402     hmacsha1_start, hmacsha1_bytes, hmacsha1_genresult, hmacsha1_verresult,\r
403     "hmac-sha1",\r
404     20,\r
405     "HMAC-SHA1"\r
406 };\r
408 const struct ssh_mac ssh_hmac_sha1_96 = {\r
409     sha1_make_context, sha1_free_context, sha1_key,\r
410     sha1_96_generate, sha1_96_verify,\r
411     hmacsha1_start, hmacsha1_bytes,\r
412     hmacsha1_96_genresult, hmacsha1_96_verresult,\r
413     "hmac-sha1-96",\r
414     12,\r
415     "HMAC-SHA1-96"\r
416 };\r
418 const struct ssh_mac ssh_hmac_sha1_buggy = {\r
419     sha1_make_context, sha1_free_context, sha1_key_buggy,\r
420     sha1_generate, sha1_verify,\r
421     hmacsha1_start, hmacsha1_bytes, hmacsha1_genresult, hmacsha1_verresult,\r
422     "hmac-sha1",\r
423     20,\r
424     "bug-compatible HMAC-SHA1"\r
425 };\r
427 const struct ssh_mac ssh_hmac_sha1_96_buggy = {\r
428     sha1_make_context, sha1_free_context, sha1_key_buggy,\r
429     sha1_96_generate, sha1_96_verify,\r
430     hmacsha1_start, hmacsha1_bytes,\r
431     hmacsha1_96_genresult, hmacsha1_96_verresult,\r
432     "hmac-sha1-96",\r
433     12,\r
434     "bug-compatible HMAC-SHA1-96"\r
435 };\r