CPatch: New memory management
[TortoiseGit.git] / src / TortoisePlink / SSHSH256.C
blob018f61f6c19b56f445c90a11163731515246c8d6
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_copy(const void *vold)\r
205     const SHA256_State *old = (const SHA256_State *)vold;\r
206     SHA256_State *s;\r
208     s = snew(SHA256_State);\r
209     *s = *old;\r
210     return s;\r
213 static void sha256_free(void *handle)\r
215     SHA256_State *s = handle;\r
217     smemclr(s, sizeof(*s));\r
218     sfree(s);\r
221 static void sha256_bytes(void *handle, const void *p, int len)\r
223     SHA256_State *s = handle;\r
225     SHA256_Bytes(s, p, len);\r
228 static void sha256_final(void *handle, unsigned char *output)\r
230     SHA256_State *s = handle;\r
232     SHA256_Final(s, output);\r
233     sha256_free(s);\r
236 const struct ssh_hash ssh_sha256 = {\r
237     sha256_init, sha256_copy, sha256_bytes, sha256_final, sha256_free,\r
238     32, "SHA-256"\r
239 };\r
241 /* ----------------------------------------------------------------------\r
242  * The above is the SHA-256 algorithm itself. Now we implement the\r
243  * HMAC wrapper on it.\r
244  */\r
246 static void *sha256_make_context(void *cipher_ctx)\r
248     return snewn(3, SHA256_State);\r
251 static void sha256_free_context(void *handle)\r
253     smemclr(handle, 3 * sizeof(SHA256_State));\r
254     sfree(handle);\r
257 static void sha256_key_internal(void *handle, unsigned char *key, int len)\r
259     SHA256_State *keys = (SHA256_State *)handle;\r
260     unsigned char foo[64];\r
261     int i;\r
263     memset(foo, 0x36, 64);\r
264     for (i = 0; i < len && i < 64; i++)\r
265         foo[i] ^= key[i];\r
266     SHA256_Init(&keys[0]);\r
267     SHA256_Bytes(&keys[0], foo, 64);\r
269     memset(foo, 0x5C, 64);\r
270     for (i = 0; i < len && i < 64; i++)\r
271         foo[i] ^= key[i];\r
272     SHA256_Init(&keys[1]);\r
273     SHA256_Bytes(&keys[1], foo, 64);\r
275     smemclr(foo, 64);                  /* burn the evidence */\r
278 static void sha256_key(void *handle, unsigned char *key)\r
280     sha256_key_internal(handle, key, 32);\r
283 static void hmacsha256_start(void *handle)\r
285     SHA256_State *keys = (SHA256_State *)handle;\r
287     keys[2] = keys[0];                /* structure copy */\r
290 static void hmacsha256_bytes(void *handle, unsigned char const *blk, int len)\r
292     SHA256_State *keys = (SHA256_State *)handle;\r
293     SHA256_Bytes(&keys[2], (void *)blk, len);\r
296 static void hmacsha256_genresult(void *handle, unsigned char *hmac)\r
298     SHA256_State *keys = (SHA256_State *)handle;\r
299     SHA256_State s;\r
300     unsigned char intermediate[32];\r
302     s = keys[2];                       /* structure copy */\r
303     SHA256_Final(&s, intermediate);\r
304     s = keys[1];                       /* structure copy */\r
305     SHA256_Bytes(&s, intermediate, 32);\r
306     SHA256_Final(&s, hmac);\r
309 static void sha256_do_hmac(void *handle, unsigned char *blk, int len,\r
310                          unsigned long seq, unsigned char *hmac)\r
312     unsigned char seqbuf[4];\r
314     PUT_32BIT_MSB_FIRST(seqbuf, seq);\r
315     hmacsha256_start(handle);\r
316     hmacsha256_bytes(handle, seqbuf, 4);\r
317     hmacsha256_bytes(handle, blk, len);\r
318     hmacsha256_genresult(handle, hmac);\r
321 static void sha256_generate(void *handle, unsigned char *blk, int len,\r
322                           unsigned long seq)\r
324     sha256_do_hmac(handle, blk, len, seq, blk + len);\r
327 static int hmacsha256_verresult(void *handle, unsigned char const *hmac)\r
329     unsigned char correct[32];\r
330     hmacsha256_genresult(handle, correct);\r
331     return smemeq(correct, hmac, 32);\r
334 static int sha256_verify(void *handle, unsigned char *blk, int len,\r
335                        unsigned long seq)\r
337     unsigned char correct[32];\r
338     sha256_do_hmac(handle, blk, len, seq, correct);\r
339     return smemeq(correct, blk + len, 32);\r
342 const struct ssh_mac ssh_hmac_sha256 = {\r
343     sha256_make_context, sha256_free_context, sha256_key,\r
344     sha256_generate, sha256_verify,\r
345     hmacsha256_start, hmacsha256_bytes,\r
346     hmacsha256_genresult, hmacsha256_verresult,\r
347     "hmac-sha2-256", "hmac-sha2-256-etm@openssh.com",\r
348     32, 32,\r
349     "HMAC-SHA-256"\r
350 };\r
352 #ifdef TEST\r
354 #include <stdio.h>\r
355 #include <stdlib.h>\r
356 #include <assert.h>\r
358 int main(void) {\r
359     unsigned char digest[32];\r
360     int i, j, errors;\r
362     struct {\r
363         const char *teststring;\r
364         unsigned char digest[32];\r
365     } tests[] = {\r
366         { "abc", {\r
367             0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,\r
368             0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,\r
369             0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,\r
370             0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,\r
371         } },\r
372         { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", {\r
373             0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,\r
374             0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,\r
375             0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,\r
376             0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,\r
377         } },\r
378     };\r
380     errors = 0;\r
382     for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {\r
383         SHA256_Simple(tests[i].teststring,\r
384                       strlen(tests[i].teststring), digest);\r
385         for (j = 0; j < 32; j++) {\r
386             if (digest[j] != tests[i].digest[j]) {\r
387                 fprintf(stderr,\r
388                         "\"%s\" digest byte %d should be 0x%02x, is 0x%02x\n",\r
389                         tests[i].teststring, j, tests[i].digest[j], digest[j]);\r
390                 errors++;\r
391             }\r
392         }\r
393     }\r
395     printf("%d errors\n", errors);\r
397     return 0;\r
400 #endif\r