Doc: Fix broken link
[TortoiseGit.git] / src / TortoisePlink / SSHSHA.C
blob97dd3e29547844036fde626b5391d506c784c694
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
217     smemclr(&s, sizeof(s));\r
220 /*\r
221  * Thin abstraction for things where hashes are pluggable.\r
222  */\r
224 static void *sha1_init(void)\r
226     SHA_State *s;\r
228     s = snew(SHA_State);\r
229     SHA_Init(s);\r
230     return s;\r
233 static void *sha1_copy(const void *vold)\r
235     const SHA_State *old = (const SHA_State *)vold;\r
236     SHA_State *s;\r
238     s = snew(SHA_State);\r
239     *s = *old;\r
240     return s;\r
243 static void sha1_free(void *handle)\r
245     SHA_State *s = handle;\r
247     smemclr(s, sizeof(*s));\r
248     sfree(s);\r
251 static void sha1_bytes(void *handle, const void *p, int len)\r
253     SHA_State *s = handle;\r
255     SHA_Bytes(s, p, len);\r
258 static void sha1_final(void *handle, unsigned char *output)\r
260     SHA_State *s = handle;\r
262     SHA_Final(s, output);\r
263     sha1_free(s);\r
266 const struct ssh_hash ssh_sha1 = {\r
267     sha1_init, sha1_copy, sha1_bytes, sha1_final, sha1_free, 20, "SHA-1"\r
268 };\r
270 /* ----------------------------------------------------------------------\r
271  * The above is the SHA-1 algorithm itself. Now we implement the\r
272  * HMAC wrapper on it.\r
273  */\r
275 static void *sha1_make_context(void *cipher_ctx)\r
277     return snewn(3, SHA_State);\r
280 static void sha1_free_context(void *handle)\r
282     smemclr(handle, 3 * sizeof(SHA_State));\r
283     sfree(handle);\r
286 static void sha1_key_internal(void *handle, unsigned char *key, int len)\r
288     SHA_State *keys = (SHA_State *)handle;\r
289     unsigned char foo[64];\r
290     int i;\r
292     memset(foo, 0x36, 64);\r
293     for (i = 0; i < len && i < 64; i++)\r
294         foo[i] ^= key[i];\r
295     SHA_Init(&keys[0]);\r
296     SHA_Bytes(&keys[0], foo, 64);\r
298     memset(foo, 0x5C, 64);\r
299     for (i = 0; i < len && i < 64; i++)\r
300         foo[i] ^= key[i];\r
301     SHA_Init(&keys[1]);\r
302     SHA_Bytes(&keys[1], foo, 64);\r
304     smemclr(foo, 64);                  /* burn the evidence */\r
307 static void sha1_key(void *handle, unsigned char *key)\r
309     sha1_key_internal(handle, key, 20);\r
312 static void sha1_key_buggy(void *handle, unsigned char *key)\r
314     sha1_key_internal(handle, key, 16);\r
317 static void hmacsha1_start(void *handle)\r
319     SHA_State *keys = (SHA_State *)handle;\r
321     keys[2] = keys[0];                /* structure copy */\r
324 static void hmacsha1_bytes(void *handle, unsigned char const *blk, int len)\r
326     SHA_State *keys = (SHA_State *)handle;\r
327     SHA_Bytes(&keys[2], (void *)blk, len);\r
330 static void hmacsha1_genresult(void *handle, unsigned char *hmac)\r
332     SHA_State *keys = (SHA_State *)handle;\r
333     SHA_State s;\r
334     unsigned char intermediate[20];\r
336     s = keys[2];                       /* structure copy */\r
337     SHA_Final(&s, intermediate);\r
338     s = keys[1];                       /* structure copy */\r
339     SHA_Bytes(&s, intermediate, 20);\r
340     SHA_Final(&s, hmac);\r
343 static void sha1_do_hmac(void *handle, unsigned char *blk, int len,\r
344                          unsigned long seq, unsigned char *hmac)\r
346     unsigned char seqbuf[4];\r
348     PUT_32BIT_MSB_FIRST(seqbuf, seq);\r
349     hmacsha1_start(handle);\r
350     hmacsha1_bytes(handle, seqbuf, 4);\r
351     hmacsha1_bytes(handle, blk, len);\r
352     hmacsha1_genresult(handle, hmac);\r
355 static void sha1_generate(void *handle, unsigned char *blk, int len,\r
356                           unsigned long seq)\r
358     sha1_do_hmac(handle, blk, len, seq, blk + len);\r
361 static int hmacsha1_verresult(void *handle, unsigned char const *hmac)\r
363     unsigned char correct[20];\r
364     hmacsha1_genresult(handle, correct);\r
365     return smemeq(correct, hmac, 20);\r
368 static int sha1_verify(void *handle, unsigned char *blk, int len,\r
369                        unsigned long seq)\r
371     unsigned char correct[20];\r
372     sha1_do_hmac(handle, blk, len, seq, correct);\r
373     return smemeq(correct, blk + len, 20);\r
376 static void hmacsha1_96_genresult(void *handle, unsigned char *hmac)\r
378     unsigned char full[20];\r
379     hmacsha1_genresult(handle, full);\r
380     memcpy(hmac, full, 12);\r
383 static void sha1_96_generate(void *handle, unsigned char *blk, int len,\r
384                              unsigned long seq)\r
386     unsigned char full[20];\r
387     sha1_do_hmac(handle, blk, len, seq, full);\r
388     memcpy(blk + len, full, 12);\r
391 static int hmacsha1_96_verresult(void *handle, unsigned char const *hmac)\r
393     unsigned char correct[20];\r
394     hmacsha1_genresult(handle, correct);\r
395     return smemeq(correct, hmac, 12);\r
398 static int sha1_96_verify(void *handle, unsigned char *blk, int len,\r
399                        unsigned long seq)\r
401     unsigned char correct[20];\r
402     sha1_do_hmac(handle, blk, len, seq, correct);\r
403     return smemeq(correct, blk + len, 12);\r
406 void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,\r
407                       unsigned char *output) {\r
408     SHA_State states[2];\r
409     unsigned char intermediate[20];\r
411     sha1_key_internal(states, key, keylen);\r
412     SHA_Bytes(&states[0], data, datalen);\r
413     SHA_Final(&states[0], intermediate);\r
415     SHA_Bytes(&states[1], intermediate, 20);\r
416     SHA_Final(&states[1], output);\r
419 const struct ssh_mac ssh_hmac_sha1 = {\r
420     sha1_make_context, sha1_free_context, sha1_key,\r
421     sha1_generate, sha1_verify,\r
422     hmacsha1_start, hmacsha1_bytes, hmacsha1_genresult, hmacsha1_verresult,\r
423     "hmac-sha1", "hmac-sha1-etm@openssh.com",\r
424     20, 20,\r
425     "HMAC-SHA1"\r
426 };\r
428 const struct ssh_mac ssh_hmac_sha1_96 = {\r
429     sha1_make_context, sha1_free_context, sha1_key,\r
430     sha1_96_generate, sha1_96_verify,\r
431     hmacsha1_start, hmacsha1_bytes,\r
432     hmacsha1_96_genresult, hmacsha1_96_verresult,\r
433     "hmac-sha1-96", "hmac-sha1-96-etm@openssh.com",\r
434     12, 20,\r
435     "HMAC-SHA1-96"\r
436 };\r
438 const struct ssh_mac ssh_hmac_sha1_buggy = {\r
439     sha1_make_context, sha1_free_context, sha1_key_buggy,\r
440     sha1_generate, sha1_verify,\r
441     hmacsha1_start, hmacsha1_bytes, hmacsha1_genresult, hmacsha1_verresult,\r
442     "hmac-sha1", NULL,\r
443     20, 16,\r
444     "bug-compatible HMAC-SHA1"\r
445 };\r
447 const struct ssh_mac ssh_hmac_sha1_96_buggy = {\r
448     sha1_make_context, sha1_free_context, sha1_key_buggy,\r
449     sha1_96_generate, sha1_96_verify,\r
450     hmacsha1_start, hmacsha1_bytes,\r
451     hmacsha1_96_genresult, hmacsha1_96_verresult,\r
452     "hmac-sha1-96", NULL,\r
453     12, 16,\r
454     "bug-compatible HMAC-SHA1-96"\r
455 };\r