source: filezilla/trunk/fuentes/src/putty/sshsh512.c @ 3185

Last change on this file since 3185 was 3185, checked in by jrpelegrina, 3 years ago

Update new version: 3.15.02

File size: 14.2 KB
Line 
1/*
2 * SHA-512 algorithm as described at
3 *
4 *   http://csrc.nist.gov/cryptval/shs.html
5 *
6 * Modifications made for SHA-384 also
7 */
8
9#ifdef SHA512_STANDALONE
10typedef struct {
11    uint64 h[8];
12    unsigned char block[128];
13    int blkused;
14    uint32 len[4];
15} SHA512_State;
16#else
17#include "ssh.h"
18#endif
19
20#define BLKSIZE 128
21
22/*
23 * Arithmetic implementations. Note that AND, XOR and NOT can
24 * overlap destination with one source, but the others can't.
25 */
26#define add(r,x,y) ( r.lo = y.lo + x.lo, \
27                     r.hi = y.hi + x.hi + ((uint32)r.lo < (uint32)y.lo) )
28#define rorB(r,x,y) ( r.lo = ((uint32)x.hi >> ((y)-32)) | ((uint32)x.lo << (64-(y))), \
29                      r.hi = ((uint32)x.lo >> ((y)-32)) | ((uint32)x.hi << (64-(y))) )
30#define rorL(r,x,y) ( r.lo = ((uint32)x.lo >> (y)) | ((uint32)x.hi << (32-(y))), \
31                      r.hi = ((uint32)x.hi >> (y)) | ((uint32)x.lo << (32-(y))) )
32#define shrB(r,x,y) ( r.lo = (uint32)x.hi >> ((y)-32), r.hi = 0 )
33#define shrL(r,x,y) ( r.lo = ((uint32)x.lo >> (y)) | ((uint32)x.hi << (32-(y))), \
34                      r.hi = (uint32)x.hi >> (y) )
35#define putty_and(r,x,y) ( r.lo = x.lo & y.lo, r.hi = x.hi & y.hi )
36#define putty_xor(r,x,y) ( r.lo = x.lo ^ y.lo, r.hi = x.hi ^ y.hi )
37#define putty_not(r,x) ( r.lo = ~x.lo, r.hi = ~x.hi )
38#define INIT(h,l) { h, l }
39#define BUILD(r,h,l) ( r.hi = h, r.lo = l )
40#define EXTRACT(h,l,r) ( h = r.hi, l = r.lo )
41
42/* ----------------------------------------------------------------------
43 * Core SHA512 algorithm: processes 16-doubleword blocks into a
44 * message digest.
45 */
46
47#define Ch(r,t,x,y,z) ( putty_not(t,x), putty_and(r,t,z), putty_and(t,x,y), putty_xor(r,r,t) )
48#define Maj(r,t,x,y,z) ( putty_and(r,x,y), putty_and(t,x,z), putty_xor(r,r,t), \
49                         putty_and(t,y,z), putty_xor(r,r,t) )
50#define bigsigma0(r,t,x) ( rorL(r,x,28), rorB(t,x,34), putty_xor(r,r,t), \
51                           rorB(t,x,39), putty_xor(r,r,t) )
52#define bigsigma1(r,t,x) ( rorL(r,x,14), rorL(t,x,18), putty_xor(r,r,t), \
53                           rorB(t,x,41), putty_xor(r,r,t) )
54#define smallsigma0(r,t,x) ( rorL(r,x,1), rorL(t,x,8), putty_xor(r,r,t), \
55                             shrL(t,x,7), putty_xor(r,r,t) )
56#define smallsigma1(r,t,x) ( rorL(r,x,19), rorB(t,x,61), putty_xor(r,r,t), \
57                             shrL(t,x,6), putty_xor(r,r,t) )
58
59static void SHA512_Core_Init(SHA512_State *s) {
60    static const uint64 iv[] = {
61        INIT(0x6a09e667, 0xf3bcc908),
62        INIT(0xbb67ae85, 0x84caa73b),
63        INIT(0x3c6ef372, 0xfe94f82b),
64        INIT(0xa54ff53a, 0x5f1d36f1),
65        INIT(0x510e527f, 0xade682d1),
66        INIT(0x9b05688c, 0x2b3e6c1f),
67        INIT(0x1f83d9ab, 0xfb41bd6b),
68        INIT(0x5be0cd19, 0x137e2179),
69    };
70    int i;
71    for (i = 0; i < 8; i++)
72        s->h[i] = iv[i];
73}
74
75#ifndef SHA512_STANDALONE
76static void SHA384_Core_Init(SHA512_State *s) {
77    static const uint64 iv[] = {
78        INIT(0xcbbb9d5d, 0xc1059ed8),
79        INIT(0x629a292a, 0x367cd507),
80        INIT(0x9159015a, 0x3070dd17),
81        INIT(0x152fecd8, 0xf70e5939),
82        INIT(0x67332667, 0xffc00b31),
83        INIT(0x8eb44a87, 0x68581511),
84        INIT(0xdb0c2e0d, 0x64f98fa7),
85        INIT(0x47b5481d, 0xbefa4fa4),
86    };
87    int i;
88    for (i = 0; i < 8; i++)
89        s->h[i] = iv[i];
90}
91#endif
92
93static void SHA512_Block(SHA512_State *s, uint64 *block) {
94    uint64 w[80];
95    uint64 a,b,c,d,e,f,g,h;
96    static const uint64 k[] = {
97        INIT(0x428a2f98, 0xd728ae22), INIT(0x71374491, 0x23ef65cd),
98        INIT(0xb5c0fbcf, 0xec4d3b2f), INIT(0xe9b5dba5, 0x8189dbbc),
99        INIT(0x3956c25b, 0xf348b538), INIT(0x59f111f1, 0xb605d019),
100        INIT(0x923f82a4, 0xaf194f9b), INIT(0xab1c5ed5, 0xda6d8118),
101        INIT(0xd807aa98, 0xa3030242), INIT(0x12835b01, 0x45706fbe),
102        INIT(0x243185be, 0x4ee4b28c), INIT(0x550c7dc3, 0xd5ffb4e2),
103        INIT(0x72be5d74, 0xf27b896f), INIT(0x80deb1fe, 0x3b1696b1),
104        INIT(0x9bdc06a7, 0x25c71235), INIT(0xc19bf174, 0xcf692694),
105        INIT(0xe49b69c1, 0x9ef14ad2), INIT(0xefbe4786, 0x384f25e3),
106        INIT(0x0fc19dc6, 0x8b8cd5b5), INIT(0x240ca1cc, 0x77ac9c65),
107        INIT(0x2de92c6f, 0x592b0275), INIT(0x4a7484aa, 0x6ea6e483),
108        INIT(0x5cb0a9dc, 0xbd41fbd4), INIT(0x76f988da, 0x831153b5),
109        INIT(0x983e5152, 0xee66dfab), INIT(0xa831c66d, 0x2db43210),
110        INIT(0xb00327c8, 0x98fb213f), INIT(0xbf597fc7, 0xbeef0ee4),
111        INIT(0xc6e00bf3, 0x3da88fc2), INIT(0xd5a79147, 0x930aa725),
112        INIT(0x06ca6351, 0xe003826f), INIT(0x14292967, 0x0a0e6e70),
113        INIT(0x27b70a85, 0x46d22ffc), INIT(0x2e1b2138, 0x5c26c926),
114        INIT(0x4d2c6dfc, 0x5ac42aed), INIT(0x53380d13, 0x9d95b3df),
115        INIT(0x650a7354, 0x8baf63de), INIT(0x766a0abb, 0x3c77b2a8),
116        INIT(0x81c2c92e, 0x47edaee6), INIT(0x92722c85, 0x1482353b),
117        INIT(0xa2bfe8a1, 0x4cf10364), INIT(0xa81a664b, 0xbc423001),
118        INIT(0xc24b8b70, 0xd0f89791), INIT(0xc76c51a3, 0x0654be30),
119        INIT(0xd192e819, 0xd6ef5218), INIT(0xd6990624, 0x5565a910),
120        INIT(0xf40e3585, 0x5771202a), INIT(0x106aa070, 0x32bbd1b8),
121        INIT(0x19a4c116, 0xb8d2d0c8), INIT(0x1e376c08, 0x5141ab53),
122        INIT(0x2748774c, 0xdf8eeb99), INIT(0x34b0bcb5, 0xe19b48a8),
123        INIT(0x391c0cb3, 0xc5c95a63), INIT(0x4ed8aa4a, 0xe3418acb),
124        INIT(0x5b9cca4f, 0x7763e373), INIT(0x682e6ff3, 0xd6b2b8a3),
125        INIT(0x748f82ee, 0x5defb2fc), INIT(0x78a5636f, 0x43172f60),
126        INIT(0x84c87814, 0xa1f0ab72), INIT(0x8cc70208, 0x1a6439ec),
127        INIT(0x90befffa, 0x23631e28), INIT(0xa4506ceb, 0xde82bde9),
128        INIT(0xbef9a3f7, 0xb2c67915), INIT(0xc67178f2, 0xe372532b),
129        INIT(0xca273ece, 0xea26619c), INIT(0xd186b8c7, 0x21c0c207),
130        INIT(0xeada7dd6, 0xcde0eb1e), INIT(0xf57d4f7f, 0xee6ed178),
131        INIT(0x06f067aa, 0x72176fba), INIT(0x0a637dc5, 0xa2c898a6),
132        INIT(0x113f9804, 0xbef90dae), INIT(0x1b710b35, 0x131c471b),
133        INIT(0x28db77f5, 0x23047d84), INIT(0x32caab7b, 0x40c72493),
134        INIT(0x3c9ebe0a, 0x15c9bebc), INIT(0x431d67c4, 0x9c100d4c),
135        INIT(0x4cc5d4be, 0xcb3e42b6), INIT(0x597f299c, 0xfc657e2a),
136        INIT(0x5fcb6fab, 0x3ad6faec), INIT(0x6c44198c, 0x4a475817),
137    };
138
139    int t;
140
141    for (t = 0; t < 16; t++)
142        w[t] = block[t];
143
144    for (t = 16; t < 80; t++) {
145        uint64 p, q, r, tmp;
146        smallsigma1(p, tmp, w[t-2]);
147        smallsigma0(q, tmp, w[t-15]);
148        add(r, p, q);
149        add(p, r, w[t-7]);
150        add(w[t], p, w[t-16]);
151    }
152
153    a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3];
154    e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7];
155
156    for (t = 0; t < 80; t+=8) {
157        uint64 tmp, p, q, r;
158
159#define ROUND(j,a,b,c,d,e,f,g,h) \
160        bigsigma1(p, tmp, e); \
161        Ch(q, tmp, e, f, g); \
162        add(r, p, q); \
163        add(p, r, k[j]) ; \
164        add(q, p, w[j]); \
165        add(r, q, h); \
166        bigsigma0(p, tmp, a); \
167        Maj(tmp, q, a, b, c); \
168        add(q, tmp, p); \
169        add(p, r, d); \
170        d = p; \
171        add(h, q, r);
172
173        ROUND(t+0, a,b,c,d,e,f,g,h);
174        ROUND(t+1, h,a,b,c,d,e,f,g);
175        ROUND(t+2, g,h,a,b,c,d,e,f);
176        ROUND(t+3, f,g,h,a,b,c,d,e);
177        ROUND(t+4, e,f,g,h,a,b,c,d);
178        ROUND(t+5, d,e,f,g,h,a,b,c);
179        ROUND(t+6, c,d,e,f,g,h,a,b);
180        ROUND(t+7, b,c,d,e,f,g,h,a);
181    }
182
183    {
184        uint64 tmp;
185#define UPDATE(state, local) ( tmp = state, add(state, tmp, local) )
186        UPDATE(s->h[0], a); UPDATE(s->h[1], b);
187        UPDATE(s->h[2], c); UPDATE(s->h[3], d);
188        UPDATE(s->h[4], e); UPDATE(s->h[5], f);
189        UPDATE(s->h[6], g); UPDATE(s->h[7], h);
190    }
191}
192
193/* ----------------------------------------------------------------------
194 * Outer SHA512 algorithm: take an arbitrary length byte string,
195 * convert it into 16-doubleword blocks with the prescribed padding
196 * at the end, and pass those blocks to the core SHA512 algorithm.
197 */
198
199void SHA512_Init(SHA512_State *s) {
200    int i;
201    SHA512_Core_Init(s);
202    s->blkused = 0;
203    for (i = 0; i < 4; i++)
204        s->len[i] = 0;
205}
206
207#ifndef SHA512_STANDALONE
208void SHA384_Init(SHA512_State *s) {
209    int i;
210    SHA384_Core_Init(s);
211    s->blkused = 0;
212    for (i = 0; i < 4; i++)
213        s->len[i] = 0;
214}
215#endif
216
217void SHA512_Bytes(SHA512_State *s, const void *p, int len) {
218    unsigned char *q = (unsigned char *)p;
219    uint64 wordblock[16];
220    uint32 lenw = len;
221    int i;
222
223    /*
224     * Update the length field.
225     */
226    for (i = 0; i < 4; i++) {
227        s->len[i] += lenw;
228        lenw = (s->len[i] < lenw);
229    }
230
231    if (s->blkused && s->blkused+len < BLKSIZE) {
232        /*
233         * Trivial case: just add to the block.
234         */
235        memcpy(s->block + s->blkused, q, len);
236        s->blkused += len;
237    } else {
238        /*
239         * We must complete and process at least one block.
240         */
241        while (s->blkused + len >= BLKSIZE) {
242            memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
243            q += BLKSIZE - s->blkused;
244            len -= BLKSIZE - s->blkused;
245            /* Now process the block. Gather bytes big-endian into words */
246            for (i = 0; i < 16; i++) {
247                uint32 h, l;
248                h = ( ((uint32)s->block[i*8+0]) << 24 ) |
249                    ( ((uint32)s->block[i*8+1]) << 16 ) |
250                    ( ((uint32)s->block[i*8+2]) <<  8 ) |
251                    ( ((uint32)s->block[i*8+3]) <<  0 );
252                l = ( ((uint32)s->block[i*8+4]) << 24 ) |
253                    ( ((uint32)s->block[i*8+5]) << 16 ) |
254                    ( ((uint32)s->block[i*8+6]) <<  8 ) |
255                    ( ((uint32)s->block[i*8+7]) <<  0 );
256                BUILD(wordblock[i], h, l);
257            }
258            SHA512_Block(s, wordblock);
259            s->blkused = 0;
260        }
261        memcpy(s->block, q, len);
262        s->blkused = len;
263    }
264}
265
266void SHA512_Final(SHA512_State *s, unsigned char *digest) {
267    int i;
268    int pad;
269    unsigned char c[BLKSIZE];
270    uint32 len[4];
271
272    if (s->blkused >= BLKSIZE-16)
273        pad = (BLKSIZE-16) + BLKSIZE - s->blkused;
274    else
275        pad = (BLKSIZE-16) - s->blkused;
276
277    for (i = 4; i-- ;) {
278        uint32 lenhi = s->len[i];
279        uint32 lenlo = i > 0 ? s->len[i-1] : 0;
280        len[i] = (lenhi << 3) | (lenlo >> (32-3));
281    }
282
283    memset(c, 0, pad);
284    c[0] = 0x80;
285    SHA512_Bytes(s, &c, pad);
286
287    for (i = 0; i < 4; i++) {
288        c[i*4+0] = (len[3-i] >> 24) & 0xFF;
289        c[i*4+1] = (len[3-i] >> 16) & 0xFF;
290        c[i*4+2] = (len[3-i] >>  8) & 0xFF;
291        c[i*4+3] = (len[3-i] >>  0) & 0xFF;
292    }
293
294    SHA512_Bytes(s, &c, 16);
295
296    for (i = 0; i < 8; i++) {
297        uint32 h, l;
298        EXTRACT(h, l, s->h[i]);
299        digest[i*8+0] = (h >> 24) & 0xFF;
300        digest[i*8+1] = (h >> 16) & 0xFF;
301        digest[i*8+2] = (h >>  8) & 0xFF;
302        digest[i*8+3] = (h >>  0) & 0xFF;
303        digest[i*8+4] = (l >> 24) & 0xFF;
304        digest[i*8+5] = (l >> 16) & 0xFF;
305        digest[i*8+6] = (l >>  8) & 0xFF;
306        digest[i*8+7] = (l >>  0) & 0xFF;
307    }
308}
309
310#ifndef SHA512_STANDALONE
311void SHA384_Final(SHA512_State *s, unsigned char *digest) {
312    unsigned char biggerDigest[512 / 8];
313    SHA512_Final(s, biggerDigest);
314    memcpy(digest, biggerDigest, 384 / 8);
315}
316
317void SHA512_Simple(const void *p, int len, unsigned char *output) {
318    SHA512_State s;
319
320    SHA512_Init(&s);
321    SHA512_Bytes(&s, p, len);
322    SHA512_Final(&s, output);
323    smemclr(&s, sizeof(s));
324}
325
326void SHA384_Simple(const void *p, int len, unsigned char *output) {
327    SHA512_State s;
328
329    SHA384_Init(&s);
330    SHA512_Bytes(&s, p, len);
331    SHA384_Final(&s, output);
332    smemclr(&s, sizeof(s));
333}
334
335/*
336 * Thin abstraction for things where hashes are pluggable.
337 */
338
339static void *sha512_init(void)
340{
341    SHA512_State *s;
342
343    s = snew(SHA512_State);
344    SHA512_Init(s);
345    return s;
346}
347
348static void *sha512_copy(const void *vold)
349{
350    const SHA512_State *old = (const SHA512_State *)vold;
351    SHA512_State *s;
352
353    s = snew(SHA512_State);
354    *s = *old;
355    return s;
356}
357
358static void sha512_free(void *handle)
359{
360    SHA512_State *s = handle;
361
362    smemclr(s, sizeof(*s));
363    sfree(s);
364}
365
366static void sha512_bytes(void *handle, const void *p, int len)
367{
368    SHA512_State *s = handle;
369
370    SHA512_Bytes(s, p, len);
371}
372
373static void sha512_final(void *handle, unsigned char *output)
374{
375    SHA512_State *s = handle;
376
377    SHA512_Final(s, output);
378    sha512_free(s);
379}
380
381const struct ssh_hash ssh_sha512 = {
382    sha512_init, sha512_copy, sha512_bytes, sha512_final, sha512_free,
383    64, "SHA-512"
384};
385
386static void *sha384_init(void)
387{
388    SHA512_State *s;
389
390    s = snew(SHA512_State);
391    SHA384_Init(s);
392    return s;
393}
394
395static void sha384_final(void *handle, unsigned char *output)
396{
397    SHA512_State *s = handle;
398
399    SHA384_Final(s, output);
400    smemclr(s, sizeof(*s));
401    sfree(s);
402}
403
404const struct ssh_hash ssh_sha384 = {
405    sha384_init, sha512_copy, sha512_bytes, sha384_final, sha512_free,
406    48, "SHA-384"
407};
408#endif
409
410#ifdef TEST
411
412#include <stdio.h>
413#include <stdlib.h>
414#include <assert.h>
415
416int main(void) {
417    unsigned char digest[64];
418    int i, j, errors;
419
420    struct {
421        const char *teststring;
422        unsigned char digest512[64];
423    } tests[] = {
424        { "abc", {
425            0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
426            0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
427            0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
428            0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
429            0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
430            0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
431            0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
432            0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
433        } },
434        { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
435        "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", {
436            0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
437            0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
438            0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
439            0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
440            0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
441            0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
442            0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
443            0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09,
444        } },
445        { NULL, {
446            0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64,
447            0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,
448            0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28,
449            0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,
450            0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a,
451            0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,
452            0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e,
453            0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b, 
454        } },
455    };
456
457    errors = 0;
458
459    for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
460        if (tests[i].teststring) {
461            SHA512_Simple(tests[i].teststring,
462                          strlen(tests[i].teststring), digest);
463        } else {
464            SHA512_State s;
465            int n;
466            SHA512_Init(&s);
467            for (n = 0; n < 1000000 / 40; n++)
468                SHA512_Bytes(&s, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
469                             40);
470            SHA512_Final(&s, digest);
471        }
472        for (j = 0; j < 64; j++) {
473            if (digest[j] != tests[i].digest512[j]) {
474                fprintf(stderr,
475                        "\"%s\" digest512 byte %d should be 0x%02x, is 0x%02x\n",
476                        tests[i].teststring, j, tests[i].digest512[j],
477                        digest[j]);
478                errors++;
479            }
480        }
481
482    }
483
484    printf("%d errors\n", errors);
485
486    return 0;
487}
488
489#endif
Note: See TracBrowser for help on using the repository browser.