Fixed issue #2495: "Show Reflog" dialog shows empty action for "push" entries
[TortoiseGit.git] / src / TortoisePlink / SSHSH256.C
blob49fb84203e3923b60cf49cb13f9e77cb73a42fbd
1 /*\r
2  * SHA-256 algorithm as described at\r
3  * \r
4  *   http://csrc.nist.gov/cryptval/shs.html\r
5  */\r
6 \r
7 #include "ssh.h"\r
8 \r
9 /* ----------------------------------------------------------------------\r
10  * Core SHA256 algorithm: processes 16-word blocks into a message digest.\r
11  */\r
13 #define ror(x,y) ( ((x) << (32-y)) | (((uint32)(x)) >> (y)) )\r
14 #define shr(x,y) ( (((uint32)(x)) >> (y)) )\r
15 #define Ch(x,y,z) ( ((x) & (y)) ^ (~(x) & (z)) )\r
16 #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) )\r
17 #define bigsigma0(x) ( ror((x),2) ^ ror((x),13) ^ ror((x),22) )\r
18 #define bigsigma1(x) ( ror((x),6) ^ ror((x),11) ^ ror((x),25) )\r
19 #define smallsigma0(x) ( ror((x),7) ^ ror((x),18) ^ shr((x),3) )\r
20 #define smallsigma1(x) ( ror((x),17) ^ ror((x),19) ^ shr((x),10) )\r
22 void SHA256_Core_Init(SHA256_State *s) {\r
23     s->h[0] = 0x6a09e667;\r
24     s->h[1] = 0xbb67ae85;\r
25     s->h[2] = 0x3c6ef372;\r
26     s->h[3] = 0xa54ff53a;\r
27     s->h[4] = 0x510e527f;\r
28     s->h[5] = 0x9b05688c;\r
29     s->h[6] = 0x1f83d9ab;\r
30     s->h[7] = 0x5be0cd19;\r
31 }\r
33 void SHA256_Block(SHA256_State *s, uint32 *block) {\r
34     uint32 w[80];\r
35     uint32 a,b,c,d,e,f,g,h;\r
36     static const int k[] = {\r
37         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,\r
38         0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\r
39         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\r
40         0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\r
41         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,\r
42         0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\r
43         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,\r
44         0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\r
45         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\r
46         0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\r
47         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,\r
48         0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\r
49         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,\r
50         0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\r
51         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\r
52         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\r
53     };\r
55     int t;\r
57     for (t = 0; t < 16; t++)\r
58         w[t] = block[t];\r
60     for (t = 16; t < 64; t++)\r
61         w[t] = smallsigma1(w[t-2]) + w[t-7] + smallsigma0(w[t-15]) + w[t-16];\r
63     a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3];\r
64     e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7];\r
66     for (t = 0; t < 64; t+=8) {\r
67         uint32 t1, t2;\r
69 #define ROUND(j,a,b,c,d,e,f,g,h) \\r
70         t1 = h + bigsigma1(e) + Ch(e,f,g) + k[j] + w[j]; \\r
71         t2 = bigsigma0(a) + Maj(a,b,c); \\r
72         d = d + t1; h = t1 + t2;\r
74         ROUND(t+0, a,b,c,d,e,f,g,h);\r
75         ROUND(t+1, h,a,b,c,d,e,f,g);\r
76         ROUND(t+2, g,h,a,b,c,d,e,f);\r
77         ROUND(t+3, f,g,h,a,b,c,d,e);\r
78         ROUND(t+4, e,f,g,h,a,b,c,d);\r
79         ROUND(t+5, d,e,f,g,h,a,b,c);\r
80         ROUND(t+6, c,d,e,f,g,h,a,b);\r
81         ROUND(t+7, b,c,d,e,f,g,h,a);\r
82     }\r
84     s->h[0] += a; s->h[1] += b; s->h[2] += c; s->h[3] += d;\r
85     s->h[4] += e; s->h[5] += f; s->h[6] += g; s->h[7] += h;\r
86 }\r
88 /* ----------------------------------------------------------------------\r
89  * Outer SHA256 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 SHA256 algorithm.\r
92  */\r
94 #define BLKSIZE 64\r
96 void SHA256_Init(SHA256_State *s) {\r
97     SHA256_Core_Init(s);\r
98     s->blkused = 0;\r
99     s->lenhi = s->lenlo = 0;\r
102 void SHA256_Bytes(SHA256_State *s, const void *p, int len) {\r
103     unsigned char *q = (unsigned char *)p;\r
104     uint32 wordblock[16];\r
105     uint32 lenw = len;\r
106     int i;\r
108     /*\r
109      * Update the length field.\r
110      */\r
111     s->lenlo += lenw;\r
112     s->lenhi += (s->lenlo < lenw);\r
114     if (s->blkused && s->blkused+len < BLKSIZE) {\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 >= BLKSIZE) {\r
125             memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);\r
126             q += BLKSIZE - s->blkused;\r
127             len -= BLKSIZE - 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             SHA256_Block(s, wordblock);\r
137             s->blkused = 0;\r
138         }\r
139         memcpy(s->block, q, len);\r
140         s->blkused = len;\r
141     }\r
144 void SHA256_Final(SHA256_State *s, unsigned char *digest) {\r
145     int i;\r
146     int pad;\r
147     unsigned char c[64];\r
148     uint32 lenhi, lenlo;\r
150     if (s->blkused >= 56)\r
151         pad = 56 + 64 - s->blkused;\r
152     else\r
153         pad = 56 - s->blkused;\r
155     lenhi = (s->lenhi << 3) | (s->lenlo >> (32-3));\r
156     lenlo = (s->lenlo << 3);\r
158     memset(c, 0, pad);\r
159     c[0] = 0x80;\r
160     SHA256_Bytes(s, &c, pad);\r
162     c[0] = (lenhi >> 24) & 0xFF;\r
163     c[1] = (lenhi >> 16) & 0xFF;\r
164     c[2] = (lenhi >>  8) & 0xFF;\r
165     c[3] = (lenhi >>  0) & 0xFF;\r
166     c[4] = (lenlo >> 24) & 0xFF;\r
167     c[5] = (lenlo >> 16) & 0xFF;\r
168     c[6] = (lenlo >>  8) & 0xFF;\r
169     c[7] = (lenlo >>  0) & 0xFF;\r
171     SHA256_Bytes(s, &c, 8);\r
173     for (i = 0; i < 8; i++) {\r
174         digest[i*4+0] = (s->h[i] >> 24) & 0xFF;\r
175         digest[i*4+1] = (s->h[i] >> 16) & 0xFF;\r
176         digest[i*4+2] = (s->h[i] >>  8) & 0xFF;\r
177         digest[i*4+3] = (s->h[i] >>  0) & 0xFF;\r
178     }\r
181 void SHA256_Simple(const void *p, int len, unsigned char *output) {\r
182     SHA256_State s;\r
184     SHA256_Init(&s);\r
185     SHA256_Bytes(&s, p, len);\r
186     SHA256_Final(&s, output);\r
189 /*\r
190  * Thin abstraction for things where hashes are pluggable.\r
191  */\r
193 static void *sha256_init(void)\r
195     SHA256_State *s;\r
197     s = snew(SHA256_State);\r
198     SHA256_Init(s);\r
199     return s;\r
202 static void sha256_bytes(void *handle, void *p, int len)\r
204     SHA256_State *s = handle;\r
206     SHA256_Bytes(s, p, len);\r
209 static void sha256_final(void *handle, unsigned char *output)\r
211     SHA256_State *s = handle;\r
213     SHA256_Final(s, output);\r
214     sfree(s);\r
217 const struct ssh_hash ssh_sha256 = {\r
218     sha256_init, sha256_bytes, sha256_final, 32, "SHA-256"\r
219 };\r
221 /* ----------------------------------------------------------------------\r
222  * The above is the SHA-256 algorithm itself. Now we implement the\r
223  * HMAC wrapper on it.\r
224  */\r
226 static void *sha256_make_context(void)\r
228     return snewn(3, SHA256_State);\r
231 static void sha256_free_context(void *handle)\r
233     sfree(handle);\r
236 static void sha256_key_internal(void *handle, unsigned char *key, int len)\r
238     SHA256_State *keys = (SHA256_State *)handle;\r
239     unsigned char foo[64];\r
240     int i;\r
242     memset(foo, 0x36, 64);\r
243     for (i = 0; i < len && i < 64; i++)\r
244         foo[i] ^= key[i];\r
245     SHA256_Init(&keys[0]);\r
246     SHA256_Bytes(&keys[0], foo, 64);\r
248     memset(foo, 0x5C, 64);\r
249     for (i = 0; i < len && i < 64; i++)\r
250         foo[i] ^= key[i];\r
251     SHA256_Init(&keys[1]);\r
252     SHA256_Bytes(&keys[1], foo, 64);\r
254     smemclr(foo, 64);                  /* burn the evidence */\r
257 static void sha256_key(void *handle, unsigned char *key)\r
259     sha256_key_internal(handle, key, 32);\r
262 static void hmacsha256_start(void *handle)\r
264     SHA256_State *keys = (SHA256_State *)handle;\r
266     keys[2] = keys[0];                /* structure copy */\r
269 static void hmacsha256_bytes(void *handle, unsigned char const *blk, int len)\r
271     SHA256_State *keys = (SHA256_State *)handle;\r
272     SHA256_Bytes(&keys[2], (void *)blk, len);\r
275 static void hmacsha256_genresult(void *handle, unsigned char *hmac)\r
277     SHA256_State *keys = (SHA256_State *)handle;\r
278     SHA256_State s;\r
279     unsigned char intermediate[32];\r
281     s = keys[2];                       /* structure copy */\r
282     SHA256_Final(&s, intermediate);\r
283     s = keys[1];                       /* structure copy */\r
284     SHA256_Bytes(&s, intermediate, 32);\r
285     SHA256_Final(&s, hmac);\r
288 static void sha256_do_hmac(void *handle, unsigned char *blk, int len,\r
289                          unsigned long seq, unsigned char *hmac)\r
291     unsigned char seqbuf[4];\r
293     PUT_32BIT_MSB_FIRST(seqbuf, seq);\r
294     hmacsha256_start(handle);\r
295     hmacsha256_bytes(handle, seqbuf, 4);\r
296     hmacsha256_bytes(handle, blk, len);\r
297     hmacsha256_genresult(handle, hmac);\r
300 static void sha256_generate(void *handle, unsigned char *blk, int len,\r
301                           unsigned long seq)\r
303     sha256_do_hmac(handle, blk, len, seq, blk + len);\r
306 static int hmacsha256_verresult(void *handle, unsigned char const *hmac)\r
308     unsigned char correct[32];\r
309     hmacsha256_genresult(handle, correct);\r
310     return !memcmp(correct, hmac, 32);\r
313 static int sha256_verify(void *handle, unsigned char *blk, int len,\r
314                        unsigned long seq)\r
316     unsigned char correct[32];\r
317     sha256_do_hmac(handle, blk, len, seq, correct);\r
318     return !memcmp(correct, blk + len, 32);\r
321 const struct ssh_mac ssh_hmac_sha256 = {\r
322     sha256_make_context, sha256_free_context, sha256_key,\r
323     sha256_generate, sha256_verify,\r
324     hmacsha256_start, hmacsha256_bytes,\r
325     hmacsha256_genresult, hmacsha256_verresult,\r
326     "hmac-sha2-256",\r
327     32,\r
328     "HMAC-SHA-256"\r
329 };\r
331 #ifdef TEST\r
333 #include <stdio.h>\r
334 #include <stdlib.h>\r
335 #include <assert.h>\r
337 int main(void) {\r
338     unsigned char digest[32];\r
339     int i, j, errors;\r
341     struct {\r
342         const char *teststring;\r
343         unsigned char digest[32];\r
344     } tests[] = {\r
345         { "abc", {\r
346             0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,\r
347             0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,\r
348             0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,\r
349             0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,\r
350         } },\r
351         { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", {\r
352             0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,\r
353             0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,\r
354             0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,\r
355             0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,\r
356         } },\r
357     };\r
359     errors = 0;\r
361     for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {\r
362         SHA256_Simple(tests[i].teststring,\r
363                       strlen(tests[i].teststring), digest);\r
364         for (j = 0; j < 32; j++) {\r
365             if (digest[j] != tests[i].digest[j]) {\r
366                 fprintf(stderr,\r
367                         "\"%s\" digest byte %d should be 0x%02x, is 0x%02x\n",\r
368                         tests[i].teststring, j, tests[i].digest[j], digest[j]);\r
369                 errors++;\r
370             }\r
371         }\r
372     }\r
374     printf("%d errors\n", errors);\r
376     return 0;\r
379 #endif\r