Refactored: Replace 'count' parameter of CGit::GetLogCmd() with CFilterData::m_Number...
[TortoiseGit.git] / src / TortoisePlink / SSHSH256.C
blob8cda9969c52266acb6b721a2e3daa9aa397564a8
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
187     smemclr(&s, sizeof(s));\r
190 /*\r
191  * Thin abstraction for things where hashes are pluggable.\r
192  */\r
194 static void *sha256_init(void)\r
196     SHA256_State *s;\r
198     s = snew(SHA256_State);\r
199     SHA256_Init(s);\r
200     return s;\r
203 static void sha256_bytes(void *handle, void *p, int len)\r
205     SHA256_State *s = handle;\r
207     SHA256_Bytes(s, p, len);\r
210 static void sha256_final(void *handle, unsigned char *output)\r
212     SHA256_State *s = handle;\r
214     SHA256_Final(s, output);\r
215     smemclr(s, sizeof(*s));\r
216     sfree(s);\r
219 const struct ssh_hash ssh_sha256 = {\r
220     sha256_init, sha256_bytes, sha256_final, 32, "SHA-256"\r
221 };\r
223 /* ----------------------------------------------------------------------\r
224  * The above is the SHA-256 algorithm itself. Now we implement the\r
225  * HMAC wrapper on it.\r
226  */\r
228 static void *sha256_make_context(void)\r
230     return snewn(3, SHA256_State);\r
233 static void sha256_free_context(void *handle)\r
235     smemclr(handle, 3 * sizeof(SHA256_State));\r
236     sfree(handle);\r
239 static void sha256_key_internal(void *handle, unsigned char *key, int len)\r
241     SHA256_State *keys = (SHA256_State *)handle;\r
242     unsigned char foo[64];\r
243     int i;\r
245     memset(foo, 0x36, 64);\r
246     for (i = 0; i < len && i < 64; i++)\r
247         foo[i] ^= key[i];\r
248     SHA256_Init(&keys[0]);\r
249     SHA256_Bytes(&keys[0], foo, 64);\r
251     memset(foo, 0x5C, 64);\r
252     for (i = 0; i < len && i < 64; i++)\r
253         foo[i] ^= key[i];\r
254     SHA256_Init(&keys[1]);\r
255     SHA256_Bytes(&keys[1], foo, 64);\r
257     smemclr(foo, 64);                  /* burn the evidence */\r
260 static void sha256_key(void *handle, unsigned char *key)\r
262     sha256_key_internal(handle, key, 32);\r
265 static void hmacsha256_start(void *handle)\r
267     SHA256_State *keys = (SHA256_State *)handle;\r
269     keys[2] = keys[0];                /* structure copy */\r
272 static void hmacsha256_bytes(void *handle, unsigned char const *blk, int len)\r
274     SHA256_State *keys = (SHA256_State *)handle;\r
275     SHA256_Bytes(&keys[2], (void *)blk, len);\r
278 static void hmacsha256_genresult(void *handle, unsigned char *hmac)\r
280     SHA256_State *keys = (SHA256_State *)handle;\r
281     SHA256_State s;\r
282     unsigned char intermediate[32];\r
284     s = keys[2];                       /* structure copy */\r
285     SHA256_Final(&s, intermediate);\r
286     s = keys[1];                       /* structure copy */\r
287     SHA256_Bytes(&s, intermediate, 32);\r
288     SHA256_Final(&s, hmac);\r
291 static void sha256_do_hmac(void *handle, unsigned char *blk, int len,\r
292                          unsigned long seq, unsigned char *hmac)\r
294     unsigned char seqbuf[4];\r
296     PUT_32BIT_MSB_FIRST(seqbuf, seq);\r
297     hmacsha256_start(handle);\r
298     hmacsha256_bytes(handle, seqbuf, 4);\r
299     hmacsha256_bytes(handle, blk, len);\r
300     hmacsha256_genresult(handle, hmac);\r
303 static void sha256_generate(void *handle, unsigned char *blk, int len,\r
304                           unsigned long seq)\r
306     sha256_do_hmac(handle, blk, len, seq, blk + len);\r
309 static int hmacsha256_verresult(void *handle, unsigned char const *hmac)\r
311     unsigned char correct[32];\r
312     hmacsha256_genresult(handle, correct);\r
313     return smemeq(correct, hmac, 32);\r
316 static int sha256_verify(void *handle, unsigned char *blk, int len,\r
317                        unsigned long seq)\r
319     unsigned char correct[32];\r
320     sha256_do_hmac(handle, blk, len, seq, correct);\r
321     return smemeq(correct, blk + len, 32);\r
324 const struct ssh_mac ssh_hmac_sha256 = {\r
325     sha256_make_context, sha256_free_context, sha256_key,\r
326     sha256_generate, sha256_verify,\r
327     hmacsha256_start, hmacsha256_bytes,\r
328     hmacsha256_genresult, hmacsha256_verresult,\r
329     "hmac-sha2-256",\r
330     32,\r
331     "HMAC-SHA-256"\r
332 };\r
334 #ifdef TEST\r
336 #include <stdio.h>\r
337 #include <stdlib.h>\r
338 #include <assert.h>\r
340 int main(void) {\r
341     unsigned char digest[32];\r
342     int i, j, errors;\r
344     struct {\r
345         const char *teststring;\r
346         unsigned char digest[32];\r
347     } tests[] = {\r
348         { "abc", {\r
349             0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,\r
350             0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,\r
351             0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,\r
352             0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,\r
353         } },\r
354         { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", {\r
355             0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,\r
356             0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,\r
357             0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,\r
358             0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,\r
359         } },\r
360     };\r
362     errors = 0;\r
364     for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {\r
365         SHA256_Simple(tests[i].teststring,\r
366                       strlen(tests[i].teststring), digest);\r
367         for (j = 0; j < 32; j++) {\r
368             if (digest[j] != tests[i].digest[j]) {\r
369                 fprintf(stderr,\r
370                         "\"%s\" digest byte %d should be 0x%02x, is 0x%02x\n",\r
371                         tests[i].teststring, j, tests[i].digest[j], digest[j]);\r
372                 errors++;\r
373             }\r
374         }\r
375     }\r
377     printf("%d errors\n", errors);\r
379     return 0;\r
382 #endif\r