1/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10 */
11#include "tomcrypt.h"
12
13/**
14   @param sha512.c
15   SHA512 by Tom St Denis
16*/
17
18#ifdef SHA512
19
20const struct ltc_hash_descriptor sha512_desc =
21{
22    "sha512",
23    5,
24    64,
25    128,
26
27    /* OID */
28   { 2, 16, 840, 1, 101, 3, 4, 2, 3,  },
29   9,
30
31    &sha512_init,
32    &sha512_process,
33    &sha512_done,
34    &sha512_test,
35    NULL
36};
37
38/* the K array */
39static const ulong64 K[80] = {
40CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
41CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
42CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
43CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
44CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
45CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
46CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
47CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
48CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
49CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
50CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
51CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
52CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
53CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
54CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
55CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
56CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
57CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
58CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
59CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
60CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
61CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
62CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
63CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
64CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
65CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
66CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
67CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
68CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
69CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
70CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
71CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
72CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
73CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
74CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
75CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
76CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
77CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
78CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
79CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
80};
81
82/* Various logical functions */
83#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
84#define Maj(x,y,z)      (((x | y) & z) | (x & y))
85#define S(x, n)         ROR64c(x, n)
86#define R(x, n)         (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n))
87#define Sigma0(x)       (S(x, 28) ^ S(x, 34) ^ S(x, 39))
88#define Sigma1(x)       (S(x, 14) ^ S(x, 18) ^ S(x, 41))
89#define Gamma0(x)       (S(x, 1) ^ S(x, 8) ^ R(x, 7))
90#define Gamma1(x)       (S(x, 19) ^ S(x, 61) ^ R(x, 6))
91
92/* compress 1024-bits */
93#ifdef LTC_CLEAN_STACK
94static int _sha512_compress(hash_state * md, unsigned char *buf)
95#else
96static int  sha512_compress(hash_state * md, unsigned char *buf)
97#endif
98{
99    ulong64 S[8], W[80], t0, t1;
100    int i;
101
102    /* copy state into S */
103    for (i = 0; i < 8; i++) {
104        S[i] = md->sha512.state[i];
105    }
106
107    /* copy the state into 1024-bits into W[0..15] */
108    for (i = 0; i < 16; i++) {
109        LOAD64H(W[i], buf + (8*i));
110    }
111
112    /* fill W[16..79] */
113    for (i = 16; i < 80; i++) {
114        W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
115    }
116
117    /* Compress */
118#ifdef LTC_SMALL_CODE
119    for (i = 0; i < 80; i++) {
120        t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
121        t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
122        S[7] = S[6];
123        S[6] = S[5];
124        S[5] = S[4];
125        S[4] = S[3] + t0;
126        S[3] = S[2];
127        S[2] = S[1];
128        S[1] = S[0];
129        S[0] = t0 + t1;
130    }
131#else
132#define RND(a,b,c,d,e,f,g,h,i)                    \
133     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
134     t1 = Sigma0(a) + Maj(a, b, c);                  \
135     d += t0;                                        \
136     h  = t0 + t1;
137
138     for (i = 0; i < 80; i += 8) {
139         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
140         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
141         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
142         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
143         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
144         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
145         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
146         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
147     }
148#endif
149
150
151    /* feedback */
152    for (i = 0; i < 8; i++) {
153        md->sha512.state[i] = md->sha512.state[i] + S[i];
154    }
155
156    return CRYPT_OK;
157}
158
159/* compress 1024-bits */
160#ifdef LTC_CLEAN_STACK
161static int sha512_compress(hash_state * md, unsigned char *buf)
162{
163    int err;
164    err = _sha512_compress(md, buf);
165    burn_stack(sizeof(ulong64) * 90 + sizeof(int));
166    return err;
167}
168#endif
169
170/**
171   Initialize the hash state
172   @param md   The hash state you wish to initialize
173   @return CRYPT_OK if successful
174*/
175int sha512_init(hash_state * md)
176{
177    LTC_ARGCHK(md != NULL);
178    md->sha512.curlen = 0;
179    md->sha512.length = 0;
180    md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
181    md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
182    md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
183    md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
184    md->sha512.state[4] = CONST64(0x510e527fade682d1);
185    md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
186    md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
187    md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
188    return CRYPT_OK;
189}
190
191/**
192   Process a block of memory though the hash
193   @param md     The hash state
194   @param in     The data to hash
195   @param inlen  The length of the data (octets)
196   @return CRYPT_OK if successful
197*/
198HASH_PROCESS(sha512_process, sha512_compress, sha512, 128)
199
200/**
201   Terminate the hash to get the digest
202   @param md  The hash state
203   @param out [out] The destination of the hash (64 bytes)
204   @return CRYPT_OK if successful
205*/
206int sha512_done(hash_state * md, unsigned char *out)
207{
208    int i;
209
210    LTC_ARGCHK(md  != NULL);
211    LTC_ARGCHK(out != NULL);
212
213    if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
214       return CRYPT_INVALID_ARG;
215    }
216
217    /* increase the length of the message */
218    md->sha512.length += md->sha512.curlen * CONST64(8);
219
220    /* append the '1' bit */
221    md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;
222
223    /* if the length is currently above 112 bytes we append zeros
224     * then compress.  Then we can fall back to padding zeros and length
225     * encoding like normal.
226     */
227    if (md->sha512.curlen > 112) {
228        while (md->sha512.curlen < 128) {
229            md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
230        }
231        sha512_compress(md, md->sha512.buf);
232        md->sha512.curlen = 0;
233    }
234
235    /* pad upto 120 bytes of zeroes
236     * note: that from 112 to 120 is the 64 MSB of the length.  We assume that you won't hash
237     * > 2^64 bits of data... :-)
238     */
239    while (md->sha512.curlen < 120) {
240        md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
241    }
242
243    /* store length */
244    STORE64H(md->sha512.length, md->sha512.buf+120);
245    sha512_compress(md, md->sha512.buf);
246
247    /* copy output */
248    for (i = 0; i < 8; i++) {
249        STORE64H(md->sha512.state[i], out+(8*i));
250    }
251#ifdef LTC_CLEAN_STACK
252    zeromem(md, sizeof(hash_state));
253#endif
254    return CRYPT_OK;
255}
256
257/**
258  Self-test the hash
259  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
260*/
261int  sha512_test(void)
262{
263 #ifndef LTC_TEST
264    return CRYPT_NOP;
265 #else
266  static const struct {
267      char *msg;
268      unsigned char hash[64];
269  } tests[] = {
270    { "abc",
271     { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
272       0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
273       0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
274       0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
275       0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
276       0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
277       0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
278       0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
279    },
280    { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
281     { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
282       0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
283       0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
284       0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
285       0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
286       0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
287       0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
288       0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
289    },
290  };
291
292  int i;
293  unsigned char tmp[64];
294  hash_state md;
295
296  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
297      sha512_init(&md);
298      sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
299      sha512_done(&md, tmp);
300      if (XMEMCMP(tmp, tests[i].hash, 64) != 0) {
301         return CRYPT_FAIL_TESTVECTOR;
302      }
303  }
304  return CRYPT_OK;
305  #endif
306}
307
308#ifdef SHA384
309   #include "sha384.c"
310#endif
311
312#endif
313
314
315
316
317/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha512.c,v $ */
318/* $Revision: 1.8 $ */
319/* $Date: 2006/11/01 09:28:17 $ */
320