]> git.ipfire.org Git - people/ms/putty.git/blame - sshsh256.c
Add search to connection list box.
[people/ms/putty.git] / sshsh256.c
CommitLineData
1c1af145 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
22void 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
33void 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
96void SHA256_Init(SHA256_State *s) {
97 SHA256_Core_Init(s);
98 s->blkused = 0;
99 s->lenhi = s->lenlo = 0;
100}
101
102void 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
144void 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
181void 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
193static void *sha256_init(void)
194{
195 SHA256_State *s;
196
197 s = snew(SHA256_State);
198 SHA256_Init(s);
199 return s;
200}
201
202static void sha256_bytes(void *handle, void *p, int len)
203{
204 SHA256_State *s = handle;
205
206 SHA256_Bytes(s, p, len);
207}
208
209static 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
217const 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
227int 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