]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - sshsh512.c
Oops - another missing file :-/
[PuTTY.git] / sshsh512.c
1 /*\r
2  * SHA-512 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 #define BLKSIZE 128\r
10 \r
11 typedef unsigned int uint32;\r
12 \r
13 /*\r
14  * Arithmetic implementations. Note that AND, XOR and NOT can\r
15  * overlap destination with one source, but the others can't.\r
16  */\r
17 #define add(r,x,y) ( r.lo = y.lo + x.lo, \\r
18                      r.hi = y.hi + x.hi + (r.lo < y.lo) )\r
19 #define rorB(r,x,y) ( r.lo = (x.hi >> ((y)-32)) | (x.lo << (64-(y))), \\r
20                       r.hi = (x.lo >> ((y)-32)) | (x.hi << (64-(y))) )\r
21 #define rorL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \\r
22                       r.hi = (x.hi >> (y)) | (x.lo << (32-(y))) )\r
23 #define shrB(r,x,y) ( r.lo = x.hi >> ((y)-32), r.hi = 0 )\r
24 #define shrL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \\r
25                       r.hi = x.hi >> (y) )\r
26 #define and(r,x,y) ( r.lo = x.lo & y.lo, r.hi = x.hi & y.hi )\r
27 #define xor(r,x,y) ( r.lo = x.lo ^ y.lo, r.hi = x.hi ^ y.hi )\r
28 #define not(r,x) ( r.lo = ~x.lo, r.hi = ~x.hi )\r
29 #define INIT(h,l) { h, l }\r
30 #define BUILD(r,h,l) ( r.hi = h, r.lo = l )\r
31 #define EXTRACT(h,l,r) ( h = r.hi, l = r.lo )\r
32 \r
33 /* ----------------------------------------------------------------------\r
34  * Core SHA512 algorithm: processes 16-doubleword blocks into a\r
35  * message digest.\r
36  */\r
37 \r
38 #define Ch(r,t,x,y,z) ( not(t,x), and(r,t,z), and(t,x,y), xor(r,r,t) )\r
39 #define Maj(r,t,x,y,z) ( and(r,x,y), and(t,x,z), xor(r,r,t), \\r
40                          and(t,y,z), xor(r,r,t) )\r
41 #define bigsigma0(r,t,x) ( rorL(r,x,28), rorB(t,x,34), xor(r,r,t), \\r
42                            rorB(t,x,39), xor(r,r,t) )\r
43 #define bigsigma1(r,t,x) ( rorL(r,x,14), rorL(t,x,18), xor(r,r,t), \\r
44                            rorB(t,x,41), xor(r,r,t) )\r
45 #define smallsigma0(r,t,x) ( rorL(r,x,1), rorL(t,x,8), xor(r,r,t), \\r
46                              shrL(t,x,7), xor(r,r,t) )\r
47 #define smallsigma1(r,t,x) ( rorL(r,x,19), rorB(t,x,61), xor(r,r,t), \\r
48                              shrL(t,x,6), xor(r,r,t) )\r
49 \r
50 void SHA512_Core_Init(SHA512_State *s) {\r
51     static const uint64 iv[] = {\r
52         INIT(0x6a09e667, 0xf3bcc908),\r
53         INIT(0xbb67ae85, 0x84caa73b),\r
54         INIT(0x3c6ef372, 0xfe94f82b),\r
55         INIT(0xa54ff53a, 0x5f1d36f1),\r
56         INIT(0x510e527f, 0xade682d1),\r
57         INIT(0x9b05688c, 0x2b3e6c1f),\r
58         INIT(0x1f83d9ab, 0xfb41bd6b),\r
59         INIT(0x5be0cd19, 0x137e2179),\r
60     };\r
61     int i;\r
62     for (i = 0; i < 8; i++)\r
63         s->h[i] = iv[i];\r
64 }\r
65 \r
66 void SHA512_Block(SHA512_State *s, uint64 *block) {\r
67     uint64 w[80];\r
68     uint64 a,b,c,d,e,f,g,h;\r
69     static const uint64 k[] = {\r
70         INIT(0x428a2f98, 0xd728ae22), INIT(0x71374491, 0x23ef65cd),\r
71         INIT(0xb5c0fbcf, 0xec4d3b2f), INIT(0xe9b5dba5, 0x8189dbbc),\r
72         INIT(0x3956c25b, 0xf348b538), INIT(0x59f111f1, 0xb605d019),\r
73         INIT(0x923f82a4, 0xaf194f9b), INIT(0xab1c5ed5, 0xda6d8118),\r
74         INIT(0xd807aa98, 0xa3030242), INIT(0x12835b01, 0x45706fbe),\r
75         INIT(0x243185be, 0x4ee4b28c), INIT(0x550c7dc3, 0xd5ffb4e2),\r
76         INIT(0x72be5d74, 0xf27b896f), INIT(0x80deb1fe, 0x3b1696b1),\r
77         INIT(0x9bdc06a7, 0x25c71235), INIT(0xc19bf174, 0xcf692694),\r
78         INIT(0xe49b69c1, 0x9ef14ad2), INIT(0xefbe4786, 0x384f25e3),\r
79         INIT(0x0fc19dc6, 0x8b8cd5b5), INIT(0x240ca1cc, 0x77ac9c65),\r
80         INIT(0x2de92c6f, 0x592b0275), INIT(0x4a7484aa, 0x6ea6e483),\r
81         INIT(0x5cb0a9dc, 0xbd41fbd4), INIT(0x76f988da, 0x831153b5),\r
82         INIT(0x983e5152, 0xee66dfab), INIT(0xa831c66d, 0x2db43210),\r
83         INIT(0xb00327c8, 0x98fb213f), INIT(0xbf597fc7, 0xbeef0ee4),\r
84         INIT(0xc6e00bf3, 0x3da88fc2), INIT(0xd5a79147, 0x930aa725),\r
85         INIT(0x06ca6351, 0xe003826f), INIT(0x14292967, 0x0a0e6e70),\r
86         INIT(0x27b70a85, 0x46d22ffc), INIT(0x2e1b2138, 0x5c26c926),\r
87         INIT(0x4d2c6dfc, 0x5ac42aed), INIT(0x53380d13, 0x9d95b3df),\r
88         INIT(0x650a7354, 0x8baf63de), INIT(0x766a0abb, 0x3c77b2a8),\r
89         INIT(0x81c2c92e, 0x47edaee6), INIT(0x92722c85, 0x1482353b),\r
90         INIT(0xa2bfe8a1, 0x4cf10364), INIT(0xa81a664b, 0xbc423001),\r
91         INIT(0xc24b8b70, 0xd0f89791), INIT(0xc76c51a3, 0x0654be30),\r
92         INIT(0xd192e819, 0xd6ef5218), INIT(0xd6990624, 0x5565a910),\r
93         INIT(0xf40e3585, 0x5771202a), INIT(0x106aa070, 0x32bbd1b8),\r
94         INIT(0x19a4c116, 0xb8d2d0c8), INIT(0x1e376c08, 0x5141ab53),\r
95         INIT(0x2748774c, 0xdf8eeb99), INIT(0x34b0bcb5, 0xe19b48a8),\r
96         INIT(0x391c0cb3, 0xc5c95a63), INIT(0x4ed8aa4a, 0xe3418acb),\r
97         INIT(0x5b9cca4f, 0x7763e373), INIT(0x682e6ff3, 0xd6b2b8a3),\r
98         INIT(0x748f82ee, 0x5defb2fc), INIT(0x78a5636f, 0x43172f60),\r
99         INIT(0x84c87814, 0xa1f0ab72), INIT(0x8cc70208, 0x1a6439ec),\r
100         INIT(0x90befffa, 0x23631e28), INIT(0xa4506ceb, 0xde82bde9),\r
101         INIT(0xbef9a3f7, 0xb2c67915), INIT(0xc67178f2, 0xe372532b),\r
102         INIT(0xca273ece, 0xea26619c), INIT(0xd186b8c7, 0x21c0c207),\r
103         INIT(0xeada7dd6, 0xcde0eb1e), INIT(0xf57d4f7f, 0xee6ed178),\r
104         INIT(0x06f067aa, 0x72176fba), INIT(0x0a637dc5, 0xa2c898a6),\r
105         INIT(0x113f9804, 0xbef90dae), INIT(0x1b710b35, 0x131c471b),\r
106         INIT(0x28db77f5, 0x23047d84), INIT(0x32caab7b, 0x40c72493),\r
107         INIT(0x3c9ebe0a, 0x15c9bebc), INIT(0x431d67c4, 0x9c100d4c),\r
108         INIT(0x4cc5d4be, 0xcb3e42b6), INIT(0x597f299c, 0xfc657e2a),\r
109         INIT(0x5fcb6fab, 0x3ad6faec), INIT(0x6c44198c, 0x4a475817),\r
110     };\r
111 \r
112     int t;\r
113 \r
114     for (t = 0; t < 16; t++)\r
115         w[t] = block[t];\r
116 \r
117     for (t = 16; t < 80; t++) {\r
118         uint64 p, q, r, tmp;\r
119         smallsigma1(p, tmp, w[t-2]);\r
120         smallsigma0(q, tmp, w[t-15]);\r
121         add(r, p, q);\r
122         add(p, r, w[t-7]);\r
123         add(w[t], p, w[t-16]);\r
124     }\r
125 \r
126     a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3];\r
127     e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7];\r
128 \r
129     for (t = 0; t < 80; t+=8) {\r
130         uint64 tmp, p, q, r;\r
131 \r
132 #define ROUND(j,a,b,c,d,e,f,g,h) \\r
133         bigsigma1(p, tmp, e); \\r
134         Ch(q, tmp, e, f, g); \\r
135         add(r, p, q); \\r
136         add(p, r, k[j]) ; \\r
137         add(q, p, w[j]); \\r
138         add(r, q, h); \\r
139         bigsigma0(p, tmp, a); \\r
140         Maj(tmp, q, a, b, c); \\r
141         add(q, tmp, p); \\r
142         add(p, r, d); \\r
143         d = p; \\r
144         add(h, q, r);\r
145 \r
146         ROUND(t+0, a,b,c,d,e,f,g,h);\r
147         ROUND(t+1, h,a,b,c,d,e,f,g);\r
148         ROUND(t+2, g,h,a,b,c,d,e,f);\r
149         ROUND(t+3, f,g,h,a,b,c,d,e);\r
150         ROUND(t+4, e,f,g,h,a,b,c,d);\r
151         ROUND(t+5, d,e,f,g,h,a,b,c);\r
152         ROUND(t+6, c,d,e,f,g,h,a,b);\r
153         ROUND(t+7, b,c,d,e,f,g,h,a);\r
154     }\r
155 \r
156     {\r
157         uint64 tmp;\r
158 #define UPDATE(state, local) ( tmp = state, add(state, tmp, local) )\r
159         UPDATE(s->h[0], a); UPDATE(s->h[1], b);\r
160         UPDATE(s->h[2], c); UPDATE(s->h[3], d);\r
161         UPDATE(s->h[4], e); UPDATE(s->h[5], f);\r
162         UPDATE(s->h[6], g); UPDATE(s->h[7], h);\r
163     }\r
164 }\r
165 \r
166 /* ----------------------------------------------------------------------\r
167  * Outer SHA512 algorithm: take an arbitrary length byte string,\r
168  * convert it into 16-doubleword blocks with the prescribed padding\r
169  * at the end, and pass those blocks to the core SHA512 algorithm.\r
170  */\r
171 \r
172 void SHA512_Init(SHA512_State *s) {\r
173     int i;\r
174     SHA512_Core_Init(s);\r
175     s->blkused = 0;\r
176     for (i = 0; i < 4; i++)\r
177         s->len[i] = 0;\r
178 }\r
179 \r
180 void SHA512_Bytes(SHA512_State *s, const void *p, int len) {\r
181     unsigned char *q = (unsigned char *)p;\r
182     uint64 wordblock[16];\r
183     uint32 lenw = len;\r
184     int i;\r
185 \r
186     /*\r
187      * Update the length field.\r
188      */\r
189     for (i = 0; i < 4; i++) {\r
190         s->len[i] += lenw;\r
191         lenw = (s->len[i] < lenw);\r
192     }\r
193 \r
194     if (s->blkused && s->blkused+len < BLKSIZE) {\r
195         /*\r
196          * Trivial case: just add to the block.\r
197          */\r
198         memcpy(s->block + s->blkused, q, len);\r
199         s->blkused += len;\r
200     } else {\r
201         /*\r
202          * We must complete and process at least one block.\r
203          */\r
204         while (s->blkused + len >= BLKSIZE) {\r
205             memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);\r
206             q += BLKSIZE - s->blkused;\r
207             len -= BLKSIZE - s->blkused;\r
208             /* Now process the block. Gather bytes big-endian into words */\r
209             for (i = 0; i < 16; i++) {\r
210                 uint32 h, l;\r
211                 h = ( ((uint32)s->block[i*8+0]) << 24 ) |\r
212                     ( ((uint32)s->block[i*8+1]) << 16 ) |\r
213                     ( ((uint32)s->block[i*8+2]) <<  8 ) |\r
214                     ( ((uint32)s->block[i*8+3]) <<  0 );\r
215                 l = ( ((uint32)s->block[i*8+4]) << 24 ) |\r
216                     ( ((uint32)s->block[i*8+5]) << 16 ) |\r
217                     ( ((uint32)s->block[i*8+6]) <<  8 ) |\r
218                     ( ((uint32)s->block[i*8+7]) <<  0 );\r
219                 BUILD(wordblock[i], h, l);\r
220             }\r
221             SHA512_Block(s, wordblock);\r
222             s->blkused = 0;\r
223         }\r
224         memcpy(s->block, q, len);\r
225         s->blkused = len;\r
226     }\r
227 }\r
228 \r
229 void SHA512_Final(SHA512_State *s, unsigned char *digest) {\r
230     int i;\r
231     int pad;\r
232     unsigned char c[BLKSIZE];\r
233     uint32 len[4];\r
234 \r
235     if (s->blkused >= BLKSIZE-16)\r
236         pad = (BLKSIZE-16) + BLKSIZE - s->blkused;\r
237     else\r
238         pad = (BLKSIZE-16) - s->blkused;\r
239 \r
240     for (i = 4; i-- ;) {\r
241         uint32 lenhi = s->len[i];\r
242         uint32 lenlo = i > 0 ? s->len[i-1] : 0;\r
243         len[i] = (lenhi << 3) | (lenlo >> (32-3));\r
244     }\r
245 \r
246     memset(c, 0, pad);\r
247     c[0] = 0x80;\r
248     SHA512_Bytes(s, &c, pad);\r
249 \r
250     for (i = 0; i < 4; i++) {\r
251         c[i*4+0] = (len[3-i] >> 24) & 0xFF;\r
252         c[i*4+1] = (len[3-i] >> 16) & 0xFF;\r
253         c[i*4+2] = (len[3-i] >>  8) & 0xFF;\r
254         c[i*4+3] = (len[3-i] >>  0) & 0xFF;\r
255     }\r
256 \r
257     SHA512_Bytes(s, &c, 16);\r
258 \r
259     for (i = 0; i < 8; i++) {\r
260         uint32 h, l;\r
261         EXTRACT(h, l, s->h[i]);\r
262         digest[i*8+0] = (h >> 24) & 0xFF;\r
263         digest[i*8+1] = (h >> 16) & 0xFF;\r
264         digest[i*8+2] = (h >>  8) & 0xFF;\r
265         digest[i*8+3] = (h >>  0) & 0xFF;\r
266         digest[i*8+4] = (l >> 24) & 0xFF;\r
267         digest[i*8+5] = (l >> 16) & 0xFF;\r
268         digest[i*8+6] = (l >>  8) & 0xFF;\r
269         digest[i*8+7] = (l >>  0) & 0xFF;\r
270     }\r
271 }\r
272 \r
273 void SHA512_Simple(const void *p, int len, unsigned char *output) {\r
274     SHA512_State s;\r
275 \r
276     SHA512_Init(&s);\r
277     SHA512_Bytes(&s, p, len);\r
278     SHA512_Final(&s, output);\r
279 }\r
280 \r
281 #ifdef TEST\r
282 \r
283 #include <stdio.h>\r
284 #include <stdlib.h>\r
285 #include <assert.h>\r
286 \r
287 int main(void) {\r
288     unsigned char digest[64];\r
289     int i, j, errors;\r
290 \r
291     struct {\r
292         const char *teststring;\r
293         unsigned char digest512[64];\r
294     } tests[] = {\r
295         { "abc", {\r
296             0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,\r
297             0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,\r
298             0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,\r
299             0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,\r
300             0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,\r
301             0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,\r
302             0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,\r
303             0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,\r
304         } },\r
305         { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"\r
306         "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", {\r
307             0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,\r
308             0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,\r
309             0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,\r
310             0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,\r
311             0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,\r
312             0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,\r
313             0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,\r
314             0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09,\r
315         } },\r
316         { NULL, {\r
317             0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64,\r
318             0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,\r
319             0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28,\r
320             0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,\r
321             0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a,\r
322             0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,\r
323             0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e,\r
324             0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b, \r
325         } },\r
326     };\r
327 \r
328     errors = 0;\r
329 \r
330     for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {\r
331         if (tests[i].teststring) {\r
332             SHA512_Simple(tests[i].teststring,\r
333                           strlen(tests[i].teststring), digest);\r
334         } else {\r
335             SHA512_State s;\r
336             int n;\r
337             SHA512_Init(&s);\r
338             for (n = 0; n < 1000000 / 40; n++)\r
339                 SHA512_Bytes(&s, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",\r
340                              40);\r
341             SHA512_Final(&s, digest);\r
342         }\r
343         for (j = 0; j < 64; j++) {\r
344             if (digest[j] != tests[i].digest512[j]) {\r
345                 fprintf(stderr,\r
346                         "\"%s\" digest512 byte %d should be 0x%02x, is 0x%02x\n",\r
347                         tests[i].teststring, j, tests[i].digest512[j],\r
348                         digest[j]);\r
349                 errors++;\r
350             }\r
351         }\r
352 \r
353     }\r
354 \r
355     printf("%d errors\n", errors);\r
356 \r
357     return 0;\r
358 }\r
359 \r
360 #endif\r