OSDN Git Service

Add support for MLSD responses from some broken hosts.
[ffftp/ffftp.git] / putty / SSHSH256.C
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
12 \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
21 \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
32 \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
54 \r
55     int t;\r
56 \r
57     for (t = 0; t < 16; t++)\r
58         w[t] = block[t];\r
59 \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
62 \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
65 \r
66     for (t = 0; t < 64; t+=8) {\r
67         uint32 t1, t2;\r
68 \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
73 \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
83 \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
87 \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
93 \r
94 #define BLKSIZE 64\r
95 \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
100 }\r
101 \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
107 \r
108     /*\r
109      * Update the length field.\r
110      */\r
111     s->lenlo += lenw;\r
112     s->lenhi += (s->lenlo < lenw);\r
113 \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
142 }\r
143 \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
149 \r
150     if (s->blkused >= 56)\r
151         pad = 56 + 64 - s->blkused;\r
152     else\r
153         pad = 56 - s->blkused;\r
154 \r
155     lenhi = (s->lenhi << 3) | (s->lenlo >> (32-3));\r
156     lenlo = (s->lenlo << 3);\r
157 \r
158     memset(c, 0, pad);\r
159     c[0] = 0x80;\r
160     SHA256_Bytes(s, &c, pad);\r
161 \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
170 \r
171     SHA256_Bytes(s, &c, 8);\r
172 \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
179 }\r
180 \r
181 void SHA256_Simple(const void *p, int len, unsigned char *output) {\r
182     SHA256_State s;\r
183 \r
184     SHA256_Init(&s);\r
185     SHA256_Bytes(&s, p, len);\r
186     SHA256_Final(&s, output);\r
187 }\r
188 \r
189 /*\r
190  * Thin abstraction for things where hashes are pluggable.\r
191  */\r
192 \r
193 static void *sha256_init(void)\r
194 {\r
195     SHA256_State *s;\r
196 \r
197     s = snew(SHA256_State);\r
198     SHA256_Init(s);\r
199     return s;\r
200 }\r
201 \r
202 static void sha256_bytes(void *handle, void *p, int len)\r
203 {\r
204     SHA256_State *s = handle;\r
205 \r
206     SHA256_Bytes(s, p, len);\r
207 }\r
208 \r
209 static void sha256_final(void *handle, unsigned char *output)\r
210 {\r
211     SHA256_State *s = handle;\r
212 \r
213     SHA256_Final(s, output);\r
214     sfree(s);\r
215 }\r
216 \r
217 const struct ssh_hash ssh_sha256 = {\r
218     sha256_init, sha256_bytes, sha256_final, 32, "SHA-256"\r
219 };\r
220 \r
221 #ifdef TEST\r
222 \r
223 #include <stdio.h>\r
224 #include <stdlib.h>\r
225 #include <assert.h>\r
226 \r
227 int main(void) {\r
228     unsigned char digest[32];\r
229     int i, j, errors;\r
230 \r
231     struct {\r
232         const char *teststring;\r
233         unsigned char digest[32];\r
234     } tests[] = {\r
235         { "abc", {\r
236             0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,\r
237             0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,\r
238             0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,\r
239             0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,\r
240         } },\r
241         { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", {\r
242             0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,\r
243             0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,\r
244             0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,\r
245             0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,\r
246         } },\r
247     };\r
248 \r
249     errors = 0;\r
250 \r
251     for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {\r
252         SHA256_Simple(tests[i].teststring,\r
253                       strlen(tests[i].teststring), digest);\r
254         for (j = 0; j < 32; j++) {\r
255             if (digest[j] != tests[i].digest[j]) {\r
256                 fprintf(stderr,\r
257                         "\"%s\" digest byte %d should be 0x%02x, is 0x%02x\n",\r
258                         tests[i].teststring, j, tests[i].digest[j], digest[j]);\r
259                 errors++;\r
260             }\r
261         }\r
262     }\r
263 \r
264     printf("%d errors\n", errors);\r
265 \r
266     return 0;\r
267 }\r
268 \r
269 #endif\r