]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - sshsh256.c
Merge r9365 (bump version number to 0.62).
[PuTTY.git] / sshsh256.c
1 /*
2  * SHA-256 algorithm as described at
3  * 
4  *   http://csrc.nist.gov/cryptval/shs.html
5  */
6
7 #include "ssh.h"
8
9 /* ----------------------------------------------------------------------
10  * Core SHA256 algorithm: processes 16-word blocks into a message digest.
11  */
12
13 #define ror(x,y) ( ((x) << (32-y)) | (((uint32)(x)) >> (y)) )
14 #define shr(x,y) ( (((uint32)(x)) >> (y)) )
15 #define Ch(x,y,z) ( ((x) & (y)) ^ (~(x) & (z)) )
16 #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) )
17 #define bigsigma0(x) ( ror((x),2) ^ ror((x),13) ^ ror((x),22) )
18 #define bigsigma1(x) ( ror((x),6) ^ ror((x),11) ^ ror((x),25) )
19 #define smallsigma0(x) ( ror((x),7) ^ ror((x),18) ^ shr((x),3) )
20 #define smallsigma1(x) ( ror((x),17) ^ ror((x),19) ^ shr((x),10) )
21
22 void SHA256_Core_Init(SHA256_State *s) {
23     s->h[0] = 0x6a09e667;
24     s->h[1] = 0xbb67ae85;
25     s->h[2] = 0x3c6ef372;
26     s->h[3] = 0xa54ff53a;
27     s->h[4] = 0x510e527f;
28     s->h[5] = 0x9b05688c;
29     s->h[6] = 0x1f83d9ab;
30     s->h[7] = 0x5be0cd19;
31 }
32
33 void SHA256_Block(SHA256_State *s, uint32 *block) {
34     uint32 w[80];
35     uint32 a,b,c,d,e,f,g,h;
36     static const int k[] = {
37         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
38         0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
39         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
40         0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
41         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
42         0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
43         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
44         0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
45         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
46         0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
47         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
48         0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
49         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
50         0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
51         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
52         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
53     };
54
55     int t;
56
57     for (t = 0; t < 16; t++)
58         w[t] = block[t];
59
60     for (t = 16; t < 64; t++)
61         w[t] = smallsigma1(w[t-2]) + w[t-7] + smallsigma0(w[t-15]) + w[t-16];
62
63     a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3];
64     e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7];
65
66     for (t = 0; t < 64; t+=8) {
67         uint32 t1, t2;
68
69 #define ROUND(j,a,b,c,d,e,f,g,h) \
70         t1 = h + bigsigma1(e) + Ch(e,f,g) + k[j] + w[j]; \
71         t2 = bigsigma0(a) + Maj(a,b,c); \
72         d = d + t1; h = t1 + t2;
73
74         ROUND(t+0, a,b,c,d,e,f,g,h);
75         ROUND(t+1, h,a,b,c,d,e,f,g);
76         ROUND(t+2, g,h,a,b,c,d,e,f);
77         ROUND(t+3, f,g,h,a,b,c,d,e);
78         ROUND(t+4, e,f,g,h,a,b,c,d);
79         ROUND(t+5, d,e,f,g,h,a,b,c);
80         ROUND(t+6, c,d,e,f,g,h,a,b);
81         ROUND(t+7, b,c,d,e,f,g,h,a);
82     }
83
84     s->h[0] += a; s->h[1] += b; s->h[2] += c; s->h[3] += d;
85     s->h[4] += e; s->h[5] += f; s->h[6] += g; s->h[7] += h;
86 }
87
88 /* ----------------------------------------------------------------------
89  * Outer SHA256 algorithm: take an arbitrary length byte string,
90  * convert it into 16-word blocks with the prescribed padding at
91  * the end, and pass those blocks to the core SHA256 algorithm.
92  */
93
94 #define BLKSIZE 64
95
96 void SHA256_Init(SHA256_State *s) {
97     SHA256_Core_Init(s);
98     s->blkused = 0;
99     s->lenhi = s->lenlo = 0;
100 }
101
102 void SHA256_Bytes(SHA256_State *s, const void *p, int len) {
103     unsigned char *q = (unsigned char *)p;
104     uint32 wordblock[16];
105     uint32 lenw = len;
106     int i;
107
108     /*
109      * Update the length field.
110      */
111     s->lenlo += lenw;
112     s->lenhi += (s->lenlo < lenw);
113
114     if (s->blkused && s->blkused+len < BLKSIZE) {
115         /*
116          * Trivial case: just add to the block.
117          */
118         memcpy(s->block + s->blkused, q, len);
119         s->blkused += len;
120     } else {
121         /*
122          * We must complete and process at least one block.
123          */
124         while (s->blkused + len >= BLKSIZE) {
125             memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
126             q += BLKSIZE - s->blkused;
127             len -= BLKSIZE - s->blkused;
128             /* Now process the block. Gather bytes big-endian into words */
129             for (i = 0; i < 16; i++) {
130                 wordblock[i] =
131                     ( ((uint32)s->block[i*4+0]) << 24 ) |
132                     ( ((uint32)s->block[i*4+1]) << 16 ) |
133                     ( ((uint32)s->block[i*4+2]) <<  8 ) |
134                     ( ((uint32)s->block[i*4+3]) <<  0 );
135             }
136             SHA256_Block(s, wordblock);
137             s->blkused = 0;
138         }
139         memcpy(s->block, q, len);
140         s->blkused = len;
141     }
142 }
143
144 void SHA256_Final(SHA256_State *s, unsigned char *digest) {
145     int i;
146     int pad;
147     unsigned char c[64];
148     uint32 lenhi, lenlo;
149
150     if (s->blkused >= 56)
151         pad = 56 + 64 - s->blkused;
152     else
153         pad = 56 - s->blkused;
154
155     lenhi = (s->lenhi << 3) | (s->lenlo >> (32-3));
156     lenlo = (s->lenlo << 3);
157
158     memset(c, 0, pad);
159     c[0] = 0x80;
160     SHA256_Bytes(s, &c, pad);
161
162     c[0] = (lenhi >> 24) & 0xFF;
163     c[1] = (lenhi >> 16) & 0xFF;
164     c[2] = (lenhi >>  8) & 0xFF;
165     c[3] = (lenhi >>  0) & 0xFF;
166     c[4] = (lenlo >> 24) & 0xFF;
167     c[5] = (lenlo >> 16) & 0xFF;
168     c[6] = (lenlo >>  8) & 0xFF;
169     c[7] = (lenlo >>  0) & 0xFF;
170
171     SHA256_Bytes(s, &c, 8);
172
173     for (i = 0; i < 8; i++) {
174         digest[i*4+0] = (s->h[i] >> 24) & 0xFF;
175         digest[i*4+1] = (s->h[i] >> 16) & 0xFF;
176         digest[i*4+2] = (s->h[i] >>  8) & 0xFF;
177         digest[i*4+3] = (s->h[i] >>  0) & 0xFF;
178     }
179 }
180
181 void SHA256_Simple(const void *p, int len, unsigned char *output) {
182     SHA256_State s;
183
184     SHA256_Init(&s);
185     SHA256_Bytes(&s, p, len);
186     SHA256_Final(&s, output);
187 }
188
189 /*
190  * Thin abstraction for things where hashes are pluggable.
191  */
192
193 static void *sha256_init(void)
194 {
195     SHA256_State *s;
196
197     s = snew(SHA256_State);
198     SHA256_Init(s);
199     return s;
200 }
201
202 static void sha256_bytes(void *handle, void *p, int len)
203 {
204     SHA256_State *s = handle;
205
206     SHA256_Bytes(s, p, len);
207 }
208
209 static void sha256_final(void *handle, unsigned char *output)
210 {
211     SHA256_State *s = handle;
212
213     SHA256_Final(s, output);
214     sfree(s);
215 }
216
217 const struct ssh_hash ssh_sha256 = {
218     sha256_init, sha256_bytes, sha256_final, 32, "SHA-256"
219 };
220
221 #ifdef TEST
222
223 #include <stdio.h>
224 #include <stdlib.h>
225 #include <assert.h>
226
227 int main(void) {
228     unsigned char digest[32];
229     int i, j, errors;
230
231     struct {
232         const char *teststring;
233         unsigned char digest[32];
234     } tests[] = {
235         { "abc", {
236             0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
237             0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
238             0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
239             0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
240         } },
241         { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", {
242             0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
243             0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
244             0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
245             0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
246         } },
247     };
248
249     errors = 0;
250
251     for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
252         SHA256_Simple(tests[i].teststring,
253                       strlen(tests[i].teststring), digest);
254         for (j = 0; j < 32; j++) {
255             if (digest[j] != tests[i].digest[j]) {
256                 fprintf(stderr,
257                         "\"%s\" digest byte %d should be 0x%02x, is 0x%02x\n",
258                         tests[i].teststring, j, tests[i].digest[j], digest[j]);
259                 errors++;
260             }
261         }
262     }
263
264     printf("%d errors\n", errors);
265
266     return 0;
267 }
268
269 #endif